OSDN Git Service

* print-tree.c (print_node, indent_to): Remove redundant prototypes.
[pf3gnuchains/gcc-fork.git] / gcc / scan-decls.c
1 /* scan-decls.c - Extracts declarations from cpp output.
2    Copyright (C) 1993, 1995, 97-98, 1999 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 #include "scan.h"
24
25 static void skip_to_closing_brace PARAMS ((cpp_reader *));
26
27 int brace_nesting = 0;
28
29 /* The first extern_C_braces_length elements of extern_C_braces
30    indicate the (brace nesting levels of) left braces that were
31    prefixed by extern "C".  */
32 int extern_C_braces_length = 0;
33 char extern_C_braces[20];
34 #define in_extern_C_brace (extern_C_braces_length>0)
35
36 /* True if the function declaration currently being scanned is
37    prefixed by extern "C".  */
38 int current_extern_C = 0;
39
40 static void
41 skip_to_closing_brace (pfile)
42      cpp_reader *pfile;
43 {
44   int nesting = 1;
45   for (;;)
46     {
47       enum cpp_token token = cpp_get_token (pfile);
48       if (token == CPP_EOF)
49         break;
50       if (token == CPP_LBRACE)
51         nesting++;
52       if (token == CPP_RBRACE && --nesting == 0)
53         break;
54     }
55 }
56
57 /* This function scans a C source file (actually, the output of cpp),
58    reading from FP.  It looks for function declarations, and
59    external variable declarations.  
60
61    The following grammar (as well as some extra stuff) is recognized:
62
63    declaration:
64      (decl-specifier)* declarator ("," declarator)* ";"
65    decl-specifier:
66      identifier
67      keyword
68      extern "C"
69    declarator:
70      (ptr-operator)* dname [ "(" argument-declaration-list ")" ]
71    ptr-operator:
72      ("*" | "&") ("const" | "volatile")*
73    dname:
74      identifier
75
76 Here dname is the actual name being declared.
77 */
78
79 int
80 scan_decls (pfile, argc, argv)
81      cpp_reader *pfile;
82      int argc ATTRIBUTE_UNUSED;
83      char **argv ATTRIBUTE_UNUSED;
84 {
85   int saw_extern, saw_inline;
86   int start_written;
87   /* If declarator_start is non-zero, it marks the start of the current
88      declarator.  If it is zero, we are either still parsing the
89      decl-specs, or prev_id_start marks the start of the declarator.  */
90   int declarator_start;
91   int prev_id_start, prev_id_end;
92   enum cpp_token token;
93
94  new_statement:
95   CPP_SET_WRITTEN (pfile, 0);
96   start_written = 0;
97   token = cpp_get_token (pfile);
98
99  handle_statement:
100   current_extern_C = 0;
101   saw_extern = 0;
102   saw_inline = 0;
103   if (token == CPP_RBRACE)
104     {
105       /* Pop an 'extern "C"' nesting level, if appropriate.  */
106       if (extern_C_braces_length
107           && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
108         extern_C_braces_length--;
109       brace_nesting--;
110       goto new_statement;
111     }
112   if (token == CPP_LBRACE)
113     {
114       brace_nesting++;
115       goto new_statement;
116     }
117   if (token == CPP_EOF)
118     return 0;
119   if (token == CPP_SEMICOLON)
120     goto new_statement;
121   if (token != CPP_NAME)
122     goto new_statement;
123
124   prev_id_start = 0;
125   declarator_start = 0;
126   for (;;)
127     {
128       switch (token)
129         {
130         case CPP_LPAREN:
131           /* Looks like this is the start of a formal parameter list.  */
132           if (prev_id_start)
133             {
134               int nesting = 1;
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);
139               for (;;)
140                 {
141                   token = cpp_get_token (pfile);
142                   if (token == CPP_LPAREN)
143                     nesting++;
144                   else if (token == CPP_RPAREN)
145                     {
146                       nesting--;
147                       if (nesting == 0)
148                         break;
149                     }
150                   else if (token == CPP_EOF)
151                     break;
152                   else if (token == CPP_NAME || token == CPP_3DOTS)
153                     have_arg_list = 1;
154                 }
155               recognized_function (pfile->token_buffer + prev_id_start,
156                                    prev_id_end - prev_id_start,
157                                    (saw_inline ? 'I'
158                                     : in_extern_C_brace || current_extern_C
159                                     ? 'F' : 'f'),
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)
165                 {
166                   /* skip body of (normally) inline function */
167                   skip_to_closing_brace (pfile);
168                   goto new_statement;
169                 }
170               goto maybe_handle_comma;
171             }
172           break;
173         case CPP_OTHER:
174           if (CPP_WRITTEN (pfile) == (size_t) 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)
184             {
185               recognized_extern (pfile->token_buffer + prev_id_start,
186                                  prev_id_end - prev_id_start,
187                                  pfile->token_buffer,
188                                  prev_id_start);
189             }
190           /* ... fall through ...  */
191         maybe_handle_comma:
192           if (token != CPP_COMMA)
193             goto new_statement;
194 #if 0
195         handle_comma:
196 #endif
197           /* Handle multiple declarators in a single declaration,
198              as in:  extern char *strcpy (), *strcat (), ... ; */
199           if (declarator_start == 0)
200             declarator_start = prev_id_start;
201           CPP_SET_WRITTEN (pfile, declarator_start);
202           break;
203         case CPP_NAME:
204           /* "inline" and "extern" are recognized but skipped */
205           if (strcmp (pfile->token_buffer, "inline") == 0)
206             {
207               saw_inline = 1;
208               CPP_SET_WRITTEN (pfile, start_written);
209             }
210           if (strcmp (pfile->token_buffer, "extern") == 0)
211             {
212               saw_extern = 1;
213               CPP_SET_WRITTEN (pfile, start_written);
214               token = cpp_get_non_space_token (pfile);
215               if (token == CPP_STRING
216                   && strcmp (pfile->token_buffer, "\"C\"") == 0)
217                 {
218                   CPP_SET_WRITTEN (pfile, start_written);
219                   current_extern_C = 1;
220                   token = cpp_get_non_space_token (pfile);
221                   if (token == CPP_LBRACE)
222                     {
223                       brace_nesting++;
224                       extern_C_braces[extern_C_braces_length++]
225                         = brace_nesting;
226                       goto new_statement;
227                     }
228                 }
229               else
230                 continue;
231               break;
232             }
233           /* This may be the name of a variable or function.  */
234           prev_id_start = start_written;
235           prev_id_end = CPP_WRITTEN (pfile);
236           break;
237
238         case CPP_EOF:
239           return 0;
240
241         case CPP_LBRACE:  case CPP_RBRACE:  case CPP_DIRECTIVE:
242           goto new_statement;  /* handle_statement? */
243           
244         case CPP_HSPACE:  case CPP_VSPACE:  case CPP_COMMENT:  case CPP_POP:
245           /* Skip initial white space.  */
246           if (start_written == 0)
247             CPP_SET_WRITTEN (pfile, 0);
248           break;
249
250          default:
251           prev_id_start = 0;
252         }
253
254       start_written = CPP_WRITTEN (pfile);
255       token = cpp_get_token (pfile);
256     }
257 }