📄 fix-header.c
字号:
/* fix-header.c - Make C header file suitable for C++. Copyright (C) 1993, 1994, 1995 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 more conforming with ANSI/POSIX, and more suitable for 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"#ifndef O_RDONLY#define O_RDONLY 0#endif#if !__STDC__#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;#endifint missing_errno = 0;#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, 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;struct std_include_entry { const char *name; namelist required; namelist extra; int special;};/* End of namelist NAMES. */namelistnamelist_end (names) namelist names;{ register namelist ptr; for (ptr = names; ; ptr++) { if (*ptr == '\0') { ptr++; if (*ptr == '\0') return ptr; } }}const char NONE[] = "";struct std_include_entry *include_entry;struct std_include_entry std_include_table [] = { { "ctype.h", "isalnum\0isalpha\0iscntrl\0isdigit\0isgraph\0islower\0\isprint\0ispunct\0isspace\0isupper\0isxdigit\0tolower\0toupper\0", NONE }, { "dirent.h", "closedir\0opendir\0readdir\0rewinddir\0", NONE}, { "errno.h", NONE, "errno\0" }, { "curses.h", "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", NONE }, { "fcntl.h", "creat\0fcntl\0open\0", NONE }, /* Maybe also "getgrent fgetgrent setgrent endgrent" */ { "grp.h", "getgrgid\0getgrnam\0", NONE },/*{ "limit.h", ... provided by gcc }, */ { "locale.h", "localeconv\0setlocale\0", NONE }, { "math.h", "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", "HUGE_VAL\0" }, { "pwd.h", "getpwnam\0getpwuid\0", NONE }, /* Left out siglongjmp sigsetjmp - these depend on sigjmp_buf. */ { "setjmp.h", "longjmp\0setjmp\0", NONE }, /* 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", "kill\0raise\0", NONE }, { "stdio.h", "clearerr\0fclose\0feof\0ferror\0fflush\0fgetc\0fgetpos\0\fgets\0fopen\0fprintf\0fputc\0fputs\0fread\0freopen\0fscanf\0fseek\0\fsetpos\0ftell\0fwrite\0getc\0getchar\0gets\0pclose\0perror\0popen\0\printf\0putc\0putchar\0puts\0remove\0rename\0rewind\0scanf\0setbuf\0\setvbuf\0sprintf\0sscanf\0vprintf\0vsprintf\0vfprintf\0tmpfile\0\tmpnam\0ungetc\0", NONE },/* 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", "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", NONE }, { "string.h", "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", NONE },/* Should perhaps also add NULL and size_t */ { "sys/stat.h", "chmod\0fstat\0mkdir\0mkfifo\0stat\0lstat\0umask\0", "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" }, { "sys/times.h", "times\0", NONE }, /* "sys/types.h" add types (not in old g++-include) */ { "sys/utsname.h", "uname\0", NONE }, { "sys/wait.h", "wait\0waitpid\0", "WEXITSTATUS\0WIFEXITED\0WIFSIGNALED\0WIFSTOPPED\0WSTOPSIG\0\WTERMSIG\0WNOHANG\0WNOTRACED\0" }, { "tar.h", NONE, NONE }, { "termios.h", "cfgetispeed\0cfgetospeed\0cfsetispeed\0cfsetospeed\0tcdrain\0tcflow\0tcflush\0tcgetattr\0tcsendbreak\0tcsetattr\0", NONE }, { "time.h", "asctime\0clock\0ctime\0difftime\0gmtime\0localtime\0mktime\0strftime\0time\0tzset\0", NONE }, { "unistd.h", "_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\0getopt\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", NONE }, { 0, NONE, NONE }};enum special_file special_file_handling = no_special;/* The following are only used when handling sys/stat.h *//* They are set if the corresponding macro has been seen. */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;/* 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;namelist required_functions_list;int required_unseen_count = 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. */ if (fn) { if (REQUIRED (fn)) required_unseen_count--; SET_SEEN (fn); } switch (special_file_handling) { case errno_h: if (strcmp (fname, "errno") == 0) missing_errno = 0; break; case sys_stat_h: if (fname[0] == 'S' && fname[1] == '_') { if (strcmp (fname, "S_IFBLK") == 0) seen_S_IFBLK++; else if (strcmp (fname, "S_ISBLK") == 0) seen_S_ISBLK++; else if (strcmp (fname, "S_IFCHR") == 0) seen_S_IFCHR++; else if (strcmp (fname, "S_ISCHR") == 0) seen_S_ISCHR++; else if (strcmp (fname, "S_IFDIR") == 0) seen_S_IFDIR++; else if (strcmp (fname, "S_ISDIR") == 0) seen_S_ISDIR++; else if (strcmp (fname, "S_IFIFO") == 0) seen_S_IFIFO++; else if (strcmp (fname, "S_ISFIFO") == 0) seen_S_ISFIFO++; else if (strcmp (fname, "S_IFLNK") == 0) seen_S_IFLNK++; else if (strcmp (fname, "S_ISLNK") == 0) seen_S_ISLNK++; else if (strcmp (fname, "S_IFREG") == 0) seen_S_IFREG++; else if (strcmp (fname, "S_ISREG") == 0) seen_S_ISREG++; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -