OSDN Git Service

Merge. See ChangeLog.
[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 /* This filter scans a C source file (actually, the output of cpp).
19    It looks for function declaration.  For each declaration, it prints:
20
21         NAME;C;RTYPE;ARGS;FILENAME;LINENO;
22
23    NAME is the function's name.
24    C is "I" if the function is declared as inline;  "F" if the
25    declaration is nested inside 'extern "C"' braces;  otherwise "f".
26    RTYPE is the function's return type.
27    ARGS is the function's argument list.
28    FILENAME and LINENO is where the declarations was seen
29    (taking #-directives into account).
30
31    Also:
32
33         NAME;M;
34    indicates that the macro NAME was seen (when invoked from fixproto).
35         NAME;X;TYPE;
36    indicates that 'extern TYPE NAME;' was seen.
37
38    Written by Per Bothner <bothner@cygnus.com>, July 1993.
39    */
40
41 #include <stdio.h>
42 #include <ctype.h>
43 #include "scan.h"
44
45 sstring buf;
46 sstring rtype;
47
48 int brace_nesting = 0;
49
50 /* The first extern_C_braces_length elements of extern_C_braces
51    indicate the (brace nesting levels of) left braces that were
52    prefixed by extern "C". */
53 int extern_C_braces_length = 0;
54 char extern_C_braces[20];
55 #define in_extern_C_brace (extern_C_braces_length>0)
56
57 /* True if the function declaration currently being scanned is
58    prefixed by extern "C". */
59 int current_extern_C = 0;
60
61 static void
62 skip_to_closing_brace (fp)
63      FILE *fp;
64 {
65   int nesting = 1;
66   for (;;)
67     {
68       int c = get_token (fp, &buf);
69       if (c == EOF)
70         break;
71       if (c == '{')
72         nesting++;
73       if (c == '}' && --nesting == 0)
74         break;
75     }
76 }
77
78 int
79 main ()
80 {
81   FILE *fp = stdin;
82   int c;
83   int saw_extern, saw_inline;
84
85  new_statement:
86   c = get_token (fp, &buf);
87  handle_statement:
88   current_extern_C = 0;
89   saw_extern = 0;
90   saw_inline = 0;
91   if (c == '}')
92     {
93       /* pop an 'extern "C"' nesting level, if appropriate */
94       if (extern_C_braces_length
95           && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
96         extern_C_braces_length--;
97       brace_nesting--;
98       goto new_statement;
99     }
100   if (c == '{')
101     {
102       brace_nesting++;
103       goto new_statement;
104     }
105   if (c == EOF)
106     return 0;
107   if (c == ';')
108     goto new_statement;
109   if (c != IDENTIFIER_TOKEN)
110     goto new_statement;
111   rtype.ptr = rtype.base;
112   if (SSTRING_LENGTH (&buf) > 16
113       && strncmp (buf.base, "__DEFINED_MACRO_", 16) == 0)
114     {
115       fprintf (stdout, "%s;M;\n", buf.base+16);
116       goto new_statement;
117     }
118   if (strcmp (buf.base, "inline") == 0)
119     {
120       saw_inline = 1;
121       c = get_token (fp, &buf);
122     }
123   if (strcmp (buf.base, "extern") == 0)
124     {
125       saw_extern = 1;
126       c = get_token (fp, &buf);
127       if (c == STRING_TOKEN && strcmp (buf.base, "C") == 0)
128         {
129           current_extern_C = 1;
130           c = get_token (fp, &buf);
131           if (c == '{')
132             {
133               brace_nesting++;
134               extern_C_braces[extern_C_braces_length++] = brace_nesting;
135               goto new_statement;
136             }
137           c = get_token (fp, &buf);
138         }
139     }
140   for (;;)
141     {
142       int followingc = getc (fp); /* char following token in buf */
143
144       MAKE_SSTRING_SPACE(&rtype, 1);
145       *rtype.ptr = 0;
146
147       if (c == IDENTIFIER_TOKEN)
148         {
149           int nextc = skip_spaces (fp, followingc);
150           if (nextc == '(')
151             {
152               int nesting = 1;
153
154               fprintf (stdout, "%s;%s;%s;",
155                        buf.base,
156                        saw_inline ? "I"
157                        : in_extern_C_brace || current_extern_C ? "F" : "f",
158                        rtype.base);
159               c = skip_spaces (fp, ' ');
160               for (;;)
161                 {
162                   if (c == '(')
163                     nesting++;
164                   else if (c == ')')
165                     if (--nesting == 0)
166                       break;
167                   if (c == EOF)
168                     break;
169                   if (c == '\n')
170                     c = ' ';
171                   putc (c, stdout);     
172                   c = getc (fp);
173                 }
174               fprintf (stdout, ";%s;%d;\n",
175                        source_filename.base, source_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               fprintf (stdout, "%s;X;%s;\n", buf.base, rtype.base);
188               goto handle_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 }