Annotation of GNUtools/cc/protoize.c, revision 1.1

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

unix.superglobalmegacorp.com

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