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