Import final gcc2 snapshot (990109)
[official-gcc.git] / gcc / scan-decls.c
blob4a3443b5d7059f939faf9501e1996cdc1b925db0
1 /* scan-decls.c - Extracts declarations from cpp output.
2 Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
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.
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.
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
16 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 Written by Per Bothner <bothner@cygnus.com>, July 1993. */
20 #include "hconfig.h"
21 #include "system.h"
22 #include "cpplib.h"
24 int brace_nesting = 0;
26 /* The first extern_C_braces_length elements of extern_C_braces
27 indicate the (brace nesting levels of) left braces that were
28 prefixed by extern "C". */
29 int extern_C_braces_length = 0;
30 char extern_C_braces[20];
31 #define in_extern_C_brace (extern_C_braces_length>0)
33 /* True if the function declaration currently being scanned is
34 prefixed by extern "C". */
35 int current_extern_C = 0;
37 static void
38 skip_to_closing_brace (pfile)
39 cpp_reader *pfile;
41 int nesting = 1;
42 for (;;)
44 enum cpp_token token = cpp_get_token (pfile);
45 if (token == CPP_EOF)
46 break;
47 if (token == CPP_LBRACE)
48 nesting++;
49 if (token == CPP_RBRACE && --nesting == 0)
50 break;
54 /* This function scans a C source file (actually, the output of cpp),
55 reading from FP. It looks for function declarations, and
56 external variable declarations.
58 The following grammar (as well as some extra stuff) is recognized:
60 declaration:
61 (decl-specifier)* declarator ("," declarator)* ";"
62 decl-specifier:
63 identifier
64 keyword
65 extern "C"
66 declarator:
67 (ptr-operator)* dname [ "(" argument-declaration-list ")" ]
68 ptr-operator:
69 ("*" | "&") ("const" | "volatile")*
70 dname:
71 identifier
73 Here dname is the actual name being declared.
76 int
77 scan_decls (pfile, argc, argv)
78 cpp_reader *pfile;
79 int argc;
80 char **argv;
82 int saw_extern, saw_inline;
83 int start_written;
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;
92 new_statement:
93 CPP_SET_WRITTEN (pfile, 0);
94 start_written = 0;
95 token = cpp_get_token (pfile);
97 handle_statement:
98 current_extern_C = 0;
99 saw_extern = 0;
100 saw_inline = 0;
101 if (token == CPP_RBRACE)
103 /* Pop an 'extern "C"' nesting level, if appropriate. */
104 if (extern_C_braces_length
105 && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
106 extern_C_braces_length--;
107 brace_nesting--;
108 goto new_statement;
110 if (token == CPP_LBRACE)
112 brace_nesting++;
113 goto new_statement;
115 if (token == CPP_EOF)
116 return 0;
117 if (token == CPP_SEMICOLON)
118 goto new_statement;
119 if (token != CPP_NAME)
120 goto new_statement;
122 prev_id_start = 0;
123 declarator_start = 0;
124 for (;;)
126 switch (token)
128 case CPP_LPAREN:
129 /* Looks like this is the start of a formal parameter list. */
130 if (prev_id_start)
132 int nesting = 1;
133 int have_arg_list = 0;
134 cpp_buffer *fbuf = cpp_file_buffer (pfile);
135 long func_lineno;
136 cpp_buf_line_and_col (fbuf, &func_lineno, NULL);
137 for (;;)
139 token = cpp_get_token (pfile);
140 if (token == CPP_LPAREN)
141 nesting++;
142 else if (token == CPP_RPAREN)
144 nesting--;
145 if (nesting == 0)
146 break;
148 else if (token == CPP_EOF)
149 break;
150 else if (token == CPP_NAME || token == CPP_3DOTS)
151 have_arg_list = 1;
153 recognized_function (pfile->token_buffer + prev_id_start,
154 prev_id_end - prev_id_start,
155 (saw_inline ? 'I'
156 : in_extern_C_brace || current_extern_C
157 ? 'F' : 'f'),
158 pfile->token_buffer, prev_id_start,
159 have_arg_list,
160 fbuf->nominal_fname, func_lineno);
161 token = cpp_get_non_space_token (pfile);
162 if (token == CPP_LBRACE)
164 /* skip body of (normally) inline function */
165 skip_to_closing_brace (pfile);
166 goto new_statement;
168 goto maybe_handle_comma;
170 break;
171 case CPP_OTHER:
172 if (CPP_WRITTEN (pfile) == start_written + 1
173 && (CPP_PWRITTEN (pfile)[-1] == '*'
174 || CPP_PWRITTEN (pfile)[-1] == '&'))
175 declarator_start = start_written;
176 else
177 goto handle_statement;
178 break;
179 case CPP_COMMA:
180 case CPP_SEMICOLON:
181 if (prev_id_start && saw_extern)
183 recognized_extern (pfile->token_buffer + prev_id_start,
184 prev_id_end - prev_id_start,
185 pfile->token_buffer,
186 prev_id_start);
188 /* ... fall through ... */
189 maybe_handle_comma:
190 if (token != CPP_COMMA)
191 goto new_statement;
192 handle_comma:
193 /* Handle multiple declarators in a single declaration,
194 as in: extern char *strcpy (), *strcat (), ... ; */
195 if (declarator_start == 0)
196 declarator_start = prev_id_start;
197 CPP_SET_WRITTEN (pfile, declarator_start);
198 break;
199 case CPP_NAME:
200 /* "inline" and "extern" are recognized but skipped */
201 if (strcmp (pfile->token_buffer, "inline") == 0)
203 saw_inline = 1;
204 CPP_SET_WRITTEN (pfile, start_written);
206 if (strcmp (pfile->token_buffer, "extern") == 0)
208 saw_extern = 1;
209 CPP_SET_WRITTEN (pfile, start_written);
210 token = cpp_get_non_space_token (pfile);
211 if (token == CPP_STRING
212 && strcmp (pfile->token_buffer, "\"C\"") == 0)
214 CPP_SET_WRITTEN (pfile, start_written);
215 current_extern_C = 1;
216 token = cpp_get_non_space_token (pfile);
217 if (token == CPP_LBRACE)
219 brace_nesting++;
220 extern_C_braces[extern_C_braces_length++]
221 = brace_nesting;
222 goto new_statement;
225 else
226 continue;
227 break;
229 /* This may be the name of a variable or function. */
230 prev_id_start = start_written;
231 prev_id_end = CPP_WRITTEN (pfile);
232 break;
234 case CPP_EOF:
235 return; /* ??? FIXME */
237 case CPP_LBRACE: case CPP_RBRACE: case CPP_DIRECTIVE:
238 goto new_statement; /* handle_statement? */
240 case CPP_HSPACE: case CPP_VSPACE: case CPP_COMMENT: case CPP_POP:
241 /* Skip initial white space. */
242 if (start_written == 0)
243 CPP_SET_WRITTEN (pfile, 0);
244 break;
246 default:
247 prev_id_start = 0;
250 start_written = CPP_WRITTEN (pfile);
251 token = cpp_get_token (pfile);