1 /* Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com). 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 2, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING. If not, write to the Free 19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 20 02111-1307, USA. */ 21 22 #include "config.h" 23 #include "system.h" 24 #include "intl.h" 25 #include "cppdefault.h" 26 27 #include <setjmp.h> 28 #include <signal.h> 29 #if ! defined( SIGCHLD ) && defined( SIGCLD ) 30 # define SIGCHLD SIGCLD 31 #endif 32 #ifdef HAVE_UNISTD_H 33 #include <unistd.h> 34 #endif 35 #undef abort 36 #include "version.h" 37 38 /* Include getopt.h for the sake of getopt_long. */ 39 #include "getopt.h" 40 41 /* Macro to see if the path elements match. */ 42 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 43 #define IS_SAME_PATH_CHAR(a,b) (TOUPPER (a) == TOUPPER (b)) 44 #else 45 #define IS_SAME_PATH_CHAR(a,b) ((a) == (b)) 46 #endif 47 48 /* Macro to see if the paths match. */ 49 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 50 #define IS_SAME_PATH(a,b) (strcasecmp (a, b) == 0) 51 #else 52 #define IS_SAME_PATH(a,b) (strcmp (a, b) == 0) 53 #endif 54 55 /* Suffix for aux-info files. */ 56 #ifdef __MSDOS__ 57 #define AUX_INFO_SUFFIX "X" 58 #else 59 #define AUX_INFO_SUFFIX ".X" 60 #endif 61 62 /* Suffix for saved files. */ 63 #ifdef __MSDOS__ 64 #define SAVE_SUFFIX "sav" 65 #else 66 #define SAVE_SUFFIX ".save" 67 #endif 68 69 /* Suffix for renamed C++ files. */ 70 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 71 #define CPLUS_FILE_SUFFIX "cc" 72 #else 73 #define CPLUS_FILE_SUFFIX "C" 74 #endif 75 76 static void usage PARAMS ((void)) ATTRIBUTE_NORETURN; 77 static void aux_info_corrupted PARAMS ((void)) ATTRIBUTE_NORETURN; 78 static void declare_source_confusing PARAMS ((const char *)) ATTRIBUTE_NORETURN; 79 static const char *shortpath PARAMS ((const char *, const char *)); 80 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN; 81 static void notice PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1; 82 static char *savestring PARAMS ((const char *, unsigned int)); 83 static char *dupnstr PARAMS ((const char *, size_t)); 84 static const char *substr PARAMS ((const char *, const char * const)); 85 static int safe_read PARAMS ((int, PTR, int)); 86 static void safe_write PARAMS ((int, PTR, int, const char *)); 87 static void save_pointers PARAMS ((void)); 88 static void restore_pointers PARAMS ((void)); 89 static int is_id_char PARAMS ((int)); 90 static int in_system_include_dir PARAMS ((const char *)); 91 static int directory_specified_p PARAMS ((const char *)); 92 static int file_excluded_p PARAMS ((const char *)); 93 static char *unexpand_if_needed PARAMS ((const char *)); 94 static char *abspath PARAMS ((const char *, const char *)); 95 static int is_abspath PARAMS ((const char *)); 96 static void check_aux_info PARAMS ((int)); 97 static const char *find_corresponding_lparen PARAMS ((const char *)); 98 static int referenced_file_is_newer PARAMS ((const char *, time_t)); 99 static void save_def_or_dec PARAMS ((const char *, int)); 100 static void munge_compile_params PARAMS ((const char *)); 101 static int gen_aux_info_file PARAMS ((const char *)); 102 static void process_aux_info_file PARAMS ((const char *, int, int)); 103 static int identify_lineno PARAMS ((const char *)); 104 static void check_source PARAMS ((int, const char *)); 105 static const char *seek_to_line PARAMS ((int)); 106 static const char *forward_to_next_token_char PARAMS ((const char *)); 107 static void output_bytes PARAMS ((const char *, size_t)); 108 static void output_string PARAMS ((const char *)); 109 static void output_up_to PARAMS ((const char *)); 110 static int other_variable_style_function PARAMS ((const char *)); 111 static const char *find_rightmost_formals_list PARAMS ((const char *)); 112 static void do_cleaning PARAMS ((char *, const char *)); 113 static const char *careful_find_l_paren PARAMS ((const char *)); 114 static void do_processing PARAMS ((void)); 115 116 /* Look for these where the `const' qualifier is intentionally cast aside. */ 117 #define NONCONST 118 119 /* Define a default place to find the SYSCALLS.X file. */ 120 121 #ifndef UNPROTOIZE 122 123 #ifndef STANDARD_EXEC_PREFIX 124 #define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/" 125 #endif /* !defined STANDARD_EXEC_PREFIX */ 126 127 static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX; 128 static const char * const target_machine = DEFAULT_TARGET_MACHINE; 129 static const char * const target_version = DEFAULT_TARGET_VERSION; 130 131 #endif /* !defined (UNPROTOIZE) */ 132 133 /* Suffix of aux_info files. */ 134 135 static const char * const aux_info_suffix = AUX_INFO_SUFFIX; 136 137 /* String to attach to filenames for saved versions of original files. */ 138 139 static const char * const save_suffix = SAVE_SUFFIX; 140 141 /* String to attach to C filenames renamed to C++. */ 142 143 static const char * const cplus_suffix = CPLUS_FILE_SUFFIX; 144 145 #ifndef UNPROTOIZE 146 147 /* File name of the file which contains descriptions of standard system 148 routines. Note that we never actually do anything with this file per se, 149 but we do read in its corresponding aux_info file. */ 150 151 static const char syscalls_filename[] = "SYSCALLS.c"; 152 153 /* Default place to find the above file. */ 154 155 static const char * default_syscalls_dir; 156 157 /* Variable to hold the complete absolutized filename of the SYSCALLS.c.X 158 file. */ 159 160 static char * syscalls_absolute_filename; 161 162 #endif /* !defined (UNPROTOIZE) */ 163 164 /* Type of the structure that holds information about macro unexpansions. */ 165 166 struct unexpansion_struct { 167 const char *const expanded; 168 const char *const contracted; 169 }; 170 typedef struct unexpansion_struct unexpansion; 171 172 /* A table of conversions that may need to be made for some (stupid) older 173 operating systems where these types are preprocessor macros rather than 174 typedefs (as they really ought to be). 175 176 WARNING: The contracted forms must be as small (or smaller) as the 177 expanded forms, or else havoc will ensue. */ 178 179 static const unexpansion unexpansions[] = { 180 { "struct _iobuf", "FILE" }, 181 { 0, 0 } 182 }; 183 184 /* The number of "primary" slots in the hash tables for filenames and for 185 function names. This can be as big or as small as you like, except that 186 it must be a power of two. */ 187 188 #define HASH_TABLE_SIZE (1 << 9) 189 190 /* Bit mask to use when computing hash values. */ 191 192 static const int hash_mask = (HASH_TABLE_SIZE - 1); 193 194 195 /* Datatype for lists of directories or filenames. */ 196 struct string_list 197 { 198 const char *name; 199 struct string_list *next; 200 }; 201 202 static struct string_list *string_list_cons PARAMS ((const char *, 203 struct string_list *)); 204 205 /* List of directories in which files should be converted. */ 206 207 struct string_list *directory_list; 208 209 /* List of file names which should not be converted. 210 A file is excluded if the end of its name, following a /, 211 matches one of the names in this list. */ 212 213 struct string_list *exclude_list; 214 215 /* The name of the other style of variable-number-of-parameters functions 216 (i.e. the style that we want to leave unconverted because we don't yet 217 know how to convert them to this style. This string is used in warning 218 messages. */ 219 220 /* Also define here the string that we can search for in the parameter lists 221 taken from the .X files which will unambiguously indicate that we have 222 found a varargs style function. */ 223 224 #ifdef UNPROTOIZE 225 static const char * const other_var_style = "stdarg"; 226 #else /* !defined (UNPROTOIZE) */ 227 static const char * const other_var_style = "varargs"; 228 /* Note that this is a string containing the expansion of va_alist. 229 But in `main' we discard all but the first token. */ 230 static const char *varargs_style_indicator = STRINGX (va_alist); 231 #endif /* !defined (UNPROTOIZE) */ 232 233 /* The following two types are used to create hash tables. In this program, 234 there are two hash tables which are used to store and quickly lookup two 235 different classes of strings. The first type of strings stored in the 236 first hash table are absolute filenames of files which protoize needs to 237 know about. The second type of strings (stored in the second hash table) 238 are function names. It is this second class of strings which really 239 inspired the use of the hash tables, because there may be a lot of them. */ 240 241 typedef struct hash_table_entry_struct hash_table_entry; 242 243 /* Do some typedefs so that we don't have to write "struct" so often. */ 244 245 typedef struct def_dec_info_struct def_dec_info; 246 typedef struct file_info_struct file_info; 247 typedef struct f_list_chain_item_struct f_list_chain_item; 248 249 #ifndef UNPROTOIZE 250 static int is_syscalls_file PARAMS ((const file_info *)); 251 static void rename_c_file PARAMS ((const hash_table_entry *)); 252 static const def_dec_info *find_extern_def PARAMS ((const def_dec_info *, 253 const def_dec_info *)); 254 static const def_dec_info *find_static_definition PARAMS ((const def_dec_info *)); 255 static void connect_defs_and_decs PARAMS ((const hash_table_entry *)); 256 static void add_local_decl PARAMS ((const def_dec_info *, const char *)); 257 static void add_global_decls PARAMS ((const file_info *, const char *)); 258 #endif /* ! UNPROTOIZE */ 259 static int needs_to_be_converted PARAMS ((const file_info *)); 260 static void visit_each_hash_node PARAMS ((const hash_table_entry *, 261 void (*)(const hash_table_entry *))); 262 static hash_table_entry *add_symbol PARAMS ((hash_table_entry *, const char *)); 263 static hash_table_entry *lookup PARAMS ((hash_table_entry *, const char *)); 264 static void free_def_dec PARAMS ((def_dec_info *)); 265 static file_info *find_file PARAMS ((const char *, int)); 266 static void reverse_def_dec_list PARAMS ((const hash_table_entry *)); 267 static void edit_fn_declaration PARAMS ((const def_dec_info *, const char *)); 268 static int edit_formals_lists PARAMS ((const char *, unsigned int, 269 const def_dec_info *)); 270 static void edit_fn_definition PARAMS ((const def_dec_info *, const char *)); 271 static void scan_for_missed_items PARAMS ((const file_info *)); 272 static void edit_file PARAMS ((const hash_table_entry *)); 273 274 /* In the struct below, note that the "_info" field has two different uses 275 depending on the type of hash table we are in (i.e. either the filenames 276 hash table or the function names hash table). In the filenames hash table 277 the info fields of the entries point to the file_info struct which is 278 associated with each filename (1 per filename). In the function names 279 hash table, the info field points to the head of a singly linked list of 280 def_dec_info entries which are all defs or decs of the function whose 281 name is pointed to by the "symbol" field. Keeping all of the defs/decs 282 for a given function name on a special list specifically for that function 283 name makes it quick and easy to find out all of the important information 284 about a given (named) function. */ 285 286 struct hash_table_entry_struct { 287 hash_table_entry * hash_next; /* -> to secondary entries */ 288 const char * symbol; /* -> to the hashed string */ 289 union { 290 const def_dec_info * _ddip; 291 file_info * _fip; 292 } _info; 293 }; 294 #define ddip _info._ddip 295 #define fip _info._fip 296 297 /* Define a type specifically for our two hash tables. */ 298 299 typedef hash_table_entry hash_table[HASH_TABLE_SIZE]; 300 301 /* The following struct holds all of the important information about any 302 single filename (e.g. file) which we need to know about. */ 303 304 struct file_info_struct { 305 const hash_table_entry * hash_entry; /* -> to associated hash entry */ 306 const def_dec_info * defs_decs; /* -> to chain of defs/decs */ 307 time_t mtime; /* Time of last modification. */ 308 }; 309 310 /* Due to the possibility that functions may return pointers to functions, 311 (which may themselves have their own parameter lists) and due to the 312 fact that returned pointers-to-functions may be of type "pointer-to- 313 function-returning-pointer-to-function" (ad nauseum) we have to keep 314 an entire chain of ANSI style formal parameter lists for each function. 315 316 Normally, for any given function, there will only be one formals list 317 on the chain, but you never know. 318 319 Note that the head of each chain of formals lists is pointed to by the 320 `f_list_chain' field of the corresponding def_dec_info record. 321 322 For any given chain, the item at the head of the chain is the *leftmost* 323 parameter list seen in the actual C language function declaration. If 324 there are other members of the chain, then these are linked in left-to-right 325 order from the head of the chain. */ 326 327 struct f_list_chain_item_struct { 328 const f_list_chain_item * chain_next; /* -> to next item on chain */ 329 const char * formals_list; /* -> to formals list string */ 330 }; 331 332 /* The following struct holds all of the important information about any 333 single function definition or declaration which we need to know about. 334 Note that for unprotoize we don't need to know very much because we 335 never even create records for stuff that we don't intend to convert 336 (like for instance defs and decs which are already in old K&R format 337 and "implicit" function declarations). */ 338 339 struct def_dec_info_struct { 340 const def_dec_info * next_in_file; /* -> to rest of chain for file */ 341 file_info * file; /* -> file_info for containing file */ 342 int line; /* source line number of def/dec */ 343 const char * ansi_decl; /* -> left end of ansi decl */ 344 hash_table_entry * hash_entry; /* -> hash entry for function name */ 345 unsigned int is_func_def; /* = 0 means this is a declaration */ 346 const def_dec_info * next_for_func; /* -> to rest of chain for func name */ 347 unsigned int f_list_count; /* count of formals lists we expect */ 348 char prototyped; /* = 0 means already prototyped */ 349 #ifndef UNPROTOIZE 350 const f_list_chain_item * f_list_chain; /* -> chain of formals lists */ 351 const def_dec_info * definition; /* -> def/dec containing related def */ 352 char is_static; /* = 0 means visibility is "extern" */ 353 char is_implicit; /* != 0 for implicit func decl's */ 354 char written; /* != 0 means written for implicit */ 355 #else /* !defined (UNPROTOIZE) */ 356 const char * formal_names; /* -> to list of names of formals */ 357 const char * formal_decls; /* -> to string of formal declarations */ 358 #endif /* !defined (UNPROTOIZE) */ 359 }; 360 361 /* Pointer to the tail component of the filename by which this program was 362 invoked. Used everywhere in error and warning messages. */ 363 364 static const char *pname; 365 366 /* Error counter. Will be nonzero if we should give up at the next convenient 367 stopping point. */ 368 369 static int errors = 0; 370 371 /* Option flags. */ 372 /* ??? These comments should say what the flag mean as well as the options 373 that set them. */ 374 375 /* File name to use for running gcc. Allows GCC 2 to be named 376 something other than gcc. */ 377 static const char *compiler_file_name = "gcc"; 378 379 static int version_flag = 0; /* Print our version number. */ 380 static int quiet_flag = 0; /* Don't print messages normally. */ 381 static int nochange_flag = 0; /* Don't convert, just say what files 382 we would have converted. */ 383 static int nosave_flag = 0; /* Don't save the old version. */ 384 static int keep_flag = 0; /* Don't delete the .X files. */ 385 static const char ** compile_params = 0; /* Option string for gcc. */ 386 #ifdef UNPROTOIZE 387 static const char *indent_string = " "; /* Indentation for newly 388 inserted parm decls. */ 389 #else /* !defined (UNPROTOIZE) */ 390 static int local_flag = 0; /* Insert new local decls (when?). */ 391 static int global_flag = 0; /* set by -g option */ 392 static int cplusplus_flag = 0; /* Rename converted files to *.C. */ 393 static const char *nondefault_syscalls_dir = 0; /* Dir to look for 394 SYSCALLS.c.X in. */ 395 #endif /* !defined (UNPROTOIZE) */ 396 397 /* An index into the compile_params array where we should insert the source 398 file name when we are ready to exec the C compiler. A zero value indicates 399 that we have not yet called munge_compile_params. */ 400 401 static int input_file_name_index = 0; 402 403 /* An index into the compile_params array where we should insert the filename 404 for the aux info file, when we run the C compiler. */ 405 static int aux_info_file_name_index = 0; 406 407 /* Count of command line arguments which were "filename" arguments. */ 408 409 static int n_base_source_files = 0; 410 411 /* Points to a malloc'ed list of pointers to all of the filenames of base 412 source files which were specified on the command line. */ 413 414 static const char **base_source_filenames; 415 416 /* Line number of the line within the current aux_info file that we 417 are currently processing. Used for error messages in case the prototypes 418 info file is corrupted somehow. */ 419 420 static int current_aux_info_lineno; 421 422 /* Pointer to the name of the source file currently being converted. */ 423 424 static const char *convert_filename; 425 426 /* Pointer to relative root string (taken from aux_info file) which indicates 427 where directory the user was in when he did the compilation step that 428 produced the containing aux_info file. */ 429 430 static const char *invocation_filename; 431 432 /* Pointer to the base of the input buffer that holds the original text for the 433 source file currently being converted. */ 434 435 static const char *orig_text_base; 436 437 /* Pointer to the byte just beyond the end of the input buffer that holds the 438 original text for the source file currently being converted. */ 439 440 static const char *orig_text_limit; 441 442 /* Pointer to the base of the input buffer that holds the cleaned text for the 443 source file currently being converted. */ 444 445 static const char *clean_text_base; 446 447 /* Pointer to the byte just beyond the end of the input buffer that holds the 448 cleaned text for the source file currently being converted. */ 449 450 static const char *clean_text_limit; 451 452 /* Pointer to the last byte in the cleaned text buffer that we have already 453 (virtually) copied to the output buffer (or decided to ignore). */ 454 455 static const char * clean_read_ptr; 456 457 /* Pointer to the base of the output buffer that holds the replacement text 458 for the source file currently being converted. */ 459 460 static char *repl_text_base; 461 462 /* Pointer to the byte just beyond the end of the output buffer that holds the 463 replacement text for the source file currently being converted. */ 464 465 static char *repl_text_limit; 466 467 /* Pointer to the last byte which has been stored into the output buffer. 468 The next byte to be stored should be stored just past where this points 469 to. */ 470 471 static char * repl_write_ptr; 472 473 /* Pointer into the cleaned text buffer for the source file we are currently 474 converting. This points to the first character of the line that we last 475 did a "seek_to_line" to (see below). */ 476 477 static const char *last_known_line_start; 478 479 /* Number of the line (in the cleaned text buffer) that we last did a 480 "seek_to_line" to. Will be one if we just read a new source file 481 into the cleaned text buffer. */ 482 483 static int last_known_line_number; 484 485 /* The filenames hash table. */ 486 487 static hash_table filename_primary; 488 489 /* The function names hash table. */ 490 491 static hash_table function_name_primary; 492 493 /* The place to keep the recovery address which is used only in cases where 494 we get hopelessly confused by something in the cleaned original text. */ 495 496 static jmp_buf source_confusion_recovery; 497 498 /* A pointer to the current directory filename (used by abspath). */ 499 500 static char *cwd_buffer; 501 502 /* A place to save the read pointer until we are sure that an individual 503 attempt at editing will succeed. */ 504 505 static const char * saved_clean_read_ptr; 506 507 /* A place to save the write pointer until we are sure that an individual 508 attempt at editing will succeed. */ 509 510 static char * saved_repl_write_ptr; 511 512 /* Translate and output an error message. */ 513 static void 514 notice VPARAMS ((const char *msgid, ...)) 515 { 516 VA_OPEN (ap, msgid); 517 VA_FIXEDARG (ap, const char *, msgid); 518 519 vfprintf (stderr, _(msgid), ap); 520 VA_CLOSE (ap); 521 } 522 523 524 /* Make a copy of a string INPUT with size SIZE. */ 525 526 static char * 527 savestring (input, size) 528 const char *input; 529 unsigned int size; 530 { 531 char *output = (char *) xmalloc (size + 1); 532 strcpy (output, input); 533 return output; 534 } 535 536 /* More 'friendly' abort that prints the line and file. 537 config.h can #define abort fancy_abort if you like that sort of thing. */ 538 539 void 540 fancy_abort () 541 { 542 notice ("%s: internal abort\n", pname); 543 exit (FATAL_EXIT_CODE); 544 } 545 546 /* Make a duplicate of the first N bytes of a given string in a newly 547 allocated area. */ 548 549 static char * 550 dupnstr (s, n) 551 const char *s; 552 size_t n; 553 { 554 char *ret_val = (char *) xmalloc (n + 1); 555 556 strncpy (ret_val, s, n); 557 ret_val[n] = '\0'; 558 return ret_val; 559 } 560 561 /* Return a pointer to the first occurrence of s2 within s1 or NULL if s2 562 does not occur within s1. Assume neither s1 nor s2 are null pointers. */ 563 564 static const char * 565 substr (s1, s2) 566 const char *s1; 567 const char *const s2; 568 { 569 for (; *s1 ; s1++) 570 { 571 const char *p1; 572 const char *p2; 573 int c; 574 575 for (p1 = s1, p2 = s2; (c = *p2); p1++, p2++) 576 if (*p1 != c) 577 goto outer; 578 return s1; 579 outer: 580 ; 581 } 582 return 0; 583 } 584 585 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME, 586 retrying if necessary. Return the actual number of bytes read. */ 587 588 static int 589 safe_read (desc, ptr, len) 590 int desc; 591 PTR ptr; 592 int len; 593 { 594 int left = len; 595 while (left > 0) { 596 int nchars = read (desc, ptr, left); 597 if (nchars < 0) 598 { 599 #ifdef EINTR 600 if (errno == EINTR) 601 continue; 602 #endif 603 return nchars; 604 } 605 if (nchars == 0) 606 break; 607 /* Arithmetic on void pointers is a gcc extension. */ 608 ptr = (char *) ptr + nchars; 609 left -= nchars; 610 } 611 return len - left; 612 } 613 614 /* Write LEN bytes at PTR to descriptor DESC, 615 retrying if necessary, and treating any real error as fatal. */ 616 617 static void 618 safe_write (desc, ptr, len, out_fname) 619 int desc; 620 PTR ptr; 621 int len; 622 const char *out_fname; 623 { 624 while (len > 0) { 625 int written = write (desc, ptr, len); 626 if (written < 0) 627 { 628 int errno_val = errno; 629 #ifdef EINTR 630 if (errno_val == EINTR) 631 continue; 632 #endif 633 notice ("%s: error writing file `%s': %s\n", 634 pname, shortpath (NULL, out_fname), xstrerror (errno_val)); 635 return; 636 } 637 /* Arithmetic on void pointers is a gcc extension. */ 638 ptr = (char *) ptr + written; 639 len -= written; 640 } 641 } 642 643 /* Get setup to recover in case the edit we are about to do goes awry. */ 644 645 static void 646 save_pointers () 647 { 648 saved_clean_read_ptr = clean_read_ptr; 649 saved_repl_write_ptr = repl_write_ptr; 650 } 651 652 /* Call this routine to recover our previous state whenever something looks 653 too confusing in the source code we are trying to edit. */ 654 655 static void 656 restore_pointers () 657 { 658 clean_read_ptr = saved_clean_read_ptr; 659 repl_write_ptr = saved_repl_write_ptr; 660 } 661 662 /* Return true if the given character is a valid identifier character. */ 663 664 static int 665 is_id_char (ch) 666 int ch; 667 { 668 return (ISIDNUM (ch) || (ch == '$')); 669 } 670 671 /* Give a message indicating the proper way to invoke this program and then 672 exit with nonzero status. */ 673 674 static void 675 usage () 676 { 677 #ifdef UNPROTOIZE 678 notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n", 679 pname, pname); 680 #else /* !defined (UNPROTOIZE) */ 681 notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n", 682 pname, pname); 683 #endif /* !defined (UNPROTOIZE) */ 684 exit (FATAL_EXIT_CODE); 685 } 686 687 /* Return true if the given filename (assumed to be an absolute filename) 688 designates a file residing anywhere beneath any one of the "system" 689 include directories. */ 690 691 static int 692 in_system_include_dir (path) 693 const char *path; 694 { 695 const struct default_include *p; 696 697 if (! is_abspath (path)) 698 abort (); /* Must be an absolutized filename. */ 699 700 for (p = cpp_include_defaults; p->fname; p++) 701 if (!strncmp (path, p->fname, strlen (p->fname)) 702 && IS_DIR_SEPARATOR (path[strlen (p->fname)])) 703 return 1; 704 return 0; 705 } 706 707 #if 0 708 /* Return true if the given filename designates a file that the user has 709 read access to and for which the user has write access to the containing 710 directory. */ 711 712 static int 713 file_could_be_converted (const char *path) 714 { 715 char *const dir_name = (char *) alloca (strlen (path) + 1); 716 717 if (access (path, R_OK)) 718 return 0; 719 720 { 721 char *dir_last_slash; 722 723 strcpy (dir_name, path); 724 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR); 725 #ifdef DIR_SEPARATOR_2 726 { 727 char *slash; 728 729 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name, 730 DIR_SEPARATOR_2); 731 if (slash) 732 dir_last_slash = slash; 733 } 734 #endif 735 if (dir_last_slash) 736 *dir_last_slash = '\0'; 737 else 738 abort (); /* Should have been an absolutized filename. */ 739 } 740 741 if (access (path, W_OK)) 742 return 0; 743 744 return 1; 745 } 746 747 /* Return true if the given filename designates a file that we are allowed 748 to modify. Files which we should not attempt to modify are (a) "system" 749 include files, and (b) files which the user doesn't have write access to, 750 and (c) files which reside in directories which the user doesn't have 751 write access to. Unless requested to be quiet, give warnings about 752 files that we will not try to convert for one reason or another. An 753 exception is made for "system" include files, which we never try to 754 convert and for which we don't issue the usual warnings. */ 755 756 static int 757 file_normally_convertible (const char *path) 758 { 759 char *const dir_name = alloca (strlen (path) + 1); 760 761 if (in_system_include_dir (path)) 762 return 0; 763 764 { 765 char *dir_last_slash; 766 767 strcpy (dir_name, path); 768 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR); 769 #ifdef DIR_SEPARATOR_2 770 { 771 char *slash; 772 773 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name, 774 DIR_SEPARATOR_2); 775 if (slash) 776 dir_last_slash = slash; 777 } 778 #endif 779 if (dir_last_slash) 780 *dir_last_slash = '\0'; 781 else 782 abort (); /* Should have been an absolutized filename. */ 783 } 784 785 if (access (path, R_OK)) 786 { 787 if (!quiet_flag) 788 notice ("%s: warning: no read access for file `%s'\n", 789 pname, shortpath (NULL, path)); 790 return 0; 791 } 792 793 if (access (path, W_OK)) 794 { 795 if (!quiet_flag) 796 notice ("%s: warning: no write access for file `%s'\n", 797 pname, shortpath (NULL, path)); 798 return 0; 799 } 800 801 if (access (dir_name, W_OK)) 802 { 803 if (!quiet_flag) 804 notice ("%s: warning: no write access for dir containing `%s'\n", 805 pname, shortpath (NULL, path)); 806 return 0; 807 } 808 809 return 1; 810 } 811 #endif /* 0 */ 812 813 #ifndef UNPROTOIZE 814 815 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X 816 file. Return false otherwise. */ 817 818 static int 819 is_syscalls_file (fi_p) 820 const file_info *fi_p; 821 { 822 char const *f = fi_p->hash_entry->symbol; 823 size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1; 824 return sysl <= fl && strcmp (f + fl - sysl, syscalls_filename) == 0; 825 } 826 827 #endif /* !defined (UNPROTOIZE) */ 828 829 /* Check to see if this file will need to have anything done to it on this 830 run. If there is nothing in the given file which both needs conversion 831 and for which we have the necessary stuff to do the conversion, return 832 false. Otherwise, return true. 833 834 Note that (for protoize) it is only valid to call this function *after* 835 the connections between declarations and definitions have all been made 836 by connect_defs_and_decs. */ 837 838 static int 839 needs_to_be_converted (file_p) 840 const file_info *file_p; 841 { 842 const def_dec_info *ddp; 843 844 #ifndef UNPROTOIZE 845 846 if (is_syscalls_file (file_p)) 847 return 0; 848 849 #endif /* !defined (UNPROTOIZE) */ 850 851 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file) 852 853 if ( 854 855 #ifndef UNPROTOIZE 856 857 /* ... and if we a protoizing and this function is in old style ... */ 858 !ddp->prototyped 859 /* ... and if this a definition or is a decl with an associated def ... */ 860 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition)) 861 862 #else /* defined (UNPROTOIZE) */ 863 864 /* ... and if we are unprotoizing and this function is in new style ... */ 865 ddp->prototyped 866 867 #endif /* defined (UNPROTOIZE) */ 868 ) 869 /* ... then the containing file needs converting. */ 870 return -1; 871 return 0; 872 } 873 874 /* Return 1 if the file name NAME is in a directory 875 that should be converted. */ 876 877 static int 878 directory_specified_p (name) 879 const char *name; 880 { 881 struct string_list *p; 882 883 for (p = directory_list; p; p = p->next) 884 if (!strncmp (name, p->name, strlen (p->name)) 885 && IS_DIR_SEPARATOR (name[strlen (p->name)])) 886 { 887 const char *q = name + strlen (p->name) + 1; 888 889 /* If there are more slashes, it's in a subdir, so 890 this match doesn't count. */ 891 while (*q++) 892 if (IS_DIR_SEPARATOR (*(q-1))) 893 goto lose; 894 return 1; 895 896 lose: ; 897 } 898 899 return 0; 900 } 901 902 /* Return 1 if the file named NAME should be excluded from conversion. */ 903 904 static int 905 file_excluded_p (name) 906 const char *name; 907 { 908 struct string_list *p; 909 int len = strlen (name); 910 911 for (p = exclude_list; p; p = p->next) 912 if (!strcmp (name + len - strlen (p->name), p->name) 913 && IS_DIR_SEPARATOR (name[len - strlen (p->name) - 1])) 914 return 1; 915 916 return 0; 917 } 918 919 /* Construct a new element of a string_list. 920 STRING is the new element value, and REST holds the remaining elements. */ 921 922 static struct string_list * 923 string_list_cons (string, rest) 924 const char *string; 925 struct string_list *rest; 926 { 927 struct string_list *temp 928 = (struct string_list *) xmalloc (sizeof (struct string_list)); 929 930 temp->next = rest; 931 temp->name = string; 932 return temp; 933 } 934 935 /* ??? The GNU convention for mentioning function args in its comments 936 is to capitalize them. So change "hash_tab_p" to HASH_TAB_P below. 937 Likewise for all the other functions. */ 938 939 /* Given a hash table, apply some function to each node in the table. The 940 table to traverse is given as the "hash_tab_p" argument, and the 941 function to be applied to each node in the table is given as "func" 942 argument. */ 943 944 static void 945 visit_each_hash_node (hash_tab_p, func) 946 const hash_table_entry *hash_tab_p; 947 void (*func) PARAMS ((const hash_table_entry *)); 948 { 949 const hash_table_entry *primary; 950 951 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++) 952 if (primary->symbol) 953 { 954 hash_table_entry *second; 955 956 (*func)(primary); 957 for (second = primary->hash_next; second; second = second->hash_next) 958 (*func) (second); 959 } 960 } 961 962 /* Initialize all of the fields of a new hash table entry, pointed 963 to by the "p" parameter. Note that the space to hold the entry 964 is assumed to have already been allocated before this routine is 965 called. */ 966 967 static hash_table_entry * 968 add_symbol (p, s) 969 hash_table_entry *p; 970 const char *s; 971 { 972 p->hash_next = NULL; 973 p->symbol = xstrdup (s); 974 p->ddip = NULL; 975 p->fip = NULL; 976 return p; 977 } 978 979 /* Look for a particular function name or filename in the particular 980 hash table indicated by "hash_tab_p". If the name is not in the 981 given hash table, add it. Either way, return a pointer to the 982 hash table entry for the given name. */ 983 984 static hash_table_entry * 985 lookup (hash_tab_p, search_symbol) 986 hash_table_entry *hash_tab_p; 987 const char *search_symbol; 988 { 989 int hash_value = 0; 990 const char *search_symbol_char_p = search_symbol; 991 hash_table_entry *p; 992 993 while (*search_symbol_char_p) 994 hash_value += *search_symbol_char_p++; 995 hash_value &= hash_mask; 996 p = &hash_tab_p[hash_value]; 997 if (! p->symbol) 998 return add_symbol (p, search_symbol); 999 if (!strcmp (p->symbol, search_symbol)) 1000 return p; 1001 while (p->hash_next) 1002 { 1003 p = p->hash_next; 1004 if (!strcmp (p->symbol, search_symbol)) 1005 return p; 1006 } 1007 p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry)); 1008 p = p->hash_next; 1009 return add_symbol (p, search_symbol); 1010 } 1011 1012 /* Throw a def/dec record on the junk heap. 1013 1014 Also, since we are not using this record anymore, free up all of the 1015 stuff it pointed to. */ 1016 1017 static void 1018 free_def_dec (p) 1019 def_dec_info *p; 1020 { 1021 free ((NONCONST PTR) p->ansi_decl); 1022 1023 #ifndef UNPROTOIZE 1024 { 1025 const f_list_chain_item * curr; 1026 const f_list_chain_item * next; 1027 1028 for (curr = p->f_list_chain; curr; curr = next) 1029 { 1030 next = curr->chain_next; 1031 free ((NONCONST PTR) curr); 1032 } 1033 } 1034 #endif /* !defined (UNPROTOIZE) */ 1035 1036 free (p); 1037 } 1038 1039 /* Unexpand as many macro symbol as we can find. 1040 1041 If the given line must be unexpanded, make a copy of it in the heap and 1042 return a pointer to the unexpanded copy. Otherwise return NULL. */ 1043 1044 static char * 1045 unexpand_if_needed (aux_info_line) 1046 const char *aux_info_line; 1047 { 1048 static char *line_buf = 0; 1049 static int line_buf_size = 0; 1050 const unexpansion *unexp_p; 1051 int got_unexpanded = 0; 1052 const char *s; 1053 char *copy_p = line_buf; 1054 1055 if (line_buf == 0) 1056 { 1057 line_buf_size = 1024; 1058 line_buf = (char *) xmalloc (line_buf_size); 1059 } 1060 1061 copy_p = line_buf; 1062 1063 /* Make a copy of the input string in line_buf, expanding as necessary. */ 1064 1065 for (s = aux_info_line; *s != '\n'; ) 1066 { 1067 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++) 1068 { 1069 const char *in_p = unexp_p->expanded; 1070 size_t len = strlen (in_p); 1071 1072 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len])) 1073 { 1074 int size = strlen (unexp_p->contracted); 1075 got_unexpanded = 1; 1076 if (copy_p + size - line_buf >= line_buf_size) 1077 { 1078 int offset = copy_p - line_buf; 1079 line_buf_size *= 2; 1080 line_buf_size += size; 1081 line_buf = (char *) xrealloc (line_buf, line_buf_size); 1082 copy_p = line_buf + offset; 1083 } 1084 strcpy (copy_p, unexp_p->contracted); 1085 copy_p += size; 1086 1087 /* Assume that there will not be another replacement required 1088 within the text just replaced. */ 1089 1090 s += len; 1091 goto continue_outer; 1092 } 1093 } 1094 if (copy_p - line_buf == line_buf_size) 1095 { 1096 int offset = copy_p - line_buf; 1097 line_buf_size *= 2; 1098 line_buf = (char *) xrealloc (line_buf, line_buf_size); 1099 copy_p = line_buf + offset; 1100 } 1101 *copy_p++ = *s++; 1102 continue_outer: ; 1103 } 1104 if (copy_p + 2 - line_buf >= line_buf_size) 1105 { 1106 int offset = copy_p - line_buf; 1107 line_buf_size *= 2; 1108 line_buf = (char *) xrealloc (line_buf, line_buf_size); 1109 copy_p = line_buf + offset; 1110 } 1111 *copy_p++ = '\n'; 1112 *copy_p = '\0'; 1113 1114 return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0); 1115 } 1116 1117 /* Return 1 if pathname is absolute. */ 1118 1119 static int 1120 is_abspath (path) 1121 const char *path; 1122 { 1123 return (IS_DIR_SEPARATOR (path[0]) 1124 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 1125 /* Check for disk name on MS-DOS-based systems. */ 1126 || (path[0] && path[1] == ':' && IS_DIR_SEPARATOR (path[2])) 1127 #endif 1128 ); 1129 } 1130 1131 /* Return the absolutized filename for the given relative 1132 filename. Note that if that filename is already absolute, it may 1133 still be returned in a modified form because this routine also 1134 eliminates redundant slashes and single dots and eliminates double 1135 dots to get a shortest possible filename from the given input 1136 filename. The absolutization of relative filenames is made by 1137 assuming that the given filename is to be taken as relative to 1138 the first argument (cwd) or to the current directory if cwd is 1139 NULL. */ 1140 1141 static char * 1142 abspath (cwd, rel_filename) 1143 const char *cwd; 1144 const char *rel_filename; 1145 { 1146 /* Setup the current working directory as needed. */ 1147 const char *const cwd2 = (cwd) ? cwd : cwd_buffer; 1148 char *const abs_buffer 1149 = (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 2); 1150 char *endp = abs_buffer; 1151 char *outp, *inp; 1152 1153 /* Copy the filename (possibly preceded by the current working 1154 directory name) into the absolutization buffer. */ 1155 1156 { 1157 const char *src_p; 1158 1159 if (! is_abspath (rel_filename)) 1160 { 1161 src_p = cwd2; 1162 while ((*endp++ = *src_p++)) 1163 continue; 1164 *(endp-1) = DIR_SEPARATOR; /* overwrite null */ 1165 } 1166 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 1167 else if (IS_DIR_SEPARATOR (rel_filename[0])) 1168 { 1169 /* A path starting with a directory separator is considered absolute 1170 for dos based filesystems, but it's really not -- it's just the 1171 convention used throughout GCC and it works. However, in this 1172 case, we still need to prepend the drive spec from cwd_buffer. */ 1173 *endp++ = cwd2[0]; 1174 *endp++ = cwd2[1]; 1175 } 1176 #endif 1177 src_p = rel_filename; 1178 while ((*endp++ = *src_p++)) 1179 continue; 1180 } 1181 1182 /* Now make a copy of abs_buffer into abs_buffer, shortening the 1183 filename (by taking out slashes and dots) as we go. */ 1184 1185 outp = inp = abs_buffer; 1186 *outp++ = *inp++; /* copy first slash */ 1187 #if defined (apollo) || defined (_WIN32) || defined (__INTERIX) 1188 if (IS_DIR_SEPARATOR (inp[0])) 1189 *outp++ = *inp++; /* copy second slash */ 1190 #endif 1191 for (;;) 1192 { 1193 if (!inp[0]) 1194 break; 1195 else if (IS_DIR_SEPARATOR (inp[0]) && IS_DIR_SEPARATOR (outp[-1])) 1196 { 1197 inp++; 1198 continue; 1199 } 1200 else if (inp[0] == '.' && IS_DIR_SEPARATOR (outp[-1])) 1201 { 1202 if (!inp[1]) 1203 break; 1204 else if (IS_DIR_SEPARATOR (inp[1])) 1205 { 1206 inp += 2; 1207 continue; 1208 } 1209 else if ((inp[1] == '.') && (inp[2] == 0 1210 || IS_DIR_SEPARATOR (inp[2]))) 1211 { 1212 inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2; 1213 outp -= 2; 1214 while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*outp)) 1215 outp--; 1216 if (outp < abs_buffer) 1217 { 1218 /* Catch cases like /.. where we try to backup to a 1219 point above the absolute root of the logical file 1220 system. */ 1221 1222 notice ("%s: invalid file name: %s\n", 1223 pname, rel_filename); 1224 exit (FATAL_EXIT_CODE); 1225 } 1226 *++outp = '\0'; 1227 continue; 1228 } 1229 } 1230 *outp++ = *inp++; 1231 } 1232 1233 /* On exit, make sure that there is a trailing null, and make sure that 1234 the last character of the returned string is *not* a slash. */ 1235 1236 *outp = '\0'; 1237 if (IS_DIR_SEPARATOR (outp[-1])) 1238 *--outp = '\0'; 1239 1240 /* Make a copy (in the heap) of the stuff left in the absolutization 1241 buffer and return a pointer to the copy. */ 1242 1243 return savestring (abs_buffer, outp - abs_buffer); 1244 } 1245 1246 /* Given a filename (and possibly a directory name from which the filename 1247 is relative) return a string which is the shortest possible 1248 equivalent for the corresponding full (absolutized) filename. The 1249 shortest possible equivalent may be constructed by converting the 1250 absolutized filename to be a relative filename (i.e. relative to 1251 the actual current working directory). However if a relative filename 1252 is longer, then the full absolute filename is returned. 1253 1254 KNOWN BUG: 1255 1256 Note that "simple-minded" conversion of any given type of filename (either 1257 relative or absolute) may not result in a valid equivalent filename if any 1258 subpart of the original filename is actually a symbolic link. */ 1259 1260 static const char * 1261 shortpath (cwd, filename) 1262 const char *cwd; 1263 const char *filename; 1264 { 1265 char *rel_buffer; 1266 char *rel_buf_p; 1267 char *cwd_p = cwd_buffer; 1268 char *path_p; 1269 int unmatched_slash_count = 0; 1270 size_t filename_len = strlen (filename); 1271 1272 path_p = abspath (cwd, filename); 1273 rel_buf_p = rel_buffer = (char *) xmalloc (filename_len); 1274 1275 while (*cwd_p && IS_SAME_PATH_CHAR (*cwd_p, *path_p)) 1276 { 1277 cwd_p++; 1278 path_p++; 1279 } 1280 if (!*cwd_p && (!*path_p || IS_DIR_SEPARATOR (*path_p))) 1281 { 1282 /* whole pwd matched */ 1283 if (!*path_p) /* input *is* the current path! */ 1284 return "."; 1285 else 1286 return ++path_p; 1287 } 1288 else 1289 { 1290 if (*path_p) 1291 { 1292 --cwd_p; 1293 --path_p; 1294 while (! IS_DIR_SEPARATOR (*cwd_p)) /* backup to last slash */ 1295 { 1296 --cwd_p; 1297 --path_p; 1298 } 1299 cwd_p++; 1300 path_p++; 1301 unmatched_slash_count++; 1302 } 1303 1304 /* Find out how many directory levels in cwd were *not* matched. */ 1305 while (*cwd_p++) 1306 if (IS_DIR_SEPARATOR (*(cwd_p-1))) 1307 unmatched_slash_count++; 1308 1309 /* Now we know how long the "short name" will be. 1310 Reject it if longer than the input. */ 1311 if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len) 1312 return filename; 1313 1314 /* For each of them, put a `../' at the beginning of the short name. */ 1315 while (unmatched_slash_count--) 1316 { 1317 /* Give up if the result gets to be longer 1318 than the absolute path name. */ 1319 if (rel_buffer + filename_len <= rel_buf_p + 3) 1320 return filename; 1321 *rel_buf_p++ = '.'; 1322 *rel_buf_p++ = '.'; 1323 *rel_buf_p++ = DIR_SEPARATOR; 1324 } 1325 1326 /* Then tack on the unmatched part of the desired file's name. */ 1327 do 1328 { 1329 if (rel_buffer + filename_len <= rel_buf_p) 1330 return filename; 1331 } 1332 while ((*rel_buf_p++ = *path_p++)); 1333 1334 --rel_buf_p; 1335 if (IS_DIR_SEPARATOR (*(rel_buf_p-1))) 1336 *--rel_buf_p = '\0'; 1337 return rel_buffer; 1338 } 1339 } 1340 1341 /* Lookup the given filename in the hash table for filenames. If it is a 1342 new one, then the hash table info pointer will be null. In this case, 1343 we create a new file_info record to go with the filename, and we initialize 1344 that record with some reasonable values. */ 1345 1346 /* FILENAME was const, but that causes a warning on AIX when calling stat. 1347 That is probably a bug in AIX, but might as well avoid the warning. */ 1348 1349 static file_info * 1350 find_file (filename, do_not_stat) 1351 const char *filename; 1352 int do_not_stat; 1353 { 1354 hash_table_entry *hash_entry_p; 1355 1356 hash_entry_p = lookup (filename_primary, filename); 1357 if (hash_entry_p->fip) 1358 return hash_entry_p->fip; 1359 else 1360 { 1361 struct stat stat_buf; 1362 file_info *file_p = (file_info *) xmalloc (sizeof (file_info)); 1363 1364 /* If we cannot get status on any given source file, give a warning 1365 and then just set its time of last modification to infinity. */ 1366 1367 if (do_not_stat) 1368 stat_buf.st_mtime = (time_t) 0; 1369 else 1370 { 1371 if (stat (filename, &stat_buf) == -1) 1372 { 1373 int errno_val = errno; 1374 notice ("%s: %s: can't get status: %s\n", 1375 pname, shortpath (NULL, filename), 1376 xstrerror (errno_val)); 1377 stat_buf.st_mtime = (time_t) -1; 1378 } 1379 } 1380 1381 hash_entry_p->fip = file_p; 1382 file_p->hash_entry = hash_entry_p; 1383 file_p->defs_decs = NULL; 1384 file_p->mtime = stat_buf.st_mtime; 1385 return file_p; 1386 } 1387 } 1388 1389 /* Generate a fatal error because some part of the aux_info file is 1390 messed up. */ 1391 1392 static void 1393 aux_info_corrupted () 1394 { 1395 notice ("\n%s: fatal error: aux info file corrupted at line %d\n", 1396 pname, current_aux_info_lineno); 1397 exit (FATAL_EXIT_CODE); 1398 } 1399 1400 /* ??? This comment is vague. Say what the condition is for. */ 1401 /* Check to see that a condition is true. This is kind of like an assert. */ 1402 1403 static void 1404 check_aux_info (cond) 1405 int cond; 1406 { 1407 if (! cond) 1408 aux_info_corrupted (); 1409 } 1410 1411 /* Given a pointer to the closing right parenthesis for a particular formals 1412 list (in an aux_info file) find the corresponding left parenthesis and 1413 return a pointer to it. */ 1414 1415 static const char * 1416 find_corresponding_lparen (p) 1417 const char *p; 1418 { 1419 const char *q; 1420 int paren_depth; 1421 1422 for (paren_depth = 1, q = p-1; paren_depth; q--) 1423 { 1424 switch (*q) 1425 { 1426 case ')': 1427 paren_depth++; 1428 break; 1429 case '(': 1430 paren_depth--; 1431 break; 1432 } 1433 } 1434 return ++q; 1435 } 1436 1437 /* Given a line from an aux info file, and a time at which the aux info 1438 file it came from was created, check to see if the item described in 1439 the line comes from a file which has been modified since the aux info 1440 file was created. If so, return nonzero, else return zero. */ 1441 1442 static int 1443 referenced_file_is_newer (l, aux_info_mtime) 1444 const char *l; 1445 time_t aux_info_mtime; 1446 { 1447 const char *p; 1448 file_info *fi_p; 1449 char *filename; 1450 1451 check_aux_info (l[0] == '/'); 1452 check_aux_info (l[1] == '*'); 1453 check_aux_info (l[2] == ' '); 1454 1455 { 1456 const char *filename_start = p = l + 3; 1457 1458 while (*p != ':' 1459 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 1460 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1))) 1461 #endif 1462 ) 1463 p++; 1464 filename = (char *) alloca ((size_t) (p - filename_start) + 1); 1465 strncpy (filename, filename_start, (size_t) (p - filename_start)); 1466 filename[p-filename_start] = '\0'; 1467 } 1468 1469 /* Call find_file to find the file_info record associated with the file 1470 which contained this particular def or dec item. Note that this call 1471 may cause a new file_info record to be created if this is the first time 1472 that we have ever known about this particular file. */ 1473 1474 fi_p = find_file (abspath (invocation_filename, filename), 0); 1475 1476 return (fi_p->mtime > aux_info_mtime); 1477 } 1478 1479 /* Given a line of info from the aux_info file, create a new 1480 def_dec_info record to remember all of the important information about 1481 a function definition or declaration. 1482 1483 Link this record onto the list of such records for the particular file in 1484 which it occurred in proper (descending) line number order (for now). 1485 1486 If there is an identical record already on the list for the file, throw 1487 this one away. Doing so takes care of the (useless and troublesome) 1488 duplicates which are bound to crop up due to multiple inclusions of any 1489 given individual header file. 1490 1491 Finally, link the new def_dec record onto the list of such records 1492 pertaining to this particular function name. */ 1493 1494 static void 1495 save_def_or_dec (l, is_syscalls) 1496 const char *l; 1497 int is_syscalls; 1498 { 1499 const char *p; 1500 const char *semicolon_p; 1501 def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info)); 1502 1503 #ifndef UNPROTOIZE 1504 def_dec_p->written = 0; 1505 #endif /* !defined (UNPROTOIZE) */ 1506 1507 /* Start processing the line by picking off 5 pieces of information from 1508 the left hand end of the line. These are filename, line number, 1509 new/old/implicit flag (new = ANSI prototype format), definition or 1510 declaration flag, and extern/static flag). */ 1511 1512 check_aux_info (l[0] == '/'); 1513 check_aux_info (l[1] == '*'); 1514 check_aux_info (l[2] == ' '); 1515 1516 { 1517 const char *filename_start = p = l + 3; 1518 char *filename; 1519 1520 while (*p != ':' 1521 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 1522 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1))) 1523 #endif 1524 ) 1525 p++; 1526 filename = (char *) alloca ((size_t) (p - filename_start) + 1); 1527 strncpy (filename, filename_start, (size_t) (p - filename_start)); 1528 filename[p-filename_start] = '\0'; 1529 1530 /* Call find_file to find the file_info record associated with the file 1531 which contained this particular def or dec item. Note that this call 1532 may cause a new file_info record to be created if this is the first time 1533 that we have ever known about this particular file. 1534 1535 Note that we started out by forcing all of the base source file names 1536 (i.e. the names of the aux_info files with the .X stripped off) into the 1537 filenames hash table, and we simultaneously setup file_info records for 1538 all of these base file names (even if they may be useless later). 1539 The file_info records for all of these "base" file names (properly) 1540 act as file_info records for the "original" (i.e. un-included) files 1541 which were submitted to gcc for compilation (when the -aux-info 1542 option was used). */ 1543 1544 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls); 1545 } 1546 1547 { 1548 const char *line_number_start = ++p; 1549 char line_number[10]; 1550 1551 while (*p != ':' 1552 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 1553 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1))) 1554 #endif 1555 ) 1556 p++; 1557 strncpy (line_number, line_number_start, (size_t) (p - line_number_start)); 1558 line_number[p-line_number_start] = '\0'; 1559 def_dec_p->line = atoi (line_number); 1560 } 1561 1562 /* Check that this record describes a new-style, old-style, or implicit 1563 definition or declaration. */ 1564 1565 p++; /* Skip over the `:'. */ 1566 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I')); 1567 1568 /* Is this a new style (ANSI prototyped) definition or declaration? */ 1569 1570 def_dec_p->prototyped = (*p == 'N'); 1571 1572 #ifndef UNPROTOIZE 1573 1574 /* Is this an implicit declaration? */ 1575 1576 def_dec_p->is_implicit = (*p == 'I'); 1577 1578 #endif /* !defined (UNPROTOIZE) */ 1579 1580 p++; 1581 1582 check_aux_info ((*p == 'C') || (*p == 'F')); 1583 1584 /* Is this item a function definition (F) or a declaration (C). Note that 1585 we treat item taken from the syscalls file as though they were function 1586 definitions regardless of what the stuff in the file says. */ 1587 1588 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls); 1589 1590 #ifndef UNPROTOIZE 1591 def_dec_p->definition = 0; /* Fill this in later if protoizing. */ 1592 #endif /* !defined (UNPROTOIZE) */ 1593 1594 check_aux_info (*p++ == ' '); 1595 check_aux_info (*p++ == '*'); 1596 check_aux_info (*p++ == '/'); 1597 check_aux_info (*p++ == ' '); 1598 1599 #ifdef UNPROTOIZE 1600 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6))); 1601 #else /* !defined (UNPROTOIZE) */ 1602 if (!strncmp (p, "static", 6)) 1603 def_dec_p->is_static = -1; 1604 else if (!strncmp (p, "extern", 6)) 1605 def_dec_p->is_static = 0; 1606 else 1607 check_aux_info (0); /* Didn't find either `extern' or `static'. */ 1608 #endif /* !defined (UNPROTOIZE) */ 1609 1610 { 1611 const char *ansi_start = p; 1612 1613 p += 6; /* Pass over the "static" or "extern". */ 1614 1615 /* We are now past the initial stuff. Search forward from here to find 1616 the terminating semicolon that should immediately follow the entire 1617 ANSI format function declaration. */ 1618 1619 while (*++p != ';') 1620 continue; 1621 1622 semicolon_p = p; 1623 1624 /* Make a copy of the ansi declaration part of the line from the aux_info 1625 file. */ 1626 1627 def_dec_p->ansi_decl 1628 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start)); 1629 1630 /* Backup and point at the final right paren of the final argument list. */ 1631 1632 p--; 1633 1634 #ifndef UNPROTOIZE 1635 def_dec_p->f_list_chain = NULL; 1636 #endif /* !defined (UNPROTOIZE) */ 1637 1638 while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--; 1639 if (*p != ')') 1640 { 1641 free_def_dec (def_dec_p); 1642 return; 1643 } 1644 } 1645 1646 /* Now isolate a whole set of formal argument lists, one-by-one. Normally, 1647 there will only be one list to isolate, but there could be more. */ 1648 1649 def_dec_p->f_list_count = 0; 1650 1651 for (;;) 1652 { 1653 const char *left_paren_p = find_corresponding_lparen (p); 1654 #ifndef UNPROTOIZE 1655 { 1656 f_list_chain_item *cip 1657 = (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item)); 1658 1659 cip->formals_list 1660 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1))); 1661 1662 /* Add the new chain item at the head of the current list. */ 1663 1664 cip->chain_next = def_dec_p->f_list_chain; 1665 def_dec_p->f_list_chain = cip; 1666 } 1667 #endif /* !defined (UNPROTOIZE) */ 1668 def_dec_p->f_list_count++; 1669 1670 p = left_paren_p - 2; 1671 1672 /* p must now point either to another right paren, or to the last 1673 character of the name of the function that was declared/defined. 1674 If p points to another right paren, then this indicates that we 1675 are dealing with multiple formals lists. In that case, there 1676 really should be another right paren preceding this right paren. */ 1677 1678 if (*p != ')') 1679 break; 1680 else 1681 check_aux_info (*--p == ')'); 1682 } 1683 1684 1685 { 1686 const char *past_fn = p + 1; 1687 1688 check_aux_info (*past_fn == ' '); 1689 1690 /* Scan leftwards over the identifier that names the function. */ 1691 1692 while (is_id_char (*p)) 1693 p--; 1694 p++; 1695 1696 /* p now points to the leftmost character of the function name. */ 1697 1698 { 1699 char *fn_string = (char *) alloca (past_fn - p + 1); 1700 1701 strncpy (fn_string, p, (size_t) (past_fn - p)); 1702 fn_string[past_fn-p] = '\0'; 1703 def_dec_p->hash_entry = lookup (function_name_primary, fn_string); 1704 } 1705 } 1706 1707 /* Look at all of the defs and decs for this function name that we have 1708 collected so far. If there is already one which is at the same 1709 line number in the same file, then we can discard this new def_dec_info 1710 record. 1711 1712 As an extra assurance that any such pair of (nominally) identical 1713 function declarations are in fact identical, we also compare the 1714 ansi_decl parts of the lines from the aux_info files just to be on 1715 the safe side. 1716 1717 This comparison will fail if (for instance) the user was playing 1718 messy games with the preprocessor which ultimately causes one 1719 function declaration in one header file to look differently when 1720 that file is included by two (or more) other files. */ 1721 1722 { 1723 const def_dec_info *other; 1724 1725 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func) 1726 { 1727 if (def_dec_p->line == other->line && def_dec_p->file == other->file) 1728 { 1729 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl)) 1730 { 1731 notice ("%s:%d: declaration of function `%s' takes different forms\n", 1732 def_dec_p->file->hash_entry->symbol, 1733 def_dec_p->line, 1734 def_dec_p->hash_entry->symbol); 1735 exit (FATAL_EXIT_CODE); 1736 } 1737 free_def_dec (def_dec_p); 1738 return; 1739 } 1740 } 1741 } 1742 1743 #ifdef UNPROTOIZE 1744 1745 /* If we are doing unprotoizing, we must now setup the pointers that will 1746 point to the K&R name list and to the K&R argument declarations list. 1747 1748 Note that if this is only a function declaration, then we should not 1749 expect to find any K&R style formals list following the ANSI-style 1750 formals list. This is because GCC knows that such information is 1751 useless in the case of function declarations (function definitions 1752 are a different story however). 1753 1754 Since we are unprotoizing, we don't need any such lists anyway. 1755 All we plan to do is to delete all characters between ()'s in any 1756 case. */ 1757 1758 def_dec_p->formal_names = NULL; 1759 def_dec_p->formal_decls = NULL; 1760 1761 if (def_dec_p->is_func_def) 1762 { 1763 p = semicolon_p; 1764 check_aux_info (*++p == ' '); 1765 check_aux_info (*++p == '/'); 1766 check_aux_info (*++p == '*'); 1767 check_aux_info (*++p == ' '); 1768 check_aux_info (*++p == '('); 1769 1770 { 1771 const char *kr_names_start = ++p; /* Point just inside '('. */ 1772 1773 while (*p++ != ')') 1774 continue; 1775 p--; /* point to closing right paren */ 1776 1777 /* Make a copy of the K&R parameter names list. */ 1778 1779 def_dec_p->formal_names 1780 = dupnstr (kr_names_start, (size_t) (p - kr_names_start)); 1781 } 1782 1783 check_aux_info (*++p == ' '); 1784 p++; 1785 1786 /* p now points to the first character of the K&R style declarations 1787 list (if there is one) or to the star-slash combination that ends 1788 the comment in which such lists get embedded. */ 1789 1790 /* Make a copy of the K&R formal decls list and set the def_dec record 1791 to point to it. */ 1792 1793 if (*p == '*') /* Are there no K&R declarations? */ 1794 { 1795 check_aux_info (*++p == '/'); 1796 def_dec_p->formal_decls = ""; 1797 } 1798 else 1799 { 1800 const char *kr_decls_start = p; 1801 1802 while (p[0] != '*' || p[1] != '/') 1803 p++; 1804 p--; 1805 1806 check_aux_info (*p == ' '); 1807 1808 def_dec_p->formal_decls 1809 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start)); 1810 } 1811 1812 /* Handle a special case. If we have a function definition marked as 1813 being in "old" style, and if its formal names list is empty, then 1814 it may actually have the string "void" in its real formals list 1815 in the original source code. Just to make sure, we will get setup 1816 to convert such things anyway. 1817 1818 This kludge only needs to be here because of an insurmountable 1819 problem with generating .X files. */ 1820 1821 if (!def_dec_p->prototyped && !*def_dec_p->formal_names) 1822 def_dec_p->prototyped = 1; 1823 } 1824 1825 /* Since we are unprotoizing, if this item is already in old (K&R) style, 1826 we can just ignore it. If that is true, throw away the itme now. */ 1827 1828 if (!def_dec_p->prototyped) 1829 { 1830 free_def_dec (def_dec_p); 1831 return; 1832 } 1833 1834 #endif /* defined (UNPROTOIZE) */ 1835 1836 /* Add this record to the head of the list of records pertaining to this 1837 particular function name. */ 1838 1839 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip; 1840 def_dec_p->hash_entry->ddip = def_dec_p; 1841 1842 /* Add this new def_dec_info record to the sorted list of def_dec_info 1843 records for this file. Note that we don't have to worry about duplicates 1844 (caused by multiple inclusions of header files) here because we have 1845 already eliminated duplicates above. */ 1846 1847 if (!def_dec_p->file->defs_decs) 1848 { 1849 def_dec_p->file->defs_decs = def_dec_p; 1850 def_dec_p->next_in_file = NULL; 1851 } 1852 else 1853 { 1854 int line = def_dec_p->line; 1855 const def_dec_info *prev = NULL; 1856 const def_dec_info *curr = def_dec_p->file->defs_decs; 1857 const def_dec_info *next = curr->next_in_file; 1858 1859 while (next && (line < curr->line)) 1860 { 1861 prev = curr; 1862 curr = next; 1863 next = next->next_in_file; 1864 } 1865 if (line >= curr->line) 1866 { 1867 def_dec_p->next_in_file = curr; 1868 if (prev) 1869 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p; 1870 else 1871 def_dec_p->file->defs_decs = def_dec_p; 1872 } 1873 else /* assert (next == NULL); */ 1874 { 1875 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p; 1876 /* assert (next == NULL); */ 1877 def_dec_p->next_in_file = next; 1878 } 1879 } 1880 } 1881 1882 /* Set up the vector COMPILE_PARAMS which is the argument list for running GCC. 1883 Also set input_file_name_index and aux_info_file_name_index 1884 to the indices of the slots where the file names should go. */ 1885 1886 /* We initialize the vector by removing -g, -O, -S, -c, and -o options, 1887 and adding '-aux-info AUXFILE -S -o /dev/null INFILE' at the end. */ 1888 1889 static void 1890 munge_compile_params (params_list) 1891 const char *params_list; 1892 { 1893 /* Build up the contents in a temporary vector 1894 that is so big that to has to be big enough. */ 1895 const char **temp_params 1896 = (const char **) alloca ((strlen (params_list) + 8) * sizeof (char *)); 1897 int param_count = 0; 1898 const char *param; 1899 struct stat st; 1900 1901 temp_params[param_count++] = compiler_file_name; 1902 for (;;) 1903 { 1904 while (ISSPACE ((const unsigned char)*params_list)) 1905 params_list++; 1906 if (!*params_list) 1907 break; 1908 param = params_list; 1909 while (*params_list && !ISSPACE ((const unsigned char)*params_list)) 1910 params_list++; 1911 if (param[0] != '-') 1912 temp_params[param_count++] 1913 = dupnstr (param, (size_t) (params_list - param)); 1914 else 1915 { 1916 switch (param[1]) 1917 { 1918 case 'g': 1919 case 'O': 1920 case 'S': 1921 case 'c': 1922 break; /* Don't copy these. */ 1923 case 'o': 1924 while (ISSPACE ((const unsigned char)*params_list)) 1925 params_list++; 1926 while (*params_list 1927 && !ISSPACE ((const unsigned char)*params_list)) 1928 params_list++; 1929 break; 1930 default: 1931 temp_params[param_count++] 1932 = dupnstr (param, (size_t) (params_list - param)); 1933 } 1934 } 1935 if (!*params_list) 1936 break; 1937 } 1938 temp_params[param_count++] = "-aux-info"; 1939 1940 /* Leave room for the aux-info file name argument. */ 1941 aux_info_file_name_index = param_count; 1942 temp_params[param_count++] = NULL; 1943 1944 temp_params[param_count++] = "-S"; 1945 temp_params[param_count++] = "-o"; 1946 1947 if ((stat (HOST_BIT_BUCKET, &st) == 0) 1948 && (!S_ISDIR (st.st_mode)) 1949 && (access (HOST_BIT_BUCKET, W_OK) == 0)) 1950 temp_params[param_count++] = HOST_BIT_BUCKET; 1951 else 1952 /* FIXME: This is hardly likely to be right, if HOST_BIT_BUCKET is not 1953 writable. But until this is rejigged to use make_temp_file(), this 1954 is the best we can do. */ 1955 temp_params[param_count++] = "/dev/null"; 1956 1957 /* Leave room for the input file name argument. */ 1958 input_file_name_index = param_count; 1959 temp_params[param_count++] = NULL; 1960 /* Terminate the list. */ 1961 temp_params[param_count++] = NULL; 1962 1963 /* Make a copy of the compile_params in heap space. */ 1964 1965 compile_params 1966 = (const char **) xmalloc (sizeof (char *) * (param_count+1)); 1967 memcpy (compile_params, temp_params, sizeof (char *) * param_count); 1968 } 1969 1970 /* Do a recompilation for the express purpose of generating a new aux_info 1971 file to go with a specific base source file. 1972 1973 The result is a boolean indicating success. */ 1974 1975 static int 1976 gen_aux_info_file (base_filename) 1977 const char *base_filename; 1978 { 1979 if (!input_file_name_index) 1980 munge_compile_params (""); 1981 1982 /* Store the full source file name in the argument vector. */ 1983 compile_params[input_file_name_index] = shortpath (NULL, base_filename); 1984 /* Add .X to source file name to get aux-info file name. */ 1985 compile_params[aux_info_file_name_index] = 1986 concat (compile_params[input_file_name_index], aux_info_suffix, NULL); 1987 1988 if (!quiet_flag) 1989 notice ("%s: compiling `%s'\n", 1990 pname, compile_params[input_file_name_index]); 1991 1992 { 1993 char *errmsg_fmt, *errmsg_arg; 1994 int wait_status, pid; 1995 1996 pid = pexecute (compile_params[0], (char * const *) compile_params, 1997 pname, NULL, &errmsg_fmt, &errmsg_arg, 1998 PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH); 1999 2000 if (pid == -1) 2001 { 2002 int errno_val = errno; 2003 fprintf (stderr, "%s: ", pname); 2004 fprintf (stderr, errmsg_fmt, errmsg_arg); 2005 fprintf (stderr, ": %s\n", xstrerror (errno_val)); 2006 return 0; 2007 } 2008 2009 pid = pwait (pid, &wait_status, 0); 2010 if (pid == -1) 2011 { 2012 notice ("%s: wait: %s\n", pname, xstrerror (errno)); 2013 return 0; 2014 } 2015 if (WIFSIGNALED (wait_status)) 2016 { 2017 notice ("%s: subprocess got fatal signal %d\n", 2018 pname, WTERMSIG (wait_status)); 2019 return 0; 2020 } 2021 if (WIFEXITED (wait_status)) 2022 { 2023 if (WEXITSTATUS (wait_status) != 0) 2024 { 2025 notice ("%s: %s exited with status %d\n", 2026 pname, compile_params[0], WEXITSTATUS (wait_status)); 2027 return 0; 2028 } 2029 return 1; 2030 } 2031 abort (); 2032 } 2033 } 2034 2035 /* Read in all of the information contained in a single aux_info file. 2036 Save all of the important stuff for later. */ 2037 2038 static void 2039 process_aux_info_file (base_source_filename, keep_it, is_syscalls) 2040 const char *base_source_filename; 2041 int keep_it; 2042 int is_syscalls; 2043 { 2044 size_t base_len = strlen (base_source_filename); 2045 char * aux_info_filename 2046 = (char *) alloca (base_len + strlen (aux_info_suffix) + 1); 2047 char *aux_info_base; 2048 char *aux_info_limit; 2049 char *aux_info_relocated_name; 2050 const char *aux_info_second_line; 2051 time_t aux_info_mtime; 2052 size_t aux_info_size; 2053 int must_create; 2054 2055 /* Construct the aux_info filename from the base source filename. */ 2056 2057 strcpy (aux_info_filename, base_source_filename); 2058 strcat (aux_info_filename, aux_info_suffix); 2059 2060 /* Check that the aux_info file exists and is readable. If it does not 2061 exist, try to create it (once only). */ 2062 2063 /* If file doesn't exist, set must_create. 2064 Likewise if it exists and we can read it but it is obsolete. 2065 Otherwise, report an error. */ 2066 must_create = 0; 2067 2068 /* Come here with must_create set to 1 if file is out of date. */ 2069 start_over: ; 2070 2071 if (access (aux_info_filename, R_OK) == -1) 2072 { 2073 if (errno == ENOENT) 2074 { 2075 if (is_syscalls) 2076 { 2077 notice ("%s: warning: missing SYSCALLS file `%s'\n", 2078 pname, aux_info_filename); 2079 return; 2080 } 2081 must_create = 1; 2082 } 2083 else 2084 { 2085 int errno_val = errno; 2086 notice ("%s: can't read aux info file `%s': %s\n", 2087 pname, shortpath (NULL, aux_info_filename), 2088 xstrerror (errno_val)); 2089 errors++; 2090 return; 2091 } 2092 } 2093 #if 0 /* There is code farther down to take care of this. */ 2094 else 2095 { 2096 struct stat s1, s2; 2097 stat (aux_info_file_name, &s1); 2098 stat (base_source_file_name, &s2); 2099 if (s2.st_mtime > s1.st_mtime) 2100 must_create = 1; 2101 } 2102 #endif /* 0 */ 2103 2104 /* If we need a .X file, create it, and verify we can read it. */ 2105 if (must_create) 2106 { 2107 if (!gen_aux_info_file (base_source_filename)) 2108 { 2109 errors++; 2110 return; 2111 } 2112 if (access (aux_info_filename, R_OK) == -1) 2113 { 2114 int errno_val = errno; 2115 notice ("%s: can't read aux info file `%s': %s\n", 2116 pname, shortpath (NULL, aux_info_filename), 2117 xstrerror (errno_val)); 2118 errors++; 2119 return; 2120 } 2121 } 2122 2123 { 2124 struct stat stat_buf; 2125 2126 /* Get some status information about this aux_info file. */ 2127 2128 if (stat (aux_info_filename, &stat_buf) == -1) 2129 { 2130 int errno_val = errno; 2131 notice ("%s: can't get status of aux info file `%s': %s\n", 2132 pname, shortpath (NULL, aux_info_filename), 2133 xstrerror (errno_val)); 2134 errors++; 2135 return; 2136 } 2137 2138 /* Check on whether or not this aux_info file is zero length. If it is, 2139 then just ignore it and return. */ 2140 2141 if ((aux_info_size = stat_buf.st_size) == 0) 2142 return; 2143 2144 /* Get the date/time of last modification for this aux_info file and 2145 remember it. We will have to check that any source files that it 2146 contains information about are at least this old or older. */ 2147 2148 aux_info_mtime = stat_buf.st_mtime; 2149 2150 if (!is_syscalls) 2151 { 2152 /* Compare mod time with the .c file; update .X file if obsolete. 2153 The code later on can fail to check the .c file 2154 if it did not directly define any functions. */ 2155 2156 if (stat (base_source_filename, &stat_buf) == -1) 2157 { 2158 int errno_val = errno; 2159 notice ("%s: can't get status of aux info file `%s': %s\n", 2160 pname, shortpath (NULL, base_source_filename), 2161 xstrerror (errno_val)); 2162 errors++; 2163 return; 2164 } 2165 if (stat_buf.st_mtime > aux_info_mtime) 2166 { 2167 must_create = 1; 2168 goto start_over; 2169 } 2170 } 2171 } 2172 2173 { 2174 int aux_info_file; 2175 int fd_flags; 2176 2177 /* Open the aux_info file. */ 2178 2179 fd_flags = O_RDONLY; 2180 #ifdef O_BINARY 2181 /* Use binary mode to avoid having to deal with different EOL characters. */ 2182 fd_flags |= O_BINARY; 2183 #endif 2184 if ((aux_info_file = open (aux_info_filename, fd_flags, 0444 )) == -1) 2185 { 2186 int errno_val = errno; 2187 notice ("%s: can't open aux info file `%s' for reading: %s\n", 2188 pname, shortpath (NULL, aux_info_filename), 2189 xstrerror (errno_val)); 2190 return; 2191 } 2192 2193 /* Allocate space to hold the aux_info file in memory. */ 2194 2195 aux_info_base = xmalloc (aux_info_size + 1); 2196 aux_info_limit = aux_info_base + aux_info_size; 2197 *aux_info_limit = '\0'; 2198 2199 /* Read the aux_info file into memory. */ 2200 2201 if (safe_read (aux_info_file, aux_info_base, aux_info_size) != 2202 (int) aux_info_size) 2203 { 2204 int errno_val = errno; 2205 notice ("%s: error reading aux info file `%s': %s\n", 2206 pname, shortpath (NULL, aux_info_filename), 2207 xstrerror (errno_val)); 2208 free (aux_info_base); 2209 close (aux_info_file); 2210 return; 2211 } 2212 2213 /* Close the aux info file. */ 2214 2215 if (close (aux_info_file)) 2216 { 2217 int errno_val = errno; 2218 notice ("%s: error closing aux info file `%s': %s\n", 2219 pname, shortpath (NULL, aux_info_filename), 2220 xstrerror (errno_val)); 2221 free (aux_info_base); 2222 close (aux_info_file); 2223 return; 2224 } 2225 } 2226 2227 /* Delete the aux_info file (unless requested not to). If the deletion 2228 fails for some reason, don't even worry about it. */ 2229 2230 if (must_create && !keep_it) 2231 if (unlink (aux_info_filename) == -1) 2232 { 2233 int errno_val = errno; 2234 notice ("%s: can't delete aux info file `%s': %s\n", 2235 pname, shortpath (NULL, aux_info_filename), 2236 xstrerror (errno_val)); 2237 } 2238 2239 /* Save a pointer into the first line of the aux_info file which 2240 contains the filename of the directory from which the compiler 2241 was invoked when the associated source file was compiled. 2242 This information is used later to help create complete 2243 filenames out of the (potentially) relative filenames in 2244 the aux_info file. */ 2245 2246 { 2247 char *p = aux_info_base; 2248 2249 while (*p != ':' 2250 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 2251 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1))) 2252 #endif 2253 ) 2254 p++; 2255 p++; 2256 while (*p == ' ') 2257 p++; 2258 invocation_filename = p; /* Save a pointer to first byte of path. */ 2259 while (*p != ' ') 2260 p++; 2261 *p++ = DIR_SEPARATOR; 2262 *p++ = '\0'; 2263 while (*p++ != '\n') 2264 continue; 2265 aux_info_second_line = p; 2266 aux_info_relocated_name = 0; 2267 if (! is_abspath (invocation_filename)) 2268 { 2269 /* INVOCATION_FILENAME is relative; 2270 append it to BASE_SOURCE_FILENAME's dir. */ 2271 char *dir_end; 2272 aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename)); 2273 strcpy (aux_info_relocated_name, base_source_filename); 2274 dir_end = strrchr (aux_info_relocated_name, DIR_SEPARATOR); 2275 #ifdef DIR_SEPARATOR_2 2276 { 2277 char *slash; 2278 2279 slash = strrchr (dir_end ? dir_end : aux_info_relocated_name, 2280 DIR_SEPARATOR_2); 2281 if (slash) 2282 dir_end = slash; 2283 } 2284 #endif 2285 if (dir_end) 2286 dir_end++; 2287 else 2288 dir_end = aux_info_relocated_name; 2289 strcpy (dir_end, invocation_filename); 2290 invocation_filename = aux_info_relocated_name; 2291 } 2292 } 2293 2294 2295 { 2296 const char *aux_info_p; 2297 2298 /* Do a pre-pass on the lines in the aux_info file, making sure that all 2299 of the source files referenced in there are at least as old as this 2300 aux_info file itself. If not, go back and regenerate the aux_info 2301 file anew. Don't do any of this for the syscalls file. */ 2302 2303 if (!is_syscalls) 2304 { 2305 current_aux_info_lineno = 2; 2306 2307 for (aux_info_p = aux_info_second_line; *aux_info_p; ) 2308 { 2309 if (referenced_file_is_newer (aux_info_p, aux_info_mtime)) 2310 { 2311 free (aux_info_base); 2312 free (aux_info_relocated_name); 2313 if (keep_it && unlink (aux_info_filename) == -1) 2314 { 2315 int errno_val = errno; 2316 notice ("%s: can't delete file `%s': %s\n", 2317 pname, shortpath (NULL, aux_info_filename), 2318 xstrerror (errno_val)); 2319 return; 2320 } 2321 must_create = 1; 2322 goto start_over; 2323 } 2324 2325 /* Skip over the rest of this line to start of next line. */ 2326 2327 while (*aux_info_p != '\n') 2328 aux_info_p++; 2329 aux_info_p++; 2330 current_aux_info_lineno++; 2331 } 2332 } 2333 2334 /* Now do the real pass on the aux_info lines. Save their information in 2335 the in-core data base. */ 2336 2337 current_aux_info_lineno = 2; 2338 2339 for (aux_info_p = aux_info_second_line; *aux_info_p;) 2340 { 2341 char *unexpanded_line = unexpand_if_needed (aux_info_p); 2342 2343 if (unexpanded_line) 2344 { 2345 save_def_or_dec (unexpanded_line, is_syscalls); 2346 free (unexpanded_line); 2347 } 2348 else 2349 save_def_or_dec (aux_info_p, is_syscalls); 2350 2351 /* Skip over the rest of this line and get to start of next line. */ 2352 2353 while (*aux_info_p != '\n') 2354 aux_info_p++; 2355 aux_info_p++; 2356 current_aux_info_lineno++; 2357 } 2358 } 2359 2360 free (aux_info_base); 2361 free (aux_info_relocated_name); 2362 } 2363 2364 #ifndef UNPROTOIZE 2365 2366 /* Check an individual filename for a .c suffix. If the filename has this 2367 suffix, rename the file such that its suffix is changed to .C. This 2368 function implements the -C option. */ 2369 2370 static void 2371 rename_c_file (hp) 2372 const hash_table_entry *hp; 2373 { 2374 const char *filename = hp->symbol; 2375 int last_char_index = strlen (filename) - 1; 2376 char *const new_filename = (char *) alloca (strlen (filename) 2377 + strlen (cplus_suffix) + 1); 2378 2379 /* Note that we don't care here if the given file was converted or not. It 2380 is possible that the given file was *not* converted, simply because there 2381 was nothing in it which actually required conversion. Even in this case, 2382 we want to do the renaming. Note that we only rename files with the .c 2383 suffix (except for the syscalls file, which is left alone). */ 2384 2385 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.' 2386 || IS_SAME_PATH (syscalls_absolute_filename, filename)) 2387 return; 2388 2389 strcpy (new_filename, filename); 2390 strcpy (&new_filename[last_char_index], cplus_suffix); 2391 2392 if (rename (filename, new_filename) == -1) 2393 { 2394 int errno_val = errno; 2395 notice ("%s: warning: can't rename file `%s' to `%s': %s\n", 2396 pname, shortpath (NULL, filename), 2397 shortpath (NULL, new_filename), xstrerror (errno_val)); 2398 errors++; 2399 return; 2400 } 2401 } 2402 2403 #endif /* !defined (UNPROTOIZE) */ 2404 2405 /* Take the list of definitions and declarations attached to a particular 2406 file_info node and reverse the order of the list. This should get the 2407 list into an order such that the item with the lowest associated line 2408 number is nearest the head of the list. When these lists are originally 2409 built, they are in the opposite order. We want to traverse them in 2410 normal line number order later (i.e. lowest to highest) so reverse the 2411 order here. */ 2412 2413 static void 2414 reverse_def_dec_list (hp) 2415 const hash_table_entry *hp; 2416 { 2417 file_info *file_p = hp->fip; 2418 def_dec_info *prev = NULL; 2419 def_dec_info *current = (def_dec_info *) file_p->defs_decs; 2420 2421 if (!current) 2422 return; /* no list to reverse */ 2423 2424 prev = current; 2425 if (! (current = (def_dec_info *) current->next_in_file)) 2426 return; /* can't reverse a single list element */ 2427 2428 prev->next_in_file = NULL; 2429 2430 while (current) 2431 { 2432 def_dec_info *next = (def_dec_info *) current->next_in_file; 2433 2434 current->next_in_file = prev; 2435 prev = current; 2436 current = next; 2437 } 2438 2439 file_p->defs_decs = prev; 2440 } 2441 2442 #ifndef UNPROTOIZE 2443 2444 /* Find the (only?) extern definition for a particular function name, starting 2445 from the head of the linked list of entries for the given name. If we 2446 cannot find an extern definition for the given function name, issue a 2447 warning and scrounge around for the next best thing, i.e. an extern 2448 function declaration with a prototype attached to it. Note that we only 2449 allow such substitutions for extern declarations and never for static 2450 declarations. That's because the only reason we allow them at all is 2451 to let un-prototyped function declarations for system-supplied library 2452 functions get their prototypes from our own extra SYSCALLS.c.X file which 2453 contains all of the correct prototypes for system functions. */ 2454 2455 static const def_dec_info * 2456 find_extern_def (head, user) 2457 const def_dec_info *head; 2458 const def_dec_info *user; 2459 { 2460 const def_dec_info *dd_p; 2461 const def_dec_info *extern_def_p = NULL; 2462 int conflict_noted = 0; 2463 2464 /* Don't act too stupid here. Somebody may try to convert an entire system 2465 in one swell fwoop (rather than one program at a time, as should be done) 2466 and in that case, we may find that there are multiple extern definitions 2467 of a given function name in the entire set of source files that we are 2468 converting. If however one of these definitions resides in exactly the 2469 same source file as the reference we are trying to satisfy then in that 2470 case it would be stupid for us to fail to realize that this one definition 2471 *must* be the precise one we are looking for. 2472 2473 To make sure that we don't miss an opportunity to make this "same file" 2474 leap of faith, we do a prescan of the list of records relating to the 2475 given function name, and we look (on this first scan) *only* for a 2476 definition of the function which is in the same file as the reference 2477 we are currently trying to satisfy. */ 2478 2479 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func) 2480 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file) 2481 return dd_p; 2482 2483 /* Now, since we have not found a definition in the same file as the 2484 reference, we scan the list again and consider all possibilities from 2485 all files. Here we may get conflicts with the things listed in the 2486 SYSCALLS.c.X file, but if that happens it only means that the source 2487 code being converted contains its own definition of a function which 2488 could have been supplied by libc.a. In such cases, we should avoid 2489 issuing the normal warning, and defer to the definition given in the 2490 user's own code. */ 2491 2492 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func) 2493 if (dd_p->is_func_def && !dd_p->is_static) 2494 { 2495 if (!extern_def_p) /* Previous definition? */ 2496 extern_def_p = dd_p; /* Remember the first definition found. */ 2497 else 2498 { 2499 /* Ignore definition just found if it came from SYSCALLS.c.X. */ 2500 2501 if (is_syscalls_file (dd_p->file)) 2502 continue; 2503 2504 /* Quietly replace the definition previously found with the one 2505 just found if the previous one was from SYSCALLS.c.X. */ 2506 2507 if (is_syscalls_file (extern_def_p->file)) 2508 { 2509 extern_def_p = dd_p; 2510 continue; 2511 } 2512 2513 /* If we get here, then there is a conflict between two function 2514 declarations for the same function, both of which came from the 2515 user's own code. */ 2516 2517 if (!conflict_noted) /* first time we noticed? */ 2518 { 2519 conflict_noted = 1; 2520 notice ("%s: conflicting extern definitions of '%s'\n", 2521 pname, head->hash_entry->symbol); 2522 if (!quiet_flag) 2523 { 2524 notice ("%s: declarations of '%s' will not be converted\n", 2525 pname, head->hash_entry->symbol); 2526 notice ("%s: conflict list for '%s' follows:\n", 2527 pname, head->hash_entry->symbol); 2528 fprintf (stderr, "%s: %s(%d): %s\n", 2529 pname, 2530 shortpath (NULL, extern_def_p->file->hash_entry->symbol), 2531 extern_def_p->line, extern_def_p->ansi_decl); 2532 } 2533 } 2534 if (!quiet_flag) 2535 fprintf (stderr, "%s: %s(%d): %s\n", 2536 pname, 2537 shortpath (NULL, dd_p->file->hash_entry->symbol), 2538 dd_p->line, dd_p->ansi_decl); 2539 } 2540 } 2541 2542 /* We want to err on the side of caution, so if we found multiple conflicting 2543 definitions for the same function, treat this as being that same as if we 2544 had found no definitions (i.e. return NULL). */ 2545 2546 if (conflict_noted) 2547 return NULL; 2548 2549 if (!extern_def_p) 2550 { 2551 /* We have no definitions for this function so do the next best thing. 2552 Search for an extern declaration already in prototype form. */ 2553 2554 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func) 2555 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped) 2556 { 2557 extern_def_p = dd_p; /* save a pointer to the definition */ 2558 if (!quiet_flag) 2559 notice ("%s: warning: using formals list from %s(%d) for function `%s'\n", 2560 pname, 2561 shortpath (NULL, dd_p->file->hash_entry->symbol), 2562 dd_p->line, dd_p->hash_entry->symbol); 2563 break; 2564 } 2565 2566 /* Gripe about unprototyped function declarations that we found no 2567 corresponding definition (or other source of prototype information) 2568 for. 2569 2570 Gripe even if the unprototyped declaration we are worried about 2571 exists in a file in one of the "system" include directories. We 2572 can gripe about these because we should have at least found a 2573 corresponding (pseudo) definition in the SYSCALLS.c.X file. If we 2574 didn't, then that means that the SYSCALLS.c.X file is missing some 2575 needed prototypes for this particular system. That is worth telling 2576 the user about! */ 2577 2578 if (!extern_def_p) 2579 { 2580 const char *file = user->file->hash_entry->symbol; 2581 2582 if (!quiet_flag) 2583 if (in_system_include_dir (file)) 2584 { 2585 /* Why copy this string into `needed' at all? 2586 Why not just use user->ansi_decl without copying? */ 2587 char *needed = (char *) alloca (strlen (user->ansi_decl) + 1); 2588 char *p; 2589 2590 strcpy (needed, user->ansi_decl); 2591 p = (NONCONST char *) substr (needed, user->hash_entry->symbol) 2592 + strlen (user->hash_entry->symbol) + 2; 2593 /* Avoid having ??? in the string. */ 2594 *p++ = '?'; 2595 *p++ = '?'; 2596 *p++ = '?'; 2597 strcpy (p, ");"); 2598 2599 notice ("%s: %d: `%s' used but missing from SYSCALLS\n", 2600 shortpath (NULL, file), user->line, 2601 needed+7); /* Don't print "extern " */ 2602 } 2603 #if 0 2604 else 2605 notice ("%s: %d: warning: no extern definition for `%s'\n", 2606 shortpath (NULL, file), user->line, 2607 user->hash_entry->symbol); 2608 #endif 2609 } 2610 } 2611 return extern_def_p; 2612 } 2613 2614 /* Find the (only?) static definition for a particular function name in a 2615 given file. Here we get the function-name and the file info indirectly 2616 from the def_dec_info record pointer which is passed in. */ 2617 2618 static const def_dec_info * 2619 find_static_definition (user) 2620 const def_dec_info *user; 2621 { 2622 const def_dec_info *head = user->hash_entry->ddip; 2623 const def_dec_info *dd_p; 2624 int num_static_defs = 0; 2625 const def_dec_info *static_def_p = NULL; 2626 2627 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func) 2628 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file)) 2629 { 2630 static_def_p = dd_p; /* save a pointer to the definition */ 2631 num_static_defs++; 2632 } 2633 if (num_static_defs == 0) 2634 { 2635 if (!quiet_flag) 2636 notice ("%s: warning: no static definition for `%s' in file `%s'\n", 2637 pname, head->hash_entry->symbol, 2638 shortpath (NULL, user->file->hash_entry->symbol)); 2639 } 2640 else if (num_static_defs > 1) 2641 { 2642 notice ("%s: multiple static defs of `%s' in file `%s'\n", 2643 pname, head->hash_entry->symbol, 2644 shortpath (NULL, user->file->hash_entry->symbol)); 2645 return NULL; 2646 } 2647 return static_def_p; 2648 } 2649 2650 /* Find good prototype style formal argument lists for all of the function 2651 declarations which didn't have them before now. 2652 2653 To do this we consider each function name one at a time. For each function 2654 name, we look at the items on the linked list of def_dec_info records for 2655 that particular name. 2656 2657 Somewhere on this list we should find one (and only one) def_dec_info 2658 record which represents the actual function definition, and this record 2659 should have a nice formal argument list already associated with it. 2660 2661 Thus, all we have to do is to connect up all of the other def_dec_info 2662 records for this particular function name to the special one which has 2663 the full-blown formals list. 2664 2665 Of course it is a little more complicated than just that. See below for 2666 more details. */ 2667 2668 static void 2669 connect_defs_and_decs (hp) 2670 const hash_table_entry *hp; 2671 { 2672 const def_dec_info *dd_p; 2673 const def_dec_info *extern_def_p = NULL; 2674 int first_extern_reference = 1; 2675 2676 /* Traverse the list of definitions and declarations for this particular 2677 function name. For each item on the list, if it is a function 2678 definition (either old style or new style) then GCC has already been 2679 kind enough to produce a prototype for us, and it is associated with 2680 the item already, so declare the item as its own associated "definition". 2681 2682 Also, for each item which is only a function declaration, but which 2683 nonetheless has its own prototype already (obviously supplied by the user) 2684 declare the item as its own definition. 2685 2686 Note that when/if there are multiple user-supplied prototypes already 2687 present for multiple declarations of any given function, these multiple 2688 prototypes *should* all match exactly with one another and with the 2689 prototype for the actual function definition. We don't check for this 2690 here however, since we assume that the compiler must have already done 2691 this consistency checking when it was creating the .X files. */ 2692 2693 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func) 2694 if (dd_p->prototyped) 2695 ((NONCONST def_dec_info *) dd_p)->definition = dd_p; 2696 2697 /* Traverse the list of definitions and declarations for this particular 2698 function name. For each item on the list, if it is an extern function 2699 declaration and if it has no associated definition yet, go try to find 2700 the matching extern definition for the declaration. 2701 2702 When looking for the matching function definition, warn the user if we 2703 fail to find one. 2704 2705 If we find more that one function definition also issue a warning. 2706 2707 Do the search for the matching definition only once per unique function 2708 name (and only when absolutely needed) so that we can avoid putting out 2709 redundant warning messages, and so that we will only put out warning 2710 messages when there is actually a reference (i.e. a declaration) for 2711 which we need to find a matching definition. */ 2712 2713 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func) 2714 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition) 2715 { 2716 if (first_extern_reference) 2717 { 2718 extern_def_p = find_extern_def (hp->ddip, dd_p); 2719 first_extern_reference = 0; 2720 } 2721 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p; 2722 } 2723 2724 /* Traverse the list of definitions and declarations for this particular 2725 function name. For each item on the list, if it is a static function 2726 declaration and if it has no associated definition yet, go try to find 2727 the matching static definition for the declaration within the same file. 2728 2729 When looking for the matching function definition, warn the user if we 2730 fail to find one in the same file with the declaration, and refuse to 2731 convert this kind of cross-file static function declaration. After all, 2732 this is stupid practice and should be discouraged. 2733 2734 We don't have to worry about the possibility that there is more than one 2735 matching function definition in the given file because that would have 2736 been flagged as an error by the compiler. 2737 2738 Do the search for the matching definition only once per unique 2739 function-name/source-file pair (and only when absolutely needed) so that 2740 we can avoid putting out redundant warning messages, and so that we will 2741 only put out warning messages when there is actually a reference (i.e. a 2742 declaration) for which we actually need to find a matching definition. */ 2743 2744 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func) 2745 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition) 2746 { 2747 const def_dec_info *dd_p2; 2748 const def_dec_info *static_def; 2749 2750 /* We have now found a single static declaration for which we need to 2751 find a matching definition. We want to minimize the work (and the 2752 number of warnings), so we will find an appropriate (matching) 2753 static definition for this declaration, and then distribute it 2754 (as the definition for) any and all other static declarations 2755 for this function name which occur within the same file, and which 2756 do not already have definitions. 2757 2758 Note that a trick is used here to prevent subsequent attempts to 2759 call find_static_definition for a given function-name & file 2760 if the first such call returns NULL. Essentially, we convert 2761 these NULL return values to -1, and put the -1 into the definition 2762 field for each other static declaration from the same file which 2763 does not already have an associated definition. 2764 This makes these other static declarations look like they are 2765 actually defined already when the outer loop here revisits them 2766 later on. Thus, the outer loop will skip over them. Later, we 2767 turn the -1's back to NULL's. */ 2768 2769 ((NONCONST def_dec_info *) dd_p)->definition = 2770 (static_def = find_static_definition (dd_p)) 2771 ? static_def 2772 : (const def_dec_info *) -1; 2773 2774 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func) 2775 if (!dd_p2->is_func_def && dd_p2->is_static 2776 && !dd_p2->definition && (dd_p2->file == dd_p->file)) 2777 ((NONCONST def_dec_info *) dd_p2)->definition = dd_p->definition; 2778 } 2779 2780 /* Convert any dummy (-1) definitions we created in the step above back to 2781 NULL's (as they should be). */ 2782 2783 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func) 2784 if (dd_p->definition == (def_dec_info *) -1) 2785 ((NONCONST def_dec_info *) dd_p)->definition = NULL; 2786 } 2787 2788 #endif /* !defined (UNPROTOIZE) */ 2789 2790 /* Give a pointer into the clean text buffer, return a number which is the 2791 original source line number that the given pointer points into. */ 2792 2793 static int 2794 identify_lineno (clean_p) 2795 const char *clean_p; 2796 { 2797 int line_num = 1; 2798 const char *scan_p; 2799 2800 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++) 2801 if (*scan_p == '\n') 2802 line_num++; 2803 return line_num; 2804 } 2805 2806 /* Issue an error message and give up on doing this particular edit. */ 2807 2808 static void 2809 declare_source_confusing (clean_p) 2810 const char *clean_p; 2811 { 2812 if (!quiet_flag) 2813 { 2814 if (clean_p == 0) 2815 notice ("%s: %d: warning: source too confusing\n", 2816 shortpath (NULL, convert_filename), last_known_line_number); 2817 else 2818 notice ("%s: %d: warning: source too confusing\n", 2819 shortpath (NULL, convert_filename), 2820 identify_lineno (clean_p)); 2821 } 2822 longjmp (source_confusion_recovery, 1); 2823 } 2824 2825 /* Check that a condition which is expected to be true in the original source 2826 code is in fact true. If not, issue an error message and give up on 2827 converting this particular source file. */ 2828 2829 static void 2830 check_source (cond, clean_p) 2831 int cond; 2832 const char *clean_p; 2833 { 2834 if (!cond) 2835 declare_source_confusing (clean_p); 2836 } 2837 2838 /* If we think of the in-core cleaned text buffer as a memory mapped 2839 file (with the variable last_known_line_start acting as sort of a 2840 file pointer) then we can imagine doing "seeks" on the buffer. The 2841 following routine implements a kind of "seek" operation for the in-core 2842 (cleaned) copy of the source file. When finished, it returns a pointer to 2843 the start of a given (numbered) line in the cleaned text buffer. 2844 2845 Note that protoize only has to "seek" in the forward direction on the 2846 in-core cleaned text file buffers, and it never needs to back up. 2847 2848 This routine is made a little bit faster by remembering the line number 2849 (and pointer value) supplied (and returned) from the previous "seek". 2850 This prevents us from always having to start all over back at the top 2851 of the in-core cleaned buffer again. */ 2852 2853 static const char * 2854 seek_to_line (n) 2855 int n; 2856 { 2857 if (n < last_known_line_number) 2858 abort (); 2859 2860 while (n > last_known_line_number) 2861 { 2862 while (*last_known_line_start != '\n') 2863 check_source (++last_known_line_start < clean_text_limit, 0); 2864 last_known_line_start++; 2865 last_known_line_number++; 2866 } 2867 return last_known_line_start; 2868 } 2869 2870 /* Given a pointer to a character in the cleaned text buffer, return a pointer 2871 to the next non-whitespace character which follows it. */ 2872 2873 static const char * 2874 forward_to_next_token_char (ptr) 2875 const char *ptr; 2876 { 2877 for (++ptr; ISSPACE ((const unsigned char)*ptr); 2878 check_source (++ptr < clean_text_limit, 0)) 2879 continue; 2880 return ptr; 2881 } 2882 2883 /* Copy a chunk of text of length `len' and starting at `str' to the current 2884 output buffer. Note that all attempts to add stuff to the current output 2885 buffer ultimately go through here. */ 2886 2887 static void 2888 output_bytes (str, len) 2889 const char *str; 2890 size_t len; 2891 { 2892 if ((repl_write_ptr + 1) + len >= repl_text_limit) 2893 { 2894 size_t new_size = (repl_text_limit - repl_text_base) << 1; 2895 char *new_buf = (char *) xrealloc (repl_text_base, new_size); 2896 2897 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base); 2898 repl_text_base = new_buf; 2899 repl_text_limit = new_buf + new_size; 2900 } 2901 memcpy (repl_write_ptr + 1, str, len); 2902 repl_write_ptr += len; 2903 } 2904 2905 /* Copy all bytes (except the trailing null) of a null terminated string to 2906 the current output buffer. */ 2907 2908 static void 2909 output_string (str) 2910 const char *str; 2911 { 2912 output_bytes (str, strlen (str)); 2913 } 2914 2915 /* Copy some characters from the original text buffer to the current output 2916 buffer. 2917 2918 This routine takes a pointer argument `p' which is assumed to be a pointer 2919 into the cleaned text buffer. The bytes which are copied are the `original' 2920 equivalents for the set of bytes between the last value of `clean_read_ptr' 2921 and the argument value `p'. 2922 2923 The set of bytes copied however, comes *not* from the cleaned text buffer, 2924 but rather from the direct counterparts of these bytes within the original 2925 text buffer. 2926 2927 Thus, when this function is called, some bytes from the original text 2928 buffer (which may include original comments and preprocessing directives) 2929 will be copied into the output buffer. 2930 2931 Note that the request implied when this routine is called includes the 2932 byte pointed to by the argument pointer `p'. */ 2933 2934 static void 2935 output_up_to (p) 2936 const char *p; 2937 { 2938 size_t copy_length = (size_t) (p - clean_read_ptr); 2939 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1; 2940 2941 if (copy_length == 0) 2942 return; 2943 2944 output_bytes (copy_start, copy_length); 2945 clean_read_ptr = p; 2946 } 2947 2948 /* Given a pointer to a def_dec_info record which represents some form of 2949 definition of a function (perhaps a real definition, or in lieu of that 2950 perhaps just a declaration with a full prototype) return true if this 2951 function is one which we should avoid converting. Return false 2952 otherwise. */ 2953 2954 static int 2955 other_variable_style_function (ansi_header) 2956 const char *ansi_header; 2957 { 2958 #ifdef UNPROTOIZE 2959 2960 /* See if we have a stdarg function, or a function which has stdarg style 2961 parameters or a stdarg style return type. */ 2962 2963 return substr (ansi_header, "...") != 0; 2964 2965 #else /* !defined (UNPROTOIZE) */ 2966 2967 /* See if we have a varargs function, or a function which has varargs style 2968 parameters or a varargs style return type. */ 2969 2970 const char *p; 2971 int len = strlen (varargs_style_indicator); 2972 2973 for (p = ansi_header; p; ) 2974 { 2975 const char *candidate; 2976 2977 if ((candidate = substr (p, varargs_style_indicator)) == 0) 2978 return 0; 2979 else 2980 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len])) 2981 return 1; 2982 else 2983 p = candidate + 1; 2984 } 2985 return 0; 2986 #endif /* !defined (UNPROTOIZE) */ 2987 } 2988 2989 /* Do the editing operation specifically for a function "declaration". Note 2990 that editing for function "definitions" are handled in a separate routine 2991 below. */ 2992 2993 static void 2994 edit_fn_declaration (def_dec_p, clean_text_p) 2995 const def_dec_info *def_dec_p; 2996 const char *volatile clean_text_p; 2997 { 2998 const char *start_formals; 2999 const char *end_formals; 3000 const char *function_to_edit = def_dec_p->hash_entry->symbol; 3001 size_t func_name_len = strlen (function_to_edit); 3002 const char *end_of_fn_name; 3003 3004 #ifndef UNPROTOIZE 3005 3006 const f_list_chain_item *this_f_list_chain_item; 3007 const def_dec_info *definition = def_dec_p->definition; 3008 3009 /* If we are protoizing, and if we found no corresponding definition for 3010 this particular function declaration, then just leave this declaration 3011 exactly as it is. */ 3012 3013 if (!definition) 3014 return; 3015 3016 /* If we are protoizing, and if the corresponding definition that we found 3017 for this particular function declaration defined an old style varargs 3018 function, then we want to issue a warning and just leave this function 3019 declaration unconverted. */ 3020 3021 if (other_variable_style_function (definition->ansi_decl)) 3022 { 3023 if (!quiet_flag) 3024 notice ("%s: %d: warning: varargs function declaration not converted\n", 3025 shortpath (NULL, def_dec_p->file->hash_entry->symbol), 3026 def_dec_p->line); 3027 return; 3028 } 3029 3030 #endif /* !defined (UNPROTOIZE) */ 3031 3032 /* Setup here to recover from confusing source code detected during this 3033 particular "edit". */ 3034 3035 save_pointers (); 3036 if (setjmp (source_confusion_recovery)) 3037 { 3038 restore_pointers (); 3039 notice ("%s: declaration of function `%s' not converted\n", 3040 pname, function_to_edit); 3041 return; 3042 } 3043 3044 /* We are editing a function declaration. The line number we did a seek to 3045 contains the comma or semicolon which follows the declaration. Our job 3046 now is to scan backwards looking for the function name. This name *must* 3047 be followed by open paren (ignoring whitespace, of course). We need to 3048 replace everything between that open paren and the corresponding closing 3049 paren. If we are protoizing, we need to insert the prototype-style 3050 formals lists. If we are unprotoizing, we need to just delete everything 3051 between the pairs of opening and closing parens. */ 3052 3053 /* First move up to the end of the line. */ 3054 3055 while (*clean_text_p != '\n') 3056 check_source (++clean_text_p < clean_text_limit, 0); 3057 clean_text_p--; /* Point to just before the newline character. */ 3058 3059 /* Now we can scan backwards for the function name. */ 3060 3061 do 3062 { 3063 for (;;) 3064 { 3065 /* Scan leftwards until we find some character which can be 3066 part of an identifier. */ 3067 3068 while (!is_id_char (*clean_text_p)) 3069 check_source (--clean_text_p > clean_read_ptr, 0); 3070 3071 /* Scan backwards until we find a char that cannot be part of an 3072 identifier. */ 3073 3074 while (is_id_char (*clean_text_p)) 3075 check_source (--clean_text_p > clean_read_ptr, 0); 3076 3077 /* Having found an "id break", see if the following id is the one 3078 that we are looking for. If so, then exit from this loop. */ 3079 3080 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len)) 3081 { 3082 char ch = *(clean_text_p + 1 + func_name_len); 3083 3084 /* Must also check to see that the name in the source text 3085 ends where it should (in order to prevent bogus matches 3086 on similar but longer identifiers. */ 3087 3088 if (! is_id_char (ch)) 3089 break; /* exit from loop */ 3090 } 3091 } 3092 3093 /* We have now found the first perfect match for the function name in 3094 our backward search. This may or may not be the actual function 3095 name at the start of the actual function declaration (i.e. we could 3096 have easily been mislead). We will try to avoid getting fooled too 3097 often by looking forward for the open paren which should follow the 3098 identifier we just found. We ignore whitespace while hunting. If 3099 the next non-whitespace byte we see is *not* an open left paren, 3100 then we must assume that we have been fooled and we start over 3101 again accordingly. Note that there is no guarantee, that even if 3102 we do see the open paren, that we are in the right place. 3103 Programmers do the strangest things sometimes! */ 3104 3105 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol); 3106 start_formals = forward_to_next_token_char (end_of_fn_name); 3107 } 3108 while (*start_formals != '('); 3109 3110 /* start_of_formals now points to the opening left paren which immediately 3111 follows the name of the function. */ 3112 3113 /* Note that there may be several formals lists which need to be modified 3114 due to the possibility that the return type of this function is a 3115 pointer-to-function type. If there are several formals lists, we 3116 convert them in left-to-right order here. */ 3117 3118 #ifndef UNPROTOIZE 3119 this_f_list_chain_item = definition->f_list_chain; 3120 #endif /* !defined (UNPROTOIZE) */ 3121 3122 for (;;) 3123 { 3124 { 3125 int depth; 3126 3127 end_formals = start_formals + 1; 3128 depth = 1; 3129 for (; depth; check_source (++end_formals < clean_text_limit, 0)) 3130 { 3131 switch (*end_formals) 3132 { 3133 case '(': 3134 depth++; 3135 break; 3136 case ')': 3137 depth--; 3138 break; 3139 } 3140 } 3141 end_formals--; 3142 } 3143 3144 /* end_formals now points to the closing right paren of the formals 3145 list whose left paren is pointed to by start_formals. */ 3146 3147 /* Now, if we are protoizing, we insert the new ANSI-style formals list 3148 attached to the associated definition of this function. If however 3149 we are unprotoizing, then we simply delete any formals list which 3150 may be present. */ 3151 3152 output_up_to (start_formals); 3153 #ifndef UNPROTOIZE 3154 if (this_f_list_chain_item) 3155 { 3156 output_string (this_f_list_chain_item->formals_list); 3157 this_f_list_chain_item = this_f_list_chain_item->chain_next; 3158 } 3159 else 3160 { 3161 if (!quiet_flag) 3162 notice ("%s: warning: too many parameter lists in declaration of `%s'\n", 3163 pname, def_dec_p->hash_entry->symbol); 3164 check_source (0, end_formals); /* leave the declaration intact */ 3165 } 3166 #endif /* !defined (UNPROTOIZE) */ 3167 clean_read_ptr = end_formals - 1; 3168 3169 /* Now see if it looks like there may be another formals list associated 3170 with the function declaration that we are converting (following the 3171 formals list that we just converted. */ 3172 3173 { 3174 const char *another_r_paren = forward_to_next_token_char (end_formals); 3175 3176 if ((*another_r_paren != ')') 3177 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '(')) 3178 { 3179 #ifndef UNPROTOIZE 3180 if (this_f_list_chain_item) 3181 { 3182 if (!quiet_flag) 3183 notice ("\n%s: warning: too few parameter lists in declaration of `%s'\n", 3184 pname, def_dec_p->hash_entry->symbol); 3185 check_source (0, start_formals); /* leave the decl intact */ 3186 } 3187 #endif /* !defined (UNPROTOIZE) */ 3188 break; 3189 3190 } 3191 } 3192 3193 /* There does appear to be yet another formals list, so loop around 3194 again, and convert it also. */ 3195 } 3196 } 3197 3198 /* Edit a whole group of formals lists, starting with the rightmost one 3199 from some set of formals lists. This routine is called once (from the 3200 outside) for each function declaration which is converted. It is 3201 recursive however, and it calls itself once for each remaining formal 3202 list that lies to the left of the one it was originally called to work 3203 on. Thus, a whole set gets done in right-to-left order. 3204 3205 This routine returns nonzero if it thinks that it should not be trying 3206 to convert this particular function definition (because the name of the 3207 function doesn't match the one expected). */ 3208 3209 static int 3210 edit_formals_lists (end_formals, f_list_count, def_dec_p) 3211 const char *end_formals; 3212 unsigned int f_list_count; 3213 const def_dec_info *def_dec_p; 3214 { 3215 const char *start_formals; 3216 int depth; 3217 3218 start_formals = end_formals - 1; 3219 depth = 1; 3220 for (; depth; check_source (--start_formals > clean_read_ptr, 0)) 3221 { 3222 switch (*start_formals) 3223 { 3224 case '(': 3225 depth--; 3226 break; 3227 case ')': 3228 depth++; 3229 break; 3230 } 3231 } 3232 start_formals++; 3233 3234 /* start_formals now points to the opening left paren of the formals list. */ 3235 3236 f_list_count--; 3237 3238 if (f_list_count) 3239 { 3240 const char *next_end; 3241 3242 /* There should be more formal lists to the left of here. */ 3243 3244 next_end = start_formals - 1; 3245 check_source (next_end > clean_read_ptr, 0); 3246 while (ISSPACE ((const unsigned char)*next_end)) 3247 check_source (--next_end > clean_read_ptr, 0); 3248 check_source (*next_end == ')', next_end); 3249 check_source (--next_end > clean_read_ptr, 0); 3250 check_source (*next_end == ')', next_end); 3251 if (edit_formals_lists (next_end, f_list_count, def_dec_p)) 3252 return 1; 3253 } 3254 3255 /* Check that the function name in the header we are working on is the same 3256 as the one we would expect to find. If not, issue a warning and return 3257 nonzero. */ 3258 3259 if (f_list_count == 0) 3260 { 3261 const char *expected = def_dec_p->hash_entry->symbol; 3262 const char *func_name_start; 3263 const char *func_name_limit; 3264 size_t func_name_len; 3265 3266 for (func_name_limit = start_formals-1; 3267 ISSPACE ((const unsigned char)*func_name_limit); ) 3268 check_source (--func_name_limit > clean_read_ptr, 0); 3269 3270 for (func_name_start = func_name_limit++; 3271 is_id_char (*func_name_start); 3272 func_name_start--) 3273 check_source (func_name_start > clean_read_ptr, 0); 3274 func_name_start++; 3275 func_name_len = func_name_limit - func_name_start; 3276 if (func_name_len == 0) 3277 check_source (0, func_name_start); 3278 if (func_name_len != strlen (expected) 3279 || strncmp (func_name_start, expected, func_name_len)) 3280 { 3281 notice ("%s: %d: warning: found `%s' but expected `%s'\n", 3282 shortpath (NULL, def_dec_p->file->hash_entry->symbol), 3283 identify_lineno (func_name_start), 3284 dupnstr (func_name_start, func_name_len), 3285 expected); 3286 return 1; 3287 } 3288 } 3289 3290 output_up_to (start_formals); 3291 3292 #ifdef UNPROTOIZE 3293 if (f_list_count == 0) 3294 output_string (def_dec_p->formal_names); 3295 #else /* !defined (UNPROTOIZE) */ 3296 { 3297 unsigned f_list_depth; 3298 const f_list_chain_item *flci_p = def_dec_p->f_list_chain; 3299 3300 /* At this point, the current value of f_list count says how many 3301 links we have to follow through the f_list_chain to get to the 3302 particular formals list that we need to output next. */ 3303 3304 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++) 3305 flci_p = flci_p->chain_next; 3306 output_string (flci_p->formals_list); 3307 } 3308 #endif /* !defined (UNPROTOIZE) */ 3309 3310 clean_read_ptr = end_formals - 1; 3311 return 0; 3312 } 3313 3314 /* Given a pointer to a byte in the clean text buffer which points to 3315 the beginning of a line that contains a "follower" token for a 3316 function definition header, do whatever is necessary to find the 3317 right closing paren for the rightmost formals list of the function 3318 definition header. */ 3319 3320 static const char * 3321 find_rightmost_formals_list (clean_text_p) 3322 const char *clean_text_p; 3323 { 3324 const char *end_formals; 3325 3326 /* We are editing a function definition. The line number we did a seek 3327 to contains the first token which immediately follows the entire set of 3328 formals lists which are part of this particular function definition 3329 header. 3330 3331 Our job now is to scan leftwards in the clean text looking for the 3332 right-paren which is at the end of the function header's rightmost 3333 formals list. 3334 3335 If we ignore whitespace, this right paren should be the first one we 3336 see which is (ignoring whitespace) immediately followed either by the 3337 open curly-brace beginning the function body or by an alphabetic 3338 character (in the case where the function definition is in old (K&R) 3339 style and there are some declarations of formal parameters). */ 3340 3341 /* It is possible that the right paren we are looking for is on the 3342 current line (together with its following token). Just in case that 3343 might be true, we start out here by skipping down to the right end of 3344 the current line before starting our scan. */ 3345 3346 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++) 3347 continue; 3348 end_formals--; 3349 3350 #ifdef UNPROTOIZE 3351 3352 /* Now scan backwards while looking for the right end of the rightmost 3353 formals list associated with this function definition. */ 3354 3355 { 3356 char ch; 3357 const char *l_brace_p; 3358 3359 /* Look leftward and try to find a right-paren. */ 3360 3361 while (*end_formals != ')') 3362 { 3363 if (ISSPACE ((unsigned char)*end_formals)) 3364 while (ISSPACE ((unsigned char)*end_formals)) 3365 check_source (--end_formals > clean_read_ptr, 0); 3366 else 3367 check_source (--end_formals > clean_read_ptr, 0); 3368 } 3369 3370 ch = *(l_brace_p = forward_to_next_token_char (end_formals)); 3371 /* Since we are unprotoizing an ANSI-style (prototyped) function 3372 definition, there had better not be anything (except whitespace) 3373 between the end of the ANSI formals list and the beginning of the 3374 function body (i.e. the '{'). */ 3375 3376 check_source (ch == '{', l_brace_p); 3377 } 3378 3379 #else /* !defined (UNPROTOIZE) */ 3380 3381 /* Now scan backwards while looking for the right end of the rightmost 3382 formals list associated with this function definition. */ 3383 3384 while (1) 3385 { 3386 char ch; 3387 const char *l_brace_p; 3388 3389 /* Look leftward and try to find a right-paren. */ 3390 3391 while (*end_formals != ')') 3392 { 3393 if (ISSPACE ((const unsigned char)*end_formals)) 3394 while (ISSPACE ((const unsigned char)*end_formals)) 3395 check_source (--end_formals > clean_read_ptr, 0); 3396 else 3397 check_source (--end_formals > clean_read_ptr, 0); 3398 } 3399 3400 ch = *(l_brace_p = forward_to_next_token_char (end_formals)); 3401 3402 /* Since it is possible that we found a right paren before the starting 3403 '{' of the body which IS NOT the one at the end of the real K&R 3404 formals list (say for instance, we found one embedded inside one of 3405 the old K&R formal parameter declarations) we have to check to be 3406 sure that this is in fact the right paren that we were looking for. 3407 3408 The one we were looking for *must* be followed by either a '{' or 3409 by an alphabetic character, while others *cannot* validly be followed 3410 by such characters. */ 3411 3412 if ((ch == '{') || ISALPHA ((unsigned char) ch)) 3413 break; 3414 3415 /* At this point, we have found a right paren, but we know that it is 3416 not the one we were looking for, so backup one character and keep 3417 looking. */ 3418 3419 check_source (--end_formals > clean_read_ptr, 0); 3420 } 3421 3422 #endif /* !defined (UNPROTOIZE) */ 3423 3424 return end_formals; 3425 } 3426 3427 #ifndef UNPROTOIZE 3428 3429 /* Insert into the output file a totally new declaration for a function 3430 which (up until now) was being called from within the current block 3431 without having been declared at any point such that the declaration 3432 was visible (i.e. in scope) at the point of the call. 3433 3434 We need to add in explicit declarations for all such function calls 3435 in order to get the full benefit of prototype-based function call 3436 parameter type checking. */ 3437 3438 static void 3439 add_local_decl (def_dec_p, clean_text_p) 3440 const def_dec_info *def_dec_p; 3441 const char *clean_text_p; 3442 { 3443 const char *start_of_block; 3444 const char *function_to_edit = def_dec_p->hash_entry->symbol; 3445 3446 /* Don't insert new local explicit declarations unless explicitly requested 3447 to do so. */ 3448 3449 if (!local_flag) 3450 return; 3451 3452 /* Setup here to recover from confusing source code detected during this 3453 particular "edit". */ 3454 3455 save_pointers (); 3456 if (setjmp (source_confusion_recovery)) 3457 { 3458 restore_pointers (); 3459 notice ("%s: local declaration for function `%s' not inserted\n", 3460 pname, function_to_edit); 3461 return; 3462 } 3463 3464 /* We have already done a seek to the start of the line which should 3465 contain *the* open curly brace which begins the block in which we need 3466 to insert an explicit function declaration (to replace the implicit one). 3467 3468 Now we scan that line, starting from the left, until we find the 3469 open curly brace we are looking for. Note that there may actually be 3470 multiple open curly braces on the given line, but we will be happy 3471 with the leftmost one no matter what. */ 3472 3473 start_of_block = clean_text_p; 3474 while (*start_of_block != '{' && *start_of_block != '\n') 3475 check_source (++start_of_block < clean_text_limit, 0); 3476 3477 /* Note that the line from the original source could possibly 3478 contain *no* open curly braces! This happens if the line contains 3479 a macro call which expands into a chunk of text which includes a 3480 block (and that block's associated open and close curly braces). 3481 In cases like this, we give up, issue a warning, and do nothing. */ 3482 3483 if (*start_of_block != '{') 3484 { 3485 if (!quiet_flag) 3486 notice ("\n%s: %d: warning: can't add declaration of `%s' into macro call\n", 3487 def_dec_p->file->hash_entry->symbol, def_dec_p->line, 3488 def_dec_p->hash_entry->symbol); 3489 return; 3490 } 3491 3492 /* Figure out what a nice (pretty) indentation would be for the new 3493 declaration we are adding. In order to do this, we must scan forward 3494 from the '{' until we find the first line which starts with some 3495 non-whitespace characters (i.e. real "token" material). */ 3496 3497 { 3498 const char *ep = forward_to_next_token_char (start_of_block) - 1; 3499 const char *sp; 3500 3501 /* Now we have ep pointing at the rightmost byte of some existing indent 3502 stuff. At least that is the hope. 3503 3504 We can now just scan backwards and find the left end of the existing 3505 indentation string, and then copy it to the output buffer. */ 3506 3507 for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--) 3508 continue; 3509 3510 /* Now write out the open { which began this block, and any following 3511 trash up to and including the last byte of the existing indent that 3512 we just found. */ 3513 3514 output_up_to (ep); 3515 3516 /* Now we go ahead and insert the new declaration at this point. 3517 3518 If the definition of the given function is in the same file that we 3519 are currently editing, and if its full ANSI declaration normally 3520 would start with the keyword `extern', suppress the `extern'. */ 3521 3522 { 3523 const char *decl = def_dec_p->definition->ansi_decl; 3524 3525 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file)) 3526 decl += 7; 3527 output_string (decl); 3528 } 3529 3530 /* Finally, write out a new indent string, just like the preceding one 3531 that we found. This will typically include a newline as the first 3532 character of the indent string. */ 3533 3534 output_bytes (sp, (size_t) (ep - sp) + 1); 3535 } 3536 } 3537 3538 /* Given a pointer to a file_info record, and a pointer to the beginning 3539 of a line (in the clean text buffer) which is assumed to contain the 3540 first "follower" token for the first function definition header in the 3541 given file, find a good place to insert some new global function 3542 declarations (which will replace scattered and imprecise implicit ones) 3543 and then insert the new explicit declaration at that point in the file. */ 3544 3545 static void 3546 add_global_decls (file_p, clean_text_p) 3547 const file_info *file_p; 3548 const char *clean_text_p; 3549 { 3550 const def_dec_info *dd_p; 3551 const char *scan_p; 3552 3553 /* Setup here to recover from confusing source code detected during this 3554 particular "edit". */ 3555 3556 save_pointers (); 3557 if (setjmp (source_confusion_recovery)) 3558 { 3559 restore_pointers (); 3560 notice ("%s: global declarations for file `%s' not inserted\n", 3561 pname, shortpath (NULL, file_p->hash_entry->symbol)); 3562 return; 3563 } 3564 3565 /* Start by finding a good location for adding the new explicit function 3566 declarations. To do this, we scan backwards, ignoring whitespace 3567 and comments and other junk until we find either a semicolon, or until 3568 we hit the beginning of the file. */ 3569 3570 scan_p = find_rightmost_formals_list (clean_text_p); 3571 for (;; --scan_p) 3572 { 3573 if (scan_p < clean_text_base) 3574 break; 3575 check_source (scan_p > clean_read_ptr, 0); 3576 if (*scan_p == ';') 3577 break; 3578 } 3579 3580 /* scan_p now points either to a semicolon, or to just before the start 3581 of the whole file. */ 3582 3583 /* Now scan forward for the first non-whitespace character. In theory, 3584 this should be the first character of the following function definition 3585 header. We will put in the added declarations just prior to that. */ 3586 3587 scan_p++; 3588 while (ISSPACE ((const unsigned char)*scan_p)) 3589 scan_p++; 3590 scan_p--; 3591 3592 output_up_to (scan_p); 3593 3594 /* Now write out full prototypes for all of the things that had been 3595 implicitly declared in this file (but only those for which we were 3596 actually able to find unique matching definitions). Avoid duplicates 3597 by marking things that we write out as we go. */ 3598 3599 { 3600 int some_decls_added = 0; 3601 3602 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file) 3603 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written) 3604 { 3605 const char *decl = dd_p->definition->ansi_decl; 3606 3607 /* If the function for which we are inserting a declaration is 3608 actually defined later in the same file, then suppress the 3609 leading `extern' keyword (if there is one). */ 3610 3611 if (*decl == 'e' && (dd_p->file == dd_p->definition->file)) 3612 decl += 7; 3613 3614 output_string ("\n"); 3615 output_string (decl); 3616 some_decls_added = 1; 3617 ((NONCONST def_dec_info *) dd_p->definition)->written = 1; 3618 } 3619 if (some_decls_added) 3620 output_string ("\n\n"); 3621 } 3622 3623 /* Unmark all of the definitions that we just marked. */ 3624 3625 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file) 3626 if (dd_p->definition) 3627 ((NONCONST def_dec_info *) dd_p->definition)->written = 0; 3628 } 3629 3630 #endif /* !defined (UNPROTOIZE) */ 3631 3632 /* Do the editing operation specifically for a function "definition". Note 3633 that editing operations for function "declarations" are handled by a 3634 separate routine above. */ 3635 3636 static void 3637 edit_fn_definition (def_dec_p, clean_text_p) 3638 const def_dec_info *def_dec_p; 3639 const char *clean_text_p; 3640 { 3641 const char *end_formals; 3642 const char *function_to_edit = def_dec_p->hash_entry->symbol; 3643 3644 /* Setup here to recover from confusing source code detected during this 3645 particular "edit". */ 3646 3647 save_pointers (); 3648 if (setjmp (source_confusion_recovery)) 3649 { 3650 restore_pointers (); 3651 notice ("%s: definition of function `%s' not converted\n", 3652 pname, function_to_edit); 3653 return; 3654 } 3655 3656 end_formals = find_rightmost_formals_list (clean_text_p); 3657 3658 /* end_of_formals now points to the closing right paren of the rightmost 3659 formals list which is actually part of the `header' of the function 3660 definition that we are converting. */ 3661 3662 /* If the header of this function definition looks like it declares a 3663 function with a variable number of arguments, and if the way it does 3664 that is different from that way we would like it (i.e. varargs vs. 3665 stdarg) then issue a warning and leave the header unconverted. */ 3666 3667 if (other_variable_style_function (def_dec_p->ansi_decl)) 3668 { 3669 if (!quiet_flag) 3670 notice ("%s: %d: warning: definition of %s not converted\n", 3671 shortpath (NULL, def_dec_p->file->hash_entry->symbol), 3672 identify_lineno (end_formals), 3673 other_var_style); 3674 output_up_to (end_formals); 3675 return; 3676 } 3677 3678 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p)) 3679 { 3680 restore_pointers (); 3681 notice ("%s: definition of function `%s' not converted\n", 3682 pname, function_to_edit); 3683 return; 3684 } 3685 3686 /* Have to output the last right paren because this never gets flushed by 3687 edit_formals_list. */ 3688 3689 output_up_to (end_formals); 3690 3691 #ifdef UNPROTOIZE 3692 { 3693 const char *decl_p; 3694 const char *semicolon_p; 3695 const char *limit_p; 3696 const char *scan_p; 3697 int had_newlines = 0; 3698 3699 /* Now write out the K&R style formal declarations, one per line. */ 3700 3701 decl_p = def_dec_p->formal_decls; 3702 limit_p = decl_p + strlen (decl_p); 3703 for (;decl_p < limit_p; decl_p = semicolon_p + 2) 3704 { 3705 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++) 3706 continue; 3707 output_string ("\n"); 3708 output_string (indent_string); 3709 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p)); 3710 } 3711 3712 /* If there are no newlines between the end of the formals list and the 3713 start of the body, we should insert one now. */ 3714 3715 for (scan_p = end_formals+1; *scan_p != '{'; ) 3716 { 3717 if (*scan_p == '\n') 3718 { 3719 had_newlines = 1; 3720 break; 3721 } 3722 check_source (++scan_p < clean_text_limit, 0); 3723 } 3724 if (!had_newlines) 3725 output_string ("\n"); 3726 } 3727 #else /* !defined (UNPROTOIZE) */ 3728 /* If we are protoizing, there may be some flotsam & jetsam (like comments 3729 and preprocessing directives) after the old formals list but before 3730 the following { and we would like to preserve that stuff while effectively 3731 deleting the existing K&R formal parameter declarations. We do so here 3732 in a rather tricky way. Basically, we white out any stuff *except* 3733 the comments/pp-directives in the original text buffer, then, if there 3734 is anything in this area *other* than whitespace, we output it. */ 3735 { 3736 const char *end_formals_orig; 3737 const char *start_body; 3738 const char *start_body_orig; 3739 const char *scan; 3740 const char *scan_orig; 3741 int have_flotsam = 0; 3742 int have_newlines = 0; 3743 3744 for (start_body = end_formals + 1; *start_body != '{';) 3745 check_source (++start_body < clean_text_limit, 0); 3746 3747 end_formals_orig = orig_text_base + (end_formals - clean_text_base); 3748 start_body_orig = orig_text_base + (start_body - clean_text_base); 3749 scan = end_formals + 1; 3750 scan_orig = end_formals_orig + 1; 3751 for (; scan < start_body; scan++, scan_orig++) 3752 { 3753 if (*scan == *scan_orig) 3754 { 3755 have_newlines |= (*scan_orig == '\n'); 3756 /* Leave identical whitespace alone. */ 3757 if (!ISSPACE ((const unsigned char)*scan_orig)) 3758 *((NONCONST char *) scan_orig) = ' '; /* identical - so whiteout */ 3759 } 3760 else 3761 have_flotsam = 1; 3762 } 3763 if (have_flotsam) 3764 output_bytes (end_formals_orig + 1, 3765 (size_t) (start_body_orig - end_formals_orig) - 1); 3766 else 3767 if (have_newlines) 3768 output_string ("\n"); 3769 else 3770 output_string (" "); 3771 clean_read_ptr = start_body - 1; 3772 } 3773 #endif /* !defined (UNPROTOIZE) */ 3774 } 3775 3776 /* Clean up the clean text buffer. Do this by converting comments and 3777 preprocessing directives into spaces. Also convert line continuations 3778 into whitespace. Also, whiteout string and character literals. */ 3779 3780 static void 3781 do_cleaning (new_clean_text_base, new_clean_text_limit) 3782 char *new_clean_text_base; 3783 const char *new_clean_text_limit; 3784 { 3785 char *scan_p; 3786 int non_whitespace_since_newline = 0; 3787 3788 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++) 3789 { 3790 switch (*scan_p) 3791 { 3792 case '/': /* Handle comments. */ 3793 if (scan_p[1] != '*') 3794 goto regular; 3795 non_whitespace_since_newline = 1; 3796 scan_p[0] = ' '; 3797 scan_p[1] = ' '; 3798 scan_p += 2; 3799 while (scan_p[1] != '/' || scan_p[0] != '*') 3800 { 3801 if (!ISSPACE ((const unsigned char)*scan_p)) 3802 *scan_p = ' '; 3803 if (++scan_p >= new_clean_text_limit) 3804 abort (); 3805 } 3806 *scan_p++ = ' '; 3807 *scan_p = ' '; 3808 break; 3809 3810 case '#': /* Handle pp directives. */ 3811 if (non_whitespace_since_newline) 3812 goto regular; 3813 *scan_p = ' '; 3814 while (scan_p[1] != '\n' || scan_p[0] == '\\') 3815 { 3816 if (!ISSPACE ((const unsigned char)*scan_p)) 3817 *scan_p = ' '; 3818 if (++scan_p >= new_clean_text_limit) 3819 abort (); 3820 } 3821 *scan_p++ = ' '; 3822 break; 3823 3824 case '\'': /* Handle character literals. */ 3825 non_whitespace_since_newline = 1; 3826 while (scan_p[1] != '\'' || scan_p[0] == '\\') 3827 { 3828 if (scan_p[0] == '\\' 3829 && !ISSPACE ((const unsigned char) scan_p[1])) 3830 scan_p[1] = ' '; 3831 if (!ISSPACE ((const unsigned char)*scan_p)) 3832 *scan_p = ' '; 3833 if (++scan_p >= new_clean_text_limit) 3834 abort (); 3835 } 3836 *scan_p++ = ' '; 3837 break; 3838 3839 case '"': /* Handle string literals. */ 3840 non_whitespace_since_newline = 1; 3841 while (scan_p[1] != '"' || scan_p[0] == '\\') 3842 { 3843 if (scan_p[0] == '\\' 3844 && !ISSPACE ((const unsigned char) scan_p[1])) 3845 scan_p[1] = ' '; 3846 if (!ISSPACE ((const unsigned char)*scan_p)) 3847 *scan_p = ' '; 3848 if (++scan_p >= new_clean_text_limit) 3849 abort (); 3850 } 3851 if (!ISSPACE ((const unsigned char)*scan_p)) 3852 *scan_p = ' '; 3853 scan_p++; 3854 break; 3855 3856 case '\\': /* Handle line continuations. */ 3857 if (scan_p[1] != '\n') 3858 goto regular; 3859 *scan_p = ' '; 3860 break; 3861 3862 case '\n': 3863 non_whitespace_since_newline = 0; /* Reset. */ 3864 break; 3865 3866 case ' ': 3867 case '\v': 3868 case '\t': 3869 case '\r': 3870 case '\f': 3871 case '\b': 3872 break; /* Whitespace characters. */ 3873 3874 default: 3875 regular: 3876 non_whitespace_since_newline = 1; 3877 break; 3878 } 3879 } 3880 } 3881 3882 /* Given a pointer to the closing right parenthesis for a particular formals 3883 list (in the clean text buffer) find the corresponding left parenthesis 3884 and return a pointer to it. */ 3885 3886 static const char * 3887 careful_find_l_paren (p) 3888 const char *p; 3889 { 3890 const char *q; 3891 int paren_depth; 3892 3893 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0)) 3894 { 3895 switch (*q) 3896 { 3897 case ')': 3898 paren_depth++; 3899 break; 3900 case '(': 3901 paren_depth--; 3902 break; 3903 } 3904 } 3905 return ++q; 3906 } 3907 3908 /* Scan the clean text buffer for cases of function definitions that we 3909 don't really know about because they were preprocessed out when the 3910 aux info files were created. 3911 3912 In this version of protoize/unprotoize we just give a warning for each 3913 one found. A later version may be able to at least unprotoize such 3914 missed items. 3915 3916 Note that we may easily find all function definitions simply by 3917 looking for places where there is a left paren which is (ignoring 3918 whitespace) immediately followed by either a left-brace or by an 3919 upper or lower case letter. Whenever we find this combination, we 3920 have also found a function definition header. 3921 3922 Finding function *declarations* using syntactic clues is much harder. 3923 I will probably try to do this in a later version though. */ 3924 3925 static void 3926 scan_for_missed_items (file_p) 3927 const file_info *file_p; 3928 { 3929 static const char *scan_p; 3930 const char *limit = clean_text_limit - 3; 3931 static const char *backup_limit; 3932 3933 backup_limit = clean_text_base - 1; 3934 3935 for (scan_p = clean_text_base; scan_p < limit; scan_p++) 3936 { 3937 if (*scan_p == ')') 3938 { 3939 static const char *last_r_paren; 3940 const char *ahead_p; 3941 3942 last_r_paren = scan_p; 3943 3944 for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); ) 3945 check_source (++ahead_p < limit, limit); 3946 3947 scan_p = ahead_p - 1; 3948 3949 if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{') 3950 { 3951 const char *last_l_paren; 3952 const int lineno = identify_lineno (ahead_p); 3953 3954 if (setjmp (source_confusion_recovery)) 3955 continue; 3956 3957 /* We know we have a function definition header. Now skip 3958 leftwards over all of its associated formals lists. */ 3959 3960 do 3961 { 3962 last_l_paren = careful_find_l_paren (last_r_paren); 3963 for (last_r_paren = last_l_paren-1; 3964 ISSPACE ((const unsigned char)*last_r_paren); ) 3965 check_source (--last_r_paren >= backup_limit, backup_limit); 3966 } 3967 while (*last_r_paren == ')'); 3968 3969 if (is_id_char (*last_r_paren)) 3970 { 3971 const char *id_limit = last_r_paren + 1; 3972 const char *id_start; 3973 size_t id_length; 3974 const def_dec_info *dd_p; 3975 3976 for (id_start = id_limit-1; is_id_char (*id_start); ) 3977 check_source (--id_start >= backup_limit, backup_limit); 3978 id_start++; 3979 backup_limit = id_start; 3980 if ((id_length = (size_t) (id_limit - id_start)) == 0) 3981 goto not_missed; 3982 3983 { 3984 char *func_name = (char *) alloca (id_length + 1); 3985 static const char * const stmt_keywords[] 3986 = { "if", "else", "do", "while", "for", "switch", "case", "return", 0 }; 3987 const char * const *stmt_keyword; 3988 3989 strncpy (func_name, id_start, id_length); 3990 func_name[id_length] = '\0'; 3991 3992 /* We must check here to see if we are actually looking at 3993 a statement rather than an actual function call. */ 3994 3995 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++) 3996 if (!strcmp (func_name, *stmt_keyword)) 3997 goto not_missed; 3998 3999 #if 0 4000 notice ("%s: found definition of `%s' at %s(%d)\n", 4001 pname, 4002 func_name, 4003 shortpath (NULL, file_p->hash_entry->symbol), 4004 identify_lineno (id_start)); 4005 #endif /* 0 */ 4006 /* We really should check for a match of the function name 4007 here also, but why bother. */ 4008 4009 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file) 4010 if (dd_p->is_func_def && dd_p->line == lineno) 4011 goto not_missed; 4012 4013 /* If we make it here, then we did not know about this 4014 function definition. */ 4015 4016 notice ("%s: %d: warning: `%s' excluded by preprocessing\n", 4017 shortpath (NULL, file_p->hash_entry->symbol), 4018 identify_lineno (id_start), func_name); 4019 notice ("%s: function definition not converted\n", 4020 pname); 4021 } 4022 not_missed: ; 4023 } 4024 } 4025 } 4026 } 4027 } 4028 4029 /* Do all editing operations for a single source file (either a "base" file 4030 or an "include" file). To do this we read the file into memory, keep a 4031 virgin copy there, make another cleaned in-core copy of the original file 4032 (i.e. one in which all of the comments and preprocessing directives have 4033 been replaced with whitespace), then use these two in-core copies of the 4034 file to make a new edited in-core copy of the file. Finally, rename the 4035 original file (as a way of saving it), and then write the edited version 4036 of the file from core to a disk file of the same name as the original. 4037 4038 Note that the trick of making a copy of the original sans comments & 4039 preprocessing directives make the editing a whole lot easier. */ 4040 4041 static void 4042 edit_file (hp) 4043 const hash_table_entry *hp; 4044 { 4045 struct stat stat_buf; 4046 const file_info *file_p = hp->fip; 4047 char *new_orig_text_base; 4048 char *new_orig_text_limit; 4049 char *new_clean_text_base; 4050 char *new_clean_text_limit; 4051 size_t orig_size; 4052 size_t repl_size; 4053 int first_definition_in_file; 4054 4055 /* If we are not supposed to be converting this file, or if there is 4056 nothing in there which needs converting, just skip this file. */ 4057 4058 if (!needs_to_be_converted (file_p)) 4059 return; 4060 4061 convert_filename = file_p->hash_entry->symbol; 4062 4063 /* Convert a file if it is in a directory where we want conversion 4064 and the file is not excluded. */ 4065 4066 if (!directory_specified_p (convert_filename) 4067 || file_excluded_p (convert_filename)) 4068 { 4069 if (!quiet_flag 4070 #ifdef UNPROTOIZE 4071 /* Don't even mention "system" include files unless we are 4072 protoizing. If we are protoizing, we mention these as a 4073 gentle way of prodding the user to convert his "system" 4074 include files to prototype format. */ 4075 && !in_system_include_dir (convert_filename) 4076 #endif /* defined (UNPROTOIZE) */ 4077 ) 4078 notice ("%s: `%s' not converted\n", 4079 pname, shortpath (NULL, convert_filename)); 4080 return; 4081 } 4082 4083 /* Let the user know what we are up to. */ 4084 4085 if (nochange_flag) 4086 notice ("%s: would convert file `%s'\n", 4087 pname, shortpath (NULL, convert_filename)); 4088 else 4089 notice ("%s: converting file `%s'\n", 4090 pname, shortpath (NULL, convert_filename)); 4091 fflush (stderr); 4092 4093 /* Find out the size (in bytes) of the original file. */ 4094 4095 /* The cast avoids an erroneous warning on AIX. */ 4096 if (stat (convert_filename, &stat_buf) == -1) 4097 { 4098 int errno_val = errno; 4099 notice ("%s: can't get status for file `%s': %s\n", 4100 pname, shortpath (NULL, convert_filename), 4101 xstrerror (errno_val)); 4102 return; 4103 } 4104 orig_size = stat_buf.st_size; 4105 4106 /* Allocate a buffer to hold the original text. */ 4107 4108 orig_text_base = new_orig_text_base = (char *) xmalloc (orig_size + 2); 4109 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size; 4110 4111 /* Allocate a buffer to hold the cleaned-up version of the original text. */ 4112 4113 clean_text_base = new_clean_text_base = (char *) xmalloc (orig_size + 2); 4114 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size; 4115 clean_read_ptr = clean_text_base - 1; 4116 4117 /* Allocate a buffer that will hopefully be large enough to hold the entire 4118 converted output text. As an initial guess for the maximum size of the 4119 output buffer, use 125% of the size of the original + some extra. This 4120 buffer can be expanded later as needed. */ 4121 4122 repl_size = orig_size + (orig_size >> 2) + 4096; 4123 repl_text_base = (char *) xmalloc (repl_size + 2); 4124 repl_text_limit = repl_text_base + repl_size - 1; 4125 repl_write_ptr = repl_text_base - 1; 4126 4127 { 4128 int input_file; 4129 int fd_flags; 4130 4131 /* Open the file to be converted in READ ONLY mode. */ 4132 4133 fd_flags = O_RDONLY; 4134 #ifdef O_BINARY 4135 /* Use binary mode to avoid having to deal with different EOL characters. */ 4136 fd_flags |= O_BINARY; 4137 #endif 4138 if ((input_file = open (convert_filename, fd_flags, 0444)) == -1) 4139 { 4140 int errno_val = errno; 4141 notice ("%s: can't open file `%s' for reading: %s\n", 4142 pname, shortpath (NULL, convert_filename), 4143 xstrerror (errno_val)); 4144 return; 4145 } 4146 4147 /* Read the entire original source text file into the original text buffer 4148 in one swell fwoop. Then figure out where the end of the text is and 4149 make sure that it ends with a newline followed by a null. */ 4150 4151 if (safe_read (input_file, new_orig_text_base, orig_size) != 4152 (int) orig_size) 4153 { 4154 int errno_val = errno; 4155 close (input_file); 4156 notice ("\n%s: error reading input file `%s': %s\n", 4157 pname, shortpath (NULL, convert_filename), 4158 xstrerror (errno_val)); 4159 return; 4160 } 4161 4162 close (input_file); 4163 } 4164 4165 if (orig_size == 0 || orig_text_limit[-1] != '\n') 4166 { 4167 *new_orig_text_limit++ = '\n'; 4168 orig_text_limit++; 4169 } 4170 4171 /* Create the cleaned up copy of the original text. */ 4172 4173 memcpy (new_clean_text_base, orig_text_base, 4174 (size_t) (orig_text_limit - orig_text_base)); 4175 do_cleaning (new_clean_text_base, new_clean_text_limit); 4176 4177 #if 0 4178 { 4179 int clean_file; 4180 size_t clean_size = orig_text_limit - orig_text_base; 4181 char *const clean_filename = (char *) alloca (strlen (convert_filename) + 6 + 1); 4182 4183 /* Open (and create) the clean file. */ 4184 4185 strcpy (clean_filename, convert_filename); 4186 strcat (clean_filename, ".clean"); 4187 if ((clean_file = creat (clean_filename, 0666)) == -1) 4188 { 4189 int errno_val = errno; 4190 notice ("%s: can't create/open clean file `%s': %s\n", 4191 pname, shortpath (NULL, clean_filename), 4192 xstrerror (errno_val)); 4193 return; 4194 } 4195 4196 /* Write the clean file. */ 4197 4198 safe_write (clean_file, new_clean_text_base, clean_size, clean_filename); 4199 4200 close (clean_file); 4201 } 4202 #endif /* 0 */ 4203 4204 /* Do a simplified scan of the input looking for things that were not 4205 mentioned in the aux info files because of the fact that they were 4206 in a region of the source which was preprocessed-out (via #if or 4207 via #ifdef). */ 4208 4209 scan_for_missed_items (file_p); 4210 4211 /* Setup to do line-oriented forward seeking in the clean text buffer. */ 4212 4213 last_known_line_number = 1; 4214 last_known_line_start = clean_text_base; 4215 4216 /* Now get down to business and make all of the necessary edits. */ 4217 4218 { 4219 const def_dec_info *def_dec_p; 4220 4221 first_definition_in_file = 1; 4222 def_dec_p = file_p->defs_decs; 4223 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file) 4224 { 4225 const char *clean_text_p = seek_to_line (def_dec_p->line); 4226 4227 /* clean_text_p now points to the first character of the line which 4228 contains the `terminator' for the declaration or definition that 4229 we are about to process. */ 4230 4231 #ifndef UNPROTOIZE 4232 4233 if (global_flag && def_dec_p->is_func_def && first_definition_in_file) 4234 { 4235 add_global_decls (def_dec_p->file, clean_text_p); 4236 first_definition_in_file = 0; 4237 } 4238 4239 /* Don't edit this item if it is already in prototype format or if it 4240 is a function declaration and we have found no corresponding 4241 definition. */ 4242 4243 if (def_dec_p->prototyped 4244 || (!def_dec_p->is_func_def && !def_dec_p->definition)) 4245 continue; 4246 4247 #endif /* !defined (UNPROTOIZE) */ 4248 4249 if (def_dec_p->is_func_def) 4250 edit_fn_definition (def_dec_p, clean_text_p); 4251 else 4252 #ifndef UNPROTOIZE 4253 if (def_dec_p->is_implicit) 4254 add_local_decl (def_dec_p, clean_text_p); 4255 else 4256 #endif /* !defined (UNPROTOIZE) */ 4257 edit_fn_declaration (def_dec_p, clean_text_p); 4258 } 4259 } 4260 4261 /* Finalize things. Output the last trailing part of the original text. */ 4262 4263 output_up_to (clean_text_limit - 1); 4264 4265 /* If this is just a test run, stop now and just deallocate the buffers. */ 4266 4267 if (nochange_flag) 4268 { 4269 free (new_orig_text_base); 4270 free (new_clean_text_base); 4271 free (repl_text_base); 4272 return; 4273 } 4274 4275 /* Change the name of the original input file. This is just a quick way of 4276 saving the original file. */ 4277 4278 if (!nosave_flag) 4279 { 4280 char *new_filename 4281 = (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2); 4282 4283 strcpy (new_filename, convert_filename); 4284 #ifdef __MSDOS__ 4285 /* MSDOS filenames are restricted to 8.3 format, so we save `foo.c' 4286 as `foo.<save_suffix>'. */ 4287 new_filename[(strlen (convert_filename) - 1] = '\0'; 4288 #endif 4289 strcat (new_filename, save_suffix); 4290 4291 /* Don't overwrite existing file. */ 4292 if (access (new_filename, F_OK) == 0) 4293 { 4294 if (!quiet_flag) 4295 notice ("%s: warning: file `%s' already saved in `%s'\n", 4296 pname, 4297 shortpath (NULL, convert_filename), 4298 shortpath (NULL, new_filename)); 4299 } 4300 else if (rename (convert_filename, new_filename) == -1) 4301 { 4302 int errno_val = errno; 4303 notice ("%s: can't link file `%s' to `%s': %s\n", 4304 pname, 4305 shortpath (NULL, convert_filename), 4306 shortpath (NULL, new_filename), 4307 xstrerror (errno_val)); 4308 return; 4309 } 4310 } 4311 4312 if (unlink (convert_filename) == -1) 4313 { 4314 int errno_val = errno; 4315 /* The file may have already been renamed. */ 4316 if (errno_val != ENOENT) 4317 { 4318 notice ("%s: can't delete file `%s': %s\n", 4319 pname, shortpath (NULL, convert_filename), 4320 xstrerror (errno_val)); 4321 return; 4322 } 4323 } 4324 4325 { 4326 int output_file; 4327 4328 /* Open (and create) the output file. */ 4329 4330 if ((output_file = creat (convert_filename, 0666)) == -1) 4331 { 4332 int errno_val = errno; 4333 notice ("%s: can't create/open output file `%s': %s\n", 4334 pname, shortpath (NULL, convert_filename), 4335 xstrerror (errno_val)); 4336 return; 4337 } 4338 #ifdef O_BINARY 4339 /* Use binary mode to avoid changing the existing EOL character. */ 4340 setmode (output_file, O_BINARY); 4341 #endif 4342 4343 /* Write the output file. */ 4344 4345 { 4346 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base; 4347 4348 safe_write (output_file, repl_text_base, out_size, convert_filename); 4349 } 4350 4351 close (output_file); 4352 } 4353 4354 /* Deallocate the conversion buffers. */ 4355 4356 free (new_orig_text_base); 4357 free (new_clean_text_base); 4358 free (repl_text_base); 4359 4360 /* Change the mode of the output file to match the original file. */ 4361 4362 /* The cast avoids an erroneous warning on AIX. */ 4363 if (chmod (convert_filename, stat_buf.st_mode) == -1) 4364 { 4365 int errno_val = errno; 4366 notice ("%s: can't change mode of file `%s': %s\n", 4367 pname, shortpath (NULL, convert_filename), 4368 xstrerror (errno_val)); 4369 } 4370 4371 /* Note: We would try to change the owner and group of the output file 4372 to match those of the input file here, except that may not be a good 4373 thing to do because it might be misleading. Also, it might not even 4374 be possible to do that (on BSD systems with quotas for instance). */ 4375 } 4376 4377 /* Do all of the individual steps needed to do the protoization (or 4378 unprotoization) of the files referenced in the aux_info files given 4379 in the command line. */ 4380 4381 static void 4382 do_processing () 4383 { 4384 const char * const *base_pp; 4385 const char * const * const end_pps 4386 = &base_source_filenames[n_base_source_files]; 4387 4388 #ifndef UNPROTOIZE 4389 int syscalls_len; 4390 #endif /* !defined (UNPROTOIZE) */ 4391 4392 /* One-by-one, check (and create if necessary), open, and read all of the 4393 stuff in each aux_info file. After reading each aux_info file, the 4394 aux_info_file just read will be automatically deleted unless the 4395 keep_flag is set. */ 4396 4397 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++) 4398 process_aux_info_file (*base_pp, keep_flag, 0); 4399 4400 #ifndef UNPROTOIZE 4401 4402 /* Also open and read the special SYSCALLS.c aux_info file which gives us 4403 the prototypes for all of the standard system-supplied functions. */ 4404 4405 if (nondefault_syscalls_dir) 4406 { 4407 syscalls_absolute_filename 4408 = (char *) xmalloc (strlen (nondefault_syscalls_dir) + 1 4409 + sizeof (syscalls_filename)); 4410 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir); 4411 } 4412 else 4413 { 4414 GET_ENVIRONMENT (default_syscalls_dir, "GCC_EXEC_PREFIX"); 4415 if (!default_syscalls_dir) 4416 { 4417 default_syscalls_dir = standard_exec_prefix; 4418 } 4419 syscalls_absolute_filename 4420 = (char *) xmalloc (strlen (default_syscalls_dir) + 0 4421 + strlen (target_machine) + 1 4422 + strlen (target_version) + 1 4423 + sizeof (syscalls_filename)); 4424 strcpy (syscalls_absolute_filename, default_syscalls_dir); 4425 strcat (syscalls_absolute_filename, target_machine); 4426 strcat (syscalls_absolute_filename, "/"); 4427 strcat (syscalls_absolute_filename, target_version); 4428 strcat (syscalls_absolute_filename, "/"); 4429 } 4430 4431 syscalls_len = strlen (syscalls_absolute_filename); 4432 if (! IS_DIR_SEPARATOR (*(syscalls_absolute_filename + syscalls_len - 1))) 4433 { 4434 *(syscalls_absolute_filename + syscalls_len++) = DIR_SEPARATOR; 4435 *(syscalls_absolute_filename + syscalls_len) = '\0'; 4436 } 4437 strcat (syscalls_absolute_filename, syscalls_filename); 4438 4439 /* Call process_aux_info_file in such a way that it does not try to 4440 delete the SYSCALLS aux_info file. */ 4441 4442 process_aux_info_file (syscalls_absolute_filename, 1, 1); 4443 4444 #endif /* !defined (UNPROTOIZE) */ 4445 4446 /* When we first read in all of the information from the aux_info files 4447 we saved in it descending line number order, because that was likely to 4448 be faster. Now however, we want the chains of def & dec records to 4449 appear in ascending line number order as we get further away from the 4450 file_info record that they hang from. The following line causes all of 4451 these lists to be rearranged into ascending line number order. */ 4452 4453 visit_each_hash_node (filename_primary, reverse_def_dec_list); 4454 4455 #ifndef UNPROTOIZE 4456 4457 /* Now do the "real" work. The following line causes each declaration record 4458 to be "visited". For each of these nodes, an attempt is made to match 4459 up the function declaration with a corresponding function definition, 4460 which should have a full prototype-format formals list with it. Once 4461 these match-ups are made, the conversion of the function declarations 4462 to prototype format can be made. */ 4463 4464 visit_each_hash_node (function_name_primary, connect_defs_and_decs); 4465 4466 #endif /* !defined (UNPROTOIZE) */ 4467 4468 /* Now convert each file that can be converted (and needs to be). */ 4469 4470 visit_each_hash_node (filename_primary, edit_file); 4471 4472 #ifndef UNPROTOIZE 4473 4474 /* If we are working in cplusplus mode, try to rename all .c files to .C 4475 files. Don't panic if some of the renames don't work. */ 4476 4477 if (cplusplus_flag && !nochange_flag) 4478 visit_each_hash_node (filename_primary, rename_c_file); 4479 4480 #endif /* !defined (UNPROTOIZE) */ 4481 } 4482 4483 static const struct option longopts[] = 4484 { 4485 {"version", 0, 0, 'V'}, 4486 {"file_name", 0, 0, 'p'}, 4487 {"quiet", 0, 0, 'q'}, 4488 {"silent", 0, 0, 'q'}, 4489 {"force", 0, 0, 'f'}, 4490 {"keep", 0, 0, 'k'}, 4491 {"nosave", 0, 0, 'N'}, 4492 {"nochange", 0, 0, 'n'}, 4493 {"compiler-options", 1, 0, 'c'}, 4494 {"exclude", 1, 0, 'x'}, 4495 {"directory", 1, 0, 'd'}, 4496 #ifdef UNPROTOIZE 4497 {"indent", 1, 0, 'i'}, 4498 #else 4499 {"local", 0, 0, 'l'}, 4500 {"global", 0, 0, 'g'}, 4501 {"c++", 0, 0, 'C'}, 4502 {"syscalls-dir", 1, 0, 'B'}, 4503 #endif 4504 {0, 0, 0, 0} 4505 }; 4506 4507 extern int main PARAMS ((int, char **const)); 4508 4509 int 4510 main (argc, argv) 4511 int argc; 4512 char **const argv; 4513 { 4514 int longind; 4515 int c; 4516 const char *params = ""; 4517 4518 pname = strrchr (argv[0], DIR_SEPARATOR); 4519 #ifdef DIR_SEPARATOR_2 4520 { 4521 char *slash; 4522 4523 slash = strrchr (pname ? pname : argv[0], DIR_SEPARATOR_2); 4524 if (slash) 4525 pname = slash; 4526 } 4527 #endif 4528 pname = pname ? pname+1 : argv[0]; 4529 4530 #ifdef SIGCHLD 4531 /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will 4532 receive the signal. A different setting is inheritable */ 4533 signal (SIGCHLD, SIG_DFL); 4534 #endif 4535 4536 gcc_init_libintl (); 4537 4538 cwd_buffer = getpwd (); 4539 if (!cwd_buffer) 4540 { 4541 notice ("%s: cannot get working directory: %s\n", 4542 pname, xstrerror(errno)); 4543 return (FATAL_EXIT_CODE); 4544 } 4545 4546 /* By default, convert the files in the current directory. */ 4547 directory_list = string_list_cons (cwd_buffer, NULL); 4548 4549 while ((c = getopt_long (argc, argv, 4550 #ifdef UNPROTOIZE 4551 "c:d:i:knNp:qvVx:", 4552 #else 4553 "B:c:Cd:gklnNp:qvVx:", 4554 #endif 4555 longopts, &longind)) != EOF) 4556 { 4557 if (c == 0) /* Long option. */ 4558 c = longopts[longind].val; 4559 switch (c) 4560 { 4561 case 'p': 4562 compiler_file_name = optarg; 4563 break; 4564 case 'd': 4565 directory_list 4566 = string_list_cons (abspath (NULL, optarg), directory_list); 4567 break; 4568 case 'x': 4569 exclude_list = string_list_cons (optarg, exclude_list); 4570 break; 4571 4572 case 'v': 4573 case 'V': 4574 version_flag = 1; 4575 break; 4576 case 'q': 4577 quiet_flag = 1; 4578 break; 4579 #if 0 4580 case 'f': 4581 force_flag = 1; 4582 break; 4583 #endif 4584 case 'n': 4585 nochange_flag = 1; 4586 keep_flag = 1; 4587 break; 4588 case 'N': 4589 nosave_flag = 1; 4590 break; 4591 case 'k': 4592 keep_flag = 1; 4593 break; 4594 case 'c': 4595 params = optarg; 4596 break; 4597 #ifdef UNPROTOIZE 4598 case 'i': 4599 indent_string = optarg; 4600 break; 4601 #else /* !defined (UNPROTOIZE) */ 4602 case 'l': 4603 local_flag = 1; 4604 break; 4605 case 'g': 4606 global_flag = 1; 4607 break; 4608 case 'C': 4609 cplusplus_flag = 1; 4610 break; 4611 case 'B': 4612 nondefault_syscalls_dir = optarg; 4613 break; 4614 #endif /* !defined (UNPROTOIZE) */ 4615 default: 4616 usage (); 4617 } 4618 } 4619 4620 /* Set up compile_params based on -p and -c options. */ 4621 munge_compile_params (params); 4622 4623 n_base_source_files = argc - optind; 4624 4625 /* Now actually make a list of the base source filenames. */ 4626 4627 base_source_filenames 4628 = (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *)); 4629 n_base_source_files = 0; 4630 for (; optind < argc; optind++) 4631 { 4632 const char *path = abspath (NULL, argv[optind]); 4633 int len = strlen (path); 4634 4635 if (path[len-1] == 'c' && path[len-2] == '.') 4636 base_source_filenames[n_base_source_files++] = path; 4637 else 4638 { 4639 notice ("%s: input file names must have .c suffixes: %s\n", 4640 pname, shortpath (NULL, path)); 4641 errors++; 4642 } 4643 } 4644 4645 #ifndef UNPROTOIZE 4646 /* We are only interested in the very first identifier token in the 4647 definition of `va_list', so if there is more junk after that first 4648 identifier token, delete it from the `varargs_style_indicator'. */ 4649 { 4650 const char *cp; 4651 4652 for (cp = varargs_style_indicator; ISIDNUM (*cp); cp++) 4653 continue; 4654 if (*cp != 0) 4655 varargs_style_indicator = savestring (varargs_style_indicator, 4656 cp - varargs_style_indicator); 4657 } 4658 #endif /* !defined (UNPROTOIZE) */ 4659 4660 if (errors) 4661 usage (); 4662 else 4663 { 4664 if (version_flag) 4665 fprintf (stderr, "%s: %s\n", pname, version_string); 4666 do_processing (); 4667 } 4668 4669 return (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 4670 } 4671