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