00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 #include "hconfig.h"
00079 #include "system.h"
00080 #include "obstack.h"
00081 #include "scan.h"
00082 #include "cpplib.h"
00083
00084 static void v_fatal PARAMS ((const char *, va_list)) ATTRIBUTE_PRINTF (1,0) ATTRIBUTE_NORETURN;
00085 static void fatal PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
00086
00087 sstring buf;
00088
00089 int verbose = 0;
00090 int partial_count = 0;
00091 int warnings = 0;
00092
00093
00094
00095
00096
00097 #if ADD_MISSING_EXTERN_C
00098 int missing_extern_C_count = 0;
00099 #endif
00100
00101 #ifndef SGI_MONGOOSE
00102
00103 #include "xsys-protos.h"
00104 #endif
00105
00106 #ifdef FIXPROTO_IGNORE_LIST
00107
00108
00109
00110
00111
00112
00113
00114 static const char *const files_to_ignore[] = {
00115 "X11/",
00116 FIXPROTO_IGNORE_LIST
00117 0
00118 };
00119 #endif
00120
00121 char *inf_buffer;
00122 char *inf_limit;
00123 char *inf_ptr;
00124 static const char *cur_file;
00125
00126
00127
00128 enum special_file
00129 {
00130 no_special,
00131 #ifdef errno_h
00132 #undef errno_h
00133 #endif
00134 errno_h,
00135 #ifdef stdio_h
00136 #undef stdio_h
00137 #endif
00138 stdio_h,
00139 #ifdef stdlib_h
00140 #undef stdlib_h
00141 #endif
00142 stdlib_h,
00143 #ifdef sys_stat_h
00144 #undef sys_stat_h
00145 #endif
00146 sys_stat_h
00147 };
00148
00149
00150
00151
00152 typedef const char *namelist;
00153
00154
00155 typedef int symbol_flags;
00156
00157
00158 #define ANSI_SYMBOL 1
00159
00160
00161
00162
00163
00164
00165
00166
00167 #if ADD_MISSING_POSIX
00168
00169 #define POSIX1_SYMBOL 2
00170 #define POSIX2_SYMBOL 4
00171 #else
00172 #define POSIX1_SYMBOL 0
00173 #define POSIX2_SYMBOL 0
00174 #endif
00175
00176 #if ADD_MISSING_XOPEN
00177
00178 #define XOPEN_SYMBOL 8
00179
00180 #define XOPEN_EXTENDED_SYMBOL 16
00181 #else
00182 #define XOPEN_SYMBOL 0
00183 #define XOPEN_EXTENDED_SYMBOL 0
00184 #endif
00185
00186
00187 #define MACRO_SYMBOL 512
00188
00189 struct symbol_list {
00190 symbol_flags flags;
00191 namelist names;
00192 };
00193
00194 #define SYMBOL_TABLE_SIZE 10
00195 struct symbol_list symbol_table[SYMBOL_TABLE_SIZE];
00196 int cur_symbol_table_size;
00197
00198 static void add_symbols PARAMS ((symbol_flags, namelist));
00199 static struct fn_decl *lookup_std_proto PARAMS ((const char *, int));
00200 static void write_lbrac PARAMS ((void));
00201 static void recognized_macro PARAMS ((const char *));
00202 static void check_macro_names PARAMS ((cpp_reader *, namelist));
00203 static void read_scan_file PARAMS ((char *, int, char **));
00204 static void write_rbrac PARAMS ((void));
00205 static int inf_skip_spaces PARAMS ((int));
00206 static int inf_read_upto PARAMS ((sstring *, int));
00207 static int inf_scan_ident PARAMS ((sstring *, int));
00208 static int check_protection PARAMS ((int *, int *));
00209 static void cb_file_change PARAMS ((cpp_reader *, const struct line_map *));
00210
00211 static void
00212 add_symbols (flags, names)
00213 symbol_flags flags;
00214 namelist names;
00215 {
00216 symbol_table[cur_symbol_table_size].flags = flags;
00217 symbol_table[cur_symbol_table_size].names = names;
00218 cur_symbol_table_size++;
00219 if (cur_symbol_table_size >= SYMBOL_TABLE_SIZE)
00220 fatal ("too many calls to add_symbols");
00221 symbol_table[cur_symbol_table_size].names = NULL;
00222 }
00223
00224 struct std_include_entry {
00225 const char *const name;
00226 const symbol_flags flags;
00227 const namelist names;
00228 };
00229
00230 const char NONE[] = "";
00231
00232
00233 const char CONTINUED[] = "";
00234
00235 const struct std_include_entry *include_entry;
00236
00237 const struct std_include_entry std_include_table [] = {
00238 { "ctype.h", ANSI_SYMBOL,
00239 "isalnum\0isalpha\0iscntrl\0isdigit\0isgraph\0islower\0\
00240 isprint\0ispunct\0isspace\0isupper\0isxdigit\0tolower\0toupper\0" },
00241
00242 { "dirent.h", POSIX1_SYMBOL, "closedir\0opendir\0readdir\0rewinddir\0"},
00243
00244 { "errno.h", ANSI_SYMBOL|MACRO_SYMBOL, "errno\0" },
00245
00246
00247 { "curses.h", ANSI_SYMBOL, "box\0delwin\0endwin\0getcurx\0getcury\0initscr\0\
00248 mvcur\0mvwprintw\0mvwscanw\0newwin\0overlay\0overwrite\0\
00249 scroll\0subwin\0touchwin\0waddstr\0wclear\0wclrtobot\0wclrtoeol\0\
00250 waddch\0wdelch\0wdeleteln\0werase\0wgetch\0wgetstr\0winsch\0winsertln\0\
00251 wmove\0wprintw\0wrefresh\0wscanw\0wstandend\0wstandout\0" },
00252
00253 { "fcntl.h", POSIX1_SYMBOL, "creat\0fcntl\0open\0" },
00254
00255
00256 { "grp.h", POSIX1_SYMBOL, "getgrgid\0getgrnam\0" },
00257
00258
00259
00260 { "locale.h", ANSI_SYMBOL, "localeconv\0setlocale\0" },
00261
00262 { "math.h", ANSI_SYMBOL,
00263 "acos\0asin\0atan\0atan2\0ceil\0cos\0cosh\0exp\0\
00264 fabs\0floor\0fmod\0frexp\0ldexp\0log10\0log\0modf\0pow\0sin\0sinh\0sqrt\0\
00265 tan\0tanh\0" },
00266
00267 { CONTINUED, ANSI_SYMBOL|MACRO_SYMBOL, "HUGE_VAL\0" },
00268
00269 { "pwd.h", POSIX1_SYMBOL, "getpwnam\0getpwuid\0" },
00270
00271
00272 { "setjmp.h", ANSI_SYMBOL, "longjmp\0setjmp\0" },
00273
00274
00275
00276
00277
00278
00279 { "signal.h", ANSI_SYMBOL, "kill\0raise\0" },
00280
00281 { "stdio.h", ANSI_SYMBOL,
00282 "clearerr\0fclose\0feof\0ferror\0fflush\0fgetc\0fgetpos\0\
00283 fgets\0fopen\0fprintf\0fputc\0fputs\0fread\0freopen\0fscanf\0fseek\0\
00284 fsetpos\0ftell\0fwrite\0getc\0getchar\0gets\0perror\0\
00285 printf\0putc\0putchar\0puts\0remove\0rename\0rewind\0scanf\0setbuf\0\
00286 setvbuf\0sprintf\0sscanf\0vprintf\0vsprintf\0vfprintf\0tmpfile\0\
00287 tmpnam\0ungetc\0" },
00288 { CONTINUED, POSIX1_SYMBOL, "fdopen\0fileno\0" },
00289 { CONTINUED, POSIX2_SYMBOL, "pclose\0popen\0" },
00290
00291
00292
00293
00294
00295
00296 { "stdlib.h", ANSI_SYMBOL,
00297 "abort\0abs\0atexit\0atof\0atoi\0atol\0bsearch\0calloc\0\
00298 exit\0free\0getenv\0labs\0malloc\0putenv\0qsort\0rand\0realloc\0\
00299 srand\0strtod\0strtol\0strtoul\0system\0" },
00300 { CONTINUED, ANSI_SYMBOL|MACRO_SYMBOL, "EXIT_FAILURE\0EXIT_SUCCESS\0" },
00301
00302 { "string.h", ANSI_SYMBOL, "memchr\0memcmp\0memcpy\0memmove\0memset\0\
00303 strcat\0strchr\0strcmp\0strcoll\0strcpy\0strcspn\0strerror\0\
00304 strlen\0strncat\0strncmp\0strncpy\0strpbrk\0strrchr\0strspn\0strstr\0\
00305 strtok\0strxfrm\0" },
00306
00307
00308 { "strings.h", XOPEN_EXTENDED_SYMBOL,
00309 "bcmp\0bcopy\0bzero\0ffs\0index\0rindex\0strcasecmp\0strncasecmp\0" },
00310
00311 { "strops.h", XOPEN_EXTENDED_SYMBOL, "ioctl\0" },
00312
00313
00314
00315
00316 { "sys/ioctl.h", XOPEN_EXTENDED_SYMBOL, "ioctl\0" },
00317
00318 { "sys/socket.h", XOPEN_EXTENDED_SYMBOL, "socket\0" },
00319
00320 { "sys/stat.h", POSIX1_SYMBOL,
00321 "chmod\0fstat\0mkdir\0mkfifo\0stat\0lstat\0umask\0" },
00322 { CONTINUED, POSIX1_SYMBOL|MACRO_SYMBOL,
00323 "S_ISDIR\0S_ISBLK\0S_ISCHR\0S_ISFIFO\0S_ISREG\0S_ISLNK\0S_IFDIR\0\
00324 S_IFBLK\0S_IFCHR\0S_IFIFO\0S_IFREG\0S_IFLNK\0" },
00325 { CONTINUED, XOPEN_EXTENDED_SYMBOL, "fchmod\0" },
00326
00327 #if 0
00328
00329 { "sys/time.h", XOPEN_EXTENDED_SYMBOL, "select\0" },
00330 { "sys/select.h", XOPEN_EXTENDED_SYMBOL , "select\0" },
00331 #endif
00332
00333 { "sys/times.h", POSIX1_SYMBOL, "times\0" },
00334
00335
00336 { "sys/utsname.h", POSIX1_SYMBOL, "uname\0" },
00337
00338 { "sys/wait.h", POSIX1_SYMBOL, "wait\0waitpid\0" },
00339 { CONTINUED, POSIX1_SYMBOL|MACRO_SYMBOL,
00340 "WEXITSTATUS\0WIFEXITED\0WIFSIGNALED\0WIFSTOPPED\0WSTOPSIG\0\
00341 WTERMSIG\0WNOHANG\0WNOTRACED\0" },
00342
00343 { "tar.h", POSIX1_SYMBOL, NONE },
00344
00345 { "termios.h", POSIX1_SYMBOL,
00346 "cfgetispeed\0cfgetospeed\0cfsetispeed\0cfsetospeed\0tcdrain\0tcflow\0tcflush\0tcgetattr\0tcsendbreak\0tcsetattr\0" },
00347
00348 { "time.h", ANSI_SYMBOL,
00349 "asctime\0clock\0ctime\0difftime\0gmtime\0localtime\0mktime\0strftime\0time\0tzset\0" },
00350
00351 { "unistd.h", POSIX1_SYMBOL,
00352 "_exit\0access\0alarm\0chdir\0chown\0close\0ctermid\0cuserid\0\
00353 dup\0dup2\0execl\0execle\0execlp\0execv\0execve\0execvp\0fork\0fpathconf\0\
00354 getcwd\0getegid\0geteuid\0getgid\0getlogin\0getpgrp\0getpid\0\
00355 getppid\0getuid\0isatty\0link\0lseek\0pathconf\0pause\0pipe\0read\0rmdir\0\
00356 setgid\0setpgid\0setsid\0setuid\0sleep\0sysconf\0tcgetpgrp\0tcsetpgrp\0\
00357 ttyname\0unlink\0write\0" },
00358 { CONTINUED, POSIX2_SYMBOL, "getopt\0" },
00359 { CONTINUED, XOPEN_EXTENDED_SYMBOL,
00360 "lockf\0gethostid\0gethostname\0readlink\0symlink\0" },
00361
00362 { "utime.h", POSIX1_SYMBOL, "utime\0" },
00363
00364 { NULL, 0, NONE }
00365 };
00366
00367 enum special_file special_file_handling = no_special;
00368
00369
00370
00371 int seen_S_IFBLK = 0, seen_S_ISBLK = 0;
00372 int seen_S_IFCHR = 0, seen_S_ISCHR = 0;
00373 int seen_S_IFDIR = 0, seen_S_ISDIR = 0;
00374 int seen_S_IFIFO = 0, seen_S_ISFIFO = 0;
00375 int seen_S_IFLNK = 0, seen_S_ISLNK = 0;
00376 int seen_S_IFREG = 0, seen_S_ISREG = 0;
00377
00378 int seen_errno = 0;
00379
00380 int seen_EXIT_FAILURE = 0, seen_EXIT_SUCCESS = 0;
00381
00382 struct obstack scan_file_obstack;
00383
00384
00385
00386 static struct fn_decl *
00387 lookup_std_proto (name, name_length)
00388 const char *name;
00389 int name_length;
00390 {
00391 int i = hashstr (name, name_length) % HASH_SIZE;
00392 int i0 = i;
00393 for (;;)
00394 {
00395 struct fn_decl *fn;
00396 if (hash_tab[i] == 0)
00397 return NULL;
00398 fn = &std_protos[hash_tab[i]];
00399 if ((int) strlen (fn->fname) == name_length
00400 && strncmp (fn->fname, name, name_length) == 0)
00401 return fn;
00402 i = (i+1) % HASH_SIZE;
00403 if (i == i0)
00404 abort ();
00405 }
00406 }
00407
00408 char *inc_filename;
00409 int inc_filename_length;
00410 const char *progname = "fix-header";
00411 FILE *outf;
00412 sstring line;
00413
00414 int lbrac_line, rbrac_line;
00415
00416 int required_unseen_count = 0;
00417 int required_other = 0;
00418
00419 static void
00420 write_lbrac ()
00421 {
00422
00423 #if ADD_MISSING_EXTERN_C
00424 if (missing_extern_C_count + required_unseen_count > 0)
00425 fprintf (outf, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
00426 #endif
00427
00428 if (partial_count)
00429 {
00430 fprintf (outf, "#ifndef _PARAMS\n");
00431 fprintf (outf, "#if defined(__STDC__) || defined(__cplusplus)\n");
00432 fprintf (outf, "#define _PARAMS(ARGS) ARGS\n");
00433 fprintf (outf, "#else\n");
00434 fprintf (outf, "#define _PARAMS(ARGS) ()\n");
00435 fprintf (outf, "#endif\n#endif /* _PARAMS */\n");
00436 }
00437 }
00438
00439 struct partial_proto
00440 {
00441 struct partial_proto *next;
00442 struct fn_decl *fn;
00443 int line_seen;
00444 };
00445
00446 struct partial_proto *partial_proto_list = NULL;
00447
00448 struct partial_proto required_dummy_proto, seen_dummy_proto;
00449 #define REQUIRED(FN) ((FN)->partial == &required_dummy_proto)
00450 #define SET_REQUIRED(FN) ((FN)->partial = &required_dummy_proto)
00451 #define SET_SEEN(FN) ((FN)->partial = &seen_dummy_proto)
00452 #define SEEN(FN) ((FN)->partial == &seen_dummy_proto)
00453
00454 static void
00455 recognized_macro (fname)
00456 const char *fname;
00457 {
00458
00459 struct fn_decl *fn = lookup_std_proto (fname, strlen (fname));
00460
00461
00462 if (fn)
00463 {
00464 if (REQUIRED (fn))
00465 required_unseen_count--;
00466 SET_SEEN (fn);
00467 }
00468
00469 switch (special_file_handling)
00470 {
00471 case errno_h:
00472 if (strcmp (fname, "errno") == 0 && !seen_errno)
00473 seen_errno = 1, required_other--;
00474 break;
00475 case stdlib_h:
00476 if (strcmp (fname, "EXIT_FAILURE") == 0 && !seen_EXIT_FAILURE)
00477 seen_EXIT_FAILURE = 1, required_other--;
00478 if (strcmp (fname, "EXIT_SUCCESS") == 0 && !seen_EXIT_SUCCESS)
00479 seen_EXIT_SUCCESS = 1, required_other--;
00480 break;
00481 case sys_stat_h:
00482 if (fname[0] == 'S' && fname[1] == '_')
00483 {
00484 if (strcmp (fname, "S_IFBLK") == 0) seen_S_IFBLK++;
00485 else if (strcmp (fname, "S_ISBLK") == 0) seen_S_ISBLK++;
00486 else if (strcmp (fname, "S_IFCHR") == 0) seen_S_IFCHR++;
00487 else if (strcmp (fname, "S_ISCHR") == 0) seen_S_ISCHR++;
00488 else if (strcmp (fname, "S_IFDIR") == 0) seen_S_IFDIR++;
00489 else if (strcmp (fname, "S_ISDIR") == 0) seen_S_ISDIR++;
00490 else if (strcmp (fname, "S_IFIFO") == 0) seen_S_IFIFO++;
00491 else if (strcmp (fname, "S_ISFIFO") == 0) seen_S_ISFIFO++;
00492 else if (strcmp (fname, "S_IFLNK") == 0) seen_S_IFLNK++;
00493 else if (strcmp (fname, "S_ISLNK") == 0) seen_S_ISLNK++;
00494 else if (strcmp (fname, "S_IFREG") == 0) seen_S_IFREG++;
00495 else if (strcmp (fname, "S_ISREG") == 0) seen_S_ISREG++;
00496 }
00497 break;
00498
00499 default:
00500 break;
00501 }
00502 }
00503
00504 void
00505 recognized_extern (name)
00506 const cpp_token *name;
00507 {
00508 switch (special_file_handling)
00509 {
00510 case errno_h:
00511 if (cpp_ideq (name, "errno"))
00512 seen_errno = 1, required_other--;
00513 break;
00514
00515 default:
00516 break;
00517 }
00518 }
00519
00520
00521
00522
00523
00524
00525 void
00526 recognized_function (fname, line, kind, have_arg_list)
00527 const cpp_token *fname;
00528 unsigned int line;
00529 int kind;
00530 int have_arg_list;
00531 {
00532 struct partial_proto *partial;
00533 int i;
00534 struct fn_decl *fn;
00535 #if ADD_MISSING_EXTERN_C
00536 if (kind == 'f')
00537 missing_extern_C_count++;
00538 #endif
00539
00540 fn = lookup_std_proto ((const char *) NODE_NAME (fname->val.node),
00541 NODE_LEN (fname->val.node));
00542
00543
00544 if (fn)
00545 {
00546 if (REQUIRED (fn))
00547 required_unseen_count--;
00548 SET_SEEN (fn);
00549 }
00550
00551
00552 if (have_arg_list)
00553 return;
00554
00555 if (kind == 'I')
00556 return;
00557
00558
00559
00560 i = strlen (cur_file);
00561 if (i < inc_filename_length
00562 || strcmp (inc_filename, cur_file + (i - inc_filename_length)) != 0)
00563 return;
00564
00565 if (fn == NULL)
00566 return;
00567 if (fn->params[0] == '\0')
00568 return;
00569
00570
00571
00572 partial_count++;
00573 partial = (struct partial_proto *)
00574 obstack_alloc (&scan_file_obstack, sizeof (struct partial_proto));
00575 partial->line_seen = line;
00576 partial->fn = fn;
00577 fn->partial = partial;
00578 partial->next = partial_proto_list;
00579 partial_proto_list = partial;
00580 if (verbose)
00581 {
00582 fprintf (stderr, "(%s: %s non-prototype function declaration.)\n",
00583 inc_filename, fn->fname);
00584 }
00585 }
00586
00587
00588
00589
00590 static void
00591 check_macro_names (pfile, names)
00592 cpp_reader *pfile;
00593 namelist names;
00594 {
00595 size_t len;
00596 while (*names)
00597 {
00598 len = strlen (names);
00599 if (cpp_defined (pfile, (const unsigned char *)names, len))
00600 recognized_macro (names);
00601 names += len + 1;
00602 }
00603 }
00604
00605 static void
00606 cb_file_change (pfile, map)
00607 cpp_reader *pfile ATTRIBUTE_UNUSED;
00608 const struct line_map *map;
00609 {
00610
00611 cur_file = map->to_file;
00612 }
00613
00614 static void
00615 read_scan_file (in_fname, argc, argv)
00616 char *in_fname;
00617 int argc;
00618 char **argv;
00619 {
00620 cpp_reader *scan_in;
00621 cpp_callbacks *cb;
00622 cpp_options *options;
00623 struct fn_decl *fn;
00624 int i;
00625 struct symbol_list *cur_symbols;
00626
00627 obstack_init (&scan_file_obstack);
00628
00629 scan_in = cpp_create_reader (CLK_GNUC89);
00630 cb = cpp_get_callbacks (scan_in);
00631 cb->file_change = cb_file_change;
00632
00633
00634
00635 options = cpp_get_options (scan_in);
00636 options->inhibit_warnings = 1;
00637 options->inhibit_errors = 1;
00638
00639 i = cpp_handle_options (scan_in, argc, argv);
00640 if (i < argc)
00641 cpp_error (scan_in, DL_ERROR, "invalid option `%s'", argv[i]);
00642 if (cpp_errors (scan_in))
00643 exit (FATAL_EXIT_CODE);
00644
00645 if (! cpp_read_main_file (scan_in, in_fname, NULL))
00646 exit (FATAL_EXIT_CODE);
00647
00648 cpp_finish_options (scan_in);
00649
00650
00651 cpp_make_system_header (scan_in, 1, 0);
00652
00653 scan_decls (scan_in, argc, argv);
00654 for (cur_symbols = &symbol_table[0]; cur_symbols->names; cur_symbols++)
00655 check_macro_names (scan_in, cur_symbols->names);
00656
00657
00658
00659 if (special_file_handling == stdio_h
00660 && (fn = lookup_std_proto ("_filbuf", 7)) != NULL)
00661 {
00662 static const unsigned char getchar_call[] = "getchar();";
00663 int seen_filbuf = 0;
00664
00665
00666 cpp_push_buffer (scan_in, getchar_call, sizeof(getchar_call) - 1,
00667 true, 1);
00668 for (;;)
00669 {
00670 const cpp_token *t = cpp_get_token (scan_in);
00671
00672 if (t->type == CPP_EOF)
00673 break;
00674 else if (cpp_ideq (t, "_filbuf"))
00675 seen_filbuf++;
00676 }
00677
00678 if (seen_filbuf)
00679 {
00680 int need_filbuf = !SEEN (fn) && !REQUIRED (fn);
00681 struct fn_decl *flsbuf_fn = lookup_std_proto ("_flsbuf", 7);
00682 int need_flsbuf
00683 = flsbuf_fn && !SEEN (flsbuf_fn) && !REQUIRED (flsbuf_fn);
00684
00685
00686 if (need_filbuf + need_flsbuf)
00687 {
00688 const char *new_list;
00689 if (need_filbuf)
00690 SET_REQUIRED (fn);
00691 if (need_flsbuf)
00692 SET_REQUIRED (flsbuf_fn);
00693 if (need_flsbuf && need_filbuf)
00694 new_list = "_filbuf\0_flsbuf\0";
00695 else if (need_flsbuf)
00696 new_list = "_flsbuf\0";
00697 else
00698 new_list = "_filbuf\0";
00699 add_symbols (ANSI_SYMBOL, new_list);
00700 required_unseen_count += need_filbuf + need_flsbuf;
00701 }
00702 }
00703 }
00704
00705 if (required_unseen_count + partial_count + required_other
00706 #if ADD_MISSING_EXTERN_C
00707 + missing_extern_C_count
00708 #endif
00709 == 0)
00710 {
00711 if (verbose)
00712 fprintf (stderr, "%s: OK, nothing needs to be done.\n", inc_filename);
00713 exit (SUCCESS_EXIT_CODE);
00714 }
00715 if (!verbose)
00716 fprintf (stderr, "%s: fixing %s\n", progname, inc_filename);
00717 else
00718 {
00719 if (required_unseen_count)
00720 fprintf (stderr, "%s: %d missing function declarations.\n",
00721 inc_filename, required_unseen_count);
00722 if (partial_count)
00723 fprintf (stderr, "%s: %d non-prototype function declarations.\n",
00724 inc_filename, partial_count);
00725 #if ADD_MISSING_EXTERN_C
00726 if (missing_extern_C_count)
00727 fprintf (stderr,
00728 "%s: %d declarations not protected by extern \"C\".\n",
00729 inc_filename, missing_extern_C_count);
00730 #endif
00731 }
00732 }
00733
00734 static void
00735 write_rbrac ()
00736 {
00737 struct fn_decl *fn;
00738 const char *cptr;
00739 struct symbol_list *cur_symbols;
00740
00741 if (required_unseen_count)
00742 {
00743 #ifdef NO_IMPLICIT_EXTERN_C
00744 fprintf (outf, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
00745 #endif
00746 }
00747
00748
00749 for (cur_symbols = &symbol_table[0]; cur_symbols->names; cur_symbols++)
00750 {
00751 int if_was_emitted = 0;
00752 int name_len;
00753 cptr = cur_symbols->names;
00754 for ( ; (name_len = strlen (cptr)) != 0; cptr+= name_len + 1)
00755 {
00756 int macro_protect = 0;
00757
00758 if (cur_symbols->flags & MACRO_SYMBOL)
00759 continue;
00760
00761 fn = lookup_std_proto (cptr, name_len);
00762 if (fn == NULL || !REQUIRED (fn))
00763 continue;
00764
00765 if (!if_was_emitted)
00766 {
00767
00768 if (cur_symbols->flags & ANSI_SYMBOL)
00769 fprintf (outf,
00770 "#if defined(__USE_FIXED_PROTOTYPES__) || defined(__cplusplus) || defined (__STRICT_ANSI__)\n");
00771 else if (cur_symbols->flags & (POSIX1_SYMBOL|POSIX2_SYMBOL))
00772 fprintf (outf,
00773 "#if defined(__USE_FIXED_PROTOTYPES__) || (defined(__cplusplus) \\\n\
00774 ? (!defined(__STRICT_ANSI__) || defined(_POSIX_SOURCE)) \\\n\
00775 : (defined(__STRICT_ANSI__) && defined(_POSIX_SOURCE)))\n");
00776 else if (cur_symbols->flags & XOPEN_SYMBOL)
00777 {
00778 fprintf (outf,
00779 "#if defined(__USE_FIXED_PROTOTYPES__) \\\n\
00780 || (defined(__STRICT_ANSI__) && defined(_XOPEN_SOURCE))\n");
00781 }
00782 else if (cur_symbols->flags & XOPEN_EXTENDED_SYMBOL)
00783 {
00784 fprintf (outf,
00785 "#if defined(__USE_FIXED_PROTOTYPES__) \\\n\
00786 || (defined(__STRICT_ANSI__) && defined(_XOPEN_EXTENDED_SOURCE))\n");
00787 }
00788 else
00789 {
00790 fatal ("internal error for function %s", fn->fname);
00791 }
00792 if_was_emitted = 1;
00793 }
00794
00795
00796
00797 if (!strcmp (fn->fname, "memmove")
00798 || !strcmp (fn->fname, "putc")
00799 || !strcmp (fn->fname, "getc")
00800 || !strcmp (fn->fname, "vprintf")
00801 || !strcmp (fn->fname, "vfprintf")
00802 || !strcmp (fn->fname, "vsprintf")
00803 || !strcmp (fn->fname, "rewinddir")
00804 || !strcmp (fn->fname, "abort"))
00805 macro_protect = 1;
00806
00807 if (macro_protect)
00808 fprintf (outf, "#ifndef %s\n", fn->fname);
00809 fprintf (outf, "extern %s %s (%s);\n",
00810 fn->rtype, fn->fname, fn->params);
00811 if (macro_protect)
00812 fprintf (outf, "#endif\n");
00813 }
00814 if (if_was_emitted)
00815 fprintf (outf,
00816 "#endif /* defined(__USE_FIXED_PROTOTYPES__) || ... */\n");
00817 }
00818 if (required_unseen_count)
00819 {
00820 #ifdef NO_IMPLICIT_EXTERN_C
00821 fprintf (outf, "#ifdef __cplusplus\n}\n#endif\n");
00822 #endif
00823 }
00824
00825 switch (special_file_handling)
00826 {
00827 case errno_h:
00828 if (!seen_errno)
00829 fprintf (outf, "extern int errno;\n");
00830 break;
00831 case stdlib_h:
00832 if (!seen_EXIT_FAILURE)
00833 fprintf (outf, "#define EXIT_FAILURE 1\n");
00834 if (!seen_EXIT_SUCCESS)
00835 fprintf (outf, "#define EXIT_SUCCESS 0\n");
00836 break;
00837 case sys_stat_h:
00838 if (!seen_S_ISBLK && seen_S_IFBLK)
00839 fprintf (outf,
00840 "#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)\n");
00841 if (!seen_S_ISCHR && seen_S_IFCHR)
00842 fprintf (outf,
00843 "#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)\n");
00844 if (!seen_S_ISDIR && seen_S_IFDIR)
00845 fprintf (outf,
00846 "#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)\n");
00847 if (!seen_S_ISFIFO && seen_S_IFIFO)
00848 fprintf (outf,
00849 "#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)\n");
00850 if (!seen_S_ISLNK && seen_S_IFLNK)
00851 fprintf (outf,
00852 "#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)\n");
00853 if (!seen_S_ISREG && seen_S_IFREG)
00854 fprintf (outf,
00855 "#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)\n");
00856 break;
00857
00858 default:
00859 break;
00860 }
00861
00862
00863 #if ADD_MISSING_EXTERN_C
00864 if (missing_extern_C_count + required_unseen_count > 0)
00865 fprintf (outf, "#ifdef __cplusplus\n}\n#endif\n");
00866 #endif
00867 }
00868
00869
00870
00871
00872
00873
00874
00875
00876 #define INF_GET() (inf_ptr < inf_limit ? *(unsigned char *) inf_ptr++ : EOF)
00877 #define INF_UNGET(c) ((c)!=EOF && inf_ptr--)
00878
00879 static int
00880 inf_skip_spaces (c)
00881 int c;
00882 {
00883 for (;;)
00884 {
00885 if (c == ' ' || c == '\t')
00886 c = INF_GET ();
00887 else if (c == '/')
00888 {
00889 c = INF_GET ();
00890 if (c != '*')
00891 {
00892 (void) INF_UNGET (c);
00893 return '/';
00894 }
00895 c = INF_GET ();
00896 for (;;)
00897 {
00898 if (c == EOF)
00899 return EOF;
00900 else if (c != '*')
00901 {
00902 if (c == '\n')
00903 source_lineno++, lineno++;
00904 c = INF_GET ();
00905 }
00906 else if ((c = INF_GET ()) == '/')
00907 return INF_GET ();
00908 }
00909 }
00910 else
00911 break;
00912 }
00913 return c;
00914 }
00915
00916
00917
00918 static int
00919 inf_read_upto (str, delim)
00920 sstring *str;
00921 int delim;
00922 {
00923 int ch;
00924 for (;;)
00925 {
00926 ch = INF_GET ();
00927 if (ch == EOF || ch == delim)
00928 break;
00929 SSTRING_PUT (str, ch);
00930 }
00931 MAKE_SSTRING_SPACE (str, 1);
00932 *str->ptr = 0;
00933 return ch;
00934 }
00935
00936 static int
00937 inf_scan_ident (s, c)
00938 sstring *s;
00939 int c;
00940 {
00941 s->ptr = s->base;
00942 if (ISIDST (c))
00943 {
00944 for (;;)
00945 {
00946 SSTRING_PUT (s, c);
00947 c = INF_GET ();
00948 if (c == EOF || !(ISIDNUM (c)))
00949 break;
00950 }
00951 }
00952 MAKE_SSTRING_SPACE (s, 1);
00953 *s->ptr = 0;
00954 return c;
00955 }
00956
00957
00958
00959
00960
00961
00962 static int
00963 check_protection (ifndef_line, endif_line)
00964 int *ifndef_line, *endif_line;
00965 {
00966 int c;
00967 int if_nesting = 1;
00968 char *protect_name = NULL;
00969 int define_seen = 0;
00970
00971
00972 for (;; lineno++)
00973 {
00974 c = inf_skip_spaces (' ');
00975 if (c == EOF)
00976 return 0;
00977 if (c != '\n')
00978 break;
00979 }
00980 if (c != '#')
00981 return 0;
00982 c = inf_scan_ident (&buf, inf_skip_spaces (' '));
00983 if (SSTRING_LENGTH (&buf) == 0 || strcmp (buf.base, "ifndef") != 0)
00984 return 0;
00985
00986
00987 *ifndef_line = lineno;
00988 c = inf_scan_ident (&buf, inf_skip_spaces (c));
00989 if (SSTRING_LENGTH (&buf) == 0 || c == EOF)
00990 return 0;
00991 protect_name = xstrdup (buf.base);
00992
00993 (void) INF_UNGET (c);
00994 c = inf_read_upto (&buf, '\n');
00995 if (c == EOF)
00996 return 0;
00997 lineno++;
00998
00999 for (;;)
01000 {
01001 c = inf_skip_spaces (' ');
01002 if (c == EOF)
01003 return 0;
01004 if (c == '\n')
01005 {
01006 lineno++;
01007 continue;
01008 }
01009 if (c != '#')
01010 goto skip_to_eol;
01011 c = inf_scan_ident (&buf, inf_skip_spaces (' '));
01012 if (SSTRING_LENGTH (&buf) == 0)
01013 ;
01014 else if (!strcmp (buf.base, "ifndef")
01015 || !strcmp (buf.base, "ifdef") || !strcmp (buf.base, "if"))
01016 {
01017 if_nesting++;
01018 }
01019 else if (!strcmp (buf.base, "endif"))
01020 {
01021 if_nesting--;
01022 if (if_nesting == 0)
01023 break;
01024 }
01025 else if (!strcmp (buf.base, "else"))
01026 {
01027 if (if_nesting == 1)
01028 return 0;
01029 }
01030 else if (!strcmp (buf.base, "define"))
01031 {
01032 c = inf_skip_spaces (c);
01033 c = inf_scan_ident (&buf, c);
01034 if (buf.base[0] > 0 && strcmp (buf.base, protect_name) == 0)
01035 define_seen = 1;
01036 }
01037 skip_to_eol:
01038 for (;;)
01039 {
01040 if (c == '\n' || c == EOF)
01041 break;
01042 c = INF_GET ();
01043 }
01044 if (c == EOF)
01045 return 0;
01046 lineno++;
01047 }
01048
01049 if (!define_seen)
01050 return 0;
01051 *endif_line = lineno;
01052
01053 for (;;)
01054 {
01055 c = inf_skip_spaces (' ');
01056 if (c == EOF)
01057 break;
01058 if (c != '\n')
01059 return 0;
01060 }
01061
01062 return 1;
01063 }
01064
01065 extern int main PARAMS ((int, char **));
01066
01067 int
01068 main (argc, argv)
01069 int argc;
01070 char **argv;
01071 {
01072 int inf_fd;
01073 struct stat sbuf;
01074 int c;
01075 #ifdef FIXPROTO_IGNORE_LIST
01076 int i;
01077 #endif
01078 const char *cptr;
01079 int ifndef_line;
01080 int endif_line;
01081 long to_read;
01082 long int inf_size;
01083 struct symbol_list *cur_symbols;
01084
01085 if (argv[0] && argv[0][0])
01086 {
01087 char *p;
01088
01089 progname = 0;
01090 for (p = argv[0]; *p; p++)
01091 if (*p == '/')
01092 progname = p;
01093 progname = progname ? progname+1 : argv[0];
01094 }
01095
01096 if (argc < 4)
01097 {
01098 fprintf (stderr, "%s: Usage: foo.h infile.h outfile.h options\n",
01099 progname);
01100 exit (FATAL_EXIT_CODE);
01101 }
01102
01103 inc_filename = argv[1];
01104 inc_filename_length = strlen (inc_filename);
01105
01106 #ifdef FIXPROTO_IGNORE_LIST
01107 for (i = 0; files_to_ignore[i] != NULL; i++)
01108 {
01109 const char *const ignore_name = files_to_ignore[i];
01110 int ignore_len = strlen (ignore_name);
01111 if (strncmp (inc_filename, ignore_name, ignore_len) == 0)
01112 {
01113 if (ignore_name[ignore_len-1] == '/'
01114 || inc_filename[ignore_len] == '\0')
01115 {
01116 if (verbose)
01117 fprintf (stderr, "%s: ignoring %s\n", progname, inc_filename);
01118 exit (SUCCESS_EXIT_CODE);
01119 }
01120 }
01121
01122 }
01123 #endif
01124
01125 if (strcmp (inc_filename, "sys/stat.h") == 0)
01126 special_file_handling = sys_stat_h;
01127 else if (strcmp (inc_filename, "errno.h") == 0)
01128 special_file_handling = errno_h, required_other++;
01129 else if (strcmp (inc_filename, "stdlib.h") == 0)
01130 special_file_handling = stdlib_h, required_other+=2;
01131 else if (strcmp (inc_filename, "stdio.h") == 0)
01132 special_file_handling = stdio_h;
01133 include_entry = std_include_table;
01134 while (include_entry->name != NULL
01135 && ((strcmp (include_entry->name, CONTINUED) == 0)
01136 || strcmp (inc_filename, include_entry->name) != 0))
01137 include_entry++;
01138
01139 if (include_entry->name != NULL)
01140 {
01141 const struct std_include_entry *entry;
01142 cur_symbol_table_size = 0;
01143 for (entry = include_entry; ;)
01144 {
01145 if (entry->flags)
01146 add_symbols (entry->flags, entry->names);
01147 entry++;
01148 if (!entry->name || strcmp (entry->name, CONTINUED) != 0)
01149 break;
01150 }
01151 }
01152 else
01153 symbol_table[0].names = NULL;
01154
01155
01156 for (cur_symbols = &symbol_table[0]; cur_symbols->names; cur_symbols++)
01157 {
01158 int name_len;
01159 if (cur_symbols->flags & MACRO_SYMBOL)
01160 continue;
01161 cptr = cur_symbols->names;
01162 for ( ; (name_len = strlen (cptr)) != 0; cptr+= name_len + 1)
01163 {
01164 struct fn_decl *fn = lookup_std_proto (cptr, name_len);
01165 required_unseen_count++;
01166 if (fn == NULL)
01167 fprintf (stderr, "Internal error: No prototype for %s\n", cptr);
01168 else
01169 SET_REQUIRED (fn);
01170 }
01171 }
01172
01173 read_scan_file (argv[2], argc - 4, argv + 4);
01174
01175 inf_fd = open (argv[2], O_RDONLY, 0666);
01176 if (inf_fd < 0)
01177 {
01178 fprintf (stderr, "%s: Cannot open '%s' for reading -",
01179 progname, argv[2]);
01180 perror (NULL);
01181 exit (FATAL_EXIT_CODE);
01182 }
01183 if (fstat (inf_fd, &sbuf) < 0)
01184 {
01185 fprintf (stderr, "%s: Cannot get size of '%s' -", progname, argv[2]);
01186 perror (NULL);
01187 exit (FATAL_EXIT_CODE);
01188 }
01189 inf_size = sbuf.st_size;
01190 inf_buffer = (char *) xmalloc (inf_size + 2);
01191 inf_ptr = inf_buffer;
01192
01193 to_read = inf_size;
01194 while (to_read > 0)
01195 {
01196 long i = read (inf_fd, inf_buffer + inf_size - to_read, to_read);
01197 if (i < 0)
01198 {
01199 fprintf (stderr, "%s: Failed to read '%s' -", progname, argv[2]);
01200 perror (NULL);
01201 exit (FATAL_EXIT_CODE);
01202 }
01203 if (i == 0)
01204 {
01205 inf_size -= to_read;
01206 break;
01207 }
01208 to_read -= i;
01209 }
01210
01211 close (inf_fd);
01212
01213
01214 inf_buffer[inf_size] = '\n';
01215 inf_buffer[inf_size + 1] = '\0';
01216 inf_limit = inf_buffer + inf_size;
01217
01218
01219 if (inf_limit > inf_buffer && inf_limit[-1] != '\n')
01220 inf_limit++;
01221
01222 unlink (argv[3]);
01223 outf = fopen (argv[3], "w");
01224 if (outf == NULL)
01225 {
01226 fprintf (stderr, "%s: Cannot open '%s' for writing -",
01227 progname, argv[3]);
01228 perror (NULL);
01229 exit (FATAL_EXIT_CODE);
01230 }
01231
01232 lineno = 1;
01233
01234 if (check_protection (&ifndef_line, &endif_line))
01235 {
01236 lbrac_line = ifndef_line+1;
01237 rbrac_line = endif_line;
01238 }
01239 else
01240 {
01241 lbrac_line = 1;
01242 rbrac_line = -1;
01243 }
01244
01245
01246 inf_ptr = inf_buffer;
01247 lineno = 1;
01248
01249 for (;;)
01250 {
01251 if (lineno == lbrac_line)
01252 write_lbrac ();
01253 if (lineno == rbrac_line)
01254 write_rbrac ();
01255 for (;;)
01256 {
01257 struct fn_decl *fn;
01258 c = INF_GET ();
01259 if (c == EOF)
01260 break;
01261 if (ISIDST (c))
01262 {
01263 c = inf_scan_ident (&buf, c);
01264 (void) INF_UNGET (c);
01265 fputs (buf.base, outf);
01266 fn = lookup_std_proto (buf.base, strlen (buf.base));
01267
01268
01269
01270 if (fn && fn->partial && fn->partial->line_seen == lineno)
01271 {
01272 c = inf_skip_spaces (' ');
01273 if (c == EOF)
01274 break;
01275 if (c == '(')
01276 {
01277 c = inf_skip_spaces (' ');
01278 if (c == ')')
01279 {
01280 fprintf (outf, " _PARAMS((%s))", fn->params);
01281 }
01282 else
01283 {
01284 putc ('(', outf);
01285 (void) INF_UNGET (c);
01286 }
01287 }
01288 else
01289 fprintf (outf, " %c", c);
01290 }
01291 }
01292 else
01293 {
01294 putc (c, outf);
01295 if (c == '\n')
01296 break;
01297 }
01298 }
01299 if (c == EOF)
01300 break;
01301 lineno++;
01302 }
01303 if (rbrac_line < 0)
01304 write_rbrac ();
01305
01306 fclose (outf);
01307
01308 return 0;
01309 }
01310
01311
01312 static void
01313 v_fatal (str, ap)
01314 const char * str;
01315 va_list ap;
01316 {
01317 fprintf (stderr, "%s: %s: ", progname, inc_filename);
01318 vfprintf (stderr, str, ap);
01319 fprintf (stderr, "\n");
01320
01321 exit (FATAL_EXIT_CODE);
01322 }
01323
01324 static void
01325 fatal VPARAMS ((const char *str, ...))
01326 {
01327 VA_OPEN (ap, str);
01328 VA_FIXEDARG (ap, const char *, str);
01329
01330 v_fatal (str, ap);
01331 VA_CLOSE (ap);
01332 }