OSDN Git Service

* configure.in (host_xm_file, build_xm_file, xm_file, tm_file):
[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 #include "scan.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 start_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   start_written = 0;
95   token = cpp_get_token (pfile);
96
97  handle_statement:
98   current_extern_C = 0;
99   saw_extern = 0;
100   saw_inline = 0;
101   if (token == CPP_RBRACE)
102     {
103       /* Pop an 'extern "C"' nesting level, if appropriate.  */
104       if (extern_C_braces_length
105           && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
106         extern_C_braces_length--;
107       brace_nesting--;
108       goto new_statement;
109     }
110   if (token == CPP_LBRACE)
111     {
112       brace_nesting++;
113       goto new_statement;
114     }
115   if (token == CPP_EOF)
116     return 0;
117   if (token == CPP_SEMICOLON)
118     goto new_statement;
119   if (token != CPP_NAME)
120     goto new_statement;
121
122   prev_id_start = 0;
123   declarator_start = 0;
124   for (;;)
125     {
126       switch (token)
127         {
128         case CPP_LPAREN:
129           /* Looks like this is the start of a formal parameter list.  */
130           if (prev_id_start)
131             {
132               int nesting = 1;
133               int have_arg_list = 0;
134               cpp_buffer *fbuf = cpp_file_buffer (pfile);
135               long func_lineno;
136               cpp_buf_line_and_col (fbuf, &func_lineno, NULL);
137               for (;;)
138                 {
139                   token = cpp_get_token (pfile);
140                   if (token == CPP_LPAREN)
141                     nesting++;
142                   else if (token == CPP_RPAREN)
143                     {
144                       nesting--;
145                       if (nesting == 0)
146                         break;
147                     }
148                   else if (token == CPP_EOF)
149                     break;
150                   else if (token == CPP_NAME || token == CPP_3DOTS)
151                     have_arg_list = 1;
152                 }
153               recognized_function (pfile->token_buffer + prev_id_start,
154                                    prev_id_end - prev_id_start,
155                                    (saw_inline ? 'I'
156                                     : in_extern_C_brace || current_extern_C
157                                     ? 'F' : 'f'),
158                                    pfile->token_buffer, prev_id_start,
159                                    have_arg_list,
160                                    fbuf->nominal_fname, func_lineno);
161               token = cpp_get_non_space_token (pfile);
162               if (token == CPP_LBRACE)
163                 {
164                   /* skip body of (normally) inline function */
165                   skip_to_closing_brace (pfile);
166                   goto new_statement;
167                 }
168               goto maybe_handle_comma;
169             }
170           break;
171         case CPP_OTHER:
172           if (CPP_WRITTEN (pfile) == start_written + 1
173               && (CPP_PWRITTEN (pfile)[-1] == '*'
174                   || CPP_PWRITTEN (pfile)[-1] == '&'))
175             declarator_start = start_written;
176           else
177             goto handle_statement;
178           break;
179         case CPP_COMMA:
180         case CPP_SEMICOLON:
181           if (prev_id_start && saw_extern)
182             {
183               recognized_extern (pfile->token_buffer + prev_id_start,
184                                  prev_id_end - prev_id_start,
185                                  pfile->token_buffer,
186                                  prev_id_start);
187             }
188           /* ... fall through ...  */
189         maybe_handle_comma:
190           if (token != CPP_COMMA)
191             goto new_statement;
192         handle_comma:
193           /* Handle multiple declarators in a single declaration,
194              as in:  extern char *strcpy (), *strcat (), ... ; */
195           if (declarator_start == 0)
196             declarator_start = prev_id_start;
197           CPP_SET_WRITTEN (pfile, declarator_start);
198           break;
199         case CPP_NAME:
200           /* "inline" and "extern" are recognized but skipped */
201           if (strcmp (pfile->token_buffer, "inline") == 0)
202             {
203               saw_inline = 1;
204               CPP_SET_WRITTEN (pfile, start_written);
205             }
206           if (strcmp (pfile->token_buffer, "extern") == 0)
207             {
208               saw_extern = 1;
209               CPP_SET_WRITTEN (pfile, start_written);
210               token = cpp_get_non_space_token (pfile);
211               if (token == CPP_STRING
212                   && strcmp (pfile->token_buffer, "\"C\"") == 0)
213                 {
214                   CPP_SET_WRITTEN (pfile, start_written);
215                   current_extern_C = 1;
216                   token = cpp_get_non_space_token (pfile);
217                   if (token == CPP_LBRACE)
218                     {
219                       brace_nesting++;
220                       extern_C_braces[extern_C_braces_length++]
221                         = brace_nesting;
222                       goto new_statement;
223                     }
224                 }
225               else
226                 continue;
227               break;
228             }
229           /* This may be the name of a variable or function.  */
230           prev_id_start = start_written;
231           prev_id_end = CPP_WRITTEN (pfile);
232           break;
233
234         case CPP_EOF:
235           return 0;
236
237         case CPP_LBRACE:  case CPP_RBRACE:  case CPP_DIRECTIVE:
238           goto new_statement;  /* handle_statement? */
239           
240         case CPP_HSPACE:  case CPP_VSPACE:  case CPP_COMMENT:  case CPP_POP:
241           /* Skip initial white space.  */
242           if (start_written == 0)
243             CPP_SET_WRITTEN (pfile, 0);
244           break;
245
246          default:
247           prev_id_start = 0;
248         }
249
250       start_written = CPP_WRITTEN (pfile);
251       token = cpp_get_token (pfile);
252     }
253 }