Change HANDLE_PRAGMA macro so that it supports USE_CPPLIB
[official-gcc.git] / gcc / scan-decls.c
blobd2f32a86cf91a741d8dd26b412304ee3cd87c398
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 "gansidecl.h"
23 #include "cpplib.h"
24 #include "scan.h"
26 int brace_nesting = 0;
28 /* The first extern_C_braces_length elements of extern_C_braces
29 indicate the (brace nesting levels of) left braces that were
30 prefixed by extern "C". */
31 int extern_C_braces_length = 0;
32 char extern_C_braces[20];
33 #define in_extern_C_brace (extern_C_braces_length>0)
35 /* True if the function declaration currently being scanned is
36 prefixed by extern "C". */
37 int current_extern_C = 0;
39 static void
40 skip_to_closing_brace (pfile)
41 cpp_reader *pfile;
43 int nesting = 1;
44 for (;;)
46 enum cpp_token token = cpp_get_token (pfile);
47 if (token == CPP_EOF)
48 break;
49 if (token == CPP_LBRACE)
50 nesting++;
51 if (token == CPP_RBRACE && --nesting == 0)
52 break;
56 /* This function scans a C source file (actually, the output of cpp),
57 reading from FP. It looks for function declarations, and
58 external variable declarations.
60 The following grammar (as well as some extra stuff) is recognized:
62 declaration:
63 (decl-specifier)* declarator ("," declarator)* ";"
64 decl-specifier:
65 identifier
66 keyword
67 extern "C"
68 declarator:
69 (ptr-operator)* dname [ "(" argument-declaration-list ")" ]
70 ptr-operator:
71 ("*" | "&") ("const" | "volatile")*
72 dname:
73 identifier
75 Here dname is the actual name being declared.
78 int
79 scan_decls (pfile, argc, argv)
80 cpp_reader *pfile;
81 int argc;
82 char **argv;
84 int saw_extern, saw_inline;
85 int start_written;
86 /* If declarator_start is non-zero, it marks the start of the current
87 declarator. If it is zero, we are either still parsing the
88 decl-specs, or prev_id_start marks the start of the declarator. */
89 int declarator_start;
90 int prev_id_start, prev_id_end;
91 enum cpp_token token;
93 new_statement:
94 CPP_SET_WRITTEN (pfile, 0);
95 start_written = 0;
96 token = cpp_get_token (pfile);
98 handle_statement:
99 current_extern_C = 0;
100 saw_extern = 0;
101 saw_inline = 0;
102 if (token == CPP_RBRACE)
104 /* Pop an 'extern "C"' nesting level, if appropriate. */
105 if (extern_C_braces_length
106 && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
107 extern_C_braces_length--;
108 brace_nesting--;
109 goto new_statement;
111 if (token == CPP_LBRACE)
113 brace_nesting++;
114 goto new_statement;
116 if (token == CPP_EOF)
117 return 0;
118 if (token == CPP_SEMICOLON)
119 goto new_statement;
120 if (token != CPP_NAME)
121 goto new_statement;
123 prev_id_start = 0;
124 declarator_start = 0;
125 for (;;)
127 switch (token)
129 case CPP_LPAREN:
130 /* Looks like this is the start of a formal parameter list. */
131 if (prev_id_start)
133 int nesting = 1;
134 int have_arg_list = 0;
135 cpp_buffer *fbuf = cpp_file_buffer (pfile);
136 long func_lineno;
137 cpp_buf_line_and_col (fbuf, &func_lineno, NULL);
138 for (;;)
140 token = cpp_get_token (pfile);
141 if (token == CPP_LPAREN)
142 nesting++;
143 else if (token == CPP_RPAREN)
145 nesting--;
146 if (nesting == 0)
147 break;
149 else if (token == CPP_EOF)
150 break;
151 else if (token == CPP_NAME || token == CPP_3DOTS)
152 have_arg_list = 1;
154 recognized_function (pfile->token_buffer + prev_id_start,
155 prev_id_end - prev_id_start,
156 (saw_inline ? 'I'
157 : in_extern_C_brace || current_extern_C
158 ? 'F' : 'f'),
159 pfile->token_buffer, prev_id_start,
160 have_arg_list,
161 fbuf->nominal_fname, func_lineno);
162 token = cpp_get_non_space_token (pfile);
163 if (token == CPP_LBRACE)
165 /* skip body of (normally) inline function */
166 skip_to_closing_brace (pfile);
167 goto new_statement;
169 goto maybe_handle_comma;
171 break;
172 case CPP_OTHER:
173 if (CPP_WRITTEN (pfile) == start_written + 1
174 && (CPP_PWRITTEN (pfile)[-1] == '*'
175 || CPP_PWRITTEN (pfile)[-1] == '&'))
176 declarator_start = start_written;
177 else
178 goto handle_statement;
179 break;
180 case CPP_COMMA:
181 case CPP_SEMICOLON:
182 if (prev_id_start && saw_extern)
184 recognized_extern (pfile->token_buffer + prev_id_start,
185 prev_id_end - prev_id_start,
186 pfile->token_buffer,
187 prev_id_start);
189 /* ... fall through ... */
190 maybe_handle_comma:
191 if (token != CPP_COMMA)
192 goto new_statement;
193 handle_comma:
194 /* Handle multiple declarators in a single declaration,
195 as in: extern char *strcpy (), *strcat (), ... ; */
196 if (declarator_start == 0)
197 declarator_start = prev_id_start;
198 CPP_SET_WRITTEN (pfile, declarator_start);
199 break;
200 case CPP_NAME:
201 /* "inline" and "extern" are recognized but skipped */
202 if (strcmp (pfile->token_buffer, "inline") == 0)
204 saw_inline = 1;
205 CPP_SET_WRITTEN (pfile, start_written);
207 if (strcmp (pfile->token_buffer, "extern") == 0)
209 saw_extern = 1;
210 CPP_SET_WRITTEN (pfile, start_written);
211 token = cpp_get_non_space_token (pfile);
212 if (token == CPP_STRING
213 && strcmp (pfile->token_buffer, "\"C\"") == 0)
215 CPP_SET_WRITTEN (pfile, start_written);
216 current_extern_C = 1;
217 token = cpp_get_non_space_token (pfile);
218 if (token == CPP_LBRACE)
220 brace_nesting++;
221 extern_C_braces[extern_C_braces_length++]
222 = brace_nesting;
223 goto new_statement;
226 else
227 continue;
228 break;
230 /* This may be the name of a variable or function. */
231 prev_id_start = start_written;
232 prev_id_end = CPP_WRITTEN (pfile);
233 break;
235 case CPP_EOF:
236 return 0;
238 case CPP_LBRACE: case CPP_RBRACE: case CPP_DIRECTIVE:
239 goto new_statement; /* handle_statement? */
241 case CPP_HSPACE: case CPP_VSPACE: case CPP_COMMENT: case CPP_POP:
242 /* Skip initial white space. */
243 if (start_written == 0)
244 CPP_SET_WRITTEN (pfile, 0);
245 break;
247 default:
248 prev_id_start = 0;
251 start_written = CPP_WRITTEN (pfile);
252 token = cpp_get_token (pfile);