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