|
|
1.1 root 1: /* fix-header.c - Make C header file suitable for C++. 1.1.1.3 ! root 2: Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. 1.1 root 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 1.1.1.3 ! root 16: Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 1.1 root 17: 18: /* This program massages a system include file (such as stdio.h), 1.1.1.3 ! root 19: into a form more conforming with ANSI/POSIX, and more suitable for C++: 1.1 root 20: 21: * extern "C" { ... } braces are added (inside #ifndef __cplusplus), 22: if they seem to be needed. These prevent C++ compilers from name 23: mangling the functions inside the braces. 24: 25: * If an old-style incomplete function declaration is seen (without 26: an argument list), and it is a "standard" function listed in 27: the file sys-protos.h (and with a non-empty argument list), then 28: the declaration is converted to a complete prototype by replacing 29: the empty parameter list with the argument lust from sys-protos.h. 30: 31: * The program can be given a list of (names of) required standard 1.1.1.3 ! root 32: functions (such as fclose for stdio.h). If a required function 1.1 root 33: is not seen in the input, then a prototype for it will be 34: written to the output. 35: 36: * If all of the non-comment code of the original file is protected 37: against multiple inclusion: 38: #ifndef FOO 39: #define FOO 40: <body of include file> 41: #endif 42: then extra matter added to the include file is placed inside the <body>. 43: 44: * If the input file is OK (nothing needs to be done); 45: the output file is not written (nor removed if it exists). 46: 47: There are also some special actions that are done for certain 48: well-known standard include files: 49: 50: * If argv[1] is "sys/stat.h", the Posix.1 macros 51: S_ISBLK, S_ISCHR, S_ISDIR, S_ISFIFO, S_ISLNK, S_ISREG are added if 52: they were missing, and the corresponding "traditional" S_IFxxx 53: macros were defined. 54: 55: * If argv[1] is "errno.h", errno is declared if it was missing. 56: 57: * TODO: The input file should be read complete into memory, because: 58: a) it needs to be scanned twice anyway, and 59: b) it would be nice to allow update in place. 60: 61: Usage: 1.1.1.3 ! root 62: fix-header FOO.H INFILE.H OUTFILE.H [OPTIONS] 1.1 root 63: where: 64: * FOO.H is the relative file name of the include file, 65: as it would be #include'd by a C file. (E.g. stdio.h) 66: * INFILE.H is a full pathname for the input file (e.g. /usr/include/stdio.h) 67: * OUTFILE.H is the full pathname for where to write the output file, 68: if anything needs to be done. (e.g. ./include/stdio.h) 1.1.1.3 ! root 69: * OPTIONS are such as you would pass to cpp. 1.1 root 70: 71: Written by Per Bothner <[email protected]>, July 1993. */ 72: 73: #include <stdio.h> 74: #include <ctype.h> 75: #include "hconfig.h" 76: #include "obstack.h" 77: #include "scan.h" 1.1.1.3 ! root 78: #include "cpplib.h" ! 79: #ifndef O_RDONLY ! 80: #define O_RDONLY 0 ! 81: #endif ! 82: ! 83: #if !__STDC__ ! 84: #define const /* nothing */ ! 85: #endif 1.1 root 86: 1.1.1.3 ! root 87: sstring buf; 1.1.1.2 root 88: 1.1 root 89: int verbose = 0; 90: int partial_count = 0; 1.1.1.3 ! root 91: int warnings = 0; ! 92: ! 93: /* We no longer need to add extern "C", because cpp implicitly ! 94: forces the standard include files to be treated as C. */ ! 95: /*#define ADD_MISSING_EXTERN_C 1 */ ! 96: ! 97: #if ADD_MISSING_EXTERN_C 1.1 root 98: int missing_extern_C_count = 0; 1.1.1.2 root 99: #endif 1.1 root 100: int missing_errno = 0; 101: 102: #include "xsys-protos.h" 103: 1.1.1.3 ! root 104: #ifdef FIXPROTO_IGNORE_LIST ! 105: /* This is a currently unused feature. */ ! 106: ! 107: /* List of files and directories to ignore. ! 108: A directory name (ending in '/') means ignore anything in that ! 109: directory. (It might be more efficient to do directory pruning ! 110: earlier in fixproto, but this is simpler and easier to customize.) */ ! 111: ! 112: static char *files_to_ignore[] = { ! 113: "X11/", ! 114: FIXPROTO_IGNORE_LIST ! 115: 0 ! 116: }; ! 117: #endif ! 118: 1.1 root 119: char *inf_buffer; 120: char *inf_limit; 121: char *inf_ptr; 122: 123: /* Certain standard files get extra treatment */ 124: 125: enum special_file 126: { 127: no_special, 1.1.1.3 ! root 128: errno_h, ! 129: stdio_h, ! 130: sys_stat_h ! 131: }; ! 132: ! 133: /* A NAMELIST is a sequence of names, separated by '\0', and terminated ! 134: by an empty name (i.e. by "\0\0"). */ ! 135: ! 136: typedef const char* namelist; ! 137: ! 138: struct std_include_entry { ! 139: const char *name; ! 140: namelist required; ! 141: namelist extra; ! 142: int special; ! 143: }; ! 144: ! 145: /* End of namelist NAMES. */ ! 146: ! 147: namelist ! 148: namelist_end (names) ! 149: namelist names; ! 150: { ! 151: register namelist ptr; ! 152: for (ptr = names; ; ptr++) ! 153: { ! 154: if (*ptr == '\0') ! 155: { ! 156: ptr++; ! 157: if (*ptr == '\0') ! 158: return ptr; ! 159: } ! 160: } ! 161: } ! 162: ! 163: const char NONE[] = ""; ! 164: ! 165: struct std_include_entry *include_entry; ! 166: ! 167: struct std_include_entry std_include_table [] = { ! 168: { "ctype.h", ! 169: "isalnum\0isalpha\0iscntrl\0isdigit\0isgraph\0islower\0\ ! 170: isprint\0ispunct\0isspace\0isupper\0isxdigit\0tolower\0toupper\0", NONE }, ! 171: ! 172: { "dirent.h", "closedir\0opendir\0readdir\0rewinddir\0", NONE}, ! 173: ! 174: { "errno.h", NONE, "errno\0" }, ! 175: ! 176: { "curses.h", "box\0delwin\0endwin\0getcurx\0getcury\0initscr\0\ ! 177: mvcur\0mvwprintw\0mvwscanw\0newwin\0overlay\0overwrite\0\ ! 178: scroll\0subwin\0touchwin\0waddstr\0wclear\0wclrtobot\0wclrtoeol\0\ ! 179: waddch\0wdelch\0wdeleteln\0werase\0wgetch\0wgetstr\0winsch\0winsertln\0\ ! 180: wmove\0wprintw\0wrefresh\0wscanw\0wstandend\0wstandout\0", NONE }, ! 181: ! 182: { "fcntl.h", "creat\0fcntl\0open\0", NONE }, ! 183: ! 184: /* Maybe also "getgrent fgetgrent setgrent endgrent" */ ! 185: { "grp.h", "getgrgid\0getgrnam\0", NONE }, ! 186: ! 187: /*{ "limit.h", ... provided by gcc }, */ ! 188: ! 189: { "locale.h", "localeconv\0setlocale\0", NONE }, ! 190: ! 191: { "math.h", "acos\0asin\0atan\0atan2\0ceil\0cos\0cosh\0exp\0\ ! 192: fabs\0floor\0fmod\0frexp\0ldexp\0log10\0log\0modf\0pow\0sin\0sinh\0sqrt\0\ ! 193: tan\0tanh\0", "HUGE_VAL\0" }, ! 194: ! 195: { "pwd.h", "getpwnam\0getpwuid\0", NONE }, ! 196: ! 197: /* Left out siglongjmp sigsetjmp - these depend on sigjmp_buf. */ ! 198: { "setjmp.h", "longjmp\0setjmp\0", NONE }, ! 199: ! 200: /* Left out signal() - its prototype is too complex for us! ! 201: Also left out "sigaction sigaddset sigdelset sigemptyset ! 202: sigfillset sigismember sigpending sigprocmask sigsuspend" ! 203: because these need sigset_t or struct sigaction. ! 204: Most systems that provide them will also declare them. */ ! 205: { "signal.h", "kill\0raise\0", NONE }, ! 206: ! 207: { "stdio.h", "clearerr\0fclose\0feof\0ferror\0fflush\0fgetc\0fgetpos\0\ ! 208: fgets\0fopen\0fprintf\0fputc\0fputs\0fread\0freopen\0fscanf\0fseek\0\ ! 209: fsetpos\0ftell\0fwrite\0getc\0getchar\0gets\0pclose\0perror\0popen\0\ ! 210: printf\0putc\0putchar\0puts\0remove\0rename\0rewind\0scanf\0setbuf\0\ ! 211: setvbuf\0sprintf\0sscanf\0vprintf\0vsprintf\0vfprintf\0tmpfile\0\ ! 212: tmpnam\0ungetc\0", NONE }, ! 213: /* Should perhaps also handle NULL, EOF, ... ? */ ! 214: ! 215: /* "div ldiv", - ignored because these depend on div_t, ldiv_t ! 216: ignore these: "mblen mbstowcs mbstowc wcstombs wctomb" ! 217: Left out getgroups, because SunOS4 has incompatible BSD and SVR4 versions. ! 218: Should perhaps also add NULL */ ! 219: { "stdlib.h", "abort\0abs\0atexit\0atof\0atoi\0atol\0bsearch\0calloc\0\ ! 220: exit\0free\0getenv\0labs\0malloc\0putenv\0qsort\0rand\0realloc\0\ ! 221: srand\0strtod\0strtol\0strtoul\0system\0", NONE }, ! 222: ! 223: { "string.h", "memchr\0memcmp\0memcpy\0memmove\0memset\0\ ! 224: strcat\0strchr\0strcmp\0strcoll\0strcpy\0strcspn\0strerror\0\ ! 225: strlen\0strncat\0strncmp\0strncpy\0strpbrk\0strrchr\0strspn\0strstr\0\ ! 226: strtok\0strxfrm\0", NONE }, ! 227: /* Should perhaps also add NULL and size_t */ ! 228: ! 229: { "sys/stat.h", "chmod\0fstat\0mkdir\0mkfifo\0stat\0lstat\0umask\0", ! 230: "S_ISDIR\0S_ISBLK\0S_ISCHR\0S_ISFIFO\0S_ISREG\0S_ISLNK\0S_IFDIR\0\ ! 231: S_IFBLK\0S_IFCHR\0S_IFIFO\0S_IFREG\0S_IFLNK\0" }, ! 232: ! 233: { "sys/times.h", "times\0", NONE }, ! 234: /* "sys/types.h" add types (not in old g++-include) */ ! 235: ! 236: { "sys/utsname.h", "uname\0", NONE }, ! 237: ! 238: { "sys/wait.h", "wait\0waitpid\0", ! 239: "WEXITSTATUS\0WIFEXITED\0WIFSIGNALED\0WIFSTOPPED\0WSTOPSIG\0\ ! 240: WTERMSIG\0WNOHANG\0WNOTRACED\0" }, ! 241: ! 242: { "tar.h", NONE, NONE }, ! 243: ! 244: { "termios.h", "cfgetispeed\0cfgetospeed\0cfsetispeed\0cfsetospeed\0tcdrain\0tcflow\0tcflush\0tcgetattr\0tcsendbreak\0tcsetattr\0", NONE }, ! 245: ! 246: { "time.h", "asctime\0clock\0ctime\0difftime\0gmtime\0localtime\0mktime\0strftime\0time\0tzset\0", NONE }, ! 247: ! 248: { "unistd.h", "_exit\0access\0alarm\0chdir\0chown\0close\0ctermid\0cuserid\0\ ! 249: dup\0dup2\0execl\0execle\0execlp\0execv\0execve\0execvp\0fork\0fpathconf\0\ ! 250: getcwd\0getegid\0geteuid\0getgid\0getlogin\0getopt\0getpgrp\0getpid\0\ ! 251: getppid\0getuid\0isatty\0link\0lseek\0pathconf\0pause\0pipe\0read\0rmdir\0\ ! 252: setgid\0setpgid\0setsid\0setuid\0sleep\0sysconf\0tcgetpgrp\0tcsetpgrp\0\ ! 253: ttyname\0unlink\0write\0", NONE }, ! 254: ! 255: { 0, NONE, NONE } 1.1 root 256: }; 257: 258: enum special_file special_file_handling = no_special; 259: 260: /* The following are only used when handling sys/stat.h */ 261: /* They are set if the corresponding macro has been seen. */ 262: int seen_S_IFBLK = 0, seen_S_ISBLK = 0; 263: int seen_S_IFCHR = 0, seen_S_ISCHR = 0; 264: int seen_S_IFDIR = 0, seen_S_ISDIR = 0; 265: int seen_S_IFIFO = 0, seen_S_ISFIFO = 0; 266: int seen_S_IFLNK = 0, seen_S_ISLNK = 0; 267: int seen_S_IFREG = 0, seen_S_ISREG = 0; 268: 269: /* Wrapper around free, to avoid prototype clashes. */ 270: 271: void 272: xfree (ptr) 273: char *ptr; 274: { 275: free (ptr); 276: } 277: 278: /* Avoid error if config defines abort as fancy_abort. 279: It's not worth "really" implementing this because ordinary 280: compiler users never run fix-header. */ 281: 282: void 283: fancy_abort () 284: { 285: abort (); 286: } 287: 288: #define obstack_chunk_alloc xmalloc 289: #define obstack_chunk_free xfree 290: struct obstack scan_file_obstack; 291: 292: /* NOTE: If you edit this, also edit gen-protos.c !! */ 293: struct fn_decl * 1.1.1.3 ! root 294: lookup_std_proto (name, name_length) ! 295: const char *name; ! 296: int name_length; 1.1 root 297: { 1.1.1.3 ! root 298: int i = hashf (name, name_length, HASH_SIZE); 1.1 root 299: int i0 = i; 300: for (;;) 301: { 302: struct fn_decl *fn; 303: if (hash_tab[i] == 0) 304: return NULL; 305: fn = &std_protos[hash_tab[i]]; 1.1.1.3 ! root 306: if (strlen (fn->fname) == name_length ! 307: && strncmp (fn->fname, name, name_length) == 0) 1.1 root 308: return fn; 309: i = (i+1) % HASH_SIZE; 310: if (i == i0) 311: abort (); 312: } 313: } 314: 315: char *inc_filename; 316: int inc_filename_length; 317: char *progname = "fix-header"; 318: FILE *outf; 319: sstring line; 320: 321: int lbrac_line, rbrac_line; 322: 1.1.1.3 ! root 323: namelist required_functions_list; ! 324: int required_unseen_count = 0; 1.1 root 325: 1.1.1.2 root 326: void 1.1 root 327: write_lbrac () 328: { 329: 1.1.1.3 ! root 330: #if ADD_MISSING_EXTERN_C 1.1 root 331: if (missing_extern_C_count + required_unseen_count > 0) 332: fprintf (outf, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); 1.1.1.2 root 333: #endif 1.1 root 334: 335: if (partial_count) 336: { 337: fprintf (outf, "#ifndef _PARAMS\n"); 338: fprintf (outf, "#if defined(__STDC__) || defined(__cplusplus)\n"); 339: fprintf (outf, "#define _PARAMS(ARGS) ARGS\n"); 340: fprintf (outf, "#else\n"); 341: fprintf (outf, "#define _PARAMS(ARGS) ()\n"); 342: fprintf (outf, "#endif\n#endif /* _PARAMS */\n"); 343: } 344: } 345: 346: struct partial_proto 347: { 348: struct partial_proto *next; 349: char *fname; /* name of function */ 350: char *rtype; /* return type */ 351: struct fn_decl *fn; 352: int line_seen; 353: }; 354: 355: struct partial_proto *partial_proto_list = NULL; 356: 1.1.1.3 ! root 357: struct partial_proto required_dummy_proto, seen_dummy_proto; 1.1 root 358: #define REQUIRED(FN) ((FN)->partial == &required_dummy_proto) 359: #define SET_REQUIRED(FN) ((FN)->partial = &required_dummy_proto) 1.1.1.3 ! root 360: #define SET_SEEN(FN) ((FN)->partial = &seen_dummy_proto) ! 361: #define SEEN(FN) ((FN)->partial == &seen_dummy_proto) 1.1 root 362: 363: void 364: recognized_macro (fname) 365: char *fname; 366: { 367: /* The original include file defines fname as a macro. */ 1.1.1.3 ! root 368: struct fn_decl *fn = lookup_std_proto (fname, strlen (fname)); 1.1 root 369: 370: /* Since fname is a macro, don't require a prototype for it. */ 1.1.1.3 ! root 371: if (fn) 1.1 root 372: { 1.1.1.3 ! root 373: if (REQUIRED (fn)) ! 374: required_unseen_count--; ! 375: SET_SEEN (fn); 1.1 root 376: } 377: 378: switch (special_file_handling) 379: { 1.1.1.3 ! root 380: case errno_h: 1.1 root 381: if (strcmp (fname, "errno") == 0) missing_errno = 0; 382: break; 1.1.1.3 ! root 383: case sys_stat_h: 1.1 root 384: if (fname[0] == 'S' && fname[1] == '_') 385: { 386: if (strcmp (fname, "S_IFBLK") == 0) seen_S_IFBLK++; 387: else if (strcmp (fname, "S_ISBLK") == 0) seen_S_ISBLK++; 388: else if (strcmp (fname, "S_IFCHR") == 0) seen_S_IFCHR++; 389: else if (strcmp (fname, "S_ISCHR") == 0) seen_S_ISCHR++; 390: else if (strcmp (fname, "S_IFDIR") == 0) seen_S_IFDIR++; 391: else if (strcmp (fname, "S_ISDIR") == 0) seen_S_ISDIR++; 392: else if (strcmp (fname, "S_IFIFO") == 0) seen_S_IFIFO++; 393: else if (strcmp (fname, "S_ISFIFO") == 0) seen_S_ISFIFO++; 394: else if (strcmp (fname, "S_IFLNK") == 0) seen_S_IFLNK++; 395: else if (strcmp (fname, "S_ISLNK") == 0) seen_S_ISLNK++; 396: else if (strcmp (fname, "S_IFREG") == 0) seen_S_IFREG++; 397: else if (strcmp (fname, "S_ISREG") == 0) seen_S_ISREG++; 398: } 399: } 400: } 401: 402: void 1.1.1.3 ! root 403: recognized_extern (name, name_length, type, type_length) 1.1 root 404: char *name; 405: char *type; 1.1.1.3 ! root 406: int name_length, type_length; 1.1 root 407: { 408: switch (special_file_handling) 409: { 1.1.1.3 ! root 410: case errno_h: ! 411: if (strncmp (name, "errno", name_length) == 0) missing_errno = 0; 1.1 root 412: break; 413: } 414: } 415: 416: /* Called by scan_decls if it saw a function definition for a function 417: named FNAME, with return type RTYPE, and argument list ARGS, 418: in source file FILE_SEEN on line LINE_SEEN. 419: KIND is 'I' for an inline function; 420: 'F' if a normal function declaration preceded by 'extern "C"' 421: (or nested inside 'extern "C"' braces); or 422: 'f' for other function declarations. */ 423: 424: void 1.1.1.3 ! root 425: recognized_function (fname, fname_length, ! 426: kind, rtype, rtype_length, ! 427: have_arg_list, file_seen, line_seen) 1.1 root 428: char *fname; 1.1.1.3 ! root 429: int fname_length; 1.1 root 430: int kind; /* One of 'f' 'F' or 'I' */ 431: char *rtype; 1.1.1.3 ! root 432: int rtype_length; ! 433: int have_arg_list; 1.1 root 434: char *file_seen; 435: int line_seen; 436: { 437: struct partial_proto *partial; 438: int i; 439: struct fn_decl *fn; 1.1.1.3 ! root 440: #if ADD_MISSING_EXTERN_C 1.1 root 441: if (kind == 'f') 442: missing_extern_C_count++; 1.1.1.2 root 443: #endif 1.1 root 444: 1.1.1.3 ! root 445: fn = lookup_std_proto (fname, fname_length); 1.1 root 446: 447: /* Remove the function from the list of required function. */ 1.1.1.3 ! root 448: if (fn) 1.1 root 449: { 1.1.1.3 ! root 450: if (REQUIRED (fn)) ! 451: required_unseen_count--; ! 452: SET_SEEN (fn); 1.1 root 453: } 454: 455: /* If we have a full prototype, we're done. */ 1.1.1.3 ! root 456: if (have_arg_list) 1.1 root 457: return; 458: 459: if (kind == 'I') /* don't edit inline function */ 460: return; 461: 462: /* If the partial prototype was included from some other file, 463: we don't need to patch it up (in this run). */ 464: i = strlen (file_seen); 465: if (i < inc_filename_length 466: || strcmp (inc_filename, file_seen + (i - inc_filename_length)) != 0) 467: return; 468: 469: if (fn == NULL) 470: return; 471: if (fn->params[0] == '\0' || strcmp (fn->params, "void") == 0) 472: return; 473: 474: /* We only have a partial function declaration, 475: so remember that we have to add a complete prototype. */ 476: partial_count++; 477: partial = (struct partial_proto*) 478: obstack_alloc (&scan_file_obstack, sizeof (struct partial_proto)); 1.1.1.3 ! root 479: partial->fname = obstack_alloc (&scan_file_obstack, fname_length + 1); ! 480: bcopy (fname, partial->fname, fname_length); ! 481: partial->fname[fname_length] = 0; ! 482: partial->rtype = obstack_alloc (&scan_file_obstack, rtype_length + 1); ! 483: sprintf (partial->rtype, "%.*s", rtype_length, rtype); 1.1 root 484: partial->line_seen = line_seen; 485: partial->fn = fn; 486: fn->partial = partial; 487: partial->next = partial_proto_list; 488: partial_proto_list = partial; 489: if (verbose) 490: { 491: fprintf (stderr, "(%s: %s non-prototype function declaration.)\n", 1.1.1.3 ! root 492: inc_filename, partial->fname); 1.1 root 493: } 494: } 495: 1.1.1.3 ! root 496: /* For any name in NAMES that is defined as a macro, ! 497: call recognized_macro on it. */ ! 498: 1.1 root 499: void 1.1.1.3 ! root 500: check_macro_names (pfile, names) ! 501: struct parse_file *pfile; ! 502: namelist names; 1.1 root 503: { 1.1.1.3 ! root 504: while (*names) ! 505: { ! 506: if (cpp_lookup (pfile, names, -1, -1)) ! 507: recognized_macro (names); ! 508: names += strlen (names) + 1; ! 509: } ! 510: } ! 511: ! 512: void ! 513: read_scan_file (in_fname, argc, argv) ! 514: char *in_fname; ! 515: int argc; ! 516: char **argv; ! 517: { ! 518: cpp_reader scan_in; ! 519: cpp_options scan_options; ! 520: struct fn_decl *fn; ! 521: int i; ! 522: 1.1 root 523: obstack_init (&scan_file_obstack); 524: 1.1.1.3 ! root 525: init_parse_file (&scan_in); ! 526: scan_in.data = &scan_options; ! 527: init_parse_options (&scan_options); ! 528: i = cpp_handle_options (&scan_in, argc, argv); ! 529: if (i < argc) ! 530: fatal ("Invalid option `%s'", argv[i]); ! 531: push_parse_file (&scan_in, in_fname); ! 532: CPP_OPTIONS (&scan_in)->no_line_commands = 1; ! 533: ! 534: scan_decls (&scan_in, argc, argv); ! 535: check_macro_names (&scan_in, include_entry->required); ! 536: check_macro_names (&scan_in, include_entry->extra); ! 537: ! 538: if (verbose && (scan_in.errors + warnings) > 0) ! 539: fprintf (stderr, "(%s: %d errors and %d warnings from cpp)\n", ! 540: inc_filename, scan_in.errors, warnings); ! 541: if (scan_in.errors) ! 542: exit (0); ! 543: ! 544: /* Traditionally, getc and putc are defined in terms of _filbuf and _flsbuf. ! 545: If so, those functions are also required. */ ! 546: if (special_file_handling == stdio_h ! 547: && (fn = lookup_std_proto ("_filbuf", 7)) != NULL) ! 548: { ! 549: static char getchar_call[] = "getchar();"; ! 550: cpp_buffer *buf = ! 551: cpp_push_buffer (&scan_in, getchar_call, sizeof(getchar_call) - 1); ! 552: int old_written = CPP_WRITTEN (&scan_in); ! 553: int seen_filbuf = 0; ! 554: ! 555: /* Scan the macro expansion of "getchar();". */ ! 556: for (;;) ! 557: { ! 558: enum cpp_token token = cpp_get_token (&scan_in); ! 559: int length = CPP_WRITTEN (&scan_in) - old_written; ! 560: CPP_SET_WRITTEN (&scan_in, old_written); ! 561: if (token == CPP_EOF) /* Should not happen ... */ ! 562: break; ! 563: if (token == CPP_POP && CPP_BUFFER (&scan_in) == buf) ! 564: { ! 565: cpp_pop_buffer (&scan_in); ! 566: break; ! 567: } ! 568: if (token == CPP_NAME && length == 7 ! 569: && strcmp ("_filbuf", scan_in.token_buffer + old_written) == 0) ! 570: seen_filbuf++; ! 571: } ! 572: if (seen_filbuf) ! 573: { ! 574: int need_filbuf = !SEEN (fn) && !REQUIRED (fn); ! 575: struct fn_decl *flsbuf_fn = lookup_std_proto ("_flsbuf", 7); ! 576: int need_flsbuf ! 577: = flsbuf_fn && !SEEN (flsbuf_fn) && !REQUIRED (flsbuf_fn); ! 578: ! 579: /* Append "_filbuf" and/or "_flsbuf" to end of ! 580: required_functions_list. */ ! 581: if (need_filbuf + need_flsbuf) ! 582: { ! 583: int old_len = namelist_end (required_functions_list) ! 584: - required_functions_list; ! 585: char *new_list = (char*) xmalloc (old_len + 20); ! 586: bcopy (required_functions_list, new_list, old_len); ! 587: if (need_filbuf) ! 588: { ! 589: strcpy (new_list + old_len, "_filbuf"); ! 590: old_len += 8; ! 591: SET_REQUIRED (fn); ! 592: } ! 593: if (need_flsbuf) ! 594: { ! 595: strcpy (new_list + old_len, "_flsbuf"); ! 596: old_len += 8; ! 597: SET_REQUIRED (flsbuf_fn); ! 598: } ! 599: new_list[old_len] = '\0'; ! 600: required_functions_list = (namelist)new_list; ! 601: required_unseen_count += need_filbuf + need_flsbuf; ! 602: } ! 603: } ! 604: } 1.1 root 605: 1.1.1.2 root 606: if (required_unseen_count + partial_count + missing_errno 1.1.1.3 ! root 607: #if ADD_MISSING_EXTERN_C 1.1.1.2 root 608: + missing_extern_C_count 609: #endif 610: == 0) 1.1 root 611: { 612: if (verbose) 613: fprintf (stderr, "%s: OK, nothing needs to be done.\n", inc_filename); 614: exit (0); 615: } 616: if (!verbose) 617: fprintf (stderr, "%s: fixing %s\n", progname, inc_filename); 618: else 619: { 620: if (required_unseen_count) 621: fprintf (stderr, "%s: %d missing function declarations.\n", 622: inc_filename, required_unseen_count); 623: if (partial_count) 624: fprintf (stderr, "%s: %d non-prototype function declarations.\n", 625: inc_filename, partial_count); 1.1.1.3 ! root 626: #if ADD_MISSING_EXTERN_C 1.1 root 627: if (missing_extern_C_count) 628: fprintf (stderr, 629: "%s: %d declarations not protected by extern \"C\".\n", 630: inc_filename, missing_extern_C_count); 1.1.1.2 root 631: #endif 1.1 root 632: } 633: } 634: 1.1.1.2 root 635: void 1.1 root 636: write_rbrac () 637: { 638: struct fn_decl *fn; 1.1.1.3 ! root 639: const char *cptr; 1.1 root 640: 641: if (required_unseen_count) 1.1.1.2 root 642: { 643: fprintf (outf, 644: "#if defined(__cplusplus) || defined(__USE_FIXED_PROTOTYPES__)\n"); 645: #ifdef NO_IMPLICIT_EXTERN_C 646: fprintf (outf, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); 647: #endif 648: } 1.1 root 649: 650: /* Now we print out prototypes for those functions that we haven't seen. */ 1.1.1.3 ! root 651: for (cptr = required_functions_list; *cptr!= '\0'; ) 1.1 root 652: { 653: int macro_protect = 0; 1.1.1.3 ! root 654: int name_len = strlen (cptr); 1.1 root 655: 1.1.1.3 ! root 656: fn = lookup_std_proto (cptr, name_len); ! 657: cptr+= name_len + 1; 1.1 root 658: if (fn == NULL || !REQUIRED (fn)) 659: continue; 660: 661: /* In the case of memmove, protect in case the application 662: defines it as a macro before including the header. */ 663: if (!strcmp (fn->fname, "memmove") 664: || !strcmp (fn->fname, "vprintf") 665: || !strcmp (fn->fname, "vfprintf") 666: || !strcmp (fn->fname, "vsprintf") 667: || !strcmp (fn->fname, "rewinddir")) 668: macro_protect = 1; 669: 670: if (macro_protect) 671: fprintf (outf, "#ifndef %s\n", fn->fname); 672: fprintf (outf, "extern %s %s (%s);\n", 673: fn->rtype, fn->fname, fn->params); 674: if (macro_protect) 675: fprintf (outf, "#endif\n"); 676: } 677: if (required_unseen_count) 1.1.1.2 root 678: { 679: #ifdef NO_IMPLICIT_EXTERN_C 680: fprintf (outf, "#ifdef __cplusplus\n}\n#endif\n"); 681: #endif 682: fprintf (outf, 683: "#endif /* defined(__cplusplus) || defined(__USE_FIXED_PROTOTYPES__*/\n"); 684: } 1.1 root 685: 686: switch (special_file_handling) 687: { 1.1.1.3 ! root 688: case errno_h: 1.1 root 689: if (missing_errno) 690: fprintf (outf, "extern int errno;\n"); 691: break; 1.1.1.3 ! root 692: case sys_stat_h: 1.1 root 693: if (!seen_S_ISBLK && seen_S_IFBLK) 694: fprintf (outf, 695: "#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)\n"); 696: if (!seen_S_ISCHR && seen_S_IFCHR) 697: fprintf (outf, 698: "#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)\n"); 699: if (!seen_S_ISDIR && seen_S_IFDIR) 700: fprintf (outf, 701: "#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)\n"); 702: if (!seen_S_ISFIFO && seen_S_IFIFO) 703: fprintf (outf, 704: "#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)\n"); 705: if (!seen_S_ISLNK && seen_S_IFLNK) 706: fprintf (outf, 707: "#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)\n"); 708: if (!seen_S_ISREG && seen_S_IFREG) 709: fprintf (outf, 710: "#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)\n"); 711: break; 712: } 713: 714: 1.1.1.3 ! root 715: #if ADD_MISSING_EXTERN_C 1.1 root 716: if (missing_extern_C_count + required_unseen_count > 0) 717: fprintf (outf, "#ifdef __cplusplus\n}\n#endif\n"); 1.1.1.2 root 718: #endif 1.1 root 719: } 720: 721: char * 1.1.1.2 root 722: xstrdup (str) 1.1 root 723: char *str; 724: { 725: char *copy = (char *) xmalloc (strlen (str) + 1); 726: strcpy (copy, str); 727: return copy; 728: } 729: 730: /* Returns 1 iff the file is properly protected from multiple inclusion: 731: #ifndef PROTECT_NAME 732: #define PROTECT_NAME 733: #endif 734: 735: */ 736: 737: #define INF_GET() (inf_ptr < inf_limit ? *(unsigned char*)inf_ptr++ : EOF) 738: #define INF_UNGET(c) ((c)!=EOF && inf_ptr--) 739: 740: int 741: inf_skip_spaces (c) 742: int c; 743: { 744: for (;;) 745: { 746: if (c == ' ' || c == '\t') 747: c = INF_GET (); 748: else if (c == '/') 749: { 750: c = INF_GET (); 751: if (c != '*') 752: { 753: INF_UNGET (c); 754: return '/'; 755: } 756: c = INF_GET (); 757: for (;;) 758: { 759: if (c == EOF) 760: return EOF; 761: else if (c != '*') 762: { 763: if (c == '\n') 764: source_lineno++, lineno++; 765: c = INF_GET (); 766: } 767: else if ((c = INF_GET ()) == '/') 768: return INF_GET (); 769: } 770: } 771: else 772: break; 773: } 774: return c; 775: } 776: 777: /* Read into STR from inf_buffer upto DELIM. */ 778: 779: int 780: inf_read_upto (str, delim) 781: sstring *str; 782: int delim; 783: { 784: int ch; 785: for (;;) 786: { 787: ch = INF_GET (); 788: if (ch == EOF || ch == delim) 789: break; 790: SSTRING_PUT (str, ch); 791: } 792: MAKE_SSTRING_SPACE (str, 1); 793: *str->ptr = 0; 794: return ch; 795: } 796: 797: int 798: inf_scan_ident (s, c) 799: register sstring *s; 800: int c; 801: { 802: s->ptr = s->base; 803: if (isalpha (c) || c == '_') 804: { 805: for (;;) 806: { 807: SSTRING_PUT (s, c); 808: c = INF_GET (); 809: if (c == EOF || !(isalnum (c) || c == '_')) 810: break; 811: } 812: } 813: MAKE_SSTRING_SPACE (s, 1); 814: *s->ptr = 0; 815: return c; 816: } 817: 818: /* Returns 1 if the file is correctly protected against multiple 819: inclusion, setting *ifndef_line to the line number of the initial #ifndef 820: and setting *endif_line to the final #endif. 821: Otherwise return 0. */ 822: 823: int 824: check_protection (ifndef_line, endif_line) 825: int *ifndef_line, *endif_line; 826: { 827: int c; 828: int if_nesting = 1; /* Level of nesting of #if's */ 829: char *protect_name = NULL; /* Identifier following initial #ifndef */ 830: int define_seen = 0; 831: 832: /* Skip initial white space (including comments). */ 833: for (;; lineno++) 834: { 835: c = inf_skip_spaces (' '); 836: if (c == EOF) 837: return 0; 838: if (c != '\n') 839: break; 840: } 841: if (c != '#') 842: return 0; 843: c = inf_scan_ident (&buf, inf_skip_spaces (' ')); 844: if (SSTRING_LENGTH (&buf) == 0 || strcmp (buf.base, "ifndef") != 0) 845: return 0; 846: 847: /* So far so good: We've seen an initial #ifndef. */ 848: *ifndef_line = lineno; 849: c = inf_scan_ident (&buf, inf_skip_spaces (c)); 850: if (SSTRING_LENGTH (&buf) == 0 || c == EOF) 851: return 0; 1.1.1.2 root 852: protect_name = xstrdup (buf.base); 1.1 root 853: 854: INF_UNGET (c); 855: c = inf_read_upto (&buf, '\n'); 856: if (c == EOF) 857: return 0; 858: lineno++; 859: 860: for (;;) 861: { 862: c = inf_skip_spaces (' '); 863: if (c == EOF) 864: return 0; 865: if (c == '\n') 866: { 867: lineno++; 868: continue; 869: } 870: if (c != '#') 871: goto skip_to_eol; 872: c = inf_scan_ident (&buf, inf_skip_spaces (' ')); 873: if (SSTRING_LENGTH (&buf) == 0) 874: ; 875: else if (!strcmp (buf.base, "ifndef") 876: || !strcmp (buf.base, "ifdef") || !strcmp (buf.base, "if")) 877: { 878: if_nesting++; 879: } 880: else if (!strcmp (buf.base, "endif")) 881: { 882: if_nesting--; 883: if (if_nesting == 0) 884: break; 885: } 886: else if (!strcmp (buf.base, "else")) 887: { 888: if (if_nesting == 1) 889: return 0; 890: } 891: else if (!strcmp (buf.base, "define")) 892: { 893: if (if_nesting != 1) 894: goto skip_to_eol; 895: c = inf_skip_spaces (c); 896: c = inf_scan_ident (&buf, c); 897: if (buf.base[0] > 0 && strcmp (buf.base, protect_name) == 0) 898: define_seen = 1; 899: } 900: skip_to_eol: 901: for (;;) 902: { 903: if (c == '\n' || c == EOF) 904: break; 905: c = INF_GET (); 906: } 907: if (c == EOF) 908: return 0; 909: lineno++; 910: } 911: 912: if (!define_seen) 913: return 0; 914: *endif_line = lineno; 915: /* Skip final white space (including comments). */ 916: for (;;) 917: { 918: c = inf_skip_spaces (' '); 919: if (c == EOF) 920: break; 921: if (c != '\n') 922: return 0; 923: } 924: 925: return 1; 926: } 927: 928: int 929: main (argc, argv) 930: int argc; 931: char **argv; 932: { 933: int inf_fd; 934: struct stat sbuf; 935: int c; 936: int i, done; 1.1.1.3 ! root 937: const char *cptr, **pptr; 1.1 root 938: int ifndef_line; 939: int endif_line; 940: long to_read; 941: long int inf_size; 942: 943: if (argv[0] && argv[0][0]) 944: { 945: register char *p; 946: 947: progname = 0; 948: for (p = argv[0]; *p; p++) 949: if (*p == '/') 950: progname = p; 951: progname = progname ? progname+1 : argv[0]; 952: } 953: 954: if (argc < 4) 955: { 1.1.1.3 ! root 956: fprintf (stderr, "%s: Usage: foo.h infile.h outfile.h options\n", 1.1 root 957: progname); 958: exit (-1); 959: } 960: 961: inc_filename = argv[1]; 962: inc_filename_length = strlen (inc_filename); 963: 1.1.1.3 ! root 964: #ifdef FIXPROTO_IGNORE_LIST ! 965: for (i = 0; files_to_ignore[i] != NULL; i++) 1.1 root 966: { 1.1.1.3 ! root 967: char *ignore_name = files_to_ignore[i]; ! 968: int ignore_len = strlen (ignore_name); ! 969: if (strncmp (inc_filename, ignore_name, ignore_len) == 0) 1.1 root 970: { 1.1.1.3 ! root 971: if (ignore_name[ignore_len-1] == '/' ! 972: || inc_filename[ignore_len] == '\0') 1.1 root 973: { 1.1.1.3 ! root 974: if (verbose) ! 975: fprintf (stderr, "%s: ignoring %s\n", progname, inc_filename); ! 976: exit (0); 1.1 root 977: } 978: } 1.1.1.3 ! root 979: ! 980: } ! 981: #endif ! 982: ! 983: if (strcmp (inc_filename, "sys/stat.h") == 0) ! 984: special_file_handling = sys_stat_h; ! 985: else if (strcmp (inc_filename, "errno.h") == 0) ! 986: special_file_handling = errno_h, missing_errno = 1; ! 987: else if (strcmp (inc_filename, "stdio.h") == 0) ! 988: special_file_handling = stdio_h; ! 989: include_entry = std_include_table; ! 990: while (include_entry->name != NULL ! 991: && strcmp (inc_filename, include_entry->name) != 0) ! 992: include_entry++; ! 993: ! 994: required_functions_list = include_entry->required; ! 995: ! 996: /* Count and mark the prototypes required for this include file. */ ! 997: for (cptr = required_functions_list; *cptr!= '\0'; ) ! 998: { ! 999: int name_len = strlen (cptr); ! 1000: struct fn_decl *fn = lookup_std_proto (cptr, name_len); ! 1001: required_unseen_count++; ! 1002: if (fn == NULL) ! 1003: fprintf (stderr, "Internal error: No prototype for %s\n", cptr); ! 1004: else ! 1005: SET_REQUIRED (fn); ! 1006: cptr += name_len + 1; 1.1 root 1007: } 1008: 1.1.1.3 ! root 1009: read_scan_file (argv[2], argc - 4, argv + 4); 1.1 root 1010: 1011: inf_fd = open (argv[2], O_RDONLY, 0666); 1012: if (inf_fd < 0) 1013: { 1014: fprintf (stderr, "%s: Cannot open '%s' for reading -", 1015: progname, argv[2]); 1016: perror (NULL); 1017: exit (-1); 1018: } 1019: if (fstat (inf_fd, &sbuf) < 0) 1020: { 1021: fprintf (stderr, "%s: Cannot get size of '%s' -", progname, argv[2]); 1022: perror (NULL); 1023: exit (-1); 1024: } 1025: inf_size = sbuf.st_size; 1026: inf_buffer = (char*) xmalloc (inf_size + 2); 1027: inf_buffer[inf_size] = '\n'; 1028: inf_buffer[inf_size + 1] = '\0'; 1029: inf_limit = inf_buffer + inf_size; 1030: inf_ptr = inf_buffer; 1031: 1032: to_read = inf_size; 1033: while (to_read > 0) 1034: { 1035: long i = read (inf_fd, inf_buffer + inf_size - to_read, to_read); 1036: if (i < 0) 1037: { 1038: fprintf (stderr, "%s: Failed to read '%s' -", progname, argv[2]); 1039: perror (NULL); 1040: exit (-1); 1041: } 1042: if (i == 0) 1043: { 1044: inf_size -= to_read; 1045: break; 1046: } 1047: to_read -= i; 1048: } 1049: 1050: close (inf_fd); 1051: 1052: /* If file doesn't end with '\n', add one. */ 1053: if (inf_limit > inf_buffer && inf_limit[-1] != '\n') 1054: inf_limit++; 1055: 1056: unlink (argv[3]); 1057: outf = fopen (argv[3], "w"); 1058: if (outf == NULL) 1059: { 1060: fprintf (stderr, "%s: Cannot open '%s' for writing -", 1061: progname, argv[3]); 1062: perror (NULL); 1063: exit (-1); 1064: } 1065: 1066: lineno = 1; 1067: 1068: if (check_protection (&ifndef_line, &endif_line)) 1069: { 1070: lbrac_line = ifndef_line+1; 1071: rbrac_line = endif_line; 1072: } 1073: else 1074: { 1075: lbrac_line = 1; 1076: rbrac_line = -1; 1077: } 1078: 1079: /* Reset input file. */ 1080: inf_ptr = inf_buffer; 1081: lineno = 1; 1082: 1083: for (;;) 1084: { 1085: if (lineno == lbrac_line) 1086: write_lbrac (); 1087: if (lineno == rbrac_line) 1088: write_rbrac (); 1089: for (;;) 1090: { 1091: struct fn_decl *fn; 1092: c = INF_GET (); 1093: if (c == EOF) 1094: break; 1095: if (isalpha (c) || c == '_') 1096: { 1097: c = inf_scan_ident (&buf, c); 1098: INF_UNGET (c); 1099: fputs (buf.base, outf); 1.1.1.3 ! root 1100: fn = lookup_std_proto (buf.base, strlen (buf.base)); 1.1 root 1101: /* We only want to edit the declaration matching the one 1102: seen by scan-decls, as there can be multiple 1103: declarations, selected by #ifdef __STDC__ or whatever. */ 1104: if (fn && fn->partial && fn->partial->line_seen == lineno) 1105: { 1106: c = inf_skip_spaces (' '); 1107: if (c == EOF) 1108: break; 1109: if (c == '(') 1110: { 1111: c = inf_skip_spaces (' '); 1112: if (c == ')') 1113: { 1114: fprintf (outf, " _PARAMS((%s))", fn->params); 1115: } 1116: else 1117: { 1118: putc ('(', outf); 1119: INF_UNGET (c); 1120: } 1121: } 1122: else 1123: fprintf (outf, " %c", c); 1124: } 1125: } 1126: else 1127: { 1128: putc (c, outf); 1129: if (c == '\n') 1130: break; 1131: } 1132: } 1133: if (c == EOF) 1134: break; 1135: lineno++; 1136: } 1137: if (rbrac_line < 0) 1138: write_rbrac (); 1139: 1140: fclose (outf); 1141: 1142: return 0; 1143: } 1.1.1.3 ! root 1144: ! 1145: /* Stub error functions. These replace cpperror.c, ! 1146: because we want to suppress error messages. */ ! 1147: ! 1148: void ! 1149: cpp_file_line_for_message (pfile, filename, line, column) ! 1150: cpp_reader *pfile; ! 1151: char *filename; ! 1152: int line, column; ! 1153: { ! 1154: if (!verbose) ! 1155: return; ! 1156: if (column > 0) ! 1157: fprintf (stderr, "%s:%d:%d: ", filename, line, column); ! 1158: else ! 1159: fprintf (stderr, "%s:%d: ", filename, line); ! 1160: } ! 1161: ! 1162: void ! 1163: cpp_print_containing_files (pfile) ! 1164: cpp_reader *pfile; ! 1165: { ! 1166: } ! 1167: ! 1168: /* IS_ERROR is 1 for error, 0 for warning */ ! 1169: void cpp_message (pfile, is_error, msg, arg1, arg2, arg3) ! 1170: int is_error; ! 1171: cpp_reader *pfile; ! 1172: char *msg; ! 1173: char *arg1, *arg2, *arg3; ! 1174: { ! 1175: if (is_error) ! 1176: pfile->errors++; ! 1177: if (!verbose) ! 1178: return; ! 1179: if (!is_error) ! 1180: fprintf (stderr, "warning: "); ! 1181: fprintf (stderr, msg, arg1, arg2, arg3); ! 1182: fprintf (stderr, "\n"); ! 1183: } ! 1184: ! 1185: void ! 1186: fatal (str, arg) ! 1187: char *str, *arg; ! 1188: { ! 1189: fprintf (stderr, "%s: %s: ", progname, inc_filename); ! 1190: fprintf (stderr, str, arg); ! 1191: fprintf (stderr, "\n"); ! 1192: exit (FATAL_EXIT_CODE); ! 1193: } ! 1194: ! 1195: void ! 1196: cpp_pfatal_with_name (pfile, name) ! 1197: cpp_reader *pfile; ! 1198: char *name; ! 1199: { ! 1200: cpp_perror_with_name (pfile, name); ! 1201: exit (FATAL_EXIT_CODE); ! 1202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.