OSDN Git Service

* reload1.c (move2add_last_cc0): New.
[pf3gnuchains/gcc-fork.git] / gcc / scan-decls.c
1 /* scan-decls.c - Extracts declarations from cpp output.
2    Copyright (C) 1993, 1995, 1997, 1998,
3    1999, 2000 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 2, 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; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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 PARAMS ((cpp_reader *));
29 static const cpp_token *get_a_token PARAMS ((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 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 /* Get a token but skip padding.  */
45 static const cpp_token *
46 get_a_token (pfile)
47      cpp_reader *pfile;
48 {
49   for (;;)
50     {
51       const cpp_token *result = cpp_get_token (pfile);
52       if (result->type != CPP_PADDING)
53         return result;
54     }
55 }
56
57 static void
58 skip_to_closing_brace (pfile)
59      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 (pfile, argc, argv)
99      cpp_reader *pfile;
100      int argc ATTRIBUTE_UNUSED;
101      char **argv ATTRIBUTE_UNUSED;
102 {
103   int saw_extern, saw_inline;
104   cpp_token prev_id;
105   const cpp_token *token;
106
107  new_statement:
108   token = get_a_token (pfile);
109
110  handle_statement:
111   current_extern_C = 0;
112   saw_extern = 0;
113   saw_inline = 0;
114   if (token->type == CPP_OPEN_BRACE)
115     {
116       /* Pop an 'extern "C"' nesting level, if appropriate.  */
117       if (extern_C_braces_length
118           && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
119         extern_C_braces_length--;
120       brace_nesting--;
121       goto new_statement;
122     }
123   if (token->type == CPP_OPEN_BRACE)
124     {
125       brace_nesting++;
126       goto new_statement;
127     }
128
129   if (token->type == CPP_EOF)
130     return 0;
131
132   if (token->type == CPP_SEMICOLON)
133     goto new_statement;
134   if (token->type != CPP_NAME)
135     goto new_statement;
136
137   prev_id.type = CPP_EOF;
138   for (;;)
139     {
140       switch (token->type)
141         {
142         default:
143           goto handle_statement;
144         case CPP_MULT:
145         case CPP_AND:
146           /* skip */
147           break;
148
149         case CPP_COMMA:
150         case CPP_SEMICOLON:
151           if (prev_id.type != CPP_EOF && saw_extern)
152             {
153               recognized_extern (&prev_id);
154             }
155           if (token->type == CPP_COMMA)
156             break;
157           /* ... fall through ...  */
158         case CPP_OPEN_BRACE:  case CPP_CLOSE_BRACE:
159           goto new_statement;
160
161         case CPP_EOF:
162           return 0;
163
164         case CPP_OPEN_PAREN:
165           /* Looks like this is the start of a formal parameter list.  */
166           if (prev_id.type != CPP_EOF)
167             {
168               int nesting = 1;
169               int have_arg_list = 0;
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               recognized_function (&prev_id, token->line,
188                                    (saw_inline ? 'I'
189                                     : in_extern_C_brace || current_extern_C
190                                     ? 'F' : 'f'), have_arg_list);
191               token = get_a_token (pfile);
192               if (token->type == CPP_OPEN_BRACE)
193                 {
194                   /* skip body of (normally) inline function */
195                   skip_to_closing_brace (pfile);
196                   goto new_statement;
197                 }
198
199               /* skip a possible __attribute__ or throw expression after the
200                  parameter list */
201               while (token->type != CPP_SEMICOLON && token->type != CPP_EOF)
202                 token = get_a_token (pfile);
203               goto new_statement;
204             }
205           break;
206         case CPP_NAME:
207           /* "inline" and "extern" are recognized but skipped */
208           if (cpp_ideq (token, "inline"))
209             {
210               saw_inline = 1;
211             }
212           else if (cpp_ideq (token, "extern"))
213             {
214               saw_extern = 1;
215               token = get_a_token (pfile);
216               if (token->type == CPP_STRING
217                   && token->val.str.len == 1
218                   && token->val.str.text[0] == 'C')
219                 {
220                   current_extern_C = 1;
221                   token = get_a_token (pfile);
222                   if (token->type == CPP_OPEN_BRACE)
223                     {
224                       brace_nesting++;
225                       extern_C_braces[extern_C_braces_length++]
226                         = brace_nesting;
227                       goto new_statement;
228                     }
229                 }
230               else
231                 continue;
232               break;
233             }
234           /* This may be the name of a variable or function.  */
235           prev_id = *token;
236           break;
237         }
238       token = get_a_token (pfile);
239     }
240 }