2002-11-21 Phil Edwards <pme@gcc.gnu.org>
[official-gcc.git] / gcc / protoize.c
blobe039d6d4775041a024375838c19f17784d07019a
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, 2001, 2002 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "intl.h"
25 #include "cppdefault.h"
27 #include <setjmp.h>
28 #include <signal.h>
29 #if ! defined( SIGCHLD ) && defined( SIGCLD )
30 # define SIGCHLD SIGCLD
31 #endif
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #undef abort
36 #include "version.h"
38 /* Include getopt.h for the sake of getopt_long. */
39 #include "getopt.h"
41 /* Macro to see if the path elements match. */
42 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
43 #define IS_SAME_PATH_CHAR(a,b) (TOUPPER (a) == TOUPPER (b))
44 #else
45 #define IS_SAME_PATH_CHAR(a,b) ((a) == (b))
46 #endif
48 /* Macro to see if the paths match. */
49 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
50 #define IS_SAME_PATH(a,b) (strcasecmp (a, b) == 0)
51 #else
52 #define IS_SAME_PATH(a,b) (strcmp (a, b) == 0)
53 #endif
55 /* Suffix for aux-info files. */
56 #ifdef __MSDOS__
57 #define AUX_INFO_SUFFIX "X"
58 #else
59 #define AUX_INFO_SUFFIX ".X"
60 #endif
62 /* Suffix for saved files. */
63 #ifdef __MSDOS__
64 #define SAVE_SUFFIX "sav"
65 #else
66 #define SAVE_SUFFIX ".save"
67 #endif
69 /* Suffix for renamed C++ files. */
70 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
71 #define CPLUS_FILE_SUFFIX "cc"
72 #else
73 #define CPLUS_FILE_SUFFIX "C"
74 #endif
76 static void usage PARAMS ((void)) ATTRIBUTE_NORETURN;
77 static void aux_info_corrupted PARAMS ((void)) ATTRIBUTE_NORETURN;
78 static void declare_source_confusing PARAMS ((const char *)) ATTRIBUTE_NORETURN;
79 static const char *shortpath PARAMS ((const char *, const char *));
80 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
81 static void notice PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
82 static char *savestring PARAMS ((const char *, unsigned int));
83 static char *dupnstr PARAMS ((const char *, size_t));
84 static const char *substr PARAMS ((const char *, const char * const));
85 static int safe_read PARAMS ((int, PTR, int));
86 static void safe_write PARAMS ((int, PTR, int, const char *));
87 static void save_pointers PARAMS ((void));
88 static void restore_pointers PARAMS ((void));
89 static int is_id_char PARAMS ((int));
90 static int in_system_include_dir PARAMS ((const char *));
91 static int directory_specified_p PARAMS ((const char *));
92 static int file_excluded_p PARAMS ((const char *));
93 static char *unexpand_if_needed PARAMS ((const char *));
94 static char *abspath PARAMS ((const char *, const char *));
95 static int is_abspath PARAMS ((const char *));
96 static void check_aux_info PARAMS ((int));
97 static const char *find_corresponding_lparen PARAMS ((const char *));
98 static int referenced_file_is_newer PARAMS ((const char *, time_t));
99 static void save_def_or_dec PARAMS ((const char *, int));
100 static void munge_compile_params PARAMS ((const char *));
101 static int gen_aux_info_file PARAMS ((const char *));
102 static void process_aux_info_file PARAMS ((const char *, int, int));
103 static int identify_lineno PARAMS ((const char *));
104 static void check_source PARAMS ((int, const char *));
105 static const char *seek_to_line PARAMS ((int));
106 static const char *forward_to_next_token_char PARAMS ((const char *));
107 static void output_bytes PARAMS ((const char *, size_t));
108 static void output_string PARAMS ((const char *));
109 static void output_up_to PARAMS ((const char *));
110 static int other_variable_style_function PARAMS ((const char *));
111 static const char *find_rightmost_formals_list PARAMS ((const char *));
112 static void do_cleaning PARAMS ((char *, const char *));
113 static const char *careful_find_l_paren PARAMS ((const char *));
114 static void do_processing PARAMS ((void));
116 /* Look for these where the `const' qualifier is intentionally cast aside. */
117 #define NONCONST
119 /* Define a default place to find the SYSCALLS.X file. */
121 #ifndef UNPROTOIZE
123 #ifndef STANDARD_EXEC_PREFIX
124 #define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
125 #endif /* !defined STANDARD_EXEC_PREFIX */
127 static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX;
128 static const char * const target_machine = DEFAULT_TARGET_MACHINE;
129 static const char * const target_version = DEFAULT_TARGET_VERSION;
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 *const expanded;
168 const char *const 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);
195 /* Datatype for lists of directories or filenames. */
196 struct string_list
198 const char *name;
199 struct string_list *next;
202 static struct string_list *string_list_cons PARAMS ((const char *,
203 struct string_list *));
205 /* List of directories in which files should be converted. */
207 struct string_list *directory_list;
209 /* List of file names which should not be converted.
210 A file is excluded if the end of its name, following a /,
211 matches one of the names in this list. */
213 struct string_list *exclude_list;
215 /* The name of the other style of variable-number-of-parameters functions
216 (i.e. the style that we want to leave unconverted because we don't yet
217 know how to convert them to this style. This string is used in warning
218 messages. */
220 /* Also define here the string that we can search for in the parameter lists
221 taken from the .X files which will unambiguously indicate that we have
222 found a varargs style function. */
224 #ifdef UNPROTOIZE
225 static const char * const other_var_style = "stdarg";
226 #else /* !defined (UNPROTOIZE) */
227 static const char * const other_var_style = "varargs";
228 /* Note that this is a string containing the expansion of va_alist.
229 But in `main' we discard all but the first token. */
230 static const char *varargs_style_indicator = STRINGX (va_alist);
231 #endif /* !defined (UNPROTOIZE) */
233 /* The following two types are used to create hash tables. In this program,
234 there are two hash tables which are used to store and quickly lookup two
235 different classes of strings. The first type of strings stored in the
236 first hash table are absolute filenames of files which protoize needs to
237 know about. The second type of strings (stored in the second hash table)
238 are function names. It is this second class of strings which really
239 inspired the use of the hash tables, because there may be a lot of them. */
241 typedef struct hash_table_entry_struct hash_table_entry;
243 /* Do some typedefs so that we don't have to write "struct" so often. */
245 typedef struct def_dec_info_struct def_dec_info;
246 typedef struct file_info_struct file_info;
247 typedef struct f_list_chain_item_struct f_list_chain_item;
249 #ifndef UNPROTOIZE
250 static int is_syscalls_file PARAMS ((const file_info *));
251 static void rename_c_file PARAMS ((const hash_table_entry *));
252 static const def_dec_info *find_extern_def PARAMS ((const def_dec_info *,
253 const def_dec_info *));
254 static const def_dec_info *find_static_definition PARAMS ((const def_dec_info *));
255 static void connect_defs_and_decs PARAMS ((const hash_table_entry *));
256 static void add_local_decl PARAMS ((const def_dec_info *, const char *));
257 static void add_global_decls PARAMS ((const file_info *, const char *));
258 #endif /* ! UNPROTOIZE */
259 static int needs_to_be_converted PARAMS ((const file_info *));
260 static void visit_each_hash_node PARAMS ((const hash_table_entry *,
261 void (*)(const hash_table_entry *)));
262 static hash_table_entry *add_symbol PARAMS ((hash_table_entry *, const char *));
263 static hash_table_entry *lookup PARAMS ((hash_table_entry *, const char *));
264 static void free_def_dec PARAMS ((def_dec_info *));
265 static file_info *find_file PARAMS ((const char *, int));
266 static void reverse_def_dec_list PARAMS ((const hash_table_entry *));
267 static void edit_fn_declaration PARAMS ((const def_dec_info *, const char *));
268 static int edit_formals_lists PARAMS ((const char *, unsigned int,
269 const def_dec_info *));
270 static void edit_fn_definition PARAMS ((const def_dec_info *, const char *));
271 static void scan_for_missed_items PARAMS ((const file_info *));
272 static void edit_file PARAMS ((const hash_table_entry *));
274 /* In the struct below, note that the "_info" field has two different uses
275 depending on the type of hash table we are in (i.e. either the filenames
276 hash table or the function names hash table). In the filenames hash table
277 the info fields of the entries point to the file_info struct which is
278 associated with each filename (1 per filename). In the function names
279 hash table, the info field points to the head of a singly linked list of
280 def_dec_info entries which are all defs or decs of the function whose
281 name is pointed to by the "symbol" field. Keeping all of the defs/decs
282 for a given function name on a special list specifically for that function
283 name makes it quick and easy to find out all of the important information
284 about a given (named) function. */
286 struct hash_table_entry_struct {
287 hash_table_entry * hash_next; /* -> to secondary entries */
288 const char * symbol; /* -> to the hashed string */
289 union {
290 const def_dec_info * _ddip;
291 file_info * _fip;
292 } _info;
294 #define ddip _info._ddip
295 #define fip _info._fip
297 /* Define a type specifically for our two hash tables. */
299 typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
301 /* The following struct holds all of the important information about any
302 single filename (e.g. file) which we need to know about. */
304 struct file_info_struct {
305 const hash_table_entry * hash_entry; /* -> to associated hash entry */
306 const def_dec_info * defs_decs; /* -> to chain of defs/decs */
307 time_t mtime; /* Time of last modification. */
310 /* Due to the possibility that functions may return pointers to functions,
311 (which may themselves have their own parameter lists) and due to the
312 fact that returned pointers-to-functions may be of type "pointer-to-
313 function-returning-pointer-to-function" (ad nauseum) we have to keep
314 an entire chain of ANSI style formal parameter lists for each function.
316 Normally, for any given function, there will only be one formals list
317 on the chain, but you never know.
319 Note that the head of each chain of formals lists is pointed to by the
320 `f_list_chain' field of the corresponding def_dec_info record.
322 For any given chain, the item at the head of the chain is the *leftmost*
323 parameter list seen in the actual C language function declaration. If
324 there are other members of the chain, then these are linked in left-to-right
325 order from the head of the chain. */
327 struct f_list_chain_item_struct {
328 const f_list_chain_item * chain_next; /* -> to next item on chain */
329 const char * formals_list; /* -> to formals list string */
332 /* The following struct holds all of the important information about any
333 single function definition or declaration which we need to know about.
334 Note that for unprotoize we don't need to know very much because we
335 never even create records for stuff that we don't intend to convert
336 (like for instance defs and decs which are already in old K&R format
337 and "implicit" function declarations). */
339 struct def_dec_info_struct {
340 const def_dec_info * next_in_file; /* -> to rest of chain for file */
341 file_info * file; /* -> file_info for containing file */
342 int line; /* source line number of def/dec */
343 const char * ansi_decl; /* -> left end of ansi decl */
344 hash_table_entry * hash_entry; /* -> hash entry for function name */
345 unsigned int is_func_def; /* = 0 means this is a declaration */
346 const def_dec_info * next_for_func; /* -> to rest of chain for func name */
347 unsigned int f_list_count; /* count of formals lists we expect */
348 char prototyped; /* = 0 means already prototyped */
349 #ifndef UNPROTOIZE
350 const f_list_chain_item * f_list_chain; /* -> chain of formals lists */
351 const def_dec_info * definition; /* -> def/dec containing related def */
352 char is_static; /* = 0 means visibility is "extern" */
353 char is_implicit; /* != 0 for implicit func decl's */
354 char written; /* != 0 means written for implicit */
355 #else /* !defined (UNPROTOIZE) */
356 const char * formal_names; /* -> to list of names of formals */
357 const char * formal_decls; /* -> to string of formal declarations */
358 #endif /* !defined (UNPROTOIZE) */
361 /* Pointer to the tail component of the filename by which this program was
362 invoked. Used everywhere in error and warning messages. */
364 static const char *pname;
366 /* Error counter. Will be nonzero if we should give up at the next convenient
367 stopping point. */
369 static int errors = 0;
371 /* Option flags. */
372 /* ??? These comments should say what the flag mean as well as the options
373 that set them. */
375 /* File name to use for running gcc. Allows GCC 2 to be named
376 something other than gcc. */
377 static const char *compiler_file_name = "gcc";
379 static int version_flag = 0; /* Print our version number. */
380 static int quiet_flag = 0; /* Don't print messages normally. */
381 static int nochange_flag = 0; /* Don't convert, just say what files
382 we would have converted. */
383 static int nosave_flag = 0; /* Don't save the old version. */
384 static int keep_flag = 0; /* Don't delete the .X files. */
385 static const char ** compile_params = 0; /* Option string for gcc. */
386 #ifdef UNPROTOIZE
387 static const char *indent_string = " "; /* Indentation for newly
388 inserted parm decls. */
389 #else /* !defined (UNPROTOIZE) */
390 static int local_flag = 0; /* Insert new local decls (when?). */
391 static int global_flag = 0; /* set by -g option */
392 static int cplusplus_flag = 0; /* Rename converted files to *.C. */
393 static const char *nondefault_syscalls_dir = 0; /* Dir to look for
394 SYSCALLS.c.X in. */
395 #endif /* !defined (UNPROTOIZE) */
397 /* An index into the compile_params array where we should insert the source
398 file name when we are ready to exec the C compiler. A zero value indicates
399 that we have not yet called munge_compile_params. */
401 static int input_file_name_index = 0;
403 /* An index into the compile_params array where we should insert the filename
404 for the aux info file, when we run the C compiler. */
405 static int aux_info_file_name_index = 0;
407 /* Count of command line arguments which were "filename" arguments. */
409 static int n_base_source_files = 0;
411 /* Points to a malloc'ed list of pointers to all of the filenames of base
412 source files which were specified on the command line. */
414 static const char **base_source_filenames;
416 /* Line number of the line within the current aux_info file that we
417 are currently processing. Used for error messages in case the prototypes
418 info file is corrupted somehow. */
420 static int current_aux_info_lineno;
422 /* Pointer to the name of the source file currently being converted. */
424 static const char *convert_filename;
426 /* Pointer to relative root string (taken from aux_info file) which indicates
427 where directory the user was in when he did the compilation step that
428 produced the containing aux_info file. */
430 static const char *invocation_filename;
432 /* Pointer to the base of the input buffer that holds the original text for the
433 source file currently being converted. */
435 static const char *orig_text_base;
437 /* Pointer to the byte just beyond the end of the input buffer that holds the
438 original text for the source file currently being converted. */
440 static const char *orig_text_limit;
442 /* Pointer to the base of the input buffer that holds the cleaned text for the
443 source file currently being converted. */
445 static const char *clean_text_base;
447 /* Pointer to the byte just beyond the end of the input buffer that holds the
448 cleaned text for the source file currently being converted. */
450 static const char *clean_text_limit;
452 /* Pointer to the last byte in the cleaned text buffer that we have already
453 (virtually) copied to the output buffer (or decided to ignore). */
455 static const char * clean_read_ptr;
457 /* Pointer to the base of the output buffer that holds the replacement text
458 for the source file currently being converted. */
460 static char *repl_text_base;
462 /* Pointer to the byte just beyond the end of the output buffer that holds the
463 replacement text for the source file currently being converted. */
465 static char *repl_text_limit;
467 /* Pointer to the last byte which has been stored into the output buffer.
468 The next byte to be stored should be stored just past where this points
469 to. */
471 static char * repl_write_ptr;
473 /* Pointer into the cleaned text buffer for the source file we are currently
474 converting. This points to the first character of the line that we last
475 did a "seek_to_line" to (see below). */
477 static const char *last_known_line_start;
479 /* Number of the line (in the cleaned text buffer) that we last did a
480 "seek_to_line" to. Will be one if we just read a new source file
481 into the cleaned text buffer. */
483 static int last_known_line_number;
485 /* The filenames hash table. */
487 static hash_table filename_primary;
489 /* The function names hash table. */
491 static hash_table function_name_primary;
493 /* The place to keep the recovery address which is used only in cases where
494 we get hopelessly confused by something in the cleaned original text. */
496 static jmp_buf source_confusion_recovery;
498 /* A pointer to the current directory filename (used by abspath). */
500 static char *cwd_buffer;
502 /* A place to save the read pointer until we are sure that an individual
503 attempt at editing will succeed. */
505 static const char * saved_clean_read_ptr;
507 /* A place to save the write pointer until we are sure that an individual
508 attempt at editing will succeed. */
510 static char * saved_repl_write_ptr;
512 /* Translate and output an error message. */
513 static void
514 notice VPARAMS ((const char *msgid, ...))
516 VA_OPEN (ap, msgid);
517 VA_FIXEDARG (ap, const char *, msgid);
519 vfprintf (stderr, _(msgid), ap);
520 VA_CLOSE (ap);
524 /* Make a copy of a string INPUT with size SIZE. */
526 static char *
527 savestring (input, size)
528 const char *input;
529 unsigned int size;
531 char *output = (char *) xmalloc (size + 1);
532 strcpy (output, input);
533 return output;
536 /* More 'friendly' abort that prints the line and file.
537 config.h can #define abort fancy_abort if you like that sort of thing. */
539 void
540 fancy_abort ()
542 notice ("%s: internal abort\n", pname);
543 exit (FATAL_EXIT_CODE);
546 /* Make a duplicate of the first N bytes of a given string in a newly
547 allocated area. */
549 static char *
550 dupnstr (s, n)
551 const char *s;
552 size_t n;
554 char *ret_val = (char *) xmalloc (n + 1);
556 strncpy (ret_val, s, n);
557 ret_val[n] = '\0';
558 return ret_val;
561 /* Return a pointer to the first occurrence of s2 within s1 or NULL if s2
562 does not occur within s1. Assume neither s1 nor s2 are null pointers. */
564 static const char *
565 substr (s1, s2)
566 const char *s1;
567 const char *const s2;
569 for (; *s1 ; s1++)
571 const char *p1;
572 const char *p2;
573 int c;
575 for (p1 = s1, p2 = s2; (c = *p2); p1++, p2++)
576 if (*p1 != c)
577 goto outer;
578 return s1;
579 outer:
582 return 0;
585 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
586 retrying if necessary. Return the actual number of bytes read. */
588 static int
589 safe_read (desc, ptr, len)
590 int desc;
591 PTR ptr;
592 int len;
594 int left = len;
595 while (left > 0) {
596 int nchars = read (desc, ptr, left);
597 if (nchars < 0)
599 #ifdef EINTR
600 if (errno == EINTR)
601 continue;
602 #endif
603 return nchars;
605 if (nchars == 0)
606 break;
607 /* Arithmetic on void pointers is a gcc extension. */
608 ptr = (char *) ptr + nchars;
609 left -= nchars;
611 return len - left;
614 /* Write LEN bytes at PTR to descriptor DESC,
615 retrying if necessary, and treating any real error as fatal. */
617 static void
618 safe_write (desc, ptr, len, out_fname)
619 int desc;
620 PTR ptr;
621 int len;
622 const char *out_fname;
624 while (len > 0) {
625 int written = write (desc, ptr, len);
626 if (written < 0)
628 int errno_val = errno;
629 #ifdef EINTR
630 if (errno_val == EINTR)
631 continue;
632 #endif
633 notice ("%s: error writing file `%s': %s\n",
634 pname, shortpath (NULL, out_fname), xstrerror (errno_val));
635 return;
637 /* Arithmetic on void pointers is a gcc extension. */
638 ptr = (char *) ptr + written;
639 len -= written;
643 /* Get setup to recover in case the edit we are about to do goes awry. */
645 static void
646 save_pointers ()
648 saved_clean_read_ptr = clean_read_ptr;
649 saved_repl_write_ptr = repl_write_ptr;
652 /* Call this routine to recover our previous state whenever something looks
653 too confusing in the source code we are trying to edit. */
655 static void
656 restore_pointers ()
658 clean_read_ptr = saved_clean_read_ptr;
659 repl_write_ptr = saved_repl_write_ptr;
662 /* Return true if the given character is a valid identifier character. */
664 static int
665 is_id_char (ch)
666 int ch;
668 return (ISIDNUM (ch) || (ch == '$'));
671 /* Give a message indicating the proper way to invoke this program and then
672 exit with nonzero status. */
674 static void
675 usage ()
677 #ifdef UNPROTOIZE
678 notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
679 pname, pname);
680 #else /* !defined (UNPROTOIZE) */
681 notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
682 pname, pname);
683 #endif /* !defined (UNPROTOIZE) */
684 exit (FATAL_EXIT_CODE);
687 /* Return true if the given filename (assumed to be an absolute filename)
688 designates a file residing anywhere beneath any one of the "system"
689 include directories. */
691 static int
692 in_system_include_dir (path)
693 const char *path;
695 const struct default_include *p;
697 if (! is_abspath (path))
698 abort (); /* Must be an absolutized filename. */
700 for (p = cpp_include_defaults; p->fname; p++)
701 if (!strncmp (path, p->fname, strlen (p->fname))
702 && IS_DIR_SEPARATOR (path[strlen (p->fname)]))
703 return 1;
704 return 0;
707 #if 0
708 /* Return true if the given filename designates a file that the user has
709 read access to and for which the user has write access to the containing
710 directory. */
712 static int
713 file_could_be_converted (const char *path)
715 char *const dir_name = (char *) alloca (strlen (path) + 1);
717 if (access (path, R_OK))
718 return 0;
721 char *dir_last_slash;
723 strcpy (dir_name, path);
724 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
725 #ifdef DIR_SEPARATOR_2
727 char *slash;
729 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
730 DIR_SEPARATOR_2);
731 if (slash)
732 dir_last_slash = slash;
734 #endif
735 if (dir_last_slash)
736 *dir_last_slash = '\0';
737 else
738 abort (); /* Should have been an absolutized filename. */
741 if (access (path, W_OK))
742 return 0;
744 return 1;
747 /* Return true if the given filename designates a file that we are allowed
748 to modify. Files which we should not attempt to modify are (a) "system"
749 include files, and (b) files which the user doesn't have write access to,
750 and (c) files which reside in directories which the user doesn't have
751 write access to. Unless requested to be quiet, give warnings about
752 files that we will not try to convert for one reason or another. An
753 exception is made for "system" include files, which we never try to
754 convert and for which we don't issue the usual warnings. */
756 static int
757 file_normally_convertible (const char *path)
759 char *const dir_name = alloca (strlen (path) + 1);
761 if (in_system_include_dir (path))
762 return 0;
765 char *dir_last_slash;
767 strcpy (dir_name, path);
768 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
769 #ifdef DIR_SEPARATOR_2
771 char *slash;
773 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
774 DIR_SEPARATOR_2);
775 if (slash)
776 dir_last_slash = slash;
778 #endif
779 if (dir_last_slash)
780 *dir_last_slash = '\0';
781 else
782 abort (); /* Should have been an absolutized filename. */
785 if (access (path, R_OK))
787 if (!quiet_flag)
788 notice ("%s: warning: no read access for file `%s'\n",
789 pname, shortpath (NULL, path));
790 return 0;
793 if (access (path, W_OK))
795 if (!quiet_flag)
796 notice ("%s: warning: no write access for file `%s'\n",
797 pname, shortpath (NULL, path));
798 return 0;
801 if (access (dir_name, W_OK))
803 if (!quiet_flag)
804 notice ("%s: warning: no write access for dir containing `%s'\n",
805 pname, shortpath (NULL, path));
806 return 0;
809 return 1;
811 #endif /* 0 */
813 #ifndef UNPROTOIZE
815 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X
816 file. Return false otherwise. */
818 static int
819 is_syscalls_file (fi_p)
820 const file_info *fi_p;
822 char const *f = fi_p->hash_entry->symbol;
823 size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
824 return sysl <= fl && strcmp (f + fl - sysl, syscalls_filename) == 0;
827 #endif /* !defined (UNPROTOIZE) */
829 /* Check to see if this file will need to have anything done to it on this
830 run. If there is nothing in the given file which both needs conversion
831 and for which we have the necessary stuff to do the conversion, return
832 false. Otherwise, return true.
834 Note that (for protoize) it is only valid to call this function *after*
835 the connections between declarations and definitions have all been made
836 by connect_defs_and_decs. */
838 static int
839 needs_to_be_converted (file_p)
840 const file_info *file_p;
842 const def_dec_info *ddp;
844 #ifndef UNPROTOIZE
846 if (is_syscalls_file (file_p))
847 return 0;
849 #endif /* !defined (UNPROTOIZE) */
851 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
853 if (
855 #ifndef UNPROTOIZE
857 /* ... and if we a protoizing and this function is in old style ... */
858 !ddp->prototyped
859 /* ... and if this a definition or is a decl with an associated def ... */
860 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
862 #else /* defined (UNPROTOIZE) */
864 /* ... and if we are unprotoizing and this function is in new style ... */
865 ddp->prototyped
867 #endif /* defined (UNPROTOIZE) */
869 /* ... then the containing file needs converting. */
870 return -1;
871 return 0;
874 /* Return 1 if the file name NAME is in a directory
875 that should be converted. */
877 static int
878 directory_specified_p (name)
879 const char *name;
881 struct string_list *p;
883 for (p = directory_list; p; p = p->next)
884 if (!strncmp (name, p->name, strlen (p->name))
885 && IS_DIR_SEPARATOR (name[strlen (p->name)]))
887 const char *q = name + strlen (p->name) + 1;
889 /* If there are more slashes, it's in a subdir, so
890 this match doesn't count. */
891 while (*q++)
892 if (IS_DIR_SEPARATOR (*(q-1)))
893 goto lose;
894 return 1;
896 lose: ;
899 return 0;
902 /* Return 1 if the file named NAME should be excluded from conversion. */
904 static int
905 file_excluded_p (name)
906 const char *name;
908 struct string_list *p;
909 int len = strlen (name);
911 for (p = exclude_list; p; p = p->next)
912 if (!strcmp (name + len - strlen (p->name), p->name)
913 && IS_DIR_SEPARATOR (name[len - strlen (p->name) - 1]))
914 return 1;
916 return 0;
919 /* Construct a new element of a string_list.
920 STRING is the new element value, and REST holds the remaining elements. */
922 static struct string_list *
923 string_list_cons (string, rest)
924 const char *string;
925 struct string_list *rest;
927 struct string_list *temp
928 = (struct string_list *) xmalloc (sizeof (struct string_list));
930 temp->next = rest;
931 temp->name = string;
932 return temp;
935 /* ??? The GNU convention for mentioning function args in its comments
936 is to capitalize them. So change "hash_tab_p" to HASH_TAB_P below.
937 Likewise for all the other functions. */
939 /* Given a hash table, apply some function to each node in the table. The
940 table to traverse is given as the "hash_tab_p" argument, and the
941 function to be applied to each node in the table is given as "func"
942 argument. */
944 static void
945 visit_each_hash_node (hash_tab_p, func)
946 const hash_table_entry *hash_tab_p;
947 void (*func) PARAMS ((const hash_table_entry *));
949 const hash_table_entry *primary;
951 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
952 if (primary->symbol)
954 hash_table_entry *second;
956 (*func)(primary);
957 for (second = primary->hash_next; second; second = second->hash_next)
958 (*func) (second);
962 /* Initialize all of the fields of a new hash table entry, pointed
963 to by the "p" parameter. Note that the space to hold the entry
964 is assumed to have already been allocated before this routine is
965 called. */
967 static hash_table_entry *
968 add_symbol (p, s)
969 hash_table_entry *p;
970 const char *s;
972 p->hash_next = NULL;
973 p->symbol = xstrdup (s);
974 p->ddip = NULL;
975 p->fip = NULL;
976 return p;
979 /* Look for a particular function name or filename in the particular
980 hash table indicated by "hash_tab_p". If the name is not in the
981 given hash table, add it. Either way, return a pointer to the
982 hash table entry for the given name. */
984 static hash_table_entry *
985 lookup (hash_tab_p, search_symbol)
986 hash_table_entry *hash_tab_p;
987 const char *search_symbol;
989 int hash_value = 0;
990 const char *search_symbol_char_p = search_symbol;
991 hash_table_entry *p;
993 while (*search_symbol_char_p)
994 hash_value += *search_symbol_char_p++;
995 hash_value &= hash_mask;
996 p = &hash_tab_p[hash_value];
997 if (! p->symbol)
998 return add_symbol (p, search_symbol);
999 if (!strcmp (p->symbol, search_symbol))
1000 return p;
1001 while (p->hash_next)
1003 p = p->hash_next;
1004 if (!strcmp (p->symbol, search_symbol))
1005 return p;
1007 p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry));
1008 p = p->hash_next;
1009 return add_symbol (p, search_symbol);
1012 /* Throw a def/dec record on the junk heap.
1014 Also, since we are not using this record anymore, free up all of the
1015 stuff it pointed to. */
1017 static void
1018 free_def_dec (p)
1019 def_dec_info *p;
1021 free ((NONCONST PTR) p->ansi_decl);
1023 #ifndef UNPROTOIZE
1025 const f_list_chain_item * curr;
1026 const f_list_chain_item * next;
1028 for (curr = p->f_list_chain; curr; curr = next)
1030 next = curr->chain_next;
1031 free ((NONCONST PTR) curr);
1034 #endif /* !defined (UNPROTOIZE) */
1036 free (p);
1039 /* Unexpand as many macro symbol as we can find.
1041 If the given line must be unexpanded, make a copy of it in the heap and
1042 return a pointer to the unexpanded copy. Otherwise return NULL. */
1044 static char *
1045 unexpand_if_needed (aux_info_line)
1046 const char *aux_info_line;
1048 static char *line_buf = 0;
1049 static int line_buf_size = 0;
1050 const unexpansion *unexp_p;
1051 int got_unexpanded = 0;
1052 const char *s;
1053 char *copy_p = line_buf;
1055 if (line_buf == 0)
1057 line_buf_size = 1024;
1058 line_buf = (char *) xmalloc (line_buf_size);
1061 copy_p = line_buf;
1063 /* Make a copy of the input string in line_buf, expanding as necessary. */
1065 for (s = aux_info_line; *s != '\n'; )
1067 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
1069 const char *in_p = unexp_p->expanded;
1070 size_t len = strlen (in_p);
1072 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1074 int size = strlen (unexp_p->contracted);
1075 got_unexpanded = 1;
1076 if (copy_p + size - line_buf >= line_buf_size)
1078 int offset = copy_p - line_buf;
1079 line_buf_size *= 2;
1080 line_buf_size += size;
1081 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1082 copy_p = line_buf + offset;
1084 strcpy (copy_p, unexp_p->contracted);
1085 copy_p += size;
1087 /* Assume that there will not be another replacement required
1088 within the text just replaced. */
1090 s += len;
1091 goto continue_outer;
1094 if (copy_p - line_buf == line_buf_size)
1096 int offset = copy_p - line_buf;
1097 line_buf_size *= 2;
1098 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1099 copy_p = line_buf + offset;
1101 *copy_p++ = *s++;
1102 continue_outer: ;
1104 if (copy_p + 2 - line_buf >= line_buf_size)
1106 int offset = copy_p - line_buf;
1107 line_buf_size *= 2;
1108 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1109 copy_p = line_buf + offset;
1111 *copy_p++ = '\n';
1112 *copy_p = '\0';
1114 return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
1117 /* Return 1 if pathname is absolute. */
1119 static int
1120 is_abspath (path)
1121 const char *path;
1123 return (IS_DIR_SEPARATOR (path[0])
1124 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1125 /* Check for disk name on MS-DOS-based systems. */
1126 || (path[0] && path[1] == ':' && IS_DIR_SEPARATOR (path[2]))
1127 #endif
1131 /* Return the absolutized filename for the given relative
1132 filename. Note that if that filename is already absolute, it may
1133 still be returned in a modified form because this routine also
1134 eliminates redundant slashes and single dots and eliminates double
1135 dots to get a shortest possible filename from the given input
1136 filename. The absolutization of relative filenames is made by
1137 assuming that the given filename is to be taken as relative to
1138 the first argument (cwd) or to the current directory if cwd is
1139 NULL. */
1141 static char *
1142 abspath (cwd, rel_filename)
1143 const char *cwd;
1144 const char *rel_filename;
1146 /* Setup the current working directory as needed. */
1147 const char *const cwd2 = (cwd) ? cwd : cwd_buffer;
1148 char *const abs_buffer
1149 = (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 2);
1150 char *endp = abs_buffer;
1151 char *outp, *inp;
1153 /* Copy the filename (possibly preceded by the current working
1154 directory name) into the absolutization buffer. */
1157 const char *src_p;
1159 if (! is_abspath (rel_filename))
1161 src_p = cwd2;
1162 while ((*endp++ = *src_p++))
1163 continue;
1164 *(endp-1) = DIR_SEPARATOR; /* overwrite null */
1166 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1167 else if (IS_DIR_SEPARATOR (rel_filename[0]))
1169 /* A path starting with a directory separator is considered absolute
1170 for dos based filesystems, but it's really not -- it's just the
1171 convention used throughout GCC and it works. However, in this
1172 case, we still need to prepend the drive spec from cwd_buffer. */
1173 *endp++ = cwd2[0];
1174 *endp++ = cwd2[1];
1176 #endif
1177 src_p = rel_filename;
1178 while ((*endp++ = *src_p++))
1179 continue;
1182 /* Now make a copy of abs_buffer into abs_buffer, shortening the
1183 filename (by taking out slashes and dots) as we go. */
1185 outp = inp = abs_buffer;
1186 *outp++ = *inp++; /* copy first slash */
1187 #if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
1188 if (IS_DIR_SEPARATOR (inp[0]))
1189 *outp++ = *inp++; /* copy second slash */
1190 #endif
1191 for (;;)
1193 if (!inp[0])
1194 break;
1195 else if (IS_DIR_SEPARATOR (inp[0]) && IS_DIR_SEPARATOR (outp[-1]))
1197 inp++;
1198 continue;
1200 else if (inp[0] == '.' && IS_DIR_SEPARATOR (outp[-1]))
1202 if (!inp[1])
1203 break;
1204 else if (IS_DIR_SEPARATOR (inp[1]))
1206 inp += 2;
1207 continue;
1209 else if ((inp[1] == '.') && (inp[2] == 0
1210 || IS_DIR_SEPARATOR (inp[2])))
1212 inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2;
1213 outp -= 2;
1214 while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*outp))
1215 outp--;
1216 if (outp < abs_buffer)
1218 /* Catch cases like /.. where we try to backup to a
1219 point above the absolute root of the logical file
1220 system. */
1222 notice ("%s: invalid file name: %s\n",
1223 pname, rel_filename);
1224 exit (FATAL_EXIT_CODE);
1226 *++outp = '\0';
1227 continue;
1230 *outp++ = *inp++;
1233 /* On exit, make sure that there is a trailing null, and make sure that
1234 the last character of the returned string is *not* a slash. */
1236 *outp = '\0';
1237 if (IS_DIR_SEPARATOR (outp[-1]))
1238 *--outp = '\0';
1240 /* Make a copy (in the heap) of the stuff left in the absolutization
1241 buffer and return a pointer to the copy. */
1243 return savestring (abs_buffer, outp - abs_buffer);
1246 /* Given a filename (and possibly a directory name from which the filename
1247 is relative) return a string which is the shortest possible
1248 equivalent for the corresponding full (absolutized) filename. The
1249 shortest possible equivalent may be constructed by converting the
1250 absolutized filename to be a relative filename (i.e. relative to
1251 the actual current working directory). However if a relative filename
1252 is longer, then the full absolute filename is returned.
1254 KNOWN BUG:
1256 Note that "simple-minded" conversion of any given type of filename (either
1257 relative or absolute) may not result in a valid equivalent filename if any
1258 subpart of the original filename is actually a symbolic link. */
1260 static const char *
1261 shortpath (cwd, filename)
1262 const char *cwd;
1263 const char *filename;
1265 char *rel_buffer;
1266 char *rel_buf_p;
1267 char *cwd_p = cwd_buffer;
1268 char *path_p;
1269 int unmatched_slash_count = 0;
1270 size_t filename_len = strlen (filename);
1272 path_p = abspath (cwd, filename);
1273 rel_buf_p = rel_buffer = (char *) xmalloc (filename_len);
1275 while (*cwd_p && IS_SAME_PATH_CHAR (*cwd_p, *path_p))
1277 cwd_p++;
1278 path_p++;
1280 if (!*cwd_p && (!*path_p || IS_DIR_SEPARATOR (*path_p)))
1282 /* whole pwd matched */
1283 if (!*path_p) /* input *is* the current path! */
1284 return ".";
1285 else
1286 return ++path_p;
1288 else
1290 if (*path_p)
1292 --cwd_p;
1293 --path_p;
1294 while (! IS_DIR_SEPARATOR (*cwd_p)) /* backup to last slash */
1296 --cwd_p;
1297 --path_p;
1299 cwd_p++;
1300 path_p++;
1301 unmatched_slash_count++;
1304 /* Find out how many directory levels in cwd were *not* matched. */
1305 while (*cwd_p++)
1306 if (IS_DIR_SEPARATOR (*(cwd_p-1)))
1307 unmatched_slash_count++;
1309 /* Now we know how long the "short name" will be.
1310 Reject it if longer than the input. */
1311 if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
1312 return filename;
1314 /* For each of them, put a `../' at the beginning of the short name. */
1315 while (unmatched_slash_count--)
1317 /* Give up if the result gets to be longer
1318 than the absolute path name. */
1319 if (rel_buffer + filename_len <= rel_buf_p + 3)
1320 return filename;
1321 *rel_buf_p++ = '.';
1322 *rel_buf_p++ = '.';
1323 *rel_buf_p++ = DIR_SEPARATOR;
1326 /* Then tack on the unmatched part of the desired file's name. */
1329 if (rel_buffer + filename_len <= rel_buf_p)
1330 return filename;
1332 while ((*rel_buf_p++ = *path_p++));
1334 --rel_buf_p;
1335 if (IS_DIR_SEPARATOR (*(rel_buf_p-1)))
1336 *--rel_buf_p = '\0';
1337 return rel_buffer;
1341 /* Lookup the given filename in the hash table for filenames. If it is a
1342 new one, then the hash table info pointer will be null. In this case,
1343 we create a new file_info record to go with the filename, and we initialize
1344 that record with some reasonable values. */
1346 /* FILENAME was const, but that causes a warning on AIX when calling stat.
1347 That is probably a bug in AIX, but might as well avoid the warning. */
1349 static file_info *
1350 find_file (filename, do_not_stat)
1351 const char *filename;
1352 int do_not_stat;
1354 hash_table_entry *hash_entry_p;
1356 hash_entry_p = lookup (filename_primary, filename);
1357 if (hash_entry_p->fip)
1358 return hash_entry_p->fip;
1359 else
1361 struct stat stat_buf;
1362 file_info *file_p = (file_info *) xmalloc (sizeof (file_info));
1364 /* If we cannot get status on any given source file, give a warning
1365 and then just set its time of last modification to infinity. */
1367 if (do_not_stat)
1368 stat_buf.st_mtime = (time_t) 0;
1369 else
1371 if (stat (filename, &stat_buf) == -1)
1373 int errno_val = errno;
1374 notice ("%s: %s: can't get status: %s\n",
1375 pname, shortpath (NULL, filename),
1376 xstrerror (errno_val));
1377 stat_buf.st_mtime = (time_t) -1;
1381 hash_entry_p->fip = file_p;
1382 file_p->hash_entry = hash_entry_p;
1383 file_p->defs_decs = NULL;
1384 file_p->mtime = stat_buf.st_mtime;
1385 return file_p;
1389 /* Generate a fatal error because some part of the aux_info file is
1390 messed up. */
1392 static void
1393 aux_info_corrupted ()
1395 notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
1396 pname, current_aux_info_lineno);
1397 exit (FATAL_EXIT_CODE);
1400 /* ??? This comment is vague. Say what the condition is for. */
1401 /* Check to see that a condition is true. This is kind of like an assert. */
1403 static void
1404 check_aux_info (cond)
1405 int cond;
1407 if (! cond)
1408 aux_info_corrupted ();
1411 /* Given a pointer to the closing right parenthesis for a particular formals
1412 list (in an aux_info file) find the corresponding left parenthesis and
1413 return a pointer to it. */
1415 static const char *
1416 find_corresponding_lparen (p)
1417 const char *p;
1419 const char *q;
1420 int paren_depth;
1422 for (paren_depth = 1, q = p-1; paren_depth; q--)
1424 switch (*q)
1426 case ')':
1427 paren_depth++;
1428 break;
1429 case '(':
1430 paren_depth--;
1431 break;
1434 return ++q;
1437 /* Given a line from an aux info file, and a time at which the aux info
1438 file it came from was created, check to see if the item described in
1439 the line comes from a file which has been modified since the aux info
1440 file was created. If so, return nonzero, else return zero. */
1442 static int
1443 referenced_file_is_newer (l, aux_info_mtime)
1444 const char *l;
1445 time_t aux_info_mtime;
1447 const char *p;
1448 file_info *fi_p;
1449 char *filename;
1451 check_aux_info (l[0] == '/');
1452 check_aux_info (l[1] == '*');
1453 check_aux_info (l[2] == ' ');
1456 const char *filename_start = p = l + 3;
1458 while (*p != ':'
1459 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1460 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1461 #endif
1463 p++;
1464 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1465 strncpy (filename, filename_start, (size_t) (p - filename_start));
1466 filename[p-filename_start] = '\0';
1469 /* Call find_file to find the file_info record associated with the file
1470 which contained this particular def or dec item. Note that this call
1471 may cause a new file_info record to be created if this is the first time
1472 that we have ever known about this particular file. */
1474 fi_p = find_file (abspath (invocation_filename, filename), 0);
1476 return (fi_p->mtime > aux_info_mtime);
1479 /* Given a line of info from the aux_info file, create a new
1480 def_dec_info record to remember all of the important information about
1481 a function definition or declaration.
1483 Link this record onto the list of such records for the particular file in
1484 which it occurred in proper (descending) line number order (for now).
1486 If there is an identical record already on the list for the file, throw
1487 this one away. Doing so takes care of the (useless and troublesome)
1488 duplicates which are bound to crop up due to multiple inclusions of any
1489 given individual header file.
1491 Finally, link the new def_dec record onto the list of such records
1492 pertaining to this particular function name. */
1494 static void
1495 save_def_or_dec (l, is_syscalls)
1496 const char *l;
1497 int is_syscalls;
1499 const char *p;
1500 const char *semicolon_p;
1501 def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info));
1503 #ifndef UNPROTOIZE
1504 def_dec_p->written = 0;
1505 #endif /* !defined (UNPROTOIZE) */
1507 /* Start processing the line by picking off 5 pieces of information from
1508 the left hand end of the line. These are filename, line number,
1509 new/old/implicit flag (new = ANSI prototype format), definition or
1510 declaration flag, and extern/static flag). */
1512 check_aux_info (l[0] == '/');
1513 check_aux_info (l[1] == '*');
1514 check_aux_info (l[2] == ' ');
1517 const char *filename_start = p = l + 3;
1518 char *filename;
1520 while (*p != ':'
1521 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1522 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1523 #endif
1525 p++;
1526 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1527 strncpy (filename, filename_start, (size_t) (p - filename_start));
1528 filename[p-filename_start] = '\0';
1530 /* Call find_file to find the file_info record associated with the file
1531 which contained this particular def or dec item. Note that this call
1532 may cause a new file_info record to be created if this is the first time
1533 that we have ever known about this particular file.
1535 Note that we started out by forcing all of the base source file names
1536 (i.e. the names of the aux_info files with the .X stripped off) into the
1537 filenames hash table, and we simultaneously setup file_info records for
1538 all of these base file names (even if they may be useless later).
1539 The file_info records for all of these "base" file names (properly)
1540 act as file_info records for the "original" (i.e. un-included) files
1541 which were submitted to gcc for compilation (when the -aux-info
1542 option was used). */
1544 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1548 const char *line_number_start = ++p;
1549 char line_number[10];
1551 while (*p != ':'
1552 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1553 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1554 #endif
1556 p++;
1557 strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1558 line_number[p-line_number_start] = '\0';
1559 def_dec_p->line = atoi (line_number);
1562 /* Check that this record describes a new-style, old-style, or implicit
1563 definition or declaration. */
1565 p++; /* Skip over the `:'. */
1566 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1568 /* Is this a new style (ANSI prototyped) definition or declaration? */
1570 def_dec_p->prototyped = (*p == 'N');
1572 #ifndef UNPROTOIZE
1574 /* Is this an implicit declaration? */
1576 def_dec_p->is_implicit = (*p == 'I');
1578 #endif /* !defined (UNPROTOIZE) */
1580 p++;
1582 check_aux_info ((*p == 'C') || (*p == 'F'));
1584 /* Is this item a function definition (F) or a declaration (C). Note that
1585 we treat item taken from the syscalls file as though they were function
1586 definitions regardless of what the stuff in the file says. */
1588 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1590 #ifndef UNPROTOIZE
1591 def_dec_p->definition = 0; /* Fill this in later if protoizing. */
1592 #endif /* !defined (UNPROTOIZE) */
1594 check_aux_info (*p++ == ' ');
1595 check_aux_info (*p++ == '*');
1596 check_aux_info (*p++ == '/');
1597 check_aux_info (*p++ == ' ');
1599 #ifdef UNPROTOIZE
1600 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1601 #else /* !defined (UNPROTOIZE) */
1602 if (!strncmp (p, "static", 6))
1603 def_dec_p->is_static = -1;
1604 else if (!strncmp (p, "extern", 6))
1605 def_dec_p->is_static = 0;
1606 else
1607 check_aux_info (0); /* Didn't find either `extern' or `static'. */
1608 #endif /* !defined (UNPROTOIZE) */
1611 const char *ansi_start = p;
1613 p += 6; /* Pass over the "static" or "extern". */
1615 /* We are now past the initial stuff. Search forward from here to find
1616 the terminating semicolon that should immediately follow the entire
1617 ANSI format function declaration. */
1619 while (*++p != ';')
1620 continue;
1622 semicolon_p = p;
1624 /* Make a copy of the ansi declaration part of the line from the aux_info
1625 file. */
1627 def_dec_p->ansi_decl
1628 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1630 /* Backup and point at the final right paren of the final argument list. */
1632 p--;
1634 #ifndef UNPROTOIZE
1635 def_dec_p->f_list_chain = NULL;
1636 #endif /* !defined (UNPROTOIZE) */
1638 while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
1639 if (*p != ')')
1641 free_def_dec (def_dec_p);
1642 return;
1646 /* Now isolate a whole set of formal argument lists, one-by-one. Normally,
1647 there will only be one list to isolate, but there could be more. */
1649 def_dec_p->f_list_count = 0;
1651 for (;;)
1653 const char *left_paren_p = find_corresponding_lparen (p);
1654 #ifndef UNPROTOIZE
1656 f_list_chain_item *cip
1657 = (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
1659 cip->formals_list
1660 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1662 /* Add the new chain item at the head of the current list. */
1664 cip->chain_next = def_dec_p->f_list_chain;
1665 def_dec_p->f_list_chain = cip;
1667 #endif /* !defined (UNPROTOIZE) */
1668 def_dec_p->f_list_count++;
1670 p = left_paren_p - 2;
1672 /* p must now point either to another right paren, or to the last
1673 character of the name of the function that was declared/defined.
1674 If p points to another right paren, then this indicates that we
1675 are dealing with multiple formals lists. In that case, there
1676 really should be another right paren preceding this right paren. */
1678 if (*p != ')')
1679 break;
1680 else
1681 check_aux_info (*--p == ')');
1686 const char *past_fn = p + 1;
1688 check_aux_info (*past_fn == ' ');
1690 /* Scan leftwards over the identifier that names the function. */
1692 while (is_id_char (*p))
1693 p--;
1694 p++;
1696 /* p now points to the leftmost character of the function name. */
1699 char *fn_string = (char *) alloca (past_fn - p + 1);
1701 strncpy (fn_string, p, (size_t) (past_fn - p));
1702 fn_string[past_fn-p] = '\0';
1703 def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1707 /* Look at all of the defs and decs for this function name that we have
1708 collected so far. If there is already one which is at the same
1709 line number in the same file, then we can discard this new def_dec_info
1710 record.
1712 As an extra assurance that any such pair of (nominally) identical
1713 function declarations are in fact identical, we also compare the
1714 ansi_decl parts of the lines from the aux_info files just to be on
1715 the safe side.
1717 This comparison will fail if (for instance) the user was playing
1718 messy games with the preprocessor which ultimately causes one
1719 function declaration in one header file to look differently when
1720 that file is included by two (or more) other files. */
1723 const def_dec_info *other;
1725 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1727 if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1729 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1731 notice ("%s:%d: declaration of function `%s' takes different forms\n",
1732 def_dec_p->file->hash_entry->symbol,
1733 def_dec_p->line,
1734 def_dec_p->hash_entry->symbol);
1735 exit (FATAL_EXIT_CODE);
1737 free_def_dec (def_dec_p);
1738 return;
1743 #ifdef UNPROTOIZE
1745 /* If we are doing unprotoizing, we must now setup the pointers that will
1746 point to the K&R name list and to the K&R argument declarations list.
1748 Note that if this is only a function declaration, then we should not
1749 expect to find any K&R style formals list following the ANSI-style
1750 formals list. This is because GCC knows that such information is
1751 useless in the case of function declarations (function definitions
1752 are a different story however).
1754 Since we are unprotoizing, we don't need any such lists anyway.
1755 All we plan to do is to delete all characters between ()'s in any
1756 case. */
1758 def_dec_p->formal_names = NULL;
1759 def_dec_p->formal_decls = NULL;
1761 if (def_dec_p->is_func_def)
1763 p = semicolon_p;
1764 check_aux_info (*++p == ' ');
1765 check_aux_info (*++p == '/');
1766 check_aux_info (*++p == '*');
1767 check_aux_info (*++p == ' ');
1768 check_aux_info (*++p == '(');
1771 const char *kr_names_start = ++p; /* Point just inside '('. */
1773 while (*p++ != ')')
1774 continue;
1775 p--; /* point to closing right paren */
1777 /* Make a copy of the K&R parameter names list. */
1779 def_dec_p->formal_names
1780 = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1783 check_aux_info (*++p == ' ');
1784 p++;
1786 /* p now points to the first character of the K&R style declarations
1787 list (if there is one) or to the star-slash combination that ends
1788 the comment in which such lists get embedded. */
1790 /* Make a copy of the K&R formal decls list and set the def_dec record
1791 to point to it. */
1793 if (*p == '*') /* Are there no K&R declarations? */
1795 check_aux_info (*++p == '/');
1796 def_dec_p->formal_decls = "";
1798 else
1800 const char *kr_decls_start = p;
1802 while (p[0] != '*' || p[1] != '/')
1803 p++;
1804 p--;
1806 check_aux_info (*p == ' ');
1808 def_dec_p->formal_decls
1809 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1812 /* Handle a special case. If we have a function definition marked as
1813 being in "old" style, and if its formal names list is empty, then
1814 it may actually have the string "void" in its real formals list
1815 in the original source code. Just to make sure, we will get setup
1816 to convert such things anyway.
1818 This kludge only needs to be here because of an insurmountable
1819 problem with generating .X files. */
1821 if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1822 def_dec_p->prototyped = 1;
1825 /* Since we are unprotoizing, if this item is already in old (K&R) style,
1826 we can just ignore it. If that is true, throw away the itme now. */
1828 if (!def_dec_p->prototyped)
1830 free_def_dec (def_dec_p);
1831 return;
1834 #endif /* defined (UNPROTOIZE) */
1836 /* Add this record to the head of the list of records pertaining to this
1837 particular function name. */
1839 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1840 def_dec_p->hash_entry->ddip = def_dec_p;
1842 /* Add this new def_dec_info record to the sorted list of def_dec_info
1843 records for this file. Note that we don't have to worry about duplicates
1844 (caused by multiple inclusions of header files) here because we have
1845 already eliminated duplicates above. */
1847 if (!def_dec_p->file->defs_decs)
1849 def_dec_p->file->defs_decs = def_dec_p;
1850 def_dec_p->next_in_file = NULL;
1852 else
1854 int line = def_dec_p->line;
1855 const def_dec_info *prev = NULL;
1856 const def_dec_info *curr = def_dec_p->file->defs_decs;
1857 const def_dec_info *next = curr->next_in_file;
1859 while (next && (line < curr->line))
1861 prev = curr;
1862 curr = next;
1863 next = next->next_in_file;
1865 if (line >= curr->line)
1867 def_dec_p->next_in_file = curr;
1868 if (prev)
1869 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1870 else
1871 def_dec_p->file->defs_decs = def_dec_p;
1873 else /* assert (next == NULL); */
1875 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
1876 /* assert (next == NULL); */
1877 def_dec_p->next_in_file = next;
1882 /* Set up the vector COMPILE_PARAMS which is the argument list for running GCC.
1883 Also set input_file_name_index and aux_info_file_name_index
1884 to the indices of the slots where the file names should go. */
1886 /* We initialize the vector by removing -g, -O, -S, -c, and -o options,
1887 and adding '-aux-info AUXFILE -S -o /dev/null INFILE' at the end. */
1889 static void
1890 munge_compile_params (params_list)
1891 const char *params_list;
1893 /* Build up the contents in a temporary vector
1894 that is so big that to has to be big enough. */
1895 const char **temp_params
1896 = (const char **) alloca ((strlen (params_list) + 8) * sizeof (char *));
1897 int param_count = 0;
1898 const char *param;
1899 struct stat st;
1901 temp_params[param_count++] = compiler_file_name;
1902 for (;;)
1904 while (ISSPACE ((const unsigned char)*params_list))
1905 params_list++;
1906 if (!*params_list)
1907 break;
1908 param = params_list;
1909 while (*params_list && !ISSPACE ((const unsigned char)*params_list))
1910 params_list++;
1911 if (param[0] != '-')
1912 temp_params[param_count++]
1913 = dupnstr (param, (size_t) (params_list - param));
1914 else
1916 switch (param[1])
1918 case 'g':
1919 case 'O':
1920 case 'S':
1921 case 'c':
1922 break; /* Don't copy these. */
1923 case 'o':
1924 while (ISSPACE ((const unsigned char)*params_list))
1925 params_list++;
1926 while (*params_list
1927 && !ISSPACE ((const unsigned char)*params_list))
1928 params_list++;
1929 break;
1930 default:
1931 temp_params[param_count++]
1932 = dupnstr (param, (size_t) (params_list - param));
1935 if (!*params_list)
1936 break;
1938 temp_params[param_count++] = "-aux-info";
1940 /* Leave room for the aux-info file name argument. */
1941 aux_info_file_name_index = param_count;
1942 temp_params[param_count++] = NULL;
1944 temp_params[param_count++] = "-S";
1945 temp_params[param_count++] = "-o";
1947 if ((stat (HOST_BIT_BUCKET, &st) == 0)
1948 && (!S_ISDIR (st.st_mode))
1949 && (access (HOST_BIT_BUCKET, W_OK) == 0))
1950 temp_params[param_count++] = HOST_BIT_BUCKET;
1951 else
1952 /* FIXME: This is hardly likely to be right, if HOST_BIT_BUCKET is not
1953 writable. But until this is rejigged to use make_temp_file(), this
1954 is the best we can do. */
1955 temp_params[param_count++] = "/dev/null";
1957 /* Leave room for the input file name argument. */
1958 input_file_name_index = param_count;
1959 temp_params[param_count++] = NULL;
1960 /* Terminate the list. */
1961 temp_params[param_count++] = NULL;
1963 /* Make a copy of the compile_params in heap space. */
1965 compile_params
1966 = (const char **) xmalloc (sizeof (char *) * (param_count+1));
1967 memcpy (compile_params, temp_params, sizeof (char *) * param_count);
1970 /* Do a recompilation for the express purpose of generating a new aux_info
1971 file to go with a specific base source file.
1973 The result is a boolean indicating success. */
1975 static int
1976 gen_aux_info_file (base_filename)
1977 const char *base_filename;
1979 if (!input_file_name_index)
1980 munge_compile_params ("");
1982 /* Store the full source file name in the argument vector. */
1983 compile_params[input_file_name_index] = shortpath (NULL, base_filename);
1984 /* Add .X to source file name to get aux-info file name. */
1985 compile_params[aux_info_file_name_index] =
1986 concat (compile_params[input_file_name_index], aux_info_suffix, NULL);
1988 if (!quiet_flag)
1989 notice ("%s: compiling `%s'\n",
1990 pname, compile_params[input_file_name_index]);
1993 char *errmsg_fmt, *errmsg_arg;
1994 int wait_status, pid;
1996 pid = pexecute (compile_params[0], (char * const *) compile_params,
1997 pname, NULL, &errmsg_fmt, &errmsg_arg,
1998 PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
2000 if (pid == -1)
2002 int errno_val = errno;
2003 fprintf (stderr, "%s: ", pname);
2004 fprintf (stderr, errmsg_fmt, errmsg_arg);
2005 fprintf (stderr, ": %s\n", xstrerror (errno_val));
2006 return 0;
2009 pid = pwait (pid, &wait_status, 0);
2010 if (pid == -1)
2012 notice ("%s: wait: %s\n", pname, xstrerror (errno));
2013 return 0;
2015 if (WIFSIGNALED (wait_status))
2017 notice ("%s: subprocess got fatal signal %d\n",
2018 pname, WTERMSIG (wait_status));
2019 return 0;
2021 if (WIFEXITED (wait_status))
2023 if (WEXITSTATUS (wait_status) != 0)
2025 notice ("%s: %s exited with status %d\n",
2026 pname, compile_params[0], WEXITSTATUS (wait_status));
2027 return 0;
2029 return 1;
2031 abort ();
2035 /* Read in all of the information contained in a single aux_info file.
2036 Save all of the important stuff for later. */
2038 static void
2039 process_aux_info_file (base_source_filename, keep_it, is_syscalls)
2040 const char *base_source_filename;
2041 int keep_it;
2042 int is_syscalls;
2044 size_t base_len = strlen (base_source_filename);
2045 char * aux_info_filename
2046 = (char *) alloca (base_len + strlen (aux_info_suffix) + 1);
2047 char *aux_info_base;
2048 char *aux_info_limit;
2049 char *aux_info_relocated_name;
2050 const char *aux_info_second_line;
2051 time_t aux_info_mtime;
2052 size_t aux_info_size;
2053 int must_create;
2055 /* Construct the aux_info filename from the base source filename. */
2057 strcpy (aux_info_filename, base_source_filename);
2058 strcat (aux_info_filename, aux_info_suffix);
2060 /* Check that the aux_info file exists and is readable. If it does not
2061 exist, try to create it (once only). */
2063 /* If file doesn't exist, set must_create.
2064 Likewise if it exists and we can read it but it is obsolete.
2065 Otherwise, report an error. */
2066 must_create = 0;
2068 /* Come here with must_create set to 1 if file is out of date. */
2069 start_over: ;
2071 if (access (aux_info_filename, R_OK) == -1)
2073 if (errno == ENOENT)
2075 if (is_syscalls)
2077 notice ("%s: warning: missing SYSCALLS file `%s'\n",
2078 pname, aux_info_filename);
2079 return;
2081 must_create = 1;
2083 else
2085 int errno_val = errno;
2086 notice ("%s: can't read aux info file `%s': %s\n",
2087 pname, shortpath (NULL, aux_info_filename),
2088 xstrerror (errno_val));
2089 errors++;
2090 return;
2093 #if 0 /* There is code farther down to take care of this. */
2094 else
2096 struct stat s1, s2;
2097 stat (aux_info_file_name, &s1);
2098 stat (base_source_file_name, &s2);
2099 if (s2.st_mtime > s1.st_mtime)
2100 must_create = 1;
2102 #endif /* 0 */
2104 /* If we need a .X file, create it, and verify we can read it. */
2105 if (must_create)
2107 if (!gen_aux_info_file (base_source_filename))
2109 errors++;
2110 return;
2112 if (access (aux_info_filename, R_OK) == -1)
2114 int errno_val = errno;
2115 notice ("%s: can't read aux info file `%s': %s\n",
2116 pname, shortpath (NULL, aux_info_filename),
2117 xstrerror (errno_val));
2118 errors++;
2119 return;
2124 struct stat stat_buf;
2126 /* Get some status information about this aux_info file. */
2128 if (stat (aux_info_filename, &stat_buf) == -1)
2130 int errno_val = errno;
2131 notice ("%s: can't get status of aux info file `%s': %s\n",
2132 pname, shortpath (NULL, aux_info_filename),
2133 xstrerror (errno_val));
2134 errors++;
2135 return;
2138 /* Check on whether or not this aux_info file is zero length. If it is,
2139 then just ignore it and return. */
2141 if ((aux_info_size = stat_buf.st_size) == 0)
2142 return;
2144 /* Get the date/time of last modification for this aux_info file and
2145 remember it. We will have to check that any source files that it
2146 contains information about are at least this old or older. */
2148 aux_info_mtime = stat_buf.st_mtime;
2150 if (!is_syscalls)
2152 /* Compare mod time with the .c file; update .X file if obsolete.
2153 The code later on can fail to check the .c file
2154 if it did not directly define any functions. */
2156 if (stat (base_source_filename, &stat_buf) == -1)
2158 int errno_val = errno;
2159 notice ("%s: can't get status of aux info file `%s': %s\n",
2160 pname, shortpath (NULL, base_source_filename),
2161 xstrerror (errno_val));
2162 errors++;
2163 return;
2165 if (stat_buf.st_mtime > aux_info_mtime)
2167 must_create = 1;
2168 goto start_over;
2174 int aux_info_file;
2175 int fd_flags;
2177 /* Open the aux_info file. */
2179 fd_flags = O_RDONLY;
2180 #ifdef O_BINARY
2181 /* Use binary mode to avoid having to deal with different EOL characters. */
2182 fd_flags |= O_BINARY;
2183 #endif
2184 if ((aux_info_file = open (aux_info_filename, fd_flags, 0444 )) == -1)
2186 int errno_val = errno;
2187 notice ("%s: can't open aux info file `%s' for reading: %s\n",
2188 pname, shortpath (NULL, aux_info_filename),
2189 xstrerror (errno_val));
2190 return;
2193 /* Allocate space to hold the aux_info file in memory. */
2195 aux_info_base = xmalloc (aux_info_size + 1);
2196 aux_info_limit = aux_info_base + aux_info_size;
2197 *aux_info_limit = '\0';
2199 /* Read the aux_info file into memory. */
2201 if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
2202 (int) aux_info_size)
2204 int errno_val = errno;
2205 notice ("%s: error reading aux info file `%s': %s\n",
2206 pname, shortpath (NULL, aux_info_filename),
2207 xstrerror (errno_val));
2208 free (aux_info_base);
2209 close (aux_info_file);
2210 return;
2213 /* Close the aux info file. */
2215 if (close (aux_info_file))
2217 int errno_val = errno;
2218 notice ("%s: error closing aux info file `%s': %s\n",
2219 pname, shortpath (NULL, aux_info_filename),
2220 xstrerror (errno_val));
2221 free (aux_info_base);
2222 close (aux_info_file);
2223 return;
2227 /* Delete the aux_info file (unless requested not to). If the deletion
2228 fails for some reason, don't even worry about it. */
2230 if (must_create && !keep_it)
2231 if (unlink (aux_info_filename) == -1)
2233 int errno_val = errno;
2234 notice ("%s: can't delete aux info file `%s': %s\n",
2235 pname, shortpath (NULL, aux_info_filename),
2236 xstrerror (errno_val));
2239 /* Save a pointer into the first line of the aux_info file which
2240 contains the filename of the directory from which the compiler
2241 was invoked when the associated source file was compiled.
2242 This information is used later to help create complete
2243 filenames out of the (potentially) relative filenames in
2244 the aux_info file. */
2247 char *p = aux_info_base;
2249 while (*p != ':'
2250 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
2251 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
2252 #endif
2254 p++;
2255 p++;
2256 while (*p == ' ')
2257 p++;
2258 invocation_filename = p; /* Save a pointer to first byte of path. */
2259 while (*p != ' ')
2260 p++;
2261 *p++ = DIR_SEPARATOR;
2262 *p++ = '\0';
2263 while (*p++ != '\n')
2264 continue;
2265 aux_info_second_line = p;
2266 aux_info_relocated_name = 0;
2267 if (! is_abspath (invocation_filename))
2269 /* INVOCATION_FILENAME is relative;
2270 append it to BASE_SOURCE_FILENAME's dir. */
2271 char *dir_end;
2272 aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
2273 strcpy (aux_info_relocated_name, base_source_filename);
2274 dir_end = strrchr (aux_info_relocated_name, DIR_SEPARATOR);
2275 #ifdef DIR_SEPARATOR_2
2277 char *slash;
2279 slash = strrchr (dir_end ? dir_end : aux_info_relocated_name,
2280 DIR_SEPARATOR_2);
2281 if (slash)
2282 dir_end = slash;
2284 #endif
2285 if (dir_end)
2286 dir_end++;
2287 else
2288 dir_end = aux_info_relocated_name;
2289 strcpy (dir_end, invocation_filename);
2290 invocation_filename = aux_info_relocated_name;
2296 const char *aux_info_p;
2298 /* Do a pre-pass on the lines in the aux_info file, making sure that all
2299 of the source files referenced in there are at least as old as this
2300 aux_info file itself. If not, go back and regenerate the aux_info
2301 file anew. Don't do any of this for the syscalls file. */
2303 if (!is_syscalls)
2305 current_aux_info_lineno = 2;
2307 for (aux_info_p = aux_info_second_line; *aux_info_p; )
2309 if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2311 free (aux_info_base);
2312 free (aux_info_relocated_name);
2313 if (keep_it && unlink (aux_info_filename) == -1)
2315 int errno_val = errno;
2316 notice ("%s: can't delete file `%s': %s\n",
2317 pname, shortpath (NULL, aux_info_filename),
2318 xstrerror (errno_val));
2319 return;
2321 must_create = 1;
2322 goto start_over;
2325 /* Skip over the rest of this line to start of next line. */
2327 while (*aux_info_p != '\n')
2328 aux_info_p++;
2329 aux_info_p++;
2330 current_aux_info_lineno++;
2334 /* Now do the real pass on the aux_info lines. Save their information in
2335 the in-core data base. */
2337 current_aux_info_lineno = 2;
2339 for (aux_info_p = aux_info_second_line; *aux_info_p;)
2341 char *unexpanded_line = unexpand_if_needed (aux_info_p);
2343 if (unexpanded_line)
2345 save_def_or_dec (unexpanded_line, is_syscalls);
2346 free (unexpanded_line);
2348 else
2349 save_def_or_dec (aux_info_p, is_syscalls);
2351 /* Skip over the rest of this line and get to start of next line. */
2353 while (*aux_info_p != '\n')
2354 aux_info_p++;
2355 aux_info_p++;
2356 current_aux_info_lineno++;
2360 free (aux_info_base);
2361 free (aux_info_relocated_name);
2364 #ifndef UNPROTOIZE
2366 /* Check an individual filename for a .c suffix. If the filename has this
2367 suffix, rename the file such that its suffix is changed to .C. This
2368 function implements the -C option. */
2370 static void
2371 rename_c_file (hp)
2372 const hash_table_entry *hp;
2374 const char *filename = hp->symbol;
2375 int last_char_index = strlen (filename) - 1;
2376 char *const new_filename = (char *) alloca (strlen (filename)
2377 + strlen (cplus_suffix) + 1);
2379 /* Note that we don't care here if the given file was converted or not. It
2380 is possible that the given file was *not* converted, simply because there
2381 was nothing in it which actually required conversion. Even in this case,
2382 we want to do the renaming. Note that we only rename files with the .c
2383 suffix (except for the syscalls file, which is left alone). */
2385 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.'
2386 || IS_SAME_PATH (syscalls_absolute_filename, filename))
2387 return;
2389 strcpy (new_filename, filename);
2390 strcpy (&new_filename[last_char_index], cplus_suffix);
2392 if (rename (filename, new_filename) == -1)
2394 int errno_val = errno;
2395 notice ("%s: warning: can't rename file `%s' to `%s': %s\n",
2396 pname, shortpath (NULL, filename),
2397 shortpath (NULL, new_filename), xstrerror (errno_val));
2398 errors++;
2399 return;
2403 #endif /* !defined (UNPROTOIZE) */
2405 /* Take the list of definitions and declarations attached to a particular
2406 file_info node and reverse the order of the list. This should get the
2407 list into an order such that the item with the lowest associated line
2408 number is nearest the head of the list. When these lists are originally
2409 built, they are in the opposite order. We want to traverse them in
2410 normal line number order later (i.e. lowest to highest) so reverse the
2411 order here. */
2413 static void
2414 reverse_def_dec_list (hp)
2415 const hash_table_entry *hp;
2417 file_info *file_p = hp->fip;
2418 def_dec_info *prev = NULL;
2419 def_dec_info *current = (def_dec_info *) file_p->defs_decs;
2421 if (!current)
2422 return; /* no list to reverse */
2424 prev = current;
2425 if (! (current = (def_dec_info *) current->next_in_file))
2426 return; /* can't reverse a single list element */
2428 prev->next_in_file = NULL;
2430 while (current)
2432 def_dec_info *next = (def_dec_info *) current->next_in_file;
2434 current->next_in_file = prev;
2435 prev = current;
2436 current = next;
2439 file_p->defs_decs = prev;
2442 #ifndef UNPROTOIZE
2444 /* Find the (only?) extern definition for a particular function name, starting
2445 from the head of the linked list of entries for the given name. If we
2446 cannot find an extern definition for the given function name, issue a
2447 warning and scrounge around for the next best thing, i.e. an extern
2448 function declaration with a prototype attached to it. Note that we only
2449 allow such substitutions for extern declarations and never for static
2450 declarations. That's because the only reason we allow them at all is
2451 to let un-prototyped function declarations for system-supplied library
2452 functions get their prototypes from our own extra SYSCALLS.c.X file which
2453 contains all of the correct prototypes for system functions. */
2455 static const def_dec_info *
2456 find_extern_def (head, user)
2457 const def_dec_info *head;
2458 const def_dec_info *user;
2460 const def_dec_info *dd_p;
2461 const def_dec_info *extern_def_p = NULL;
2462 int conflict_noted = 0;
2464 /* Don't act too stupid here. Somebody may try to convert an entire system
2465 in one swell fwoop (rather than one program at a time, as should be done)
2466 and in that case, we may find that there are multiple extern definitions
2467 of a given function name in the entire set of source files that we are
2468 converting. If however one of these definitions resides in exactly the
2469 same source file as the reference we are trying to satisfy then in that
2470 case it would be stupid for us to fail to realize that this one definition
2471 *must* be the precise one we are looking for.
2473 To make sure that we don't miss an opportunity to make this "same file"
2474 leap of faith, we do a prescan of the list of records relating to the
2475 given function name, and we look (on this first scan) *only* for a
2476 definition of the function which is in the same file as the reference
2477 we are currently trying to satisfy. */
2479 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2480 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2481 return dd_p;
2483 /* Now, since we have not found a definition in the same file as the
2484 reference, we scan the list again and consider all possibilities from
2485 all files. Here we may get conflicts with the things listed in the
2486 SYSCALLS.c.X file, but if that happens it only means that the source
2487 code being converted contains its own definition of a function which
2488 could have been supplied by libc.a. In such cases, we should avoid
2489 issuing the normal warning, and defer to the definition given in the
2490 user's own code. */
2492 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2493 if (dd_p->is_func_def && !dd_p->is_static)
2495 if (!extern_def_p) /* Previous definition? */
2496 extern_def_p = dd_p; /* Remember the first definition found. */
2497 else
2499 /* Ignore definition just found if it came from SYSCALLS.c.X. */
2501 if (is_syscalls_file (dd_p->file))
2502 continue;
2504 /* Quietly replace the definition previously found with the one
2505 just found if the previous one was from SYSCALLS.c.X. */
2507 if (is_syscalls_file (extern_def_p->file))
2509 extern_def_p = dd_p;
2510 continue;
2513 /* If we get here, then there is a conflict between two function
2514 declarations for the same function, both of which came from the
2515 user's own code. */
2517 if (!conflict_noted) /* first time we noticed? */
2519 conflict_noted = 1;
2520 notice ("%s: conflicting extern definitions of '%s'\n",
2521 pname, head->hash_entry->symbol);
2522 if (!quiet_flag)
2524 notice ("%s: declarations of '%s' will not be converted\n",
2525 pname, head->hash_entry->symbol);
2526 notice ("%s: conflict list for '%s' follows:\n",
2527 pname, head->hash_entry->symbol);
2528 fprintf (stderr, "%s: %s(%d): %s\n",
2529 pname,
2530 shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2531 extern_def_p->line, extern_def_p->ansi_decl);
2534 if (!quiet_flag)
2535 fprintf (stderr, "%s: %s(%d): %s\n",
2536 pname,
2537 shortpath (NULL, dd_p->file->hash_entry->symbol),
2538 dd_p->line, dd_p->ansi_decl);
2542 /* We want to err on the side of caution, so if we found multiple conflicting
2543 definitions for the same function, treat this as being that same as if we
2544 had found no definitions (i.e. return NULL). */
2546 if (conflict_noted)
2547 return NULL;
2549 if (!extern_def_p)
2551 /* We have no definitions for this function so do the next best thing.
2552 Search for an extern declaration already in prototype form. */
2554 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2555 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2557 extern_def_p = dd_p; /* save a pointer to the definition */
2558 if (!quiet_flag)
2559 notice ("%s: warning: using formals list from %s(%d) for function `%s'\n",
2560 pname,
2561 shortpath (NULL, dd_p->file->hash_entry->symbol),
2562 dd_p->line, dd_p->hash_entry->symbol);
2563 break;
2566 /* Gripe about unprototyped function declarations that we found no
2567 corresponding definition (or other source of prototype information)
2568 for.
2570 Gripe even if the unprototyped declaration we are worried about
2571 exists in a file in one of the "system" include directories. We
2572 can gripe about these because we should have at least found a
2573 corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
2574 didn't, then that means that the SYSCALLS.c.X file is missing some
2575 needed prototypes for this particular system. That is worth telling
2576 the user about! */
2578 if (!extern_def_p)
2580 const char *file = user->file->hash_entry->symbol;
2582 if (!quiet_flag)
2583 if (in_system_include_dir (file))
2585 /* Why copy this string into `needed' at all?
2586 Why not just use user->ansi_decl without copying? */
2587 char *needed = (char *) alloca (strlen (user->ansi_decl) + 1);
2588 char *p;
2590 strcpy (needed, user->ansi_decl);
2591 p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
2592 + strlen (user->hash_entry->symbol) + 2;
2593 /* Avoid having ??? in the string. */
2594 *p++ = '?';
2595 *p++ = '?';
2596 *p++ = '?';
2597 strcpy (p, ");");
2599 notice ("%s: %d: `%s' used but missing from SYSCALLS\n",
2600 shortpath (NULL, file), user->line,
2601 needed+7); /* Don't print "extern " */
2603 #if 0
2604 else
2605 notice ("%s: %d: warning: no extern definition for `%s'\n",
2606 shortpath (NULL, file), user->line,
2607 user->hash_entry->symbol);
2608 #endif
2611 return extern_def_p;
2614 /* Find the (only?) static definition for a particular function name in a
2615 given file. Here we get the function-name and the file info indirectly
2616 from the def_dec_info record pointer which is passed in. */
2618 static const def_dec_info *
2619 find_static_definition (user)
2620 const def_dec_info *user;
2622 const def_dec_info *head = user->hash_entry->ddip;
2623 const def_dec_info *dd_p;
2624 int num_static_defs = 0;
2625 const def_dec_info *static_def_p = NULL;
2627 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2628 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2630 static_def_p = dd_p; /* save a pointer to the definition */
2631 num_static_defs++;
2633 if (num_static_defs == 0)
2635 if (!quiet_flag)
2636 notice ("%s: warning: no static definition for `%s' in file `%s'\n",
2637 pname, head->hash_entry->symbol,
2638 shortpath (NULL, user->file->hash_entry->symbol));
2640 else if (num_static_defs > 1)
2642 notice ("%s: multiple static defs of `%s' in file `%s'\n",
2643 pname, head->hash_entry->symbol,
2644 shortpath (NULL, user->file->hash_entry->symbol));
2645 return NULL;
2647 return static_def_p;
2650 /* Find good prototype style formal argument lists for all of the function
2651 declarations which didn't have them before now.
2653 To do this we consider each function name one at a time. For each function
2654 name, we look at the items on the linked list of def_dec_info records for
2655 that particular name.
2657 Somewhere on this list we should find one (and only one) def_dec_info
2658 record which represents the actual function definition, and this record
2659 should have a nice formal argument list already associated with it.
2661 Thus, all we have to do is to connect up all of the other def_dec_info
2662 records for this particular function name to the special one which has
2663 the full-blown formals list.
2665 Of course it is a little more complicated than just that. See below for
2666 more details. */
2668 static void
2669 connect_defs_and_decs (hp)
2670 const hash_table_entry *hp;
2672 const def_dec_info *dd_p;
2673 const def_dec_info *extern_def_p = NULL;
2674 int first_extern_reference = 1;
2676 /* Traverse the list of definitions and declarations for this particular
2677 function name. For each item on the list, if it is a function
2678 definition (either old style or new style) then GCC has already been
2679 kind enough to produce a prototype for us, and it is associated with
2680 the item already, so declare the item as its own associated "definition".
2682 Also, for each item which is only a function declaration, but which
2683 nonetheless has its own prototype already (obviously supplied by the user)
2684 declare the item as its own definition.
2686 Note that when/if there are multiple user-supplied prototypes already
2687 present for multiple declarations of any given function, these multiple
2688 prototypes *should* all match exactly with one another and with the
2689 prototype for the actual function definition. We don't check for this
2690 here however, since we assume that the compiler must have already done
2691 this consistency checking when it was creating the .X files. */
2693 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2694 if (dd_p->prototyped)
2695 ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2697 /* Traverse the list of definitions and declarations for this particular
2698 function name. For each item on the list, if it is an extern function
2699 declaration and if it has no associated definition yet, go try to find
2700 the matching extern definition for the declaration.
2702 When looking for the matching function definition, warn the user if we
2703 fail to find one.
2705 If we find more that one function definition also issue a warning.
2707 Do the search for the matching definition only once per unique function
2708 name (and only when absolutely needed) so that we can avoid putting out
2709 redundant warning messages, and so that we will only put out warning
2710 messages when there is actually a reference (i.e. a declaration) for
2711 which we need to find a matching definition. */
2713 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2714 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2716 if (first_extern_reference)
2718 extern_def_p = find_extern_def (hp->ddip, dd_p);
2719 first_extern_reference = 0;
2721 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2724 /* Traverse the list of definitions and declarations for this particular
2725 function name. For each item on the list, if it is a static function
2726 declaration and if it has no associated definition yet, go try to find
2727 the matching static definition for the declaration within the same file.
2729 When looking for the matching function definition, warn the user if we
2730 fail to find one in the same file with the declaration, and refuse to
2731 convert this kind of cross-file static function declaration. After all,
2732 this is stupid practice and should be discouraged.
2734 We don't have to worry about the possibility that there is more than one
2735 matching function definition in the given file because that would have
2736 been flagged as an error by the compiler.
2738 Do the search for the matching definition only once per unique
2739 function-name/source-file pair (and only when absolutely needed) so that
2740 we can avoid putting out redundant warning messages, and so that we will
2741 only put out warning messages when there is actually a reference (i.e. a
2742 declaration) for which we actually need to find a matching definition. */
2744 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2745 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2747 const def_dec_info *dd_p2;
2748 const def_dec_info *static_def;
2750 /* We have now found a single static declaration for which we need to
2751 find a matching definition. We want to minimize the work (and the
2752 number of warnings), so we will find an appropriate (matching)
2753 static definition for this declaration, and then distribute it
2754 (as the definition for) any and all other static declarations
2755 for this function name which occur within the same file, and which
2756 do not already have definitions.
2758 Note that a trick is used here to prevent subsequent attempts to
2759 call find_static_definition for a given function-name & file
2760 if the first such call returns NULL. Essentially, we convert
2761 these NULL return values to -1, and put the -1 into the definition
2762 field for each other static declaration from the same file which
2763 does not already have an associated definition.
2764 This makes these other static declarations look like they are
2765 actually defined already when the outer loop here revisits them
2766 later on. Thus, the outer loop will skip over them. Later, we
2767 turn the -1's back to NULL's. */
2769 ((NONCONST def_dec_info *) dd_p)->definition =
2770 (static_def = find_static_definition (dd_p))
2771 ? static_def
2772 : (const def_dec_info *) -1;
2774 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2775 if (!dd_p2->is_func_def && dd_p2->is_static
2776 && !dd_p2->definition && (dd_p2->file == dd_p->file))
2777 ((NONCONST def_dec_info *) dd_p2)->definition = dd_p->definition;
2780 /* Convert any dummy (-1) definitions we created in the step above back to
2781 NULL's (as they should be). */
2783 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2784 if (dd_p->definition == (def_dec_info *) -1)
2785 ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2788 #endif /* !defined (UNPROTOIZE) */
2790 /* Give a pointer into the clean text buffer, return a number which is the
2791 original source line number that the given pointer points into. */
2793 static int
2794 identify_lineno (clean_p)
2795 const char *clean_p;
2797 int line_num = 1;
2798 const char *scan_p;
2800 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2801 if (*scan_p == '\n')
2802 line_num++;
2803 return line_num;
2806 /* Issue an error message and give up on doing this particular edit. */
2808 static void
2809 declare_source_confusing (clean_p)
2810 const char *clean_p;
2812 if (!quiet_flag)
2814 if (clean_p == 0)
2815 notice ("%s: %d: warning: source too confusing\n",
2816 shortpath (NULL, convert_filename), last_known_line_number);
2817 else
2818 notice ("%s: %d: warning: source too confusing\n",
2819 shortpath (NULL, convert_filename),
2820 identify_lineno (clean_p));
2822 longjmp (source_confusion_recovery, 1);
2825 /* Check that a condition which is expected to be true in the original source
2826 code is in fact true. If not, issue an error message and give up on
2827 converting this particular source file. */
2829 static void
2830 check_source (cond, clean_p)
2831 int cond;
2832 const char *clean_p;
2834 if (!cond)
2835 declare_source_confusing (clean_p);
2838 /* If we think of the in-core cleaned text buffer as a memory mapped
2839 file (with the variable last_known_line_start acting as sort of a
2840 file pointer) then we can imagine doing "seeks" on the buffer. The
2841 following routine implements a kind of "seek" operation for the in-core
2842 (cleaned) copy of the source file. When finished, it returns a pointer to
2843 the start of a given (numbered) line in the cleaned text buffer.
2845 Note that protoize only has to "seek" in the forward direction on the
2846 in-core cleaned text file buffers, and it never needs to back up.
2848 This routine is made a little bit faster by remembering the line number
2849 (and pointer value) supplied (and returned) from the previous "seek".
2850 This prevents us from always having to start all over back at the top
2851 of the in-core cleaned buffer again. */
2853 static const char *
2854 seek_to_line (n)
2855 int n;
2857 if (n < last_known_line_number)
2858 abort ();
2860 while (n > last_known_line_number)
2862 while (*last_known_line_start != '\n')
2863 check_source (++last_known_line_start < clean_text_limit, 0);
2864 last_known_line_start++;
2865 last_known_line_number++;
2867 return last_known_line_start;
2870 /* Given a pointer to a character in the cleaned text buffer, return a pointer
2871 to the next non-whitespace character which follows it. */
2873 static const char *
2874 forward_to_next_token_char (ptr)
2875 const char *ptr;
2877 for (++ptr; ISSPACE ((const unsigned char)*ptr);
2878 check_source (++ptr < clean_text_limit, 0))
2879 continue;
2880 return ptr;
2883 /* Copy a chunk of text of length `len' and starting at `str' to the current
2884 output buffer. Note that all attempts to add stuff to the current output
2885 buffer ultimately go through here. */
2887 static void
2888 output_bytes (str, len)
2889 const char *str;
2890 size_t len;
2892 if ((repl_write_ptr + 1) + len >= repl_text_limit)
2894 size_t new_size = (repl_text_limit - repl_text_base) << 1;
2895 char *new_buf = (char *) xrealloc (repl_text_base, new_size);
2897 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
2898 repl_text_base = new_buf;
2899 repl_text_limit = new_buf + new_size;
2901 memcpy (repl_write_ptr + 1, str, len);
2902 repl_write_ptr += len;
2905 /* Copy all bytes (except the trailing null) of a null terminated string to
2906 the current output buffer. */
2908 static void
2909 output_string (str)
2910 const char *str;
2912 output_bytes (str, strlen (str));
2915 /* Copy some characters from the original text buffer to the current output
2916 buffer.
2918 This routine takes a pointer argument `p' which is assumed to be a pointer
2919 into the cleaned text buffer. The bytes which are copied are the `original'
2920 equivalents for the set of bytes between the last value of `clean_read_ptr'
2921 and the argument value `p'.
2923 The set of bytes copied however, comes *not* from the cleaned text buffer,
2924 but rather from the direct counterparts of these bytes within the original
2925 text buffer.
2927 Thus, when this function is called, some bytes from the original text
2928 buffer (which may include original comments and preprocessing directives)
2929 will be copied into the output buffer.
2931 Note that the request implied when this routine is called includes the
2932 byte pointed to by the argument pointer `p'. */
2934 static void
2935 output_up_to (p)
2936 const char *p;
2938 size_t copy_length = (size_t) (p - clean_read_ptr);
2939 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
2941 if (copy_length == 0)
2942 return;
2944 output_bytes (copy_start, copy_length);
2945 clean_read_ptr = p;
2948 /* Given a pointer to a def_dec_info record which represents some form of
2949 definition of a function (perhaps a real definition, or in lieu of that
2950 perhaps just a declaration with a full prototype) return true if this
2951 function is one which we should avoid converting. Return false
2952 otherwise. */
2954 static int
2955 other_variable_style_function (ansi_header)
2956 const char *ansi_header;
2958 #ifdef UNPROTOIZE
2960 /* See if we have a stdarg function, or a function which has stdarg style
2961 parameters or a stdarg style return type. */
2963 return substr (ansi_header, "...") != 0;
2965 #else /* !defined (UNPROTOIZE) */
2967 /* See if we have a varargs function, or a function which has varargs style
2968 parameters or a varargs style return type. */
2970 const char *p;
2971 int len = strlen (varargs_style_indicator);
2973 for (p = ansi_header; p; )
2975 const char *candidate;
2977 if ((candidate = substr (p, varargs_style_indicator)) == 0)
2978 return 0;
2979 else
2980 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
2981 return 1;
2982 else
2983 p = candidate + 1;
2985 return 0;
2986 #endif /* !defined (UNPROTOIZE) */
2989 /* Do the editing operation specifically for a function "declaration". Note
2990 that editing for function "definitions" are handled in a separate routine
2991 below. */
2993 static void
2994 edit_fn_declaration (def_dec_p, clean_text_p)
2995 const def_dec_info *def_dec_p;
2996 const char *volatile clean_text_p;
2998 const char *start_formals;
2999 const char *end_formals;
3000 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3001 size_t func_name_len = strlen (function_to_edit);
3002 const char *end_of_fn_name;
3004 #ifndef UNPROTOIZE
3006 const f_list_chain_item *this_f_list_chain_item;
3007 const def_dec_info *definition = def_dec_p->definition;
3009 /* If we are protoizing, and if we found no corresponding definition for
3010 this particular function declaration, then just leave this declaration
3011 exactly as it is. */
3013 if (!definition)
3014 return;
3016 /* If we are protoizing, and if the corresponding definition that we found
3017 for this particular function declaration defined an old style varargs
3018 function, then we want to issue a warning and just leave this function
3019 declaration unconverted. */
3021 if (other_variable_style_function (definition->ansi_decl))
3023 if (!quiet_flag)
3024 notice ("%s: %d: warning: varargs function declaration not converted\n",
3025 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3026 def_dec_p->line);
3027 return;
3030 #endif /* !defined (UNPROTOIZE) */
3032 /* Setup here to recover from confusing source code detected during this
3033 particular "edit". */
3035 save_pointers ();
3036 if (setjmp (source_confusion_recovery))
3038 restore_pointers ();
3039 notice ("%s: declaration of function `%s' not converted\n",
3040 pname, function_to_edit);
3041 return;
3044 /* We are editing a function declaration. The line number we did a seek to
3045 contains the comma or semicolon which follows the declaration. Our job
3046 now is to scan backwards looking for the function name. This name *must*
3047 be followed by open paren (ignoring whitespace, of course). We need to
3048 replace everything between that open paren and the corresponding closing
3049 paren. If we are protoizing, we need to insert the prototype-style
3050 formals lists. If we are unprotoizing, we need to just delete everything
3051 between the pairs of opening and closing parens. */
3053 /* First move up to the end of the line. */
3055 while (*clean_text_p != '\n')
3056 check_source (++clean_text_p < clean_text_limit, 0);
3057 clean_text_p--; /* Point to just before the newline character. */
3059 /* Now we can scan backwards for the function name. */
3063 for (;;)
3065 /* Scan leftwards until we find some character which can be
3066 part of an identifier. */
3068 while (!is_id_char (*clean_text_p))
3069 check_source (--clean_text_p > clean_read_ptr, 0);
3071 /* Scan backwards until we find a char that cannot be part of an
3072 identifier. */
3074 while (is_id_char (*clean_text_p))
3075 check_source (--clean_text_p > clean_read_ptr, 0);
3077 /* Having found an "id break", see if the following id is the one
3078 that we are looking for. If so, then exit from this loop. */
3080 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
3082 char ch = *(clean_text_p + 1 + func_name_len);
3084 /* Must also check to see that the name in the source text
3085 ends where it should (in order to prevent bogus matches
3086 on similar but longer identifiers. */
3088 if (! is_id_char (ch))
3089 break; /* exit from loop */
3093 /* We have now found the first perfect match for the function name in
3094 our backward search. This may or may not be the actual function
3095 name at the start of the actual function declaration (i.e. we could
3096 have easily been mislead). We will try to avoid getting fooled too
3097 often by looking forward for the open paren which should follow the
3098 identifier we just found. We ignore whitespace while hunting. If
3099 the next non-whitespace byte we see is *not* an open left paren,
3100 then we must assume that we have been fooled and we start over
3101 again accordingly. Note that there is no guarantee, that even if
3102 we do see the open paren, that we are in the right place.
3103 Programmers do the strangest things sometimes! */
3105 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
3106 start_formals = forward_to_next_token_char (end_of_fn_name);
3108 while (*start_formals != '(');
3110 /* start_of_formals now points to the opening left paren which immediately
3111 follows the name of the function. */
3113 /* Note that there may be several formals lists which need to be modified
3114 due to the possibility that the return type of this function is a
3115 pointer-to-function type. If there are several formals lists, we
3116 convert them in left-to-right order here. */
3118 #ifndef UNPROTOIZE
3119 this_f_list_chain_item = definition->f_list_chain;
3120 #endif /* !defined (UNPROTOIZE) */
3122 for (;;)
3125 int depth;
3127 end_formals = start_formals + 1;
3128 depth = 1;
3129 for (; depth; check_source (++end_formals < clean_text_limit, 0))
3131 switch (*end_formals)
3133 case '(':
3134 depth++;
3135 break;
3136 case ')':
3137 depth--;
3138 break;
3141 end_formals--;
3144 /* end_formals now points to the closing right paren of the formals
3145 list whose left paren is pointed to by start_formals. */
3147 /* Now, if we are protoizing, we insert the new ANSI-style formals list
3148 attached to the associated definition of this function. If however
3149 we are unprotoizing, then we simply delete any formals list which
3150 may be present. */
3152 output_up_to (start_formals);
3153 #ifndef UNPROTOIZE
3154 if (this_f_list_chain_item)
3156 output_string (this_f_list_chain_item->formals_list);
3157 this_f_list_chain_item = this_f_list_chain_item->chain_next;
3159 else
3161 if (!quiet_flag)
3162 notice ("%s: warning: too many parameter lists in declaration of `%s'\n",
3163 pname, def_dec_p->hash_entry->symbol);
3164 check_source (0, end_formals); /* leave the declaration intact */
3166 #endif /* !defined (UNPROTOIZE) */
3167 clean_read_ptr = end_formals - 1;
3169 /* Now see if it looks like there may be another formals list associated
3170 with the function declaration that we are converting (following the
3171 formals list that we just converted. */
3174 const char *another_r_paren = forward_to_next_token_char (end_formals);
3176 if ((*another_r_paren != ')')
3177 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3179 #ifndef UNPROTOIZE
3180 if (this_f_list_chain_item)
3182 if (!quiet_flag)
3183 notice ("\n%s: warning: too few parameter lists in declaration of `%s'\n",
3184 pname, def_dec_p->hash_entry->symbol);
3185 check_source (0, start_formals); /* leave the decl intact */
3187 #endif /* !defined (UNPROTOIZE) */
3188 break;
3193 /* There does appear to be yet another formals list, so loop around
3194 again, and convert it also. */
3198 /* Edit a whole group of formals lists, starting with the rightmost one
3199 from some set of formals lists. This routine is called once (from the
3200 outside) for each function declaration which is converted. It is
3201 recursive however, and it calls itself once for each remaining formal
3202 list that lies to the left of the one it was originally called to work
3203 on. Thus, a whole set gets done in right-to-left order.
3205 This routine returns nonzero if it thinks that it should not be trying
3206 to convert this particular function definition (because the name of the
3207 function doesn't match the one expected). */
3209 static int
3210 edit_formals_lists (end_formals, f_list_count, def_dec_p)
3211 const char *end_formals;
3212 unsigned int f_list_count;
3213 const def_dec_info *def_dec_p;
3215 const char *start_formals;
3216 int depth;
3218 start_formals = end_formals - 1;
3219 depth = 1;
3220 for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3222 switch (*start_formals)
3224 case '(':
3225 depth--;
3226 break;
3227 case ')':
3228 depth++;
3229 break;
3232 start_formals++;
3234 /* start_formals now points to the opening left paren of the formals list. */
3236 f_list_count--;
3238 if (f_list_count)
3240 const char *next_end;
3242 /* There should be more formal lists to the left of here. */
3244 next_end = start_formals - 1;
3245 check_source (next_end > clean_read_ptr, 0);
3246 while (ISSPACE ((const unsigned char)*next_end))
3247 check_source (--next_end > clean_read_ptr, 0);
3248 check_source (*next_end == ')', next_end);
3249 check_source (--next_end > clean_read_ptr, 0);
3250 check_source (*next_end == ')', next_end);
3251 if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3252 return 1;
3255 /* Check that the function name in the header we are working on is the same
3256 as the one we would expect to find. If not, issue a warning and return
3257 nonzero. */
3259 if (f_list_count == 0)
3261 const char *expected = def_dec_p->hash_entry->symbol;
3262 const char *func_name_start;
3263 const char *func_name_limit;
3264 size_t func_name_len;
3266 for (func_name_limit = start_formals-1;
3267 ISSPACE ((const unsigned char)*func_name_limit); )
3268 check_source (--func_name_limit > clean_read_ptr, 0);
3270 for (func_name_start = func_name_limit++;
3271 is_id_char (*func_name_start);
3272 func_name_start--)
3273 check_source (func_name_start > clean_read_ptr, 0);
3274 func_name_start++;
3275 func_name_len = func_name_limit - func_name_start;
3276 if (func_name_len == 0)
3277 check_source (0, func_name_start);
3278 if (func_name_len != strlen (expected)
3279 || strncmp (func_name_start, expected, func_name_len))
3281 notice ("%s: %d: warning: found `%s' but expected `%s'\n",
3282 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3283 identify_lineno (func_name_start),
3284 dupnstr (func_name_start, func_name_len),
3285 expected);
3286 return 1;
3290 output_up_to (start_formals);
3292 #ifdef UNPROTOIZE
3293 if (f_list_count == 0)
3294 output_string (def_dec_p->formal_names);
3295 #else /* !defined (UNPROTOIZE) */
3297 unsigned f_list_depth;
3298 const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3300 /* At this point, the current value of f_list count says how many
3301 links we have to follow through the f_list_chain to get to the
3302 particular formals list that we need to output next. */
3304 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3305 flci_p = flci_p->chain_next;
3306 output_string (flci_p->formals_list);
3308 #endif /* !defined (UNPROTOIZE) */
3310 clean_read_ptr = end_formals - 1;
3311 return 0;
3314 /* Given a pointer to a byte in the clean text buffer which points to
3315 the beginning of a line that contains a "follower" token for a
3316 function definition header, do whatever is necessary to find the
3317 right closing paren for the rightmost formals list of the function
3318 definition header. */
3320 static const char *
3321 find_rightmost_formals_list (clean_text_p)
3322 const char *clean_text_p;
3324 const char *end_formals;
3326 /* We are editing a function definition. The line number we did a seek
3327 to contains the first token which immediately follows the entire set of
3328 formals lists which are part of this particular function definition
3329 header.
3331 Our job now is to scan leftwards in the clean text looking for the
3332 right-paren which is at the end of the function header's rightmost
3333 formals list.
3335 If we ignore whitespace, this right paren should be the first one we
3336 see which is (ignoring whitespace) immediately followed either by the
3337 open curly-brace beginning the function body or by an alphabetic
3338 character (in the case where the function definition is in old (K&R)
3339 style and there are some declarations of formal parameters). */
3341 /* It is possible that the right paren we are looking for is on the
3342 current line (together with its following token). Just in case that
3343 might be true, we start out here by skipping down to the right end of
3344 the current line before starting our scan. */
3346 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3347 continue;
3348 end_formals--;
3350 #ifdef UNPROTOIZE
3352 /* Now scan backwards while looking for the right end of the rightmost
3353 formals list associated with this function definition. */
3356 char ch;
3357 const char *l_brace_p;
3359 /* Look leftward and try to find a right-paren. */
3361 while (*end_formals != ')')
3363 if (ISSPACE ((unsigned char)*end_formals))
3364 while (ISSPACE ((unsigned char)*end_formals))
3365 check_source (--end_formals > clean_read_ptr, 0);
3366 else
3367 check_source (--end_formals > clean_read_ptr, 0);
3370 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3371 /* Since we are unprotoizing an ANSI-style (prototyped) function
3372 definition, there had better not be anything (except whitespace)
3373 between the end of the ANSI formals list and the beginning of the
3374 function body (i.e. the '{'). */
3376 check_source (ch == '{', l_brace_p);
3379 #else /* !defined (UNPROTOIZE) */
3381 /* Now scan backwards while looking for the right end of the rightmost
3382 formals list associated with this function definition. */
3384 while (1)
3386 char ch;
3387 const char *l_brace_p;
3389 /* Look leftward and try to find a right-paren. */
3391 while (*end_formals != ')')
3393 if (ISSPACE ((const unsigned char)*end_formals))
3394 while (ISSPACE ((const unsigned char)*end_formals))
3395 check_source (--end_formals > clean_read_ptr, 0);
3396 else
3397 check_source (--end_formals > clean_read_ptr, 0);
3400 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3402 /* Since it is possible that we found a right paren before the starting
3403 '{' of the body which IS NOT the one at the end of the real K&R
3404 formals list (say for instance, we found one embedded inside one of
3405 the old K&R formal parameter declarations) we have to check to be
3406 sure that this is in fact the right paren that we were looking for.
3408 The one we were looking for *must* be followed by either a '{' or
3409 by an alphabetic character, while others *cannot* validly be followed
3410 by such characters. */
3412 if ((ch == '{') || ISALPHA ((unsigned char) ch))
3413 break;
3415 /* At this point, we have found a right paren, but we know that it is
3416 not the one we were looking for, so backup one character and keep
3417 looking. */
3419 check_source (--end_formals > clean_read_ptr, 0);
3422 #endif /* !defined (UNPROTOIZE) */
3424 return end_formals;
3427 #ifndef UNPROTOIZE
3429 /* Insert into the output file a totally new declaration for a function
3430 which (up until now) was being called from within the current block
3431 without having been declared at any point such that the declaration
3432 was visible (i.e. in scope) at the point of the call.
3434 We need to add in explicit declarations for all such function calls
3435 in order to get the full benefit of prototype-based function call
3436 parameter type checking. */
3438 static void
3439 add_local_decl (def_dec_p, clean_text_p)
3440 const def_dec_info *def_dec_p;
3441 const char *clean_text_p;
3443 const char *start_of_block;
3444 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3446 /* Don't insert new local explicit declarations unless explicitly requested
3447 to do so. */
3449 if (!local_flag)
3450 return;
3452 /* Setup here to recover from confusing source code detected during this
3453 particular "edit". */
3455 save_pointers ();
3456 if (setjmp (source_confusion_recovery))
3458 restore_pointers ();
3459 notice ("%s: local declaration for function `%s' not inserted\n",
3460 pname, function_to_edit);
3461 return;
3464 /* We have already done a seek to the start of the line which should
3465 contain *the* open curly brace which begins the block in which we need
3466 to insert an explicit function declaration (to replace the implicit one).
3468 Now we scan that line, starting from the left, until we find the
3469 open curly brace we are looking for. Note that there may actually be
3470 multiple open curly braces on the given line, but we will be happy
3471 with the leftmost one no matter what. */
3473 start_of_block = clean_text_p;
3474 while (*start_of_block != '{' && *start_of_block != '\n')
3475 check_source (++start_of_block < clean_text_limit, 0);
3477 /* Note that the line from the original source could possibly
3478 contain *no* open curly braces! This happens if the line contains
3479 a macro call which expands into a chunk of text which includes a
3480 block (and that block's associated open and close curly braces).
3481 In cases like this, we give up, issue a warning, and do nothing. */
3483 if (*start_of_block != '{')
3485 if (!quiet_flag)
3486 notice ("\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
3487 def_dec_p->file->hash_entry->symbol, def_dec_p->line,
3488 def_dec_p->hash_entry->symbol);
3489 return;
3492 /* Figure out what a nice (pretty) indentation would be for the new
3493 declaration we are adding. In order to do this, we must scan forward
3494 from the '{' until we find the first line which starts with some
3495 non-whitespace characters (i.e. real "token" material). */
3498 const char *ep = forward_to_next_token_char (start_of_block) - 1;
3499 const char *sp;
3501 /* Now we have ep pointing at the rightmost byte of some existing indent
3502 stuff. At least that is the hope.
3504 We can now just scan backwards and find the left end of the existing
3505 indentation string, and then copy it to the output buffer. */
3507 for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--)
3508 continue;
3510 /* Now write out the open { which began this block, and any following
3511 trash up to and including the last byte of the existing indent that
3512 we just found. */
3514 output_up_to (ep);
3516 /* Now we go ahead and insert the new declaration at this point.
3518 If the definition of the given function is in the same file that we
3519 are currently editing, and if its full ANSI declaration normally
3520 would start with the keyword `extern', suppress the `extern'. */
3523 const char *decl = def_dec_p->definition->ansi_decl;
3525 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
3526 decl += 7;
3527 output_string (decl);
3530 /* Finally, write out a new indent string, just like the preceding one
3531 that we found. This will typically include a newline as the first
3532 character of the indent string. */
3534 output_bytes (sp, (size_t) (ep - sp) + 1);
3538 /* Given a pointer to a file_info record, and a pointer to the beginning
3539 of a line (in the clean text buffer) which is assumed to contain the
3540 first "follower" token for the first function definition header in the
3541 given file, find a good place to insert some new global function
3542 declarations (which will replace scattered and imprecise implicit ones)
3543 and then insert the new explicit declaration at that point in the file. */
3545 static void
3546 add_global_decls (file_p, clean_text_p)
3547 const file_info *file_p;
3548 const char *clean_text_p;
3550 const def_dec_info *dd_p;
3551 const char *scan_p;
3553 /* Setup here to recover from confusing source code detected during this
3554 particular "edit". */
3556 save_pointers ();
3557 if (setjmp (source_confusion_recovery))
3559 restore_pointers ();
3560 notice ("%s: global declarations for file `%s' not inserted\n",
3561 pname, shortpath (NULL, file_p->hash_entry->symbol));
3562 return;
3565 /* Start by finding a good location for adding the new explicit function
3566 declarations. To do this, we scan backwards, ignoring whitespace
3567 and comments and other junk until we find either a semicolon, or until
3568 we hit the beginning of the file. */
3570 scan_p = find_rightmost_formals_list (clean_text_p);
3571 for (;; --scan_p)
3573 if (scan_p < clean_text_base)
3574 break;
3575 check_source (scan_p > clean_read_ptr, 0);
3576 if (*scan_p == ';')
3577 break;
3580 /* scan_p now points either to a semicolon, or to just before the start
3581 of the whole file. */
3583 /* Now scan forward for the first non-whitespace character. In theory,
3584 this should be the first character of the following function definition
3585 header. We will put in the added declarations just prior to that. */
3587 scan_p++;
3588 while (ISSPACE ((const unsigned char)*scan_p))
3589 scan_p++;
3590 scan_p--;
3592 output_up_to (scan_p);
3594 /* Now write out full prototypes for all of the things that had been
3595 implicitly declared in this file (but only those for which we were
3596 actually able to find unique matching definitions). Avoid duplicates
3597 by marking things that we write out as we go. */
3600 int some_decls_added = 0;
3602 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3603 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
3605 const char *decl = dd_p->definition->ansi_decl;
3607 /* If the function for which we are inserting a declaration is
3608 actually defined later in the same file, then suppress the
3609 leading `extern' keyword (if there is one). */
3611 if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
3612 decl += 7;
3614 output_string ("\n");
3615 output_string (decl);
3616 some_decls_added = 1;
3617 ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
3619 if (some_decls_added)
3620 output_string ("\n\n");
3623 /* Unmark all of the definitions that we just marked. */
3625 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3626 if (dd_p->definition)
3627 ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
3630 #endif /* !defined (UNPROTOIZE) */
3632 /* Do the editing operation specifically for a function "definition". Note
3633 that editing operations for function "declarations" are handled by a
3634 separate routine above. */
3636 static void
3637 edit_fn_definition (def_dec_p, clean_text_p)
3638 const def_dec_info *def_dec_p;
3639 const char *clean_text_p;
3641 const char *end_formals;
3642 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3644 /* Setup here to recover from confusing source code detected during this
3645 particular "edit". */
3647 save_pointers ();
3648 if (setjmp (source_confusion_recovery))
3650 restore_pointers ();
3651 notice ("%s: definition of function `%s' not converted\n",
3652 pname, function_to_edit);
3653 return;
3656 end_formals = find_rightmost_formals_list (clean_text_p);
3658 /* end_of_formals now points to the closing right paren of the rightmost
3659 formals list which is actually part of the `header' of the function
3660 definition that we are converting. */
3662 /* If the header of this function definition looks like it declares a
3663 function with a variable number of arguments, and if the way it does
3664 that is different from that way we would like it (i.e. varargs vs.
3665 stdarg) then issue a warning and leave the header unconverted. */
3667 if (other_variable_style_function (def_dec_p->ansi_decl))
3669 if (!quiet_flag)
3670 notice ("%s: %d: warning: definition of %s not converted\n",
3671 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3672 identify_lineno (end_formals),
3673 other_var_style);
3674 output_up_to (end_formals);
3675 return;
3678 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
3680 restore_pointers ();
3681 notice ("%s: definition of function `%s' not converted\n",
3682 pname, function_to_edit);
3683 return;
3686 /* Have to output the last right paren because this never gets flushed by
3687 edit_formals_list. */
3689 output_up_to (end_formals);
3691 #ifdef UNPROTOIZE
3693 const char *decl_p;
3694 const char *semicolon_p;
3695 const char *limit_p;
3696 const char *scan_p;
3697 int had_newlines = 0;
3699 /* Now write out the K&R style formal declarations, one per line. */
3701 decl_p = def_dec_p->formal_decls;
3702 limit_p = decl_p + strlen (decl_p);
3703 for (;decl_p < limit_p; decl_p = semicolon_p + 2)
3705 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
3706 continue;
3707 output_string ("\n");
3708 output_string (indent_string);
3709 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
3712 /* If there are no newlines between the end of the formals list and the
3713 start of the body, we should insert one now. */
3715 for (scan_p = end_formals+1; *scan_p != '{'; )
3717 if (*scan_p == '\n')
3719 had_newlines = 1;
3720 break;
3722 check_source (++scan_p < clean_text_limit, 0);
3724 if (!had_newlines)
3725 output_string ("\n");
3727 #else /* !defined (UNPROTOIZE) */
3728 /* If we are protoizing, there may be some flotsam & jetsam (like comments
3729 and preprocessing directives) after the old formals list but before
3730 the following { and we would like to preserve that stuff while effectively
3731 deleting the existing K&R formal parameter declarations. We do so here
3732 in a rather tricky way. Basically, we white out any stuff *except*
3733 the comments/pp-directives in the original text buffer, then, if there
3734 is anything in this area *other* than whitespace, we output it. */
3736 const char *end_formals_orig;
3737 const char *start_body;
3738 const char *start_body_orig;
3739 const char *scan;
3740 const char *scan_orig;
3741 int have_flotsam = 0;
3742 int have_newlines = 0;
3744 for (start_body = end_formals + 1; *start_body != '{';)
3745 check_source (++start_body < clean_text_limit, 0);
3747 end_formals_orig = orig_text_base + (end_formals - clean_text_base);
3748 start_body_orig = orig_text_base + (start_body - clean_text_base);
3749 scan = end_formals + 1;
3750 scan_orig = end_formals_orig + 1;
3751 for (; scan < start_body; scan++, scan_orig++)
3753 if (*scan == *scan_orig)
3755 have_newlines |= (*scan_orig == '\n');
3756 /* Leave identical whitespace alone. */
3757 if (!ISSPACE ((const unsigned char)*scan_orig))
3758 *((NONCONST char *) scan_orig) = ' '; /* identical - so whiteout */
3760 else
3761 have_flotsam = 1;
3763 if (have_flotsam)
3764 output_bytes (end_formals_orig + 1,
3765 (size_t) (start_body_orig - end_formals_orig) - 1);
3766 else
3767 if (have_newlines)
3768 output_string ("\n");
3769 else
3770 output_string (" ");
3771 clean_read_ptr = start_body - 1;
3773 #endif /* !defined (UNPROTOIZE) */
3776 /* Clean up the clean text buffer. Do this by converting comments and
3777 preprocessing directives into spaces. Also convert line continuations
3778 into whitespace. Also, whiteout string and character literals. */
3780 static void
3781 do_cleaning (new_clean_text_base, new_clean_text_limit)
3782 char *new_clean_text_base;
3783 const char *new_clean_text_limit;
3785 char *scan_p;
3786 int non_whitespace_since_newline = 0;
3788 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
3790 switch (*scan_p)
3792 case '/': /* Handle comments. */
3793 if (scan_p[1] != '*')
3794 goto regular;
3795 non_whitespace_since_newline = 1;
3796 scan_p[0] = ' ';
3797 scan_p[1] = ' ';
3798 scan_p += 2;
3799 while (scan_p[1] != '/' || scan_p[0] != '*')
3801 if (!ISSPACE ((const unsigned char)*scan_p))
3802 *scan_p = ' ';
3803 if (++scan_p >= new_clean_text_limit)
3804 abort ();
3806 *scan_p++ = ' ';
3807 *scan_p = ' ';
3808 break;
3810 case '#': /* Handle pp directives. */
3811 if (non_whitespace_since_newline)
3812 goto regular;
3813 *scan_p = ' ';
3814 while (scan_p[1] != '\n' || scan_p[0] == '\\')
3816 if (!ISSPACE ((const unsigned char)*scan_p))
3817 *scan_p = ' ';
3818 if (++scan_p >= new_clean_text_limit)
3819 abort ();
3821 *scan_p++ = ' ';
3822 break;
3824 case '\'': /* Handle character literals. */
3825 non_whitespace_since_newline = 1;
3826 while (scan_p[1] != '\'' || scan_p[0] == '\\')
3828 if (scan_p[0] == '\\'
3829 && !ISSPACE ((const unsigned char) scan_p[1]))
3830 scan_p[1] = ' ';
3831 if (!ISSPACE ((const unsigned char)*scan_p))
3832 *scan_p = ' ';
3833 if (++scan_p >= new_clean_text_limit)
3834 abort ();
3836 *scan_p++ = ' ';
3837 break;
3839 case '"': /* Handle string literals. */
3840 non_whitespace_since_newline = 1;
3841 while (scan_p[1] != '"' || scan_p[0] == '\\')
3843 if (scan_p[0] == '\\'
3844 && !ISSPACE ((const unsigned char) scan_p[1]))
3845 scan_p[1] = ' ';
3846 if (!ISSPACE ((const unsigned char)*scan_p))
3847 *scan_p = ' ';
3848 if (++scan_p >= new_clean_text_limit)
3849 abort ();
3851 if (!ISSPACE ((const unsigned char)*scan_p))
3852 *scan_p = ' ';
3853 scan_p++;
3854 break;
3856 case '\\': /* Handle line continuations. */
3857 if (scan_p[1] != '\n')
3858 goto regular;
3859 *scan_p = ' ';
3860 break;
3862 case '\n':
3863 non_whitespace_since_newline = 0; /* Reset. */
3864 break;
3866 case ' ':
3867 case '\v':
3868 case '\t':
3869 case '\r':
3870 case '\f':
3871 case '\b':
3872 break; /* Whitespace characters. */
3874 default:
3875 regular:
3876 non_whitespace_since_newline = 1;
3877 break;
3882 /* Given a pointer to the closing right parenthesis for a particular formals
3883 list (in the clean text buffer) find the corresponding left parenthesis
3884 and return a pointer to it. */
3886 static const char *
3887 careful_find_l_paren (p)
3888 const char *p;
3890 const char *q;
3891 int paren_depth;
3893 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
3895 switch (*q)
3897 case ')':
3898 paren_depth++;
3899 break;
3900 case '(':
3901 paren_depth--;
3902 break;
3905 return ++q;
3908 /* Scan the clean text buffer for cases of function definitions that we
3909 don't really know about because they were preprocessed out when the
3910 aux info files were created.
3912 In this version of protoize/unprotoize we just give a warning for each
3913 one found. A later version may be able to at least unprotoize such
3914 missed items.
3916 Note that we may easily find all function definitions simply by
3917 looking for places where there is a left paren which is (ignoring
3918 whitespace) immediately followed by either a left-brace or by an
3919 upper or lower case letter. Whenever we find this combination, we
3920 have also found a function definition header.
3922 Finding function *declarations* using syntactic clues is much harder.
3923 I will probably try to do this in a later version though. */
3925 static void
3926 scan_for_missed_items (file_p)
3927 const file_info *file_p;
3929 static const char *scan_p;
3930 const char *limit = clean_text_limit - 3;
3931 static const char *backup_limit;
3933 backup_limit = clean_text_base - 1;
3935 for (scan_p = clean_text_base; scan_p < limit; scan_p++)
3937 if (*scan_p == ')')
3939 static const char *last_r_paren;
3940 const char *ahead_p;
3942 last_r_paren = scan_p;
3944 for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
3945 check_source (++ahead_p < limit, limit);
3947 scan_p = ahead_p - 1;
3949 if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
3951 const char *last_l_paren;
3952 const int lineno = identify_lineno (ahead_p);
3954 if (setjmp (source_confusion_recovery))
3955 continue;
3957 /* We know we have a function definition header. Now skip
3958 leftwards over all of its associated formals lists. */
3962 last_l_paren = careful_find_l_paren (last_r_paren);
3963 for (last_r_paren = last_l_paren-1;
3964 ISSPACE ((const unsigned char)*last_r_paren); )
3965 check_source (--last_r_paren >= backup_limit, backup_limit);
3967 while (*last_r_paren == ')');
3969 if (is_id_char (*last_r_paren))
3971 const char *id_limit = last_r_paren + 1;
3972 const char *id_start;
3973 size_t id_length;
3974 const def_dec_info *dd_p;
3976 for (id_start = id_limit-1; is_id_char (*id_start); )
3977 check_source (--id_start >= backup_limit, backup_limit);
3978 id_start++;
3979 backup_limit = id_start;
3980 if ((id_length = (size_t) (id_limit - id_start)) == 0)
3981 goto not_missed;
3984 char *func_name = (char *) alloca (id_length + 1);
3985 static const char * const stmt_keywords[]
3986 = { "if", "else", "do", "while", "for", "switch", "case", "return", 0 };
3987 const char * const *stmt_keyword;
3989 strncpy (func_name, id_start, id_length);
3990 func_name[id_length] = '\0';
3992 /* We must check here to see if we are actually looking at
3993 a statement rather than an actual function call. */
3995 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
3996 if (!strcmp (func_name, *stmt_keyword))
3997 goto not_missed;
3999 #if 0
4000 notice ("%s: found definition of `%s' at %s(%d)\n",
4001 pname,
4002 func_name,
4003 shortpath (NULL, file_p->hash_entry->symbol),
4004 identify_lineno (id_start));
4005 #endif /* 0 */
4006 /* We really should check for a match of the function name
4007 here also, but why bother. */
4009 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
4010 if (dd_p->is_func_def && dd_p->line == lineno)
4011 goto not_missed;
4013 /* If we make it here, then we did not know about this
4014 function definition. */
4016 notice ("%s: %d: warning: `%s' excluded by preprocessing\n",
4017 shortpath (NULL, file_p->hash_entry->symbol),
4018 identify_lineno (id_start), func_name);
4019 notice ("%s: function definition not converted\n",
4020 pname);
4022 not_missed: ;
4029 /* Do all editing operations for a single source file (either a "base" file
4030 or an "include" file). To do this we read the file into memory, keep a
4031 virgin copy there, make another cleaned in-core copy of the original file
4032 (i.e. one in which all of the comments and preprocessing directives have
4033 been replaced with whitespace), then use these two in-core copies of the
4034 file to make a new edited in-core copy of the file. Finally, rename the
4035 original file (as a way of saving it), and then write the edited version
4036 of the file from core to a disk file of the same name as the original.
4038 Note that the trick of making a copy of the original sans comments &
4039 preprocessing directives make the editing a whole lot easier. */
4041 static void
4042 edit_file (hp)
4043 const hash_table_entry *hp;
4045 struct stat stat_buf;
4046 const file_info *file_p = hp->fip;
4047 char *new_orig_text_base;
4048 char *new_orig_text_limit;
4049 char *new_clean_text_base;
4050 char *new_clean_text_limit;
4051 size_t orig_size;
4052 size_t repl_size;
4053 int first_definition_in_file;
4055 /* If we are not supposed to be converting this file, or if there is
4056 nothing in there which needs converting, just skip this file. */
4058 if (!needs_to_be_converted (file_p))
4059 return;
4061 convert_filename = file_p->hash_entry->symbol;
4063 /* Convert a file if it is in a directory where we want conversion
4064 and the file is not excluded. */
4066 if (!directory_specified_p (convert_filename)
4067 || file_excluded_p (convert_filename))
4069 if (!quiet_flag
4070 #ifdef UNPROTOIZE
4071 /* Don't even mention "system" include files unless we are
4072 protoizing. If we are protoizing, we mention these as a
4073 gentle way of prodding the user to convert his "system"
4074 include files to prototype format. */
4075 && !in_system_include_dir (convert_filename)
4076 #endif /* defined (UNPROTOIZE) */
4078 notice ("%s: `%s' not converted\n",
4079 pname, shortpath (NULL, convert_filename));
4080 return;
4083 /* Let the user know what we are up to. */
4085 if (nochange_flag)
4086 notice ("%s: would convert file `%s'\n",
4087 pname, shortpath (NULL, convert_filename));
4088 else
4089 notice ("%s: converting file `%s'\n",
4090 pname, shortpath (NULL, convert_filename));
4091 fflush (stderr);
4093 /* Find out the size (in bytes) of the original file. */
4095 /* The cast avoids an erroneous warning on AIX. */
4096 if (stat (convert_filename, &stat_buf) == -1)
4098 int errno_val = errno;
4099 notice ("%s: can't get status for file `%s': %s\n",
4100 pname, shortpath (NULL, convert_filename),
4101 xstrerror (errno_val));
4102 return;
4104 orig_size = stat_buf.st_size;
4106 /* Allocate a buffer to hold the original text. */
4108 orig_text_base = new_orig_text_base = (char *) xmalloc (orig_size + 2);
4109 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
4111 /* Allocate a buffer to hold the cleaned-up version of the original text. */
4113 clean_text_base = new_clean_text_base = (char *) xmalloc (orig_size + 2);
4114 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
4115 clean_read_ptr = clean_text_base - 1;
4117 /* Allocate a buffer that will hopefully be large enough to hold the entire
4118 converted output text. As an initial guess for the maximum size of the
4119 output buffer, use 125% of the size of the original + some extra. This
4120 buffer can be expanded later as needed. */
4122 repl_size = orig_size + (orig_size >> 2) + 4096;
4123 repl_text_base = (char *) xmalloc (repl_size + 2);
4124 repl_text_limit = repl_text_base + repl_size - 1;
4125 repl_write_ptr = repl_text_base - 1;
4128 int input_file;
4129 int fd_flags;
4131 /* Open the file to be converted in READ ONLY mode. */
4133 fd_flags = O_RDONLY;
4134 #ifdef O_BINARY
4135 /* Use binary mode to avoid having to deal with different EOL characters. */
4136 fd_flags |= O_BINARY;
4137 #endif
4138 if ((input_file = open (convert_filename, fd_flags, 0444)) == -1)
4140 int errno_val = errno;
4141 notice ("%s: can't open file `%s' for reading: %s\n",
4142 pname, shortpath (NULL, convert_filename),
4143 xstrerror (errno_val));
4144 return;
4147 /* Read the entire original source text file into the original text buffer
4148 in one swell fwoop. Then figure out where the end of the text is and
4149 make sure that it ends with a newline followed by a null. */
4151 if (safe_read (input_file, new_orig_text_base, orig_size) !=
4152 (int) orig_size)
4154 int errno_val = errno;
4155 close (input_file);
4156 notice ("\n%s: error reading input file `%s': %s\n",
4157 pname, shortpath (NULL, convert_filename),
4158 xstrerror (errno_val));
4159 return;
4162 close (input_file);
4165 if (orig_size == 0 || orig_text_limit[-1] != '\n')
4167 *new_orig_text_limit++ = '\n';
4168 orig_text_limit++;
4171 /* Create the cleaned up copy of the original text. */
4173 memcpy (new_clean_text_base, orig_text_base,
4174 (size_t) (orig_text_limit - orig_text_base));
4175 do_cleaning (new_clean_text_base, new_clean_text_limit);
4177 #if 0
4179 int clean_file;
4180 size_t clean_size = orig_text_limit - orig_text_base;
4181 char *const clean_filename = (char *) alloca (strlen (convert_filename) + 6 + 1);
4183 /* Open (and create) the clean file. */
4185 strcpy (clean_filename, convert_filename);
4186 strcat (clean_filename, ".clean");
4187 if ((clean_file = creat (clean_filename, 0666)) == -1)
4189 int errno_val = errno;
4190 notice ("%s: can't create/open clean file `%s': %s\n",
4191 pname, shortpath (NULL, clean_filename),
4192 xstrerror (errno_val));
4193 return;
4196 /* Write the clean file. */
4198 safe_write (clean_file, new_clean_text_base, clean_size, clean_filename);
4200 close (clean_file);
4202 #endif /* 0 */
4204 /* Do a simplified scan of the input looking for things that were not
4205 mentioned in the aux info files because of the fact that they were
4206 in a region of the source which was preprocessed-out (via #if or
4207 via #ifdef). */
4209 scan_for_missed_items (file_p);
4211 /* Setup to do line-oriented forward seeking in the clean text buffer. */
4213 last_known_line_number = 1;
4214 last_known_line_start = clean_text_base;
4216 /* Now get down to business and make all of the necessary edits. */
4219 const def_dec_info *def_dec_p;
4221 first_definition_in_file = 1;
4222 def_dec_p = file_p->defs_decs;
4223 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
4225 const char *clean_text_p = seek_to_line (def_dec_p->line);
4227 /* clean_text_p now points to the first character of the line which
4228 contains the `terminator' for the declaration or definition that
4229 we are about to process. */
4231 #ifndef UNPROTOIZE
4233 if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
4235 add_global_decls (def_dec_p->file, clean_text_p);
4236 first_definition_in_file = 0;
4239 /* Don't edit this item if it is already in prototype format or if it
4240 is a function declaration and we have found no corresponding
4241 definition. */
4243 if (def_dec_p->prototyped
4244 || (!def_dec_p->is_func_def && !def_dec_p->definition))
4245 continue;
4247 #endif /* !defined (UNPROTOIZE) */
4249 if (def_dec_p->is_func_def)
4250 edit_fn_definition (def_dec_p, clean_text_p);
4251 else
4252 #ifndef UNPROTOIZE
4253 if (def_dec_p->is_implicit)
4254 add_local_decl (def_dec_p, clean_text_p);
4255 else
4256 #endif /* !defined (UNPROTOIZE) */
4257 edit_fn_declaration (def_dec_p, clean_text_p);
4261 /* Finalize things. Output the last trailing part of the original text. */
4263 output_up_to (clean_text_limit - 1);
4265 /* If this is just a test run, stop now and just deallocate the buffers. */
4267 if (nochange_flag)
4269 free (new_orig_text_base);
4270 free (new_clean_text_base);
4271 free (repl_text_base);
4272 return;
4275 /* Change the name of the original input file. This is just a quick way of
4276 saving the original file. */
4278 if (!nosave_flag)
4280 char *new_filename
4281 = (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
4283 strcpy (new_filename, convert_filename);
4284 #ifdef __MSDOS__
4285 /* MSDOS filenames are restricted to 8.3 format, so we save `foo.c'
4286 as `foo.<save_suffix>'. */
4287 new_filename[(strlen (convert_filename) - 1] = '\0';
4288 #endif
4289 strcat (new_filename, save_suffix);
4291 /* Don't overwrite existing file. */
4292 if (access (new_filename, F_OK) == 0)
4294 if (!quiet_flag)
4295 notice ("%s: warning: file `%s' already saved in `%s'\n",
4296 pname,
4297 shortpath (NULL, convert_filename),
4298 shortpath (NULL, new_filename));
4300 else if (rename (convert_filename, new_filename) == -1)
4302 int errno_val = errno;
4303 notice ("%s: can't link file `%s' to `%s': %s\n",
4304 pname,
4305 shortpath (NULL, convert_filename),
4306 shortpath (NULL, new_filename),
4307 xstrerror (errno_val));
4308 return;
4312 if (unlink (convert_filename) == -1)
4314 int errno_val = errno;
4315 /* The file may have already been renamed. */
4316 if (errno_val != ENOENT)
4318 notice ("%s: can't delete file `%s': %s\n",
4319 pname, shortpath (NULL, convert_filename),
4320 xstrerror (errno_val));
4321 return;
4326 int output_file;
4328 /* Open (and create) the output file. */
4330 if ((output_file = creat (convert_filename, 0666)) == -1)
4332 int errno_val = errno;
4333 notice ("%s: can't create/open output file `%s': %s\n",
4334 pname, shortpath (NULL, convert_filename),
4335 xstrerror (errno_val));
4336 return;
4338 #ifdef O_BINARY
4339 /* Use binary mode to avoid changing the existing EOL character. */
4340 setmode (output_file, O_BINARY);
4341 #endif
4343 /* Write the output file. */
4346 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
4348 safe_write (output_file, repl_text_base, out_size, convert_filename);
4351 close (output_file);
4354 /* Deallocate the conversion buffers. */
4356 free (new_orig_text_base);
4357 free (new_clean_text_base);
4358 free (repl_text_base);
4360 /* Change the mode of the output file to match the original file. */
4362 /* The cast avoids an erroneous warning on AIX. */
4363 if (chmod (convert_filename, stat_buf.st_mode) == -1)
4365 int errno_val = errno;
4366 notice ("%s: can't change mode of file `%s': %s\n",
4367 pname, shortpath (NULL, convert_filename),
4368 xstrerror (errno_val));
4371 /* Note: We would try to change the owner and group of the output file
4372 to match those of the input file here, except that may not be a good
4373 thing to do because it might be misleading. Also, it might not even
4374 be possible to do that (on BSD systems with quotas for instance). */
4377 /* Do all of the individual steps needed to do the protoization (or
4378 unprotoization) of the files referenced in the aux_info files given
4379 in the command line. */
4381 static void
4382 do_processing ()
4384 const char * const *base_pp;
4385 const char * const * const end_pps
4386 = &base_source_filenames[n_base_source_files];
4388 #ifndef UNPROTOIZE
4389 int syscalls_len;
4390 #endif /* !defined (UNPROTOIZE) */
4392 /* One-by-one, check (and create if necessary), open, and read all of the
4393 stuff in each aux_info file. After reading each aux_info file, the
4394 aux_info_file just read will be automatically deleted unless the
4395 keep_flag is set. */
4397 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
4398 process_aux_info_file (*base_pp, keep_flag, 0);
4400 #ifndef UNPROTOIZE
4402 /* Also open and read the special SYSCALLS.c aux_info file which gives us
4403 the prototypes for all of the standard system-supplied functions. */
4405 if (nondefault_syscalls_dir)
4407 syscalls_absolute_filename
4408 = (char *) xmalloc (strlen (nondefault_syscalls_dir) + 1
4409 + sizeof (syscalls_filename));
4410 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
4412 else
4414 GET_ENVIRONMENT (default_syscalls_dir, "GCC_EXEC_PREFIX");
4415 if (!default_syscalls_dir)
4417 default_syscalls_dir = standard_exec_prefix;
4419 syscalls_absolute_filename
4420 = (char *) xmalloc (strlen (default_syscalls_dir) + 0
4421 + strlen (target_machine) + 1
4422 + strlen (target_version) + 1
4423 + sizeof (syscalls_filename));
4424 strcpy (syscalls_absolute_filename, default_syscalls_dir);
4425 strcat (syscalls_absolute_filename, target_machine);
4426 strcat (syscalls_absolute_filename, "/");
4427 strcat (syscalls_absolute_filename, target_version);
4428 strcat (syscalls_absolute_filename, "/");
4431 syscalls_len = strlen (syscalls_absolute_filename);
4432 if (! IS_DIR_SEPARATOR (*(syscalls_absolute_filename + syscalls_len - 1)))
4434 *(syscalls_absolute_filename + syscalls_len++) = DIR_SEPARATOR;
4435 *(syscalls_absolute_filename + syscalls_len) = '\0';
4437 strcat (syscalls_absolute_filename, syscalls_filename);
4439 /* Call process_aux_info_file in such a way that it does not try to
4440 delete the SYSCALLS aux_info file. */
4442 process_aux_info_file (syscalls_absolute_filename, 1, 1);
4444 #endif /* !defined (UNPROTOIZE) */
4446 /* When we first read in all of the information from the aux_info files
4447 we saved in it descending line number order, because that was likely to
4448 be faster. Now however, we want the chains of def & dec records to
4449 appear in ascending line number order as we get further away from the
4450 file_info record that they hang from. The following line causes all of
4451 these lists to be rearranged into ascending line number order. */
4453 visit_each_hash_node (filename_primary, reverse_def_dec_list);
4455 #ifndef UNPROTOIZE
4457 /* Now do the "real" work. The following line causes each declaration record
4458 to be "visited". For each of these nodes, an attempt is made to match
4459 up the function declaration with a corresponding function definition,
4460 which should have a full prototype-format formals list with it. Once
4461 these match-ups are made, the conversion of the function declarations
4462 to prototype format can be made. */
4464 visit_each_hash_node (function_name_primary, connect_defs_and_decs);
4466 #endif /* !defined (UNPROTOIZE) */
4468 /* Now convert each file that can be converted (and needs to be). */
4470 visit_each_hash_node (filename_primary, edit_file);
4472 #ifndef UNPROTOIZE
4474 /* If we are working in cplusplus mode, try to rename all .c files to .C
4475 files. Don't panic if some of the renames don't work. */
4477 if (cplusplus_flag && !nochange_flag)
4478 visit_each_hash_node (filename_primary, rename_c_file);
4480 #endif /* !defined (UNPROTOIZE) */
4483 static const struct option longopts[] =
4485 {"version", 0, 0, 'V'},
4486 {"file_name", 0, 0, 'p'},
4487 {"quiet", 0, 0, 'q'},
4488 {"silent", 0, 0, 'q'},
4489 {"force", 0, 0, 'f'},
4490 {"keep", 0, 0, 'k'},
4491 {"nosave", 0, 0, 'N'},
4492 {"nochange", 0, 0, 'n'},
4493 {"compiler-options", 1, 0, 'c'},
4494 {"exclude", 1, 0, 'x'},
4495 {"directory", 1, 0, 'd'},
4496 #ifdef UNPROTOIZE
4497 {"indent", 1, 0, 'i'},
4498 #else
4499 {"local", 0, 0, 'l'},
4500 {"global", 0, 0, 'g'},
4501 {"c++", 0, 0, 'C'},
4502 {"syscalls-dir", 1, 0, 'B'},
4503 #endif
4504 {0, 0, 0, 0}
4507 extern int main PARAMS ((int, char **const));
4510 main (argc, argv)
4511 int argc;
4512 char **const argv;
4514 int longind;
4515 int c;
4516 const char *params = "";
4518 pname = strrchr (argv[0], DIR_SEPARATOR);
4519 #ifdef DIR_SEPARATOR_2
4521 char *slash;
4523 slash = strrchr (pname ? pname : argv[0], DIR_SEPARATOR_2);
4524 if (slash)
4525 pname = slash;
4527 #endif
4528 pname = pname ? pname+1 : argv[0];
4530 #ifdef SIGCHLD
4531 /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
4532 receive the signal. A different setting is inheritable */
4533 signal (SIGCHLD, SIG_DFL);
4534 #endif
4536 gcc_init_libintl ();
4538 cwd_buffer = getpwd ();
4539 if (!cwd_buffer)
4541 notice ("%s: cannot get working directory: %s\n",
4542 pname, xstrerror(errno));
4543 return (FATAL_EXIT_CODE);
4546 /* By default, convert the files in the current directory. */
4547 directory_list = string_list_cons (cwd_buffer, NULL);
4549 while ((c = getopt_long (argc, argv,
4550 #ifdef UNPROTOIZE
4551 "c:d:i:knNp:qvVx:",
4552 #else
4553 "B:c:Cd:gklnNp:qvVx:",
4554 #endif
4555 longopts, &longind)) != EOF)
4557 if (c == 0) /* Long option. */
4558 c = longopts[longind].val;
4559 switch (c)
4561 case 'p':
4562 compiler_file_name = optarg;
4563 break;
4564 case 'd':
4565 directory_list
4566 = string_list_cons (abspath (NULL, optarg), directory_list);
4567 break;
4568 case 'x':
4569 exclude_list = string_list_cons (optarg, exclude_list);
4570 break;
4572 case 'v':
4573 case 'V':
4574 version_flag = 1;
4575 break;
4576 case 'q':
4577 quiet_flag = 1;
4578 break;
4579 #if 0
4580 case 'f':
4581 force_flag = 1;
4582 break;
4583 #endif
4584 case 'n':
4585 nochange_flag = 1;
4586 keep_flag = 1;
4587 break;
4588 case 'N':
4589 nosave_flag = 1;
4590 break;
4591 case 'k':
4592 keep_flag = 1;
4593 break;
4594 case 'c':
4595 params = optarg;
4596 break;
4597 #ifdef UNPROTOIZE
4598 case 'i':
4599 indent_string = optarg;
4600 break;
4601 #else /* !defined (UNPROTOIZE) */
4602 case 'l':
4603 local_flag = 1;
4604 break;
4605 case 'g':
4606 global_flag = 1;
4607 break;
4608 case 'C':
4609 cplusplus_flag = 1;
4610 break;
4611 case 'B':
4612 nondefault_syscalls_dir = optarg;
4613 break;
4614 #endif /* !defined (UNPROTOIZE) */
4615 default:
4616 usage ();
4620 /* Set up compile_params based on -p and -c options. */
4621 munge_compile_params (params);
4623 n_base_source_files = argc - optind;
4625 /* Now actually make a list of the base source filenames. */
4627 base_source_filenames
4628 = (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *));
4629 n_base_source_files = 0;
4630 for (; optind < argc; optind++)
4632 const char *path = abspath (NULL, argv[optind]);
4633 int len = strlen (path);
4635 if (path[len-1] == 'c' && path[len-2] == '.')
4636 base_source_filenames[n_base_source_files++] = path;
4637 else
4639 notice ("%s: input file names must have .c suffixes: %s\n",
4640 pname, shortpath (NULL, path));
4641 errors++;
4645 #ifndef UNPROTOIZE
4646 /* We are only interested in the very first identifier token in the
4647 definition of `va_list', so if there is more junk after that first
4648 identifier token, delete it from the `varargs_style_indicator'. */
4650 const char *cp;
4652 for (cp = varargs_style_indicator; ISIDNUM (*cp); cp++)
4653 continue;
4654 if (*cp != 0)
4655 varargs_style_indicator = savestring (varargs_style_indicator,
4656 cp - varargs_style_indicator);
4658 #endif /* !defined (UNPROTOIZE) */
4660 if (errors)
4661 usage ();
4662 else
4664 if (version_flag)
4665 fprintf (stderr, "%s: %s\n", pname, version_string);
4666 do_processing ();
4669 return (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);