OSDN Git Service

(scan_decls): After seeing an extern variable
[pf3gnuchains/gcc-fork.git] / gcc / scan-decls.c
1 /* scan-decls.c - Extracts declarations from cpp output.
2    Copyright (C) 1993 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, 675 Mass Ave, Cambridge, MA 02139, 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 "scan.h"
24
25 sstring buf;
26 sstring rtype;
27 sstring arg_list;
28
29 int brace_nesting = 0;
30
31 /* The first extern_C_braces_length elements of extern_C_braces
32    indicate the (brace nesting levels of) left braces that were
33    prefixed by extern "C".  */
34 int extern_C_braces_length = 0;
35 char extern_C_braces[20];
36 #define in_extern_C_brace (extern_C_braces_length>0)
37
38 /* True if the function declaration currently being scanned is
39    prefixed by extern "C".  */
40 int current_extern_C = 0;
41
42 static void
43 skip_to_closing_brace (fp)
44      FILE *fp;
45 {
46   int nesting = 1;
47   for (;;)
48     {
49       int c = get_token (fp, &buf);
50       if (c == EOF)
51         break;
52       if (c == '{')
53         nesting++;
54       if (c == '}' && --nesting == 0)
55         break;
56     }
57 }
58
59 /* This function scans a C source file (actually, the output of cpp),
60    reading from FP.  It looks for function declarations, and certain
61    other interesting sequences (external variables and macros).  */
62
63 int
64 scan_decls (fp)
65      FILE *fp;
66 {
67   int c;
68   int saw_extern, saw_inline;
69
70  new_statement:
71   c = get_token (fp, &buf);
72  handle_statement:
73   current_extern_C = 0;
74   saw_extern = 0;
75   saw_inline = 0;
76   if (c == '}')
77     {
78       /* Pop an 'extern "C"' nesting level, if appropriate.  */
79       if (extern_C_braces_length
80           && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
81         extern_C_braces_length--;
82       brace_nesting--;
83       goto new_statement;
84     }
85   if (c == '{')
86     {
87       brace_nesting++;
88       goto new_statement;
89     }
90   if (c == EOF)
91     return 0;
92   if (c == ';')
93     goto new_statement;
94   if (c != IDENTIFIER_TOKEN)
95     goto new_statement;
96   rtype.ptr = rtype.base;
97   if (SSTRING_LENGTH (&buf) > 16
98       && strncmp (buf.base, "__DEFINED_MACRO_", 16) == 0)
99     {
100       /* For certain interesting macro names, fixproto puts
101          #ifdef FOO
102          __DEFINED_MACRO_FOO
103          #endif
104          into the file to be pre-processed.  So if we see __DEFINED_MACRO_FOO,
105          it means FOO was defined, which we may want to make a note of.  */
106       recognized_macro (buf.base+16);
107       goto new_statement;
108     }
109   if (strcmp (buf.base, "inline") == 0)
110     {
111       saw_inline = 1;
112       c = get_token (fp, &buf);
113     }
114   if (strcmp (buf.base, "extern") == 0)
115     {
116       saw_extern = 1;
117       c = get_token (fp, &buf);
118       if (c == STRING_TOKEN && strcmp (buf.base, "C") == 0)
119         {
120           current_extern_C = 1;
121           c = get_token (fp, &buf);
122           if (c == '{')
123             {
124               brace_nesting++;
125               extern_C_braces[extern_C_braces_length++] = brace_nesting;
126               goto new_statement;
127             }
128           c = get_token (fp, &buf);
129         }
130     }
131   for (;;)
132     {
133       int followingc = getc (fp); /* char following token in buf */
134
135       MAKE_SSTRING_SPACE (&rtype, 1);
136       *rtype.ptr = 0;
137
138       if (c == IDENTIFIER_TOKEN)
139         {
140           int nextc = skip_spaces (fp, followingc);
141           if (nextc == '(')
142             {
143               int nesting = 1;
144               int func_lineno = source_lineno;
145               char *args;
146
147               arg_list.ptr = arg_list.base;
148               for (;;)
149                 {
150                   c = getc (fp);
151                   if (c == '(')
152                     nesting++;
153                   else if (c == ')')
154                     if (--nesting == 0)
155                       break;
156                   if (c == EOF)
157                     break;
158                   if (c == '\n')
159                     {
160                       c = ' ';
161                       source_lineno++;
162                       lineno++;
163                     }
164                   SSTRING_PUT (&arg_list, c);
165                 }
166               SSTRING_PUT (&arg_list, '\0');
167               args = arg_list.base;
168               while (*args == ' ')
169                 args++;
170               recognized_function (buf.base,
171                                    (saw_inline ? 'I'
172                                     : in_extern_C_brace || current_extern_C
173                                     ? 'F' : 'f'),
174                                    rtype.base, args,
175                                    source_filename.base, func_lineno);
176               c = get_token (fp, &buf);
177               if (c == '{')
178                 {
179                   /* skip body of (normally) inline function */
180                   skip_to_closing_brace (fp);
181                   goto new_statement;
182                 }
183               goto handle_statement;
184             }
185           else if (nextc == ';' && saw_extern)
186             {
187               recognized_extern (buf.base, rtype.base);
188               goto new_statement;
189             }
190           else
191             ungetc (nextc, fp);
192         }
193       else if (followingc != EOF)
194         ungetc (followingc, fp);
195       if (c == ';' || c == '{' || c == '}' || c == EOF)
196         goto handle_statement;
197       sstring_append (&rtype, &buf);
198       if (followingc == ' ' || followingc == '\t' || followingc == '\n')
199         SSTRING_PUT (&rtype, ' ');
200       c = get_token (fp, &buf);
201     }
202 }