|
|
1.1 root 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 <[email protected]>, 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.