OSDN Git Service

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