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