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