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