source: trunk/third/gcc/scan-decls.c @ 11288

Revision 11288, 6.7 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11287, which included commits to RCS files with non-trunk default branches.
Line 
1/* scan-decls.c - Extracts declarations from cpp output.
2   Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc.
3
4This program is free software; you can redistribute it and/or modify it
5under the terms of the GNU General Public License as published by the
6Free Software Foundation; either version 2, or (at your option) any
7later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18   Written by Per Bothner <bothner@cygnus.com>, July 1993.  */
19
20#include <stdio.h>
21#include <ctype.h>
22#include "hconfig.h"
23#include "cpplib.h"
24
25int brace_nesting = 0;
26
27/* The first extern_C_braces_length elements of extern_C_braces
28   indicate the (brace nesting levels of) left braces that were
29   prefixed by extern "C".  */
30int extern_C_braces_length = 0;
31char extern_C_braces[20];
32#define in_extern_C_brace (extern_C_braces_length>0)
33
34/* True if the function declaration currently being scanned is
35   prefixed by extern "C".  */
36int current_extern_C = 0;
37
38static void
39skip_to_closing_brace (pfile)
40     cpp_reader *pfile;
41{
42  int nesting = 1;
43  for (;;)
44    {
45      enum cpp_token token = cpp_get_token (pfile);
46      if (token == CPP_EOF)
47        break;
48      if (token == CPP_LBRACE)
49        nesting++;
50      if (token == CPP_RBRACE && --nesting == 0)
51        break;
52    }
53}
54
55/* This function scans a C source file (actually, the output of cpp),
56   reading from FP.  It looks for function declarations, and
57   external variable declarations. 
58
59   The following grammar (as well as some extra stuff) is recognized:
60
61   declaration:
62     (decl-specifier)* declarator ("," declarator)* ";"
63   decl-specifier:
64     identifier
65     keyword
66     extern "C"
67   declarator:
68     (ptr-operator)* dname [ "(" argument-declaration-list ")" ]
69   ptr-operator:
70     ("*" | "&") ("const" | "volatile")*
71   dname:
72     identifier
73
74Here dname is the actual name being declared.
75*/
76
77int
78scan_decls (pfile, argc, argv)
79     cpp_reader *pfile;
80     int argc;
81     char **argv;
82{
83  int saw_extern, saw_inline;
84  int start_written;
85  int old_written;
86  /* If declarator_start is non-zero, it marks the start of the current
87     declarator.  If it is zero, we are either still parsing the
88     decl-specs, or prev_id_start marks the start of the declarator.  */
89  int declarator_start;
90  int prev_id_start, prev_id_end;
91  enum cpp_token token;
92
93 new_statement:
94  CPP_SET_WRITTEN (pfile, 0);
95  start_written = 0;
96  token = cpp_get_token (pfile);
97
98 handle_statement:
99  current_extern_C = 0;
100  saw_extern = 0;
101  saw_inline = 0;
102  if (token == CPP_RBRACE)
103    {
104      /* Pop an 'extern "C"' nesting level, if appropriate.  */
105      if (extern_C_braces_length
106          && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
107        extern_C_braces_length--;
108      brace_nesting--;
109      goto new_statement;
110    }
111  if (token == CPP_LBRACE)
112    {
113      brace_nesting++;
114      goto new_statement;
115    }
116  if (token == CPP_EOF)
117    return 0;
118  if (token == CPP_SEMICOLON)
119    goto new_statement;
120  if (token != CPP_NAME)
121    goto new_statement;
122
123  prev_id_start = 0;
124  declarator_start = 0;
125  for (;;)
126    {
127      switch (token)
128        {
129        case CPP_LPAREN:
130          /* Looks like this is the start of a formal parameter list.  */
131          if (prev_id_start)
132            {
133              int nesting = 1;
134              int have_arg_list = 0;
135              cpp_buffer *fbuf = cpp_file_buffer (pfile);
136              long func_lineno;
137              cpp_buf_line_and_col (fbuf, &func_lineno, NULL);
138              for (;;)
139                {
140                  token = cpp_get_token (pfile);
141                  if (token == CPP_LPAREN)
142                    nesting++;
143                  else if (token == CPP_RPAREN)
144                    {
145                      nesting--;
146                      if (nesting == 0)
147                        break;
148                    }
149                  else if (token == CPP_EOF)
150                    break;
151                  else if (token == CPP_NAME || token == CPP_3DOTS)
152                    have_arg_list = 1;
153                }
154              recognized_function (pfile->token_buffer + prev_id_start,
155                                   prev_id_end - prev_id_start,
156                                   (saw_inline ? 'I'
157                                    : in_extern_C_brace || current_extern_C
158                                    ? 'F' : 'f'),
159                                   pfile->token_buffer, prev_id_start,
160                                   have_arg_list,
161                                   fbuf->nominal_fname, func_lineno);
162              token = cpp_get_non_space_token (pfile);
163              if (token == CPP_LBRACE)
164                {
165                  /* skip body of (normally) inline function */
166                  skip_to_closing_brace (pfile);
167                  goto new_statement;
168                }
169              goto maybe_handle_comma;
170            }
171          break;
172        case CPP_OTHER:
173          if (CPP_WRITTEN (pfile) == start_written + 1
174              && (CPP_PWRITTEN (pfile)[-1] == '*'
175                  || CPP_PWRITTEN (pfile)[-1] == '&'))
176            declarator_start = start_written;
177          else
178            goto handle_statement;
179          break;
180        case CPP_COMMA:
181        case CPP_SEMICOLON:
182          if (prev_id_start && saw_extern)
183            {
184              recognized_extern (pfile->token_buffer + prev_id_start,
185                                 prev_id_end - prev_id_start,
186                                 pfile->token_buffer,
187                                 prev_id_start);
188            }
189          /* ... fall through ...  */
190        maybe_handle_comma:
191          if (token != CPP_COMMA)
192            goto new_statement;
193        handle_comma:
194          /* Handle multiple declarators in a single declaration,
195             as in:  extern char *strcpy (), *strcat (), ... ; */
196          if (declarator_start == 0)
197            declarator_start = prev_id_start;
198          CPP_SET_WRITTEN (pfile, declarator_start);
199          break;
200        case CPP_NAME:
201          /* "inline" and "extern" are recognized but skipped */
202          if (strcmp (pfile->token_buffer, "inline") == 0)
203            {
204              saw_inline = 1;
205              CPP_SET_WRITTEN (pfile, start_written);
206            }
207          if (strcmp (pfile->token_buffer, "extern") == 0)
208            {
209              saw_extern = 1;
210              CPP_SET_WRITTEN (pfile, start_written);
211              token = cpp_get_non_space_token (pfile);
212              if (token == CPP_STRING
213                  && strcmp (pfile->token_buffer, "\"C\"") == 0)
214                {
215                  CPP_SET_WRITTEN (pfile, start_written);
216                  current_extern_C = 1;
217                  token = cpp_get_non_space_token (pfile);
218                  if (token == CPP_LBRACE)
219                    {
220                      brace_nesting++;
221                      extern_C_braces[extern_C_braces_length++]
222                        = brace_nesting;
223                      goto new_statement;
224                    }
225                }
226              else
227                continue;
228              break;
229            }
230          /* This may be the name of a variable or function.  */
231          prev_id_start = start_written;
232          prev_id_end = CPP_WRITTEN (pfile);
233          break;
234
235        case CPP_EOF:
236          return;  /* ??? FIXME */
237
238        case CPP_LBRACE:  case CPP_RBRACE:  case CPP_DIRECTIVE:
239          goto new_statement;  /* handle_statement? */
240         
241        case CPP_HSPACE:  case CPP_VSPACE:  case CPP_COMMENT:  case CPP_POP:
242          /* Skip initial white space.  */
243          if (start_written == 0)
244            CPP_SET_WRITTEN (pfile, 0);
245          break;
246
247         default:
248          prev_id_start = 0;
249        }
250
251      start_written = CPP_WRITTEN (pfile);
252      token = cpp_get_token (pfile);
253    }
254}
Note: See TracBrowser for help on using the repository browser.