OSDN Git Service

more rigorous SIGCHLD guarding
[pf3gnuchains/gcc-fork.git] / gcc / protoize.c
1 /* Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com).
2    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3    1999, 2000 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, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "intl.h"
25
26 #include <setjmp.h>
27 #include <signal.h>
28 #if ! defined( SIGCHLD ) && defined( SIGCLD )
29 #  define SIGCHLD SIGCLD
30 #endif
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 #undef abort
35 #include "version.h"
36
37 /* Include getopt.h for the sake of getopt_long. */
38 #include "getopt.h"
39
40 /* Macro to see if the path elements match.  */
41 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
42 #define IS_SAME_PATH_CHAR(a,b) (TOUPPER (a) == TOUPPER (b))
43 #else
44 #define IS_SAME_PATH_CHAR(a,b) ((a) == (b))
45 #endif
46
47 /* Macro to see if the paths match.  */
48 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
49 #define IS_SAME_PATH(a,b) (strcasecmp (a, b) == 0)
50 #else
51 #define IS_SAME_PATH(a,b) (strcmp (a, b) == 0)
52 #endif
53
54 /* Suffix for aux-info files.  */
55 #ifdef __MSDOS__
56 #define AUX_INFO_SUFFIX "X"
57 #else
58 #define AUX_INFO_SUFFIX ".X"
59 #endif
60
61 /* Suffix for saved files.  */
62 #ifdef __MSDOS__
63 #define SAVE_SUFFIX "sav"
64 #else
65 #define SAVE_SUFFIX ".save"
66 #endif
67
68 /* Suffix for renamed C++ files.  */
69 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
70 #define CPLUS_FILE_SUFFIX "cc"
71 #else
72 #define CPLUS_FILE_SUFFIX "C"
73 #endif
74
75 static void usage PARAMS ((void)) ATTRIBUTE_NORETURN;
76 static void aux_info_corrupted PARAMS ((void)) ATTRIBUTE_NORETURN;
77 static void declare_source_confusing PARAMS ((const char *)) ATTRIBUTE_NORETURN;
78 static const char *shortpath PARAMS ((const char *, const char *));
79 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
80 static void notice PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
81 static char *savestring PARAMS ((const char *, unsigned int));
82 static char *dupnstr PARAMS ((const char *, size_t));
83 static const char *substr PARAMS ((const char *, const char * const));
84 static int safe_read PARAMS ((int, PTR, int));
85 static void safe_write PARAMS ((int, PTR, int, const char *));
86 static void save_pointers PARAMS ((void));
87 static void restore_pointers PARAMS ((void));
88 static int is_id_char PARAMS ((int));
89 static int in_system_include_dir PARAMS ((const char *));
90 static int directory_specified_p PARAMS ((const char *));
91 static int file_excluded_p PARAMS ((const char *));
92 static char *unexpand_if_needed PARAMS ((const char *));
93 static char *abspath PARAMS ((const char *, const char *));
94 static int is_abspath PARAMS ((const char *));
95 static void check_aux_info PARAMS ((int));
96 static const char *find_corresponding_lparen PARAMS ((const char *));
97 static int referenced_file_is_newer PARAMS ((const char *, time_t));
98 static void save_def_or_dec PARAMS ((const char *, int));
99 static void munge_compile_params PARAMS ((const char *));
100 static int gen_aux_info_file PARAMS ((const char *));
101 static void process_aux_info_file PARAMS ((const char *, int, int));
102 static int identify_lineno PARAMS ((const char *));
103 static void check_source PARAMS ((int, const char *));
104 static const char *seek_to_line PARAMS ((int));
105 static const char *forward_to_next_token_char PARAMS ((const char *));
106 static void output_bytes PARAMS ((const char *, size_t));
107 static void output_string PARAMS ((const char *));
108 static void output_up_to PARAMS ((const char *));
109 static int other_variable_style_function PARAMS ((const char *));
110 static const char *find_rightmost_formals_list PARAMS ((const char *));
111 static void do_cleaning PARAMS ((char *, const char *));
112 static const char *careful_find_l_paren PARAMS ((const char *));
113 static void do_processing PARAMS ((void));
114
115 /* Look for these where the `const' qualifier is intentionally cast aside.  */
116 #define NONCONST
117
118 /* Define a default place to find the SYSCALLS.X file.  */
119
120 #ifndef UNPROTOIZE
121
122 #ifndef STANDARD_EXEC_PREFIX
123 #define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
124 #endif /* !defined STANDARD_EXEC_PREFIX */
125
126 static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX;
127 static const char * const target_machine = DEFAULT_TARGET_MACHINE;
128 static const char * const target_version = DEFAULT_TARGET_VERSION;
129
130 #ifndef GET_ENV_PATH_LIST
131 #define GET_ENV_PATH_LIST(VAR,NAME)     do { (VAR) = getenv (NAME); } while (0)
132 #endif
133
134 #endif /* !defined (UNPROTOIZE) */
135
136 /* Suffix of aux_info files.  */
137
138 static const char * const aux_info_suffix = AUX_INFO_SUFFIX;
139
140 /* String to attach to filenames for saved versions of original files.  */
141
142 static const char * const save_suffix = SAVE_SUFFIX;
143
144 /* String to attach to C filenames renamed to C++.  */
145
146 static const char * const cplus_suffix = CPLUS_FILE_SUFFIX;
147
148 #ifndef UNPROTOIZE
149
150 /* File name of the file which contains descriptions of standard system
151    routines.  Note that we never actually do anything with this file per se,
152    but we do read in its corresponding aux_info file.  */
153
154 static const char syscalls_filename[] = "SYSCALLS.c";
155
156 /* Default place to find the above file.  */
157
158 static const char * default_syscalls_dir;
159
160 /* Variable to hold the complete absolutized filename of the SYSCALLS.c.X
161    file.  */
162
163 static char * syscalls_absolute_filename;
164
165 #endif /* !defined (UNPROTOIZE) */
166
167 /* Type of the structure that holds information about macro unexpansions.  */
168
169 struct unexpansion_struct {
170   const char *expanded;
171   const char *contracted;
172 };
173 typedef struct unexpansion_struct unexpansion;
174
175 /* A table of conversions that may need to be made for some (stupid) older
176    operating systems where these types are preprocessor macros rather than
177    typedefs (as they really ought to be).
178
179    WARNING: The contracted forms must be as small (or smaller) as the
180    expanded forms, or else havoc will ensue.  */
181
182 static const unexpansion unexpansions[] = {
183   { "struct _iobuf", "FILE" },
184   { 0, 0 }
185 };
186
187 /* The number of "primary" slots in the hash tables for filenames and for
188    function names.  This can be as big or as small as you like, except that
189    it must be a power of two.  */
190
191 #define HASH_TABLE_SIZE         (1 << 9)
192
193 /* Bit mask to use when computing hash values.  */
194
195 static const int hash_mask = (HASH_TABLE_SIZE - 1);
196
197 /* Make a table of default system include directories
198    just as it is done in cpp.  */
199
200 #ifndef STANDARD_INCLUDE_DIR
201 #define STANDARD_INCLUDE_DIR "/usr/include"
202 #endif
203
204 #ifndef LOCAL_INCLUDE_DIR
205 #define LOCAL_INCLUDE_DIR "/usr/local/include"
206 #endif
207
208 struct default_include { const char *fname; 
209                          const char *component;
210                          int x1, x2; } include_defaults[]
211 #ifdef INCLUDE_DEFAULTS
212   = INCLUDE_DEFAULTS;
213 #else
214   = {
215     /* Pick up GNU C++ specific include files.  */
216     { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
217 #ifdef CROSS_COMPILE
218     /* This is the dir for fixincludes.  Put it just before
219        the files that we fix.  */
220     { GCC_INCLUDE_DIR, "GCC", 0, 0 },
221     /* For cross-compilation, this dir name is generated
222        automatically in Makefile.in.  */
223     { CROSS_INCLUDE_DIR, 0, 0, 0 },
224     /* This is another place that the target system's headers might be.  */
225     { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
226 #else /* not CROSS_COMPILE */
227     /* This should be /use/local/include and should come before
228        the fixincludes-fixed header files.  */
229     { LOCAL_INCLUDE_DIR, 0, 0, 1 },
230     /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
231        Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h.  */
232     { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
233     /* This is the dir for fixincludes.  Put it just before
234        the files that we fix.  */
235     { GCC_INCLUDE_DIR, "GCC", 0, 0 },
236     /* Some systems have an extra dir of include files.  */
237 #ifdef SYSTEM_INCLUDE_DIR
238     { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
239 #endif
240     { STANDARD_INCLUDE_DIR, 0, 0, 0},
241 #endif /* not CROSS_COMPILE */
242     { 0, 0, 0, 0}
243     };
244 #endif /* no INCLUDE_DEFAULTS */
245
246 /* Datatype for lists of directories or filenames.  */
247 struct string_list
248 {
249   const char *name;
250   struct string_list *next;
251 };
252
253 static struct string_list *string_list_cons PARAMS ((const char *,
254                                                      struct string_list *));
255
256 /* List of directories in which files should be converted.  */
257
258 struct string_list *directory_list;
259
260 /* List of file names which should not be converted.
261    A file is excluded if the end of its name, following a /,
262    matches one of the names in this list.  */
263
264 struct string_list *exclude_list;
265
266 /* The name of the other style of variable-number-of-parameters functions
267    (i.e. the style that we want to leave unconverted because we don't yet
268    know how to convert them to this style.  This string is used in warning
269    messages.  */
270
271 /* Also define here the string that we can search for in the parameter lists
272    taken from the .X files which will unambiguously indicate that we have
273    found a varargs style function.  */
274
275 #ifdef UNPROTOIZE
276 static const char * const other_var_style = "stdarg";
277 #else /* !defined (UNPROTOIZE) */
278 static const char * const other_var_style = "varargs";
279 /* Note that this is a string containing the expansion of va_alist.
280    But in `main' we discard all but the first token.  */
281 static const char *varargs_style_indicator = STRINGIFY (va_alist);
282 #endif /* !defined (UNPROTOIZE) */
283
284 /* The following two types are used to create hash tables.  In this program,
285    there are two hash tables which are used to store and quickly lookup two
286    different classes of strings.  The first type of strings stored in the
287    first hash table are absolute filenames of files which protoize needs to
288    know about.  The second type of strings (stored in the second hash table)
289    are function names.  It is this second class of strings which really
290    inspired the use of the hash tables, because there may be a lot of them.  */
291
292 typedef struct hash_table_entry_struct hash_table_entry;
293
294 /* Do some typedefs so that we don't have to write "struct" so often.  */
295
296 typedef struct def_dec_info_struct def_dec_info;
297 typedef struct file_info_struct file_info;
298 typedef struct f_list_chain_item_struct f_list_chain_item;
299
300 #ifndef UNPROTOIZE
301 static int is_syscalls_file PARAMS ((const file_info *));
302 static void rename_c_file PARAMS ((const hash_table_entry *));
303 static const def_dec_info *find_extern_def PARAMS ((const def_dec_info *,
304                                                     const def_dec_info *));
305 static const def_dec_info *find_static_definition PARAMS ((const def_dec_info *));
306 static void connect_defs_and_decs PARAMS ((const hash_table_entry *));
307 static void add_local_decl PARAMS ((const def_dec_info *, const char *));
308 static void add_global_decls PARAMS ((const file_info *, const char *));
309 #endif /* ! UNPROTOIZE */
310 static int needs_to_be_converted PARAMS ((const file_info *));
311 static void visit_each_hash_node PARAMS ((const hash_table_entry *,
312                                           void (*)(const hash_table_entry *)));
313 static hash_table_entry *add_symbol PARAMS ((hash_table_entry *, const char *));
314 static hash_table_entry *lookup PARAMS ((hash_table_entry *, const char *));
315 static void free_def_dec PARAMS ((def_dec_info *));
316 static file_info *find_file PARAMS ((const char *, int));
317 static void reverse_def_dec_list PARAMS ((const hash_table_entry *));
318 static void edit_fn_declaration PARAMS ((const def_dec_info *, const char *));
319 static int edit_formals_lists PARAMS ((const char *, unsigned int,
320                                        const def_dec_info *));
321 static void edit_fn_definition PARAMS ((const def_dec_info *, const char *));
322 static void scan_for_missed_items PARAMS ((const file_info *));
323 static void edit_file PARAMS ((const hash_table_entry *));
324
325 /* In the struct below, note that the "_info" field has two different uses
326    depending on the type of hash table we are in (i.e. either the filenames
327    hash table or the function names hash table).  In the filenames hash table
328    the info fields of the entries point to the file_info struct which is
329    associated with each filename (1 per filename).  In the function names
330    hash table, the info field points to the head of a singly linked list of
331    def_dec_info entries which are all defs or decs of the function whose
332    name is pointed to by the "symbol" field.  Keeping all of the defs/decs
333    for a given function name on a special list specifically for that function
334    name makes it quick and easy to find out all of the important information
335    about a given (named) function.  */
336
337 struct hash_table_entry_struct {
338   hash_table_entry *            hash_next;      /* -> to secondary entries */
339   const char *                  symbol;         /* -> to the hashed string */
340   union {
341     const def_dec_info *        _ddip;
342     file_info *                 _fip;
343   } _info;
344 };
345 #define ddip _info._ddip
346 #define fip _info._fip
347
348 /* Define a type specifically for our two hash tables.  */
349
350 typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
351
352 /* The following struct holds all of the important information about any
353    single filename (e.g. file) which we need to know about.  */
354
355 struct file_info_struct {
356   const hash_table_entry *      hash_entry; /* -> to associated hash entry */
357   const def_dec_info *          defs_decs;  /* -> to chain of defs/decs */
358   time_t                        mtime;      /* Time of last modification.  */
359 };
360
361 /* Due to the possibility that functions may return pointers to functions,
362    (which may themselves have their own parameter lists) and due to the
363    fact that returned pointers-to-functions may be of type "pointer-to-
364    function-returning-pointer-to-function" (ad nauseum) we have to keep
365    an entire chain of ANSI style formal parameter lists for each function.
366
367    Normally, for any given function, there will only be one formals list
368    on the chain, but you never know.
369
370    Note that the head of each chain of formals lists is pointed to by the
371    `f_list_chain' field of the corresponding def_dec_info record.
372
373    For any given chain, the item at the head of the chain is the *leftmost*
374    parameter list seen in the actual C language function declaration.  If
375    there are other members of the chain, then these are linked in left-to-right
376    order from the head of the chain.  */
377
378 struct f_list_chain_item_struct {
379   const f_list_chain_item *     chain_next;     /* -> to next item on chain */
380   const char *                  formals_list;   /* -> to formals list string */
381 };
382
383 /* The following struct holds all of the important information about any
384    single function definition or declaration which we need to know about.
385    Note that for unprotoize we don't need to know very much because we
386    never even create records for stuff that we don't intend to convert
387    (like for instance defs and decs which are already in old K&R format
388    and "implicit" function declarations).  */
389
390 struct def_dec_info_struct {
391   const def_dec_info *  next_in_file;   /* -> to rest of chain for file */
392   file_info *           file;           /* -> file_info for containing file */
393   int                   line;           /* source line number of def/dec */
394   const char *          ansi_decl;      /* -> left end of ansi decl */
395   hash_table_entry *    hash_entry;     /* -> hash entry for function name */
396   unsigned int          is_func_def;    /* = 0 means this is a declaration */
397   const def_dec_info *  next_for_func;  /* -> to rest of chain for func name */
398   unsigned int          f_list_count;   /* count of formals lists we expect */
399   char                  prototyped;     /* = 0 means already prototyped */
400 #ifndef UNPROTOIZE
401   const f_list_chain_item * f_list_chain;       /* -> chain of formals lists */
402   const def_dec_info *  definition;     /* -> def/dec containing related def */
403   char                  is_static;      /* = 0 means visibility is "extern"  */
404   char                  is_implicit;    /* != 0 for implicit func decl's */
405   char                  written;        /* != 0 means written for implicit */
406 #else /* !defined (UNPROTOIZE) */
407   const char *          formal_names;   /* -> to list of names of formals */
408   const char *          formal_decls;   /* -> to string of formal declarations */
409 #endif /* !defined (UNPROTOIZE) */
410 };
411
412 /* Pointer to the tail component of the filename by which this program was
413    invoked.  Used everywhere in error and warning messages.  */
414
415 static const char *pname;
416
417 /* Error counter.  Will be non-zero if we should give up at the next convenient
418    stopping point.  */
419
420 static int errors = 0;
421
422 /* Option flags.  */
423 /* ??? These comments should say what the flag mean as well as the options
424    that set them.  */
425
426 /* File name to use for running gcc.  Allows GCC 2 to be named
427    something other than gcc.  */
428 static const char *compiler_file_name = "gcc";
429
430 static int version_flag = 0;            /* Print our version number.  */
431 static int quiet_flag = 0;              /* Don't print messages normally.  */
432 static int nochange_flag = 0;           /* Don't convert, just say what files
433                                            we would have converted.  */
434 static int nosave_flag = 0;             /* Don't save the old version.  */
435 static int keep_flag = 0;               /* Don't delete the .X files.  */
436 static const char ** compile_params = 0;        /* Option string for gcc.  */
437 #ifdef UNPROTOIZE
438 static const char *indent_string = "     ";     /* Indentation for newly
439                                                    inserted parm decls.  */
440 #else /* !defined (UNPROTOIZE) */
441 static int local_flag = 0;              /* Insert new local decls (when?).  */
442 static int global_flag = 0;             /* set by -g option */
443 static int cplusplus_flag = 0;          /* Rename converted files to *.C.  */
444 static const char *nondefault_syscalls_dir = 0; /* Dir to look for
445                                                    SYSCALLS.c.X in.  */
446 #endif /* !defined (UNPROTOIZE) */
447
448 /* An index into the compile_params array where we should insert the source
449    file name when we are ready to exec the C compiler.  A zero value indicates
450    that we have not yet called munge_compile_params.  */
451
452 static int input_file_name_index = 0;
453
454 /* An index into the compile_params array where we should insert the filename
455    for the aux info file, when we run the C compiler.  */
456 static int aux_info_file_name_index = 0;
457
458 /* Count of command line arguments which were "filename" arguments.  */
459
460 static int n_base_source_files = 0;
461
462 /* Points to a malloc'ed list of pointers to all of the filenames of base
463    source files which were specified on the command line.  */
464
465 static const char **base_source_filenames;
466
467 /* Line number of the line within the current aux_info file that we
468    are currently processing.  Used for error messages in case the prototypes
469    info file is corrupted somehow.  */
470
471 static int current_aux_info_lineno;
472
473 /* Pointer to the name of the source file currently being converted.  */
474
475 static const char *convert_filename;
476
477 /* Pointer to relative root string (taken from aux_info file) which indicates
478    where directory the user was in when he did the compilation step that
479    produced the containing aux_info file.  */
480
481 static const char *invocation_filename;
482
483 /* Pointer to the base of the input buffer that holds the original text for the
484    source file currently being converted.  */
485
486 static const char *orig_text_base;
487
488 /* Pointer to the byte just beyond the end of the input buffer that holds the
489    original text for the source file currently being converted.  */
490
491 static const char *orig_text_limit;
492
493 /* Pointer to the base of the input buffer that holds the cleaned text for the
494    source file currently being converted.  */
495
496 static const char *clean_text_base;
497
498 /* Pointer to the byte just beyond the end of the input buffer that holds the
499    cleaned text for the source file currently being converted.  */
500
501 static const char *clean_text_limit;
502
503 /* Pointer to the last byte in the cleaned text buffer that we have already
504    (virtually) copied to the output buffer (or decided to ignore).  */
505
506 static const char * clean_read_ptr;
507
508 /* Pointer to the base of the output buffer that holds the replacement text
509    for the source file currently being converted.  */
510
511 static char *repl_text_base;
512
513 /* Pointer to the byte just beyond the end of the output buffer that holds the
514    replacement text for the source file currently being converted.  */
515
516 static char *repl_text_limit;
517
518 /* Pointer to the last byte which has been stored into the output buffer.
519    The next byte to be stored should be stored just past where this points
520    to.  */
521
522 static char * repl_write_ptr;
523
524 /* Pointer into the cleaned text buffer for the source file we are currently
525    converting.  This points to the first character of the line that we last
526    did a "seek_to_line" to (see below).  */
527
528 static const char *last_known_line_start;
529
530 /* Number of the line (in the cleaned text buffer) that we last did a
531    "seek_to_line" to.  Will be one if we just read a new source file
532    into the cleaned text buffer.  */
533
534 static int last_known_line_number;
535
536 /* The filenames hash table.  */
537
538 static hash_table filename_primary;
539
540 /* The function names hash table.  */
541
542 static hash_table function_name_primary;
543
544 /* The place to keep the recovery address which is used only in cases where
545    we get hopelessly confused by something in the cleaned original text.  */
546
547 static jmp_buf source_confusion_recovery;
548
549 /* A pointer to the current directory filename (used by abspath).  */
550
551 static char *cwd_buffer;
552
553 /* A place to save the read pointer until we are sure that an individual
554    attempt at editing will succeed.  */
555
556 static const char * saved_clean_read_ptr;
557
558 /* A place to save the write pointer until we are sure that an individual
559    attempt at editing will succeed.  */
560
561 static char * saved_repl_write_ptr;
562 \f
563 /* Translate and output an error message.  */
564 static void
565 notice VPARAMS ((const char *msgid, ...))
566 {
567 #ifndef ANSI_PROTOTYPES
568   const char *msgid;
569 #endif
570   va_list ap;
571
572   VA_START (ap, msgid);
573
574 #ifndef ANSI_PROTOTYPES
575   msgid = va_arg (ap, const char *);
576 #endif
577
578   vfprintf (stderr, _(msgid), ap);
579   va_end (ap);
580 }
581
582 \f
583 /* Make a copy of a string INPUT with size SIZE.  */
584
585 static char *
586 savestring (input, size)
587      const char *input;
588      unsigned int size;
589 {
590   char *output = (char *) xmalloc (size + 1);
591   strcpy (output, input);
592   return output;
593 }
594
595 /* More 'friendly' abort that prints the line and file.
596    config.h can #define abort fancy_abort if you like that sort of thing.  */
597
598 void
599 fancy_abort ()
600 {
601   notice ("%s: internal abort\n", pname);
602   exit (FATAL_EXIT_CODE);
603 }
604 \f
605 /* Make a duplicate of the first N bytes of a given string in a newly
606    allocated area.  */
607
608 static char *
609 dupnstr (s, n)
610      const char *s;
611      size_t n;
612 {
613   char *ret_val = (char *) xmalloc (n + 1);
614
615   strncpy (ret_val, s, n);
616   ret_val[n] = '\0';
617   return ret_val;
618 }
619
620 /* Return a pointer to the first occurrence of s2 within s1 or NULL if s2
621    does not occur within s1.  Assume neither s1 nor s2 are null pointers.  */
622
623 static const char *
624 substr (s1, s2)
625      const char *s1;
626      const char *const s2;
627 {
628   for (; *s1 ; s1++)
629     {
630       const char *p1;
631       const char *p2;
632       int c;
633
634       for (p1 = s1, p2 = s2; (c = *p2); p1++, p2++)
635         if (*p1 != c)
636           goto outer;
637       return s1;
638 outer:
639       ;
640     }
641   return 0;
642 }
643 \f
644 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
645    retrying if necessary.  Return the actual number of bytes read.  */
646
647 static int
648 safe_read (desc, ptr, len)
649      int desc;
650      PTR ptr;
651      int len;
652 {
653   int left = len;
654   while (left > 0) {
655     int nchars = read (desc, ptr, left);
656     if (nchars < 0)
657       {
658 #ifdef EINTR
659         if (errno == EINTR)
660           continue;
661 #endif
662         return nchars;
663       }
664     if (nchars == 0)
665       break;
666     /* Arithmetic on void pointers is a gcc extention.  */
667     ptr = (char *) ptr + nchars;
668     left -= nchars;
669   }
670   return len - left;
671 }
672
673 /* Write LEN bytes at PTR to descriptor DESC,
674    retrying if necessary, and treating any real error as fatal.  */
675
676 static void
677 safe_write (desc, ptr, len, out_fname)
678      int desc;
679      PTR ptr;
680      int len;
681      const char *out_fname;
682 {
683   while (len > 0) {
684     int written = write (desc, ptr, len);
685     if (written < 0)
686       {
687         int errno_val = errno;
688 #ifdef EINTR
689         if (errno_val == EINTR)
690           continue;
691 #endif
692         notice ("%s: error writing file `%s': %s\n",
693                 pname, shortpath (NULL, out_fname), xstrerror (errno_val));
694         return;
695       }
696     /* Arithmetic on void pointers is a gcc extention.  */
697     ptr = (char *) ptr + written;
698     len -= written;
699   }
700 }
701 \f
702 /* Get setup to recover in case the edit we are about to do goes awry.  */
703
704 static void
705 save_pointers ()
706 {
707   saved_clean_read_ptr = clean_read_ptr;
708   saved_repl_write_ptr = repl_write_ptr;
709 }
710
711 /* Call this routine to recover our previous state whenever something looks
712    too confusing in the source code we are trying to edit.  */
713
714 static void
715 restore_pointers ()
716 {
717   clean_read_ptr = saved_clean_read_ptr;
718   repl_write_ptr = saved_repl_write_ptr;
719 }
720
721 /* Return true if the given character is a valid identifier character.  */
722
723 static int
724 is_id_char (ch)
725      int ch;
726 {
727   return (ISALNUM (ch) || (ch == '_') || (ch == '$'));
728 }
729
730 /* Give a message indicating the proper way to invoke this program and then
731    exit with non-zero status.  */
732
733 static void
734 usage ()
735 {
736 #ifdef UNPROTOIZE
737   notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
738           pname, pname);
739 #else /* !defined (UNPROTOIZE) */
740   notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
741           pname, pname);
742 #endif /* !defined (UNPROTOIZE) */
743   exit (FATAL_EXIT_CODE);
744 }
745
746 /* Return true if the given filename (assumed to be an absolute filename)
747    designates a file residing anywhere beneath any one of the "system"
748    include directories.  */
749
750 static int
751 in_system_include_dir (path)
752      const char *path;
753 {
754   struct default_include *p;
755
756   if (! is_abspath (path))
757     abort ();           /* Must be an absolutized filename.  */
758
759   for (p = include_defaults; p->fname; p++)
760     if (!strncmp (path, p->fname, strlen (p->fname))
761         && IS_DIR_SEPARATOR (path[strlen (p->fname)]))
762       return 1;
763   return 0;
764 }
765 \f
766 #if 0
767 /* Return true if the given filename designates a file that the user has
768    read access to and for which the user has write access to the containing
769    directory.  */
770
771 static int
772 file_could_be_converted (const char *path)
773 {
774   char *const dir_name = (char *) alloca (strlen (path) + 1);
775
776   if (access (path, R_OK))
777     return 0;
778
779   {
780     char *dir_last_slash;
781
782     strcpy (dir_name, path);
783     dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
784 #ifdef DIR_SEPARATOR_2
785     {
786       char *slash;
787
788       slash = strrchr (dir_last_slash ? dir_last_slash : dir_name, 
789                        DIR_SEPARATOR_2);
790       if (slash)
791         dir_last_slash = slash;
792     }
793 #endif
794     if (dir_last_slash)
795       *dir_last_slash = '\0';
796     else
797       abort ();  /* Should have been an absolutized filename.  */
798   }
799
800   if (access (path, W_OK))
801     return 0;
802
803   return 1;
804 }
805
806 /* Return true if the given filename designates a file that we are allowed
807    to modify.  Files which we should not attempt to modify are (a) "system"
808    include files, and (b) files which the user doesn't have write access to,
809    and (c) files which reside in directories which the user doesn't have
810    write access to.  Unless requested to be quiet, give warnings about
811    files that we will not try to convert for one reason or another.  An
812    exception is made for "system" include files, which we never try to
813    convert and for which we don't issue the usual warnings.  */
814
815 static int
816 file_normally_convertible (const char *path)
817 {
818   char *const dir_name = alloca (strlen (path) + 1);
819
820   if (in_system_include_dir (path))
821     return 0;
822
823   {
824     char *dir_last_slash;
825
826     strcpy (dir_name, path);
827     dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
828 #ifdef DIR_SEPARATOR_2
829     {
830       char *slash;
831
832       slash = strrchr (dir_last_slash ? dir_last_slash : dir_name, 
833                        DIR_SEPARATOR_2);
834       if (slash)
835         dir_last_slash = slash;
836     }
837 #endif
838     if (dir_last_slash)
839       *dir_last_slash = '\0';
840     else
841       abort ();  /* Should have been an absolutized filename.  */
842   }
843
844   if (access (path, R_OK))
845     {
846       if (!quiet_flag)
847         notice ("%s: warning: no read access for file `%s'\n",
848                 pname, shortpath (NULL, path));
849       return 0;
850     }
851
852   if (access (path, W_OK))
853     {
854       if (!quiet_flag)
855         notice ("%s: warning: no write access for file `%s'\n",
856                 pname, shortpath (NULL, path));
857       return 0;
858     }
859
860   if (access (dir_name, W_OK))
861     {
862       if (!quiet_flag)
863         notice ("%s: warning: no write access for dir containing `%s'\n",
864                 pname, shortpath (NULL, path));
865       return 0;
866     }
867
868   return 1;
869 }
870 #endif /* 0 */
871 \f
872 #ifndef UNPROTOIZE
873
874 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X
875    file.  Return false otherwise.  */
876
877 static int
878 is_syscalls_file (fi_p)
879      const file_info *fi_p;
880 {
881   char const *f = fi_p->hash_entry->symbol;
882   size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
883   return sysl <= fl  &&  strcmp (f + fl - sysl, syscalls_filename) == 0;
884 }
885
886 #endif /* !defined (UNPROTOIZE) */
887
888 /* Check to see if this file will need to have anything done to it on this
889    run.  If there is nothing in the given file which both needs conversion
890    and for which we have the necessary stuff to do the conversion, return
891    false.  Otherwise, return true.
892
893    Note that (for protoize) it is only valid to call this function *after*
894    the connections between declarations and definitions have all been made
895    by connect_defs_and_decs.  */
896
897 static int
898 needs_to_be_converted (file_p)
899      const file_info *file_p;
900 {
901   const def_dec_info *ddp;
902
903 #ifndef UNPROTOIZE
904
905   if (is_syscalls_file (file_p))
906     return 0;
907
908 #endif /* !defined (UNPROTOIZE) */
909
910   for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
911
912     if (
913
914 #ifndef UNPROTOIZE
915
916       /* ... and if we a protoizing and this function is in old style ...  */
917       !ddp->prototyped
918       /* ... and if this a definition or is a decl with an associated def ...  */
919       && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
920
921 #else /* defined (UNPROTOIZE) */
922
923       /* ... and if we are unprotoizing and this function is in new style ...  */
924       ddp->prototyped
925
926 #endif /* defined (UNPROTOIZE) */
927       )
928           /* ... then the containing file needs converting.  */
929           return -1;
930   return 0;
931 }
932
933 /* Return 1 if the file name NAME is in a directory
934    that should be converted.  */
935
936 static int
937 directory_specified_p (name)
938      const char *name;
939 {
940   struct string_list *p;
941
942   for (p = directory_list; p; p = p->next)
943     if (!strncmp (name, p->name, strlen (p->name))
944         && IS_DIR_SEPARATOR (name[strlen (p->name)]))
945       {
946         const char *q = name + strlen (p->name) + 1;
947
948         /* If there are more slashes, it's in a subdir, so
949            this match doesn't count.  */
950         while (*q++)
951           if (IS_DIR_SEPARATOR (*(q-1)))
952             goto lose;
953         return 1;
954
955       lose: ;
956       }
957
958   return 0;
959 }
960
961 /* Return 1 if the file named NAME should be excluded from conversion.  */
962
963 static int
964 file_excluded_p (name)
965      const char *name;
966 {
967   struct string_list *p;
968   int len = strlen (name);
969
970   for (p = exclude_list; p; p = p->next)
971     if (!strcmp (name + len - strlen (p->name), p->name)
972         && IS_DIR_SEPARATOR (name[len - strlen (p->name) - 1]))
973       return 1;
974
975   return 0;
976 }
977
978 /* Construct a new element of a string_list.
979    STRING is the new element value, and REST holds the remaining elements.  */
980
981 static struct string_list *
982 string_list_cons (string, rest)
983      const char *string;
984      struct string_list *rest;
985 {
986   struct string_list *temp
987     = (struct string_list *) xmalloc (sizeof (struct string_list));
988
989   temp->next = rest;
990   temp->name = string;
991   return temp;
992 }
993 \f
994 /* ??? The GNU convention for mentioning function args in its comments
995    is to capitalize them.  So change "hash_tab_p" to HASH_TAB_P below.
996    Likewise for all the other functions.  */
997
998 /* Given a hash table, apply some function to each node in the table. The
999    table to traverse is given as the "hash_tab_p" argument, and the
1000    function to be applied to each node in the table is given as "func"
1001    argument.  */
1002
1003 static void
1004 visit_each_hash_node (hash_tab_p, func)
1005      const hash_table_entry *hash_tab_p;
1006      void (*func) PARAMS ((const hash_table_entry *));
1007 {
1008   const hash_table_entry *primary;
1009
1010   for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
1011     if (primary->symbol)
1012       {
1013         hash_table_entry *second;
1014
1015         (*func)(primary);
1016         for (second = primary->hash_next; second; second = second->hash_next)
1017           (*func) (second);
1018       }
1019 }
1020
1021 /* Initialize all of the fields of a new hash table entry, pointed
1022    to by the "p" parameter.  Note that the space to hold the entry
1023    is assumed to have already been allocated before this routine is
1024    called.  */
1025
1026 static hash_table_entry *
1027 add_symbol (p, s)
1028      hash_table_entry *p;
1029      const char *s;
1030 {
1031   p->hash_next = NULL;
1032   p->symbol = xstrdup (s);
1033   p->ddip = NULL;
1034   p->fip = NULL;
1035   return p;
1036 }
1037
1038 /* Look for a particular function name or filename in the particular
1039    hash table indicated by "hash_tab_p".  If the name is not in the
1040    given hash table, add it.  Either way, return a pointer to the
1041    hash table entry for the given name.  */
1042
1043 static hash_table_entry *
1044 lookup (hash_tab_p, search_symbol)
1045      hash_table_entry *hash_tab_p;
1046      const char *search_symbol;
1047 {
1048   int hash_value = 0;
1049   const char *search_symbol_char_p = search_symbol;
1050   hash_table_entry *p;
1051
1052   while (*search_symbol_char_p)
1053     hash_value += *search_symbol_char_p++;
1054   hash_value &= hash_mask;
1055   p = &hash_tab_p[hash_value];
1056   if (! p->symbol)
1057       return add_symbol (p, search_symbol);
1058   if (!strcmp (p->symbol, search_symbol))
1059     return p;
1060   while (p->hash_next)
1061     {
1062       p = p->hash_next;
1063       if (!strcmp (p->symbol, search_symbol))
1064         return p;
1065     }
1066   p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry));
1067   p = p->hash_next;
1068   return add_symbol (p, search_symbol);
1069 }
1070 \f
1071 /* Throw a def/dec record on the junk heap.
1072
1073    Also, since we are not using this record anymore, free up all of the
1074    stuff it pointed to.  */
1075
1076 static void
1077 free_def_dec (p)
1078      def_dec_info *p;
1079 {
1080   free ((NONCONST PTR) p->ansi_decl);
1081
1082 #ifndef UNPROTOIZE
1083   {
1084     const f_list_chain_item * curr;
1085     const f_list_chain_item * next;
1086
1087     for (curr = p->f_list_chain; curr; curr = next)
1088       {
1089         next = curr->chain_next;
1090         free ((NONCONST PTR) curr);
1091       }
1092   }
1093 #endif /* !defined (UNPROTOIZE) */
1094
1095   free (p);
1096 }
1097
1098 /* Unexpand as many macro symbol as we can find.
1099
1100    If the given line must be unexpanded, make a copy of it in the heap and
1101    return a pointer to the unexpanded copy.  Otherwise return NULL.  */
1102
1103 static char *
1104 unexpand_if_needed (aux_info_line)
1105      const char *aux_info_line;
1106 {
1107   static char *line_buf = 0;
1108   static int line_buf_size = 0;
1109   const unexpansion *unexp_p;
1110   int got_unexpanded = 0;
1111   const char *s;
1112   char *copy_p = line_buf;
1113
1114   if (line_buf == 0)
1115     {
1116       line_buf_size = 1024;
1117       line_buf = (char *) xmalloc (line_buf_size);
1118     }
1119
1120   copy_p = line_buf;
1121
1122   /* Make a copy of the input string in line_buf, expanding as necessary.  */
1123
1124   for (s = aux_info_line; *s != '\n'; )
1125     {
1126       for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
1127         {
1128           const char *in_p = unexp_p->expanded;
1129           size_t len = strlen (in_p);
1130
1131           if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1132             {
1133               int size = strlen (unexp_p->contracted);
1134               got_unexpanded = 1;
1135               if (copy_p + size - line_buf >= line_buf_size)
1136                 {
1137                   int offset = copy_p - line_buf;
1138                   line_buf_size *= 2;
1139                   line_buf_size += size;
1140                   line_buf = (char *) xrealloc (line_buf, line_buf_size);
1141                   copy_p = line_buf + offset;
1142                 }
1143               strcpy (copy_p, unexp_p->contracted);
1144               copy_p += size;
1145
1146               /* Assume the there will not be another replacement required
1147                  within the text just replaced.  */
1148
1149               s += len;
1150               goto continue_outer;
1151             }
1152         }
1153       if (copy_p - line_buf == line_buf_size)
1154         {
1155           int offset = copy_p - line_buf;
1156           line_buf_size *= 2;
1157           line_buf = (char *) xrealloc (line_buf, line_buf_size);
1158           copy_p = line_buf + offset;
1159         }
1160       *copy_p++ = *s++;
1161 continue_outer: ;
1162     }
1163   if (copy_p + 2 - line_buf >= line_buf_size)
1164     {
1165       int offset = copy_p - line_buf;
1166       line_buf_size *= 2;
1167       line_buf = (char *) xrealloc (line_buf, line_buf_size);
1168       copy_p = line_buf + offset;
1169     }
1170   *copy_p++ = '\n';
1171   *copy_p = '\0';
1172
1173   return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
1174 }
1175 \f
1176 /* Return 1 if pathname is absolute. */
1177
1178 static int
1179 is_abspath (path)
1180      const char *path;
1181 {
1182   return (IS_DIR_SEPARATOR (path[0])
1183 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1184           /* Check for disk name on MS-DOS-based systems.  */
1185           || (path[0] && path[1] == ':' && IS_DIR_SEPARATOR (path[2]))
1186 #endif
1187           );
1188 }
1189 \f
1190 /* Return the absolutized filename for the given relative
1191    filename.  Note that if that filename is already absolute, it may
1192    still be returned in a modified form because this routine also
1193    eliminates redundant slashes and single dots and eliminates double
1194    dots to get a shortest possible filename from the given input
1195    filename.  The absolutization of relative filenames is made by
1196    assuming that the given filename is to be taken as relative to
1197    the first argument (cwd) or to the current directory if cwd is
1198    NULL.  */
1199
1200 static char *
1201 abspath (cwd, rel_filename)
1202      const char *cwd;
1203      const char *rel_filename;
1204 {
1205   /* Setup the current working directory as needed.  */
1206   const char *cwd2 = (cwd) ? cwd : cwd_buffer;
1207   char *const abs_buffer
1208     = (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 2);
1209   char *endp = abs_buffer;
1210   char *outp, *inp;
1211
1212   /* Copy the  filename (possibly preceded by the current working
1213      directory name) into the absolutization buffer.  */
1214
1215   {
1216     const char *src_p;
1217
1218     if (! is_abspath (rel_filename))
1219       {
1220         src_p = cwd2;
1221         while ((*endp++ = *src_p++))
1222           continue;
1223         *(endp-1) = DIR_SEPARATOR;              /* overwrite null */
1224       }
1225 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1226     else if (IS_DIR_SEPARATOR (rel_filename[0]))
1227       {
1228         /* A path starting with a directory separator is considered absolute 
1229            for dos based filesystems, but it's really not -- it's just the 
1230            convention used throughout GCC and it works. However, in this
1231            case, we still need to prepend the drive spec from cwd_buffer.  */
1232         *endp++ = cwd2[0];
1233         *endp++ = cwd2[1];
1234       }
1235 #endif
1236     src_p = rel_filename;
1237     while ((*endp++ = *src_p++))
1238       continue;
1239   }
1240
1241   /* Now make a copy of abs_buffer into abs_buffer, shortening the
1242      filename (by taking out slashes and dots) as we go.  */
1243
1244   outp = inp = abs_buffer;
1245   *outp++ = *inp++;             /* copy first slash */
1246 #if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
1247   if (IS_DIR_SEPARATOR (inp[0]))
1248     *outp++ = *inp++;           /* copy second slash */
1249 #endif
1250   for (;;)
1251     {
1252       if (!inp[0])
1253         break;
1254       else if (IS_DIR_SEPARATOR (inp[0]) && IS_DIR_SEPARATOR (outp[-1]))
1255         {
1256           inp++;
1257           continue;
1258         }
1259       else if (inp[0] == '.' && IS_DIR_SEPARATOR (outp[-1]))
1260         {
1261           if (!inp[1])
1262                   break;
1263           else if (IS_DIR_SEPARATOR (inp[1]))
1264             {
1265                     inp += 2;
1266                     continue;
1267             }
1268           else if ((inp[1] == '.') && (inp[2] == 0 
1269                                        || IS_DIR_SEPARATOR (inp[2])))
1270             {
1271                     inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2;
1272                     outp -= 2;
1273                     while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*outp))
1274                 outp--;
1275                     if (outp < abs_buffer)
1276                       {
1277                         /* Catch cases like /.. where we try to backup to a
1278                            point above the absolute root of the logical file
1279                            system.  */
1280
1281                         notice ("%s: invalid file name: %s\n",
1282                                 pname, rel_filename);
1283                         exit (FATAL_EXIT_CODE);
1284                       }
1285                     *++outp = '\0';
1286                     continue;
1287                   }
1288         }
1289       *outp++ = *inp++;
1290     }
1291
1292   /* On exit, make sure that there is a trailing null, and make sure that
1293      the last character of the returned string is *not* a slash.  */
1294
1295   *outp = '\0';
1296   if (IS_DIR_SEPARATOR (outp[-1]))
1297     *--outp  = '\0';
1298
1299   /* Make a copy (in the heap) of the stuff left in the absolutization
1300      buffer and return a pointer to the copy.  */
1301
1302   return savestring (abs_buffer, outp - abs_buffer);
1303 }
1304 \f
1305 /* Given a filename (and possibly a directory name from which the filename
1306    is relative) return a string which is the shortest possible
1307    equivalent for the corresponding full (absolutized) filename.  The
1308    shortest possible equivalent may be constructed by converting the
1309    absolutized filename to be a relative filename (i.e. relative to
1310    the actual current working directory).  However if a relative filename
1311    is longer, then the full absolute filename is returned.
1312
1313    KNOWN BUG:
1314
1315    Note that "simple-minded" conversion of any given type of filename (either
1316    relative or absolute) may not result in a valid equivalent filename if any
1317    subpart of the original filename is actually a symbolic link.  */
1318
1319 static const char *
1320 shortpath (cwd, filename)
1321      const char *cwd;
1322      const char *filename;
1323 {
1324   char *rel_buffer;
1325   char *rel_buf_p;
1326   char *cwd_p = cwd_buffer;
1327   char *path_p;
1328   int unmatched_slash_count = 0;
1329   size_t filename_len = strlen (filename);
1330
1331   path_p = abspath (cwd, filename);
1332   rel_buf_p = rel_buffer = (char *) xmalloc (filename_len);
1333
1334   while (*cwd_p && IS_SAME_PATH_CHAR (*cwd_p, *path_p))
1335     {
1336       cwd_p++;
1337       path_p++;
1338     }
1339   if (!*cwd_p && (!*path_p || IS_DIR_SEPARATOR (*path_p)))
1340     {
1341       /* whole pwd matched */
1342       if (!*path_p)             /* input *is* the current path! */
1343         return ".";
1344       else
1345         return ++path_p;
1346     }
1347   else
1348     {
1349       if (*path_p)
1350         {
1351           --cwd_p;
1352           --path_p;
1353           while (! IS_DIR_SEPARATOR (*cwd_p))     /* backup to last slash */
1354             {
1355               --cwd_p;
1356               --path_p;
1357             }
1358           cwd_p++;
1359           path_p++;
1360           unmatched_slash_count++;
1361         }
1362
1363       /* Find out how many directory levels in cwd were *not* matched.  */
1364       while (*cwd_p++)
1365         if (IS_DIR_SEPARATOR (*(cwd_p-1)))
1366           unmatched_slash_count++;
1367
1368       /* Now we know how long the "short name" will be.
1369          Reject it if longer than the input.  */
1370       if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
1371         return filename;
1372
1373       /* For each of them, put a `../' at the beginning of the short name.  */
1374       while (unmatched_slash_count--)
1375         {
1376           /* Give up if the result gets to be longer
1377              than the absolute path name.  */
1378           if (rel_buffer + filename_len <= rel_buf_p + 3)
1379             return filename;
1380           *rel_buf_p++ = '.';
1381           *rel_buf_p++ = '.';
1382           *rel_buf_p++ = DIR_SEPARATOR;
1383         }
1384
1385       /* Then tack on the unmatched part of the desired file's name.  */
1386       do
1387         {
1388           if (rel_buffer + filename_len <= rel_buf_p)
1389             return filename;
1390         }
1391       while ((*rel_buf_p++ = *path_p++));
1392
1393       --rel_buf_p;
1394       if (IS_DIR_SEPARATOR (*(rel_buf_p-1)))
1395         *--rel_buf_p = '\0';
1396       return rel_buffer;
1397     }
1398 }
1399 \f
1400 /* Lookup the given filename in the hash table for filenames.  If it is a
1401    new one, then the hash table info pointer will be null.  In this case,
1402    we create a new file_info record to go with the filename, and we initialize
1403    that record with some reasonable values.  */
1404
1405 /* FILENAME was const, but that causes a warning on AIX when calling stat.
1406    That is probably a bug in AIX, but might as well avoid the warning.  */
1407
1408 static file_info *
1409 find_file (filename, do_not_stat)
1410      const char *filename;
1411      int do_not_stat;
1412 {
1413   hash_table_entry *hash_entry_p;
1414
1415   hash_entry_p = lookup (filename_primary, filename);
1416   if (hash_entry_p->fip)
1417     return hash_entry_p->fip;
1418   else
1419     {
1420       struct stat stat_buf;
1421       file_info *file_p = (file_info *) xmalloc (sizeof (file_info));
1422
1423       /* If we cannot get status on any given source file, give a warning
1424          and then just set its time of last modification to infinity.  */
1425
1426       if (do_not_stat)
1427         stat_buf.st_mtime = (time_t) 0;
1428       else
1429         {
1430           if (stat (filename, &stat_buf) == -1)
1431             {
1432               int errno_val = errno;
1433               notice ("%s: %s: can't get status: %s\n",
1434                       pname, shortpath (NULL, filename),
1435                       xstrerror (errno_val));
1436               stat_buf.st_mtime = (time_t) -1;
1437             }
1438         }
1439
1440       hash_entry_p->fip = file_p;
1441       file_p->hash_entry = hash_entry_p;
1442       file_p->defs_decs = NULL;
1443       file_p->mtime = stat_buf.st_mtime;
1444       return file_p;
1445     }
1446 }
1447
1448 /* Generate a fatal error because some part of the aux_info file is
1449    messed up.  */
1450
1451 static void
1452 aux_info_corrupted ()
1453 {
1454   notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
1455           pname, current_aux_info_lineno);
1456   exit (FATAL_EXIT_CODE);
1457 }
1458
1459 /* ??? This comment is vague.  Say what the condition is for.  */
1460 /* Check to see that a condition is true.  This is kind of like an assert.  */
1461
1462 static void
1463 check_aux_info (cond)
1464      int cond;
1465 {
1466   if (! cond)
1467     aux_info_corrupted ();
1468 }
1469
1470 /* Given a pointer to the closing right parenthesis for a particular formals
1471    list (in an aux_info file) find the corresponding left parenthesis and
1472    return a pointer to it.  */
1473
1474 static const char *
1475 find_corresponding_lparen (p)
1476      const char *p;
1477 {
1478   const char *q;
1479   int paren_depth;
1480
1481   for (paren_depth = 1, q = p-1; paren_depth; q--)
1482     {
1483       switch (*q)
1484         {
1485           case ')':
1486             paren_depth++;
1487             break;
1488           case '(':
1489             paren_depth--;
1490             break;
1491         }
1492     }
1493   return ++q;
1494 }
1495 \f
1496 /* Given a line from  an aux info file, and a time at which the aux info
1497    file it came from was created, check to see if the item described in
1498    the line comes from a file which has been modified since the aux info
1499    file was created.  If so, return non-zero, else return zero.  */
1500
1501 static int
1502 referenced_file_is_newer (l, aux_info_mtime)
1503      const char *l;
1504      time_t aux_info_mtime;
1505 {
1506   const char *p;
1507   file_info *fi_p;
1508   char *filename;
1509
1510   check_aux_info (l[0] == '/');
1511   check_aux_info (l[1] == '*');
1512   check_aux_info (l[2] == ' ');
1513
1514   {
1515     const char *filename_start = p = l + 3;
1516
1517     while (*p != ':'
1518 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1519            || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1520 #endif
1521            )
1522       p++;
1523     filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1524     strncpy (filename, filename_start, (size_t) (p - filename_start));
1525     filename[p-filename_start] = '\0';
1526   }
1527
1528   /* Call find_file to find the file_info record associated with the file
1529      which contained this particular def or dec item.  Note that this call
1530      may cause a new file_info record to be created if this is the first time
1531      that we have ever known about this particular file.  */
1532
1533   fi_p = find_file (abspath (invocation_filename, filename), 0);
1534
1535   return (fi_p->mtime > aux_info_mtime);
1536 }
1537 \f
1538 /* Given a line of info from the aux_info file, create a new
1539    def_dec_info record to remember all of the important information about
1540    a function definition or declaration.
1541
1542    Link this record onto the list of such records for the particular file in
1543    which it occurred in proper (descending) line number order (for now).
1544
1545    If there is an identical record already on the list for the file, throw
1546    this one away.  Doing so takes care of the (useless and troublesome)
1547    duplicates which are bound to crop up due to multiple inclusions of any
1548    given individual header file.
1549
1550    Finally, link the new def_dec record onto the list of such records
1551    pertaining to this particular function name.  */
1552
1553 static void
1554 save_def_or_dec (l, is_syscalls)
1555      const char *l;
1556      int is_syscalls;
1557 {
1558   const char *p;
1559   const char *semicolon_p;
1560   def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info));
1561
1562 #ifndef UNPROTOIZE
1563   def_dec_p->written = 0;
1564 #endif /* !defined (UNPROTOIZE) */
1565
1566   /* Start processing the line by picking off 5 pieces of information from
1567      the left hand end of the line.  These are filename, line number,
1568      new/old/implicit flag (new = ANSI prototype format), definition or
1569      declaration flag, and extern/static flag).  */
1570
1571   check_aux_info (l[0] == '/');
1572   check_aux_info (l[1] == '*');
1573   check_aux_info (l[2] == ' ');
1574
1575   {
1576     const char *filename_start = p = l + 3;
1577     char *filename;
1578
1579     while (*p != ':'
1580 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1581            || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1582 #endif
1583            )
1584       p++;
1585     filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1586     strncpy (filename, filename_start, (size_t) (p - filename_start));
1587     filename[p-filename_start] = '\0';
1588
1589     /* Call find_file to find the file_info record associated with the file
1590        which contained this particular def or dec item.  Note that this call
1591        may cause a new file_info record to be created if this is the first time
1592        that we have ever known about this particular file.
1593   
1594        Note that we started out by forcing all of the base source file names
1595        (i.e. the names of the aux_info files with the .X stripped off) into the
1596        filenames hash table, and we simultaneously setup file_info records for
1597        all of these base file names (even if they may be useless later).
1598        The file_info records for all of these "base" file names (properly)
1599        act as file_info records for the "original" (i.e. un-included) files
1600        which were submitted to gcc for compilation (when the -aux-info
1601        option was used).  */
1602   
1603     def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1604   }
1605
1606   {
1607     const char *line_number_start = ++p;
1608     char line_number[10];
1609
1610     while (*p != ':'
1611 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1612            || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1613 #endif
1614            )
1615       p++;
1616     strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1617     line_number[p-line_number_start] = '\0';
1618     def_dec_p->line = atoi (line_number);
1619   }
1620
1621   /* Check that this record describes a new-style, old-style, or implicit
1622      definition or declaration.  */
1623
1624   p++;  /* Skip over the `:'.  */
1625   check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1626
1627   /* Is this a new style (ANSI prototyped) definition or declaration? */
1628
1629   def_dec_p->prototyped = (*p == 'N');
1630
1631 #ifndef UNPROTOIZE
1632
1633   /* Is this an implicit declaration? */
1634
1635   def_dec_p->is_implicit = (*p == 'I');
1636
1637 #endif /* !defined (UNPROTOIZE) */
1638
1639   p++;
1640
1641   check_aux_info ((*p == 'C') || (*p == 'F'));
1642
1643   /* Is this item a function definition (F) or a declaration (C).  Note that
1644      we treat item taken from the syscalls file as though they were function
1645      definitions regardless of what the stuff in the file says.  */
1646
1647   def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1648
1649 #ifndef UNPROTOIZE
1650   def_dec_p->definition = 0;    /* Fill this in later if protoizing.  */
1651 #endif /* !defined (UNPROTOIZE) */
1652
1653   check_aux_info (*p++ == ' ');
1654   check_aux_info (*p++ == '*');
1655   check_aux_info (*p++ == '/');
1656   check_aux_info (*p++ == ' ');
1657
1658 #ifdef UNPROTOIZE
1659   check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1660 #else /* !defined (UNPROTOIZE) */
1661   if (!strncmp (p, "static", 6))
1662     def_dec_p->is_static = -1;
1663   else if (!strncmp (p, "extern", 6))
1664     def_dec_p->is_static = 0;
1665   else
1666     check_aux_info (0); /* Didn't find either `extern' or `static'.  */
1667 #endif /* !defined (UNPROTOIZE) */
1668
1669   {
1670     const char *ansi_start = p;
1671
1672     p += 6;     /* Pass over the "static" or "extern".  */
1673
1674     /* We are now past the initial stuff.  Search forward from here to find
1675        the terminating semicolon that should immediately follow the entire
1676        ANSI format function declaration.  */
1677
1678     while (*++p != ';')
1679       continue;
1680
1681     semicolon_p = p;
1682
1683     /* Make a copy of the ansi declaration part of the line from the aux_info
1684        file.  */
1685
1686     def_dec_p->ansi_decl
1687       = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1688
1689     /* Backup and point at the final right paren of the final argument list.  */
1690
1691     p--;
1692
1693 #ifndef UNPROTOIZE
1694     def_dec_p->f_list_chain = NULL;
1695 #endif /* !defined (UNPROTOIZE) */
1696
1697     while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
1698     if (*p != ')')
1699       {
1700         free_def_dec (def_dec_p);
1701         return;
1702       }
1703   }
1704
1705   /* Now isolate a whole set of formal argument lists, one-by-one.  Normally,
1706      there will only be one list to isolate, but there could be more.  */
1707
1708   def_dec_p->f_list_count = 0;
1709
1710   for (;;)
1711     {
1712       const char *left_paren_p = find_corresponding_lparen (p);
1713 #ifndef UNPROTOIZE
1714       {
1715         f_list_chain_item *cip
1716           = (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
1717
1718         cip->formals_list
1719           = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1720       
1721         /* Add the new chain item at the head of the current list.  */
1722
1723         cip->chain_next = def_dec_p->f_list_chain;
1724         def_dec_p->f_list_chain = cip;
1725       }
1726 #endif /* !defined (UNPROTOIZE) */
1727       def_dec_p->f_list_count++;
1728
1729       p = left_paren_p - 2;
1730
1731       /* p must now point either to another right paren, or to the last
1732          character of the name of the function that was declared/defined.
1733          If p points to another right paren, then this indicates that we
1734          are dealing with multiple formals lists.  In that case, there
1735          really should be another right paren preceding this right paren.  */
1736
1737       if (*p != ')')
1738         break;
1739       else
1740         check_aux_info (*--p == ')');
1741     }
1742
1743
1744   {
1745     const char *past_fn = p + 1;
1746
1747     check_aux_info (*past_fn == ' ');
1748
1749     /* Scan leftwards over the identifier that names the function.  */
1750
1751     while (is_id_char (*p))
1752       p--;
1753     p++;
1754
1755     /* p now points to the leftmost character of the function name.  */
1756
1757     {
1758       char *fn_string = (char *) alloca (past_fn - p + 1);
1759
1760       strncpy (fn_string, p, (size_t) (past_fn - p));
1761       fn_string[past_fn-p] = '\0';
1762       def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1763     }
1764   }
1765
1766   /* Look at all of the defs and decs for this function name that we have
1767      collected so far.  If there is already one which is at the same
1768      line number in the same file, then we can discard this new def_dec_info
1769      record.
1770
1771      As an extra assurance that any such pair of (nominally) identical
1772      function declarations are in fact identical, we also compare the
1773      ansi_decl parts of the lines from the aux_info files just to be on
1774      the safe side.
1775
1776      This comparison will fail if (for instance) the user was playing
1777      messy games with the preprocessor which ultimately causes one
1778      function declaration in one header file to look differently when
1779      that file is included by two (or more) other files.  */
1780
1781   {
1782     const def_dec_info *other;
1783
1784     for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1785       {
1786         if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1787           {
1788             if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1789               {
1790                 notice ("%s:%d: declaration of function `%s' takes different forms\n",
1791                         def_dec_p->file->hash_entry->symbol,
1792                         def_dec_p->line,
1793                         def_dec_p->hash_entry->symbol);
1794                 exit (FATAL_EXIT_CODE);
1795               }
1796             free_def_dec (def_dec_p);
1797             return;
1798           }
1799       }
1800   }
1801
1802 #ifdef UNPROTOIZE
1803
1804   /* If we are doing unprotoizing, we must now setup the pointers that will
1805      point to the K&R name list and to the K&R argument declarations list.
1806
1807      Note that if this is only a function declaration, then we should not
1808      expect to find any K&R style formals list following the ANSI-style
1809      formals list.  This is because GCC knows that such information is
1810      useless in the case of function declarations (function definitions
1811      are a different story however).
1812
1813      Since we are unprotoizing, we don't need any such lists anyway.
1814      All we plan to do is to delete all characters between ()'s in any
1815      case.  */
1816
1817   def_dec_p->formal_names = NULL;
1818   def_dec_p->formal_decls = NULL;
1819
1820   if (def_dec_p->is_func_def)
1821     {
1822       p = semicolon_p;
1823       check_aux_info (*++p == ' ');
1824       check_aux_info (*++p == '/');
1825       check_aux_info (*++p == '*');
1826       check_aux_info (*++p == ' ');
1827       check_aux_info (*++p == '(');
1828
1829       {
1830         const char *kr_names_start = ++p;   /* Point just inside '('.  */
1831
1832         while (*p++ != ')')
1833           continue;
1834         p--;            /* point to closing right paren */
1835
1836         /* Make a copy of the K&R parameter names list.  */
1837
1838         def_dec_p->formal_names
1839           = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1840       }
1841
1842       check_aux_info (*++p == ' ');
1843       p++;
1844
1845       /* p now points to the first character of the K&R style declarations
1846          list (if there is one) or to the star-slash combination that ends
1847          the comment in which such lists get embedded.  */
1848
1849       /* Make a copy of the K&R formal decls list and set the def_dec record
1850          to point to it.  */
1851
1852       if (*p == '*')            /* Are there no K&R declarations? */
1853         {
1854           check_aux_info (*++p == '/');
1855           def_dec_p->formal_decls = "";
1856         }
1857       else
1858         {
1859           const char *kr_decls_start = p;
1860
1861           while (p[0] != '*' || p[1] != '/')
1862             p++;
1863           p--;
1864
1865           check_aux_info (*p == ' ');
1866
1867           def_dec_p->formal_decls
1868             = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1869         }
1870
1871       /* Handle a special case.  If we have a function definition marked as
1872          being in "old" style, and if its formal names list is empty, then
1873          it may actually have the string "void" in its real formals list
1874          in the original source code.  Just to make sure, we will get setup
1875          to convert such things anyway.
1876
1877          This kludge only needs to be here because of an insurmountable
1878          problem with generating .X files.  */
1879
1880       if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1881         def_dec_p->prototyped = 1;
1882     }
1883
1884   /* Since we are unprotoizing, if this item is already in old (K&R) style,
1885      we can just ignore it.  If that is true, throw away the itme now.  */
1886
1887   if (!def_dec_p->prototyped)
1888     {
1889       free_def_dec (def_dec_p);
1890       return;
1891     }
1892
1893 #endif /* defined (UNPROTOIZE) */
1894
1895   /* Add this record to the head of the list of records pertaining to this
1896      particular function name.  */
1897
1898   def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1899   def_dec_p->hash_entry->ddip = def_dec_p;
1900
1901   /* Add this new def_dec_info record to the sorted list of def_dec_info
1902      records for this file.  Note that we don't have to worry about duplicates
1903      (caused by multiple inclusions of header files) here because we have
1904      already eliminated duplicates above.  */
1905
1906   if (!def_dec_p->file->defs_decs)
1907     {
1908       def_dec_p->file->defs_decs = def_dec_p;
1909       def_dec_p->next_in_file = NULL;
1910     }
1911   else
1912     {
1913       int line = def_dec_p->line;
1914       const def_dec_info *prev = NULL;
1915       const def_dec_info *curr = def_dec_p->file->defs_decs;
1916       const def_dec_info *next = curr->next_in_file;
1917
1918       while (next && (line < curr->line))
1919         {
1920           prev = curr;
1921           curr = next;
1922           next = next->next_in_file;
1923         }
1924       if (line >= curr->line)
1925         {
1926           def_dec_p->next_in_file = curr;
1927           if (prev)
1928             ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1929           else
1930             def_dec_p->file->defs_decs = def_dec_p;
1931         }
1932       else      /* assert (next == NULL); */
1933         {
1934           ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
1935           /* assert (next == NULL); */
1936           def_dec_p->next_in_file = next;
1937         }
1938     }
1939 }
1940 \f
1941 /* Set up the vector COMPILE_PARAMS which is the argument list for running GCC.
1942    Also set input_file_name_index and aux_info_file_name_index
1943    to the indices of the slots where the file names should go.  */
1944
1945 /* We initialize the vector by  removing -g, -O, -S, -c, and -o options,
1946    and adding '-aux-info AUXFILE -S  -o /dev/null INFILE' at the end.  */
1947
1948 static void
1949 munge_compile_params (params_list)
1950      const char *params_list;
1951 {
1952   /* Build up the contents in a temporary vector
1953      that is so big that to has to be big enough.  */
1954   const char **temp_params
1955     = (const char **) alloca ((strlen (params_list) + 8) * sizeof (char *));
1956   int param_count = 0;
1957   const char *param;
1958   struct stat st;
1959
1960   temp_params[param_count++] = compiler_file_name;
1961   for (;;)
1962     {
1963       while (ISSPACE ((const unsigned char)*params_list))
1964         params_list++;
1965       if (!*params_list)
1966         break;
1967       param = params_list;
1968       while (*params_list && !ISSPACE ((const unsigned char)*params_list))
1969         params_list++;
1970       if (param[0] != '-')
1971         temp_params[param_count++]
1972           = dupnstr (param, (size_t) (params_list - param));
1973       else
1974         {
1975           switch (param[1])
1976             {
1977               case 'g':
1978               case 'O':
1979               case 'S':
1980               case 'c':
1981                 break;          /* Don't copy these.  */
1982               case 'o':
1983                 while (ISSPACE ((const unsigned char)*params_list))
1984                   params_list++;
1985                 while (*params_list
1986                        && !ISSPACE ((const unsigned char)*params_list))
1987                   params_list++;
1988                 break;
1989               default:
1990                 temp_params[param_count++]
1991                   = dupnstr (param, (size_t) (params_list - param));
1992             }
1993         }
1994       if (!*params_list)
1995         break;
1996     }
1997   temp_params[param_count++] = "-aux-info";
1998
1999   /* Leave room for the aux-info file name argument.  */
2000   aux_info_file_name_index = param_count;
2001   temp_params[param_count++] = NULL;
2002
2003   temp_params[param_count++] = "-S";
2004   temp_params[param_count++] = "-o";
2005   
2006   if ((stat (HOST_BIT_BUCKET, &st) == 0)
2007       && (!S_ISDIR (st.st_mode))
2008       && (access (HOST_BIT_BUCKET, W_OK) == 0))
2009     temp_params[param_count++] = HOST_BIT_BUCKET;
2010   else
2011     /* FIXME: This is hardly likely to be right, if HOST_BIT_BUCKET is not
2012        writable.  But until this is rejigged to use make_temp_file(), this
2013        is the best we can do.  */
2014     temp_params[param_count++] = "/dev/null";
2015
2016   /* Leave room for the input file name argument.  */
2017   input_file_name_index = param_count;
2018   temp_params[param_count++] = NULL;
2019   /* Terminate the list.  */
2020   temp_params[param_count++] = NULL;
2021
2022   /* Make a copy of the compile_params in heap space.  */
2023
2024   compile_params
2025     = (const char **) xmalloc (sizeof (char *) * (param_count+1));
2026   memcpy (compile_params, temp_params, sizeof (char *) * param_count);
2027 }
2028
2029 /* Do a recompilation for the express purpose of generating a new aux_info
2030    file to go with a specific base source file.
2031
2032    The result is a boolean indicating success.  */
2033
2034 static int
2035 gen_aux_info_file (base_filename)
2036      const char *base_filename;
2037 {
2038   if (!input_file_name_index)
2039     munge_compile_params ("");
2040
2041   /* Store the full source file name in the argument vector.  */
2042   compile_params[input_file_name_index] = shortpath (NULL, base_filename);
2043   /* Add .X to source file name to get aux-info file name.  */
2044   compile_params[aux_info_file_name_index] =
2045     concat (compile_params[input_file_name_index], aux_info_suffix, NULL);
2046   
2047   if (!quiet_flag)
2048     notice ("%s: compiling `%s'\n",
2049             pname, compile_params[input_file_name_index]);
2050
2051   {
2052     char *errmsg_fmt, *errmsg_arg;
2053     int wait_status, pid;
2054
2055     pid = pexecute (compile_params[0], (char * const *) compile_params,
2056                     pname, NULL, &errmsg_fmt, &errmsg_arg,
2057                     PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
2058
2059     if (pid == -1)
2060       {
2061         int errno_val = errno;
2062         fprintf (stderr, "%s: ", pname);
2063         fprintf (stderr, errmsg_fmt, errmsg_arg);
2064         fprintf (stderr, ": %s\n", xstrerror (errno_val));
2065         return 0;
2066       }
2067
2068     pid = pwait (pid, &wait_status, 0);
2069     if (pid == -1)
2070       {
2071         notice ("%s: wait: %s\n", pname, xstrerror (errno));
2072         return 0;
2073       }
2074     if (WIFSIGNALED (wait_status))
2075       {
2076         notice ("%s: subprocess got fatal signal %d\n",
2077                 pname, WTERMSIG (wait_status));
2078         return 0;
2079       }
2080     if (WIFEXITED (wait_status))
2081       {
2082         if (WEXITSTATUS (wait_status) != 0)
2083           {
2084             notice ("%s: %s exited with status %d\n",
2085                     pname, compile_params[0], WEXITSTATUS (wait_status));
2086             return 0;
2087           }
2088         return 1;
2089       }
2090     abort ();
2091   }
2092 }
2093 \f
2094 /* Read in all of the information contained in a single aux_info file.
2095    Save all of the important stuff for later.  */
2096
2097 static void
2098 process_aux_info_file (base_source_filename, keep_it, is_syscalls)
2099      const char *base_source_filename;
2100      int keep_it;
2101      int is_syscalls;
2102 {
2103   size_t base_len = strlen (base_source_filename);
2104   char * aux_info_filename
2105     = (char *) alloca (base_len + strlen (aux_info_suffix) + 1);
2106   char *aux_info_base;
2107   char *aux_info_limit;
2108   char *aux_info_relocated_name;
2109   const char *aux_info_second_line;
2110   time_t aux_info_mtime;
2111   size_t aux_info_size;
2112   int must_create;
2113
2114   /* Construct the aux_info filename from the base source filename.  */
2115
2116   strcpy (aux_info_filename, base_source_filename);
2117   strcat (aux_info_filename, aux_info_suffix);
2118
2119   /* Check that the aux_info file exists and is readable.  If it does not
2120      exist, try to create it (once only).  */
2121
2122   /* If file doesn't exist, set must_create.
2123      Likewise if it exists and we can read it but it is obsolete.
2124      Otherwise, report an error.  */
2125   must_create = 0;
2126
2127   /* Come here with must_create set to 1 if file is out of date.  */
2128 start_over: ;
2129
2130   if (access (aux_info_filename, R_OK) == -1)
2131     {
2132       if (errno == ENOENT)
2133         {
2134           if (is_syscalls)
2135             {
2136               notice ("%s: warning: missing SYSCALLS file `%s'\n",
2137                       pname, aux_info_filename);
2138               return;
2139             }
2140           must_create = 1;
2141         }
2142       else
2143         {
2144           int errno_val = errno;
2145           notice ("%s: can't read aux info file `%s': %s\n",
2146                   pname, shortpath (NULL, aux_info_filename),
2147                   xstrerror (errno_val));
2148           errors++;
2149           return;
2150         }
2151     }
2152 #if 0 /* There is code farther down to take care of this.  */
2153   else
2154     {
2155       struct stat s1, s2;
2156       stat (aux_info_file_name, &s1);
2157       stat (base_source_file_name, &s2);
2158       if (s2.st_mtime > s1.st_mtime)
2159         must_create = 1;
2160     }
2161 #endif /* 0 */
2162
2163   /* If we need a .X file, create it, and verify we can read it.  */
2164   if (must_create)
2165     {
2166       if (!gen_aux_info_file (base_source_filename))
2167         {
2168           errors++;
2169           return;
2170         }
2171       if (access (aux_info_filename, R_OK) == -1)
2172         {
2173           int errno_val = errno;
2174           notice ("%s: can't read aux info file `%s': %s\n",
2175                   pname, shortpath (NULL, aux_info_filename),
2176                   xstrerror (errno_val));
2177           errors++;
2178           return;
2179         }
2180     }
2181
2182   {
2183     struct stat stat_buf;
2184
2185     /* Get some status information about this aux_info file.  */
2186   
2187     if (stat (aux_info_filename, &stat_buf) == -1)
2188       {
2189         int errno_val = errno;
2190         notice ("%s: can't get status of aux info file `%s': %s\n",
2191                 pname, shortpath (NULL, aux_info_filename),
2192                 xstrerror (errno_val));
2193         errors++;
2194         return;
2195       }
2196   
2197     /* Check on whether or not this aux_info file is zero length.  If it is,
2198        then just ignore it and return.  */
2199   
2200     if ((aux_info_size = stat_buf.st_size) == 0)
2201       return;
2202   
2203     /* Get the date/time of last modification for this aux_info file and
2204        remember it.  We will have to check that any source files that it
2205        contains information about are at least this old or older.  */
2206   
2207     aux_info_mtime = stat_buf.st_mtime;
2208
2209     if (!is_syscalls)
2210       {
2211         /* Compare mod time with the .c file; update .X file if obsolete.
2212            The code later on can fail to check the .c file
2213            if it did not directly define any functions.  */
2214
2215         if (stat (base_source_filename, &stat_buf) == -1)
2216           {
2217             int errno_val = errno;
2218             notice ("%s: can't get status of aux info file `%s': %s\n",
2219                     pname, shortpath (NULL, base_source_filename),
2220                     xstrerror (errno_val));
2221             errors++;
2222             return;
2223           }
2224         if (stat_buf.st_mtime > aux_info_mtime)
2225           {
2226             must_create = 1;
2227             goto start_over;
2228           }
2229       }
2230   }
2231
2232   {
2233     int aux_info_file;
2234     int fd_flags;
2235
2236     /* Open the aux_info file.  */
2237   
2238     fd_flags = O_RDONLY;
2239 #ifdef O_BINARY
2240     /* Use binary mode to avoid having to deal with different EOL characters. */
2241     fd_flags |= O_BINARY;
2242 #endif
2243     if ((aux_info_file = open (aux_info_filename, fd_flags, 0444 )) == -1)
2244       {
2245         int errno_val = errno;
2246         notice ("%s: can't open aux info file `%s' for reading: %s\n",
2247                 pname, shortpath (NULL, aux_info_filename),
2248                 xstrerror (errno_val));
2249         return;
2250       }
2251   
2252     /* Allocate space to hold the aux_info file in memory.  */
2253   
2254     aux_info_base = xmalloc (aux_info_size + 1);
2255     aux_info_limit = aux_info_base + aux_info_size;
2256     *aux_info_limit = '\0';
2257   
2258     /* Read the aux_info file into memory.  */
2259   
2260     if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
2261         (int) aux_info_size)
2262       {
2263         int errno_val = errno;
2264         notice ("%s: error reading aux info file `%s': %s\n",
2265                 pname, shortpath (NULL, aux_info_filename),
2266                 xstrerror (errno_val));
2267         free (aux_info_base);
2268         close (aux_info_file);
2269         return;
2270       }
2271   
2272     /* Close the aux info file.  */
2273   
2274     if (close (aux_info_file))
2275       {
2276         int errno_val = errno;
2277         notice ("%s: error closing aux info file `%s': %s\n",
2278                 pname, shortpath (NULL, aux_info_filename),
2279                 xstrerror (errno_val));
2280         free (aux_info_base);
2281         close (aux_info_file);
2282         return;
2283       }
2284   }
2285
2286   /* Delete the aux_info file (unless requested not to).  If the deletion
2287      fails for some reason, don't even worry about it.  */
2288
2289   if (must_create && !keep_it)
2290     if (unlink (aux_info_filename) == -1)
2291       {
2292         int errno_val = errno;
2293         notice ("%s: can't delete aux info file `%s': %s\n",
2294                 pname, shortpath (NULL, aux_info_filename),
2295                 xstrerror (errno_val));
2296       }
2297
2298   /* Save a pointer into the first line of the aux_info file which
2299      contains the filename of the directory from which the compiler
2300      was invoked when the associated source file was compiled.
2301      This information is used later to help create complete
2302      filenames out of the (potentially) relative filenames in
2303      the aux_info file.  */
2304
2305   {
2306     char *p = aux_info_base;
2307
2308     while (*p != ':'
2309 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
2310            || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
2311 #endif
2312            )
2313       p++;
2314     p++;
2315     while (*p == ' ')
2316       p++;
2317     invocation_filename = p;    /* Save a pointer to first byte of path.  */
2318     while (*p != ' ')
2319       p++;
2320     *p++ = DIR_SEPARATOR;
2321     *p++ = '\0';
2322     while (*p++ != '\n')
2323       continue;
2324     aux_info_second_line = p;
2325     aux_info_relocated_name = 0;
2326     if (! is_abspath (invocation_filename))
2327       {
2328         /* INVOCATION_FILENAME is relative;
2329            append it to BASE_SOURCE_FILENAME's dir.  */
2330         char *dir_end;
2331         aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
2332         strcpy (aux_info_relocated_name, base_source_filename);
2333         dir_end = strrchr (aux_info_relocated_name, DIR_SEPARATOR);
2334 #ifdef DIR_SEPARATOR_2
2335         {
2336           char *slash;
2337
2338           slash = strrchr (dir_end ? dir_end : aux_info_relocated_name, 
2339                            DIR_SEPARATOR_2);
2340           if (slash)
2341             dir_end = slash;
2342         }
2343 #endif
2344         if (dir_end)
2345           dir_end++;
2346         else
2347           dir_end = aux_info_relocated_name;
2348         strcpy (dir_end, invocation_filename);
2349         invocation_filename = aux_info_relocated_name;
2350       }
2351   }
2352
2353
2354   {
2355     const char *aux_info_p;
2356
2357     /* Do a pre-pass on the lines in the aux_info file, making sure that all
2358        of the source files referenced in there are at least as old as this
2359        aux_info file itself.  If not, go back and regenerate the aux_info
2360        file anew.  Don't do any of this for the syscalls file.  */
2361
2362     if (!is_syscalls)
2363       {
2364         current_aux_info_lineno = 2;
2365     
2366         for (aux_info_p = aux_info_second_line; *aux_info_p; )
2367           {
2368             if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2369               {
2370                 free (aux_info_base);
2371                 free (aux_info_relocated_name);
2372                 if (keep_it && unlink (aux_info_filename) == -1)
2373                   {
2374                     int errno_val = errno;
2375                     notice ("%s: can't delete file `%s': %s\n",
2376                             pname, shortpath (NULL, aux_info_filename),
2377                             xstrerror (errno_val));
2378                     return;
2379                   }
2380                 must_create = 1;
2381                 goto start_over;
2382               }
2383     
2384             /* Skip over the rest of this line to start of next line.  */
2385     
2386             while (*aux_info_p != '\n')
2387               aux_info_p++;
2388             aux_info_p++;
2389             current_aux_info_lineno++;
2390           }
2391       }
2392
2393     /* Now do the real pass on the aux_info lines.  Save their information in
2394        the in-core data base.  */
2395   
2396     current_aux_info_lineno = 2;
2397   
2398     for (aux_info_p = aux_info_second_line; *aux_info_p;)
2399       {
2400         char *unexpanded_line = unexpand_if_needed (aux_info_p);
2401   
2402         if (unexpanded_line)
2403           {
2404             save_def_or_dec (unexpanded_line, is_syscalls);
2405             free (unexpanded_line);
2406           }
2407         else
2408           save_def_or_dec (aux_info_p, is_syscalls);
2409   
2410         /* Skip over the rest of this line and get to start of next line.  */
2411   
2412         while (*aux_info_p != '\n')
2413           aux_info_p++;
2414         aux_info_p++;
2415         current_aux_info_lineno++;
2416       }
2417   }
2418
2419   free (aux_info_base);
2420   free (aux_info_relocated_name);
2421 }
2422 \f
2423 #ifndef UNPROTOIZE
2424
2425 /* Check an individual filename for a .c suffix.  If the filename has this
2426    suffix, rename the file such that its suffix is changed to .C.  This
2427    function implements the -C option.  */
2428
2429 static void
2430 rename_c_file (hp)
2431      const hash_table_entry *hp;
2432 {
2433   const char *filename = hp->symbol;
2434   int last_char_index = strlen (filename) - 1;
2435   char *const new_filename = (char *) alloca (strlen (filename) 
2436                                               + strlen (cplus_suffix) + 1);
2437
2438   /* Note that we don't care here if the given file was converted or not.  It
2439      is possible that the given file was *not* converted, simply because there
2440      was nothing in it which actually required conversion.  Even in this case,
2441      we want to do the renaming.  Note that we only rename files with the .c
2442      suffix (except for the syscalls file, which is left alone).  */
2443
2444   if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.'
2445       || IS_SAME_PATH (syscalls_absolute_filename, filename))
2446     return;
2447
2448   strcpy (new_filename, filename);
2449   strcpy (&new_filename[last_char_index], cplus_suffix);
2450
2451   if (rename (filename, new_filename) == -1)
2452     {
2453       int errno_val = errno;
2454       notice ("%s: warning: can't rename file `%s' to `%s': %s\n",
2455               pname, shortpath (NULL, filename),
2456               shortpath (NULL, new_filename), xstrerror (errno_val));
2457       errors++;
2458       return;
2459     }
2460 }
2461
2462 #endif /* !defined (UNPROTOIZE) */
2463 \f
2464 /* Take the list of definitions and declarations attached to a particular
2465    file_info node and reverse the order of the list.  This should get the
2466    list into an order such that the item with the lowest associated line
2467    number is nearest the head of the list.  When these lists are originally
2468    built, they are in the opposite order.  We want to traverse them in
2469    normal line number order later (i.e. lowest to highest) so reverse the
2470    order here.  */
2471
2472 static void
2473 reverse_def_dec_list (hp)
2474      const hash_table_entry *hp;
2475 {
2476   file_info *file_p = hp->fip;
2477   def_dec_info *prev = NULL;
2478   def_dec_info *current = (def_dec_info *)file_p->defs_decs;
2479
2480   if (!current)
2481     return;                     /* no list to reverse */
2482
2483   prev = current;
2484   if (! (current = (def_dec_info *)current->next_in_file))
2485     return;                     /* can't reverse a single list element */
2486
2487   prev->next_in_file = NULL;
2488
2489   while (current)
2490     {
2491       def_dec_info *next = (def_dec_info *)current->next_in_file;
2492
2493       current->next_in_file = prev;
2494       prev = current;
2495       current = next;
2496     }
2497
2498   file_p->defs_decs = prev;
2499 }
2500
2501 #ifndef UNPROTOIZE
2502
2503 /* Find the (only?) extern definition for a particular function name, starting
2504    from the head of the linked list of entries for the given name.  If we
2505    cannot find an extern definition for the given function name, issue a
2506    warning and scrounge around for the next best thing, i.e. an extern
2507    function declaration with a prototype attached to it.  Note that we only
2508    allow such substitutions for extern declarations and never for static
2509    declarations.  That's because the only reason we allow them at all is
2510    to let un-prototyped function declarations for system-supplied library
2511    functions get their prototypes from our own extra SYSCALLS.c.X file which
2512    contains all of the correct prototypes for system functions.  */
2513
2514 static const def_dec_info *
2515 find_extern_def (head, user)
2516      const def_dec_info *head;
2517      const def_dec_info *user;
2518 {
2519   const def_dec_info *dd_p;
2520   const def_dec_info *extern_def_p = NULL;
2521   int conflict_noted = 0;
2522
2523   /* Don't act too stupid here.  Somebody may try to convert an entire system
2524      in one swell fwoop (rather than one program at a time, as should be done)
2525      and in that case, we may find that there are multiple extern definitions
2526      of a given function name in the entire set of source files that we are
2527      converting.  If however one of these definitions resides in exactly the
2528      same source file as the reference we are trying to satisfy then in that
2529      case it would be stupid for us to fail to realize that this one definition
2530      *must* be the precise one we are looking for.
2531
2532      To make sure that we don't miss an opportunity to make this "same file"
2533      leap of faith, we do a prescan of the list of records relating to the
2534      given function name, and we look (on this first scan) *only* for a
2535      definition of the function which is in the same file as the reference
2536      we are currently trying to satisfy.  */
2537
2538   for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2539     if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2540       return dd_p;
2541
2542   /* Now, since we have not found a definition in the same file as the
2543      reference, we scan the list again and consider all possibilities from
2544      all files.  Here we may get conflicts with the things listed in the
2545      SYSCALLS.c.X file, but if that happens it only means that the source
2546      code being converted contains its own definition of a function which
2547      could have been supplied by libc.a.  In such cases, we should avoid
2548      issuing the normal warning, and defer to the definition given in the
2549      user's own code.   */
2550
2551   for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2552     if (dd_p->is_func_def && !dd_p->is_static)
2553       {
2554         if (!extern_def_p)      /* Previous definition? */
2555           extern_def_p = dd_p;  /* Remember the first definition found.  */
2556         else
2557           {
2558             /* Ignore definition just found if it came from SYSCALLS.c.X.  */
2559
2560             if (is_syscalls_file (dd_p->file))
2561               continue;
2562
2563             /* Quietly replace the definition previously found with the one
2564                just found if the previous one was from SYSCALLS.c.X.  */
2565
2566             if (is_syscalls_file (extern_def_p->file))
2567               {
2568                 extern_def_p = dd_p;
2569                 continue;
2570               }
2571
2572             /* If we get here, then there is a conflict between two function
2573                declarations for the same function, both of which came from the
2574                user's own code.  */
2575
2576             if (!conflict_noted)        /* first time we noticed? */
2577               {
2578                 conflict_noted = 1;
2579                 notice ("%s: conflicting extern definitions of '%s'\n",
2580                         pname, head->hash_entry->symbol);
2581                 if (!quiet_flag)
2582                   {
2583                     notice ("%s: declarations of '%s' will not be converted\n",
2584                             pname, head->hash_entry->symbol);
2585                     notice ("%s: conflict list for '%s' follows:\n",
2586                             pname, head->hash_entry->symbol);
2587                     fprintf (stderr, "%s:     %s(%d): %s\n",
2588                              pname,
2589                              shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2590                              extern_def_p->line, extern_def_p->ansi_decl);
2591                   }
2592               }
2593             if (!quiet_flag)
2594               fprintf (stderr, "%s:     %s(%d): %s\n",
2595                        pname,
2596                        shortpath (NULL, dd_p->file->hash_entry->symbol),
2597                        dd_p->line, dd_p->ansi_decl);
2598           }
2599       }
2600
2601   /* We want to err on the side of caution, so if we found multiple conflicting
2602      definitions for the same function, treat this as being that same as if we
2603      had found no definitions (i.e. return NULL).  */
2604
2605   if (conflict_noted)
2606     return NULL;
2607
2608   if (!extern_def_p)
2609     {
2610       /* We have no definitions for this function so do the next best thing.
2611          Search for an extern declaration already in prototype form.  */
2612
2613       for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2614         if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2615           {
2616             extern_def_p = dd_p;        /* save a pointer to the definition */
2617             if (!quiet_flag)
2618               notice ("%s: warning: using formals list from %s(%d) for function `%s'\n",
2619                       pname,
2620                       shortpath (NULL, dd_p->file->hash_entry->symbol),
2621                       dd_p->line, dd_p->hash_entry->symbol);
2622             break;
2623           }
2624
2625       /* Gripe about unprototyped function declarations that we found no
2626          corresponding definition (or other source of prototype information)
2627          for.
2628
2629          Gripe even if the unprototyped declaration we are worried about
2630          exists in a file in one of the "system" include directories.  We
2631          can gripe about these because we should have at least found a
2632          corresponding (pseudo) definition in the SYSCALLS.c.X file.  If we
2633          didn't, then that means that the SYSCALLS.c.X file is missing some
2634          needed prototypes for this particular system.  That is worth telling
2635          the user about!  */
2636
2637       if (!extern_def_p)
2638         {
2639           const char *file = user->file->hash_entry->symbol;
2640
2641           if (!quiet_flag)
2642             if (in_system_include_dir (file))
2643               {
2644                 /* Why copy this string into `needed' at all?
2645                    Why not just use user->ansi_decl without copying?  */
2646                 char *needed = (char *) alloca (strlen (user->ansi_decl) + 1);
2647                 char *p;
2648
2649                 strcpy (needed, user->ansi_decl);
2650                 p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
2651                     + strlen (user->hash_entry->symbol) + 2;
2652                 /* Avoid having ??? in the string.  */
2653                 *p++ = '?';
2654                 *p++ = '?';
2655                 *p++ = '?';
2656                 strcpy (p, ");");
2657
2658                 notice ("%s: %d: `%s' used but missing from SYSCALLS\n",
2659                         shortpath (NULL, file), user->line,
2660                         needed+7);      /* Don't print "extern " */
2661               }
2662 #if 0
2663             else
2664               notice ("%s: %d: warning: no extern definition for `%s'\n",
2665                       shortpath (NULL, file), user->line,
2666                       user->hash_entry->symbol);
2667 #endif
2668         }
2669     }
2670   return extern_def_p;
2671 }
2672 \f
2673 /* Find the (only?) static definition for a particular function name in a
2674    given file.  Here we get the function-name and the file info indirectly
2675    from the def_dec_info record pointer which is passed in.  */
2676
2677 static const def_dec_info *
2678 find_static_definition (user)
2679      const def_dec_info *user;
2680 {
2681   const def_dec_info *head = user->hash_entry->ddip;
2682   const def_dec_info *dd_p;
2683   int num_static_defs = 0;
2684   const def_dec_info *static_def_p = NULL;
2685
2686   for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2687     if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2688       {
2689         static_def_p = dd_p;    /* save a pointer to the definition */
2690         num_static_defs++;
2691       }
2692   if (num_static_defs == 0)
2693     {
2694       if (!quiet_flag)
2695         notice ("%s: warning: no static definition for `%s' in file `%s'\n",
2696                 pname, head->hash_entry->symbol,
2697                 shortpath (NULL, user->file->hash_entry->symbol));
2698     }
2699   else if (num_static_defs > 1)
2700     {
2701       notice ("%s: multiple static defs of `%s' in file `%s'\n",
2702               pname, head->hash_entry->symbol,
2703               shortpath (NULL, user->file->hash_entry->symbol));
2704       return NULL;
2705     }
2706   return static_def_p;
2707 }
2708
2709 /* Find good prototype style formal argument lists for all of the function
2710    declarations which didn't have them before now.
2711
2712    To do this we consider each function name one at a time.  For each function
2713    name, we look at the items on the linked list of def_dec_info records for
2714    that particular name.
2715
2716    Somewhere on this list we should find one (and only one) def_dec_info
2717    record which represents the actual function definition, and this record
2718    should have a nice formal argument list already associated with it.
2719
2720    Thus, all we have to do is to connect up all of the other def_dec_info
2721    records for this particular function name to the special one which has
2722    the full-blown formals list.
2723
2724    Of course it is a little more complicated than just that.  See below for
2725    more details.  */
2726
2727 static void
2728 connect_defs_and_decs (hp)
2729      const hash_table_entry *hp;
2730 {
2731   const def_dec_info *dd_p;
2732   const def_dec_info *extern_def_p = NULL;
2733   int first_extern_reference = 1;
2734
2735   /* Traverse the list of definitions and declarations for this particular
2736      function name.  For each item on the list, if it is a function
2737      definition (either old style or new style) then GCC has already been
2738      kind enough to produce a prototype for us, and it is associated with
2739      the item already, so declare the item as its own associated "definition".
2740
2741      Also, for each item which is only a function declaration, but which
2742      nonetheless has its own prototype already (obviously supplied by the user)
2743      declare the item as its own definition.
2744
2745      Note that when/if there are multiple user-supplied prototypes already
2746      present for multiple declarations of any given function, these multiple
2747      prototypes *should* all match exactly with one another and with the
2748      prototype for the actual function definition.  We don't check for this
2749      here however, since we assume that the compiler must have already done
2750      this consistency checking when it was creating the .X files.  */
2751
2752   for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2753     if (dd_p->prototyped)
2754       ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2755
2756   /* Traverse the list of definitions and declarations for this particular
2757      function name.  For each item on the list, if it is an extern function
2758      declaration and if it has no associated definition yet, go try to find
2759      the matching extern definition for the declaration.
2760
2761      When looking for the matching function definition, warn the user if we
2762      fail to find one.
2763
2764      If we find more that one function definition also issue a warning.
2765
2766      Do the search for the matching definition only once per unique function
2767      name (and only when absolutely needed) so that we can avoid putting out
2768      redundant warning messages, and so that we will only put out warning
2769      messages when there is actually a reference (i.e. a declaration) for
2770      which we need to find a matching definition.  */
2771
2772   for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2773     if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2774       {
2775         if (first_extern_reference)
2776           {
2777             extern_def_p = find_extern_def (hp->ddip, dd_p);
2778             first_extern_reference = 0;
2779           }
2780         ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2781       }
2782
2783   /* Traverse the list of definitions and declarations for this particular
2784      function name.  For each item on the list, if it is a static function
2785      declaration and if it has no associated definition yet, go try to find
2786      the matching static definition for the declaration within the same file.
2787
2788      When looking for the matching function definition, warn the user if we
2789      fail to find one in the same file with the declaration, and refuse to
2790      convert this kind of cross-file static function declaration.  After all,
2791      this is stupid practice and should be discouraged.
2792
2793      We don't have to worry about the possibility that there is more than one
2794      matching function definition in the given file because that would have
2795      been flagged as an error by the compiler.
2796
2797      Do the search for the matching definition only once per unique
2798      function-name/source-file pair (and only when absolutely needed) so that
2799      we can avoid putting out redundant warning messages, and so that we will
2800      only put out warning messages when there is actually a reference (i.e. a
2801      declaration) for which we actually need to find a matching definition.  */
2802
2803   for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2804     if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2805       {
2806         const def_dec_info *dd_p2;
2807         const def_dec_info *static_def;
2808
2809         /* We have now found a single static declaration for which we need to
2810            find a matching definition.  We want to minimize the work (and the
2811            number of warnings), so we will find an appropriate (matching)
2812            static definition for this declaration, and then distribute it
2813            (as the definition for) any and all other static declarations
2814            for this function name which occur within the same file, and which
2815            do not already have definitions.
2816
2817            Note that a trick is used here to prevent subsequent attempts to
2818            call find_static_definition for a given function-name & file
2819            if the first such call returns NULL.  Essentially, we convert
2820            these NULL return values to -1, and put the -1 into the definition
2821            field for each other static declaration from the same file which
2822            does not already have an associated definition.
2823            This makes these other static declarations look like they are
2824            actually defined already when the outer loop here revisits them
2825            later on.  Thus, the outer loop will skip over them.  Later, we
2826            turn the -1's back to NULL's.  */
2827
2828       ((NONCONST def_dec_info *) dd_p)->definition =
2829         (static_def = find_static_definition (dd_p))
2830           ? static_def
2831           : (const def_dec_info *) -1;
2832
2833       for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2834         if (!dd_p2->is_func_def && dd_p2->is_static
2835          && !dd_p2->definition && (dd_p2->file == dd_p->file))
2836           ((NONCONST def_dec_info *)dd_p2)->definition = dd_p->definition;
2837       }
2838
2839   /* Convert any dummy (-1) definitions we created in the step above back to
2840      NULL's (as they should be).  */
2841
2842   for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2843     if (dd_p->definition == (def_dec_info *) -1)
2844       ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2845 }
2846
2847 #endif /* !defined (UNPROTOIZE) */
2848
2849 /* Give a pointer into the clean text buffer, return a number which is the
2850    original source line number that the given pointer points into.  */
2851
2852 static int
2853 identify_lineno (clean_p)
2854      const char *clean_p;
2855 {
2856   int line_num = 1;
2857   const char *scan_p;
2858
2859   for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2860     if (*scan_p == '\n')
2861       line_num++;
2862   return line_num;
2863 }
2864
2865 /* Issue an error message and give up on doing this particular edit.  */
2866
2867 static void
2868 declare_source_confusing (clean_p)
2869      const char *clean_p;
2870 {
2871   if (!quiet_flag)
2872     {
2873       if (clean_p == 0)
2874         notice ("%s: %d: warning: source too confusing\n",
2875                 shortpath (NULL, convert_filename), last_known_line_number);
2876       else
2877         notice ("%s: %d: warning: source too confusing\n",
2878                 shortpath (NULL, convert_filename),
2879                 identify_lineno (clean_p));
2880     }
2881   longjmp (source_confusion_recovery, 1);
2882 }
2883
2884 /* Check that a condition which is expected to be true in the original source
2885    code is in fact true.  If not, issue an error message and give up on
2886    converting this particular source file.  */
2887
2888 static void
2889 check_source (cond, clean_p)
2890      int cond;
2891      const char *clean_p;
2892 {
2893   if (!cond)
2894     declare_source_confusing (clean_p);
2895 }
2896
2897 /* If we think of the in-core cleaned text buffer as a memory mapped
2898    file (with the variable last_known_line_start acting as sort of a
2899    file pointer) then we can imagine doing "seeks" on the buffer.  The
2900    following routine implements a kind of "seek" operation for the in-core
2901    (cleaned) copy of the source file.  When finished, it returns a pointer to
2902    the start of a given (numbered) line in the cleaned text buffer.
2903
2904    Note that protoize only has to "seek" in the forward direction on the
2905    in-core cleaned text file buffers, and it never needs to back up.
2906
2907    This routine is made a little bit faster by remembering the line number
2908    (and pointer value) supplied (and returned) from the previous "seek".
2909    This prevents us from always having to start all over back at the top
2910    of the in-core cleaned buffer again.  */
2911
2912 static const char *
2913 seek_to_line (n)
2914      int n;
2915 {
2916   if (n < last_known_line_number)
2917     abort ();
2918
2919   while (n > last_known_line_number)
2920     {
2921       while (*last_known_line_start != '\n')
2922         check_source (++last_known_line_start < clean_text_limit, 0);
2923       last_known_line_start++;
2924       last_known_line_number++;
2925     }
2926   return last_known_line_start;
2927 }
2928
2929 /* Given a pointer to a character in the cleaned text buffer, return a pointer
2930    to the next non-whitespace character which follows it.  */
2931
2932 static const char *
2933 forward_to_next_token_char (ptr)
2934      const char *ptr;
2935 {
2936   for (++ptr; ISSPACE ((const unsigned char)*ptr);
2937        check_source (++ptr < clean_text_limit, 0))
2938     continue;
2939   return ptr;
2940 }
2941
2942 /* Copy a chunk of text of length `len' and starting at `str' to the current
2943    output buffer.  Note that all attempts to add stuff to the current output
2944    buffer ultimately go through here.  */
2945
2946 static void
2947 output_bytes (str, len)
2948      const char *str;
2949      size_t len;
2950 {
2951   if ((repl_write_ptr + 1) + len >= repl_text_limit)
2952     {
2953       size_t new_size = (repl_text_limit - repl_text_base) << 1;
2954       char *new_buf = (char *) xrealloc (repl_text_base, new_size);
2955
2956       repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
2957       repl_text_base = new_buf;
2958       repl_text_limit = new_buf + new_size;
2959     }
2960   memcpy (repl_write_ptr + 1, str, len);
2961   repl_write_ptr += len;
2962 }
2963
2964 /* Copy all bytes (except the trailing null) of a null terminated string to
2965    the current output buffer.  */
2966
2967 static void
2968 output_string (str)
2969      const char *str;
2970 {
2971   output_bytes (str, strlen (str));
2972 }
2973
2974 /* Copy some characters from the original text buffer to the current output
2975    buffer.
2976
2977    This routine takes a pointer argument `p' which is assumed to be a pointer
2978    into the cleaned text buffer.  The bytes which are copied are the `original'
2979    equivalents for the set of bytes between the last value of `clean_read_ptr'
2980    and the argument value `p'.
2981
2982    The set of bytes copied however, comes *not* from the cleaned text buffer,
2983    but rather from the direct counterparts of these bytes within the original
2984    text buffer.
2985
2986    Thus, when this function is called, some bytes from the original text
2987    buffer (which may include original comments and preprocessing directives)
2988    will be copied into the  output buffer.
2989
2990    Note that the request implied when this routine is called includes the
2991    byte pointed to by the argument pointer `p'.  */
2992
2993 static void
2994 output_up_to (p)
2995      const char *p;
2996 {
2997   size_t copy_length = (size_t) (p - clean_read_ptr);
2998   const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
2999
3000   if (copy_length == 0)
3001     return;
3002
3003   output_bytes (copy_start, copy_length);
3004   clean_read_ptr = p;
3005 }
3006
3007 /* Given a pointer to a def_dec_info record which represents some form of
3008    definition of a function (perhaps a real definition, or in lieu of that
3009    perhaps just a declaration with a full prototype) return true if this
3010    function is one which we should avoid converting.  Return false
3011    otherwise.  */
3012
3013 static int
3014 other_variable_style_function (ansi_header)
3015      const char *ansi_header;
3016 {
3017 #ifdef UNPROTOIZE
3018
3019   /* See if we have a stdarg function, or a function which has stdarg style
3020      parameters or a stdarg style return type.  */
3021
3022   return substr (ansi_header, "...") != 0;
3023
3024 #else /* !defined (UNPROTOIZE) */
3025
3026   /* See if we have a varargs function, or a function which has varargs style
3027      parameters or a varargs style return type.  */
3028
3029   const char *p;
3030   int len = strlen (varargs_style_indicator);
3031
3032   for (p = ansi_header; p; )
3033     {
3034       const char *candidate;
3035
3036       if ((candidate = substr (p, varargs_style_indicator)) == 0)
3037         return 0;
3038       else
3039         if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
3040           return 1;
3041         else
3042           p = candidate + 1;
3043     }
3044   return 0;
3045 #endif /* !defined (UNPROTOIZE) */
3046 }
3047
3048 /* Do the editing operation specifically for a function "declaration".  Note
3049    that editing for function "definitions" are handled in a separate routine
3050    below.  */
3051
3052 static void
3053 edit_fn_declaration (def_dec_p, clean_text_p)
3054      const def_dec_info *def_dec_p;
3055      const char *volatile clean_text_p;
3056 {
3057   const char *start_formals;
3058   const char *end_formals;
3059   const char *function_to_edit = def_dec_p->hash_entry->symbol;
3060   size_t func_name_len = strlen (function_to_edit);
3061   const char *end_of_fn_name;
3062
3063 #ifndef UNPROTOIZE
3064
3065   const f_list_chain_item *this_f_list_chain_item;
3066   const def_dec_info *definition = def_dec_p->definition;
3067
3068   /* If we are protoizing, and if we found no corresponding definition for
3069      this particular function declaration, then just leave this declaration
3070      exactly as it is.  */
3071
3072   if (!definition)
3073     return;
3074
3075   /* If we are protoizing, and if the corresponding definition that we found
3076      for this particular function declaration defined an old style varargs
3077      function, then we want to issue a warning and just leave this function
3078      declaration unconverted.  */
3079
3080   if (other_variable_style_function (definition->ansi_decl))
3081     {
3082       if (!quiet_flag)
3083         notice ("%s: %d: warning: varargs function declaration not converted\n",
3084                 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3085                 def_dec_p->line);
3086       return;
3087     }
3088
3089 #endif /* !defined (UNPROTOIZE) */
3090
3091   /* Setup here to recover from confusing source code detected during this
3092      particular "edit".  */
3093
3094   save_pointers ();
3095   if (setjmp (source_confusion_recovery))
3096     {
3097       restore_pointers ();
3098       notice ("%s: declaration of function `%s' not converted\n",
3099               pname, function_to_edit);
3100       return;
3101     }
3102
3103   /* We are editing a function declaration.  The line number we did a seek to
3104      contains the comma or semicolon which follows the declaration.  Our job
3105      now is to scan backwards looking for the function name.  This name *must*
3106      be followed by open paren (ignoring whitespace, of course).  We need to
3107      replace everything between that open paren and the corresponding closing
3108      paren.  If we are protoizing, we need to insert the prototype-style
3109      formals lists.  If we are unprotoizing, we need to just delete everything
3110      between the pairs of opening and closing parens.  */
3111
3112   /* First move up to the end of the line.  */
3113
3114   while (*clean_text_p != '\n')
3115     check_source (++clean_text_p < clean_text_limit, 0);
3116   clean_text_p--;  /* Point to just before the newline character.  */
3117
3118   /* Now we can scan backwards for the function name.  */
3119
3120   do
3121     {
3122       for (;;)
3123         {
3124           /* Scan leftwards until we find some character which can be
3125              part of an identifier.  */
3126
3127           while (!is_id_char (*clean_text_p))
3128             check_source (--clean_text_p > clean_read_ptr, 0);
3129
3130           /* Scan backwards until we find a char that cannot be part of an
3131              identifier.  */
3132
3133           while (is_id_char (*clean_text_p))
3134             check_source (--clean_text_p > clean_read_ptr, 0);
3135
3136           /* Having found an "id break", see if the following id is the one
3137              that we are looking for.  If so, then exit from this loop.  */
3138
3139           if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
3140             {
3141               char ch = *(clean_text_p + 1 + func_name_len);
3142
3143               /* Must also check to see that the name in the source text
3144                  ends where it should (in order to prevent bogus matches
3145                  on similar but longer identifiers.  */
3146
3147               if (! is_id_char (ch))
3148                 break;                  /* exit from loop */
3149             }
3150         }
3151     
3152       /* We have now found the first perfect match for the function name in
3153          our backward search.  This may or may not be the actual function
3154          name at the start of the actual function declaration (i.e. we could
3155          have easily been mislead).  We will try to avoid getting fooled too
3156          often by looking forward for the open paren which should follow the
3157          identifier we just found.  We ignore whitespace while hunting.  If
3158          the next non-whitespace byte we see is *not* an open left paren,
3159          then we must assume that we have been fooled and we start over
3160          again accordingly.  Note that there is no guarantee, that even if
3161          we do see the open paren, that we are in the right place.
3162          Programmers do the strangest things sometimes!  */
3163     
3164       end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
3165       start_formals = forward_to_next_token_char (end_of_fn_name);
3166     }
3167   while (*start_formals != '(');
3168
3169   /* start_of_formals now points to the opening left paren which immediately
3170      follows the name of the function.  */
3171
3172   /* Note that there may be several formals lists which need to be modified
3173      due to the possibility that the return type of this function is a
3174      pointer-to-function type.  If there are several formals lists, we
3175      convert them in left-to-right order here.  */
3176
3177 #ifndef UNPROTOIZE
3178   this_f_list_chain_item = definition->f_list_chain;
3179 #endif /* !defined (UNPROTOIZE) */
3180
3181   for (;;)
3182     {
3183       {
3184         int depth;
3185
3186         end_formals = start_formals + 1;
3187         depth = 1;
3188         for (; depth; check_source (++end_formals < clean_text_limit, 0))
3189           {
3190             switch (*end_formals)
3191               {
3192                 case '(':
3193                   depth++;
3194                   break;
3195                 case ')':
3196                   depth--;
3197                   break;
3198               }
3199           }
3200         end_formals--;
3201       }
3202
3203       /* end_formals now points to the closing right paren of the formals
3204          list whose left paren is pointed to by start_formals.  */
3205     
3206       /* Now, if we are protoizing, we insert the new ANSI-style formals list
3207          attached to the associated definition of this function.  If however
3208          we are unprotoizing, then we simply delete any formals list which
3209          may be present.  */
3210     
3211       output_up_to (start_formals);
3212 #ifndef UNPROTOIZE
3213       if (this_f_list_chain_item)
3214         {
3215           output_string (this_f_list_chain_item->formals_list);
3216           this_f_list_chain_item = this_f_list_chain_item->chain_next;
3217         }
3218       else
3219         {
3220           if (!quiet_flag)
3221             notice ("%s: warning: too many parameter lists in declaration of `%s'\n",
3222                     pname, def_dec_p->hash_entry->symbol);
3223           check_source (0, end_formals);  /* leave the declaration intact */
3224         }
3225 #endif /* !defined (UNPROTOIZE) */
3226       clean_read_ptr = end_formals - 1;
3227
3228       /* Now see if it looks like there may be another formals list associated
3229          with the function declaration that we are converting (following the
3230          formals list that we just converted.  */
3231
3232       {
3233         const char *another_r_paren = forward_to_next_token_char (end_formals);
3234
3235         if ((*another_r_paren != ')')
3236             || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3237           {
3238 #ifndef UNPROTOIZE
3239             if (this_f_list_chain_item)
3240               {
3241                 if (!quiet_flag)
3242                   notice ("\n%s: warning: too few parameter lists in declaration of `%s'\n",
3243                           pname, def_dec_p->hash_entry->symbol);
3244                 check_source (0, start_formals); /* leave the decl intact */
3245               }
3246 #endif /* !defined (UNPROTOIZE) */
3247             break;
3248   
3249           }
3250       }
3251
3252       /* There does appear to be yet another formals list, so loop around
3253          again, and convert it also.  */
3254     }
3255 }
3256
3257 /* Edit a whole group of formals lists, starting with the rightmost one
3258    from some set of formals lists.  This routine is called once (from the
3259    outside) for each function declaration which is converted.  It is
3260    recursive however, and it calls itself once for each remaining formal
3261    list that lies to the left of the one it was originally called to work
3262    on.  Thus, a whole set gets done in right-to-left order.
3263
3264    This routine returns non-zero if it thinks that it should not be trying
3265    to convert this particular function definition (because the name of the
3266    function doesn't match the one expected).  */
3267
3268 static int
3269 edit_formals_lists (end_formals, f_list_count, def_dec_p)
3270      const char *end_formals;
3271      unsigned int f_list_count;
3272      const def_dec_info *def_dec_p;
3273 {
3274   const char *start_formals;
3275   int depth;
3276
3277   start_formals = end_formals - 1;
3278   depth = 1;
3279   for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3280     {
3281       switch (*start_formals)
3282         {
3283           case '(':
3284             depth--;
3285             break;
3286           case ')':
3287             depth++;
3288             break;
3289         }
3290     }
3291   start_formals++;
3292
3293   /* start_formals now points to the opening left paren of the formals list.  */
3294
3295   f_list_count--;
3296
3297   if (f_list_count)
3298     {
3299       const char *next_end;
3300
3301       /* There should be more formal lists to the left of here.  */
3302
3303       next_end = start_formals - 1;
3304       check_source (next_end > clean_read_ptr, 0);
3305       while (ISSPACE ((const unsigned char)*next_end))
3306         check_source (--next_end > clean_read_ptr, 0);
3307       check_source (*next_end == ')', next_end);
3308       check_source (--next_end > clean_read_ptr, 0);
3309       check_source (*next_end == ')', next_end);
3310       if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3311         return 1;
3312     }
3313
3314   /* Check that the function name in the header we are working on is the same
3315      as the one we would expect to find.  If not, issue a warning and return
3316      non-zero.  */
3317
3318   if (f_list_count == 0)
3319     {
3320       const char *expected = def_dec_p->hash_entry->symbol;
3321       const char *func_name_start;
3322       const char *func_name_limit;
3323       size_t func_name_len;
3324
3325       for (func_name_limit = start_formals-1;
3326            ISSPACE ((const unsigned char)*func_name_limit); )
3327         check_source (--func_name_limit > clean_read_ptr, 0);
3328
3329       for (func_name_start = func_name_limit++;
3330            is_id_char (*func_name_start);
3331            func_name_start--)
3332         check_source (func_name_start > clean_read_ptr, 0);
3333       func_name_start++;
3334       func_name_len = func_name_limit - func_name_start;
3335       if (func_name_len == 0)
3336         check_source (0, func_name_start);
3337       if (func_name_len != strlen (expected)
3338           || strncmp (func_name_start, expected, func_name_len))
3339         {
3340           notice ("%s: %d: warning: found `%s' but expected `%s'\n",
3341                   shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3342                   identify_lineno (func_name_start),
3343                   dupnstr (func_name_start, func_name_len),
3344                   expected);
3345           return 1;
3346         }
3347     }
3348
3349   output_up_to (start_formals);
3350
3351 #ifdef UNPROTOIZE
3352   if (f_list_count == 0)
3353     output_string (def_dec_p->formal_names);
3354 #else /* !defined (UNPROTOIZE) */
3355   {
3356     unsigned f_list_depth;
3357     const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3358
3359     /* At this point, the current value of f_list count says how many
3360        links we have to follow through the f_list_chain to get to the
3361        particular formals list that we need to output next.  */
3362
3363     for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3364       flci_p = flci_p->chain_next;
3365     output_string (flci_p->formals_list);
3366   }
3367 #endif /* !defined (UNPROTOIZE) */
3368
3369   clean_read_ptr = end_formals - 1;
3370   return 0;
3371 }
3372
3373 /* Given a pointer to a byte in the clean text buffer which points to
3374    the beginning of a line that contains a "follower" token for a
3375    function definition header, do whatever is necessary to find the
3376    right closing paren for the rightmost formals list of the function
3377    definition header.  */
3378
3379 static const char *
3380 find_rightmost_formals_list (clean_text_p)
3381      const char *clean_text_p;
3382 {
3383   const char *end_formals;
3384
3385   /* We are editing a function definition.  The line number we did a seek
3386      to contains the first token which immediately follows the entire set of
3387      formals lists which are part of this particular function definition
3388      header.
3389
3390      Our job now is to scan leftwards in the clean text looking for the
3391      right-paren which is at the end of the function header's rightmost
3392      formals list.
3393
3394      If we ignore whitespace, this right paren should be the first one we
3395      see which is (ignoring whitespace) immediately followed either by the
3396      open curly-brace beginning the function body or by an alphabetic
3397      character (in the case where the function definition is in old (K&R)
3398      style and there are some declarations of formal parameters).  */
3399
3400    /* It is possible that the right paren we are looking for is on the
3401       current line (together with its following token).  Just in case that
3402       might be true, we start out here by skipping down to the right end of
3403       the current line before starting our scan.  */
3404
3405   for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3406     continue;
3407   end_formals--;
3408
3409 #ifdef UNPROTOIZE
3410
3411   /* Now scan backwards while looking for the right end of the rightmost
3412      formals list associated with this function definition.  */
3413
3414   {
3415     char ch;
3416     const char *l_brace_p;
3417
3418     /* Look leftward and try to find a right-paren.  */
3419
3420     while (*end_formals != ')')
3421       {
3422         if (ISSPACE ((unsigned char)*end_formals))
3423           while (ISSPACE ((unsigned char)*end_formals))
3424             check_source (--end_formals > clean_read_ptr, 0);
3425         else
3426           check_source (--end_formals > clean_read_ptr, 0);
3427       }
3428
3429     ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3430     /* Since we are unprotoizing an ANSI-style (prototyped) function
3431        definition, there had better not be anything (except whitespace)
3432        between the end of the ANSI formals list and the beginning of the
3433        function body (i.e. the '{').  */
3434
3435     check_source (ch == '{', l_brace_p);
3436   }
3437
3438 #else /* !defined (UNPROTOIZE) */
3439
3440   /* Now scan backwards while looking for the right end of the rightmost
3441      formals list associated with this function definition.  */
3442
3443   while (1)
3444     {
3445       char ch;
3446       const char *l_brace_p;
3447
3448       /* Look leftward and try to find a right-paren.  */
3449
3450       while (*end_formals != ')')
3451         {
3452           if (ISSPACE ((const unsigned char)*end_formals))
3453             while (ISSPACE ((const unsigned char)*end_formals))
3454               check_source (--end_formals > clean_read_ptr, 0);
3455           else
3456             check_source (--end_formals > clean_read_ptr, 0);
3457         }
3458
3459       ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3460
3461       /* Since it is possible that we found a right paren before the starting
3462          '{' of the body which IS NOT the one at the end of the real K&R
3463          formals list (say for instance, we found one embedded inside one of
3464          the old K&R formal parameter declarations) we have to check to be
3465          sure that this is in fact the right paren that we were looking for.
3466
3467          The one we were looking for *must* be followed by either a '{' or
3468          by an alphabetic character, while others *cannot* validly be followed
3469          by such characters.  */
3470
3471       if ((ch == '{') || ISALPHA ((unsigned char)ch))
3472         break;
3473
3474       /* At this point, we have found a right paren, but we know that it is
3475          not the one we were looking for, so backup one character and keep
3476          looking.  */
3477
3478       check_source (--end_formals > clean_read_ptr, 0);
3479     }
3480
3481 #endif /* !defined (UNPROTOIZE) */
3482
3483   return end_formals;
3484 }
3485
3486 #ifndef UNPROTOIZE
3487
3488 /* Insert into the output file a totally new declaration for a function
3489    which (up until now) was being called from within the current block
3490    without having been declared at any point such that the declaration
3491    was visible (i.e. in scope) at the point of the call.
3492
3493    We need to add in explicit declarations for all such function calls
3494    in order to get the full benefit of prototype-based function call
3495    parameter type checking.  */
3496
3497 static void
3498 add_local_decl (def_dec_p, clean_text_p)
3499      const def_dec_info *def_dec_p;
3500      const char *clean_text_p;
3501 {
3502   const char *start_of_block;
3503   const char *function_to_edit = def_dec_p->hash_entry->symbol;
3504
3505   /* Don't insert new local explicit declarations unless explicitly requested
3506      to do so.  */
3507
3508   if (!local_flag)
3509     return;
3510
3511   /* Setup here to recover from confusing source code detected during this
3512      particular "edit".  */
3513
3514   save_pointers ();
3515   if (setjmp (source_confusion_recovery))
3516     {
3517       restore_pointers ();
3518       notice ("%s: local declaration for function `%s' not inserted\n",
3519               pname, function_to_edit);
3520       return;
3521     }
3522
3523   /* We have already done a seek to the start of the line which should
3524      contain *the* open curly brace which begins the block in which we need
3525      to insert an explicit function declaration (to replace the implicit one).
3526
3527      Now we scan that line, starting from the left, until we find the
3528      open curly brace we are looking for.  Note that there may actually be
3529      multiple open curly braces on the given line, but we will be happy
3530      with the leftmost one no matter what.  */
3531
3532   start_of_block = clean_text_p;
3533   while (*start_of_block != '{' && *start_of_block != '\n')
3534     check_source (++start_of_block < clean_text_limit, 0);
3535
3536   /* Note that the line from the original source could possibly
3537      contain *no* open curly braces!  This happens if the line contains
3538      a macro call which expands into a chunk of text which includes a
3539      block (and that block's associated open and close curly braces).
3540      In cases like this, we give up, issue a warning, and do nothing.  */
3541
3542   if (*start_of_block != '{')
3543     {
3544       if (!quiet_flag)
3545         notice ("\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
3546           def_dec_p->file->hash_entry->symbol, def_dec_p->line, 
3547           def_dec_p->hash_entry->symbol);
3548       return;
3549     }
3550
3551   /* Figure out what a nice (pretty) indentation would be for the new
3552      declaration we are adding.  In order to do this, we must scan forward
3553      from the '{' until we find the first