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