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