scan-decls.c revision 50397
1237263Snp/* scan-decls.c - Extracts declarations from cpp output. 2237263Snp Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. 3237263Snp 4237263SnpThis program is free software; you can redistribute it and/or modify it 5237263Snpunder the terms of the GNU General Public License as published by the 6237263SnpFree Software Foundation; either version 2, or (at your option) any 7237263Snplater version. 8237263Snp 9237263SnpThis program is distributed in the hope that it will be useful, 10237263Snpbut WITHOUT ANY WARRANTY; without even the implied warranty of 11237263SnpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12237263SnpGNU General Public License for more details. 13237263Snp 14237263SnpYou should have received a copy of the GNU General Public License 15237263Snpalong with this program; if not, write to the Free Software 16237263SnpFoundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17237263Snp 18237263Snp Written by Per Bothner <bothner@cygnus.com>, July 1993. */ 19237263Snp 20237263Snp#include "hconfig.h" 21237263Snp#include "system.h" 22237263Snp#include "gansidecl.h" 23237263Snp#include "cpplib.h" 24237263Snp#include "scan.h" 25237263Snp 26174641Skmacyint brace_nesting = 0; 27237263Snp 28237263Snp/* The first extern_C_braces_length elements of extern_C_braces 29174641Skmacy indicate the (brace nesting levels of) left braces that were 30237263Snp prefixed by extern "C". */ 31174641Skmacyint extern_C_braces_length = 0; 32237263Snpchar extern_C_braces[20]; 33237263Snp#define in_extern_C_brace (extern_C_braces_length>0) 34237263Snp 35237263Snp/* True if the function declaration currently being scanned is 36237263Snp prefixed by extern "C". */ 37237263Snpint current_extern_C = 0; 38237263Snp 39237263Snpstatic void 40237263Snpskip_to_closing_brace (pfile) 41237263Snp cpp_reader *pfile; 42237263Snp{ 43237263Snp int nesting = 1; 44239544Snp for (;;) 45237263Snp { 46237263Snp enum cpp_token token = cpp_get_token (pfile); 47237263Snp if (token == CPP_EOF) 48237263Snp break; 49174641Skmacy if (token == CPP_LBRACE) 50237263Snp nesting++; 51237263Snp if (token == CPP_RBRACE && --nesting == 0) 52237263Snp break; 53237263Snp } 54174641Skmacy} 55237263Snp 56174641Skmacy/* This function scans a C source file (actually, the output of cpp), 57237263Snp reading from FP. It looks for function declarations, and 58237263Snp external variable declarations. 59237263Snp 60237263Snp The following grammar (as well as some extra stuff) is recognized: 61174641Skmacy 62237263Snp declaration: 63237263Snp (decl-specifier)* declarator ("," declarator)* ";" 64237263Snp decl-specifier: 65174641Skmacy identifier 66237263Snp keyword 67237263Snp extern "C" 68237263Snp declarator: 69237263Snp (ptr-operator)* dname [ "(" argument-declaration-list ")" ] 70237263Snp ptr-operator: 71237263Snp ("*" | "&") ("const" | "volatile")* 72237263Snp dname: 73237263Snp identifier 74181067Skmacy 75237263SnpHere dname is the actual name being declared. 76237263Snp*/ 77237263Snp 78237263Snpint 79181067Skmacyscan_decls (pfile, argc, argv) 80237263Snp cpp_reader *pfile; 81237263Snp int argc; 82237263Snp char **argv; 83237263Snp{ 84237263Snp int saw_extern, saw_inline; 85237263Snp int start_written; 86174641Skmacy /* If declarator_start is non-zero, it marks the start of the current 87237263Snp declarator. If it is zero, we are either still parsing the 88237263Snp decl-specs, or prev_id_start marks the start of the declarator. */ 89237263Snp int declarator_start; 90237263Snp int prev_id_start, prev_id_end; 91174641Skmacy enum cpp_token token; 92237263Snp 93174641Skmacy new_statement: 94237263Snp CPP_SET_WRITTEN (pfile, 0); 95237263Snp start_written = 0; 96237263Snp token = cpp_get_token (pfile); 97174641Skmacy 98237263Snp handle_statement: 99237263Snp current_extern_C = 0; 100237263Snp saw_extern = 0; 101237263Snp saw_inline = 0; 102237263Snp if (token == CPP_RBRACE) 103174641Skmacy { 104237263Snp /* Pop an 'extern "C"' nesting level, if appropriate. */ 105237263Snp if (extern_C_braces_length 106174641Skmacy && extern_C_braces[extern_C_braces_length - 1] == brace_nesting) 107237263Snp extern_C_braces_length--; 108237263Snp brace_nesting--; 109237263Snp goto new_statement; 110174641Skmacy } 111237263Snp if (token == CPP_LBRACE) 112237263Snp { 113174641Skmacy brace_nesting++; 114237263Snp goto new_statement; 115237263Snp } 116237263Snp if (token == CPP_EOF) 117237263Snp return 0; 118237263Snp if (token == CPP_SEMICOLON) 119174641Skmacy goto new_statement; 120237263Snp if (token != CPP_NAME) 121237263Snp goto new_statement; 122237263Snp 123237263Snp prev_id_start = 0; 124237263Snp declarator_start = 0; 125237263Snp for (;;) 126174641Skmacy { 127237263Snp switch (token) 128237263Snp { 129237263Snp case CPP_LPAREN: 130237263Snp /* Looks like this is the start of a formal parameter list. */ 131237263Snp if (prev_id_start) 132237263Snp { 133237263Snp int nesting = 1; 134237263Snp int have_arg_list = 0; 135237263Snp cpp_buffer *fbuf = cpp_file_buffer (pfile); 136237263Snp long func_lineno; 137237263Snp cpp_buf_line_and_col (fbuf, &func_lineno, NULL); 138237263Snp for (;;) 139237263Snp { 140237263Snp token = cpp_get_token (pfile); 141237263Snp if (token == CPP_LPAREN) 142237263Snp nesting++; 143237263Snp else if (token == CPP_RPAREN) 144237263Snp { 145237263Snp nesting--; 146237263Snp if (nesting == 0) 147237263Snp break; 148237263Snp } 149237263Snp else if (token == CPP_EOF) 150174641Skmacy break; 151237263Snp else if (token == CPP_NAME || token == CPP_3DOTS) 152237263Snp have_arg_list = 1; 153237263Snp } 154237263Snp recognized_function (pfile->token_buffer + prev_id_start, 155237263Snp prev_id_end - prev_id_start, 156237263Snp (saw_inline ? 'I' 157237263Snp : in_extern_C_brace || current_extern_C 158237263Snp ? 'F' : 'f'), 159237263Snp pfile->token_buffer, prev_id_start, 160237263Snp have_arg_list, 161237263Snp fbuf->nominal_fname, func_lineno); 162237263Snp token = cpp_get_non_space_token (pfile); 163237263Snp if (token == CPP_LBRACE) 164237263Snp { 165237263Snp /* skip body of (normally) inline function */ 166237263Snp skip_to_closing_brace (pfile); 167237263Snp goto new_statement; 168237263Snp } 169237263Snp goto maybe_handle_comma; 170237263Snp } 171237263Snp break; 172237263Snp case CPP_OTHER: 173237263Snp if (CPP_WRITTEN (pfile) == start_written + 1 174237263Snp && (CPP_PWRITTEN (pfile)[-1] == '*' 175237263Snp || CPP_PWRITTEN (pfile)[-1] == '&')) 176237263Snp declarator_start = start_written; 177237263Snp else 178237263Snp goto handle_statement; 179237263Snp break; 180237263Snp case CPP_COMMA: 181237263Snp case CPP_SEMICOLON: 182237263Snp if (prev_id_start && saw_extern) 183237263Snp { 184237263Snp recognized_extern (pfile->token_buffer + prev_id_start, 185237263Snp prev_id_end - prev_id_start, 186237263Snp pfile->token_buffer, 187237263Snp prev_id_start); 188237263Snp } 189237263Snp /* ... fall through ... */ 190237263Snp maybe_handle_comma: 191237263Snp if (token != CPP_COMMA) 192237263Snp goto new_statement; 193237263Snp handle_comma: 194237263Snp /* Handle multiple declarators in a single declaration, 195237263Snp as in: extern char *strcpy (), *strcat (), ... ; */ 196237263Snp if (declarator_start == 0) 197237263Snp declarator_start = prev_id_start; 198237263Snp CPP_SET_WRITTEN (pfile, declarator_start); 199237263Snp break; 200237263Snp case CPP_NAME: 201237263Snp /* "inline" and "extern" are recognized but skipped */ 202237263Snp if (strcmp (pfile->token_buffer, "inline") == 0) 203237263Snp { 204237263Snp saw_inline = 1; 205237263Snp CPP_SET_WRITTEN (pfile, start_written); 206237263Snp } 207237263Snp if (strcmp (pfile->token_buffer, "extern") == 0) 208237263Snp { 209237263Snp saw_extern = 1; 210237263Snp CPP_SET_WRITTEN (pfile, start_written); 211237263Snp token = cpp_get_non_space_token (pfile); 212237263Snp if (token == CPP_STRING 213237263Snp && strcmp (pfile->token_buffer, "\"C\"") == 0) 214237263Snp { 215237263Snp CPP_SET_WRITTEN (pfile, start_written); 216237263Snp current_extern_C = 1; 217237263Snp token = cpp_get_non_space_token (pfile); 218237263Snp if (token == CPP_LBRACE) 219237263Snp { 220237263Snp brace_nesting++; 221237263Snp extern_C_braces[extern_C_braces_length++] 222237263Snp = brace_nesting; 223237263Snp goto new_statement; 224237263Snp } 225237263Snp } 226237263Snp else 227237263Snp continue; 228237263Snp break; 229237263Snp } 230237263Snp /* This may be the name of a variable or function. */ 231237263Snp prev_id_start = start_written; 232237263Snp prev_id_end = CPP_WRITTEN (pfile); 233237263Snp break; 234237263Snp 235237263Snp case CPP_EOF: 236237263Snp return 0; 237237263Snp 238237263Snp case CPP_LBRACE: case CPP_RBRACE: case CPP_DIRECTIVE: 239237263Snp goto new_statement; /* handle_statement? */ 240237263Snp 241237263Snp case CPP_HSPACE: case CPP_VSPACE: case CPP_COMMENT: case CPP_POP: 242237263Snp /* Skip initial white space. */ 243237263Snp if (start_written == 0) 244237263Snp CPP_SET_WRITTEN (pfile, 0); 245237263Snp break; 246237263Snp 247237263Snp default: 248237263Snp prev_id_start = 0; 249237263Snp } 250237263Snp 251237263Snp start_written = CPP_WRITTEN (pfile); 252237263Snp token = cpp_get_token (pfile); 253237263Snp } 254237263Snp} 255237263Snp