OSDN Git Service

More cutover to system.h:
[pf3gnuchains/gcc-fork.git] / gcc / scan-decls.c
1 /* scan-decls.c - Extracts declarations from cpp output.
2    Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
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
16 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18    Written by Per Bothner <bothner@cygnus.com>, July 1993.  */
19
20 #include "hconfig.h"
21 #include "system.h"
22 #include "cpplib.h"
23
24 int brace_nesting = 0;
25
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)
32
33 /* True if the function declaration currently being scanned is
34    prefixed by extern "C".  */
35 int current_extern_C = 0;
36
37 static void
38 skip_to_closing_brace (pfile)
39      cpp_reader *pfile;
40 {
41   int nesting = 1;
42   for (;;)
43     {
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;
51     }
52 }
53
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.  
57
58    The following grammar (as well as some extra stuff) is recognized:
59
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
72
73 Here dname is the actual name being declared.
74 */
75
76 int
77 scan_decls (pfile, argc, argv)
78      cpp_reader *pfile;
79      int argc;
80      char **argv;
81 {
82   int saw_extern, saw_inline;
83   int start_written;
84   /* If declarator_start is non-zero, it marks the start of the current
85      declarator.  If it is zero, we are either still parsing the
86      decl-specs, or prev_id_start marks the start of the declarator.  */
87   int declarator_start;
88   int prev_id_start, prev_id_end;
89   enum cpp_token token;
90
91  new_statement:
92   CPP_SET_WRITTEN (pfile, 0);
93   start_written = 0;
94   token = cpp_get_token (pfile);
95
96  handle_statement:
97   current_extern_C = 0;
98   saw_extern = 0;
99   saw_inline = 0;
100   if (token == CPP_RBRACE)
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     }
109   if (token == CPP_LBRACE)
110     {
111       brace_nesting++;
112       goto new_statement;
113     }
114   if (token == CPP_EOF)
115     return 0;
116   if (token == CPP_SEMICOLON)
117     goto new_statement;
118   if (token != CPP_NAME)
119     goto new_statement;
120
121   prev_id_start = 0;
122   declarator_start = 0;
123   for (;;)
124     {
125       switch (token)
126         {
127         case CPP_LPAREN:
128           /* Looks like this is the start of a formal parameter list.  */
129           if (prev_id_start)
130             {
131               int nesting = 1;
132               int have_arg_list = 0;
133               cpp_buffer *fbuf = cpp_file_buffer (pfile);
134               long func_lineno;
135               cpp_buf_line_and_col (fbuf, &func_lineno, NULL);
136               for (;;)
137                 {
138                   token = cpp_get_token (pfile);
139                   if (token == CPP_LPAREN)
140                     nesting++;
141                   else if (token == CPP_RPAREN)
142                     {
143                       nesting--;
144                       if (nesting == 0)
145                         break;
146                     }
147                   else if (token == CPP_EOF)
148                     break;
149                   else if (token == CPP_NAME || token == CPP_3DOTS)
150                     have_arg_list = 1;
151                 }
152               recognized_function (pfile->token_buffer + prev_id_start,
153                                    prev_id_end - prev_id_start,
154                                    (saw_inline ? 'I'
155                                     : in_extern_C_brace || current_extern_C
156                                     ? 'F' : 'f'),
157                                    pfile->token_buffer, prev_id_start,
158                                    have_arg_list,
159                                    fbuf->nominal_fname, func_lineno);
160               token = cpp_get_non_space_token (pfile);
161               if (token == CPP_LBRACE)
162                 {
163                   /* skip body of (normally) inline function */
164                   skip_to_closing_brace (pfile);
165                   goto new_statement;
166                 }
167               goto maybe_handle_comma;
168             }
169           break;
170         case CPP_OTHER:
171           if (CPP_WRITTEN (pfile) == start_written + 1
172               && (CPP_PWRITTEN (pfile)[-1] == '*'
173                   || CPP_PWRITTEN (pfile)[-1] == '&'))
174             declarator_start = start_written;
175           else
176             goto handle_statement;
177           break;
178         case CPP_COMMA:
179         case CPP_SEMICOLON:
180           if (prev_id_start && saw_extern)
181             {
182               recognized_extern (pfile->token_buffer + prev_id_start,
183                                  prev_id_end - prev_id_start,
184                                  pfile->token_buffer,
185                                  prev_id_start);
186             }
187           /* ... fall through ...  */
188         maybe_handle_comma:
189           if (token != CPP_COMMA)
190             goto new_statement;
191         handle_comma:
192           /* Handle multiple declarators in a single declaration,
193              as in:  extern char *strcpy (), *strcat (), ... ; */
194           if (declarator_start == 0)
195             declarator_start = prev_id_start;
196           CPP_SET_WRITTEN (pfile, declarator_start);
197           break;
198         case CPP_NAME:
199           /* "inline" and "extern" are recognized but skipped */
200           if (strcmp (pfile->token_buffer, "inline") == 0)
201             {
202               saw_inline = 1;
203               CPP_SET_WRITTEN (pfile, start_written);
204             }
205           if (strcmp (pfile->token_buffer, "extern") == 0)
206             {
207               saw_extern = 1;
208               CPP_SET_WRITTEN (pfile, start_written);
209               token = cpp_get_non_space_token (pfile);
210               if (token == CPP_STRING
211                   && strcmp (pfile->token_buffer, "\"C\"") == 0)
212                 {
213                   CPP_SET_WRITTEN (pfile, start_written);
214                   current_extern_C = 1;
215                   token = cpp_get_non_space_token (pfile);
216                   if (token == CPP_LBRACE)
217                     {
218                       brace_nesting++;
219                       extern_C_braces[extern_C_braces_length++]
220                         = brace_nesting;
221                       goto new_statement;
222                     }
223                 }
224               else
225                 continue;
226               break;
227             }
228           /* This may be the name of a variable or function.  */
229           prev_id_start = start_written;
230           prev_id_end = CPP_WRITTEN (pfile);
231           break;
232
233         case CPP_EOF:
234           return 0;
235
236         case CPP_LBRACE:  case CPP_RBRACE:  case CPP_DIRECTIVE:
237           goto new_statement;  /* handle_statement? */
238           
239         case CPP_HSPACE:  case CPP_VSPACE:  case CPP_COMMENT:  case CPP_POP:
240           /* Skip initial white space.  */
241           if (start_written == 0)
242             CPP_SET_WRITTEN (pfile, 0);
243           break;
244
245          default:
246           prev_id_start = 0;
247         }
248
249       start_written = CPP_WRITTEN (pfile);
250       token = cpp_get_token (pfile);
251     }
252 }