Fix typos in comment
[official-gcc.git] / gcc / protoize.c
blob7a58df23ef7d6932471b68a26f83902642d07ddf
1 /* Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com).
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "intl.h"
26 #include <setjmp.h>
27 #include <signal.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #undef abort
32 #include "version.h"
34 /* Include getopt.h for the sake of getopt_long. */
35 #include "getopt.h"
37 /* Macro to see if the path elements match. */
38 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
39 #define IS_SAME_PATH_CHAR(a,b) (toupper (a) == toupper (b))
40 #else
41 #define IS_SAME_PATH_CHAR(a,b) ((a) == (b))
42 #endif
44 /* Macro to see if the paths match. */
45 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
46 #define IS_SAME_PATH(a,b) (strcasecmp (a, b) == 0)
47 #else
48 #define IS_SAME_PATH(a,b) (strcmp (a, b) == 0)
49 #endif
51 /* Suffix for aux-info files. */
52 #ifdef __MSDOS__
53 #define AUX_INFO_SUFFIX "X"
54 #else
55 #define AUX_INFO_SUFFIX ".X"
56 #endif
58 /* Suffix for saved files. */
59 #ifdef __MSDOS__
60 #define SAVE_SUFFIX "sav"
61 #else
62 #define SAVE_SUFFIX ".save"
63 #endif
65 /* Suffix for renamed C++ files. */
66 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
67 #define CPLUS_FILE_SUFFIX "cc"
68 #else
69 #define CPLUS_FILE_SUFFIX "C"
70 #endif
72 static void usage PARAMS ((void)) ATTRIBUTE_NORETURN;
73 static void aux_info_corrupted PARAMS ((void)) ATTRIBUTE_NORETURN;
74 static void declare_source_confusing PARAMS ((const char *)) ATTRIBUTE_NORETURN;
75 static const char *shortpath PARAMS ((const char *, const char *));
76 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
77 static void notice PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
78 static char *savestring PARAMS ((const char *, unsigned int));
79 static char *dupnstr PARAMS ((const char *, size_t));
80 static const char *substr PARAMS ((const char *, const char * const));
81 static int safe_read PARAMS ((int, PTR, int));
82 static void safe_write PARAMS ((int, PTR, int, const char *));
83 static void save_pointers PARAMS ((void));
84 static void restore_pointers PARAMS ((void));
85 static int is_id_char PARAMS ((int));
86 static int in_system_include_dir PARAMS ((const char *));
87 static int directory_specified_p PARAMS ((const char *));
88 static int file_excluded_p PARAMS ((const char *));
89 static char *unexpand_if_needed PARAMS ((const char *));
90 static char *abspath PARAMS ((const char *, const char *));
91 static int is_abspath PARAMS ((const char *));
92 static void check_aux_info PARAMS ((int));
93 static const char *find_corresponding_lparen PARAMS ((const char *));
94 static int referenced_file_is_newer PARAMS ((const char *, time_t));
95 static void save_def_or_dec PARAMS ((const char *, int));
96 static void munge_compile_params PARAMS ((const char *));
97 static int gen_aux_info_file PARAMS ((const char *));
98 static void process_aux_info_file PARAMS ((const char *, int, int));
99 static int identify_lineno PARAMS ((const char *));
100 static void check_source PARAMS ((int, const char *));
101 static const char *seek_to_line PARAMS ((int));
102 static const char *forward_to_next_token_char PARAMS ((const char *));
103 static void output_bytes PARAMS ((const char *, size_t));
104 static void output_string PARAMS ((const char *));
105 static void output_up_to PARAMS ((const char *));
106 static int other_variable_style_function PARAMS ((const char *));
107 static const char *find_rightmost_formals_list PARAMS ((const char *));
108 static void do_cleaning PARAMS ((char *, const char *));
109 static const char *careful_find_l_paren PARAMS ((const char *));
110 static void do_processing PARAMS ((void));
112 /* Look for these where the `const' qualifier is intentionally cast aside. */
113 #define NONCONST
115 /* Define a default place to find the SYSCALLS.X file. */
117 #ifndef UNPROTOIZE
119 #ifndef STANDARD_EXEC_PREFIX
120 #define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
121 #endif /* !defined STANDARD_EXEC_PREFIX */
123 static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX;
124 static const char * const target_machine = DEFAULT_TARGET_MACHINE;
125 static const char * const target_version = DEFAULT_TARGET_VERSION;
127 #ifndef GET_ENV_PATH_LIST
128 #define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
129 #endif
131 #endif /* !defined (UNPROTOIZE) */
133 /* Suffix of aux_info files. */
135 static const char * const aux_info_suffix = AUX_INFO_SUFFIX;
137 /* String to attach to filenames for saved versions of original files. */
139 static const char * const save_suffix = SAVE_SUFFIX;
141 /* String to attach to C filenames renamed to C++. */
143 static const char * const cplus_suffix = CPLUS_FILE_SUFFIX;
145 #ifndef UNPROTOIZE
147 /* File name of the file which contains descriptions of standard system
148 routines. Note that we never actually do anything with this file per se,
149 but we do read in its corresponding aux_info file. */
151 static const char syscalls_filename[] = "SYSCALLS.c";
153 /* Default place to find the above file. */
155 static const char * default_syscalls_dir;
157 /* Variable to hold the complete absolutized filename of the SYSCALLS.c.X
158 file. */
160 static char * syscalls_absolute_filename;
162 #endif /* !defined (UNPROTOIZE) */
164 /* Type of the structure that holds information about macro unexpansions. */
166 struct unexpansion_struct {
167 const char *expanded;
168 const char *contracted;
170 typedef struct unexpansion_struct unexpansion;
172 /* A table of conversions that may need to be made for some (stupid) older
173 operating systems where these types are preprocessor macros rather than
174 typedefs (as they really ought to be).
176 WARNING: The contracted forms must be as small (or smaller) as the
177 expanded forms, or else havoc will ensue. */
179 static const unexpansion unexpansions[] = {
180 { "struct _iobuf", "FILE" },
181 { 0, 0 }
184 /* The number of "primary" slots in the hash tables for filenames and for
185 function names. This can be as big or as small as you like, except that
186 it must be a power of two. */
188 #define HASH_TABLE_SIZE (1 << 9)
190 /* Bit mask to use when computing hash values. */
192 static const int hash_mask = (HASH_TABLE_SIZE - 1);
194 /* Make a table of default system include directories
195 just as it is done in cpp. */
197 #ifndef STANDARD_INCLUDE_DIR
198 #define STANDARD_INCLUDE_DIR "/usr/include"
199 #endif
201 #ifndef LOCAL_INCLUDE_DIR
202 #define LOCAL_INCLUDE_DIR "/usr/local/include"
203 #endif
205 struct default_include { const char *fname;
206 const char *component;
207 int x1, x2; } include_defaults[]
208 #ifdef INCLUDE_DEFAULTS
209 = INCLUDE_DEFAULTS;
210 #else
212 /* Pick up GNU C++ specific include files. */
213 { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
214 #ifdef CROSS_COMPILE
215 /* This is the dir for fixincludes. Put it just before
216 the files that we fix. */
217 { GCC_INCLUDE_DIR, "GCC", 0, 0 },
218 /* For cross-compilation, this dir name is generated
219 automatically in Makefile.in. */
220 { CROSS_INCLUDE_DIR, 0, 0, 0 },
221 /* This is another place that the target system's headers might be. */
222 { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
223 #else /* not CROSS_COMPILE */
224 /* This should be /use/local/include and should come before
225 the fixincludes-fixed header files. */
226 { LOCAL_INCLUDE_DIR, 0, 0, 1 },
227 /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
228 Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */
229 { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
230 /* This is the dir for fixincludes. Put it just before
231 the files that we fix. */
232 { GCC_INCLUDE_DIR, "GCC", 0, 0 },
233 /* Some systems have an extra dir of include files. */
234 #ifdef SYSTEM_INCLUDE_DIR
235 { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
236 #endif
237 { STANDARD_INCLUDE_DIR, 0, 0, 0},
238 #endif /* not CROSS_COMPILE */
239 { 0, 0, 0, 0}
241 #endif /* no INCLUDE_DEFAULTS */
243 /* Datatype for lists of directories or filenames. */
244 struct string_list
246 const char *name;
247 struct string_list *next;
250 static struct string_list *string_list_cons PARAMS ((const char *,
251 struct string_list *));
253 /* List of directories in which files should be converted. */
255 struct string_list *directory_list;
257 /* List of file names which should not be converted.
258 A file is excluded if the end of its name, following a /,
259 matches one of the names in this list. */
261 struct string_list *exclude_list;
263 /* The name of the other style of variable-number-of-parameters functions
264 (i.e. the style that we want to leave unconverted because we don't yet
265 know how to convert them to this style. This string is used in warning
266 messages. */
268 /* Also define here the string that we can search for in the parameter lists
269 taken from the .X files which will unambiguously indicate that we have
270 found a varargs style function. */
272 #ifdef UNPROTOIZE
273 static const char * const other_var_style = "stdarg";
274 #else /* !defined (UNPROTOIZE) */
275 static const char * const other_var_style = "varargs";
276 /* Note that this is a string containing the expansion of va_alist.
277 But in `main' we discard all but the first token. */
278 static const char *varargs_style_indicator = STRINGIFY (va_alist);
279 #endif /* !defined (UNPROTOIZE) */
281 /* The following two types are used to create hash tables. In this program,
282 there are two hash tables which are used to store and quickly lookup two
283 different classes of strings. The first type of strings stored in the
284 first hash table are absolute filenames of files which protoize needs to
285 know about. The second type of strings (stored in the second hash table)
286 are function names. It is this second class of strings which really
287 inspired the use of the hash tables, because there may be a lot of them. */
289 typedef struct hash_table_entry_struct hash_table_entry;
291 /* Do some typedefs so that we don't have to write "struct" so often. */
293 typedef struct def_dec_info_struct def_dec_info;
294 typedef struct file_info_struct file_info;
295 typedef struct f_list_chain_item_struct f_list_chain_item;
297 #ifndef UNPROTOIZE
298 static int is_syscalls_file PARAMS ((const file_info *));
299 static void rename_c_file PARAMS ((const hash_table_entry *));
300 static const def_dec_info *find_extern_def PARAMS ((const def_dec_info *,
301 const def_dec_info *));
302 static const def_dec_info *find_static_definition PARAMS ((const def_dec_info *));
303 static void connect_defs_and_decs PARAMS ((const hash_table_entry *));
304 static void add_local_decl PARAMS ((const def_dec_info *, const char *));
305 static void add_global_decls PARAMS ((const file_info *, const char *));
306 #endif /* ! UNPROTOIZE */
307 static int needs_to_be_converted PARAMS ((const file_info *));
308 static void visit_each_hash_node PARAMS ((const hash_table_entry *,
309 void (*)(const hash_table_entry *)));
310 static hash_table_entry *add_symbol PARAMS ((hash_table_entry *, const char *));
311 static hash_table_entry *lookup PARAMS ((hash_table_entry *, const char *));
312 static void free_def_dec PARAMS ((def_dec_info *));
313 static file_info *find_file PARAMS ((const char *, int));
314 static void reverse_def_dec_list PARAMS ((const hash_table_entry *));
315 static void edit_fn_declaration PARAMS ((const def_dec_info *, const char *));
316 static int edit_formals_lists PARAMS ((const char *, unsigned int,
317 const def_dec_info *));
318 static void edit_fn_definition PARAMS ((const def_dec_info *, const char *));
319 static void scan_for_missed_items PARAMS ((const file_info *));
320 static void edit_file PARAMS ((const hash_table_entry *));
322 /* In the struct below, note that the "_info" field has two different uses
323 depending on the type of hash table we are in (i.e. either the filenames
324 hash table or the function names hash table). In the filenames hash table
325 the info fields of the entries point to the file_info struct which is
326 associated with each filename (1 per filename). In the function names
327 hash table, the info field points to the head of a singly linked list of
328 def_dec_info entries which are all defs or decs of the function whose
329 name is pointed to by the "symbol" field. Keeping all of the defs/decs
330 for a given function name on a special list specifically for that function
331 name makes it quick and easy to find out all of the important information
332 about a given (named) function. */
334 struct hash_table_entry_struct {
335 hash_table_entry * hash_next; /* -> to secondary entries */
336 const char * symbol; /* -> to the hashed string */
337 union {
338 const def_dec_info * _ddip;
339 file_info * _fip;
340 } _info;
342 #define ddip _info._ddip
343 #define fip _info._fip
345 /* Define a type specifically for our two hash tables. */
347 typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
349 /* The following struct holds all of the important information about any
350 single filename (e.g. file) which we need to know about. */
352 struct file_info_struct {
353 const hash_table_entry * hash_entry; /* -> to associated hash entry */
354 const def_dec_info * defs_decs; /* -> to chain of defs/decs */
355 time_t mtime; /* Time of last modification. */
358 /* Due to the possibility that functions may return pointers to functions,
359 (which may themselves have their own parameter lists) and due to the
360 fact that returned pointers-to-functions may be of type "pointer-to-
361 function-returning-pointer-to-function" (ad nauseum) we have to keep
362 an entire chain of ANSI style formal parameter lists for each function.
364 Normally, for any given function, there will only be one formals list
365 on the chain, but you never know.
367 Note that the head of each chain of formals lists is pointed to by the
368 `f_list_chain' field of the corresponding def_dec_info record.
370 For any given chain, the item at the head of the chain is the *leftmost*
371 parameter list seen in the actual C language function declaration. If
372 there are other members of the chain, then these are linked in left-to-right
373 order from the head of the chain. */
375 struct f_list_chain_item_struct {
376 const f_list_chain_item * chain_next; /* -> to next item on chain */
377 const char * formals_list; /* -> to formals list string */
380 /* The following struct holds all of the important information about any
381 single function definition or declaration which we need to know about.
382 Note that for unprotoize we don't need to know very much because we
383 never even create records for stuff that we don't intend to convert
384 (like for instance defs and decs which are already in old K&R format
385 and "implicit" function declarations). */
387 struct def_dec_info_struct {
388 const def_dec_info * next_in_file; /* -> to rest of chain for file */
389 file_info * file; /* -> file_info for containing file */
390 int line; /* source line number of def/dec */
391 const char * ansi_decl; /* -> left end of ansi decl */
392 hash_table_entry * hash_entry; /* -> hash entry for function name */
393 unsigned int is_func_def; /* = 0 means this is a declaration */
394 const def_dec_info * next_for_func; /* -> to rest of chain for func name */
395 unsigned int f_list_count; /* count of formals lists we expect */
396 char prototyped; /* = 0 means already prototyped */
397 #ifndef UNPROTOIZE
398 const f_list_chain_item * f_list_chain; /* -> chain of formals lists */
399 const def_dec_info * definition; /* -> def/dec containing related def */
400 char is_static; /* = 0 means visibility is "extern" */
401 char is_implicit; /* != 0 for implicit func decl's */
402 char written; /* != 0 means written for implicit */
403 #else /* !defined (UNPROTOIZE) */
404 const char * formal_names; /* -> to list of names of formals */
405 const char * formal_decls; /* -> to string of formal declarations */
406 #endif /* !defined (UNPROTOIZE) */
409 /* Pointer to the tail component of the filename by which this program was
410 invoked. Used everywhere in error and warning messages. */
412 static const char *pname;
414 /* Error counter. Will be non-zero if we should give up at the next convenient
415 stopping point. */
417 static int errors = 0;
419 /* Option flags. */
420 /* ??? These comments should say what the flag mean as well as the options
421 that set them. */
423 /* File name to use for running gcc. Allows GCC 2 to be named
424 something other than gcc. */
425 static const char *compiler_file_name = "gcc";
427 static int version_flag = 0; /* Print our version number. */
428 static int quiet_flag = 0; /* Don't print messages normally. */
429 static int nochange_flag = 0; /* Don't convert, just say what files
430 we would have converted. */
431 static int nosave_flag = 0; /* Don't save the old version. */
432 static int keep_flag = 0; /* Don't delete the .X files. */
433 static const char ** compile_params = 0; /* Option string for gcc. */
434 #ifdef UNPROTOIZE
435 static const char *indent_string = " "; /* Indentation for newly
436 inserted parm decls. */
437 #else /* !defined (UNPROTOIZE) */
438 static int local_flag = 0; /* Insert new local decls (when?). */
439 static int global_flag = 0; /* set by -g option */
440 static int cplusplus_flag = 0; /* Rename converted files to *.C. */
441 static const char *nondefault_syscalls_dir = 0; /* Dir to look for
442 SYSCALLS.c.X in. */
443 #endif /* !defined (UNPROTOIZE) */
445 /* An index into the compile_params array where we should insert the source
446 file name when we are ready to exec the C compiler. A zero value indicates
447 that we have not yet called munge_compile_params. */
449 static int input_file_name_index = 0;
451 /* An index into the compile_params array where we should insert the filename
452 for the aux info file, when we run the C compiler. */
453 static int aux_info_file_name_index = 0;
455 /* Count of command line arguments which were "filename" arguments. */
457 static int n_base_source_files = 0;
459 /* Points to a malloc'ed list of pointers to all of the filenames of base
460 source files which were specified on the command line. */
462 static const char **base_source_filenames;
464 /* Line number of the line within the current aux_info file that we
465 are currently processing. Used for error messages in case the prototypes
466 info file is corrupted somehow. */
468 static int current_aux_info_lineno;
470 /* Pointer to the name of the source file currently being converted. */
472 static const char *convert_filename;
474 /* Pointer to relative root string (taken from aux_info file) which indicates
475 where directory the user was in when he did the compilation step that
476 produced the containing aux_info file. */
478 static const char *invocation_filename;
480 /* Pointer to the base of the input buffer that holds the original text for the
481 source file currently being converted. */
483 static const char *orig_text_base;
485 /* Pointer to the byte just beyond the end of the input buffer that holds the
486 original text for the source file currently being converted. */
488 static const char *orig_text_limit;
490 /* Pointer to the base of the input buffer that holds the cleaned text for the
491 source file currently being converted. */
493 static const char *clean_text_base;
495 /* Pointer to the byte just beyond the end of the input buffer that holds the
496 cleaned text for the source file currently being converted. */
498 static const char *clean_text_limit;
500 /* Pointer to the last byte in the cleaned text buffer that we have already
501 (virtually) copied to the output buffer (or decided to ignore). */
503 static const char * clean_read_ptr;
505 /* Pointer to the base of the output buffer that holds the replacement text
506 for the source file currently being converted. */
508 static char *repl_text_base;
510 /* Pointer to the byte just beyond the end of the output buffer that holds the
511 replacement text for the source file currently being converted. */
513 static char *repl_text_limit;
515 /* Pointer to the last byte which has been stored into the output buffer.
516 The next byte to be stored should be stored just past where this points
517 to. */
519 static char * repl_write_ptr;
521 /* Pointer into the cleaned text buffer for the source file we are currently
522 converting. This points to the first character of the line that we last
523 did a "seek_to_line" to (see below). */
525 static const char *last_known_line_start;
527 /* Number of the line (in the cleaned text buffer) that we last did a
528 "seek_to_line" to. Will be one if we just read a new source file
529 into the cleaned text buffer. */
531 static int last_known_line_number;
533 /* The filenames hash table. */
535 static hash_table filename_primary;
537 /* The function names hash table. */
539 static hash_table function_name_primary;
541 /* The place to keep the recovery address which is used only in cases where
542 we get hopelessly confused by something in the cleaned original text. */
544 static jmp_buf source_confusion_recovery;
546 /* A pointer to the current directory filename (used by abspath). */
548 static char *cwd_buffer;
550 /* A place to save the read pointer until we are sure that an individual
551 attempt at editing will succeed. */
553 static const char * saved_clean_read_ptr;
555 /* A place to save the write pointer until we are sure that an individual
556 attempt at editing will succeed. */
558 static char * saved_repl_write_ptr;
560 /* Translate and output an error message. */
561 static void
562 notice VPARAMS ((const char *msgid, ...))
564 #ifndef ANSI_PROTOTYPES
565 const char *msgid;
566 #endif
567 va_list ap;
569 VA_START (ap, msgid);
571 #ifndef ANSI_PROTOTYPES
572 msgid = va_arg (ap, const char *);
573 #endif
575 vfprintf (stderr, _(msgid), ap);
576 va_end (ap);
580 /* Make a copy of a string INPUT with size SIZE. */
582 static char *
583 savestring (input, size)
584 const char *input;
585 unsigned int size;
587 char *output = (char *) xmalloc (size + 1);
588 strcpy (output, input);
589 return output;
592 /* More 'friendly' abort that prints the line and file.
593 config.h can #define abort fancy_abort if you like that sort of thing. */
595 void
596 fancy_abort ()
598 notice ("%s: internal abort\n", pname);
599 exit (FATAL_EXIT_CODE);
602 /* Make a duplicate of the first N bytes of a given string in a newly
603 allocated area. */
605 static char *
606 dupnstr (s, n)
607 const char *s;
608 size_t n;
610 char *ret_val = (char *) xmalloc (n + 1);
612 strncpy (ret_val, s, n);
613 ret_val[n] = '\0';
614 return ret_val;
617 /* Return a pointer to the first occurrence of s2 within s1 or NULL if s2
618 does not occur within s1. Assume neither s1 nor s2 are null pointers. */
620 static const char *
621 substr (s1, s2)
622 const char *s1;
623 const char *const s2;
625 for (; *s1 ; s1++)
627 const char *p1;
628 const char *p2;
629 int c;
631 for (p1 = s1, p2 = s2; (c = *p2); p1++, p2++)
632 if (*p1 != c)
633 goto outer;
634 return s1;
635 outer:
638 return 0;
641 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
642 retrying if necessary. Return the actual number of bytes read. */
644 static int
645 safe_read (desc, ptr, len)
646 int desc;
647 PTR ptr;
648 int len;
650 int left = len;
651 while (left > 0) {
652 int nchars = read (desc, ptr, left);
653 if (nchars < 0)
655 #ifdef EINTR
656 if (errno == EINTR)
657 continue;
658 #endif
659 return nchars;
661 if (nchars == 0)
662 break;
663 /* Arithmetic on void pointers is a gcc extention. */
664 ptr = (char *) ptr + nchars;
665 left -= nchars;
667 return len - left;
670 /* Write LEN bytes at PTR to descriptor DESC,
671 retrying if necessary, and treating any real error as fatal. */
673 static void
674 safe_write (desc, ptr, len, out_fname)
675 int desc;
676 PTR ptr;
677 int len;
678 const char *out_fname;
680 while (len > 0) {
681 int written = write (desc, ptr, len);
682 if (written < 0)
684 int errno_val = errno;
685 #ifdef EINTR
686 if (errno_val == EINTR)
687 continue;
688 #endif
689 notice ("%s: error writing file `%s': %s\n",
690 pname, shortpath (NULL, out_fname), xstrerror (errno_val));
691 return;
693 /* Arithmetic on void pointers is a gcc extention. */
694 ptr = (char *) ptr + written;
695 len -= written;
699 /* Get setup to recover in case the edit we are about to do goes awry. */
701 static void
702 save_pointers ()
704 saved_clean_read_ptr = clean_read_ptr;
705 saved_repl_write_ptr = repl_write_ptr;
708 /* Call this routine to recover our previous state whenever something looks
709 too confusing in the source code we are trying to edit. */
711 static void
712 restore_pointers ()
714 clean_read_ptr = saved_clean_read_ptr;
715 repl_write_ptr = saved_repl_write_ptr;
718 /* Return true if the given character is a valid identifier character. */
720 static int
721 is_id_char (ch)
722 int ch;
724 return (ISALNUM (ch) || (ch == '_') || (ch == '$'));
727 /* Give a message indicating the proper way to invoke this program and then
728 exit with non-zero status. */
730 static void
731 usage ()
733 #ifdef UNPROTOIZE
734 notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
735 pname, pname);
736 #else /* !defined (UNPROTOIZE) */
737 notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
738 pname, pname);
739 #endif /* !defined (UNPROTOIZE) */
740 exit (FATAL_EXIT_CODE);
743 /* Return true if the given filename (assumed to be an absolute filename)
744 designates a file residing anywhere beneath any one of the "system"
745 include directories. */
747 static int
748 in_system_include_dir (path)
749 const char *path;
751 struct default_include *p;
753 if (! is_abspath (path))
754 abort (); /* Must be an absolutized filename. */
756 for (p = include_defaults; p->fname; p++)
757 if (!strncmp (path, p->fname, strlen (p->fname))
758 && IS_DIR_SEPARATOR (path[strlen (p->fname)]))
759 return 1;
760 return 0;
763 #if 0
764 /* Return true if the given filename designates a file that the user has
765 read access to and for which the user has write access to the containing
766 directory. */
768 static int
769 file_could_be_converted (const char *path)
771 char *const dir_name = (char *) alloca (strlen (path) + 1);
773 if (access (path, R_OK))
774 return 0;
777 char *dir_last_slash;
779 strcpy (dir_name, path);
780 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
781 #ifdef DIR_SEPARATOR_2
783 char *slash;
785 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
786 DIR_SEPARATOR_2);
787 if (slash)
788 dir_last_slash = slash;
790 #endif
791 if (dir_last_slash)
792 *dir_last_slash = '\0';
793 else
794 abort (); /* Should have been an absolutized filename. */
797 if (access (path, W_OK))
798 return 0;
800 return 1;
803 /* Return true if the given filename designates a file that we are allowed
804 to modify. Files which we should not attempt to modify are (a) "system"
805 include files, and (b) files which the user doesn't have write access to,
806 and (c) files which reside in directories which the user doesn't have
807 write access to. Unless requested to be quiet, give warnings about
808 files that we will not try to convert for one reason or another. An
809 exception is made for "system" include files, which we never try to
810 convert and for which we don't issue the usual warnings. */
812 static int
813 file_normally_convertible (const char *path)
815 char *const dir_name = alloca (strlen (path) + 1);
817 if (in_system_include_dir (path))
818 return 0;
821 char *dir_last_slash;
823 strcpy (dir_name, path);
824 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
825 #ifdef DIR_SEPARATOR_2
827 char *slash;
829 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
830 DIR_SEPARATOR_2);
831 if (slash)
832 dir_last_slash = slash;
834 #endif
835 if (dir_last_slash)
836 *dir_last_slash = '\0';
837 else
838 abort (); /* Should have been an absolutized filename. */
841 if (access (path, R_OK))
843 if (!quiet_flag)
844 notice ("%s: warning: no read access for file `%s'\n",
845 pname, shortpath (NULL, path));
846 return 0;
849 if (access (path, W_OK))
851 if (!quiet_flag)
852 notice ("%s: warning: no write access for file `%s'\n",
853 pname, shortpath (NULL, path));
854 return 0;
857 if (access (dir_name, W_OK))
859 if (!quiet_flag)
860 notice ("%s: warning: no write access for dir containing `%s'\n",
861 pname, shortpath (NULL, path));
862 return 0;
865 return 1;
867 #endif /* 0 */
869 #ifndef UNPROTOIZE
871 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X
872 file. Return false otherwise. */
874 static int
875 is_syscalls_file (fi_p)
876 const file_info *fi_p;
878 char const *f = fi_p->hash_entry->symbol;
879 size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
880 return sysl <= fl && strcmp (f + fl - sysl, syscalls_filename) == 0;
883 #endif /* !defined (UNPROTOIZE) */
885 /* Check to see if this file will need to have anything done to it on this
886 run. If there is nothing in the given file which both needs conversion
887 and for which we have the necessary stuff to do the conversion, return
888 false. Otherwise, return true.
890 Note that (for protoize) it is only valid to call this function *after*
891 the connections between declarations and definitions have all been made
892 by connect_defs_and_decs. */
894 static int
895 needs_to_be_converted (file_p)
896 const file_info *file_p;
898 const def_dec_info *ddp;
900 #ifndef UNPROTOIZE
902 if (is_syscalls_file (file_p))
903 return 0;
905 #endif /* !defined (UNPROTOIZE) */
907 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
909 if (
911 #ifndef UNPROTOIZE
913 /* ... and if we a protoizing and this function is in old style ... */
914 !ddp->prototyped
915 /* ... and if this a definition or is a decl with an associated def ... */
916 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
918 #else /* defined (UNPROTOIZE) */
920 /* ... and if we are unprotoizing and this function is in new style ... */
921 ddp->prototyped
923 #endif /* defined (UNPROTOIZE) */
925 /* ... then the containing file needs converting. */
926 return -1;
927 return 0;
930 /* Return 1 if the file name NAME is in a directory
931 that should be converted. */
933 static int
934 directory_specified_p (name)
935 const char *name;
937 struct string_list *p;
939 for (p = directory_list; p; p = p->next)
940 if (!strncmp (name, p->name, strlen (p->name))
941 && IS_DIR_SEPARATOR (name[strlen (p->name)]))
943 const char *q = name + strlen (p->name) + 1;
945 /* If there are more slashes, it's in a subdir, so
946 this match doesn't count. */
947 while (*q++)
948 if (IS_DIR_SEPARATOR (*(q-1)))
949 goto lose;
950 return 1;
952 lose: ;
955 return 0;
958 /* Return 1 if the file named NAME should be excluded from conversion. */
960 static int
961 file_excluded_p (name)
962 const char *name;
964 struct string_list *p;
965 int len = strlen (name);
967 for (p = exclude_list; p; p = p->next)
968 if (!strcmp (name + len - strlen (p->name), p->name)
969 && IS_DIR_SEPARATOR (name[len - strlen (p->name) - 1]))
970 return 1;
972 return 0;
975 /* Construct a new element of a string_list.
976 STRING is the new element value, and REST holds the remaining elements. */
978 static struct string_list *
979 string_list_cons (string, rest)
980 const char *string;
981 struct string_list *rest;
983 struct string_list *temp
984 = (struct string_list *) xmalloc (sizeof (struct string_list));
986 temp->next = rest;
987 temp->name = string;
988 return temp;
991 /* ??? The GNU convention for mentioning function args in its comments
992 is to capitalize them. So change "hash_tab_p" to HASH_TAB_P below.
993 Likewise for all the other functions. */
995 /* Given a hash table, apply some function to each node in the table. The
996 table to traverse is given as the "hash_tab_p" argument, and the
997 function to be applied to each node in the table is given as "func"
998 argument. */
1000 static void
1001 visit_each_hash_node (hash_tab_p, func)
1002 const hash_table_entry *hash_tab_p;
1003 void (*func) PARAMS ((const hash_table_entry *));
1005 const hash_table_entry *primary;
1007 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
1008 if (primary->symbol)
1010 hash_table_entry *second;
1012 (*func)(primary);
1013 for (second = primary->hash_next; second; second = second->hash_next)
1014 (*func) (second);
1018 /* Initialize all of the fields of a new hash table entry, pointed
1019 to by the "p" parameter. Note that the space to hold the entry
1020 is assumed to have already been allocated before this routine is
1021 called. */
1023 static hash_table_entry *
1024 add_symbol (p, s)
1025 hash_table_entry *p;
1026 const char *s;
1028 p->hash_next = NULL;
1029 p->symbol = xstrdup (s);
1030 p->ddip = NULL;
1031 p->fip = NULL;
1032 return p;
1035 /* Look for a particular function name or filename in the particular
1036 hash table indicated by "hash_tab_p". If the name is not in the
1037 given hash table, add it. Either way, return a pointer to the
1038 hash table entry for the given name. */
1040 static hash_table_entry *
1041 lookup (hash_tab_p, search_symbol)
1042 hash_table_entry *hash_tab_p;
1043 const char *search_symbol;
1045 int hash_value = 0;
1046 const char *search_symbol_char_p = search_symbol;
1047 hash_table_entry *p;
1049 while (*search_symbol_char_p)
1050 hash_value += *search_symbol_char_p++;
1051 hash_value &= hash_mask;
1052 p = &hash_tab_p[hash_value];
1053 if (! p->symbol)
1054 return add_symbol (p, search_symbol);
1055 if (!strcmp (p->symbol, search_symbol))
1056 return p;
1057 while (p->hash_next)
1059 p = p->hash_next;
1060 if (!strcmp (p->symbol, search_symbol))
1061 return p;
1063 p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry));
1064 p = p->hash_next;
1065 return add_symbol (p, search_symbol);
1068 /* Throw a def/dec record on the junk heap.
1070 Also, since we are not using this record anymore, free up all of the
1071 stuff it pointed to. */
1073 static void
1074 free_def_dec (p)
1075 def_dec_info *p;
1077 free ((NONCONST PTR) p->ansi_decl);
1079 #ifndef UNPROTOIZE
1081 const f_list_chain_item * curr;
1082 const f_list_chain_item * next;
1084 for (curr = p->f_list_chain; curr; curr = next)
1086 next = curr->chain_next;
1087 free ((NONCONST PTR) curr);
1090 #endif /* !defined (UNPROTOIZE) */
1092 free (p);
1095 /* Unexpand as many macro symbol as we can find.
1097 If the given line must be unexpanded, make a copy of it in the heap and
1098 return a pointer to the unexpanded copy. Otherwise return NULL. */
1100 static char *
1101 unexpand_if_needed (aux_info_line)
1102 const char *aux_info_line;
1104 static char *line_buf = 0;
1105 static int line_buf_size = 0;
1106 const unexpansion *unexp_p;
1107 int got_unexpanded = 0;
1108 const char *s;
1109 char *copy_p = line_buf;
1111 if (line_buf == 0)
1113 line_buf_size = 1024;
1114 line_buf = (char *) xmalloc (line_buf_size);
1117 copy_p = line_buf;
1119 /* Make a copy of the input string in line_buf, expanding as necessary. */
1121 for (s = aux_info_line; *s != '\n'; )
1123 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
1125 const char *in_p = unexp_p->expanded;
1126 size_t len = strlen (in_p);
1128 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1130 int size = strlen (unexp_p->contracted);
1131 got_unexpanded = 1;
1132 if (copy_p + size - line_buf >= line_buf_size)
1134 int offset = copy_p - line_buf;
1135 line_buf_size *= 2;
1136 line_buf_size += size;
1137 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1138 copy_p = line_buf + offset;
1140 strcpy (copy_p, unexp_p->contracted);
1141 copy_p += size;
1143 /* Assume the there will not be another replacement required
1144 within the text just replaced. */
1146 s += len;
1147 goto continue_outer;
1150 if (copy_p - line_buf == line_buf_size)
1152 int offset = copy_p - line_buf;
1153 line_buf_size *= 2;
1154 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1155 copy_p = line_buf + offset;
1157 *copy_p++ = *s++;
1158 continue_outer: ;
1160 if (copy_p + 2 - line_buf >= line_buf_size)
1162 int offset = copy_p - line_buf;
1163 line_buf_size *= 2;
1164 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1165 copy_p = line_buf + offset;
1167 *copy_p++ = '\n';
1168 *copy_p = '\0';
1170 return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
1173 /* Return 1 if pathname is absolute. */
1175 static int
1176 is_abspath (path)
1177 const char *path;
1179 return (IS_DIR_SEPARATOR (path[0])
1180 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1181 /* Check for disk name on MS-DOS-based systems. */
1182 || (path[0] && path[1] == ':' && IS_DIR_SEPARATOR (path[2]))
1183 #endif
1187 /* Return the absolutized filename for the given relative
1188 filename. Note that if that filename is already absolute, it may
1189 still be returned in a modified form because this routine also
1190 eliminates redundant slashes and single dots and eliminates double
1191 dots to get a shortest possible filename from the given input
1192 filename. The absolutization of relative filenames is made by
1193 assuming that the given filename is to be taken as relative to
1194 the first argument (cwd) or to the current directory if cwd is
1195 NULL. */
1197 static char *
1198 abspath (cwd, rel_filename)
1199 const char *cwd;
1200 const char *rel_filename;
1202 /* Setup the current working directory as needed. */
1203 const char *cwd2 = (cwd) ? cwd : cwd_buffer;
1204 char *const abs_buffer
1205 = (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 2);
1206 char *endp = abs_buffer;
1207 char *outp, *inp;
1209 /* Copy the filename (possibly preceded by the current working
1210 directory name) into the absolutization buffer. */
1213 const char *src_p;
1215 if (! is_abspath (rel_filename))
1217 src_p = cwd2;
1218 while ((*endp++ = *src_p++))
1219 continue;
1220 *(endp-1) = DIR_SEPARATOR; /* overwrite null */
1222 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1223 else if (IS_DIR_SEPARATOR (rel_filename[0]))
1225 /* A path starting with a directory separator is considered absolute
1226 for dos based filesystems, but it's really not -- it's just the
1227 convention used throughout GCC and it works. However, in this
1228 case, we still need to prepend the drive spec from cwd_buffer. */
1229 *endp++ = cwd2[0];
1230 *endp++ = cwd2[1];
1232 #endif
1233 src_p = rel_filename;
1234 while ((*endp++ = *src_p++))
1235 continue;
1238 /* Now make a copy of abs_buffer into abs_buffer, shortening the
1239 filename (by taking out slashes and dots) as we go. */
1241 outp = inp = abs_buffer;
1242 *outp++ = *inp++; /* copy first slash */
1243 #if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
1244 if (IS_DIR_SEPARATOR (inp[0]))
1245 *outp++ = *inp++; /* copy second slash */
1246 #endif
1247 for (;;)
1249 if (!inp[0])
1250 break;
1251 else if (IS_DIR_SEPARATOR (inp[0]) && IS_DIR_SEPARATOR (outp[-1]))
1253 inp++;
1254 continue;
1256 else if (inp[0] == '.' && IS_DIR_SEPARATOR (outp[-1]))
1258 if (!inp[1])
1259 break;
1260 else if (IS_DIR_SEPARATOR (inp[1]))
1262 inp += 2;
1263 continue;
1265 else if ((inp[1] == '.') && (inp[2] == 0
1266 || IS_DIR_SEPARATOR (inp[2])))
1268 inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2;
1269 outp -= 2;
1270 while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*outp))
1271 outp--;
1272 if (outp < abs_buffer)
1274 /* Catch cases like /.. where we try to backup to a
1275 point above the absolute root of the logical file
1276 system. */
1278 notice ("%s: invalid file name: %s\n",
1279 pname, rel_filename);
1280 exit (FATAL_EXIT_CODE);
1282 *++outp = '\0';
1283 continue;
1286 *outp++ = *inp++;
1289 /* On exit, make sure that there is a trailing null, and make sure that
1290 the last character of the returned string is *not* a slash. */
1292 *outp = '\0';
1293 if (IS_DIR_SEPARATOR (outp[-1]))
1294 *--outp = '\0';
1296 /* Make a copy (in the heap) of the stuff left in the absolutization
1297 buffer and return a pointer to the copy. */
1299 return savestring (abs_buffer, outp - abs_buffer);
1302 /* Given a filename (and possibly a directory name from which the filename
1303 is relative) return a string which is the shortest possible
1304 equivalent for the corresponding full (absolutized) filename. The
1305 shortest possible equivalent may be constructed by converting the
1306 absolutized filename to be a relative filename (i.e. relative to
1307 the actual current working directory). However if a relative filename
1308 is longer, then the full absolute filename is returned.
1310 KNOWN BUG:
1312 Note that "simple-minded" conversion of any given type of filename (either
1313 relative or absolute) may not result in a valid equivalent filename if any
1314 subpart of the original filename is actually a symbolic link. */
1316 static const char *
1317 shortpath (cwd, filename)
1318 const char *cwd;
1319 const char *filename;
1321 char *rel_buffer;
1322 char *rel_buf_p;
1323 char *cwd_p = cwd_buffer;
1324 char *path_p;
1325 int unmatched_slash_count = 0;
1326 size_t filename_len = strlen (filename);
1328 path_p = abspath (cwd, filename);
1329 rel_buf_p = rel_buffer = (char *) xmalloc (filename_len);
1331 while (*cwd_p && IS_SAME_PATH_CHAR (*cwd_p, *path_p))
1333 cwd_p++;
1334 path_p++;
1336 if (!*cwd_p && (!*path_p || IS_DIR_SEPARATOR (*path_p)))
1338 /* whole pwd matched */
1339 if (!*path_p) /* input *is* the current path! */
1340 return ".";
1341 else
1342 return ++path_p;
1344 else
1346 if (*path_p)
1348 --cwd_p;
1349 --path_p;
1350 while (! IS_DIR_SEPARATOR (*cwd_p)) /* backup to last slash */
1352 --cwd_p;
1353 --path_p;
1355 cwd_p++;
1356 path_p++;
1357 unmatched_slash_count++;
1360 /* Find out how many directory levels in cwd were *not* matched. */
1361 while (*cwd_p++)
1362 if (IS_DIR_SEPARATOR (*(cwd_p-1)))
1363 unmatched_slash_count++;
1365 /* Now we know how long the "short name" will be.
1366 Reject it if longer than the input. */
1367 if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
1368 return filename;
1370 /* For each of them, put a `../' at the beginning of the short name. */
1371 while (unmatched_slash_count--)
1373 /* Give up if the result gets to be longer
1374 than the absolute path name. */
1375 if (rel_buffer + filename_len <= rel_buf_p + 3)
1376 return filename;
1377 *rel_buf_p++ = '.';
1378 *rel_buf_p++ = '.';
1379 *rel_buf_p++ = DIR_SEPARATOR;
1382 /* Then tack on the unmatched part of the desired file's name. */
1385 if (rel_buffer + filename_len <= rel_buf_p)
1386 return filename;
1388 while ((*rel_buf_p++ = *path_p++));
1390 --rel_buf_p;
1391 if (IS_DIR_SEPARATOR (*(rel_buf_p-1)))
1392 *--rel_buf_p = '\0';
1393 return rel_buffer;
1397 /* Lookup the given filename in the hash table for filenames. If it is a
1398 new one, then the hash table info pointer will be null. In this case,
1399 we create a new file_info record to go with the filename, and we initialize
1400 that record with some reasonable values. */
1402 /* FILENAME was const, but that causes a warning on AIX when calling stat.
1403 That is probably a bug in AIX, but might as well avoid the warning. */
1405 static file_info *
1406 find_file (filename, do_not_stat)
1407 const char *filename;
1408 int do_not_stat;
1410 hash_table_entry *hash_entry_p;
1412 hash_entry_p = lookup (filename_primary, filename);
1413 if (hash_entry_p->fip)
1414 return hash_entry_p->fip;
1415 else
1417 struct stat stat_buf;
1418 file_info *file_p = (file_info *) xmalloc (sizeof (file_info));
1420 /* If we cannot get status on any given source file, give a warning
1421 and then just set its time of last modification to infinity. */
1423 if (do_not_stat)
1424 stat_buf.st_mtime = (time_t) 0;
1425 else
1427 if (stat (filename, &stat_buf) == -1)
1429 int errno_val = errno;
1430 notice ("%s: %s: can't get status: %s\n",
1431 pname, shortpath (NULL, filename),
1432 xstrerror (errno_val));
1433 stat_buf.st_mtime = (time_t) -1;
1437 hash_entry_p->fip = file_p;
1438 file_p->hash_entry = hash_entry_p;
1439 file_p->defs_decs = NULL;
1440 file_p->mtime = stat_buf.st_mtime;
1441 return file_p;
1445 /* Generate a fatal error because some part of the aux_info file is
1446 messed up. */
1448 static void
1449 aux_info_corrupted ()
1451 notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
1452 pname, current_aux_info_lineno);
1453 exit (FATAL_EXIT_CODE);
1456 /* ??? This comment is vague. Say what the condition is for. */
1457 /* Check to see that a condition is true. This is kind of like an assert. */
1459 static void
1460 check_aux_info (cond)
1461 int cond;
1463 if (! cond)
1464 aux_info_corrupted ();
1467 /* Given a pointer to the closing right parenthesis for a particular formals
1468 list (in an aux_info file) find the corresponding left parenthesis and
1469 return a pointer to it. */
1471 static const char *
1472 find_corresponding_lparen (p)
1473 const char *p;
1475 const char *q;
1476 int paren_depth;
1478 for (paren_depth = 1, q = p-1; paren_depth; q--)
1480 switch (*q)
1482 case ')':
1483 paren_depth++;
1484 break;
1485 case '(':
1486 paren_depth--;
1487 break;
1490 return ++q;
1493 /* Given a line from an aux info file, and a time at which the aux info
1494 file it came from was created, check to see if the item described in
1495 the line comes from a file which has been modified since the aux info
1496 file was created. If so, return non-zero, else return zero. */
1498 static int
1499 referenced_file_is_newer (l, aux_info_mtime)
1500 const char *l;
1501 time_t aux_info_mtime;
1503 const char *p;
1504 file_info *fi_p;
1505 char *filename;
1507 check_aux_info (l[0] == '/');
1508 check_aux_info (l[1] == '*');
1509 check_aux_info (l[2] == ' ');
1512 const char *filename_start = p = l + 3;
1514 while (*p != ':'
1515 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1516 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1517 #endif
1519 p++;
1520 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1521 strncpy (filename, filename_start, (size_t) (p - filename_start));
1522 filename[p-filename_start] = '\0';
1525 /* Call find_file to find the file_info record associated with the file
1526 which contained this particular def or dec item. Note that this call
1527 may cause a new file_info record to be created if this is the first time
1528 that we have ever known about this particular file. */
1530 fi_p = find_file (abspath (invocation_filename, filename), 0);
1532 return (fi_p->mtime > aux_info_mtime);
1535 /* Given a line of info from the aux_info file, create a new
1536 def_dec_info record to remember all of the important information about
1537 a function definition or declaration.
1539 Link this record onto the list of such records for the particular file in
1540 which it occurred in proper (descending) line number order (for now).
1542 If there is an identical record already on the list for the file, throw
1543 this one away. Doing so takes care of the (useless and troublesome)
1544 duplicates which are bound to crop up due to multiple inclusions of any
1545 given individual header file.
1547 Finally, link the new def_dec record onto the list of such records
1548 pertaining to this particular function name. */
1550 static void
1551 save_def_or_dec (l, is_syscalls)
1552 const char *l;
1553 int is_syscalls;
1555 const char *p;
1556 const char *semicolon_p;
1557 def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info));
1559 #ifndef UNPROTOIZE
1560 def_dec_p->written = 0;
1561 #endif /* !defined (UNPROTOIZE) */
1563 /* Start processing the line by picking off 5 pieces of information from
1564 the left hand end of the line. These are filename, line number,
1565 new/old/implicit flag (new = ANSI prototype format), definition or
1566 declaration flag, and extern/static flag). */
1568 check_aux_info (l[0] == '/');
1569 check_aux_info (l[1] == '*');
1570 check_aux_info (l[2] == ' ');
1573 const char *filename_start = p = l + 3;
1574 char *filename;
1576 while (*p != ':'
1577 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1578 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1579 #endif
1581 p++;
1582 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1583 strncpy (filename, filename_start, (size_t) (p - filename_start));
1584 filename[p-filename_start] = '\0';
1586 /* Call find_file to find the file_info record associated with the file
1587 which contained this particular def or dec item. Note that this call
1588 may cause a new file_info record to be created if this is the first time
1589 that we have ever known about this particular file.
1591 Note that we started out by forcing all of the base source file names
1592 (i.e. the names of the aux_info files with the .X stripped off) into the
1593 filenames hash table, and we simultaneously setup file_info records for
1594 all of these base file names (even if they may be useless later).
1595 The file_info records for all of these "base" file names (properly)
1596 act as file_info records for the "original" (i.e. un-included) files
1597 which were submitted to gcc for compilation (when the -aux-info
1598 option was used). */
1600 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1604 const char *line_number_start = ++p;
1605 char line_number[10];
1607 while (*p != ':'
1608 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1609 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1610 #endif
1612 p++;
1613 strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1614 line_number[p-line_number_start] = '\0';
1615 def_dec_p->line = atoi (line_number);
1618 /* Check that this record describes a new-style, old-style, or implicit
1619 definition or declaration. */
1621 p++; /* Skip over the `:'. */
1622 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1624 /* Is this a new style (ANSI prototyped) definition or declaration? */
1626 def_dec_p->prototyped = (*p == 'N');
1628 #ifndef UNPROTOIZE
1630 /* Is this an implicit declaration? */
1632 def_dec_p->is_implicit = (*p == 'I');
1634 #endif /* !defined (UNPROTOIZE) */
1636 p++;
1638 check_aux_info ((*p == 'C') || (*p == 'F'));
1640 /* Is this item a function definition (F) or a declaration (C). Note that
1641 we treat item taken from the syscalls file as though they were function
1642 definitions regardless of what the stuff in the file says. */
1644 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1646 #ifndef UNPROTOIZE
1647 def_dec_p->definition = 0; /* Fill this in later if protoizing. */
1648 #endif /* !defined (UNPROTOIZE) */
1650 check_aux_info (*p++ == ' ');
1651 check_aux_info (*p++ == '*');
1652 check_aux_info (*p++ == '/');
1653 check_aux_info (*p++ == ' ');
1655 #ifdef UNPROTOIZE
1656 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1657 #else /* !defined (UNPROTOIZE) */
1658 if (!strncmp (p, "static", 6))
1659 def_dec_p->is_static = -1;
1660 else if (!strncmp (p, "extern", 6))
1661 def_dec_p->is_static = 0;
1662 else
1663 check_aux_info (0); /* Didn't find either `extern' or `static'. */
1664 #endif /* !defined (UNPROTOIZE) */
1667 const char *ansi_start = p;
1669 p += 6; /* Pass over the "static" or "extern". */
1671 /* We are now past the initial stuff. Search forward from here to find
1672 the terminating semicolon that should immediately follow the entire
1673 ANSI format function declaration. */
1675 while (*++p != ';')
1676 continue;
1678 semicolon_p = p;
1680 /* Make a copy of the ansi declaration part of the line from the aux_info
1681 file. */
1683 def_dec_p->ansi_decl
1684 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1686 /* Backup and point at the final right paren of the final argument list. */
1688 p--;
1690 #ifndef UNPROTOIZE
1691 def_dec_p->f_list_chain = NULL;
1692 #endif /* !defined (UNPROTOIZE) */
1694 while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
1695 if (*p != ')')
1697 free_def_dec (def_dec_p);
1698 return;
1702 /* Now isolate a whole set of formal argument lists, one-by-one. Normally,
1703 there will only be one list to isolate, but there could be more. */
1705 def_dec_p->f_list_count = 0;
1707 for (;;)
1709 const char *left_paren_p = find_corresponding_lparen (p);
1710 #ifndef UNPROTOIZE
1712 f_list_chain_item *cip
1713 = (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
1715 cip->formals_list
1716 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1718 /* Add the new chain item at the head of the current list. */
1720 cip->chain_next = def_dec_p->f_list_chain;
1721 def_dec_p->f_list_chain = cip;
1723 #endif /* !defined (UNPROTOIZE) */
1724 def_dec_p->f_list_count++;
1726 p = left_paren_p - 2;
1728 /* p must now point either to another right paren, or to the last
1729 character of the name of the function that was declared/defined.
1730 If p points to another right paren, then this indicates that we
1731 are dealing with multiple formals lists. In that case, there
1732 really should be another right paren preceding this right paren. */
1734 if (*p != ')')
1735 break;
1736 else
1737 check_aux_info (*--p == ')');
1742 const char *past_fn = p + 1;
1744 check_aux_info (*past_fn == ' ');
1746 /* Scan leftwards over the identifier that names the function. */
1748 while (is_id_char (*p))
1749 p--;
1750 p++;
1752 /* p now points to the leftmost character of the function name. */
1755 char *fn_string = (char *) alloca (past_fn - p + 1);
1757 strncpy (fn_string, p, (size_t) (past_fn - p));
1758 fn_string[past_fn-p] = '\0';
1759 def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1763 /* Look at all of the defs and decs for this function name that we have
1764 collected so far. If there is already one which is at the same
1765 line number in the same file, then we can discard this new def_dec_info
1766 record.
1768 As an extra assurance that any such pair of (nominally) identical
1769 function declarations are in fact identical, we also compare the
1770 ansi_decl parts of the lines from the aux_info files just to be on
1771 the safe side.
1773 This comparison will fail if (for instance) the user was playing
1774 messy games with the preprocessor which ultimately causes one
1775 function declaration in one header file to look differently when
1776 that file is included by two (or more) other files. */
1779 const def_dec_info *other;
1781 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1783 if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1785 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1787 notice ("%s:%d: declaration of function `%s' takes different forms\n",
1788 def_dec_p->file->hash_entry->symbol,
1789 def_dec_p->line,
1790 def_dec_p->hash_entry->symbol);
1791 exit (FATAL_EXIT_CODE);
1793 free_def_dec (def_dec_p);
1794 return;
1799 #ifdef UNPROTOIZE
1801 /* If we are doing unprotoizing, we must now setup the pointers that will
1802 point to the K&R name list and to the K&R argument declarations list.
1804 Note that if this is only a function declaration, then we should not
1805 expect to find any K&R style formals list following the ANSI-style
1806 formals list. This is because GCC knows that such information is
1807 useless in the case of function declarations (function definitions
1808 are a different story however).
1810 Since we are unprotoizing, we don't need any such lists anyway.
1811 All we plan to do is to delete all characters between ()'s in any
1812 case. */
1814 def_dec_p->formal_names = NULL;
1815 def_dec_p->formal_decls = NULL;
1817 if (def_dec_p->is_func_def)
1819 p = semicolon_p;
1820 check_aux_info (*++p == ' ');
1821 check_aux_info (*++p == '/');
1822 check_aux_info (*++p == '*');
1823 check_aux_info (*++p == ' ');
1824 check_aux_info (*++p == '(');
1827 const char *kr_names_start = ++p; /* Point just inside '('. */
1829 while (*p++ != ')')
1830 continue;
1831 p--; /* point to closing right paren */
1833 /* Make a copy of the K&R parameter names list. */
1835 def_dec_p->formal_names
1836 = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1839 check_aux_info (*++p == ' ');
1840 p++;
1842 /* p now points to the first character of the K&R style declarations
1843 list (if there is one) or to the star-slash combination that ends
1844 the comment in which such lists get embedded. */
1846 /* Make a copy of the K&R formal decls list and set the def_dec record
1847 to point to it. */
1849 if (*p == '*') /* Are there no K&R declarations? */
1851 check_aux_info (*++p == '/');
1852 def_dec_p->formal_decls = "";
1854 else
1856 const char *kr_decls_start = p;
1858 while (p[0] != '*' || p[1] != '/')
1859 p++;
1860 p--;
1862 check_aux_info (*p == ' ');
1864 def_dec_p->formal_decls
1865 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1868 /* Handle a special case. If we have a function definition marked as
1869 being in "old" style, and if its formal names list is empty, then
1870 it may actually have the string "void" in its real formals list
1871 in the original source code. Just to make sure, we will get setup
1872 to convert such things anyway.
1874 This kludge only needs to be here because of an insurmountable
1875 problem with generating .X files. */
1877 if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1878 def_dec_p->prototyped = 1;
1881 /* Since we are unprotoizing, if this item is already in old (K&R) style,
1882 we can just ignore it. If that is true, throw away the itme now. */
1884 if (!def_dec_p->prototyped)
1886 free_def_dec (def_dec_p);
1887 return;
1890 #endif /* defined (UNPROTOIZE) */
1892 /* Add this record to the head of the list of records pertaining to this
1893 particular function name. */
1895 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1896 def_dec_p->hash_entry->ddip = def_dec_p;
1898 /* Add this new def_dec_info record to the sorted list of def_dec_info
1899 records for this file. Note that we don't have to worry about duplicates
1900 (caused by multiple inclusions of header files) here because we have
1901 already eliminated duplicates above. */
1903 if (!def_dec_p->file->defs_decs)
1905 def_dec_p->file->defs_decs = def_dec_p;
1906 def_dec_p->next_in_file = NULL;
1908 else
1910 int line = def_dec_p->line;
1911 const def_dec_info *prev = NULL;
1912 const def_dec_info *curr = def_dec_p->file->defs_decs;
1913 const def_dec_info *next = curr->next_in_file;
1915 while (next && (line < curr->line))
1917 prev = curr;
1918 curr = next;
1919 next = next->next_in_file;
1921 if (line >= curr->line)
1923 def_dec_p->next_in_file = curr;
1924 if (prev)
1925 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1926 else
1927 def_dec_p->file->defs_decs = def_dec_p;
1929 else /* assert (next == NULL); */
1931 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
1932 /* assert (next == NULL); */
1933 def_dec_p->next_in_file = next;
1938 /* Set up the vector COMPILE_PARAMS which is the argument list for running GCC.
1939 Also set input_file_name_index and aux_info_file_name_index
1940 to the indices of the slots where the file names should go. */
1942 /* We initialize the vector by removing -g, -O, -S, -c, and -o options,
1943 and adding '-aux-info AUXFILE -S -o /dev/null INFILE' at the end. */
1945 static void
1946 munge_compile_params (params_list)
1947 const char *params_list;
1949 /* Build up the contents in a temporary vector
1950 that is so big that to has to be big enough. */
1951 const char **temp_params
1952 = (const char **) alloca ((strlen (params_list) + 8) * sizeof (char *));
1953 int param_count = 0;
1954 const char *param;
1956 temp_params[param_count++] = compiler_file_name;
1957 for (;;)
1959 while (ISSPACE ((const unsigned char)*params_list))
1960 params_list++;
1961 if (!*params_list)
1962 break;
1963 param = params_list;
1964 while (*params_list && !ISSPACE ((const unsigned char)*params_list))
1965 params_list++;
1966 if (param[0] != '-')
1967 temp_params[param_count++]
1968 = dupnstr (param, (size_t) (params_list - param));
1969 else
1971 switch (param[1])
1973 case 'g':
1974 case 'O':
1975 case 'S':
1976 case 'c':
1977 break; /* Don't copy these. */
1978 case 'o':
1979 while (ISSPACE ((const unsigned char)*params_list))
1980 params_list++;
1981 while (*params_list
1982 && !ISSPACE ((const unsigned char)*params_list))
1983 params_list++;
1984 break;
1985 default:
1986 temp_params[param_count++]
1987 = dupnstr (param, (size_t) (params_list - param));
1990 if (!*params_list)
1991 break;
1993 temp_params[param_count++] = "-aux-info";
1995 /* Leave room for the aux-info file name argument. */
1996 aux_info_file_name_index = param_count;
1997 temp_params[param_count++] = NULL;
1999 temp_params[param_count++] = "-S";
2000 temp_params[param_count++] = "-o";
2001 #if defined (_WIN32) && ! defined (__CYGWIN__) && ! defined (_UWIN)
2002 temp_params[param_count++] = "NUL";
2003 #else
2004 temp_params[param_count++] = "/dev/null";
2005 #endif
2007 /* Leave room for the input file name argument. */
2008 input_file_name_index = param_count;
2009 temp_params[param_count++] = NULL;
2010 /* Terminate the list. */
2011 temp_params[param_count++] = NULL;
2013 /* Make a copy of the compile_params in heap space. */
2015 compile_params
2016 = (const char **) xmalloc (sizeof (char *) * (param_count+1));
2017 memcpy (compile_params, temp_params, sizeof (char *) * param_count);
2020 /* Do a recompilation for the express purpose of generating a new aux_info
2021 file to go with a specific base source file.
2023 The result is a boolean indicating success. */
2025 static int
2026 gen_aux_info_file (base_filename)
2027 const char *base_filename;
2029 if (!input_file_name_index)
2030 munge_compile_params ("");
2032 /* Store the full source file name in the argument vector. */
2033 compile_params[input_file_name_index] = shortpath (NULL, base_filename);
2034 /* Add .X to source file name to get aux-info file name. */
2035 compile_params[aux_info_file_name_index] =
2036 concat (compile_params[input_file_name_index], aux_info_suffix, NULL);
2038 if (!quiet_flag)
2039 notice ("%s: compiling `%s'\n",
2040 pname, compile_params[input_file_name_index]);
2043 char *errmsg_fmt, *errmsg_arg;
2044 int wait_status, pid;
2046 pid = pexecute (compile_params[0], (char * const *) compile_params,
2047 pname, NULL, &errmsg_fmt, &errmsg_arg,
2048 PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
2050 if (pid == -1)
2052 int errno_val = errno;
2053 fprintf (stderr, "%s: ", pname);
2054 fprintf (stderr, errmsg_fmt, errmsg_arg);
2055 fprintf (stderr, ": %s\n", xstrerror (errno_val));
2056 return 0;
2059 pid = pwait (pid, &wait_status, 0);
2060 if (pid == -1)
2062 notice ("%s: wait: %s\n", pname, xstrerror (errno));
2063 return 0;
2065 if (WIFSIGNALED (wait_status))
2067 notice ("%s: subprocess got fatal signal %d\n",
2068 pname, WTERMSIG (wait_status));
2069 return 0;
2071 if (WIFEXITED (wait_status))
2073 if (WEXITSTATUS (wait_status) != 0)
2075 notice ("%s: %s exited with status %d\n",
2076 pname, compile_params[0], WEXITSTATUS (wait_status));
2077 return 0;
2079 return 1;
2081 abort ();
2085 /* Read in all of the information contained in a single aux_info file.
2086 Save all of the important stuff for later. */
2088 static void
2089 process_aux_info_file (base_source_filename, keep_it, is_syscalls)
2090 const char *base_source_filename;
2091 int keep_it;
2092 int is_syscalls;
2094 size_t base_len = strlen (base_source_filename);
2095 char * aux_info_filename
2096 = (char *) alloca (base_len + strlen (aux_info_suffix) + 1);
2097 char *aux_info_base;
2098 char *aux_info_limit;
2099 char *aux_info_relocated_name;
2100 const char *aux_info_second_line;
2101 time_t aux_info_mtime;
2102 size_t aux_info_size;
2103 int must_create;
2105 /* Construct the aux_info filename from the base source filename. */
2107 strcpy (aux_info_filename, base_source_filename);
2108 strcat (aux_info_filename, aux_info_suffix);
2110 /* Check that the aux_info file exists and is readable. If it does not
2111 exist, try to create it (once only). */
2113 /* If file doesn't exist, set must_create.
2114 Likewise if it exists and we can read it but it is obsolete.
2115 Otherwise, report an error. */
2116 must_create = 0;
2118 /* Come here with must_create set to 1 if file is out of date. */
2119 start_over: ;
2121 if (access (aux_info_filename, R_OK) == -1)
2123 if (errno == ENOENT)
2125 if (is_syscalls)
2127 notice ("%s: warning: missing SYSCALLS file `%s'\n",
2128 pname, aux_info_filename);
2129 return;
2131 must_create = 1;
2133 else
2135 int errno_val = errno;
2136 notice ("%s: can't read aux info file `%s': %s\n",
2137 pname, shortpath (NULL, aux_info_filename),
2138 xstrerror (errno_val));
2139 errors++;
2140 return;
2143 #if 0 /* There is code farther down to take care of this. */
2144 else
2146 struct stat s1, s2;
2147 stat (aux_info_file_name, &s1);
2148 stat (base_source_file_name, &s2);
2149 if (s2.st_mtime > s1.st_mtime)
2150 must_create = 1;
2152 #endif /* 0 */
2154 /* If we need a .X file, create it, and verify we can read it. */
2155 if (must_create)
2157 if (!gen_aux_info_file (base_source_filename))
2159 errors++;
2160 return;
2162 if (access (aux_info_filename, R_OK) == -1)
2164 int errno_val = errno;
2165 notice ("%s: can't read aux info file `%s': %s\n",
2166 pname, shortpath (NULL, aux_info_filename),
2167 xstrerror (errno_val));
2168 errors++;
2169 return;
2174 struct stat stat_buf;
2176 /* Get some status information about this aux_info file. */
2178 if (stat (aux_info_filename, &stat_buf) == -1)
2180 int errno_val = errno;
2181 notice ("%s: can't get status of aux info file `%s': %s\n",
2182 pname, shortpath (NULL, aux_info_filename),
2183 xstrerror (errno_val));
2184 errors++;
2185 return;
2188 /* Check on whether or not this aux_info file is zero length. If it is,
2189 then just ignore it and return. */
2191 if ((aux_info_size = stat_buf.st_size) == 0)
2192 return;
2194 /* Get the date/time of last modification for this aux_info file and
2195 remember it. We will have to check that any source files that it
2196 contains information about are at least this old or older. */
2198 aux_info_mtime = stat_buf.st_mtime;
2200 if (!is_syscalls)
2202 /* Compare mod time with the .c file; update .X file if obsolete.
2203 The code later on can fail to check the .c file
2204 if it did not directly define any functions. */
2206 if (stat (base_source_filename, &stat_buf) == -1)
2208 int errno_val = errno;
2209 notice ("%s: can't get status of aux info file `%s': %s\n",
2210 pname, shortpath (NULL, base_source_filename),
2211 xstrerror (errno_val));
2212 errors++;
2213 return;
2215 if (stat_buf.st_mtime > aux_info_mtime)
2217 must_create = 1;
2218 goto start_over;
2224 int aux_info_file;
2225 int fd_flags;
2227 /* Open the aux_info file. */
2229 fd_flags = O_RDONLY;
2230 #ifdef O_BINARY
2231 /* Use binary mode to avoid having to deal with different EOL characters. */
2232 fd_flags |= O_BINARY;
2233 #endif
2234 if ((aux_info_file = open (aux_info_filename, fd_flags, 0444 )) == -1)
2236 int errno_val = errno;
2237 notice ("%s: can't open aux info file `%s' for reading: %s\n",
2238 pname, shortpath (NULL, aux_info_filename),
2239 xstrerror (errno_val));
2240 return;
2243 /* Allocate space to hold the aux_info file in memory. */
2245 aux_info_base = xmalloc (aux_info_size + 1);
2246 aux_info_limit = aux_info_base + aux_info_size;
2247 *aux_info_limit = '\0';
2249 /* Read the aux_info file into memory. */
2251 if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
2252 (int) aux_info_size)
2254 int errno_val = errno;
2255 notice ("%s: error reading aux info file `%s': %s\n",
2256 pname, shortpath (NULL, aux_info_filename),
2257 xstrerror (errno_val));
2258 free (aux_info_base);
2259 close (aux_info_file);
2260 return;
2263 /* Close the aux info file. */
2265 if (close (aux_info_file))
2267 int errno_val = errno;
2268 notice ("%s: error closing aux info file `%s': %s\n",
2269 pname, shortpath (NULL, aux_info_filename),
2270 xstrerror (errno_val));
2271 free (aux_info_base);
2272 close (aux_info_file);
2273 return;
2277 /* Delete the aux_info file (unless requested not to). If the deletion
2278 fails for some reason, don't even worry about it. */
2280 if (must_create && !keep_it)
2281 if (unlink (aux_info_filename) == -1)
2283 int errno_val = errno;
2284 notice ("%s: can't delete aux info file `%s': %s\n",
2285 pname, shortpath (NULL, aux_info_filename),
2286 xstrerror (errno_val));
2289 /* Save a pointer into the first line of the aux_info file which
2290 contains the filename of the directory from which the compiler
2291 was invoked when the associated source file was compiled.
2292 This information is used later to help create complete
2293 filenames out of the (potentially) relative filenames in
2294 the aux_info file. */
2297 char *p = aux_info_base;
2299 while (*p != ':'
2300 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
2301 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
2302 #endif
2304 p++;
2305 p++;
2306 while (*p == ' ')
2307 p++;
2308 invocation_filename = p; /* Save a pointer to first byte of path. */
2309 while (*p != ' ')
2310 p++;
2311 *p++ = DIR_SEPARATOR;
2312 *p++ = '\0';
2313 while (*p++ != '\n')
2314 continue;
2315 aux_info_second_line = p;
2316 aux_info_relocated_name = 0;
2317 if (! is_abspath (invocation_filename))
2319 /* INVOCATION_FILENAME is relative;
2320 append it to BASE_SOURCE_FILENAME's dir. */
2321 char *dir_end;
2322 aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
2323 strcpy (aux_info_relocated_name, base_source_filename);
2324 dir_end = strrchr (aux_info_relocated_name, DIR_SEPARATOR);
2325 #ifdef DIR_SEPARATOR_2
2327 char *slash;
2329 slash = strrchr (dir_end ? dir_end : aux_info_relocated_name,
2330 DIR_SEPARATOR_2);
2331 if (slash)
2332 dir_end = slash;
2334 #endif
2335 if (dir_end)
2336 dir_end++;
2337 else
2338 dir_end = aux_info_relocated_name;
2339 strcpy (dir_end, invocation_filename);
2340 invocation_filename = aux_info_relocated_name;
2346 const char *aux_info_p;
2348 /* Do a pre-pass on the lines in the aux_info file, making sure that all
2349 of the source files referenced in there are at least as old as this
2350 aux_info file itself. If not, go back and regenerate the aux_info
2351 file anew. Don't do any of this for the syscalls file. */
2353 if (!is_syscalls)
2355 current_aux_info_lineno = 2;
2357 for (aux_info_p = aux_info_second_line; *aux_info_p; )
2359 if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2361 free (aux_info_base);
2362 free (aux_info_relocated_name);
2363 if (keep_it && unlink (aux_info_filename) == -1)
2365 int errno_val = errno;
2366 notice ("%s: can't delete file `%s': %s\n",
2367 pname, shortpath (NULL, aux_info_filename),
2368 xstrerror (errno_val));
2369 return;
2371 must_create = 1;
2372 goto start_over;
2375 /* Skip over the rest of this line to start of next line. */
2377 while (*aux_info_p != '\n')
2378 aux_info_p++;
2379 aux_info_p++;
2380 current_aux_info_lineno++;
2384 /* Now do the real pass on the aux_info lines. Save their information in
2385 the in-core data base. */
2387 current_aux_info_lineno = 2;
2389 for (aux_info_p = aux_info_second_line; *aux_info_p;)
2391 char *unexpanded_line = unexpand_if_needed (aux_info_p);
2393 if (unexpanded_line)
2395 save_def_or_dec (unexpanded_line, is_syscalls);
2396 free (unexpanded_line);
2398 else
2399 save_def_or_dec (aux_info_p, is_syscalls);
2401 /* Skip over the rest of this line and get to start of next line. */
2403 while (*aux_info_p != '\n')
2404 aux_info_p++;
2405 aux_info_p++;
2406 current_aux_info_lineno++;
2410 free (aux_info_base);
2411 free (aux_info_relocated_name);
2414 #ifndef UNPROTOIZE
2416 /* Check an individual filename for a .c suffix. If the filename has this
2417 suffix, rename the file such that its suffix is changed to .C. This
2418 function implements the -C option. */
2420 static void
2421 rename_c_file (hp)
2422 const hash_table_entry *hp;
2424 const char *filename = hp->symbol;
2425 int last_char_index = strlen (filename) - 1;
2426 char *const new_filename = (char *) alloca (strlen (filename)
2427 + strlen (cplus_suffix) + 1);
2429 /* Note that we don't care here if the given file was converted or not. It
2430 is possible that the given file was *not* converted, simply because there
2431 was nothing in it which actually required conversion. Even in this case,
2432 we want to do the renaming. Note that we only rename files with the .c
2433 suffix (except for the syscalls file, which is left alone). */
2435 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.'
2436 || IS_SAME_PATH (syscalls_absolute_filename, filename))
2437 return;
2439 strcpy (new_filename, filename);
2440 strcpy (&new_filename[last_char_index], cplus_suffix);
2442 if (rename (filename, new_filename) == -1)
2444 int errno_val = errno;
2445 notice ("%s: warning: can't rename file `%s' to `%s': %s\n",
2446 pname, shortpath (NULL, filename),
2447 shortpath (NULL, new_filename), xstrerror (errno_val));
2448 errors++;
2449 return;
2453 #endif /* !defined (UNPROTOIZE) */
2455 /* Take the list of definitions and declarations attached to a particular
2456 file_info node and reverse the order of the list. This should get the
2457 list into an order such that the item with the lowest associated line
2458 number is nearest the head of the list. When these lists are originally
2459 built, they are in the opposite order. We want to traverse them in
2460 normal line number order later (i.e. lowest to highest) so reverse the
2461 order here. */
2463 static void
2464 reverse_def_dec_list (hp)
2465 const hash_table_entry *hp;
2467 file_info *file_p = hp->fip;
2468 def_dec_info *prev = NULL;
2469 def_dec_info *current = (def_dec_info *)file_p->defs_decs;
2471 if (!current)
2472 return; /* no list to reverse */
2474 prev = current;
2475 if (! (current = (def_dec_info *)current->next_in_file))
2476 return; /* can't reverse a single list element */
2478 prev->next_in_file = NULL;
2480 while (current)
2482 def_dec_info *next = (def_dec_info *)current->next_in_file;
2484 current->next_in_file = prev;
2485 prev = current;
2486 current = next;
2489 file_p->defs_decs = prev;
2492 #ifndef UNPROTOIZE
2494 /* Find the (only?) extern definition for a particular function name, starting
2495 from the head of the linked list of entries for the given name. If we
2496 cannot find an extern definition for the given function name, issue a
2497 warning and scrounge around for the next best thing, i.e. an extern
2498 function declaration with a prototype attached to it. Note that we only
2499 allow such substitutions for extern declarations and never for static
2500 declarations. That's because the only reason we allow them at all is
2501 to let un-prototyped function declarations for system-supplied library
2502 functions get their prototypes from our own extra SYSCALLS.c.X file which
2503 contains all of the correct prototypes for system functions. */
2505 static const def_dec_info *
2506 find_extern_def (head, user)
2507 const def_dec_info *head;
2508 const def_dec_info *user;
2510 const def_dec_info *dd_p;
2511 const def_dec_info *extern_def_p = NULL;
2512 int conflict_noted = 0;
2514 /* Don't act too stupid here. Somebody may try to convert an entire system
2515 in one swell fwoop (rather than one program at a time, as should be done)
2516 and in that case, we may find that there are multiple extern definitions
2517 of a given function name in the entire set of source files that we are
2518 converting. If however one of these definitions resides in exactly the
2519 same source file as the reference we are trying to satisfy then in that
2520 case it would be stupid for us to fail to realize that this one definition
2521 *must* be the precise one we are looking for.
2523 To make sure that we don't miss an opportunity to make this "same file"
2524 leap of faith, we do a prescan of the list of records relating to the
2525 given function name, and we look (on this first scan) *only* for a
2526 definition of the function which is in the same file as the reference
2527 we are currently trying to satisfy. */
2529 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2530 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2531 return dd_p;
2533 /* Now, since we have not found a definition in the same file as the
2534 reference, we scan the list again and consider all possibilities from
2535 all files. Here we may get conflicts with the things listed in the
2536 SYSCALLS.c.X file, but if that happens it only means that the source
2537 code being converted contains its own definition of a function which
2538 could have been supplied by libc.a. In such cases, we should avoid
2539 issuing the normal warning, and defer to the definition given in the
2540 user's own code. */
2542 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2543 if (dd_p->is_func_def && !dd_p->is_static)
2545 if (!extern_def_p) /* Previous definition? */
2546 extern_def_p = dd_p; /* Remember the first definition found. */
2547 else
2549 /* Ignore definition just found if it came from SYSCALLS.c.X. */
2551 if (is_syscalls_file (dd_p->file))
2552 continue;
2554 /* Quietly replace the definition previously found with the one
2555 just found if the previous one was from SYSCALLS.c.X. */
2557 if (is_syscalls_file (extern_def_p->file))
2559 extern_def_p = dd_p;
2560 continue;
2563 /* If we get here, then there is a conflict between two function
2564 declarations for the same function, both of which came from the
2565 user's own code. */
2567 if (!conflict_noted) /* first time we noticed? */
2569 conflict_noted = 1;
2570 notice ("%s: conflicting extern definitions of '%s'\n",
2571 pname, head->hash_entry->symbol);
2572 if (!quiet_flag)
2574 notice ("%s: declarations of '%s' will not be converted\n",
2575 pname, head->hash_entry->symbol);
2576 notice ("%s: conflict list for '%s' follows:\n",
2577 pname, head->hash_entry->symbol);
2578 fprintf (stderr, "%s: %s(%d): %s\n",
2579 pname,
2580 shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2581 extern_def_p->line, extern_def_p->ansi_decl);
2584 if (!quiet_flag)
2585 fprintf (stderr, "%s: %s(%d): %s\n",
2586 pname,
2587 shortpath (NULL, dd_p->file->hash_entry->symbol),
2588 dd_p->line, dd_p->ansi_decl);
2592 /* We want to err on the side of caution, so if we found multiple conflicting
2593 definitions for the same function, treat this as being that same as if we
2594 had found no definitions (i.e. return NULL). */
2596 if (conflict_noted)
2597 return NULL;
2599 if (!extern_def_p)
2601 /* We have no definitions for this function so do the next best thing.
2602 Search for an extern declaration already in prototype form. */
2604 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2605 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2607 extern_def_p = dd_p; /* save a pointer to the definition */
2608 if (!quiet_flag)
2609 notice ("%s: warning: using formals list from %s(%d) for function `%s'\n",
2610 pname,
2611 shortpath (NULL, dd_p->file->hash_entry->symbol),
2612 dd_p->line, dd_p->hash_entry->symbol);
2613 break;
2616 /* Gripe about unprototyped function declarations that we found no
2617 corresponding definition (or other source of prototype information)
2618 for.
2620 Gripe even if the unprototyped declaration we are worried about
2621 exists in a file in one of the "system" include directories. We
2622 can gripe about these because we should have at least found a
2623 corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
2624 didn't, then that means that the SYSCALLS.c.X file is missing some
2625 needed prototypes for this particular system. That is worth telling
2626 the user about! */
2628 if (!extern_def_p)
2630 const char *file = user->file->hash_entry->symbol;
2632 if (!quiet_flag)
2633 if (in_system_include_dir (file))
2635 /* Why copy this string into `needed' at all?
2636 Why not just use user->ansi_decl without copying? */
2637 char *needed = (char *) alloca (strlen (user->ansi_decl) + 1);
2638 char *p;
2640 strcpy (needed, user->ansi_decl);
2641 p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
2642 + strlen (user->hash_entry->symbol) + 2;
2643 /* Avoid having ??? in the string. */
2644 *p++ = '?';
2645 *p++ = '?';
2646 *p++ = '?';
2647 strcpy (p, ");");
2649 notice ("%s: %d: `%s' used but missing from SYSCALLS\n",
2650 shortpath (NULL, file), user->line,
2651 needed+7); /* Don't print "extern " */
2653 #if 0
2654 else
2655 notice ("%s: %d: warning: no extern definition for `%s'\n",
2656 shortpath (NULL, file), user->line,
2657 user->hash_entry->symbol);
2658 #endif
2661 return extern_def_p;
2664 /* Find the (only?) static definition for a particular function name in a
2665 given file. Here we get the function-name and the file info indirectly
2666 from the def_dec_info record pointer which is passed in. */
2668 static const def_dec_info *
2669 find_static_definition (user)
2670 const def_dec_info *user;
2672 const def_dec_info *head = user->hash_entry->ddip;
2673 const def_dec_info *dd_p;
2674 int num_static_defs = 0;
2675 const def_dec_info *static_def_p = NULL;
2677 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2678 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2680 static_def_p = dd_p; /* save a pointer to the definition */
2681 num_static_defs++;
2683 if (num_static_defs == 0)
2685 if (!quiet_flag)
2686 notice ("%s: warning: no static definition for `%s' in file `%s'\n",
2687 pname, head->hash_entry->symbol,
2688 shortpath (NULL, user->file->hash_entry->symbol));
2690 else if (num_static_defs > 1)
2692 notice ("%s: multiple static defs of `%s' in file `%s'\n",
2693 pname, head->hash_entry->symbol,
2694 shortpath (NULL, user->file->hash_entry->symbol));
2695 return NULL;
2697 return static_def_p;
2700 /* Find good prototype style formal argument lists for all of the function
2701 declarations which didn't have them before now.
2703 To do this we consider each function name one at a time. For each function
2704 name, we look at the items on the linked list of def_dec_info records for
2705 that particular name.
2707 Somewhere on this list we should find one (and only one) def_dec_info
2708 record which represents the actual function definition, and this record
2709 should have a nice formal argument list already associated with it.
2711 Thus, all we have to do is to connect up all of the other def_dec_info
2712 records for this particular function name to the special one which has
2713 the full-blown formals list.
2715 Of course it is a little more complicated than just that. See below for
2716 more details. */
2718 static void
2719 connect_defs_and_decs (hp)
2720 const hash_table_entry *hp;
2722 const def_dec_info *dd_p;
2723 const def_dec_info *extern_def_p = NULL;
2724 int first_extern_reference = 1;
2726 /* Traverse the list of definitions and declarations for this particular
2727 function name. For each item on the list, if it is a function
2728 definition (either old style or new style) then GCC has already been
2729 kind enough to produce a prototype for us, and it is associated with
2730 the item already, so declare the item as its own associated "definition".
2732 Also, for each item which is only a function declaration, but which
2733 nonetheless has its own prototype already (obviously supplied by the user)
2734 declare the item as its own definition.
2736 Note that when/if there are multiple user-supplied prototypes already
2737 present for multiple declarations of any given function, these multiple
2738 prototypes *should* all match exactly with one another and with the
2739 prototype for the actual function definition. We don't check for this
2740 here however, since we assume that the compiler must have already done
2741 this consistency checking when it was creating the .X files. */
2743 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2744 if (dd_p->prototyped)
2745 ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2747 /* Traverse the list of definitions and declarations for this particular
2748 function name. For each item on the list, if it is an extern function
2749 declaration and if it has no associated definition yet, go try to find
2750 the matching extern definition for the declaration.
2752 When looking for the matching function definition, warn the user if we
2753 fail to find one.
2755 If we find more that one function definition also issue a warning.
2757 Do the search for the matching definition only once per unique function
2758 name (and only when absolutely needed) so that we can avoid putting out
2759 redundant warning messages, and so that we will only put out warning
2760 messages when there is actually a reference (i.e. a declaration) for
2761 which we need to find a matching definition. */
2763 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2764 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2766 if (first_extern_reference)
2768 extern_def_p = find_extern_def (hp->ddip, dd_p);
2769 first_extern_reference = 0;
2771 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2774 /* Traverse the list of definitions and declarations for this particular
2775 function name. For each item on the list, if it is a static function
2776 declaration and if it has no associated definition yet, go try to find
2777 the matching static definition for the declaration within the same file.
2779 When looking for the matching function definition, warn the user if we
2780 fail to find one in the same file with the declaration, and refuse to
2781 convert this kind of cross-file static function declaration. After all,
2782 this is stupid practice and should be discouraged.
2784 We don't have to worry about the possibility that there is more than one
2785 matching function definition in the given file because that would have
2786 been flagged as an error by the compiler.
2788 Do the search for the matching definition only once per unique
2789 function-name/source-file pair (and only when absolutely needed) so that
2790 we can avoid putting out redundant warning messages, and so that we will
2791 only put out warning messages when there is actually a reference (i.e. a
2792 declaration) for which we actually need to find a matching definition. */
2794 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2795 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2797 const def_dec_info *dd_p2;
2798 const def_dec_info *static_def;
2800 /* We have now found a single static declaration for which we need to
2801 find a matching definition. We want to minimize the work (and the
2802 number of warnings), so we will find an appropriate (matching)
2803 static definition for this declaration, and then distribute it
2804 (as the definition for) any and all other static declarations
2805 for this function name which occur within the same file, and which
2806 do not already have definitions.
2808 Note that a trick is used here to prevent subsequent attempts to
2809 call find_static_definition for a given function-name & file
2810 if the first such call returns NULL. Essentially, we convert
2811 these NULL return values to -1, and put the -1 into the definition
2812 field for each other static declaration from the same file which
2813 does not already have an associated definition.
2814 This makes these other static declarations look like they are
2815 actually defined already when the outer loop here revisits them
2816 later on. Thus, the outer loop will skip over them. Later, we
2817 turn the -1's back to NULL's. */
2819 ((NONCONST def_dec_info *) dd_p)->definition =
2820 (static_def = find_static_definition (dd_p))
2821 ? static_def
2822 : (const def_dec_info *) -1;
2824 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2825 if (!dd_p2->is_func_def && dd_p2->is_static
2826 && !dd_p2->definition && (dd_p2->file == dd_p->file))
2827 ((NONCONST def_dec_info *)dd_p2)->definition = dd_p->definition;
2830 /* Convert any dummy (-1) definitions we created in the step above back to
2831 NULL's (as they should be). */
2833 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2834 if (dd_p->definition == (def_dec_info *) -1)
2835 ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2838 #endif /* !defined (UNPROTOIZE) */
2840 /* Give a pointer into the clean text buffer, return a number which is the
2841 original source line number that the given pointer points into. */
2843 static int
2844 identify_lineno (clean_p)
2845 const char *clean_p;
2847 int line_num = 1;
2848 const char *scan_p;
2850 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2851 if (*scan_p == '\n')
2852 line_num++;
2853 return line_num;
2856 /* Issue an error message and give up on doing this particular edit. */
2858 static void
2859 declare_source_confusing (clean_p)
2860 const char *clean_p;
2862 if (!quiet_flag)
2864 if (clean_p == 0)
2865 notice ("%s: %d: warning: source too confusing\n",
2866 shortpath (NULL, convert_filename), last_known_line_number);
2867 else
2868 notice ("%s: %d: warning: source too confusing\n",
2869 shortpath (NULL, convert_filename),
2870 identify_lineno (clean_p));
2872 longjmp (source_confusion_recovery, 1);
2875 /* Check that a condition which is expected to be true in the original source
2876 code is in fact true. If not, issue an error message and give up on
2877 converting this particular source file. */
2879 static void
2880 check_source (cond, clean_p)
2881 int cond;
2882 const char *clean_p;
2884 if (!cond)
2885 declare_source_confusing (clean_p);
2888 /* If we think of the in-core cleaned text buffer as a memory mapped
2889 file (with the variable last_known_line_start acting as sort of a
2890 file pointer) then we can imagine doing "seeks" on the buffer. The
2891 following routine implements a kind of "seek" operation for the in-core
2892 (cleaned) copy of the source file. When finished, it returns a pointer to
2893 the start of a given (numbered) line in the cleaned text buffer.
2895 Note that protoize only has to "seek" in the forward direction on the
2896 in-core cleaned text file buffers, and it never needs to back up.
2898 This routine is made a little bit faster by remembering the line number
2899 (and pointer value) supplied (and returned) from the previous "seek".
2900 This prevents us from always having to start all over back at the top
2901 of the in-core cleaned buffer again. */
2903 static const char *
2904 seek_to_line (n)
2905 int n;
2907 if (n < last_known_line_number)
2908 abort ();
2910 while (n > last_known_line_number)
2912 while (*last_known_line_start != '\n')
2913 check_source (++last_known_line_start < clean_text_limit, 0);
2914 last_known_line_start++;
2915 last_known_line_number++;
2917 return last_known_line_start;
2920 /* Given a pointer to a character in the cleaned text buffer, return a pointer
2921 to the next non-whitespace character which follows it. */
2923 static const char *
2924 forward_to_next_token_char (ptr)
2925 const char *ptr;
2927 for (++ptr; ISSPACE ((const unsigned char)*ptr);
2928 check_source (++ptr < clean_text_limit, 0))
2929 continue;
2930 return ptr;
2933 /* Copy a chunk of text of length `len' and starting at `str' to the current
2934 output buffer. Note that all attempts to add stuff to the current output
2935 buffer ultimately go through here. */
2937 static void
2938 output_bytes (str, len)
2939 const char *str;
2940 size_t len;
2942 if ((repl_write_ptr + 1) + len >= repl_text_limit)
2944 size_t new_size = (repl_text_limit - repl_text_base) << 1;
2945 char *new_buf = (char *) xrealloc (repl_text_base, new_size);
2947 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
2948 repl_text_base = new_buf;
2949 repl_text_limit = new_buf + new_size;
2951 memcpy (repl_write_ptr + 1, str, len);
2952 repl_write_ptr += len;
2955 /* Copy all bytes (except the trailing null) of a null terminated string to
2956 the current output buffer. */
2958 static void
2959 output_string (str)
2960 const char *str;
2962 output_bytes (str, strlen (str));
2965 /* Copy some characters from the original text buffer to the current output
2966 buffer.
2968 This routine takes a pointer argument `p' which is assumed to be a pointer
2969 into the cleaned text buffer. The bytes which are copied are the `original'
2970 equivalents for the set of bytes between the last value of `clean_read_ptr'
2971 and the argument value `p'.
2973 The set of bytes copied however, comes *not* from the cleaned text buffer,
2974 but rather from the direct counterparts of these bytes within the original
2975 text buffer.
2977 Thus, when this function is called, some bytes from the original text
2978 buffer (which may include original comments and preprocessing directives)
2979 will be copied into the output buffer.
2981 Note that the request implied when this routine is called includes the
2982 byte pointed to by the argument pointer `p'. */
2984 static void
2985 output_up_to (p)
2986 const char *p;
2988 size_t copy_length = (size_t) (p - clean_read_ptr);
2989 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
2991 if (copy_length == 0)
2992 return;
2994 output_bytes (copy_start, copy_length);
2995 clean_read_ptr = p;
2998 /* Given a pointer to a def_dec_info record which represents some form of
2999 definition of a function (perhaps a real definition, or in lieu of that
3000 perhaps just a declaration with a full prototype) return true if this
3001 function is one which we should avoid converting. Return false
3002 otherwise. */
3004 static int
3005 other_variable_style_function (ansi_header)
3006 const char *ansi_header;
3008 #ifdef UNPROTOIZE
3010 /* See if we have a stdarg function, or a function which has stdarg style
3011 parameters or a stdarg style return type. */
3013 return substr (ansi_header, "...") != 0;
3015 #else /* !defined (UNPROTOIZE) */
3017 /* See if we have a varargs function, or a function which has varargs style
3018 parameters or a varargs style return type. */
3020 const char *p;
3021 int len = strlen (varargs_style_indicator);
3023 for (p = ansi_header; p; )
3025 const char *candidate;
3027 if ((candidate = substr (p, varargs_style_indicator)) == 0)
3028 return 0;
3029 else
3030 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
3031 return 1;
3032 else
3033 p = candidate + 1;
3035 return 0;
3036 #endif /* !defined (UNPROTOIZE) */
3039 /* Do the editing operation specifically for a function "declaration". Note
3040 that editing for function "definitions" are handled in a separate routine
3041 below. */
3043 static void
3044 edit_fn_declaration (def_dec_p, clean_text_p)
3045 const def_dec_info *def_dec_p;
3046 const char *volatile clean_text_p;
3048 const char *start_formals;
3049 const char *end_formals;
3050 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3051 size_t func_name_len = strlen (function_to_edit);
3052 const char *end_of_fn_name;
3054 #ifndef UNPROTOIZE
3056 const f_list_chain_item *this_f_list_chain_item;
3057 const def_dec_info *definition = def_dec_p->definition;
3059 /* If we are protoizing, and if we found no corresponding definition for
3060 this particular function declaration, then just leave this declaration
3061 exactly as it is. */
3063 if (!definition)
3064 return;
3066 /* If we are protoizing, and if the corresponding definition that we found
3067 for this particular function declaration defined an old style varargs
3068 function, then we want to issue a warning and just leave this function
3069 declaration unconverted. */
3071 if (other_variable_style_function (definition->ansi_decl))
3073 if (!quiet_flag)
3074 notice ("%s: %d: warning: varargs function declaration not converted\n",
3075 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3076 def_dec_p->line);
3077 return;
3080 #endif /* !defined (UNPROTOIZE) */
3082 /* Setup here to recover from confusing source code detected during this
3083 particular "edit". */
3085 save_pointers ();
3086 if (setjmp (source_confusion_recovery))
3088 restore_pointers ();
3089 notice ("%s: declaration of function `%s' not converted\n",
3090 pname, function_to_edit);
3091 return;
3094 /* We are editing a function declaration. The line number we did a seek to
3095 contains the comma or semicolon which follows the declaration. Our job
3096 now is to scan backwards looking for the function name. This name *must*
3097 be followed by open paren (ignoring whitespace, of course). We need to
3098 replace everything between that open paren and the corresponding closing
3099 paren. If we are protoizing, we need to insert the prototype-style
3100 formals lists. If we are unprotoizing, we need to just delete everything
3101 between the pairs of opening and closing parens. */
3103 /* First move up to the end of the line. */
3105 while (*clean_text_p != '\n')
3106 check_source (++clean_text_p < clean_text_limit, 0);
3107 clean_text_p--; /* Point to just before the newline character. */
3109 /* Now we can scan backwards for the function name. */
3113 for (;;)
3115 /* Scan leftwards until we find some character which can be
3116 part of an identifier. */
3118 while (!is_id_char (*clean_text_p))
3119 check_source (--clean_text_p > clean_read_ptr, 0);
3121 /* Scan backwards until we find a char that cannot be part of an
3122 identifier. */
3124 while (is_id_char (*clean_text_p))
3125 check_source (--clean_text_p > clean_read_ptr, 0);
3127 /* Having found an "id break", see if the following id is the one
3128 that we are looking for. If so, then exit from this loop. */
3130 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
3132 char ch = *(clean_text_p + 1 + func_name_len);
3134 /* Must also check to see that the name in the source text
3135 ends where it should (in order to prevent bogus matches
3136 on similar but longer identifiers. */
3138 if (! is_id_char (ch))
3139 break; /* exit from loop */
3143 /* We have now found the first perfect match for the function name in
3144 our backward search. This may or may not be the actual function
3145 name at the start of the actual function declaration (i.e. we could
3146 have easily been mislead). We will try to avoid getting fooled too
3147 often by looking forward for the open paren which should follow the
3148 identifier we just found. We ignore whitespace while hunting. If
3149 the next non-whitespace byte we see is *not* an open left paren,
3150 then we must assume that we have been fooled and we start over
3151 again accordingly. Note that there is no guarantee, that even if
3152 we do see the open paren, that we are in the right place.
3153 Programmers do the strangest things sometimes! */
3155 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
3156 start_formals = forward_to_next_token_char (end_of_fn_name);
3158 while (*start_formals != '(');
3160 /* start_of_formals now points to the opening left paren which immediately
3161 follows the name of the function. */
3163 /* Note that there may be several formals lists which need to be modified
3164 due to the possibility that the return type of this function is a
3165 pointer-to-function type. If there are several formals lists, we
3166 convert them in left-to-right order here. */
3168 #ifndef UNPROTOIZE
3169 this_f_list_chain_item = definition->f_list_chain;
3170 #endif /* !defined (UNPROTOIZE) */
3172 for (;;)
3175 int depth;
3177 end_formals = start_formals + 1;
3178 depth = 1;
3179 for (; depth; check_source (++end_formals < clean_text_limit, 0))
3181 switch (*end_formals)
3183 case '(':
3184 depth++;
3185 break;
3186 case ')':
3187 depth--;
3188 break;
3191 end_formals--;
3194 /* end_formals now points to the closing right paren of the formals
3195 list whose left paren is pointed to by start_formals. */
3197 /* Now, if we are protoizing, we insert the new ANSI-style formals list
3198 attached to the associated definition of this function. If however
3199 we are unprotoizing, then we simply delete any formals list which
3200 may be present. */
3202 output_up_to (start_formals);
3203 #ifndef UNPROTOIZE
3204 if (this_f_list_chain_item)
3206 output_string (this_f_list_chain_item->formals_list);
3207 this_f_list_chain_item = this_f_list_chain_item->chain_next;
3209 else
3211 if (!quiet_flag)
3212 notice ("%s: warning: too many parameter lists in declaration of `%s'\n",
3213 pname, def_dec_p->hash_entry->symbol);
3214 check_source (0, end_formals); /* leave the declaration intact */
3216 #endif /* !defined (UNPROTOIZE) */
3217 clean_read_ptr = end_formals - 1;
3219 /* Now see if it looks like there may be another formals list associated
3220 with the function declaration that we are converting (following the
3221 formals list that we just converted. */
3224 const char *another_r_paren = forward_to_next_token_char (end_formals);
3226 if ((*another_r_paren != ')')
3227 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3229 #ifndef UNPROTOIZE
3230 if (this_f_list_chain_item)
3232 if (!quiet_flag)
3233 notice ("\n%s: warning: too few parameter lists in declaration of `%s'\n",
3234 pname, def_dec_p->hash_entry->symbol);
3235 check_source (0, start_formals); /* leave the decl intact */
3237 #endif /* !defined (UNPROTOIZE) */
3238 break;
3243 /* There does appear to be yet another formals list, so loop around
3244 again, and convert it also. */
3248 /* Edit a whole group of formals lists, starting with the rightmost one
3249 from some set of formals lists. This routine is called once (from the
3250 outside) for each function declaration which is converted. It is
3251 recursive however, and it calls itself once for each remaining formal
3252 list that lies to the left of the one it was originally called to work
3253 on. Thus, a whole set gets done in right-to-left order.
3255 This routine returns non-zero if it thinks that it should not be trying
3256 to convert this particular function definition (because the name of the
3257 function doesn't match the one expected). */
3259 static int
3260 edit_formals_lists (end_formals, f_list_count, def_dec_p)
3261 const char *end_formals;
3262 unsigned int f_list_count;
3263 const def_dec_info *def_dec_p;
3265 const char *start_formals;
3266 int depth;
3268 start_formals = end_formals - 1;
3269 depth = 1;
3270 for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3272 switch (*start_formals)
3274 case '(':
3275 depth--;
3276 break;
3277 case ')':
3278 depth++;
3279 break;
3282 start_formals++;
3284 /* start_formals now points to the opening left paren of the formals list. */
3286 f_list_count--;
3288 if (f_list_count)
3290 const char *next_end;
3292 /* There should be more formal lists to the left of here. */
3294 next_end = start_formals - 1;
3295 check_source (next_end > clean_read_ptr, 0);
3296 while (ISSPACE ((const unsigned char)*next_end))
3297 check_source (--next_end > clean_read_ptr, 0);
3298 check_source (*next_end == ')', next_end);
3299 check_source (--next_end > clean_read_ptr, 0);
3300 check_source (*next_end == ')', next_end);
3301 if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3302 return 1;
3305 /* Check that the function name in the header we are working on is the same
3306 as the one we would expect to find. If not, issue a warning and return
3307 non-zero. */
3309 if (f_list_count == 0)
3311 const char *expected = def_dec_p->hash_entry->symbol;
3312 const char *func_name_start;
3313 const char *func_name_limit;
3314 size_t func_name_len;
3316 for (func_name_limit = start_formals-1;
3317 ISSPACE ((const unsigned char)*func_name_limit); )
3318 check_source (--func_name_limit > clean_read_ptr, 0);
3320 for (func_name_start = func_name_limit++;
3321 is_id_char (*func_name_start);
3322 func_name_start--)
3323 check_source (func_name_start > clean_read_ptr, 0);
3324 func_name_start++;
3325 func_name_len = func_name_limit - func_name_start;
3326 if (func_name_len == 0)
3327 check_source (0, func_name_start);
3328 if (func_name_len != strlen (expected)
3329 || strncmp (func_name_start, expected, func_name_len))
3331 notice ("%s: %d: warning: found `%s' but expected `%s'\n",
3332 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3333 identify_lineno (func_name_start),
3334 dupnstr (func_name_start, func_name_len),
3335 expected);
3336 return 1;
3340 output_up_to (start_formals);
3342 #ifdef UNPROTOIZE
3343 if (f_list_count == 0)
3344 output_string (def_dec_p->formal_names);
3345 #else /* !defined (UNPROTOIZE) */
3347 unsigned f_list_depth;
3348 const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3350 /* At this point, the current value of f_list count says how many
3351 links we have to follow through the f_list_chain to get to the
3352 particular formals list that we need to output next. */
3354 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3355 flci_p = flci_p->chain_next;
3356 output_string (flci_p->formals_list);
3358 #endif /* !defined (UNPROTOIZE) */
3360 clean_read_ptr = end_formals - 1;
3361 return 0;
3364 /* Given a pointer to a byte in the clean text buffer which points to
3365 the beginning of a line that contains a "follower" token for a
3366 function definition header, do whatever is necessary to find the
3367 right closing paren for the rightmost formals list of the function
3368 definition header. */
3370 static const char *
3371 find_rightmost_formals_list (clean_text_p)
3372 const char *clean_text_p;
3374 const char *end_formals;
3376 /* We are editing a function definition. The line number we did a seek
3377 to contains the first token which immediately follows the entire set of
3378 formals lists which are part of this particular function definition
3379 header.
3381 Our job now is to scan leftwards in the clean text looking for the
3382 right-paren which is at the end of the function header's rightmost
3383 formals list.
3385 If we ignore whitespace, this right paren should be the first one we
3386 see which is (ignoring whitespace) immediately followed either by the
3387 open curly-brace beginning the function body or by an alphabetic
3388 character (in the case where the function definition is in old (K&R)
3389 style and there are some declarations of formal parameters). */
3391 /* It is possible that the right paren we are looking for is on the
3392 current line (together with its following token). Just in case that
3393 might be true, we start out here by skipping down to the right end of
3394 the current line before starting our scan. */
3396 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3397 continue;
3398 end_formals--;
3400 #ifdef UNPROTOIZE
3402 /* Now scan backwards while looking for the right end of the rightmost
3403 formals list associated with this function definition. */
3406 char ch;
3407 const char *l_brace_p;
3409 /* Look leftward and try to find a right-paren. */
3411 while (*end_formals != ')')
3413 if (ISSPACE ((unsigned char)*end_formals))
3414 while (ISSPACE ((unsigned char)*end_formals))
3415 check_source (--end_formals > clean_read_ptr, 0);
3416 else
3417 check_source (--end_formals > clean_read_ptr, 0);
3420 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3421 /* Since we are unprotoizing an ANSI-style (prototyped) function
3422 definition, there had better not be anything (except whitespace)
3423 between the end of the ANSI formals list and the beginning of the
3424 function body (i.e. the '{'). */
3426 check_source (ch == '{', l_brace_p);
3429 #else /* !defined (UNPROTOIZE) */
3431 /* Now scan backwards while looking for the right end of the rightmost
3432 formals list associated with this function definition. */
3434 while (1)
3436 char ch;
3437 const char *l_brace_p;
3439 /* Look leftward and try to find a right-paren. */
3441 while (*end_formals != ')')
3443 if (ISSPACE ((const unsigned char)*end_formals))
3444 while (ISSPACE ((const unsigned char)*end_formals))
3445 check_source (--end_formals > clean_read_ptr, 0);
3446 else
3447 check_source (--end_formals > clean_read_ptr, 0);
3450 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3452 /* Since it is possible that we found a right paren before the starting
3453 '{' of the body which IS NOT the one at the end of the real K&R
3454 formals list (say for instance, we found one embedded inside one of
3455 the old K&R formal parameter declarations) we have to check to be
3456 sure that this is in fact the right paren that we were looking for.
3458 The one we were looking for *must* be followed by either a '{' or
3459 by an alphabetic character, while others *cannot* validly be followed
3460 by such characters. */
3462 if ((ch == '{') || ISALPHA ((unsigned char)ch))
3463 break;
3465 /* At this point, we have found a right paren, but we know that it is
3466 not the one we were looking for, so backup one character and keep
3467 looking. */
3469 check_source (--end_formals > clean_read_ptr, 0);
3472 #endif /* !defined (UNPROTOIZE) */
3474 return end_formals;
3477 #ifndef UNPROTOIZE
3479 /* Insert into the output file a totally new declaration for a function
3480 which (up until now) was being called from within the current block
3481 without having been declared at any point such that the declaration
3482 was visible (i.e. in scope) at the point of the call.
3484 We need to add in explicit declarations for all such function calls
3485 in order to get the full benefit of prototype-based function call
3486 parameter type checking. */
3488 static void
3489 add_local_decl (def_dec_p, clean_text_p)
3490 const def_dec_info *def_dec_p;
3491 const char *clean_text_p;
3493 const char *start_of_block;
3494 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3496 /* Don't insert new local explicit declarations unless explicitly requested
3497 to do so. */
3499 if (!local_flag)
3500 return;
3502 /* Setup here to recover from confusing source code detected during this
3503 particular "edit". */
3505 save_pointers ();
3506 if (setjmp (source_confusion_recovery))
3508 restore_pointers ();
3509 notice ("%s: local declaration for function `%s' not inserted\n",
3510 pname, function_to_edit);
3511 return;
3514 /* We have already done a seek to the start of the line which should
3515 contain *the* open curly brace which begins the block in which we need
3516 to insert an explicit function declaration (to replace the implicit one).
3518 Now we scan that line, starting from the left, until we find the
3519 open curly brace we are looking for. Note that there may actually be
3520 multiple open curly braces on the given line, but we will be happy
3521 with the leftmost one no matter what. */
3523 start_of_block = clean_text_p;
3524 while (*start_of_block != '{' && *start_of_block != '\n')
3525 check_source (++start_of_block < clean_text_limit, 0);
3527 /* Note that the line from the original source could possibly
3528 contain *no* open curly braces! This happens if the line contains
3529 a macro call which expands into a chunk of text which includes a
3530 block (and that block's associated open and close curly braces).
3531 In cases like this, we give up, issue a warning, and do nothing. */
3533 if (*start_of_block != '{')
3535 if (!quiet_flag)
3536 notice ("\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
3537 def_dec_p->file->hash_entry->symbol, def_dec_p->line,
3538 def_dec_p->hash_entry->symbol);
3539 return;
3542 /* Figure out what a nice (pretty) indentation would be for the new
3543 declaration we are adding. In order to do this, we must scan forward
3544 from the '{' until we find the first line which starts with some
3545 non-whitespace characters (i.e. real "token" material). */
3548 const char *ep = forward_to_next_token_char (start_of_block) - 1;
3549 const char *sp;
3551 /* Now we have ep pointing at the rightmost byte of some existing indent
3552 stuff. At least that is the hope.
3554 We can now just scan backwards and find the left end of the existing
3555 indentation string, and then copy it to the output buffer. */
3557 for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--)
3558 continue;
3560 /* Now write out the open { which began this block, and any following
3561 trash up to and including the last byte of the existing indent that
3562 we just found. */
3564 output_up_to (ep);
3566 /* Now we go ahead and insert the new declaration at this point.
3568 If the definition of the given function is in the same file that we
3569 are currently editing, and if its full ANSI declaration normally
3570 would start with the keyword `extern', suppress the `extern'. */
3573 const char *decl = def_dec_p->definition->ansi_decl;
3575 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
3576 decl += 7;
3577 output_string (decl);
3580 /* Finally, write out a new indent string, just like the preceding one
3581 that we found. This will typically include a newline as the first
3582 character of the indent string. */
3584 output_bytes (sp, (size_t) (ep - sp) + 1);
3588 /* Given a pointer to a file_info record, and a pointer to the beginning
3589 of a line (in the clean text buffer) which is assumed to contain the
3590 first "follower" token for the first function definition header in the
3591 given file, find a good place to insert some new global function
3592 declarations (which will replace scattered and imprecise implicit ones)
3593 and then insert the new explicit declaration at that point in the file. */
3595 static void
3596 add_global_decls (file_p, clean_text_p)
3597 const file_info *file_p;
3598 const char *clean_text_p;
3600 const def_dec_info *dd_p;
3601 const char *scan_p;
3603 /* Setup here to recover from confusing source code detected during this
3604 particular "edit". */
3606 save_pointers ();
3607 if (setjmp (source_confusion_recovery))
3609 restore_pointers ();
3610 notice ("%s: global declarations for file `%s' not inserted\n",
3611 pname, shortpath (NULL, file_p->hash_entry->symbol));
3612 return;
3615 /* Start by finding a good location for adding the new explicit function
3616 declarations. To do this, we scan backwards, ignoring whitespace
3617 and comments and other junk until we find either a semicolon, or until
3618 we hit the beginning of the file. */
3620 scan_p = find_rightmost_formals_list (clean_text_p);
3621 for (;; --scan_p)
3623 if (scan_p < clean_text_base)
3624 break;
3625 check_source (scan_p > clean_read_ptr, 0);
3626 if (*scan_p == ';')
3627 break;
3630 /* scan_p now points either to a semicolon, or to just before the start
3631 of the whole file. */
3633 /* Now scan forward for the first non-whitespace character. In theory,
3634 this should be the first character of the following function definition
3635 header. We will put in the added declarations just prior to that. */
3637 scan_p++;
3638 while (ISSPACE ((const unsigned char)*scan_p))
3639 scan_p++;
3640 scan_p--;
3642 output_up_to (scan_p);
3644 /* Now write out full prototypes for all of the things that had been
3645 implicitly declared in this file (but only those for which we were
3646 actually able to find unique matching definitions). Avoid duplicates
3647 by marking things that we write out as we go. */
3650 int some_decls_added = 0;
3652 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3653 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
3655 const char *decl = dd_p->definition->ansi_decl;
3657 /* If the function for which we are inserting a declaration is
3658 actually defined later in the same file, then suppress the
3659 leading `extern' keyword (if there is one). */
3661 if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
3662 decl += 7;
3664 output_string ("\n");
3665 output_string (decl);
3666 some_decls_added = 1;
3667 ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
3669 if (some_decls_added)
3670 output_string ("\n\n");
3673 /* Unmark all of the definitions that we just marked. */
3675 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3676 if (dd_p->definition)
3677 ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
3680 #endif /* !defined (UNPROTOIZE) */
3682 /* Do the editing operation specifically for a function "definition". Note
3683 that editing operations for function "declarations" are handled by a
3684 separate routine above. */
3686 static void
3687 edit_fn_definition (def_dec_p, clean_text_p)
3688 const def_dec_info *def_dec_p;
3689 const char *clean_text_p;
3691 const char *end_formals;
3692 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3694 /* Setup here to recover from confusing source code detected during this
3695 particular "edit". */
3697 save_pointers ();
3698 if (setjmp (source_confusion_recovery))
3700 restore_pointers ();
3701 notice ("%s: definition of function `%s' not converted\n",
3702 pname, function_to_edit);
3703 return;
3706 end_formals = find_rightmost_formals_list (clean_text_p);
3708 /* end_of_formals now points to the closing right paren of the rightmost
3709 formals list which is actually part of the `header' of the function
3710 definition that we are converting. */
3712 /* If the header of this function definition looks like it declares a
3713 function with a variable number of arguments, and if the way it does
3714 that is different from that way we would like it (i.e. varargs vs.
3715 stdarg) then issue a warning and leave the header unconverted. */
3717 if (other_variable_style_function (def_dec_p->ansi_decl))
3719 if (!quiet_flag)
3720 notice ("%s: %d: warning: definition of %s not converted\n",
3721 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3722 identify_lineno (end_formals),
3723 other_var_style);
3724 output_up_to (end_formals);
3725 return;
3728 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
3730 restore_pointers ();
3731 notice ("%s: definition of function `%s' not converted\n",
3732 pname, function_to_edit);
3733 return;
3736 /* Have to output the last right paren because this never gets flushed by
3737 edit_formals_list. */
3739 output_up_to (end_formals);
3741 #ifdef UNPROTOIZE
3743 const char *decl_p;
3744 const char *semicolon_p;
3745 const char *limit_p;
3746 const char *scan_p;
3747 int had_newlines = 0;
3749 /* Now write out the K&R style formal declarations, one per line. */
3751 decl_p = def_dec_p->formal_decls;
3752 limit_p = decl_p + strlen (decl_p);
3753 for (;decl_p < limit_p; decl_p = semicolon_p + 2)
3755 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
3756 continue;
3757 output_string ("\n");
3758 output_string (indent_string);
3759 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
3762 /* If there are no newlines between the end of the formals list and the
3763 start of the body, we should insert one now. */
3765 for (scan_p = end_formals+1; *scan_p != '{'; )
3767 if (*scan_p == '\n')
3769 had_newlines = 1;
3770 break;
3772 check_source (++scan_p < clean_text_limit, 0);
3774 if (!had_newlines)
3775 output_string ("\n");
3777 #else /* !defined (UNPROTOIZE) */
3778 /* If we are protoizing, there may be some flotsam & jetsam (like comments
3779 and preprocessing directives) after the old formals list but before
3780 the following { and we would like to preserve that stuff while effectively
3781 deleting the existing K&R formal parameter declarations. We do so here
3782 in a rather tricky way. Basically, we white out any stuff *except*
3783 the comments/pp-directives in the original text buffer, then, if there
3784 is anything in this area *other* than whitespace, we output it. */
3786 const char *end_formals_orig;
3787 const char *start_body;
3788 const char *start_body_orig;
3789 const char *scan;
3790 const char *scan_orig;
3791 int have_flotsam = 0;
3792 int have_newlines = 0;
3794 for (start_body = end_formals + 1; *start_body != '{';)
3795 check_source (++start_body < clean_text_limit, 0);
3797 end_formals_orig = orig_text_base + (end_formals - clean_text_base);
3798 start_body_orig = orig_text_base + (start_body - clean_text_base);
3799 scan = end_formals + 1;
3800 scan_orig = end_formals_orig + 1;
3801 for (; scan < start_body; scan++, scan_orig++)
3803 if (*scan == *scan_orig)
3805 have_newlines |= (*scan_orig == '\n');
3806 /* Leave identical whitespace alone. */
3807 if (!ISSPACE ((const unsigned char)*scan_orig))
3808 *((NONCONST char *)scan_orig) = ' '; /* identical - so whiteout */
3810 else
3811 have_flotsam = 1;
3813 if (have_flotsam)
3814 output_bytes (end_formals_orig + 1,
3815 (size_t) (start_body_orig - end_formals_orig) - 1);
3816 else
3817 if (have_newlines)
3818 output_string ("\n");
3819 else
3820 output_string (" ");
3821 clean_read_ptr = start_body - 1;
3823 #endif /* !defined (UNPROTOIZE) */
3826 /* Clean up the clean text buffer. Do this by converting comments and
3827 preprocessing directives into spaces. Also convert line continuations
3828 into whitespace. Also, whiteout string and character literals. */
3830 static void
3831 do_cleaning (new_clean_text_base, new_clean_text_limit)
3832 char *new_clean_text_base;
3833 const char *new_clean_text_limit;
3835 char *scan_p;
3836 int non_whitespace_since_newline = 0;
3838 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
3840 switch (*scan_p)
3842 case '/': /* Handle comments. */
3843 if (scan_p[1] != '*')
3844 goto regular;
3845 non_whitespace_since_newline = 1;
3846 scan_p[0] = ' ';
3847 scan_p[1] = ' ';
3848 scan_p += 2;
3849 while (scan_p[1] != '/' || scan_p[0] != '*')
3851 if (!ISSPACE ((const unsigned char)*scan_p))
3852 *scan_p = ' ';
3853 if (++scan_p >= new_clean_text_limit)
3854 abort ();
3856 *scan_p++ = ' ';
3857 *scan_p = ' ';
3858 break;
3860 case '#': /* Handle pp directives. */
3861 if (non_whitespace_since_newline)
3862 goto regular;
3863 *scan_p = ' ';
3864 while (scan_p[1] != '\n' || scan_p[0] == '\\')
3866 if (!ISSPACE ((const unsigned char)*scan_p))
3867 *scan_p = ' ';
3868 if (++scan_p >= new_clean_text_limit)
3869 abort ();
3871 *scan_p++ = ' ';
3872 break;
3874 case '\'': /* Handle character literals. */
3875 non_whitespace_since_newline = 1;
3876 while (scan_p[1] != '\'' || scan_p[0] == '\\')
3878 if (scan_p[0] == '\\'
3879 && !ISSPACE ((const unsigned char)scan_p[1]))
3880 scan_p[1] = ' ';
3881 if (!ISSPACE ((const unsigned char)*scan_p))
3882 *scan_p = ' ';
3883 if (++scan_p >= new_clean_text_limit)
3884 abort ();
3886 *scan_p++ = ' ';
3887 break;
3889 case '"': /* Handle string literals. */
3890 non_whitespace_since_newline = 1;
3891 while (scan_p[1] != '"' || scan_p[0] == '\\')
3893 if (scan_p[0] == '\\'
3894 && !ISSPACE ((const unsigned char)scan_p[1]))
3895 scan_p[1] = ' ';
3896 if (!ISSPACE ((const unsigned char)*scan_p))
3897 *scan_p = ' ';
3898 if (++scan_p >= new_clean_text_limit)
3899 abort ();
3901 if (!ISSPACE ((const unsigned char)*scan_p))
3902 *scan_p = ' ';
3903 scan_p++;
3904 break;
3906 case '\\': /* Handle line continuations. */
3907 if (scan_p[1] != '\n')
3908 goto regular;
3909 *scan_p = ' ';
3910 break;
3912 case '\n':
3913 non_whitespace_since_newline = 0; /* Reset. */
3914 break;
3916 case ' ':
3917 case '\v':
3918 case '\t':
3919 case '\r':
3920 case '\f':
3921 case '\b':
3922 break; /* Whitespace characters. */
3924 default:
3925 regular:
3926 non_whitespace_since_newline = 1;
3927 break;
3932 /* Given a pointer to the closing right parenthesis for a particular formals
3933 list (in the clean text buffer) find the corresponding left parenthesis
3934 and return a pointer to it. */
3936 static const char *
3937 careful_find_l_paren (p)
3938 const char *p;
3940 const char *q;
3941 int paren_depth;
3943 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
3945 switch (*q)
3947 case ')':
3948 paren_depth++;
3949 break;
3950 case '(':
3951 paren_depth--;
3952 break;
3955 return ++q;
3958 /* Scan the clean text buffer for cases of function definitions that we
3959 don't really know about because they were preprocessed out when the
3960 aux info files were created.
3962 In this version of protoize/unprotoize we just give a warning for each
3963 one found. A later version may be able to at least unprotoize such
3964 missed items.
3966 Note that we may easily find all function definitions simply by
3967 looking for places where there is a left paren which is (ignoring
3968 whitespace) immediately followed by either a left-brace or by an
3969 upper or lower case letter. Whenever we find this combination, we
3970 have also found a function definition header.
3972 Finding function *declarations* using syntactic clues is much harder.
3973 I will probably try to do this in a later version though. */
3975 static void
3976 scan_for_missed_items (file_p)
3977 const file_info *file_p;
3979 static const char *scan_p;
3980 const char *limit = clean_text_limit - 3;
3981 static const char *backup_limit;
3983 backup_limit = clean_text_base - 1;
3985 for (scan_p = clean_text_base; scan_p < limit; scan_p++)
3987 if (*scan_p == ')')
3989 static const char *last_r_paren;
3990 const char *ahead_p;
3992 last_r_paren = scan_p;
3994 for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
3995 check_source (++ahead_p < limit, limit);
3997 scan_p = ahead_p - 1;
3999 if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
4001 const char *last_l_paren;
4002 const int lineno = identify_lineno (ahead_p);
4004 if (setjmp (source_confusion_recovery))
4005 continue;
4007 /* We know we have a function definition header. Now skip
4008 leftwards over all of its associated formals lists. */
4012 last_l_paren = careful_find_l_paren (last_r_paren);
4013 for (last_r_paren = last_l_paren-1;
4014 ISSPACE ((const unsigned char)*last_r_paren); )
4015 check_source (--last_r_paren >= backup_limit, backup_limit);
4017 while (*last_r_paren == ')');
4019 if (is_id_char (*last_r_paren))
4021 const char *id_limit = last_r_paren + 1;
4022 const char *id_start;
4023 size_t id_length;
4024 const def_dec_info *dd_p;
4026 for (id_start = id_limit-1; is_id_char (*id_start); )
4027 check_source (--id_start >= backup_limit, backup_limit);
4028 id_start++;
4029 backup_limit = id_start;
4030 if ((id_length = (size_t) (id_limit - id_start)) == 0)
4031 goto not_missed;
4034 char *func_name = (char *) alloca (id_length + 1);
4035 static const char * const stmt_keywords[]
4036 = { "if", "else", "do", "while", "for", "switch", "case", "return", 0 };
4037 const char * const *stmt_keyword;
4039 strncpy (func_name, id_start, id_length);
4040 func_name[id_length] = '\0';
4042 /* We must check here to see if we are actually looking at
4043 a statement rather than an actual function call. */
4045 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
4046 if (!strcmp (func_name, *stmt_keyword))
4047 goto not_missed;
4049 #if 0
4050 notice ("%s: found definition of `%s' at %s(%d)\n",
4051 pname,
4052 func_name,
4053 shortpath (NULL, file_p->hash_entry->symbol),
4054 identify_lineno (id_start));
4055 #endif /* 0 */
4056 /* We really should check for a match of the function name
4057 here also, but why bother. */
4059 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
4060 if (dd_p->is_func_def && dd_p->line == lineno)
4061 goto not_missed;
4063 /* If we make it here, then we did not know about this
4064 function definition. */
4066 notice ("%s: %d: warning: `%s' excluded by preprocessing\n",
4067 shortpath (NULL, file_p->hash_entry->symbol),
4068 identify_lineno (id_start), func_name);
4069 notice ("%s: function definition not converted\n",
4070 pname);
4072 not_missed: ;
4079 /* Do all editing operations for a single source file (either a "base" file
4080 or an "include" file). To do this we read the file into memory, keep a
4081 virgin copy there, make another cleaned in-core copy of the original file
4082 (i.e. one in which all of the comments and preprocessing directives have
4083 been replaced with whitespace), then use these two in-core copies of the
4084 file to make a new edited in-core copy of the file. Finally, rename the
4085 original file (as a way of saving it), and then write the edited version
4086 of the file from core to a disk file of the same name as the original.
4088 Note that the trick of making a copy of the original sans comments &
4089 preprocessing directives make the editing a whole lot easier. */
4091 static void
4092 edit_file (hp)
4093 const hash_table_entry *hp;
4095 struct stat stat_buf;
4096 const file_info *file_p = hp->fip;
4097 char *new_orig_text_base;
4098 char *new_orig_text_limit;
4099 char *new_clean_text_base;
4100 char *new_clean_text_limit;
4101 size_t orig_size;
4102 size_t repl_size;
4103 int first_definition_in_file;
4105 /* If we are not supposed to be converting this file, or if there is
4106 nothing in there which needs converting, just skip this file. */
4108 if (!needs_to_be_converted (file_p))
4109 return;
4111 convert_filename = file_p->hash_entry->symbol;
4113 /* Convert a file if it is in a directory where we want conversion
4114 and the file is not excluded. */
4116 if (!directory_specified_p (convert_filename)
4117 || file_excluded_p (convert_filename))
4119 if (!quiet_flag
4120 #ifdef UNPROTOIZE
4121 /* Don't even mention "system" include files unless we are
4122 protoizing. If we are protoizing, we mention these as a
4123 gentle way of prodding the user to convert his "system"
4124 include files to prototype format. */
4125 && !in_system_include_dir (convert_filename)
4126 #endif /* defined (UNPROTOIZE) */
4128 notice ("%s: `%s' not converted\n",
4129 pname, shortpath (NULL, convert_filename));
4130 return;
4133 /* Let the user know what we are up to. */
4135 if (nochange_flag)
4136 notice ("%s: would convert file `%s'\n",
4137 pname, shortpath (NULL, convert_filename));
4138 else
4139 notice ("%s: converting file `%s'\n",
4140 pname, shortpath (NULL, convert_filename));
4141 fflush (stderr);
4143 /* Find out the size (in bytes) of the original file. */
4145 /* The cast avoids an erroneous warning on AIX. */
4146 if (stat (convert_filename, &stat_buf) == -1)
4148 int errno_val = errno;
4149 notice ("%s: can't get status for file `%s': %s\n",
4150 pname, shortpath (NULL, convert_filename),
4151 xstrerror (errno_val));
4152 return;
4154 orig_size = stat_buf.st_size;
4156 /* Allocate a buffer to hold the original text. */
4158 orig_text_base = new_orig_text_base = (char *) xmalloc (orig_size + 2);
4159 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
4161 /* Allocate a buffer to hold the cleaned-up version of the original text. */
4163 clean_text_base = new_clean_text_base = (char *) xmalloc (orig_size + 2);
4164 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
4165 clean_read_ptr = clean_text_base - 1;
4167 /* Allocate a buffer that will hopefully be large enough to hold the entire
4168 converted output text. As an initial guess for the maximum size of the
4169 output buffer, use 125% of the size of the original + some extra. This
4170 buffer can be expanded later as needed. */
4172 repl_size = orig_size + (orig_size >> 2) + 4096;
4173 repl_text_base = (char *) xmalloc (repl_size + 2);
4174 repl_text_limit = repl_text_base + repl_size - 1;
4175 repl_write_ptr = repl_text_base - 1;
4178 int input_file;
4179 int fd_flags;
4181 /* Open the file to be converted in READ ONLY mode. */
4183 fd_flags = O_RDONLY;
4184 #ifdef O_BINARY
4185 /* Use binary mode to avoid having to deal with different EOL characters. */
4186 fd_flags |= O_BINARY;
4187 #endif
4188 if ((input_file = open (convert_filename, fd_flags, 0444)) == -1)
4190 int errno_val = errno;
4191 notice ("%s: can't open file `%s' for reading: %s\n",
4192 pname, shortpath (NULL, convert_filename),
4193 xstrerror (errno_val));
4194 return;
4197 /* Read the entire original source text file into the original text buffer
4198 in one swell fwoop. Then figure out where the end of the text is and
4199 make sure that it ends with a newline followed by a null. */
4201 if (safe_read (input_file, new_orig_text_base, orig_size) !=
4202 (int) orig_size)
4204 int errno_val = errno;
4205 close (input_file);
4206 notice ("\n%s: error reading input file `%s': %s\n",
4207 pname, shortpath (NULL, convert_filename),
4208 xstrerror (errno_val));
4209 return;
4212 close (input_file);
4215 if (orig_size == 0 || orig_text_limit[-1] != '\n')
4217 *new_orig_text_limit++ = '\n';
4218 orig_text_limit++;
4221 /* Create the cleaned up copy of the original text. */
4223 memcpy (new_clean_text_base, orig_text_base,
4224 (size_t) (orig_text_limit - orig_text_base));
4225 do_cleaning (new_clean_text_base, new_clean_text_limit);
4227 #if 0
4229 int clean_file;
4230 size_t clean_size = orig_text_limit - orig_text_base;
4231 char *const clean_filename = (char *) alloca (strlen (convert_filename) + 6 + 1);
4233 /* Open (and create) the clean file. */
4235 strcpy (clean_filename, convert_filename);
4236 strcat (clean_filename, ".clean");
4237 if ((clean_file = creat (clean_filename, 0666)) == -1)
4239 int errno_val = errno;
4240 notice ("%s: can't create/open clean file `%s': %s\n",
4241 pname, shortpath (NULL, clean_filename),
4242 xstrerror (errno_val));
4243 return;
4246 /* Write the clean file. */
4248 safe_write (clean_file, new_clean_text_base, clean_size, clean_filename);
4250 close (clean_file);
4252 #endif /* 0 */
4254 /* Do a simplified scan of the input looking for things that were not
4255 mentioned in the aux info files because of the fact that they were
4256 in a region of the source which was preprocessed-out (via #if or
4257 via #ifdef). */
4259 scan_for_missed_items (file_p);
4261 /* Setup to do line-oriented forward seeking in the clean text buffer. */
4263 last_known_line_number = 1;
4264 last_known_line_start = clean_text_base;
4266 /* Now get down to business and make all of the necessary edits. */
4269 const def_dec_info *def_dec_p;
4271 first_definition_in_file = 1;
4272 def_dec_p = file_p->defs_decs;
4273 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
4275 const char *clean_text_p = seek_to_line (def_dec_p->line);
4277 /* clean_text_p now points to the first character of the line which
4278 contains the `terminator' for the declaration or definition that
4279 we are about to process. */
4281 #ifndef UNPROTOIZE
4283 if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
4285 add_global_decls (def_dec_p->file, clean_text_p);
4286 first_definition_in_file = 0;
4289 /* Don't edit this item if it is already in prototype format or if it
4290 is a function declaration and we have found no corresponding
4291 definition. */
4293 if (def_dec_p->prototyped
4294 || (!def_dec_p->is_func_def && !def_dec_p->definition))
4295 continue;
4297 #endif /* !defined (UNPROTOIZE) */
4299 if (def_dec_p->is_func_def)
4300 edit_fn_definition (def_dec_p, clean_text_p);
4301 else
4302 #ifndef UNPROTOIZE
4303 if (def_dec_p->is_implicit)
4304 add_local_decl (def_dec_p, clean_text_p);
4305 else
4306 #endif /* !defined (UNPROTOIZE) */
4307 edit_fn_declaration (def_dec_p, clean_text_p);
4311 /* Finalize things. Output the last trailing part of the original text. */
4313 output_up_to (clean_text_limit - 1);
4315 /* If this is just a test run, stop now and just deallocate the buffers. */
4317 if (nochange_flag)
4319 free (new_orig_text_base);
4320 free (new_clean_text_base);
4321 free (repl_text_base);
4322 return;
4325 /* Change the name of the original input file. This is just a quick way of
4326 saving the original file. */
4328 if (!nosave_flag)
4330 char *new_filename
4331 = (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
4333 strcpy (new_filename, convert_filename);
4334 #ifdef __MSDOS__
4335 /* MSDOS filenames are restricted to 8.3 format, so we save `foo.c'
4336 as `foo.<save_suffix>'. */
4337 new_filename[(strlen (convert_filename) - 1] = '\0';
4338 #endif
4339 strcat (new_filename, save_suffix);
4341 /* Don't overwrite existing file. */
4342 if (access (new_filename, F_OK) == 0)
4344 if (!quiet_flag)
4345 notice ("%s: warning: file `%s' already saved in `%s'\n",
4346 pname,
4347 shortpath (NULL, convert_filename),
4348 shortpath (NULL, new_filename));
4350 else if (rename (convert_filename, new_filename) == -1)
4352 int errno_val = errno;
4353 notice ("%s: can't link file `%s' to `%s': %s\n",
4354 pname,
4355 shortpath (NULL, convert_filename),
4356 shortpath (NULL, new_filename),
4357 xstrerror (errno_val));
4358 return;
4362 if (unlink (convert_filename) == -1)
4364 int errno_val = errno;
4365 /* The file may have already been renamed. */
4366 if (errno_val != ENOENT)
4368 notice ("%s: can't delete file `%s': %s\n",
4369 pname, shortpath (NULL, convert_filename),
4370 xstrerror (errno_val));
4371 return;
4376 int output_file;
4378 /* Open (and create) the output file. */
4380 if ((output_file = creat (convert_filename, 0666)) == -1)
4382 int errno_val = errno;
4383 notice ("%s: can't create/open output file `%s': %s\n",
4384 pname, shortpath (NULL, convert_filename),
4385 xstrerror (errno_val));
4386 return;
4388 #ifdef O_BINARY
4389 /* Use binary mode to avoid changing the existing EOL character. */
4390 setmode (output_file, O_BINARY);
4391 #endif
4393 /* Write the output file. */
4396 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
4398 safe_write (output_file, repl_text_base, out_size, convert_filename);
4401 close (output_file);
4404 /* Deallocate the conversion buffers. */
4406 free (new_orig_text_base);
4407 free (new_clean_text_base);
4408 free (repl_text_base);
4410 /* Change the mode of the output file to match the original file. */
4412 /* The cast avoids an erroneous warning on AIX. */
4413 if (chmod (convert_filename, stat_buf.st_mode) == -1)
4415 int errno_val = errno;
4416 notice ("%s: can't change mode of file `%s': %s\n",
4417 pname, shortpath (NULL, convert_filename),
4418 xstrerror (errno_val));
4421 /* Note: We would try to change the owner and group of the output file
4422 to match those of the input file here, except that may not be a good
4423 thing to do because it might be misleading. Also, it might not even
4424 be possible to do that (on BSD systems with quotas for instance). */
4427 /* Do all of the individual steps needed to do the protoization (or
4428 unprotoization) of the files referenced in the aux_info files given
4429 in the command line. */
4431 static void
4432 do_processing ()
4434 const char * const *base_pp;
4435 const char * const * const end_pps
4436 = &base_source_filenames[n_base_source_files];
4438 #ifndef UNPROTOIZE
4439 int syscalls_len;
4440 #endif /* !defined (UNPROTOIZE) */
4442 /* One-by-one, check (and create if necessary), open, and read all of the
4443 stuff in each aux_info file. After reading each aux_info file, the
4444 aux_info_file just read will be automatically deleted unless the
4445 keep_flag is set. */
4447 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
4448 process_aux_info_file (*base_pp, keep_flag, 0);
4450 #ifndef UNPROTOIZE
4452 /* Also open and read the special SYSCALLS.c aux_info file which gives us
4453 the prototypes for all of the standard system-supplied functions. */
4455 if (nondefault_syscalls_dir)
4457 syscalls_absolute_filename
4458 = (char *) xmalloc (strlen (nondefault_syscalls_dir) + 1
4459 + sizeof (syscalls_filename));
4460 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
4462 else
4464 GET_ENV_PATH_LIST (default_syscalls_dir, "GCC_EXEC_PREFIX");
4465 if (!default_syscalls_dir)
4467 default_syscalls_dir = standard_exec_prefix;
4469 syscalls_absolute_filename
4470 = (char *) xmalloc (strlen (default_syscalls_dir) + 0
4471 + strlen (target_machine) + 1
4472 + strlen (target_version) + 1
4473 + sizeof (syscalls_filename));
4474 strcpy (syscalls_absolute_filename, default_syscalls_dir);
4475 strcat (syscalls_absolute_filename, target_machine);
4476 strcat (syscalls_absolute_filename, "/");
4477 strcat (syscalls_absolute_filename, target_version);
4478 strcat (syscalls_absolute_filename, "/");
4481 syscalls_len = strlen (syscalls_absolute_filename);
4482 if (! IS_DIR_SEPARATOR (*(syscalls_absolute_filename + syscalls_len - 1)))
4484 *(syscalls_absolute_filename + syscalls_len++) = DIR_SEPARATOR;
4485 *(syscalls_absolute_filename + syscalls_len) = '\0';
4487 strcat (syscalls_absolute_filename, syscalls_filename);
4489 /* Call process_aux_info_file in such a way that it does not try to
4490 delete the SYSCALLS aux_info file. */
4492 process_aux_info_file (syscalls_absolute_filename, 1, 1);
4494 #endif /* !defined (UNPROTOIZE) */
4496 /* When we first read in all of the information from the aux_info files
4497 we saved in it descending line number order, because that was likely to
4498 be faster. Now however, we want the chains of def & dec records to
4499 appear in ascending line number order as we get further away from the
4500 file_info record that they hang from. The following line causes all of
4501 these lists to be rearranged into ascending line number order. */
4503 visit_each_hash_node (filename_primary, reverse_def_dec_list);
4505 #ifndef UNPROTOIZE
4507 /* Now do the "real" work. The following line causes each declaration record
4508 to be "visited". For each of these nodes, an attempt is made to match
4509 up the function declaration with a corresponding function definition,
4510 which should have a full prototype-format formals list with it. Once
4511 these match-ups are made, the conversion of the function declarations
4512 to prototype format can be made. */
4514 visit_each_hash_node (function_name_primary, connect_defs_and_decs);
4516 #endif /* !defined (UNPROTOIZE) */
4518 /* Now convert each file that can be converted (and needs to be). */
4520 visit_each_hash_node (filename_primary, edit_file);
4522 #ifndef UNPROTOIZE
4524 /* If we are working in cplusplus mode, try to rename all .c files to .C
4525 files. Don't panic if some of the renames don't work. */
4527 if (cplusplus_flag && !nochange_flag)
4528 visit_each_hash_node (filename_primary, rename_c_file);
4530 #endif /* !defined (UNPROTOIZE) */
4533 static struct option longopts[] =
4535 {"version", 0, 0, 'V'},
4536 {"file_name", 0, 0, 'p'},
4537 {"quiet", 0, 0, 'q'},
4538 {"silent", 0, 0, 'q'},
4539 {"force", 0, 0, 'f'},
4540 {"keep", 0, 0, 'k'},
4541 {"nosave", 0, 0, 'N'},
4542 {"nochange", 0, 0, 'n'},
4543 {"compiler-options", 1, 0, 'c'},
4544 {"exclude", 1, 0, 'x'},
4545 {"directory", 1, 0, 'd'},
4546 #ifdef UNPROTOIZE
4547 {"indent", 1, 0, 'i'},
4548 #else
4549 {"local", 0, 0, 'l'},
4550 {"global", 0, 0, 'g'},
4551 {"c++", 0, 0, 'C'},
4552 {"syscalls-dir", 1, 0, 'B'},
4553 #endif
4554 {0, 0, 0, 0}
4557 extern int main PARAMS ((int, char **const));
4560 main (argc, argv)
4561 int argc;
4562 char **const argv;
4564 int longind;
4565 int c;
4566 const char *params = "";
4568 pname = strrchr (argv[0], DIR_SEPARATOR);
4569 #ifdef DIR_SEPARATOR_2
4571 char *slash;
4573 slash = strrchr (pname ? pname : argv[0], DIR_SEPARATOR_2);
4574 if (slash)
4575 pname = slash;
4577 #endif
4578 pname = pname ? pname+1 : argv[0];
4580 #ifdef HAVE_LC_MESSAGES
4581 setlocale (LC_MESSAGES, "");
4582 #endif
4583 (void) bindtextdomain (PACKAGE, localedir);
4584 (void) textdomain (PACKAGE);
4586 cwd_buffer = getpwd ();
4587 if (!cwd_buffer)
4589 notice ("%s: cannot get working directory: %s\n",
4590 pname, xstrerror(errno));
4591 return (FATAL_EXIT_CODE);
4594 /* By default, convert the files in the current directory. */
4595 directory_list = string_list_cons (cwd_buffer, NULL);
4597 while ((c = getopt_long (argc, argv,
4598 #ifdef UNPROTOIZE
4599 "c:d:i:knNp:qvVx:",
4600 #else
4601 "B:c:Cd:gklnNp:qvVx:",
4602 #endif
4603 longopts, &longind)) != EOF)
4605 if (c == 0) /* Long option. */
4606 c = longopts[longind].val;
4607 switch (c)
4609 case 'p':
4610 compiler_file_name = optarg;
4611 break;
4612 case 'd':
4613 directory_list
4614 = string_list_cons (abspath (NULL, optarg), directory_list);
4615 break;
4616 case 'x':
4617 exclude_list = string_list_cons (optarg, exclude_list);
4618 break;
4620 case 'v':
4621 case 'V':
4622 version_flag = 1;
4623 break;
4624 case 'q':
4625 quiet_flag = 1;
4626 break;
4627 #if 0
4628 case 'f':
4629 force_flag = 1;
4630 break;
4631 #endif
4632 case 'n':
4633 nochange_flag = 1;
4634 keep_flag = 1;
4635 break;
4636 case 'N':
4637 nosave_flag = 1;
4638 break;
4639 case 'k':
4640 keep_flag = 1;
4641 break;
4642 case 'c':
4643 params = optarg;
4644 break;
4645 #ifdef UNPROTOIZE
4646 case 'i':
4647 indent_string = optarg;
4648 break;
4649 #else /* !defined (UNPROTOIZE) */
4650 case 'l':
4651 local_flag = 1;
4652 break;
4653 case 'g':
4654 global_flag = 1;
4655 break;
4656 case 'C':
4657 cplusplus_flag = 1;
4658 break;
4659 case 'B':
4660 nondefault_syscalls_dir = optarg;
4661 break;
4662 #endif /* !defined (UNPROTOIZE) */
4663 default:
4664 usage ();
4668 /* Set up compile_params based on -p and -c options. */
4669 munge_compile_params (params);
4671 n_base_source_files = argc - optind;
4673 /* Now actually make a list of the base source filenames. */
4675 base_source_filenames
4676 = (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *));
4677 n_base_source_files = 0;
4678 for (; optind < argc; optind++)
4680 const char *path = abspath (NULL, argv[optind]);
4681 int len = strlen (path);
4683 if (path[len-1] == 'c' && path[len-2] == '.')
4684 base_source_filenames[n_base_source_files++] = path;
4685 else
4687 notice ("%s: input file names must have .c suffixes: %s\n",
4688 pname, shortpath (NULL, path));
4689 errors++;
4693 #ifndef UNPROTOIZE
4694 /* We are only interested in the very first identifier token in the
4695 definition of `va_list', so if there is more junk after that first
4696 identifier token, delete it from the `varargs_style_indicator'. */
4698 const char *cp;
4700 for (cp = varargs_style_indicator;
4701 ISALNUM ((const unsigned char)*cp) || *cp == '_'; cp++)
4702 continue;
4703 if (*cp != 0)
4704 varargs_style_indicator = savestring (varargs_style_indicator,
4705 cp - varargs_style_indicator);
4707 #endif /* !defined (UNPROTOIZE) */
4709 if (errors)
4710 usage ();
4711 else
4713 if (version_flag)
4714 fprintf (stderr, "%s: %s\n", pname, version_string);
4715 do_processing ();
4718 return (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);