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