fix-header.c
来自「GCC编译器源代码」· C语言 代码 · 共 1,375 行 · 第 1/3 页
C
1,375 行
/* fix-header.c - Make C header file suitable for C++. Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.This program is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2, or (at your option) anylater version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* This program massages a system include file (such as stdio.h), into a form that is compatible with GNU C and GNU C++. * extern "C" { ... } braces are added (inside #ifndef __cplusplus), if they seem to be needed. These prevent C++ compilers from name mangling the functions inside the braces. * If an old-style incomplete function declaration is seen (without an argument list), and it is a "standard" function listed in the file sys-protos.h (and with a non-empty argument list), then the declaration is converted to a complete prototype by replacing the empty parameter list with the argument lust from sys-protos.h. * The program can be given a list of (names of) required standard functions (such as fclose for stdio.h). If a required function is not seen in the input, then a prototype for it will be written to the output. * If all of the non-comment code of the original file is protected against multiple inclusion: #ifndef FOO #define FOO <body of include file> #endif then extra matter added to the include file is placed inside the <body>. * If the input file is OK (nothing needs to be done); the output file is not written (nor removed if it exists). There are also some special actions that are done for certain well-known standard include files: * If argv[1] is "sys/stat.h", the Posix.1 macros S_ISBLK, S_ISCHR, S_ISDIR, S_ISFIFO, S_ISLNK, S_ISREG are added if they were missing, and the corresponding "traditional" S_IFxxx macros were defined. * If argv[1] is "errno.h", errno is declared if it was missing. * TODO: The input file should be read complete into memory, because: a) it needs to be scanned twice anyway, and b) it would be nice to allow update in place. Usage: fix-header FOO.H INFILE.H OUTFILE.H [OPTIONS] where: * FOO.H is the relative file name of the include file, as it would be #include'd by a C file. (E.g. stdio.h) * INFILE.H is a full pathname for the input file (e.g. /usr/include/stdio.h) * OUTFILE.H is the full pathname for where to write the output file, if anything needs to be done. (e.g. ./include/stdio.h) * OPTIONS are such as you would pass to cpp. Written by Per Bothner <bothner@cygnus.com>, July 1993. */#include <stdio.h>#include <ctype.h>#include "hconfig.h"#include "obstack.h"#include "scan.h"#include "cpplib.h"#include "gansidecl.h"#ifndef O_RDONLY#define O_RDONLY 0#endifextern void cpp_fatal ();#if !__STDC__ && !defined(const)#define const /* nothing */#endifsstring buf;int verbose = 0;int partial_count = 0;int warnings = 0;/* We no longer need to add extern "C", because cpp implicitly forces the standard include files to be treated as C. *//*#define ADD_MISSING_EXTERN_C 1 */#if ADD_MISSING_EXTERN_Cint missing_extern_C_count = 0;#endif#include "xsys-protos.h"#ifdef FIXPROTO_IGNORE_LIST/* This is a currently unused feature. *//* List of files and directories to ignore. A directory name (ending in '/') means ignore anything in that directory. (It might be more efficient to do directory pruning earlier in fixproto, but this is simpler and easier to customize.) */static char *files_to_ignore[] = { "X11/", FIXPROTO_IGNORE_LIST 0};#endifchar *inf_buffer;char *inf_limit;char *inf_ptr;/* Certain standard files get extra treatment */enum special_file{ no_special, errno_h, stdio_h, stdlib_h, sys_stat_h};/* A NAMELIST is a sequence of names, separated by '\0', and terminated by an empty name (i.e. by "\0\0"). */typedef const char *namelist;/* The following macros provide the bits for symbol_flags. */typedef int symbol_flags;/* Used to mark names defined in the ANSI/ISO C standard. */#define ANSI_SYMBOL 1/* We no longer massage include files for POSIX or XOPEN symbols, as there are now several versions of the POSIX and XOPEN standards, and it would be a maintenance nightmare for us to track them all. Better to be compatible with the system include files. *//*#define ADD_MISSING_POSIX 1 *//*#define ADD_MISSING_XOPEN 1 */#if ADD_MISSING_POSIX/* Used to mark names defined in the Posix.1 or Posix.2 standard. */#define POSIX1_SYMBOL 2#define POSIX2_SYMBOL 4#else#define POSIX1_SYMBOL 0#define POSIX2_SYMBOL 0#endif#if ADD_MISSING_XOPEN/* Used to mark names defined in X/Open Portability Guide. */#define XOPEN_SYMBOL 8/* Used to mark names defined in X/Open UNIX Extensions. */#define XOPEN_EXTENDED_SYMBOL 16#else#define XOPEN_SYMBOL 0#define XOPEN_EXTENDED_SYMBOL 0#endif/* Used to indicate names that are not functions */#define MACRO_SYMBOL 512struct symbol_list { symbol_flags flags; namelist names;};#define SYMBOL_TABLE_SIZE 10struct symbol_list symbol_table[SYMBOL_TABLE_SIZE];int cur_symbol_table_size;voidadd_symbols (flags, names) symbol_flags flags; namelist names;{ symbol_table[cur_symbol_table_size].flags = flags; symbol_table[cur_symbol_table_size].names = names; cur_symbol_table_size++; if (cur_symbol_table_size >= SYMBOL_TABLE_SIZE) fatal ("too many calls to add_symbols"); symbol_table[cur_symbol_table_size].names = NULL; /* Termination. */}struct std_include_entry { const char *name; symbol_flags flags; namelist names;};const char NONE[] = ""; /* The empty namelist. *//* Special name to indicate a continuation line in std_include_table. */const char CONTINUED[] = "";struct std_include_entry *include_entry;struct std_include_entry std_include_table [] = { { "ctype.h", ANSI_SYMBOL, "isalnum\0isalpha\0iscntrl\0isdigit\0isgraph\0islower\0\isprint\0ispunct\0isspace\0isupper\0isxdigit\0tolower\0toupper\0" }, { "dirent.h", POSIX1_SYMBOL, "closedir\0opendir\0readdir\0rewinddir\0"}, { "errno.h", ANSI_SYMBOL|MACRO_SYMBOL, "errno\0" }, /* ANSI_SYMBOL is wrong, but ... */ { "curses.h", ANSI_SYMBOL, "box\0delwin\0endwin\0getcurx\0getcury\0initscr\0\mvcur\0mvwprintw\0mvwscanw\0newwin\0overlay\0overwrite\0\scroll\0subwin\0touchwin\0waddstr\0wclear\0wclrtobot\0wclrtoeol\0\waddch\0wdelch\0wdeleteln\0werase\0wgetch\0wgetstr\0winsch\0winsertln\0\wmove\0wprintw\0wrefresh\0wscanw\0wstandend\0wstandout\0" }, { "fcntl.h", POSIX1_SYMBOL, "creat\0fcntl\0open\0" }, /* Maybe also "getgrent fgetgrent setgrent endgrent" */ { "grp.h", POSIX1_SYMBOL, "getgrgid\0getgrnam\0" },/*{ "limit.h", ... provided by gcc }, */ { "locale.h", ANSI_SYMBOL, "localeconv\0setlocale\0" }, { "math.h", ANSI_SYMBOL, "acos\0asin\0atan\0atan2\0ceil\0cos\0cosh\0exp\0\fabs\0floor\0fmod\0frexp\0ldexp\0log10\0log\0modf\0pow\0sin\0sinh\0sqrt\0\tan\0tanh\0" }, { CONTINUED, ANSI_SYMBOL|MACRO_SYMBOL, "HUGE_VAL\0" }, { "pwd.h", POSIX1_SYMBOL, "getpwnam\0getpwuid\0" }, /* Left out siglongjmp sigsetjmp - these depend on sigjmp_buf. */ { "setjmp.h", ANSI_SYMBOL, "longjmp\0setjmp\0" }, /* Left out signal() - its prototype is too complex for us! Also left out "sigaction sigaddset sigdelset sigemptyset sigfillset sigismember sigpending sigprocmask sigsuspend" because these need sigset_t or struct sigaction. Most systems that provide them will also declare them. */ { "signal.h", ANSI_SYMBOL, "kill\0raise\0" }, { "stdio.h", ANSI_SYMBOL, "clearerr\0fclose\0feof\0ferror\0fflush\0fgetc\0fgetpos\0\fgets\0fopen\0fprintf\0fputc\0fputs\0fread\0freopen\0fscanf\0fseek\0\fsetpos\0ftell\0fwrite\0getc\0getchar\0gets\0perror\0\printf\0putc\0putchar\0puts\0remove\0rename\0rewind\0scanf\0setbuf\0\setvbuf\0sprintf\0sscanf\0vprintf\0vsprintf\0vfprintf\0tmpfile\0\tmpnam\0ungetc\0" }, { CONTINUED, POSIX1_SYMBOL, "fdopen\0fileno\0" }, { CONTINUED, POSIX2_SYMBOL, "pclose\0popen\0" }, /* I think ... *//* Should perhaps also handle NULL, EOF, ... ? */ /* "div ldiv", - ignored because these depend on div_t, ldiv_t ignore these: "mblen mbstowcs mbstowc wcstombs wctomb" Left out getgroups, because SunOS4 has incompatible BSD and SVR4 versions. Should perhaps also add NULL */ { "stdlib.h", ANSI_SYMBOL, "abort\0abs\0atexit\0atof\0atoi\0atol\0bsearch\0calloc\0\exit\0free\0getenv\0labs\0malloc\0putenv\0qsort\0rand\0realloc\0\srand\0strtod\0strtol\0strtoul\0system\0" }, { CONTINUED, ANSI_SYMBOL|MACRO_SYMBOL, "EXIT_FAILURE\0EXIT_SUCCESS\0" }, { "string.h", ANSI_SYMBOL, "memchr\0memcmp\0memcpy\0memmove\0memset\0\strcat\0strchr\0strcmp\0strcoll\0strcpy\0strcspn\0strerror\0\strlen\0strncat\0strncmp\0strncpy\0strpbrk\0strrchr\0strspn\0strstr\0\strtok\0strxfrm\0" },/* Should perhaps also add NULL and size_t */ { "strings.h", XOPEN_EXTENDED_SYMBOL, "bcmp\0bcopy\0bzero\0ffs\0index\0rindex\0strcasecmp\0strncasecmp\0" }, { "strops.h", XOPEN_EXTENDED_SYMBOL, "ioctl\0" }, /* Actually, XPG4 does not seem to have <sys/ioctl.h>, but defines ioctl in <strops.h>. However, many systems have it is sys/ioctl.h, and many systems do have <sys/ioctl.h> but not <strops.h>. */ { "sys/ioctl.h", XOPEN_EXTENDED_SYMBOL, "ioctl\0" }, { "sys/socket.h", XOPEN_EXTENDED_SYMBOL, "socket\0" }, { "sys/stat.h", POSIX1_SYMBOL, "chmod\0fstat\0mkdir\0mkfifo\0stat\0lstat\0umask\0" }, { CONTINUED, POSIX1_SYMBOL|MACRO_SYMBOL, "S_ISDIR\0S_ISBLK\0S_ISCHR\0S_ISFIFO\0S_ISREG\0S_ISLNK\0S_IFDIR\0\S_IFBLK\0S_IFCHR\0S_IFIFO\0S_IFREG\0S_IFLNK\0" }, { CONTINUED, XOPEN_EXTENDED_SYMBOL, "fchmod\0" },#if 0/* How do we handle fd_set? */ { "sys/time.h", XOPEN_EXTENDED_SYMBOL, "select\0" }, { "sys/select.h", XOPEN_EXTENDED_SYMBOL /* fake */, "select\0" },#endif { "sys/times.h", POSIX1_SYMBOL, "times\0" }, /* "sys/types.h" add types (not in old g++-include) */ { "sys/utsname.h", POSIX1_SYMBOL, "uname\0" }, { "sys/wait.h", POSIX1_SYMBOL, "wait\0waitpid\0" }, { CONTINUED, POSIX1_SYMBOL|MACRO_SYMBOL, "WEXITSTATUS\0WIFEXITED\0WIFSIGNALED\0WIFSTOPPED\0WSTOPSIG\0\WTERMSIG\0WNOHANG\0WNOTRACED\0" }, { "tar.h", POSIX1_SYMBOL, NONE }, { "termios.h", POSIX1_SYMBOL, "cfgetispeed\0cfgetospeed\0cfsetispeed\0cfsetospeed\0tcdrain\0tcflow\0tcflush\0tcgetattr\0tcsendbreak\0tcsetattr\0" }, { "time.h", ANSI_SYMBOL, "asctime\0clock\0ctime\0difftime\0gmtime\0localtime\0mktime\0strftime\0time\0tzset\0" }, { "unistd.h", POSIX1_SYMBOL, "_exit\0access\0alarm\0chdir\0chown\0close\0ctermid\0cuserid\0\dup\0dup2\0execl\0execle\0execlp\0execv\0execve\0execvp\0fork\0fpathconf\0\getcwd\0getegid\0geteuid\0getgid\0getlogin\0getpgrp\0getpid\0\getppid\0getuid\0isatty\0link\0lseek\0pathconf\0pause\0pipe\0read\0rmdir\0\setgid\0setpgid\0setsid\0setuid\0sleep\0sysconf\0tcgetpgrp\0tcsetpgrp\0\ttyname\0unlink\0write\0" }, { CONTINUED, POSIX2_SYMBOL, "getopt\0" }, { CONTINUED, XOPEN_EXTENDED_SYMBOL, "lockf\0gethostid\0gethostname\0readlink\0" }, { "utime.h", POSIX1_SYMBOL, "utime\0" }, { NULL, 0, NONE }};enum special_file special_file_handling = no_special;/* They are set if the corresponding macro has been seen. *//* The following are only used when handling sys/stat.h */int seen_S_IFBLK = 0, seen_S_ISBLK = 0;int seen_S_IFCHR = 0, seen_S_ISCHR = 0;int seen_S_IFDIR = 0, seen_S_ISDIR = 0;int seen_S_IFIFO = 0, seen_S_ISFIFO = 0;int seen_S_IFLNK = 0, seen_S_ISLNK = 0;int seen_S_IFREG = 0, seen_S_ISREG = 0;/* The following are only used when handling errno.h */int seen_errno = 0;/* The following are only used when handling stdlib.h */int seen_EXIT_FAILURE = 0, seen_EXIT_SUCCESS = 0;/* Wrapper around free, to avoid prototype clashes. */voidxfree (ptr) char *ptr;{ free (ptr);}/* Avoid error if config defines abort as fancy_abort. It's not worth "really" implementing this because ordinary compiler users never run fix-header. */voidfancy_abort (){ abort ();}#define obstack_chunk_alloc xmalloc#define obstack_chunk_free xfreestruct obstack scan_file_obstack;/* NOTE: If you edit this, also edit gen-protos.c !! */struct fn_decl *lookup_std_proto (name, name_length) const char *name; int name_length;{ int i = hashf (name, name_length, HASH_SIZE); int i0 = i; for (;;) { struct fn_decl *fn; if (hash_tab[i] == 0) return NULL; fn = &std_protos[hash_tab[i]]; if (strlen (fn->fname) == name_length && strncmp (fn->fname, name, name_length) == 0) return fn; i = (i+1) % HASH_SIZE; if (i == i0) abort (); }}char *inc_filename;int inc_filename_length;char *progname = "fix-header";FILE *outf;sstring line;int lbrac_line, rbrac_line;int required_unseen_count = 0;int required_other = 0;void write_lbrac (){ #if ADD_MISSING_EXTERN_C if (missing_extern_C_count + required_unseen_count > 0) fprintf (outf, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");#endif if (partial_count) { fprintf (outf, "#ifndef _PARAMS\n"); fprintf (outf, "#if defined(__STDC__) || defined(__cplusplus)\n"); fprintf (outf, "#define _PARAMS(ARGS) ARGS\n"); fprintf (outf, "#else\n"); fprintf (outf, "#define _PARAMS(ARGS) ()\n"); fprintf (outf, "#endif\n#endif /* _PARAMS */\n"); }}struct partial_proto{ struct partial_proto *next; char *fname; /* name of function */ char *rtype; /* return type */ struct fn_decl *fn; int line_seen;};struct partial_proto *partial_proto_list = NULL;struct partial_proto required_dummy_proto, seen_dummy_proto;#define REQUIRED(FN) ((FN)->partial == &required_dummy_proto)#define SET_REQUIRED(FN) ((FN)->partial = &required_dummy_proto)#define SET_SEEN(FN) ((FN)->partial = &seen_dummy_proto)#define SEEN(FN) ((FN)->partial == &seen_dummy_proto)voidrecognized_macro (fname) char *fname;{ /* The original include file defines fname as a macro. */ struct fn_decl *fn = lookup_std_proto (fname, strlen (fname)); /* Since fname is a macro, don't require a prototype for it. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?