Annotation of gcc/protoize.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.