Mercurial > hg > CbC > CbC_gcc
comparison gcc/scan-decls.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* scan-decls.c - Extracts declarations from cpp output. | |
2 Copyright (C) 1993, 1995, 1997, 1998, | |
3 1999, 2000, 2003, 2004, 2007 Free Software Foundation, Inc. | |
4 | |
5 This program is free software; you can redistribute it and/or modify it | |
6 under the terms of the GNU General Public License as published by the | |
7 Free Software Foundation; either version 3, or (at your option) any | |
8 later version. | |
9 | |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program; see the file COPYING3. If not see | |
17 <http://www.gnu.org/licenses/>. | |
18 | |
19 Written by Per Bothner <bothner@cygnus.com>, July 1993. */ | |
20 | |
21 #include "bconfig.h" | |
22 #include "system.h" | |
23 #include "coretypes.h" | |
24 #include "tm.h" | |
25 #include "cpplib.h" | |
26 #include "scan.h" | |
27 | |
28 static void skip_to_closing_brace (cpp_reader *); | |
29 static const cpp_token *get_a_token (cpp_reader *); | |
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 /* 20 is not enough anymore on Solaris 9. */ | |
38 #define MAX_EXTERN_C_BRACES 200 | |
39 char extern_C_braces[MAX_EXTERN_C_BRACES]; | |
40 #define in_extern_C_brace (extern_C_braces_length>0) | |
41 | |
42 /* True if the function declaration currently being scanned is | |
43 prefixed by extern "C". */ | |
44 int current_extern_C = 0; | |
45 | |
46 /* Get a token but skip padding. */ | |
47 static const cpp_token * | |
48 get_a_token (cpp_reader *pfile) | |
49 { | |
50 for (;;) | |
51 { | |
52 const cpp_token *result = cpp_get_token (pfile); | |
53 if (result->type != CPP_PADDING) | |
54 return result; | |
55 } | |
56 } | |
57 | |
58 static void | |
59 skip_to_closing_brace (cpp_reader *pfile) | |
60 { | |
61 int nesting = 1; | |
62 for (;;) | |
63 { | |
64 enum cpp_ttype token = get_a_token (pfile)->type; | |
65 | |
66 if (token == CPP_EOF) | |
67 break; | |
68 if (token == CPP_OPEN_BRACE) | |
69 nesting++; | |
70 if (token == CPP_CLOSE_BRACE && --nesting == 0) | |
71 break; | |
72 } | |
73 } | |
74 | |
75 /* This function scans a C source file (actually, the output of cpp), | |
76 reading from FP. It looks for function declarations, and | |
77 external variable declarations. | |
78 | |
79 The following grammar (as well as some extra stuff) is recognized: | |
80 | |
81 declaration: | |
82 (decl-specifier)* declarator ("," declarator)* ";" | |
83 decl-specifier: | |
84 identifier | |
85 keyword | |
86 extern "C" | |
87 declarator: | |
88 (ptr-operator)* dname [ "(" argument-declaration-list ")" ] | |
89 ptr-operator: | |
90 ("*" | "&") ("const" | "volatile")* | |
91 dname: | |
92 identifier | |
93 | |
94 Here dname is the actual name being declared. | |
95 */ | |
96 | |
97 int | |
98 scan_decls (cpp_reader *pfile, int argc ATTRIBUTE_UNUSED, | |
99 char **argv ATTRIBUTE_UNUSED) | |
100 { | |
101 int saw_extern, saw_inline; | |
102 cpp_token prev_id; | |
103 const cpp_token *token; | |
104 | |
105 new_statement: | |
106 token = get_a_token (pfile); | |
107 | |
108 handle_statement: | |
109 current_extern_C = 0; | |
110 saw_extern = 0; | |
111 saw_inline = 0; | |
112 if (token->type == CPP_OPEN_BRACE) | |
113 { | |
114 /* Pop an 'extern "C"' nesting level, if appropriate. */ | |
115 if (extern_C_braces_length | |
116 && extern_C_braces[extern_C_braces_length - 1] == brace_nesting) | |
117 extern_C_braces_length--; | |
118 brace_nesting--; | |
119 goto new_statement; | |
120 } | |
121 if (token->type == CPP_OPEN_BRACE) | |
122 { | |
123 brace_nesting++; | |
124 goto new_statement; | |
125 } | |
126 | |
127 if (token->type == CPP_EOF) | |
128 return 0; | |
129 | |
130 if (token->type == CPP_SEMICOLON) | |
131 goto new_statement; | |
132 if (token->type != CPP_NAME) | |
133 goto new_statement; | |
134 | |
135 prev_id.type = CPP_EOF; | |
136 for (;;) | |
137 { | |
138 switch (token->type) | |
139 { | |
140 default: | |
141 goto handle_statement; | |
142 case CPP_MULT: | |
143 case CPP_AND: | |
144 /* skip */ | |
145 break; | |
146 | |
147 case CPP_COMMA: | |
148 case CPP_SEMICOLON: | |
149 if (prev_id.type != CPP_EOF && saw_extern) | |
150 { | |
151 recognized_extern (&prev_id); | |
152 } | |
153 if (token->type == CPP_COMMA) | |
154 break; | |
155 /* ... fall through ... */ | |
156 case CPP_OPEN_BRACE: case CPP_CLOSE_BRACE: | |
157 goto new_statement; | |
158 | |
159 case CPP_EOF: | |
160 return 0; | |
161 | |
162 case CPP_OPEN_PAREN: | |
163 /* Looks like this is the start of a formal parameter list. */ | |
164 if (prev_id.type != CPP_EOF) | |
165 { | |
166 int nesting = 1; | |
167 int have_arg_list = 0; | |
168 const struct line_map *map; | |
169 unsigned int line; | |
170 for (;;) | |
171 { | |
172 token = get_a_token (pfile); | |
173 if (token->type == CPP_OPEN_PAREN) | |
174 nesting++; | |
175 else if (token->type == CPP_CLOSE_PAREN) | |
176 { | |
177 nesting--; | |
178 if (nesting == 0) | |
179 break; | |
180 } | |
181 else if (token->type == CPP_EOF) | |
182 break; | |
183 else if (token->type == CPP_NAME | |
184 || token->type == CPP_ELLIPSIS) | |
185 have_arg_list = 1; | |
186 } | |
187 map = linemap_lookup (&line_table, token->src_loc); | |
188 line = SOURCE_LINE (map, token->src_loc); | |
189 recognized_function (&prev_id, line, | |
190 (saw_inline ? 'I' | |
191 : in_extern_C_brace || current_extern_C | |
192 ? 'F' : 'f'), have_arg_list); | |
193 token = get_a_token (pfile); | |
194 if (token->type == CPP_OPEN_BRACE) | |
195 { | |
196 /* skip body of (normally) inline function */ | |
197 skip_to_closing_brace (pfile); | |
198 goto new_statement; | |
199 } | |
200 | |
201 /* skip a possible __attribute__ or throw expression after the | |
202 parameter list */ | |
203 while (token->type != CPP_SEMICOLON && token->type != CPP_EOF) | |
204 token = get_a_token (pfile); | |
205 if (token->type == CPP_EOF) | |
206 return 0; | |
207 goto new_statement; | |
208 } | |
209 break; | |
210 case CPP_NAME: | |
211 /* "inline" and "extern" are recognized but skipped */ | |
212 if (cpp_ideq (token, "inline")) | |
213 { | |
214 saw_inline = 1; | |
215 } | |
216 else if (cpp_ideq (token, "extern")) | |
217 { | |
218 saw_extern = 1; | |
219 token = get_a_token (pfile); | |
220 if (token->type == CPP_STRING | |
221 && token->val.str.len == 1 | |
222 && token->val.str.text[0] == 'C') | |
223 { | |
224 current_extern_C = 1; | |
225 token = get_a_token (pfile); | |
226 if (token->type == CPP_OPEN_BRACE) | |
227 { | |
228 brace_nesting++; | |
229 extern_C_braces[extern_C_braces_length++] | |
230 = brace_nesting; | |
231 if (extern_C_braces_length >= MAX_EXTERN_C_BRACES) | |
232 { | |
233 fprintf (stderr, | |
234 "Internal error: out-of-bounds index\n"); | |
235 exit (FATAL_EXIT_CODE); | |
236 } | |
237 goto new_statement; | |
238 } | |
239 } | |
240 else | |
241 continue; | |
242 break; | |
243 } | |
244 /* This may be the name of a variable or function. */ | |
245 prev_id = *token; | |
246 break; | |
247 } | |
248 token = get_a_token (pfile); | |
249 } | |
250 } |