OSDN Git Service

* except.c (expand_start_all_catch): If the machine needs to
[pf3gnuchains/gcc-fork.git] / gcc / scan-decls.c
1 /* scan-decls.c - Extracts declarations from cpp output.
2    Copyright (C) 1993, 1995 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 <stdio.h>
21 #include <ctype.h>
22 #include "hconfig.h"
23 #include "cpplib.h"
24
25 int brace_nesting = 0;
26
27 /* The first extern_C_braces_length elements of extern_C_braces
28    indicate the (brace nesting levels of) left braces that were
29    prefixed by extern "C".  */
30 int extern_C_braces_length = 0;
31 char extern_C_braces[20];
32 #define in_extern_C_brace (extern_C_braces_length>0)
33
34 /* True if the function declaration currently being scanned is
35    prefixed by extern "C".  */
36 int current_extern_C = 0;
37
38 static void
39 skip_to_closing_brace (pfile)
40      cpp_reader *pfile;
41 {
42   int nesting = 1;
43   for (;;)
44     {
45       enum cpp_token token = cpp_get_token (pfile);
46       if (token == CPP_EOF)
47         break;
48       if (token == CPP_LBRACE)
49         nesting++;
50       if (token == CPP_RBRACE && --nesting == 0)
51         break;
52     }
53 }
54
55 /* This function scans a C source file (actually, the output of cpp),
56    reading from FP.  It looks for function declarations, and
57    external variable declarations.  
58
59    The following grammar (as well as some extra stuff) is recognized:
60
61    declaration:
62      (decl-specifier)* declarator ("," declarator)* ";"
63    decl-specifier:
64      identifier
65      keyword
66      extern "C"
67    declarator:
68      (ptr-operator)* dname [ "(" argument-declaration-list ")" ]
69    ptr-operator:
70      ("*" | "&") ("const" | "volatile")*
71    dname:
72      identifier
73
74 Here dname is the actual name being declared.
75 */
76
77 int
78 scan_decls (pfile, argc, argv)
79      cpp_reader *pfile;
80      int argc;
81      char **argv;
82 {
83   int saw_extern, saw_inline;
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;
91
92  new_statement:
93   CPP_SET_WRITTEN (pfile, 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       int start_written = CPP_WRITTEN (pfile);
126       token = cpp_get_token (pfile);
127     handle_token:
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) == 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         handle_comma:
195           /* Handle multiple declarators in a single declaration,
196              as in:  extern char *strcpy (), *strcat (), ... ; */
197           if (declarator_start == 0)
198             declarator_start = prev_id_start;
199           CPP_SET_WRITTEN (pfile, declarator_start);
200           break;
201         case CPP_NAME:
202           /* "inline" and "extern" are recognized but skipped */
203           if (strcmp (pfile->token_buffer, "inline") == 0)
204             {
205               saw_inline = 1;
206               CPP_SET_WRITTEN (pfile, start_written);
207             }
208           if (strcmp (pfile->token_buffer, "extern") == 0)
209             {
210               saw_extern = 1;
211               CPP_SET_WRITTEN (pfile, start_written);
212               token = cpp_get_non_space_token (pfile);
213               if (token == CPP_STRING
214                   && strcmp (pfile->token_buffer, "\"C\"") == 0)
215                 {
216                   CPP_SET_WRITTEN (pfile, start_written);
217                   current_extern_C = 1;
218                   token = cpp_get_non_space_token (pfile);
219                   if (token == CPP_LBRACE)
220                     {
221                       brace_nesting++;
222                       extern_C_braces[extern_C_braces_length++]
223                         = brace_nesting;
224                       goto new_statement;
225                     }
226                 }
227               else
228                 goto handle_token;
229               break;
230             }
231           /* This may be the name of a variable or function.  */
232           prev_id_start = start_written;
233           prev_id_end = CPP_WRITTEN (pfile);
234           break;
235
236         case CPP_EOF:
237           return;  /* ??? FIXME */
238
239         case CPP_LBRACE:  case CPP_RBRACE:  case CPP_DIRECTIVE:
240           goto new_statement;  /* handle_statement? */
241           
242         case CPP_HSPACE:  case CPP_VSPACE:  case CPP_COMMENT:  case CPP_POP:
243           /* Skip initial white space.  */
244           if (start_written == 0)
245             CPP_SET_WRITTEN (pfile, 0);
246           break;
247
248          default:
249           prev_id_start = 0;
250         }
251     }
252 }