Merge in gcc2 snapshot 19980929. See gcc/ChangeLog and gcc/FSFChangeLog for
[platform/upstream/gcc.git] / gcc / gen-protos.c
1 /* gen-protos.c - massages a list of prototypes, for use by fixproto.
2    Copyright (C) 1993, 94-96, 1998 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #include "hconfig.h"
19 #include "system.h"
20 #include "scan.h"
21 #include "cpplib.h"
22 #include "cpphash.h"
23
24 int verbose = 0;
25 char *progname;
26
27 #define HASH_SIZE 2503 /* a prime */
28 int hash_tab[HASH_SIZE];
29 int next_index;
30
31 static void
32 add_hash (fname)
33      char *fname;
34 {
35   int i, i0;
36
37   /* NOTE:  If you edit this, also edit lookup_std_proto in fix-header.c !! */
38   i = hashf (fname, strlen (fname), HASH_SIZE);
39   i0 = i;
40   if (hash_tab[i] != 0)
41     {
42       for (;;)
43         {
44           i = (i+1) % HASH_SIZE;
45           if (i == i0)
46             abort ();
47           if (hash_tab[i] == 0)
48             break;
49         }
50     }
51   hash_tab[i] = next_index;
52
53   next_index++;
54 }
55
56 /* Given a function prototype, fill in the fields of FN.
57    The result is a boolean indicating if a function prototype was found.
58
59    The input string is modified (trailing NULs are inserted).
60    The fields of FN point to the input string.  */
61
62 static int
63 parse_fn_proto (start, end, fn)
64      char *start, *end;
65      struct fn_decl *fn;
66 {
67   register char *ptr;
68   int param_nesting = 1;
69   char *param_start, *param_end, *decl_start, *name_start, *name_end;
70
71   ptr = end - 1;
72   while (*ptr == ' ' || *ptr == '\t') ptr--;
73   if (*ptr-- != ';')
74     {
75       fprintf (stderr, "Funny input line: %s\n", start);
76       return 0;
77     }
78   while (*ptr == ' ' || *ptr == '\t') ptr--;
79   if (*ptr != ')')
80     {
81       fprintf (stderr, "Funny input line: %s\n", start);
82       return 0;
83     }
84   param_end = ptr;
85   for (;;)
86     {
87       int c = *--ptr;
88       if (c == '(' && --param_nesting == 0)
89         break;
90       else if (c == ')')
91         param_nesting++;
92     }
93   param_start = ptr+1;
94
95   ptr--;
96   while (*ptr == ' ' || *ptr == '\t') ptr--;
97
98   if (!ISALNUM ((unsigned char)*ptr))
99     {
100       if (verbose)
101         fprintf (stderr, "%s: Can't handle this complex prototype: %s\n",
102                  progname, start);
103       return 0;
104     }
105   name_end = ptr+1;
106
107   while (ISALNUM ((unsigned char)*ptr) || *ptr == '_') --ptr;
108   name_start = ptr+1;
109   while (*ptr == ' ' || *ptr == '\t') ptr--;
110   ptr[1] = 0;
111   *param_end = 0;
112   *name_end = 0;
113
114   decl_start = start;
115   if (strncmp (decl_start, "typedef ", 8) == 0)
116     return 0;
117   if (strncmp (decl_start, "extern ", 7) == 0)
118     decl_start += 7;
119
120   fn->fname = name_start;
121   fn->rtype = decl_start;
122   fn->params = param_start;
123   return 1;
124 }
125
126 int
127 main (argc, argv)
128      int argc ATTRIBUTE_UNUSED;
129      char **argv;
130 {
131   FILE *inf = stdin;
132   FILE *outf = stdout;
133   int i;
134   sstring linebuf;
135   struct fn_decl fn_decl;
136
137   i = strlen (argv[0]);
138   while (i > 0 && argv[0][i-1] != '/') --i;
139   progname = &argv[0][i];
140
141   INIT_SSTRING (&linebuf);
142
143   fprintf (outf, "struct fn_decl std_protos[] = {\n");
144
145   /* A hash table entry of 0 means "unused" so reserve it.  */
146   fprintf (outf, "  {\"\", \"\", \"\", 0},\n");
147   next_index = 1;
148   
149   for (;;)
150     {
151       int c = skip_spaces (inf, ' ');
152
153       if (c == EOF)
154         break;
155       linebuf.ptr = linebuf.base;
156       ungetc (c, inf);
157       c = read_upto (inf, &linebuf, '\n');
158       if (linebuf.base[0] == '#') /* skip cpp command */
159         continue;
160       if (linebuf.base[0] == '\0') /* skip empty line */
161         continue;
162
163       if (! parse_fn_proto (linebuf.base, linebuf.ptr, &fn_decl))
164         continue;
165
166       add_hash (fn_decl.fname);
167
168       fprintf (outf, "  {\"%s\", \"%s\", \"%s\", 0},\n",
169                fn_decl.fname, fn_decl.rtype, fn_decl.params);
170
171       if (c == EOF)
172         break;
173     }
174   fprintf (outf, "  {0, 0, 0, 0}\n};\n");
175
176
177   fprintf (outf, "#define HASH_SIZE %d\n", HASH_SIZE);
178   fprintf (outf, "short hash_tab[HASH_SIZE] = {\n");
179   for (i = 0; i < HASH_SIZE; i++)
180     fprintf (outf, "  %d,\n", hash_tab[i]);
181   fprintf (outf, "};\n");
182
183   return 0;
184 }
185
186 /* Avoid error if config defines abort as fancy_abort.
187    It's not worth "really" implementing this because ordinary
188    compiler users never run fix-header.  */
189
190 void
191 fancy_abort ()
192 {
193   abort ();
194 }
195
196 void
197 fatal (s)
198      char *s;
199 {
200   fprintf (stderr, "%s: %s\n", "gen-protos", s);
201   exit (FATAL_EXIT_CODE);
202 }