|
|
1.1 root 1: /* scan-decls.c - Extracts declarations from cpp output. 1.1.1.2 ! root 2: Copyright (C) 1993, 1995 Free Software Foundation, Inc. 1.1 root 3: 4: This program is free software; you can redistribute it and/or modify it 5: under the terms of the GNU General Public License as published by the 6: Free Software Foundation; either version 2, or (at your option) any 7: later version. 8: 9: This program is distributed in the hope that it will be useful, 10: but WITHOUT ANY WARRANTY; without even the implied warranty of 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12: GNU General Public License for more details. 13: 14: You should have received a copy of the GNU General Public License 15: along with this program; if not, write to the Free Software 1.1.1.2 ! root 16: Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1.1 root 17: 18: Written by Per Bothner <[email protected]>, July 1993. */ 19: 20: #include <stdio.h> 21: #include <ctype.h> 22: #include "hconfig.h" 1.1.1.2 ! root 23: #include "cpplib.h" 1.1 root 24: 25: int brace_nesting = 0; 26: 27: /* The first extern_C_braces_length elements of extern_C_braces 28: indicate the (brace nesting levels of) left braces that were 29: prefixed by extern "C". */ 30: int extern_C_braces_length = 0; 31: char extern_C_braces[20]; 32: #define in_extern_C_brace (extern_C_braces_length>0) 33: 34: /* True if the function declaration currently being scanned is 35: prefixed by extern "C". */ 36: int current_extern_C = 0; 37: 38: static void 1.1.1.2 ! root 39: skip_to_closing_brace (pfile) ! 40: cpp_reader *pfile; 1.1 root 41: { 42: int nesting = 1; 43: for (;;) 44: { 1.1.1.2 ! root 45: enum cpp_token token = cpp_get_token (pfile); ! 46: if (token == CPP_EOF) 1.1 root 47: break; 1.1.1.2 ! root 48: if (token == CPP_LBRACE) 1.1 root 49: nesting++; 1.1.1.2 ! root 50: if (token == CPP_RBRACE && --nesting == 0) 1.1 root 51: break; 52: } 53: } 54: 55: /* This function scans a C source file (actually, the output of cpp), 1.1.1.2 ! root 56: reading from FP. It looks for function declarations, and ! 57: external variable declarations. ! 58: ! 59: The following grammar (as well as some extra stuff) is recognized: ! 60: ! 61: declaration: ! 62: (decl-specifier)* declarator ("," declarator)* ";" ! 63: decl-specifier: ! 64: identifier ! 65: keyword ! 66: extern "C" ! 67: declarator: ! 68: (ptr-operator)* dname [ "(" argument-declaration-list ")" ] ! 69: ptr-operator: ! 70: ("*" | "&") ("const" | "volatile")* ! 71: dname: ! 72: identifier ! 73: ! 74: Here dname is the actual name being declared. ! 75: */ 1.1 root 76: 77: int 1.1.1.2 ! root 78: scan_decls (pfile, argc, argv) ! 79: cpp_reader *pfile; ! 80: int argc; ! 81: char**argv; 1.1 root 82: { 83: int saw_extern, saw_inline; 1.1.1.2 ! root 84: int old_written; ! 85: /* If declarator_start is non-zero, it marks the start of the current ! 86: declarator. If it is zero, we are either still parsing the ! 87: decl-specs, or prev_id_start marks the start of the declarator. */ ! 88: int declarator_start; ! 89: int prev_id_start, prev_id_end; ! 90: enum cpp_token token; 1.1 root 91: 92: new_statement: 1.1.1.2 ! root 93: CPP_SET_WRITTEN (pfile, 0); ! 94: token = cpp_get_token (pfile); ! 95: 1.1 root 96: handle_statement: 97: current_extern_C = 0; 98: saw_extern = 0; 99: saw_inline = 0; 1.1.1.2 ! root 100: if (token == CPP_RBRACE) 1.1 root 101: { 102: /* Pop an 'extern "C"' nesting level, if appropriate. */ 103: if (extern_C_braces_length 104: && extern_C_braces[extern_C_braces_length - 1] == brace_nesting) 105: extern_C_braces_length--; 106: brace_nesting--; 107: goto new_statement; 108: } 1.1.1.2 ! root 109: if (token == CPP_LBRACE) 1.1 root 110: { 111: brace_nesting++; 112: goto new_statement; 113: } 1.1.1.2 ! root 114: if (token == CPP_EOF) 1.1 root 115: return 0; 1.1.1.2 ! root 116: if (token == CPP_SEMICOLON) 1.1 root 117: goto new_statement; 1.1.1.2 ! root 118: if (token != CPP_NAME) 1.1 root 119: goto new_statement; 1.1.1.2 ! root 120: ! 121: prev_id_start = 0; ! 122: declarator_start = 0; 1.1 root 123: for (;;) 124: { 1.1.1.2 ! root 125: int start_written = CPP_WRITTEN (pfile); ! 126: token = cpp_get_token (pfile); ! 127: handle_token: ! 128: switch (token) 1.1 root 129: { 1.1.1.2 ! root 130: case CPP_LPAREN: ! 131: /* Looks like this is the start of a formal parameter list. */ ! 132: if (prev_id_start) 1.1 root 133: { 134: int nesting = 1; 1.1.1.2 ! root 135: int have_arg_list = 0; ! 136: cpp_buffer *fbuf = cpp_file_buffer (pfile); ! 137: long func_lineno; ! 138: cpp_buf_line_and_col (fbuf, &func_lineno, NULL); 1.1 root 139: for (;;) 140: { 1.1.1.2 ! root 141: token = cpp_get_token (pfile); ! 142: if (token == CPP_LPAREN) 1.1 root 143: nesting++; 1.1.1.2 ! root 144: else if (token == CPP_RPAREN) 1.1 root 145: { 1.1.1.2 ! root 146: nesting--; ! 147: if (nesting == 0) ! 148: break; 1.1 root 149: } 1.1.1.2 ! root 150: else if (token == CPP_EOF) ! 151: break; ! 152: else if (token == CPP_NAME || token == CPP_3DOTS) ! 153: have_arg_list = 1; 1.1 root 154: } 1.1.1.2 ! root 155: recognized_function (pfile->token_buffer + prev_id_start, ! 156: prev_id_end - prev_id_start, 1.1 root 157: (saw_inline ? 'I' 158: : in_extern_C_brace || current_extern_C 159: ? 'F' : 'f'), 1.1.1.2 ! root 160: pfile->token_buffer, prev_id_start, ! 161: have_arg_list, ! 162: fbuf->nominal_fname, func_lineno); ! 163: token = cpp_get_non_space_token (pfile); ! 164: if (token == CPP_LBRACE) 1.1 root 165: { 166: /* skip body of (normally) inline function */ 1.1.1.2 ! root 167: skip_to_closing_brace (pfile); 1.1 root 168: goto new_statement; 169: } 1.1.1.2 ! root 170: goto maybe_handle_comma; 1.1 root 171: } 1.1.1.2 ! root 172: break; ! 173: case CPP_OTHER: ! 174: if (CPP_WRITTEN (pfile) == start_written + 1 ! 175: && (CPP_PWRITTEN (pfile)[-1] == '*' ! 176: || CPP_PWRITTEN (pfile)[-1] == '&')) ! 177: declarator_start = start_written; ! 178: else ! 179: goto handle_statement; ! 180: break; ! 181: case CPP_COMMA: ! 182: case CPP_SEMICOLON: ! 183: if (prev_id_start && saw_extern) 1.1 root 184: { 1.1.1.2 ! root 185: recognized_extern (pfile->token_buffer + prev_id_start, ! 186: prev_id_end - prev_id_start, ! 187: pfile->token_buffer, ! 188: prev_id_start); 1.1 root 189: } 1.1.1.2 ! root 190: /* ... fall through ... */ ! 191: maybe_handle_comma: ! 192: if (token != CPP_COMMA) ! 193: goto new_statement; ! 194: handle_comma: ! 195: /* Handle multiple declarators in a single declaration, ! 196: as in: extern char *strcpy (), *strcat (), ... ; */ ! 197: if (declarator_start == 0) ! 198: declarator_start = prev_id_start; ! 199: CPP_SET_WRITTEN (pfile, declarator_start); ! 200: break; ! 201: case CPP_NAME: ! 202: /* "inline" and "extern" are recognized but skipped */ ! 203: if (strcmp (pfile->token_buffer, "inline") == 0) ! 204: { ! 205: saw_inline = 1; ! 206: CPP_SET_WRITTEN (pfile, start_written); ! 207: } ! 208: if (strcmp (pfile->token_buffer, "extern") == 0) ! 209: { ! 210: saw_extern = 1; ! 211: CPP_SET_WRITTEN (pfile, start_written); ! 212: token = cpp_get_non_space_token (pfile); ! 213: if (token == CPP_STRING ! 214: && strcmp (pfile->token_buffer, "\"C\"") == 0) ! 215: { ! 216: CPP_SET_WRITTEN (pfile, start_written); ! 217: current_extern_C = 1; ! 218: token = cpp_get_non_space_token (pfile); ! 219: if (token == CPP_LBRACE) ! 220: { ! 221: brace_nesting++; ! 222: extern_C_braces[extern_C_braces_length++] ! 223: = brace_nesting; ! 224: goto new_statement; ! 225: } ! 226: } ! 227: else ! 228: goto handle_token; ! 229: break; ! 230: } ! 231: /* This may be the name of a variable or function. */ ! 232: prev_id_start = start_written; ! 233: prev_id_end = CPP_WRITTEN (pfile); ! 234: break; ! 235: ! 236: case CPP_EOF: ! 237: return; /* ??? FIXME */ ! 238: ! 239: case CPP_LBRACE: case CPP_RBRACE: case CPP_DIRECTIVE: ! 240: goto new_statement; /* handle_statement? */ ! 241: ! 242: case CPP_HSPACE: case CPP_VSPACE: case CPP_COMMENT: case CPP_POP: ! 243: /* Skip initial white space. */ ! 244: if (start_written == 0) ! 245: CPP_SET_WRITTEN (pfile, 0); ! 246: break; ! 247: ! 248: default: ! 249: prev_id_start = 0; 1.1 root 250: } 251: } 252: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.