OSDN Git Service

* Makefile.in (final.o): Depend on BASIC_BLOCK_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,
3    1999, 2000 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19    Written by Per Bothner <bothner@cygnus.com>, July 1993.  */
20
21 #include "hconfig.h"
22 #include "system.h"
23 #include "cpplib.h"
24 #include "scan.h"
25
26 static void skip_to_closing_brace PARAMS ((cpp_reader *));
27
28 int brace_nesting = 0;
29
30 /* The first extern_C_braces_length elements of extern_C_braces
31    indicate the (brace nesting levels of) left braces that were
32    prefixed by extern "C".  */
33 int extern_C_braces_length = 0;
34 char extern_C_braces[20];
35 #define in_extern_C_brace (extern_C_braces_length>0)
36
37 /* True if the function declaration currently being scanned is
38    prefixed by extern "C".  */
39 int current_extern_C = 0;
40
41 static void
42 skip_to_closing_brace (pfile)
43      cpp_reader *pfile;
44 {
45   int nesting = 1;
46   for (;;)
47     {
48       enum cpp_ttype token = cpp_get_token (pfile);
49       if (token == CPP_EOF)
50         break;
51       if (token == CPP_OPEN_BRACE)
52         nesting++;
53       if (token == CPP_CLOSE_BRACE && --nesting == 0)
54         break;
55     }
56 }
57
58 /* This function scans a C source file (actually, the output of cpp),
59    reading from FP.  It looks for function declarations, and
60    external variable declarations.  
61
62    The following grammar (as well as some extra stuff) is recognized:
63
64    declaration:
65      (decl-specifier)* declarator ("," declarator)* ";"
66    decl-specifier:
67      identifier
68      keyword
69      extern "C"
70    declarator:
71      (ptr-operator)* dname [ "(" argument-declaration-list ")" ]
72    ptr-operator:
73      ("*" | "&") ("const" | "volatile")*
74    dname:
75      identifier
76
77 Here dname is the actual name being declared.
78 */
79
80 int
81 scan_decls (pfile, argc, argv)
82      cpp_reader *pfile;
83      int argc ATTRIBUTE_UNUSED;
84      char **argv ATTRIBUTE_UNUSED;
85 {
86   int saw_extern, saw_inline;
87   int start_written;
88   /* If declarator_start is non-zero, it marks the start of the current
89      declarator.  If it is zero, we are either still parsing the
90      decl-specs, or prev_id_start marks the start of the declarator.  */
91   int declarator_start;
92   int prev_id_start, prev_id_end = 0;
93   enum cpp_ttype token;
94
95  new_statement:
96   CPP_SET_WRITTEN (pfile, 0);
97   start_written = 0;
98   token = cpp_get_token (pfile);
99
100  handle_statement:
101   current_extern_C = 0;
102   saw_extern = 0;
103   saw_inline = 0;
104   if (token == CPP_OPEN_BRACE)
105     {
106       /* Pop an 'extern "C"' nesting level, if appropriate.  */
107       if (extern_C_braces_length
108           && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
109         extern_C_braces_length--;
110       brace_nesting--;
111       goto new_statement;
112     }
113   if (token == CPP_OPEN_BRACE)
114     {
115       brace_nesting++;
116       goto new_statement;
117     }
118   if (token == CPP_EOF)
119     {
120       if (CPP_BUFFER (pfile) == NULL)
121         return 0;
122       else
123         goto new_statement;
124     }
125   if (token == CPP_SEMICOLON)
126     goto new_statement;
127   if (token != CPP_NAME)
128     goto new_statement;
129
130   prev_id_start = 0;
131   declarator_start = 0;
132   for (;;)
133     {
134       switch (token)
135         {
136         case CPP_OPEN_PAREN:
137           /* Looks like this is the start of a formal parameter list.  */
138           if (prev_id_start)
139             {
140               int nesting = 1;
141               int have_arg_list = 0;
142               cpp_buffer *fbuf = cpp_file_buffer (pfile);
143               unsigned int func_lineno = CPP_BUF_LINE (fbuf);
144               for (;;)
145                 {
146                   token = cpp_get_token (pfile);
147                   if (token == CPP_OPEN_PAREN)
148                     nesting++;
149                   else if (token == CPP_CLOSE_PAREN)
150                     {
151                       nesting--;
152                       if (nesting == 0)
153                         break;
154                     }
155                   else if (token == CPP_EOF)
156                     break;
157                   else if (token == CPP_NAME || token == CPP_ELLIPSIS)
158                     have_arg_list = 1;
159                 }
160               recognized_function (pfile->token_buffer + prev_id_start,
161                                    prev_id_end - prev_id_start,
162                                    (saw_inline ? 'I'
163                                     : in_extern_C_brace || current_extern_C
164                                     ? 'F' : 'f'),
165                                    pfile->token_buffer, prev_id_start,
166                                    have_arg_list,
167                                    fbuf->nominal_fname, func_lineno);
168               token = cpp_get_non_space_token (pfile);
169               if (token == CPP_OPEN_BRACE)
170                 {
171                   /* skip body of (normally) inline function */
172                   skip_to_closing_brace (pfile);
173                   goto new_statement;
174                 }
175               goto maybe_handle_comma;
176             }
177           break;
178         case CPP_OTHER:
179           if (CPP_WRITTEN (pfile) == (size_t) start_written + 1
180               && (CPP_PWRITTEN (pfile)[-1] == '*'
181                   || CPP_PWRITTEN (pfile)[-1] == '&'))
182             declarator_start = start_written;
183           else
184             goto handle_statement;
185           break;
186         case CPP_COMMA:
187         case CPP_SEMICOLON:
188           if (prev_id_start && saw_extern)
189             {
190               recognized_extern (pfile->token_buffer + prev_id_start,
191                                  prev_id_end - prev_id_start,
192                                  pfile->token_buffer,
193                                  prev_id_start);
194             }
195           /* ... fall through ...  */
196         maybe_handle_comma:
197           if (token != CPP_COMMA)
198             goto new_statement;
199
200           /* Handle multiple declarators in a single declaration,
201              as in:  extern char *strcpy (), *strcat (), ... ; */
202           if (declarator_start == 0)
203             declarator_start = prev_id_start;
204           CPP_SET_WRITTEN (pfile, declarator_start);
205           break;
206         case CPP_NAME:
207           /* "inline" and "extern" are recognized but skipped */
208           if (!cpp_idcmp (pfile->token_buffer,
209                           CPP_WRITTEN (pfile), "inline"))
210             {
211               saw_inline = 1;
212               CPP_SET_WRITTEN (pfile, start_written);
213             }
214           else if (!cpp_idcmp (pfile->token_buffer,
215                                CPP_WRITTEN (pfile), "extern"))
216             {
217               saw_extern = 1;
218               CPP_SET_WRITTEN (pfile, start_written);
219               token = cpp_get_non_space_token (pfile);
220               if (token == CPP_STRING
221                   && strcmp (pfile->token_buffer, "\"C\"") == 0)
222                 {
223                   CPP_SET_WRITTEN (pfile, start_written);
224                   current_extern_C = 1;
225                   token = cpp_get_non_space_token (pfile);
226                   if (token == CPP_OPEN_BRACE)
227                     {
228                       brace_nesting++;
229                       extern_C_braces[extern_C_braces_length++]
230                         = brace_nesting;
231                       goto new_statement;
232                     }
233                 }
234               else
235                 continue;
236               break;
237             }
238           /* This may be the name of a variable or function.  */
239           prev_id_start = start_written;
240           prev_id_end = CPP_WRITTEN (pfile);
241           break;
242
243         case CPP_OPEN_BRACE:  case CPP_CLOSE_BRACE:  case CPP_DIRECTIVE:
244           goto new_statement;  /* handle_statement? */
245           
246         case CPP_EOF:
247           if (CPP_BUFFER (pfile) == NULL)
248             return 0;
249           /* else fall through */
250
251         case CPP_HSPACE:  case CPP_VSPACE:  case CPP_COMMENT:
252           /* Skip initial white space.  */
253           if (start_written == 0)
254             CPP_SET_WRITTEN (pfile, 0);
255           break;
256
257          default:
258           prev_id_start = 0;
259         }
260
261       start_written = CPP_WRITTEN (pfile);
262       token = cpp_get_token (pfile);
263     }
264 }