118334Speter/* gen-protos.c - massages a list of prototypes, for use by fixproto. 290075Sobrien Copyright (C) 1993, 1994, 1995, 1996, 1998, 3169689Skan 1999, 2003, 2004, 2005 Free Software Foundation, Inc. 418334Speter 518334SpeterThis program is free software; you can redistribute it and/or modify it 618334Speterunder the terms of the GNU General Public License as published by the 718334SpeterFree Software Foundation; either version 2, or (at your option) any 818334Speterlater version. 918334Speter 1018334SpeterThis program is distributed in the hope that it will be useful, 1118334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1218334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1318334SpeterGNU General Public License for more details. 1418334Speter 1518334SpeterYou should have received a copy of the GNU General Public License 1618334Speteralong with this program; if not, write to the Free Software 17169689SkanFoundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 1818334Speter 19132718Skan#include "bconfig.h" 2050397Sobrien#include "system.h" 21132718Skan#include "coretypes.h" 22132718Skan#include "tm.h" 2318334Speter#include "scan.h" 24169689Skan#include "errors.h" 2518334Speter 2650397Sobrienint verbose = 0; 2750397Sobrien 28132718Skanstatic void add_hash (const char *); 29132718Skanstatic int parse_fn_proto (char *, char *, struct fn_decl *); 3090075Sobrien 3118334Speter#define HASH_SIZE 2503 /* a prime */ 3250397Sobrienint hash_tab[HASH_SIZE]; 3350397Sobrienint next_index; 3490075Sobrienint collisions; 3518334Speter 3650397Sobrienstatic void 37132718Skanadd_hash (const char *fname) 3850397Sobrien{ 3950397Sobrien int i, i0; 4018334Speter 4150397Sobrien /* NOTE: If you edit this, also edit lookup_std_proto in fix-header.c !! */ 4290075Sobrien i = hashstr (fname, strlen (fname)) % HASH_SIZE; 4350397Sobrien i0 = i; 4450397Sobrien if (hash_tab[i] != 0) 4550397Sobrien { 4690075Sobrien collisions++; 4750397Sobrien for (;;) 4850397Sobrien { 4950397Sobrien i = (i+1) % HASH_SIZE; 50169689Skan gcc_assert (i != i0); 5150397Sobrien if (hash_tab[i] == 0) 5250397Sobrien break; 5350397Sobrien } 5450397Sobrien } 5550397Sobrien hash_tab[i] = next_index; 5618334Speter 5750397Sobrien next_index++; 5850397Sobrien} 5918334Speter 6050397Sobrien/* Given a function prototype, fill in the fields of FN. 6150397Sobrien The result is a boolean indicating if a function prototype was found. 6250397Sobrien 6350397Sobrien The input string is modified (trailing NULs are inserted). 6450397Sobrien The fields of FN point to the input string. */ 6550397Sobrien 6650397Sobrienstatic int 67132718Skanparse_fn_proto (char *start, char *end, struct fn_decl *fn) 6818334Speter{ 6990075Sobrien char *ptr; 7050397Sobrien int param_nesting = 1; 7150397Sobrien char *param_start, *param_end, *decl_start, *name_start, *name_end; 7250397Sobrien 7350397Sobrien ptr = end - 1; 7450397Sobrien while (*ptr == ' ' || *ptr == '\t') ptr--; 7550397Sobrien if (*ptr-- != ';') 7650397Sobrien { 7750397Sobrien fprintf (stderr, "Funny input line: %s\n", start); 7850397Sobrien return 0; 7950397Sobrien } 8050397Sobrien while (*ptr == ' ' || *ptr == '\t') ptr--; 8150397Sobrien if (*ptr != ')') 8250397Sobrien { 8350397Sobrien fprintf (stderr, "Funny input line: %s\n", start); 8450397Sobrien return 0; 8550397Sobrien } 8650397Sobrien param_end = ptr; 8750397Sobrien for (;;) 8850397Sobrien { 8950397Sobrien int c = *--ptr; 9050397Sobrien if (c == '(' && --param_nesting == 0) 9150397Sobrien break; 9250397Sobrien else if (c == ')') 9350397Sobrien param_nesting++; 9450397Sobrien } 9550397Sobrien param_start = ptr+1; 9650397Sobrien 9750397Sobrien ptr--; 9850397Sobrien while (*ptr == ' ' || *ptr == '\t') ptr--; 9950397Sobrien 10052284Sobrien if (!ISALNUM ((unsigned char)*ptr)) 10150397Sobrien { 10250397Sobrien if (verbose) 10350397Sobrien fprintf (stderr, "%s: Can't handle this complex prototype: %s\n", 10450397Sobrien progname, start); 10550397Sobrien return 0; 10650397Sobrien } 10750397Sobrien name_end = ptr+1; 10850397Sobrien 10990075Sobrien while (ISIDNUM (*ptr)) 11090075Sobrien --ptr; 11150397Sobrien name_start = ptr+1; 11250397Sobrien while (*ptr == ' ' || *ptr == '\t') ptr--; 11350397Sobrien ptr[1] = 0; 11450397Sobrien *param_end = 0; 11550397Sobrien *name_end = 0; 11650397Sobrien 11750397Sobrien decl_start = start; 11850397Sobrien if (strncmp (decl_start, "typedef ", 8) == 0) 11950397Sobrien return 0; 12050397Sobrien if (strncmp (decl_start, "extern ", 7) == 0) 12150397Sobrien decl_start += 7; 12250397Sobrien 12350397Sobrien fn->fname = name_start; 12450397Sobrien fn->rtype = decl_start; 12550397Sobrien fn->params = param_start; 12650397Sobrien return 1; 12718334Speter} 12818334Speter 12918334Speterint 130132718Skanmain (int argc ATTRIBUTE_UNUSED, char **argv) 13118334Speter{ 13218334Speter FILE *inf = stdin; 13318334Speter FILE *outf = stdout; 13450397Sobrien int i; 13550397Sobrien sstring linebuf; 13650397Sobrien struct fn_decl fn_decl; 13718334Speter 13850397Sobrien i = strlen (argv[0]); 13950397Sobrien while (i > 0 && argv[0][i-1] != '/') --i; 14050397Sobrien progname = &argv[0][i]; 14150397Sobrien 142169689Skan /* Unlock the stdio streams. */ 143169689Skan unlock_std_streams (); 144169689Skan 14550397Sobrien INIT_SSTRING (&linebuf); 14650397Sobrien 14718334Speter fprintf (outf, "struct fn_decl std_protos[] = {\n"); 14818334Speter 14950397Sobrien /* A hash table entry of 0 means "unused" so reserve it. */ 15052284Sobrien fprintf (outf, " {\"\", \"\", \"\", 0},\n"); 15150397Sobrien next_index = 1; 152132718Skan 15318334Speter for (;;) 15418334Speter { 15518334Speter int c = skip_spaces (inf, ' '); 15650397Sobrien 15718334Speter if (c == EOF) 15818334Speter break; 15918334Speter linebuf.ptr = linebuf.base; 16018334Speter ungetc (c, inf); 16118334Speter c = read_upto (inf, &linebuf, '\n'); 16218334Speter if (linebuf.base[0] == '#') /* skip cpp command */ 16318334Speter continue; 16418334Speter if (linebuf.base[0] == '\0') /* skip empty line */ 16518334Speter continue; 16618334Speter 16750397Sobrien if (! parse_fn_proto (linebuf.base, linebuf.ptr, &fn_decl)) 16818334Speter continue; 16918334Speter 17050397Sobrien add_hash (fn_decl.fname); 17118334Speter 17252284Sobrien fprintf (outf, " {\"%s\", \"%s\", \"%s\", 0},\n", 17350397Sobrien fn_decl.fname, fn_decl.rtype, fn_decl.params); 17418334Speter 17518334Speter if (c == EOF) 17618334Speter break; 17718334Speter } 17852284Sobrien fprintf (outf, " {0, 0, 0, 0}\n};\n"); 17918334Speter 18018334Speter 18118334Speter fprintf (outf, "#define HASH_SIZE %d\n", HASH_SIZE); 18218334Speter fprintf (outf, "short hash_tab[HASH_SIZE] = {\n"); 18318334Speter for (i = 0; i < HASH_SIZE; i++) 18418334Speter fprintf (outf, " %d,\n", hash_tab[i]); 18518334Speter fprintf (outf, "};\n"); 18618334Speter 18790075Sobrien fprintf (stderr, "gen-protos: %d entries %d collisions\n", 18890075Sobrien next_index, collisions); 189132718Skan 19018334Speter return 0; 19118334Speter} 192