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

Revision 8834, 6.7 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8833, 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 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 old_written;
85  /* If declarator_start is non-zero, it marks the start of the current
86     declarator.  If it is zero, we are either still parsing the
87     decl-specs, or prev_id_start marks the start of the declarator. */
88  int declarator_start;
89  int prev_id_start, prev_id_end;
90  enum cpp_token token;
91
92 new_statement:
93  CPP_SET_WRITTEN (pfile, 0);
94  token = cpp_get_token (pfile);
95
96 handle_statement:
97  current_extern_C = 0;
98  saw_extern = 0;
99  saw_inline = 0;
100  if (token == CPP_RBRACE)
101    {
102      /* Pop an 'extern "C"' nesting level, if appropriate.  */
103      if (extern_C_braces_length
104          && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
105        extern_C_braces_length--;
106      brace_nesting--;
107      goto new_statement;
108    }
109  if (token == CPP_LBRACE)
110    {
111      brace_nesting++;
112      goto new_statement;
113    }
114  if (token == CPP_EOF)
115    return 0;
116  if (token == CPP_SEMICOLON)
117    goto new_statement;
118  if (token != CPP_NAME)
119    goto new_statement;
120
121  prev_id_start = 0;
122  declarator_start = 0;
123  for (;;)
124    {
125      int start_written = CPP_WRITTEN (pfile);
126      token = cpp_get_token (pfile);
127    handle_token:
128      switch (token)
129        {
130        case CPP_LPAREN:
131          /* Looks like this is the start of a formal parameter list. */
132          if (prev_id_start)
133            {
134              int nesting = 1;
135              int have_arg_list = 0;
136              cpp_buffer *fbuf = cpp_file_buffer (pfile);
137              long func_lineno;
138              cpp_buf_line_and_col (fbuf, &func_lineno, NULL);
139              for (;;)
140                {
141                  token = cpp_get_token (pfile);
142                  if (token == CPP_LPAREN)
143                    nesting++;
144                  else if (token == CPP_RPAREN)
145                    {
146                      nesting--;
147                      if (nesting == 0)
148                        break;
149                    }
150                  else if (token == CPP_EOF)
151                    break;
152                  else if (token == CPP_NAME || token == CPP_3DOTS)
153                    have_arg_list = 1;
154                }
155              recognized_function (pfile->token_buffer + prev_id_start,
156                                   prev_id_end - prev_id_start,
157                                   (saw_inline ? 'I'
158                                    : in_extern_C_brace || current_extern_C
159                                    ? 'F' : 'f'),
160                                   pfile->token_buffer, prev_id_start,
161                                   have_arg_list,
162                                   fbuf->nominal_fname, func_lineno);
163              token = cpp_get_non_space_token (pfile);
164              if (token == CPP_LBRACE)
165                {
166                  /* skip body of (normally) inline function */
167                  skip_to_closing_brace (pfile);
168                  goto new_statement;
169                }
170              goto maybe_handle_comma;
171            }
172          break;
173        case CPP_OTHER:
174          if (CPP_WRITTEN (pfile) == start_written + 1
175              && (CPP_PWRITTEN (pfile)[-1] == '*'
176                  || CPP_PWRITTEN (pfile)[-1] == '&'))
177            declarator_start = start_written;
178          else
179            goto handle_statement;
180          break;
181        case CPP_COMMA:
182        case CPP_SEMICOLON:
183          if (prev_id_start && saw_extern)
184            {
185              recognized_extern (pfile->token_buffer + prev_id_start,
186                                 prev_id_end - prev_id_start,
187                                 pfile->token_buffer,
188                                 prev_id_start);
189            }
190          /* ... fall through ... */
191        maybe_handle_comma:
192          if (token != CPP_COMMA)
193            goto new_statement;
194        handle_comma:
195          /* Handle multiple declarators in a single declaration,
196             as in:  extern char *strcpy (), *strcat (), ... ; */
197          if (declarator_start == 0)
198            declarator_start = prev_id_start;
199          CPP_SET_WRITTEN (pfile, declarator_start);
200          break;
201        case CPP_NAME:
202          /* "inline" and "extern" are recognized but skipped */
203          if (strcmp (pfile->token_buffer, "inline") == 0)
204            {
205              saw_inline = 1;
206              CPP_SET_WRITTEN (pfile, start_written);
207            }
208          if (strcmp (pfile->token_buffer, "extern") == 0)
209            {
210              saw_extern = 1;
211              CPP_SET_WRITTEN (pfile, start_written);
212              token = cpp_get_non_space_token (pfile);
213              if (token == CPP_STRING
214                  && strcmp (pfile->token_buffer, "\"C\"") == 0)
215                {
216                  CPP_SET_WRITTEN (pfile, start_written);
217                  current_extern_C = 1;
218                  token = cpp_get_non_space_token (pfile);
219                  if (token == CPP_LBRACE)
220                    {
221                      brace_nesting++;
222                      extern_C_braces[extern_C_braces_length++]
223                        = brace_nesting;
224                      goto new_statement;
225                    }
226                }
227              else
228                goto handle_token;
229              break;
230            }
231          /* This may be the name of a variable or function. */
232          prev_id_start = start_written;
233          prev_id_end = CPP_WRITTEN (pfile);
234          break;
235
236        case CPP_EOF:
237          return;  /* ??? FIXME */
238
239        case CPP_LBRACE:  case CPP_RBRACE:  case CPP_DIRECTIVE:
240          goto new_statement;  /* handle_statement? */
241         
242        case CPP_HSPACE:  case CPP_VSPACE:  case CPP_COMMENT:  case CPP_POP:
243          /* Skip initial white space. */
244          if (start_written == 0)
245            CPP_SET_WRITTEN (pfile, 0);
246          break;
247
248         default:
249          prev_id_start = 0;
250        }
251    }
252}
Note: See TracBrowser for help on using the repository browser.