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