EnumSet*.class: Regenerate
[official-gcc.git] / gcc / protoize.c
blob0eb6957a969b5d299295328425945e1ccf84f8d3
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, 2003, 2004, 2005, 2007 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 3, 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 COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "intl.h"
26 #include "cppdefault.h"
28 #include <setjmp.h>
29 #include <signal.h>
30 #if ! defined( SIGCHLD ) && defined( SIGCLD )
31 # define SIGCHLD SIGCLD
32 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
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 #define IS_SAME_PATH(a,b) (FILENAME_CMP (a, b) == 0)
51 /* Suffix for aux-info files. */
52 #ifdef __MSDOS__
53 #define AUX_INFO_SUFFIX "X"
54 #else
55 #define AUX_INFO_SUFFIX ".X"
56 #endif
58 /* Suffix for saved files. */
59 #ifdef __MSDOS__
60 #define SAVE_SUFFIX "sav"
61 #else
62 #define SAVE_SUFFIX ".save"
63 #endif
65 /* Suffix for renamed C++ files. */
66 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
67 #define CPLUS_FILE_SUFFIX "cc"
68 #else
69 #define CPLUS_FILE_SUFFIX "C"
70 #endif
72 static void usage (void) ATTRIBUTE_NORETURN;
73 static void aux_info_corrupted (void) ATTRIBUTE_NORETURN;
74 static void declare_source_confusing (const char *) ATTRIBUTE_NORETURN;
75 static const char *shortpath (const char *, const char *);
76 static void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
77 static char *savestring (const char *, unsigned int);
78 static char *dupnstr (const char *, size_t);
79 static int safe_read (int, void *, int);
80 static void safe_write (int, void *, int, const char *);
81 static void save_pointers (void);
82 static void restore_pointers (void);
83 static int is_id_char (int);
84 static int in_system_include_dir (const char *);
85 static int directory_specified_p (const char *);
86 static int file_excluded_p (const char *);
87 static char *unexpand_if_needed (const char *);
88 static char *abspath (const char *, const char *);
89 static void check_aux_info (int);
90 static const char *find_corresponding_lparen (const char *);
91 static int referenced_file_is_newer (const char *, time_t);
92 static void save_def_or_dec (const char *, int);
93 static void munge_compile_params (const char *);
94 static int gen_aux_info_file (const char *);
95 static void process_aux_info_file (const char *, int, int);
96 static int identify_lineno (const char *);
97 static void check_source (int, const char *);
98 static const char *seek_to_line (int);
99 static const char *forward_to_next_token_char (const char *);
100 static void output_bytes (const char *, size_t);
101 static void output_string (const char *);
102 static void output_up_to (const char *);
103 static int other_variable_style_function (const char *);
104 static const char *find_rightmost_formals_list (const char *);
105 static void do_cleaning (char *, const char *);
106 static const char *careful_find_l_paren (const char *);
107 static void do_processing (void);
109 /* Look for these where the `const' qualifier is intentionally cast aside. */
110 #define NONCONST
112 /* Define a default place to find the SYSCALLS.X file. */
114 #ifndef UNPROTOIZE
116 #ifndef STANDARD_EXEC_PREFIX
117 #define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
118 #endif /* !defined STANDARD_EXEC_PREFIX */
120 static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX;
121 static const char * const target_machine = DEFAULT_TARGET_MACHINE;
122 static const char * const target_version = DEFAULT_TARGET_VERSION;
124 #endif /* !defined (UNPROTOIZE) */
126 /* Suffix of aux_info files. */
128 static const char * const aux_info_suffix = AUX_INFO_SUFFIX;
130 /* String to attach to filenames for saved versions of original files. */
132 static const char * const save_suffix = SAVE_SUFFIX;
134 #ifndef UNPROTOIZE
136 /* String to attach to C filenames renamed to C++. */
138 static const char * const cplus_suffix = CPLUS_FILE_SUFFIX;
140 /* File name of the file which contains descriptions of standard system
141 routines. Note that we never actually do anything with this file per se,
142 but we do read in its corresponding aux_info file. */
144 static const char syscalls_filename[] = "SYSCALLS.c";
146 /* Default place to find the above file. */
148 static const char * default_syscalls_dir;
150 /* Variable to hold the complete absolutized filename of the SYSCALLS.c.X
151 file. */
153 static char * syscalls_absolute_filename;
155 #endif /* !defined (UNPROTOIZE) */
157 /* Type of the structure that holds information about macro unexpansions. */
159 struct unexpansion_struct {
160 const char *const expanded;
161 const char *const contracted;
163 typedef struct unexpansion_struct unexpansion;
165 /* A table of conversions that may need to be made for some (stupid) older
166 operating systems where these types are preprocessor macros rather than
167 typedefs (as they really ought to be).
169 WARNING: The contracted forms must be as small (or smaller) as the
170 expanded forms, or else havoc will ensue. */
172 static const unexpansion unexpansions[] = {
173 { "struct _iobuf", "FILE" },
174 { 0, 0 }
177 /* The number of "primary" slots in the hash tables for filenames and for
178 function names. This can be as big or as small as you like, except that
179 it must be a power of two. */
181 #define HASH_TABLE_SIZE (1 << 9)
183 /* Bit mask to use when computing hash values. */
185 static const int hash_mask = (HASH_TABLE_SIZE - 1);
188 /* Datatype for lists of directories or filenames. */
189 struct string_list
191 const char *name;
192 struct string_list *next;
195 static struct string_list *string_list_cons (const char *,
196 struct string_list *);
198 /* List of directories in which files should be converted. */
200 struct string_list *directory_list;
202 /* List of file names which should not be converted.
203 A file is excluded if the end of its name, following a /,
204 matches one of the names in this list. */
206 struct string_list *exclude_list;
208 /* The name of the other style of variable-number-of-parameters functions
209 (i.e. the style that we want to leave unconverted because we don't yet
210 know how to convert them to this style. This string is used in warning
211 messages. */
213 /* Also define here the string that we can search for in the parameter lists
214 taken from the .X files which will unambiguously indicate that we have
215 found a varargs style function. */
217 #ifdef UNPROTOIZE
218 static const char * const other_var_style = "stdarg";
219 #else /* !defined (UNPROTOIZE) */
220 static const char * const other_var_style = "varargs";
221 static const char *varargs_style_indicator = "va_alist";
222 #endif /* !defined (UNPROTOIZE) */
224 /* The following two types are used to create hash tables. In this program,
225 there are two hash tables which are used to store and quickly lookup two
226 different classes of strings. The first type of strings stored in the
227 first hash table are absolute filenames of files which protoize needs to
228 know about. The second type of strings (stored in the second hash table)
229 are function names. It is this second class of strings which really
230 inspired the use of the hash tables, because there may be a lot of them. */
232 typedef struct hash_table_entry_struct hash_table_entry;
234 /* Do some typedefs so that we don't have to write "struct" so often. */
236 typedef struct def_dec_info_struct def_dec_info;
237 typedef struct file_info_struct file_info;
238 typedef struct f_list_chain_item_struct f_list_chain_item;
240 #ifndef UNPROTOIZE
241 static int is_syscalls_file (const file_info *);
242 static void rename_c_file (const hash_table_entry *);
243 static const def_dec_info *find_extern_def (const def_dec_info *,
244 const def_dec_info *);
245 static const def_dec_info *find_static_definition (const def_dec_info *);
246 static void connect_defs_and_decs (const hash_table_entry *);
247 static void add_local_decl (const def_dec_info *, const char *);
248 static void add_global_decls (const file_info *, const char *);
249 #endif /* ! UNPROTOIZE */
250 static int needs_to_be_converted (const file_info *);
251 static void visit_each_hash_node (const hash_table_entry *,
252 void (*)(const hash_table_entry *));
253 static hash_table_entry *add_symbol (hash_table_entry *, const char *);
254 static hash_table_entry *lookup (hash_table_entry *, const char *);
255 static void free_def_dec (def_dec_info *);
256 static file_info *find_file (const char *, int);
257 static void reverse_def_dec_list (const hash_table_entry *);
258 static void edit_fn_declaration (const def_dec_info *, const char *);
259 static int edit_formals_lists (const char *, unsigned int,
260 const def_dec_info *);
261 static void edit_fn_definition (const def_dec_info *, const char *);
262 static void scan_for_missed_items (const file_info *);
263 static void edit_file (const hash_table_entry *);
265 /* In the struct below, note that the "_info" field has two different uses
266 depending on the type of hash table we are in (i.e. either the filenames
267 hash table or the function names hash table). In the filenames hash table
268 the info fields of the entries point to the file_info struct which is
269 associated with each filename (1 per filename). In the function names
270 hash table, the info field points to the head of a singly linked list of
271 def_dec_info entries which are all defs or decs of the function whose
272 name is pointed to by the "symbol" field. Keeping all of the defs/decs
273 for a given function name on a special list specifically for that function
274 name makes it quick and easy to find out all of the important information
275 about a given (named) function. */
277 struct hash_table_entry_struct {
278 hash_table_entry * hash_next; /* -> to secondary entries */
279 const char * symbol; /* -> to the hashed string */
280 union {
281 const def_dec_info * _ddip;
282 file_info * _fip;
283 } _info;
285 #define ddip _info._ddip
286 #define fip _info._fip
288 /* Define a type specifically for our two hash tables. */
290 typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
292 /* The following struct holds all of the important information about any
293 single filename (e.g. file) which we need to know about. */
295 struct file_info_struct {
296 const hash_table_entry * hash_entry; /* -> to associated hash entry */
297 const def_dec_info * defs_decs; /* -> to chain of defs/decs */
298 time_t mtime; /* Time of last modification. */
301 /* Due to the possibility that functions may return pointers to functions,
302 (which may themselves have their own parameter lists) and due to the
303 fact that returned pointers-to-functions may be of type "pointer-to-
304 function-returning-pointer-to-function" (ad nauseum) we have to keep
305 an entire chain of ANSI style formal parameter lists for each function.
307 Normally, for any given function, there will only be one formals list
308 on the chain, but you never know.
310 Note that the head of each chain of formals lists is pointed to by the
311 `f_list_chain' field of the corresponding def_dec_info record.
313 For any given chain, the item at the head of the chain is the *leftmost*
314 parameter list seen in the actual C language function declaration. If
315 there are other members of the chain, then these are linked in left-to-right
316 order from the head of the chain. */
318 struct f_list_chain_item_struct {
319 const f_list_chain_item * chain_next; /* -> to next item on chain */
320 const char * formals_list; /* -> to formals list string */
323 /* The following struct holds all of the important information about any
324 single function definition or declaration which we need to know about.
325 Note that for unprotoize we don't need to know very much because we
326 never even create records for stuff that we don't intend to convert
327 (like for instance defs and decs which are already in old K&R format
328 and "implicit" function declarations). */
330 struct def_dec_info_struct {
331 const def_dec_info * next_in_file; /* -> to rest of chain for file */
332 file_info * file; /* -> file_info for containing file */
333 int line; /* source line number of def/dec */
334 const char * ansi_decl; /* -> left end of ansi decl */
335 hash_table_entry * hash_entry; /* -> hash entry for function name */
336 unsigned int is_func_def; /* = 0 means this is a declaration */
337 const def_dec_info * next_for_func; /* -> to rest of chain for func name */
338 unsigned int f_list_count; /* count of formals lists we expect */
339 char prototyped; /* = 0 means already prototyped */
340 #ifndef UNPROTOIZE
341 const f_list_chain_item * f_list_chain; /* -> chain of formals lists */
342 const def_dec_info * definition; /* -> def/dec containing related def */
343 char is_static; /* = 0 means visibility is "extern" */
344 char is_implicit; /* != 0 for implicit func decl's */
345 char written; /* != 0 means written for implicit */
346 #else /* !defined (UNPROTOIZE) */
347 const char * formal_names; /* -> to list of names of formals */
348 const char * formal_decls; /* -> to string of formal declarations */
349 #endif /* !defined (UNPROTOIZE) */
352 /* Pointer to the tail component of the filename by which this program was
353 invoked. Used everywhere in error and warning messages. */
355 static const char *pname;
357 /* Error counter. Will be nonzero if we should give up at the next convenient
358 stopping point. */
360 static int errors = 0;
362 /* Option flags. */
363 /* ??? The variables are not marked static because some of them have
364 the same names as gcc variables declared in options.h. */
365 /* ??? These comments should say what the flag mean as well as the options
366 that set them. */
368 /* File name to use for running gcc. Allows GCC 2 to be named
369 something other than gcc. */
370 static const char *compiler_file_name = "gcc";
372 int version_flag = 0; /* Print our version number. */
373 int quiet_flag = 0; /* Don't print messages normally. */
374 int nochange_flag = 0; /* Don't convert, just say what files
375 we would have converted. */
376 int nosave_flag = 0; /* Don't save the old version. */
377 int keep_flag = 0; /* Don't delete the .X files. */
378 static const char ** compile_params = 0; /* Option string for gcc. */
379 #ifdef UNPROTOIZE
380 static const char *indent_string = " "; /* Indentation for newly
381 inserted parm decls. */
382 #else /* !defined (UNPROTOIZE) */
383 int local_flag = 0; /* Insert new local decls (when?). */
384 int global_flag = 0; /* set by -g option */
385 int cplusplus_flag = 0; /* Rename converted files to *.C. */
386 static const char *nondefault_syscalls_dir = 0; /* Dir to look for
387 SYSCALLS.c.X in. */
388 #endif /* !defined (UNPROTOIZE) */
390 /* An index into the compile_params array where we should insert the source
391 file name when we are ready to exec the C compiler. A zero value indicates
392 that we have not yet called munge_compile_params. */
394 static int input_file_name_index = 0;
396 /* An index into the compile_params array where we should insert the filename
397 for the aux info file, when we run the C compiler. */
398 static int aux_info_file_name_index = 0;
400 /* Count of command line arguments which were "filename" arguments. */
402 static int n_base_source_files = 0;
404 /* Points to a malloc'ed list of pointers to all of the filenames of base
405 source files which were specified on the command line. */
407 static const char **base_source_filenames;
409 /* Line number of the line within the current aux_info file that we
410 are currently processing. Used for error messages in case the prototypes
411 info file is corrupted somehow. */
413 static int current_aux_info_lineno;
415 /* Pointer to the name of the source file currently being converted. */
417 static const char *convert_filename;
419 /* Pointer to relative root string (taken from aux_info file) which indicates
420 where directory the user was in when he did the compilation step that
421 produced the containing aux_info file. */
423 static const char *invocation_filename;
425 /* Pointer to the base of the input buffer that holds the original text for the
426 source file currently being converted. */
428 static const char *orig_text_base;
430 /* Pointer to the byte just beyond the end of the input buffer that holds the
431 original text for the source file currently being converted. */
433 static const char *orig_text_limit;
435 /* Pointer to the base of the input buffer that holds the cleaned text for the
436 source file currently being converted. */
438 static const char *clean_text_base;
440 /* Pointer to the byte just beyond the end of the input buffer that holds the
441 cleaned text for the source file currently being converted. */
443 static const char *clean_text_limit;
445 /* Pointer to the last byte in the cleaned text buffer that we have already
446 (virtually) copied to the output buffer (or decided to ignore). */
448 static const char * clean_read_ptr;
450 /* Pointer to the base of the output buffer that holds the replacement text
451 for the source file currently being converted. */
453 static char *repl_text_base;
455 /* Pointer to the byte just beyond the end of the output buffer that holds the
456 replacement text for the source file currently being converted. */
458 static char *repl_text_limit;
460 /* Pointer to the last byte which has been stored into the output buffer.
461 The next byte to be stored should be stored just past where this points
462 to. */
464 static char * repl_write_ptr;
466 /* Pointer into the cleaned text buffer for the source file we are currently
467 converting. This points to the first character of the line that we last
468 did a "seek_to_line" to (see below). */
470 static const char *last_known_line_start;
472 /* Number of the line (in the cleaned text buffer) that we last did a
473 "seek_to_line" to. Will be one if we just read a new source file
474 into the cleaned text buffer. */
476 static int last_known_line_number;
478 /* The filenames hash table. */
480 static hash_table filename_primary;
482 /* The function names hash table. */
484 static hash_table function_name_primary;
486 /* The place to keep the recovery address which is used only in cases where
487 we get hopelessly confused by something in the cleaned original text. */
489 static jmp_buf source_confusion_recovery;
491 /* A pointer to the current directory filename (used by abspath). */
493 static char *cwd_buffer;
495 /* A place to save the read pointer until we are sure that an individual
496 attempt at editing will succeed. */
498 static const char * saved_clean_read_ptr;
500 /* A place to save the write pointer until we are sure that an individual
501 attempt at editing will succeed. */
503 static char * saved_repl_write_ptr;
505 /* Translate and output an error message. */
506 static void
507 notice (const char *cmsgid, ...)
509 va_list ap;
511 va_start (ap, cmsgid);
512 vfprintf (stderr, _(cmsgid), ap);
513 va_end (ap);
517 /* Make a copy of a string INPUT with size SIZE. */
519 static char *
520 savestring (const char *input, unsigned int size)
522 char *output = xmalloc (size + 1);
523 strcpy (output, input);
524 return output;
528 /* Make a duplicate of the first N bytes of a given string in a newly
529 allocated area. */
531 static char *
532 dupnstr (const char *s, size_t n)
534 char *ret_val = xmalloc (n + 1);
536 strncpy (ret_val, s, n);
537 ret_val[n] = '\0';
538 return ret_val;
541 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
542 retrying if necessary. Return the actual number of bytes read. */
544 static int
545 safe_read (int desc, void *ptr, int len)
547 int left = len;
548 while (left > 0) {
549 int nchars = read (desc, ptr, left);
550 if (nchars < 0)
552 #ifdef EINTR
553 if (errno == EINTR)
554 continue;
555 #endif
556 return nchars;
558 if (nchars == 0)
559 break;
560 /* Arithmetic on void pointers is a gcc extension. */
561 ptr = (char *) ptr + nchars;
562 left -= nchars;
564 return len - left;
567 /* Write LEN bytes at PTR to descriptor DESC,
568 retrying if necessary, and treating any real error as fatal. */
570 static void
571 safe_write (int desc, void *ptr, int len, const char *out_fname)
573 while (len > 0) {
574 int written = write (desc, ptr, len);
575 if (written < 0)
577 int errno_val = errno;
578 #ifdef EINTR
579 if (errno_val == EINTR)
580 continue;
581 #endif
582 notice ("%s: error writing file '%s': %s\n",
583 pname, shortpath (NULL, out_fname), xstrerror (errno_val));
584 return;
586 /* Arithmetic on void pointers is a gcc extension. */
587 ptr = (char *) ptr + written;
588 len -= written;
592 /* Get setup to recover in case the edit we are about to do goes awry. */
594 static void
595 save_pointers (void)
597 saved_clean_read_ptr = clean_read_ptr;
598 saved_repl_write_ptr = repl_write_ptr;
601 /* Call this routine to recover our previous state whenever something looks
602 too confusing in the source code we are trying to edit. */
604 static void
605 restore_pointers (void)
607 clean_read_ptr = saved_clean_read_ptr;
608 repl_write_ptr = saved_repl_write_ptr;
611 /* Return true if the given character is a valid identifier character. */
613 static int
614 is_id_char (int ch)
616 return (ISIDNUM (ch) || (ch == '$'));
619 /* Give a message indicating the proper way to invoke this program and then
620 exit with nonzero status. */
622 static void
623 usage (void)
625 #ifdef UNPROTOIZE
626 notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
627 pname, pname);
628 #else /* !defined (UNPROTOIZE) */
629 notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
630 pname, pname);
631 #endif /* !defined (UNPROTOIZE) */
632 exit (FATAL_EXIT_CODE);
635 /* Return true if the given filename (assumed to be an absolute filename)
636 designates a file residing anywhere beneath any one of the "system"
637 include directories. */
639 static int
640 in_system_include_dir (const char *path)
642 const struct default_include *p;
644 gcc_assert (IS_ABSOLUTE_PATH (path));
646 for (p = cpp_include_defaults; p->fname; p++)
647 if (!strncmp (path, p->fname, strlen (p->fname))
648 && IS_DIR_SEPARATOR (path[strlen (p->fname)]))
649 return 1;
650 return 0;
653 #if 0
654 /* Return true if the given filename designates a file that the user has
655 read access to and for which the user has write access to the containing
656 directory. */
658 static int
659 file_could_be_converted (const char *path)
661 char *const dir_name = alloca (strlen (path) + 1);
663 if (access (path, R_OK))
664 return 0;
667 char *dir_last_slash;
669 strcpy (dir_name, path);
670 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
671 #ifdef DIR_SEPARATOR_2
673 char *slash;
675 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
676 DIR_SEPARATOR_2);
677 if (slash)
678 dir_last_slash = slash;
680 #endif
681 gcc_assert (dir_last_slash);
682 *dir_last_slash = '\0';
685 if (access (path, W_OK))
686 return 0;
688 return 1;
691 /* Return true if the given filename designates a file that we are allowed
692 to modify. Files which we should not attempt to modify are (a) "system"
693 include files, and (b) files which the user doesn't have write access to,
694 and (c) files which reside in directories which the user doesn't have
695 write access to. Unless requested to be quiet, give warnings about
696 files that we will not try to convert for one reason or another. An
697 exception is made for "system" include files, which we never try to
698 convert and for which we don't issue the usual warnings. */
700 static int
701 file_normally_convertible (const char *path)
703 char *const dir_name = alloca (strlen (path) + 1);
705 if (in_system_include_dir (path))
706 return 0;
709 char *dir_last_slash;
711 strcpy (dir_name, path);
712 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
713 #ifdef DIR_SEPARATOR_2
715 char *slash;
717 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
718 DIR_SEPARATOR_2);
719 if (slash)
720 dir_last_slash = slash;
722 #endif
723 gcc_assert (dir_last_slash);
724 *dir_last_slash = '\0';
727 if (access (path, R_OK))
729 if (!quiet_flag)
730 notice ("%s: warning: no read access for file '%s'\n",
731 pname, shortpath (NULL, path));
732 return 0;
735 if (access (path, W_OK))
737 if (!quiet_flag)
738 notice ("%s: warning: no write access for file '%s'\n",
739 pname, shortpath (NULL, path));
740 return 0;
743 if (access (dir_name, W_OK))
745 if (!quiet_flag)
746 notice ("%s: warning: no write access for dir containing '%s'\n",
747 pname, shortpath (NULL, path));
748 return 0;
751 return 1;
753 #endif /* 0 */
755 #ifndef UNPROTOIZE
757 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X
758 file. Return false otherwise. */
760 static int
761 is_syscalls_file (const file_info *fi_p)
763 char const *f = fi_p->hash_entry->symbol;
764 size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
765 return sysl <= fl && strcmp (f + fl - sysl, syscalls_filename) == 0;
768 #endif /* !defined (UNPROTOIZE) */
770 /* Check to see if this file will need to have anything done to it on this
771 run. If there is nothing in the given file which both needs conversion
772 and for which we have the necessary stuff to do the conversion, return
773 false. Otherwise, return true.
775 Note that (for protoize) it is only valid to call this function *after*
776 the connections between declarations and definitions have all been made
777 by connect_defs_and_decs. */
779 static int
780 needs_to_be_converted (const file_info *file_p)
782 const def_dec_info *ddp;
784 #ifndef UNPROTOIZE
786 if (is_syscalls_file (file_p))
787 return 0;
789 #endif /* !defined (UNPROTOIZE) */
791 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
793 if (
795 #ifndef UNPROTOIZE
797 /* ... and if we a protoizing and this function is in old style ... */
798 !ddp->prototyped
799 /* ... and if this a definition or is a decl with an associated def ... */
800 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
802 #else /* defined (UNPROTOIZE) */
804 /* ... and if we are unprotoizing and this function is in new style ... */
805 ddp->prototyped
807 #endif /* defined (UNPROTOIZE) */
809 /* ... then the containing file needs converting. */
810 return -1;
811 return 0;
814 /* Return 1 if the file name NAME is in a directory
815 that should be converted. */
817 static int
818 directory_specified_p (const char *name)
820 struct string_list *p;
822 for (p = directory_list; p; p = p->next)
823 if (!strncmp (name, p->name, strlen (p->name))
824 && IS_DIR_SEPARATOR (name[strlen (p->name)]))
826 const char *q = name + strlen (p->name) + 1;
828 /* If there are more slashes, it's in a subdir, so
829 this match doesn't count. */
830 while (*q++)
831 if (IS_DIR_SEPARATOR (*(q-1)))
832 goto lose;
833 return 1;
835 lose: ;
838 return 0;
841 /* Return 1 if the file named NAME should be excluded from conversion. */
843 static int
844 file_excluded_p (const char *name)
846 struct string_list *p;
847 int len = strlen (name);
849 for (p = exclude_list; p; p = p->next)
850 if (!strcmp (name + len - strlen (p->name), p->name)
851 && IS_DIR_SEPARATOR (name[len - strlen (p->name) - 1]))
852 return 1;
854 return 0;
857 /* Construct a new element of a string_list.
858 STRING is the new element value, and REST holds the remaining elements. */
860 static struct string_list *
861 string_list_cons (const char *string, struct string_list *rest)
863 struct string_list *temp = xmalloc (sizeof (struct string_list));
865 temp->next = rest;
866 temp->name = string;
867 return temp;
870 /* ??? The GNU convention for mentioning function args in its comments
871 is to capitalize them. So change "hash_tab_p" to HASH_TAB_P below.
872 Likewise for all the other functions. */
874 /* Given a hash table, apply some function to each node in the table. The
875 table to traverse is given as the "hash_tab_p" argument, and the
876 function to be applied to each node in the table is given as "func"
877 argument. */
879 static void
880 visit_each_hash_node (const hash_table_entry *hash_tab_p,
881 void (*func) (const hash_table_entry *))
883 const hash_table_entry *primary;
885 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
886 if (primary->symbol)
888 hash_table_entry *second;
890 (*func)(primary);
891 for (second = primary->hash_next; second; second = second->hash_next)
892 (*func) (second);
896 /* Initialize all of the fields of a new hash table entry, pointed
897 to by the "p" parameter. Note that the space to hold the entry
898 is assumed to have already been allocated before this routine is
899 called. */
901 static hash_table_entry *
902 add_symbol (hash_table_entry *p, const char *s)
904 p->hash_next = NULL;
905 p->symbol = xstrdup (s);
906 p->ddip = NULL;
907 p->fip = NULL;
908 return p;
911 /* Look for a particular function name or filename in the particular
912 hash table indicated by "hash_tab_p". If the name is not in the
913 given hash table, add it. Either way, return a pointer to the
914 hash table entry for the given name. */
916 static hash_table_entry *
917 lookup (hash_table_entry *hash_tab_p, const char *search_symbol)
919 int hash_value = 0;
920 const char *search_symbol_char_p = search_symbol;
921 hash_table_entry *p;
923 while (*search_symbol_char_p)
924 hash_value += *search_symbol_char_p++;
925 hash_value &= hash_mask;
926 p = &hash_tab_p[hash_value];
927 if (! p->symbol)
928 return add_symbol (p, search_symbol);
929 if (!strcmp (p->symbol, search_symbol))
930 return p;
931 while (p->hash_next)
933 p = p->hash_next;
934 if (!strcmp (p->symbol, search_symbol))
935 return p;
937 p->hash_next = xmalloc (sizeof (hash_table_entry));
938 p = p->hash_next;
939 return add_symbol (p, search_symbol);
942 /* Throw a def/dec record on the junk heap.
944 Also, since we are not using this record anymore, free up all of the
945 stuff it pointed to. */
947 static void
948 free_def_dec (def_dec_info *p)
950 free ((NONCONST void *) p->ansi_decl);
952 #ifndef UNPROTOIZE
954 const f_list_chain_item * curr;
955 const f_list_chain_item * next;
957 for (curr = p->f_list_chain; curr; curr = next)
959 next = curr->chain_next;
960 free ((NONCONST void *) curr);
963 #endif /* !defined (UNPROTOIZE) */
965 free (p);
968 /* Unexpand as many macro symbols as we can find.
970 If the given line must be unexpanded, make a copy of it in the heap and
971 return a pointer to the unexpanded copy. Otherwise return NULL. */
973 static char *
974 unexpand_if_needed (const char *aux_info_line)
976 static char *line_buf = 0;
977 static int line_buf_size = 0;
978 const unexpansion *unexp_p;
979 int got_unexpanded = 0;
980 const char *s;
981 char *copy_p = line_buf;
983 if (line_buf == 0)
985 line_buf_size = 1024;
986 line_buf = xmalloc (line_buf_size);
989 copy_p = line_buf;
991 /* Make a copy of the input string in line_buf, expanding as necessary. */
993 for (s = aux_info_line; *s != '\n'; )
995 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
997 const char *in_p = unexp_p->expanded;
998 size_t len = strlen (in_p);
1000 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1002 int size = strlen (unexp_p->contracted);
1003 got_unexpanded = 1;
1004 if (copy_p + size - line_buf >= line_buf_size)
1006 int offset = copy_p - line_buf;
1007 line_buf_size *= 2;
1008 line_buf_size += size;
1009 line_buf = xrealloc (line_buf, line_buf_size);
1010 copy_p = line_buf + offset;
1012 strcpy (copy_p, unexp_p->contracted);
1013 copy_p += size;
1015 /* Assume that there will not be another replacement required
1016 within the text just replaced. */
1018 s += len;
1019 goto continue_outer;
1022 if (copy_p - line_buf == line_buf_size)
1024 int offset = copy_p - line_buf;
1025 line_buf_size *= 2;
1026 line_buf = xrealloc (line_buf, line_buf_size);
1027 copy_p = line_buf + offset;
1029 *copy_p++ = *s++;
1030 continue_outer: ;
1032 if (copy_p + 2 - line_buf >= line_buf_size)
1034 int offset = copy_p - line_buf;
1035 line_buf_size *= 2;
1036 line_buf = xrealloc (line_buf, line_buf_size);
1037 copy_p = line_buf + offset;
1039 *copy_p++ = '\n';
1040 *copy_p = '\0';
1042 return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
1045 /* Return the absolutized filename for the given relative
1046 filename. Note that if that filename is already absolute, it may
1047 still be returned in a modified form because this routine also
1048 eliminates redundant slashes and single dots and eliminates double
1049 dots to get a shortest possible filename from the given input
1050 filename. The absolutization of relative filenames is made by
1051 assuming that the given filename is to be taken as relative to
1052 the first argument (cwd) or to the current directory if cwd is
1053 NULL. */
1055 static char *
1056 abspath (const char *cwd, const char *rel_filename)
1058 /* Setup the current working directory as needed. */
1059 const char *const cwd2 = (cwd) ? cwd : cwd_buffer;
1060 char *const abs_buffer = alloca (strlen (cwd2) + strlen (rel_filename) + 2);
1061 char *endp = abs_buffer;
1062 char *outp, *inp;
1064 /* Copy the filename (possibly preceded by the current working
1065 directory name) into the absolutization buffer. */
1068 const char *src_p;
1070 if (! IS_ABSOLUTE_PATH (rel_filename))
1072 src_p = cwd2;
1073 while ((*endp++ = *src_p++))
1074 continue;
1075 *(endp-1) = DIR_SEPARATOR; /* overwrite null */
1077 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1078 else if (IS_DIR_SEPARATOR (rel_filename[0]))
1080 /* A path starting with a directory separator is considered absolute
1081 for dos based filesystems, but it's really not -- it's just the
1082 convention used throughout GCC and it works. However, in this
1083 case, we still need to prepend the drive spec from cwd_buffer. */
1084 *endp++ = cwd2[0];
1085 *endp++ = cwd2[1];
1087 #endif
1088 src_p = rel_filename;
1089 while ((*endp++ = *src_p++))
1090 continue;
1093 /* Now make a copy of abs_buffer into abs_buffer, shortening the
1094 filename (by taking out slashes and dots) as we go. */
1096 outp = inp = abs_buffer;
1097 *outp++ = *inp++; /* copy first slash */
1098 #if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
1099 if (IS_DIR_SEPARATOR (inp[0]))
1100 *outp++ = *inp++; /* copy second slash */
1101 #endif
1102 for (;;)
1104 if (!inp[0])
1105 break;
1106 else if (IS_DIR_SEPARATOR (inp[0]) && IS_DIR_SEPARATOR (outp[-1]))
1108 inp++;
1109 continue;
1111 else if (inp[0] == '.' && IS_DIR_SEPARATOR (outp[-1]))
1113 if (!inp[1])
1114 break;
1115 else if (IS_DIR_SEPARATOR (inp[1]))
1117 inp += 2;
1118 continue;
1120 else if ((inp[1] == '.') && (inp[2] == 0
1121 || IS_DIR_SEPARATOR (inp[2])))
1123 inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2;
1124 outp -= 2;
1125 while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*outp))
1126 outp--;
1127 if (outp < abs_buffer)
1129 /* Catch cases like /.. where we try to backup to a
1130 point above the absolute root of the logical file
1131 system. */
1133 notice ("%s: invalid file name: %s\n",
1134 pname, rel_filename);
1135 exit (FATAL_EXIT_CODE);
1137 *++outp = '\0';
1138 continue;
1141 *outp++ = *inp++;
1144 /* On exit, make sure that there is a trailing null, and make sure that
1145 the last character of the returned string is *not* a slash. */
1147 *outp = '\0';
1148 if (IS_DIR_SEPARATOR (outp[-1]))
1149 *--outp = '\0';
1151 /* Make a copy (in the heap) of the stuff left in the absolutization
1152 buffer and return a pointer to the copy. */
1154 return savestring (abs_buffer, outp - abs_buffer);
1157 /* Given a filename (and possibly a directory name from which the filename
1158 is relative) return a string which is the shortest possible
1159 equivalent for the corresponding full (absolutized) filename. The
1160 shortest possible equivalent may be constructed by converting the
1161 absolutized filename to be a relative filename (i.e. relative to
1162 the actual current working directory). However if a relative filename
1163 is longer, then the full absolute filename is returned.
1165 KNOWN BUG:
1167 Note that "simple-minded" conversion of any given type of filename (either
1168 relative or absolute) may not result in a valid equivalent filename if any
1169 subpart of the original filename is actually a symbolic link. */
1171 static const char *
1172 shortpath (const char *cwd, const char *filename)
1174 char *rel_buffer;
1175 char *rel_buf_p;
1176 char *cwd_p = cwd_buffer;
1177 char *path_p;
1178 int unmatched_slash_count = 0;
1179 size_t filename_len = strlen (filename);
1181 path_p = abspath (cwd, filename);
1182 rel_buf_p = rel_buffer = xmalloc (filename_len);
1184 while (*cwd_p && IS_SAME_PATH_CHAR (*cwd_p, *path_p))
1186 cwd_p++;
1187 path_p++;
1189 if (!*cwd_p && (!*path_p || IS_DIR_SEPARATOR (*path_p)))
1191 /* whole pwd matched */
1192 if (!*path_p) /* input *is* the current path! */
1193 return ".";
1194 else
1195 return ++path_p;
1197 else
1199 if (*path_p)
1201 --cwd_p;
1202 --path_p;
1203 while (! IS_DIR_SEPARATOR (*cwd_p)) /* backup to last slash */
1205 --cwd_p;
1206 --path_p;
1208 cwd_p++;
1209 path_p++;
1210 unmatched_slash_count++;
1213 /* Find out how many directory levels in cwd were *not* matched. */
1214 while (*cwd_p++)
1215 if (IS_DIR_SEPARATOR (*(cwd_p-1)))
1216 unmatched_slash_count++;
1218 /* Now we know how long the "short name" will be.
1219 Reject it if longer than the input. */
1220 if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
1221 return filename;
1223 /* For each of them, put a `../' at the beginning of the short name. */
1224 while (unmatched_slash_count--)
1226 /* Give up if the result gets to be longer
1227 than the absolute path name. */
1228 if (rel_buffer + filename_len <= rel_buf_p + 3)
1229 return filename;
1230 *rel_buf_p++ = '.';
1231 *rel_buf_p++ = '.';
1232 *rel_buf_p++ = DIR_SEPARATOR;
1235 /* Then tack on the unmatched part of the desired file's name. */
1238 if (rel_buffer + filename_len <= rel_buf_p)
1239 return filename;
1241 while ((*rel_buf_p++ = *path_p++));
1243 --rel_buf_p;
1244 if (IS_DIR_SEPARATOR (*(rel_buf_p-1)))
1245 *--rel_buf_p = '\0';
1246 return rel_buffer;
1250 /* Lookup the given filename in the hash table for filenames. If it is a
1251 new one, then the hash table info pointer will be null. In this case,
1252 we create a new file_info record to go with the filename, and we initialize
1253 that record with some reasonable values. */
1255 /* FILENAME was const, but that causes a warning on AIX when calling stat.
1256 That is probably a bug in AIX, but might as well avoid the warning. */
1258 static file_info *
1259 find_file (const char *filename, int do_not_stat)
1261 hash_table_entry *hash_entry_p;
1263 hash_entry_p = lookup (filename_primary, filename);
1264 if (hash_entry_p->fip)
1265 return hash_entry_p->fip;
1266 else
1268 struct stat stat_buf;
1269 file_info *file_p = xmalloc (sizeof (file_info));
1271 /* If we cannot get status on any given source file, give a warning
1272 and then just set its time of last modification to infinity. */
1274 if (do_not_stat)
1275 stat_buf.st_mtime = (time_t) 0;
1276 else
1278 if (stat (filename, &stat_buf) == -1)
1280 int errno_val = errno;
1281 notice ("%s: %s: can't get status: %s\n",
1282 pname, shortpath (NULL, filename),
1283 xstrerror (errno_val));
1284 stat_buf.st_mtime = (time_t) -1;
1288 hash_entry_p->fip = file_p;
1289 file_p->hash_entry = hash_entry_p;
1290 file_p->defs_decs = NULL;
1291 file_p->mtime = stat_buf.st_mtime;
1292 return file_p;
1296 /* Generate a fatal error because some part of the aux_info file is
1297 messed up. */
1299 static void
1300 aux_info_corrupted (void)
1302 notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
1303 pname, current_aux_info_lineno);
1304 exit (FATAL_EXIT_CODE);
1307 /* ??? This comment is vague. Say what the condition is for. */
1308 /* Check to see that a condition is true. This is kind of like an assert. */
1310 static void
1311 check_aux_info (int cond)
1313 if (! cond)
1314 aux_info_corrupted ();
1317 /* Given a pointer to the closing right parenthesis for a particular formals
1318 list (in an aux_info file) find the corresponding left parenthesis and
1319 return a pointer to it. */
1321 static const char *
1322 find_corresponding_lparen (const char *p)
1324 const char *q;
1325 int paren_depth;
1327 for (paren_depth = 1, q = p-1; paren_depth; q--)
1329 switch (*q)
1331 case ')':
1332 paren_depth++;
1333 break;
1334 case '(':
1335 paren_depth--;
1336 break;
1339 return ++q;
1342 /* Given a line from an aux info file, and a time at which the aux info
1343 file it came from was created, check to see if the item described in
1344 the line comes from a file which has been modified since the aux info
1345 file was created. If so, return nonzero, else return zero. */
1347 static int
1348 referenced_file_is_newer (const char *l, time_t aux_info_mtime)
1350 const char *p;
1351 file_info *fi_p;
1352 char *filename;
1354 check_aux_info (l[0] == '/');
1355 check_aux_info (l[1] == '*');
1356 check_aux_info (l[2] == ' ');
1359 const char *filename_start = p = l + 3;
1361 while (*p != ':'
1362 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1363 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1364 #endif
1366 p++;
1367 filename = alloca ((size_t) (p - filename_start) + 1);
1368 strncpy (filename, filename_start, (size_t) (p - filename_start));
1369 filename[p-filename_start] = '\0';
1372 /* Call find_file to find the file_info record associated with the file
1373 which contained this particular def or dec item. Note that this call
1374 may cause a new file_info record to be created if this is the first time
1375 that we have ever known about this particular file. */
1377 fi_p = find_file (abspath (invocation_filename, filename), 0);
1379 return (fi_p->mtime > aux_info_mtime);
1382 /* Given a line of info from the aux_info file, create a new
1383 def_dec_info record to remember all of the important information about
1384 a function definition or declaration.
1386 Link this record onto the list of such records for the particular file in
1387 which it occurred in proper (descending) line number order (for now).
1389 If there is an identical record already on the list for the file, throw
1390 this one away. Doing so takes care of the (useless and troublesome)
1391 duplicates which are bound to crop up due to multiple inclusions of any
1392 given individual header file.
1394 Finally, link the new def_dec record onto the list of such records
1395 pertaining to this particular function name. */
1397 static void
1398 save_def_or_dec (const char *l, int is_syscalls)
1400 const char *p;
1401 const char *semicolon_p;
1402 def_dec_info *def_dec_p = xmalloc (sizeof (def_dec_info));
1404 #ifndef UNPROTOIZE
1405 def_dec_p->written = 0;
1406 #endif /* !defined (UNPROTOIZE) */
1408 /* Start processing the line by picking off 5 pieces of information from
1409 the left hand end of the line. These are filename, line number,
1410 new/old/implicit flag (new = ANSI prototype format), definition or
1411 declaration flag, and extern/static flag). */
1413 check_aux_info (l[0] == '/');
1414 check_aux_info (l[1] == '*');
1415 check_aux_info (l[2] == ' ');
1418 const char *filename_start = p = l + 3;
1419 char *filename;
1421 while (*p != ':'
1422 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1423 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1424 #endif
1426 p++;
1427 filename = alloca ((size_t) (p - filename_start) + 1);
1428 strncpy (filename, filename_start, (size_t) (p - filename_start));
1429 filename[p-filename_start] = '\0';
1431 /* Call find_file to find the file_info record associated with the file
1432 which contained this particular def or dec item. Note that this call
1433 may cause a new file_info record to be created if this is the first time
1434 that we have ever known about this particular file.
1436 Note that we started out by forcing all of the base source file names
1437 (i.e. the names of the aux_info files with the .X stripped off) into the
1438 filenames hash table, and we simultaneously setup file_info records for
1439 all of these base file names (even if they may be useless later).
1440 The file_info records for all of these "base" file names (properly)
1441 act as file_info records for the "original" (i.e. un-included) files
1442 which were submitted to gcc for compilation (when the -aux-info
1443 option was used). */
1445 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1449 const char *line_number_start = ++p;
1450 char line_number[10];
1452 while (*p != ':'
1453 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1454 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1455 #endif
1457 p++;
1458 strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1459 line_number[p-line_number_start] = '\0';
1460 def_dec_p->line = atoi (line_number);
1463 /* Check that this record describes a new-style, old-style, or implicit
1464 definition or declaration. */
1466 p++; /* Skip over the `:'. */
1467 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1469 /* Is this a new style (ANSI prototyped) definition or declaration? */
1471 def_dec_p->prototyped = (*p == 'N');
1473 #ifndef UNPROTOIZE
1475 /* Is this an implicit declaration? */
1477 def_dec_p->is_implicit = (*p == 'I');
1479 #endif /* !defined (UNPROTOIZE) */
1481 p++;
1483 check_aux_info ((*p == 'C') || (*p == 'F'));
1485 /* Is this item a function definition (F) or a declaration (C). Note that
1486 we treat item taken from the syscalls file as though they were function
1487 definitions regardless of what the stuff in the file says. */
1489 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1491 #ifndef UNPROTOIZE
1492 def_dec_p->definition = 0; /* Fill this in later if protoizing. */
1493 #endif /* !defined (UNPROTOIZE) */
1495 check_aux_info (*p++ == ' ');
1496 check_aux_info (*p++ == '*');
1497 check_aux_info (*p++ == '/');
1498 check_aux_info (*p++ == ' ');
1500 #ifdef UNPROTOIZE
1501 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1502 #else /* !defined (UNPROTOIZE) */
1503 if (!strncmp (p, "static", 6))
1504 def_dec_p->is_static = -1;
1505 else if (!strncmp (p, "extern", 6))
1506 def_dec_p->is_static = 0;
1507 else
1508 check_aux_info (0); /* Didn't find either `extern' or `static'. */
1509 #endif /* !defined (UNPROTOIZE) */
1512 const char *ansi_start = p;
1514 p += 6; /* Pass over the "static" or "extern". */
1516 /* We are now past the initial stuff. Search forward from here to find
1517 the terminating semicolon that should immediately follow the entire
1518 ANSI format function declaration. */
1520 while (*++p != ';')
1521 continue;
1523 semicolon_p = p;
1525 /* Make a copy of the ansi declaration part of the line from the aux_info
1526 file. */
1528 def_dec_p->ansi_decl
1529 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1531 /* Backup and point at the final right paren of the final argument list. */
1533 p--;
1535 #ifndef UNPROTOIZE
1536 def_dec_p->f_list_chain = NULL;
1537 #endif /* !defined (UNPROTOIZE) */
1539 while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
1540 if (*p != ')')
1542 free_def_dec (def_dec_p);
1543 return;
1547 /* Now isolate a whole set of formal argument lists, one-by-one. Normally,
1548 there will only be one list to isolate, but there could be more. */
1550 def_dec_p->f_list_count = 0;
1552 for (;;)
1554 const char *left_paren_p = find_corresponding_lparen (p);
1555 #ifndef UNPROTOIZE
1557 f_list_chain_item *cip = xmalloc (sizeof (f_list_chain_item));
1559 cip->formals_list
1560 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1562 /* Add the new chain item at the head of the current list. */
1564 cip->chain_next = def_dec_p->f_list_chain;
1565 def_dec_p->f_list_chain = cip;
1567 #endif /* !defined (UNPROTOIZE) */
1568 def_dec_p->f_list_count++;
1570 p = left_paren_p - 2;
1572 /* p must now point either to another right paren, or to the last
1573 character of the name of the function that was declared/defined.
1574 If p points to another right paren, then this indicates that we
1575 are dealing with multiple formals lists. In that case, there
1576 really should be another right paren preceding this right paren. */
1578 if (*p != ')')
1579 break;
1580 else
1581 check_aux_info (*--p == ')');
1586 const char *past_fn = p + 1;
1588 check_aux_info (*past_fn == ' ');
1590 /* Scan leftwards over the identifier that names the function. */
1592 while (is_id_char (*p))
1593 p--;
1594 p++;
1596 /* p now points to the leftmost character of the function name. */
1599 char *fn_string = alloca (past_fn - p + 1);
1601 strncpy (fn_string, p, (size_t) (past_fn - p));
1602 fn_string[past_fn-p] = '\0';
1603 def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1607 /* Look at all of the defs and decs for this function name that we have
1608 collected so far. If there is already one which is at the same
1609 line number in the same file, then we can discard this new def_dec_info
1610 record.
1612 As an extra assurance that any such pair of (nominally) identical
1613 function declarations are in fact identical, we also compare the
1614 ansi_decl parts of the lines from the aux_info files just to be on
1615 the safe side.
1617 This comparison will fail if (for instance) the user was playing
1618 messy games with the preprocessor which ultimately causes one
1619 function declaration in one header file to look differently when
1620 that file is included by two (or more) other files. */
1623 const def_dec_info *other;
1625 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1627 if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1629 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1631 notice ("%s:%d: declaration of function '%s' takes different forms\n",
1632 def_dec_p->file->hash_entry->symbol,
1633 def_dec_p->line,
1634 def_dec_p->hash_entry->symbol);
1635 exit (FATAL_EXIT_CODE);
1637 free_def_dec (def_dec_p);
1638 return;
1643 #ifdef UNPROTOIZE
1645 /* If we are doing unprotoizing, we must now setup the pointers that will
1646 point to the K&R name list and to the K&R argument declarations list.
1648 Note that if this is only a function declaration, then we should not
1649 expect to find any K&R style formals list following the ANSI-style
1650 formals list. This is because GCC knows that such information is
1651 useless in the case of function declarations (function definitions
1652 are a different story however).
1654 Since we are unprotoizing, we don't need any such lists anyway.
1655 All we plan to do is to delete all characters between ()'s in any
1656 case. */
1658 def_dec_p->formal_names = NULL;
1659 def_dec_p->formal_decls = NULL;
1661 if (def_dec_p->is_func_def)
1663 p = semicolon_p;
1664 check_aux_info (*++p == ' ');
1665 check_aux_info (*++p == '/');
1666 check_aux_info (*++p == '*');
1667 check_aux_info (*++p == ' ');
1668 check_aux_info (*++p == '(');
1671 const char *kr_names_start = ++p; /* Point just inside '('. */
1673 while (*p++ != ')')
1674 continue;
1675 p--; /* point to closing right paren */
1677 /* Make a copy of the K&R parameter names list. */
1679 def_dec_p->formal_names
1680 = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1683 check_aux_info (*++p == ' ');
1684 p++;
1686 /* p now points to the first character of the K&R style declarations
1687 list (if there is one) or to the star-slash combination that ends
1688 the comment in which such lists get embedded. */
1690 /* Make a copy of the K&R formal decls list and set the def_dec record
1691 to point to it. */
1693 if (*p == '*') /* Are there no K&R declarations? */
1695 check_aux_info (*++p == '/');
1696 def_dec_p->formal_decls = "";
1698 else
1700 const char *kr_decls_start = p;
1702 while (p[0] != '*' || p[1] != '/')
1703 p++;
1704 p--;
1706 check_aux_info (*p == ' ');
1708 def_dec_p->formal_decls
1709 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1712 /* Handle a special case. If we have a function definition marked as
1713 being in "old" style, and if its formal names list is empty, then
1714 it may actually have the string "void" in its real formals list
1715 in the original source code. Just to make sure, we will get setup
1716 to convert such things anyway.
1718 This kludge only needs to be here because of an insurmountable
1719 problem with generating .X files. */
1721 if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1722 def_dec_p->prototyped = 1;
1725 /* Since we are unprotoizing, if this item is already in old (K&R) style,
1726 we can just ignore it. If that is true, throw away the itme now. */
1728 if (!def_dec_p->prototyped)
1730 free_def_dec (def_dec_p);
1731 return;
1734 #endif /* defined (UNPROTOIZE) */
1736 /* Add this record to the head of the list of records pertaining to this
1737 particular function name. */
1739 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1740 def_dec_p->hash_entry->ddip = def_dec_p;
1742 /* Add this new def_dec_info record to the sorted list of def_dec_info
1743 records for this file. Note that we don't have to worry about duplicates
1744 (caused by multiple inclusions of header files) here because we have
1745 already eliminated duplicates above. */
1747 if (!def_dec_p->file->defs_decs)
1749 def_dec_p->file->defs_decs = def_dec_p;
1750 def_dec_p->next_in_file = NULL;
1752 else
1754 int line = def_dec_p->line;
1755 const def_dec_info *prev = NULL;
1756 const def_dec_info *curr = def_dec_p->file->defs_decs;
1757 const def_dec_info *next = curr->next_in_file;
1759 while (next && (line < curr->line))
1761 prev = curr;
1762 curr = next;
1763 next = next->next_in_file;
1765 if (line >= curr->line)
1767 def_dec_p->next_in_file = curr;
1768 if (prev)
1769 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1770 else
1771 def_dec_p->file->defs_decs = def_dec_p;
1773 else /* assert (next == NULL); */
1775 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
1776 /* assert (next == NULL); */
1777 def_dec_p->next_in_file = next;
1782 /* Set up the vector COMPILE_PARAMS which is the argument list for running GCC.
1783 Also set input_file_name_index and aux_info_file_name_index
1784 to the indices of the slots where the file names should go. */
1786 /* We initialize the vector by removing -g, -O, -S, -c, and -o options,
1787 and adding '-aux-info AUXFILE -S -o /dev/null INFILE' at the end. */
1789 static void
1790 munge_compile_params (const char *params_list)
1792 /* Build up the contents in a temporary vector
1793 that is so big that to has to be big enough. */
1794 const char **temp_params
1795 = alloca ((strlen (params_list) + 8) * sizeof (char *));
1796 int param_count = 0;
1797 const char *param;
1798 struct stat st;
1800 temp_params[param_count++] = compiler_file_name;
1801 for (;;)
1803 while (ISSPACE ((const unsigned char)*params_list))
1804 params_list++;
1805 if (!*params_list)
1806 break;
1807 param = params_list;
1808 while (*params_list && !ISSPACE ((const unsigned char)*params_list))
1809 params_list++;
1810 if (param[0] != '-')
1811 temp_params[param_count++]
1812 = dupnstr (param, (size_t) (params_list - param));
1813 else
1815 switch (param[1])
1817 case 'g':
1818 case 'O':
1819 case 'S':
1820 case 'c':
1821 break; /* Don't copy these. */
1822 case 'o':
1823 while (ISSPACE ((const unsigned char)*params_list))
1824 params_list++;
1825 while (*params_list
1826 && !ISSPACE ((const unsigned char)*params_list))
1827 params_list++;
1828 break;
1829 default:
1830 temp_params[param_count++]
1831 = dupnstr (param, (size_t) (params_list - param));
1834 if (!*params_list)
1835 break;
1837 temp_params[param_count++] = "-aux-info";
1839 /* Leave room for the aux-info file name argument. */
1840 aux_info_file_name_index = param_count;
1841 temp_params[param_count++] = NULL;
1843 temp_params[param_count++] = "-S";
1844 temp_params[param_count++] = "-o";
1846 if ((stat (HOST_BIT_BUCKET, &st) == 0)
1847 && (!S_ISDIR (st.st_mode))
1848 && (access (HOST_BIT_BUCKET, W_OK) == 0))
1849 temp_params[param_count++] = HOST_BIT_BUCKET;
1850 else
1851 /* FIXME: This is hardly likely to be right, if HOST_BIT_BUCKET is not
1852 writable. But until this is rejigged to use make_temp_file(), this
1853 is the best we can do. */
1854 temp_params[param_count++] = "/dev/null";
1856 /* Leave room for the input file name argument. */
1857 input_file_name_index = param_count;
1858 temp_params[param_count++] = NULL;
1859 /* Terminate the list. */
1860 temp_params[param_count++] = NULL;
1862 /* Make a copy of the compile_params in heap space. */
1864 compile_params = xmalloc (sizeof (char *) * (param_count+1));
1865 memcpy (compile_params, temp_params, sizeof (char *) * param_count);
1868 /* Do a recompilation for the express purpose of generating a new aux_info
1869 file to go with a specific base source file.
1871 The result is a boolean indicating success. */
1873 static int
1874 gen_aux_info_file (const char *base_filename)
1876 if (!input_file_name_index)
1877 munge_compile_params ("");
1879 /* Store the full source file name in the argument vector. */
1880 compile_params[input_file_name_index] = shortpath (NULL, base_filename);
1881 /* Add .X to source file name to get aux-info file name. */
1882 compile_params[aux_info_file_name_index] =
1883 concat (compile_params[input_file_name_index], aux_info_suffix, NULL);
1885 if (!quiet_flag)
1886 notice ("%s: compiling '%s'\n",
1887 pname, compile_params[input_file_name_index]);
1890 char *errmsg_fmt, *errmsg_arg;
1891 int wait_status, pid;
1893 pid = pexecute (compile_params[0], (char * const *) compile_params,
1894 pname, NULL, &errmsg_fmt, &errmsg_arg,
1895 PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
1897 if (pid == -1)
1899 int errno_val = errno;
1900 fprintf (stderr, "%s: ", pname);
1901 fprintf (stderr, errmsg_fmt, errmsg_arg);
1902 fprintf (stderr, ": %s\n", xstrerror (errno_val));
1903 return 0;
1906 pid = pwait (pid, &wait_status, 0);
1907 if (pid == -1)
1909 notice ("%s: wait: %s\n", pname, xstrerror (errno));
1910 return 0;
1912 if (WIFSIGNALED (wait_status))
1914 notice ("%s: subprocess got fatal signal %d\n",
1915 pname, WTERMSIG (wait_status));
1916 return 0;
1918 if (WIFEXITED (wait_status))
1920 if (WEXITSTATUS (wait_status) != 0)
1922 notice ("%s: %s exited with status %d\n",
1923 pname, compile_params[0], WEXITSTATUS (wait_status));
1924 return 0;
1926 return 1;
1928 gcc_unreachable ();
1932 /* Read in all of the information contained in a single aux_info file.
1933 Save all of the important stuff for later. */
1935 static void
1936 process_aux_info_file (const char *base_source_filename, int keep_it,
1937 int is_syscalls)
1939 size_t base_len = strlen (base_source_filename);
1940 char * aux_info_filename = alloca (base_len + strlen (aux_info_suffix) + 1);
1941 char *aux_info_base;
1942 char *aux_info_limit;
1943 char *aux_info_relocated_name;
1944 const char *aux_info_second_line;
1945 time_t aux_info_mtime;
1946 size_t aux_info_size;
1947 int must_create;
1949 /* Construct the aux_info filename from the base source filename. */
1951 strcpy (aux_info_filename, base_source_filename);
1952 strcat (aux_info_filename, aux_info_suffix);
1954 /* Check that the aux_info file exists and is readable. If it does not
1955 exist, try to create it (once only). */
1957 /* If file doesn't exist, set must_create.
1958 Likewise if it exists and we can read it but it is obsolete.
1959 Otherwise, report an error. */
1960 must_create = 0;
1962 /* Come here with must_create set to 1 if file is out of date. */
1963 start_over: ;
1965 if (access (aux_info_filename, R_OK) == -1)
1967 if (errno == ENOENT)
1969 if (is_syscalls)
1971 notice ("%s: warning: missing SYSCALLS file '%s'\n",
1972 pname, aux_info_filename);
1973 return;
1975 must_create = 1;
1977 else
1979 int errno_val = errno;
1980 notice ("%s: can't read aux info file '%s': %s\n",
1981 pname, shortpath (NULL, aux_info_filename),
1982 xstrerror (errno_val));
1983 errors++;
1984 return;
1987 #if 0 /* There is code farther down to take care of this. */
1988 else
1990 struct stat s1, s2;
1991 stat (aux_info_file_name, &s1);
1992 stat (base_source_file_name, &s2);
1993 if (s2.st_mtime > s1.st_mtime)
1994 must_create = 1;
1996 #endif /* 0 */
1998 /* If we need a .X file, create it, and verify we can read it. */
1999 if (must_create)
2001 if (!gen_aux_info_file (base_source_filename))
2003 errors++;
2004 return;
2006 if (access (aux_info_filename, R_OK) == -1)
2008 int errno_val = errno;
2009 notice ("%s: can't read aux info file '%s': %s\n",
2010 pname, shortpath (NULL, aux_info_filename),
2011 xstrerror (errno_val));
2012 errors++;
2013 return;
2018 struct stat stat_buf;
2020 /* Get some status information about this aux_info file. */
2022 if (stat (aux_info_filename, &stat_buf) == -1)
2024 int errno_val = errno;
2025 notice ("%s: can't get status of aux info file '%s': %s\n",
2026 pname, shortpath (NULL, aux_info_filename),
2027 xstrerror (errno_val));
2028 errors++;
2029 return;
2032 /* Check on whether or not this aux_info file is zero length. If it is,
2033 then just ignore it and return. */
2035 if ((aux_info_size = stat_buf.st_size) == 0)
2036 return;
2038 /* Get the date/time of last modification for this aux_info file and
2039 remember it. We will have to check that any source files that it
2040 contains information about are at least this old or older. */
2042 aux_info_mtime = stat_buf.st_mtime;
2044 if (!is_syscalls)
2046 /* Compare mod time with the .c file; update .X file if obsolete.
2047 The code later on can fail to check the .c file
2048 if it did not directly define any functions. */
2050 if (stat (base_source_filename, &stat_buf) == -1)
2052 int errno_val = errno;
2053 notice ("%s: can't get status of aux info file '%s': %s\n",
2054 pname, shortpath (NULL, base_source_filename),
2055 xstrerror (errno_val));
2056 errors++;
2057 return;
2059 if (stat_buf.st_mtime > aux_info_mtime)
2061 must_create = 1;
2062 goto start_over;
2068 int aux_info_file;
2069 int fd_flags;
2071 /* Open the aux_info file. */
2073 fd_flags = O_RDONLY;
2074 #ifdef O_BINARY
2075 /* Use binary mode to avoid having to deal with different EOL characters. */
2076 fd_flags |= O_BINARY;
2077 #endif
2078 if ((aux_info_file = open (aux_info_filename, fd_flags, 0444 )) == -1)
2080 int errno_val = errno;
2081 notice ("%s: can't open aux info file '%s' for reading: %s\n",
2082 pname, shortpath (NULL, aux_info_filename),
2083 xstrerror (errno_val));
2084 return;
2087 /* Allocate space to hold the aux_info file in memory. */
2089 aux_info_base = xmalloc (aux_info_size + 1);
2090 aux_info_limit = aux_info_base + aux_info_size;
2091 *aux_info_limit = '\0';
2093 /* Read the aux_info file into memory. */
2095 if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
2096 (int) aux_info_size)
2098 int errno_val = errno;
2099 notice ("%s: error reading aux info file '%s': %s\n",
2100 pname, shortpath (NULL, aux_info_filename),
2101 xstrerror (errno_val));
2102 free (aux_info_base);
2103 close (aux_info_file);
2104 return;
2107 /* Close the aux info file. */
2109 if (close (aux_info_file))
2111 int errno_val = errno;
2112 notice ("%s: error closing aux info file '%s': %s\n",
2113 pname, shortpath (NULL, aux_info_filename),
2114 xstrerror (errno_val));
2115 free (aux_info_base);
2116 close (aux_info_file);
2117 return;
2121 /* Delete the aux_info file (unless requested not to). If the deletion
2122 fails for some reason, don't even worry about it. */
2124 if (must_create && !keep_it)
2125 if (unlink (aux_info_filename) == -1)
2127 int errno_val = errno;
2128 notice ("%s: can't delete aux info file '%s': %s\n",
2129 pname, shortpath (NULL, aux_info_filename),
2130 xstrerror (errno_val));
2133 /* Save a pointer into the first line of the aux_info file which
2134 contains the filename of the directory from which the compiler
2135 was invoked when the associated source file was compiled.
2136 This information is used later to help create complete
2137 filenames out of the (potentially) relative filenames in
2138 the aux_info file. */
2141 char *p = aux_info_base;
2143 while (*p != ':'
2144 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
2145 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
2146 #endif
2148 p++;
2149 p++;
2150 while (*p == ' ')
2151 p++;
2152 invocation_filename = p; /* Save a pointer to first byte of path. */
2153 while (*p != ' ')
2154 p++;
2155 *p++ = DIR_SEPARATOR;
2156 *p++ = '\0';
2157 while (*p++ != '\n')
2158 continue;
2159 aux_info_second_line = p;
2160 aux_info_relocated_name = 0;
2161 if (! IS_ABSOLUTE_PATH (invocation_filename))
2163 /* INVOCATION_FILENAME is relative;
2164 append it to BASE_SOURCE_FILENAME's dir. */
2165 char *dir_end;
2166 aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
2167 strcpy (aux_info_relocated_name, base_source_filename);
2168 dir_end = strrchr (aux_info_relocated_name, DIR_SEPARATOR);
2169 #ifdef DIR_SEPARATOR_2
2171 char *slash;
2173 slash = strrchr (dir_end ? dir_end : aux_info_relocated_name,
2174 DIR_SEPARATOR_2);
2175 if (slash)
2176 dir_end = slash;
2178 #endif
2179 if (dir_end)
2180 dir_end++;
2181 else
2182 dir_end = aux_info_relocated_name;
2183 strcpy (dir_end, invocation_filename);
2184 invocation_filename = aux_info_relocated_name;
2190 const char *aux_info_p;
2192 /* Do a pre-pass on the lines in the aux_info file, making sure that all
2193 of the source files referenced in there are at least as old as this
2194 aux_info file itself. If not, go back and regenerate the aux_info
2195 file anew. Don't do any of this for the syscalls file. */
2197 if (!is_syscalls)
2199 current_aux_info_lineno = 2;
2201 for (aux_info_p = aux_info_second_line; *aux_info_p; )
2203 if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2205 free (aux_info_base);
2206 free (aux_info_relocated_name);
2207 if (keep_it && unlink (aux_info_filename) == -1)
2209 int errno_val = errno;
2210 notice ("%s: can't delete file '%s': %s\n",
2211 pname, shortpath (NULL, aux_info_filename),
2212 xstrerror (errno_val));
2213 return;
2215 must_create = 1;
2216 goto start_over;
2219 /* Skip over the rest of this line to start of next line. */
2221 while (*aux_info_p != '\n')
2222 aux_info_p++;
2223 aux_info_p++;
2224 current_aux_info_lineno++;
2228 /* Now do the real pass on the aux_info lines. Save their information in
2229 the in-core data base. */
2231 current_aux_info_lineno = 2;
2233 for (aux_info_p = aux_info_second_line; *aux_info_p;)
2235 char *unexpanded_line = unexpand_if_needed (aux_info_p);
2237 if (unexpanded_line)
2239 save_def_or_dec (unexpanded_line, is_syscalls);
2240 free (unexpanded_line);
2242 else
2243 save_def_or_dec (aux_info_p, is_syscalls);
2245 /* Skip over the rest of this line and get to start of next line. */
2247 while (*aux_info_p != '\n')
2248 aux_info_p++;
2249 aux_info_p++;
2250 current_aux_info_lineno++;
2254 free (aux_info_base);
2255 free (aux_info_relocated_name);
2258 #ifndef UNPROTOIZE
2260 /* Check an individual filename for a .c suffix. If the filename has this
2261 suffix, rename the file such that its suffix is changed to .C. This
2262 function implements the -C option. */
2264 static void
2265 rename_c_file (const hash_table_entry *hp)
2267 const char *filename = hp->symbol;
2268 int last_char_index = strlen (filename) - 1;
2269 char *const new_filename = alloca (strlen (filename)
2270 + strlen (cplus_suffix) + 1);
2272 /* Note that we don't care here if the given file was converted or not. It
2273 is possible that the given file was *not* converted, simply because there
2274 was nothing in it which actually required conversion. Even in this case,
2275 we want to do the renaming. Note that we only rename files with the .c
2276 suffix (except for the syscalls file, which is left alone). */
2278 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.'
2279 || IS_SAME_PATH (syscalls_absolute_filename, filename))
2280 return;
2282 strcpy (new_filename, filename);
2283 strcpy (&new_filename[last_char_index], cplus_suffix);
2285 if (rename (filename, new_filename) == -1)
2287 int errno_val = errno;
2288 notice ("%s: warning: can't rename file '%s' to '%s': %s\n",
2289 pname, shortpath (NULL, filename),
2290 shortpath (NULL, new_filename), xstrerror (errno_val));
2291 errors++;
2292 return;
2296 #endif /* !defined (UNPROTOIZE) */
2298 /* Take the list of definitions and declarations attached to a particular
2299 file_info node and reverse the order of the list. This should get the
2300 list into an order such that the item with the lowest associated line
2301 number is nearest the head of the list. When these lists are originally
2302 built, they are in the opposite order. We want to traverse them in
2303 normal line number order later (i.e. lowest to highest) so reverse the
2304 order here. */
2306 static void
2307 reverse_def_dec_list (const hash_table_entry *hp)
2309 file_info *file_p = hp->fip;
2310 def_dec_info *prev = NULL;
2311 def_dec_info *current = (def_dec_info *) file_p->defs_decs;
2313 if (!current)
2314 return; /* no list to reverse */
2316 prev = current;
2317 if (! (current = (def_dec_info *) current->next_in_file))
2318 return; /* can't reverse a single list element */
2320 prev->next_in_file = NULL;
2322 while (current)
2324 def_dec_info *next = (def_dec_info *) current->next_in_file;
2326 current->next_in_file = prev;
2327 prev = current;
2328 current = next;
2331 file_p->defs_decs = prev;
2334 #ifndef UNPROTOIZE
2336 /* Find the (only?) extern definition for a particular function name, starting
2337 from the head of the linked list of entries for the given name. If we
2338 cannot find an extern definition for the given function name, issue a
2339 warning and scrounge around for the next best thing, i.e. an extern
2340 function declaration with a prototype attached to it. Note that we only
2341 allow such substitutions for extern declarations and never for static
2342 declarations. That's because the only reason we allow them at all is
2343 to let un-prototyped function declarations for system-supplied library
2344 functions get their prototypes from our own extra SYSCALLS.c.X file which
2345 contains all of the correct prototypes for system functions. */
2347 static const def_dec_info *
2348 find_extern_def (const def_dec_info *head, const def_dec_info *user)
2350 const def_dec_info *dd_p;
2351 const def_dec_info *extern_def_p = NULL;
2352 int conflict_noted = 0;
2354 /* Don't act too stupid here. Somebody may try to convert an entire system
2355 in one swell fwoop (rather than one program at a time, as should be done)
2356 and in that case, we may find that there are multiple extern definitions
2357 of a given function name in the entire set of source files that we are
2358 converting. If however one of these definitions resides in exactly the
2359 same source file as the reference we are trying to satisfy then in that
2360 case it would be stupid for us to fail to realize that this one definition
2361 *must* be the precise one we are looking for.
2363 To make sure that we don't miss an opportunity to make this "same file"
2364 leap of faith, we do a prescan of the list of records relating to the
2365 given function name, and we look (on this first scan) *only* for a
2366 definition of the function which is in the same file as the reference
2367 we are currently trying to satisfy. */
2369 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2370 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2371 return dd_p;
2373 /* Now, since we have not found a definition in the same file as the
2374 reference, we scan the list again and consider all possibilities from
2375 all files. Here we may get conflicts with the things listed in the
2376 SYSCALLS.c.X file, but if that happens it only means that the source
2377 code being converted contains its own definition of a function which
2378 could have been supplied by libc.a. In such cases, we should avoid
2379 issuing the normal warning, and defer to the definition given in the
2380 user's own code. */
2382 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2383 if (dd_p->is_func_def && !dd_p->is_static)
2385 if (!extern_def_p) /* Previous definition? */
2386 extern_def_p = dd_p; /* Remember the first definition found. */
2387 else
2389 /* Ignore definition just found if it came from SYSCALLS.c.X. */
2391 if (is_syscalls_file (dd_p->file))
2392 continue;
2394 /* Quietly replace the definition previously found with the one
2395 just found if the previous one was from SYSCALLS.c.X. */
2397 if (is_syscalls_file (extern_def_p->file))
2399 extern_def_p = dd_p;
2400 continue;
2403 /* If we get here, then there is a conflict between two function
2404 declarations for the same function, both of which came from the
2405 user's own code. */
2407 if (!conflict_noted) /* first time we noticed? */
2409 conflict_noted = 1;
2410 notice ("%s: conflicting extern definitions of '%s'\n",
2411 pname, head->hash_entry->symbol);
2412 if (!quiet_flag)
2414 notice ("%s: declarations of '%s' will not be converted\n",
2415 pname, head->hash_entry->symbol);
2416 notice ("%s: conflict list for '%s' follows:\n",
2417 pname, head->hash_entry->symbol);
2418 fprintf (stderr, "%s: %s(%d): %s\n",
2419 pname,
2420 shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2421 extern_def_p->line, extern_def_p->ansi_decl);
2424 if (!quiet_flag)
2425 fprintf (stderr, "%s: %s(%d): %s\n",
2426 pname,
2427 shortpath (NULL, dd_p->file->hash_entry->symbol),
2428 dd_p->line, dd_p->ansi_decl);
2432 /* We want to err on the side of caution, so if we found multiple conflicting
2433 definitions for the same function, treat this as being that same as if we
2434 had found no definitions (i.e. return NULL). */
2436 if (conflict_noted)
2437 return NULL;
2439 if (!extern_def_p)
2441 /* We have no definitions for this function so do the next best thing.
2442 Search for an extern declaration already in prototype form. */
2444 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2445 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2447 extern_def_p = dd_p; /* save a pointer to the definition */
2448 if (!quiet_flag)
2449 notice ("%s: warning: using formals list from %s(%d) for function '%s'\n",
2450 pname,
2451 shortpath (NULL, dd_p->file->hash_entry->symbol),
2452 dd_p->line, dd_p->hash_entry->symbol);
2453 break;
2456 /* Gripe about unprototyped function declarations that we found no
2457 corresponding definition (or other source of prototype information)
2458 for.
2460 Gripe even if the unprototyped declaration we are worried about
2461 exists in a file in one of the "system" include directories. We
2462 can gripe about these because we should have at least found a
2463 corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
2464 didn't, then that means that the SYSCALLS.c.X file is missing some
2465 needed prototypes for this particular system. That is worth telling
2466 the user about! */
2468 if (!extern_def_p)
2470 const char *file = user->file->hash_entry->symbol;
2472 if (!quiet_flag)
2473 if (in_system_include_dir (file))
2475 /* Why copy this string into `needed' at all?
2476 Why not just use user->ansi_decl without copying? */
2477 char *needed = alloca (strlen (user->ansi_decl) + 1);
2478 char *p;
2480 strcpy (needed, user->ansi_decl);
2481 p = strstr (needed, user->hash_entry->symbol)
2482 + strlen (user->hash_entry->symbol) + 2;
2483 /* Avoid having ??? in the string. */
2484 *p++ = '?';
2485 *p++ = '?';
2486 *p++ = '?';
2487 strcpy (p, ");");
2489 notice ("%s: %d: '%s' used but missing from SYSCALLS\n",
2490 shortpath (NULL, file), user->line,
2491 needed+7); /* Don't print "extern " */
2493 #if 0
2494 else
2495 notice ("%s: %d: warning: no extern definition for '%s'\n",
2496 shortpath (NULL, file), user->line,
2497 user->hash_entry->symbol);
2498 #endif
2501 return extern_def_p;
2504 /* Find the (only?) static definition for a particular function name in a
2505 given file. Here we get the function-name and the file info indirectly
2506 from the def_dec_info record pointer which is passed in. */
2508 static const def_dec_info *
2509 find_static_definition (const def_dec_info *user)
2511 const def_dec_info *head = user->hash_entry->ddip;
2512 const def_dec_info *dd_p;
2513 int num_static_defs = 0;
2514 const def_dec_info *static_def_p = NULL;
2516 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2517 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2519 static_def_p = dd_p; /* save a pointer to the definition */
2520 num_static_defs++;
2522 if (num_static_defs == 0)
2524 if (!quiet_flag)
2525 notice ("%s: warning: no static definition for '%s' in file '%s'\n",
2526 pname, head->hash_entry->symbol,
2527 shortpath (NULL, user->file->hash_entry->symbol));
2529 else if (num_static_defs > 1)
2531 notice ("%s: multiple static defs of '%s' in file '%s'\n",
2532 pname, head->hash_entry->symbol,
2533 shortpath (NULL, user->file->hash_entry->symbol));
2534 return NULL;
2536 return static_def_p;
2539 /* Find good prototype style formal argument lists for all of the function
2540 declarations which didn't have them before now.
2542 To do this we consider each function name one at a time. For each function
2543 name, we look at the items on the linked list of def_dec_info records for
2544 that particular name.
2546 Somewhere on this list we should find one (and only one) def_dec_info
2547 record which represents the actual function definition, and this record
2548 should have a nice formal argument list already associated with it.
2550 Thus, all we have to do is to connect up all of the other def_dec_info
2551 records for this particular function name to the special one which has
2552 the full-blown formals list.
2554 Of course it is a little more complicated than just that. See below for
2555 more details. */
2557 static void
2558 connect_defs_and_decs (const hash_table_entry *hp)
2560 const def_dec_info *dd_p;
2561 const def_dec_info *extern_def_p = NULL;
2562 int first_extern_reference = 1;
2564 /* Traverse the list of definitions and declarations for this particular
2565 function name. For each item on the list, if it is a function
2566 definition (either old style or new style) then GCC has already been
2567 kind enough to produce a prototype for us, and it is associated with
2568 the item already, so declare the item as its own associated "definition".
2570 Also, for each item which is only a function declaration, but which
2571 nonetheless has its own prototype already (obviously supplied by the user)
2572 declare the item as its own definition.
2574 Note that when/if there are multiple user-supplied prototypes already
2575 present for multiple declarations of any given function, these multiple
2576 prototypes *should* all match exactly with one another and with the
2577 prototype for the actual function definition. We don't check for this
2578 here however, since we assume that the compiler must have already done
2579 this consistency checking when it was creating the .X files. */
2581 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2582 if (dd_p->prototyped)
2583 ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2585 /* Traverse the list of definitions and declarations for this particular
2586 function name. For each item on the list, if it is an extern function
2587 declaration and if it has no associated definition yet, go try to find
2588 the matching extern definition for the declaration.
2590 When looking for the matching function definition, warn the user if we
2591 fail to find one.
2593 If we find more that one function definition also issue a warning.
2595 Do the search for the matching definition only once per unique function
2596 name (and only when absolutely needed) so that we can avoid putting out
2597 redundant warning messages, and so that we will only put out warning
2598 messages when there is actually a reference (i.e. a declaration) for
2599 which we need to find a matching definition. */
2601 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2602 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2604 if (first_extern_reference)
2606 extern_def_p = find_extern_def (hp->ddip, dd_p);
2607 first_extern_reference = 0;
2609 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2612 /* Traverse the list of definitions and declarations for this particular
2613 function name. For each item on the list, if it is a static function
2614 declaration and if it has no associated definition yet, go try to find
2615 the matching static definition for the declaration within the same file.
2617 When looking for the matching function definition, warn the user if we
2618 fail to find one in the same file with the declaration, and refuse to
2619 convert this kind of cross-file static function declaration. After all,
2620 this is stupid practice and should be discouraged.
2622 We don't have to worry about the possibility that there is more than one
2623 matching function definition in the given file because that would have
2624 been flagged as an error by the compiler.
2626 Do the search for the matching definition only once per unique
2627 function-name/source-file pair (and only when absolutely needed) so that
2628 we can avoid putting out redundant warning messages, and so that we will
2629 only put out warning messages when there is actually a reference (i.e. a
2630 declaration) for which we actually need to find a matching definition. */
2632 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2633 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2635 const def_dec_info *dd_p2;
2636 const def_dec_info *static_def;
2638 /* We have now found a single static declaration for which we need to
2639 find a matching definition. We want to minimize the work (and the
2640 number of warnings), so we will find an appropriate (matching)
2641 static definition for this declaration, and then distribute it
2642 (as the definition for) any and all other static declarations
2643 for this function name which occur within the same file, and which
2644 do not already have definitions.
2646 Note that a trick is used here to prevent subsequent attempts to
2647 call find_static_definition for a given function-name & file
2648 if the first such call returns NULL. Essentially, we convert
2649 these NULL return values to -1, and put the -1 into the definition
2650 field for each other static declaration from the same file which
2651 does not already have an associated definition.
2652 This makes these other static declarations look like they are
2653 actually defined already when the outer loop here revisits them
2654 later on. Thus, the outer loop will skip over them. Later, we
2655 turn the -1's back to NULL's. */
2657 ((NONCONST def_dec_info *) dd_p)->definition =
2658 (static_def = find_static_definition (dd_p))
2659 ? static_def
2660 : (const def_dec_info *) -1;
2662 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2663 if (!dd_p2->is_func_def && dd_p2->is_static
2664 && !dd_p2->definition && (dd_p2->file == dd_p->file))
2665 ((NONCONST def_dec_info *) dd_p2)->definition = dd_p->definition;
2668 /* Convert any dummy (-1) definitions we created in the step above back to
2669 NULL's (as they should be). */
2671 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2672 if (dd_p->definition == (def_dec_info *) -1)
2673 ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2676 #endif /* !defined (UNPROTOIZE) */
2678 /* Give a pointer into the clean text buffer, return a number which is the
2679 original source line number that the given pointer points into. */
2681 static int
2682 identify_lineno (const char *clean_p)
2684 int line_num = 1;
2685 const char *scan_p;
2687 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2688 if (*scan_p == '\n')
2689 line_num++;
2690 return line_num;
2693 /* Issue an error message and give up on doing this particular edit. */
2695 static void
2696 declare_source_confusing (const char *clean_p)
2698 if (!quiet_flag)
2700 if (clean_p == 0)
2701 notice ("%s: %d: warning: source too confusing\n",
2702 shortpath (NULL, convert_filename), last_known_line_number);
2703 else
2704 notice ("%s: %d: warning: source too confusing\n",
2705 shortpath (NULL, convert_filename),
2706 identify_lineno (clean_p));
2708 longjmp (source_confusion_recovery, 1);
2711 /* Check that a condition which is expected to be true in the original source
2712 code is in fact true. If not, issue an error message and give up on
2713 converting this particular source file. */
2715 static void
2716 check_source (int cond, const char *clean_p)
2718 if (!cond)
2719 declare_source_confusing (clean_p);
2722 /* If we think of the in-core cleaned text buffer as a memory mapped
2723 file (with the variable last_known_line_start acting as sort of a
2724 file pointer) then we can imagine doing "seeks" on the buffer. The
2725 following routine implements a kind of "seek" operation for the in-core
2726 (cleaned) copy of the source file. When finished, it returns a pointer to
2727 the start of a given (numbered) line in the cleaned text buffer.
2729 Note that protoize only has to "seek" in the forward direction on the
2730 in-core cleaned text file buffers, and it never needs to back up.
2732 This routine is made a little bit faster by remembering the line number
2733 (and pointer value) supplied (and returned) from the previous "seek".
2734 This prevents us from always having to start all over back at the top
2735 of the in-core cleaned buffer again. */
2737 static const char *
2738 seek_to_line (int n)
2740 gcc_assert (n >= last_known_line_number);
2742 while (n > last_known_line_number)
2744 while (*last_known_line_start != '\n')
2745 check_source (++last_known_line_start < clean_text_limit, 0);
2746 last_known_line_start++;
2747 last_known_line_number++;
2749 return last_known_line_start;
2752 /* Given a pointer to a character in the cleaned text buffer, return a pointer
2753 to the next non-whitespace character which follows it. */
2755 static const char *
2756 forward_to_next_token_char (const char *ptr)
2758 for (++ptr; ISSPACE ((const unsigned char)*ptr);
2759 check_source (++ptr < clean_text_limit, 0))
2760 continue;
2761 return ptr;
2764 /* Copy a chunk of text of length `len' and starting at `str' to the current
2765 output buffer. Note that all attempts to add stuff to the current output
2766 buffer ultimately go through here. */
2768 static void
2769 output_bytes (const char *str, size_t len)
2771 if ((repl_write_ptr + 1) + len >= repl_text_limit)
2773 size_t new_size = (repl_text_limit - repl_text_base) << 1;
2774 char *new_buf = xrealloc (repl_text_base, new_size);
2776 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
2777 repl_text_base = new_buf;
2778 repl_text_limit = new_buf + new_size;
2780 memcpy (repl_write_ptr + 1, str, len);
2781 repl_write_ptr += len;
2784 /* Copy all bytes (except the trailing null) of a null terminated string to
2785 the current output buffer. */
2787 static void
2788 output_string (const char *str)
2790 output_bytes (str, strlen (str));
2793 /* Copy some characters from the original text buffer to the current output
2794 buffer.
2796 This routine takes a pointer argument `p' which is assumed to be a pointer
2797 into the cleaned text buffer. The bytes which are copied are the `original'
2798 equivalents for the set of bytes between the last value of `clean_read_ptr'
2799 and the argument value `p'.
2801 The set of bytes copied however, comes *not* from the cleaned text buffer,
2802 but rather from the direct counterparts of these bytes within the original
2803 text buffer.
2805 Thus, when this function is called, some bytes from the original text
2806 buffer (which may include original comments and preprocessing directives)
2807 will be copied into the output buffer.
2809 Note that the request implied when this routine is called includes the
2810 byte pointed to by the argument pointer `p'. */
2812 static void
2813 output_up_to (const char *p)
2815 size_t copy_length = (size_t) (p - clean_read_ptr);
2816 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
2818 if (copy_length == 0)
2819 return;
2821 output_bytes (copy_start, copy_length);
2822 clean_read_ptr = p;
2825 /* Given a pointer to a def_dec_info record which represents some form of
2826 definition of a function (perhaps a real definition, or in lieu of that
2827 perhaps just a declaration with a full prototype) return true if this
2828 function is one which we should avoid converting. Return false
2829 otherwise. */
2831 static int
2832 other_variable_style_function (const char *ansi_header)
2834 #ifdef UNPROTOIZE
2836 /* See if we have a stdarg function, or a function which has stdarg style
2837 parameters or a stdarg style return type. */
2839 return strstr (ansi_header, "...") != 0;
2841 #else /* !defined (UNPROTOIZE) */
2843 /* See if we have a varargs function, or a function which has varargs style
2844 parameters or a varargs style return type. */
2846 const char *p;
2847 int len = strlen (varargs_style_indicator);
2849 for (p = ansi_header; p; )
2851 const char *candidate;
2853 if ((candidate = strstr (p, varargs_style_indicator)) == 0)
2854 return 0;
2855 else
2856 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
2857 return 1;
2858 else
2859 p = candidate + 1;
2861 return 0;
2862 #endif /* !defined (UNPROTOIZE) */
2865 /* Do the editing operation specifically for a function "declaration". Note
2866 that editing for function "definitions" are handled in a separate routine
2867 below. */
2869 static void
2870 edit_fn_declaration (const def_dec_info *def_dec_p,
2871 const char *volatile clean_text_p)
2873 const char *start_formals;
2874 const char *end_formals;
2875 const char *function_to_edit = def_dec_p->hash_entry->symbol;
2876 size_t func_name_len = strlen (function_to_edit);
2877 const char *end_of_fn_name;
2879 #ifndef UNPROTOIZE
2881 const f_list_chain_item *this_f_list_chain_item;
2882 const def_dec_info *definition = def_dec_p->definition;
2884 /* If we are protoizing, and if we found no corresponding definition for
2885 this particular function declaration, then just leave this declaration
2886 exactly as it is. */
2888 if (!definition)
2889 return;
2891 /* If we are protoizing, and if the corresponding definition that we found
2892 for this particular function declaration defined an old style varargs
2893 function, then we want to issue a warning and just leave this function
2894 declaration unconverted. */
2896 if (other_variable_style_function (definition->ansi_decl))
2898 if (!quiet_flag)
2899 notice ("%s: %d: warning: varargs function declaration not converted\n",
2900 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
2901 def_dec_p->line);
2902 return;
2905 #endif /* !defined (UNPROTOIZE) */
2907 /* Setup here to recover from confusing source code detected during this
2908 particular "edit". */
2910 save_pointers ();
2911 if (setjmp (source_confusion_recovery))
2913 restore_pointers ();
2914 notice ("%s: declaration of function '%s' not converted\n",
2915 pname, function_to_edit);
2916 return;
2919 /* We are editing a function declaration. The line number we did a seek to
2920 contains the comma or semicolon which follows the declaration. Our job
2921 now is to scan backwards looking for the function name. This name *must*
2922 be followed by open paren (ignoring whitespace, of course). We need to
2923 replace everything between that open paren and the corresponding closing
2924 paren. If we are protoizing, we need to insert the prototype-style
2925 formals lists. If we are unprotoizing, we need to just delete everything
2926 between the pairs of opening and closing parens. */
2928 /* First move up to the end of the line. */
2930 while (*clean_text_p != '\n')
2931 check_source (++clean_text_p < clean_text_limit, 0);
2932 clean_text_p--; /* Point to just before the newline character. */
2934 /* Now we can scan backwards for the function name. */
2938 for (;;)
2940 /* Scan leftwards until we find some character which can be
2941 part of an identifier. */
2943 while (!is_id_char (*clean_text_p))
2944 check_source (--clean_text_p > clean_read_ptr, 0);
2946 /* Scan backwards until we find a char that cannot be part of an
2947 identifier. */
2949 while (is_id_char (*clean_text_p))
2950 check_source (--clean_text_p > clean_read_ptr, 0);
2952 /* Having found an "id break", see if the following id is the one
2953 that we are looking for. If so, then exit from this loop. */
2955 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
2957 char ch = *(clean_text_p + 1 + func_name_len);
2959 /* Must also check to see that the name in the source text
2960 ends where it should (in order to prevent bogus matches
2961 on similar but longer identifiers. */
2963 if (! is_id_char (ch))
2964 break; /* exit from loop */
2968 /* We have now found the first perfect match for the function name in
2969 our backward search. This may or may not be the actual function
2970 name at the start of the actual function declaration (i.e. we could
2971 have easily been mislead). We will try to avoid getting fooled too
2972 often by looking forward for the open paren which should follow the
2973 identifier we just found. We ignore whitespace while hunting. If
2974 the next non-whitespace byte we see is *not* an open left paren,
2975 then we must assume that we have been fooled and we start over
2976 again accordingly. Note that there is no guarantee, that even if
2977 we do see the open paren, that we are in the right place.
2978 Programmers do the strangest things sometimes! */
2980 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
2981 start_formals = forward_to_next_token_char (end_of_fn_name);
2983 while (*start_formals != '(');
2985 /* start_of_formals now points to the opening left paren which immediately
2986 follows the name of the function. */
2988 /* Note that there may be several formals lists which need to be modified
2989 due to the possibility that the return type of this function is a
2990 pointer-to-function type. If there are several formals lists, we
2991 convert them in left-to-right order here. */
2993 #ifndef UNPROTOIZE
2994 this_f_list_chain_item = definition->f_list_chain;
2995 #endif /* !defined (UNPROTOIZE) */
2997 for (;;)
3000 int depth;
3002 end_formals = start_formals + 1;
3003 depth = 1;
3004 for (; depth; check_source (++end_formals < clean_text_limit, 0))
3006 switch (*end_formals)
3008 case '(':
3009 depth++;
3010 break;
3011 case ')':
3012 depth--;
3013 break;
3016 end_formals--;
3019 /* end_formals now points to the closing right paren of the formals
3020 list whose left paren is pointed to by start_formals. */
3022 /* Now, if we are protoizing, we insert the new ANSI-style formals list
3023 attached to the associated definition of this function. If however
3024 we are unprotoizing, then we simply delete any formals list which
3025 may be present. */
3027 output_up_to (start_formals);
3028 #ifndef UNPROTOIZE
3029 if (this_f_list_chain_item)
3031 output_string (this_f_list_chain_item->formals_list);
3032 this_f_list_chain_item = this_f_list_chain_item->chain_next;
3034 else
3036 if (!quiet_flag)
3037 notice ("%s: warning: too many parameter lists in declaration of '%s'\n",
3038 pname, def_dec_p->hash_entry->symbol);
3039 check_source (0, end_formals); /* leave the declaration intact */
3041 #endif /* !defined (UNPROTOIZE) */
3042 clean_read_ptr = end_formals - 1;
3044 /* Now see if it looks like there may be another formals list associated
3045 with the function declaration that we are converting (following the
3046 formals list that we just converted. */
3049 const char *another_r_paren = forward_to_next_token_char (end_formals);
3051 if ((*another_r_paren != ')')
3052 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3054 #ifndef UNPROTOIZE
3055 if (this_f_list_chain_item)
3057 if (!quiet_flag)
3058 notice ("\n%s: warning: too few parameter lists in declaration of '%s'\n",
3059 pname, def_dec_p->hash_entry->symbol);
3060 check_source (0, start_formals); /* leave the decl intact */
3062 #endif /* !defined (UNPROTOIZE) */
3063 break;
3068 /* There does appear to be yet another formals list, so loop around
3069 again, and convert it also. */
3073 /* Edit a whole group of formals lists, starting with the rightmost one
3074 from some set of formals lists. This routine is called once (from the
3075 outside) for each function declaration which is converted. It is
3076 recursive however, and it calls itself once for each remaining formal
3077 list that lies to the left of the one it was originally called to work
3078 on. Thus, a whole set gets done in right-to-left order.
3080 This routine returns nonzero if it thinks that it should not be trying
3081 to convert this particular function definition (because the name of the
3082 function doesn't match the one expected). */
3084 static int
3085 edit_formals_lists (const char *end_formals, unsigned int f_list_count,
3086 const def_dec_info *def_dec_p)
3088 const char *start_formals;
3089 int depth;
3091 start_formals = end_formals - 1;
3092 depth = 1;
3093 for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3095 switch (*start_formals)
3097 case '(':
3098 depth--;
3099 break;
3100 case ')':
3101 depth++;
3102 break;
3105 start_formals++;
3107 /* start_formals now points to the opening left paren of the formals list. */
3109 f_list_count--;
3111 if (f_list_count)
3113 const char *next_end;
3115 /* There should be more formal lists to the left of here. */
3117 next_end = start_formals - 1;
3118 check_source (next_end > clean_read_ptr, 0);
3119 while (ISSPACE ((const unsigned char)*next_end))
3120 check_source (--next_end > clean_read_ptr, 0);
3121 check_source (*next_end == ')', next_end);
3122 check_source (--next_end > clean_read_ptr, 0);
3123 check_source (*next_end == ')', next_end);
3124 if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3125 return 1;
3128 /* Check that the function name in the header we are working on is the same
3129 as the one we would expect to find. If not, issue a warning and return
3130 nonzero. */
3132 if (f_list_count == 0)
3134 const char *expected = def_dec_p->hash_entry->symbol;
3135 const char *func_name_start;
3136 const char *func_name_limit;
3137 size_t func_name_len;
3139 for (func_name_limit = start_formals-1;
3140 ISSPACE ((const unsigned char)*func_name_limit); )
3141 check_source (--func_name_limit > clean_read_ptr, 0);
3143 for (func_name_start = func_name_limit++;
3144 is_id_char (*func_name_start);
3145 func_name_start--)
3146 check_source (func_name_start > clean_read_ptr, 0);
3147 func_name_start++;
3148 func_name_len = func_name_limit - func_name_start;
3149 if (func_name_len == 0)
3150 check_source (0, func_name_start);
3151 if (func_name_len != strlen (expected)
3152 || strncmp (func_name_start, expected, func_name_len))
3154 notice ("%s: %d: warning: found '%s' but expected '%s'\n",
3155 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3156 identify_lineno (func_name_start),
3157 dupnstr (func_name_start, func_name_len),
3158 expected);
3159 return 1;
3163 output_up_to (start_formals);
3165 #ifdef UNPROTOIZE
3166 if (f_list_count == 0)
3167 output_string (def_dec_p->formal_names);
3168 #else /* !defined (UNPROTOIZE) */
3170 unsigned f_list_depth;
3171 const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3173 /* At this point, the current value of f_list count says how many
3174 links we have to follow through the f_list_chain to get to the
3175 particular formals list that we need to output next. */
3177 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3178 flci_p = flci_p->chain_next;
3179 output_string (flci_p->formals_list);
3181 #endif /* !defined (UNPROTOIZE) */
3183 clean_read_ptr = end_formals - 1;
3184 return 0;
3187 /* Given a pointer to a byte in the clean text buffer which points to
3188 the beginning of a line that contains a "follower" token for a
3189 function definition header, do whatever is necessary to find the
3190 right closing paren for the rightmost formals list of the function
3191 definition header. */
3193 static const char *
3194 find_rightmost_formals_list (const char *clean_text_p)
3196 const char *end_formals;
3198 /* We are editing a function definition. The line number we did a seek
3199 to contains the first token which immediately follows the entire set of
3200 formals lists which are part of this particular function definition
3201 header.
3203 Our job now is to scan leftwards in the clean text looking for the
3204 right-paren which is at the end of the function header's rightmost
3205 formals list.
3207 If we ignore whitespace, this right paren should be the first one we
3208 see which is (ignoring whitespace) immediately followed either by the
3209 open curly-brace beginning the function body or by an alphabetic
3210 character (in the case where the function definition is in old (K&R)
3211 style and there are some declarations of formal parameters). */
3213 /* It is possible that the right paren we are looking for is on the
3214 current line (together with its following token). Just in case that
3215 might be true, we start out here by skipping down to the right end of
3216 the current line before starting our scan. */
3218 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3219 continue;
3220 end_formals--;
3222 #ifdef UNPROTOIZE
3224 /* Now scan backwards while looking for the right end of the rightmost
3225 formals list associated with this function definition. */
3228 char ch;
3229 const char *l_brace_p;
3231 /* Look leftward and try to find a right-paren. */
3233 while (*end_formals != ')')
3235 if (ISSPACE ((unsigned char)*end_formals))
3236 while (ISSPACE ((unsigned char)*end_formals))
3237 check_source (--end_formals > clean_read_ptr, 0);
3238 else
3239 check_source (--end_formals > clean_read_ptr, 0);
3242 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3243 /* Since we are unprotoizing an ANSI-style (prototyped) function
3244 definition, there had better not be anything (except whitespace)
3245 between the end of the ANSI formals list and the beginning of the
3246 function body (i.e. the '{'). */
3248 check_source (ch == '{', l_brace_p);
3251 #else /* !defined (UNPROTOIZE) */
3253 /* Now scan backwards while looking for the right end of the rightmost
3254 formals list associated with this function definition. */
3256 while (1)
3258 char ch;
3259 const char *l_brace_p;
3261 /* Look leftward and try to find a right-paren. */
3263 while (*end_formals != ')')
3265 if (ISSPACE ((const unsigned char)*end_formals))
3266 while (ISSPACE ((const unsigned char)*end_formals))
3267 check_source (--end_formals > clean_read_ptr, 0);
3268 else
3269 check_source (--end_formals > clean_read_ptr, 0);
3272 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3274 /* Since it is possible that we found a right paren before the starting
3275 '{' of the body which IS NOT the one at the end of the real K&R
3276 formals list (say for instance, we found one embedded inside one of
3277 the old K&R formal parameter declarations) we have to check to be
3278 sure that this is in fact the right paren that we were looking for.
3280 The one we were looking for *must* be followed by either a '{' or
3281 by an alphabetic character, while others *cannot* validly be followed
3282 by such characters. */
3284 if ((ch == '{') || ISALPHA ((unsigned char) ch))
3285 break;
3287 /* At this point, we have found a right paren, but we know that it is
3288 not the one we were looking for, so backup one character and keep
3289 looking. */
3291 check_source (--end_formals > clean_read_ptr, 0);
3294 #endif /* !defined (UNPROTOIZE) */
3296 return end_formals;
3299 #ifndef UNPROTOIZE
3301 /* Insert into the output file a totally new declaration for a function
3302 which (up until now) was being called from within the current block
3303 without having been declared at any point such that the declaration
3304 was visible (i.e. in scope) at the point of the call.
3306 We need to add in explicit declarations for all such function calls
3307 in order to get the full benefit of prototype-based function call
3308 parameter type checking. */
3310 static void
3311 add_local_decl (const def_dec_info *def_dec_p, const char *clean_text_p)
3313 const char *start_of_block;
3314 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3316 /* Don't insert new local explicit declarations unless explicitly requested
3317 to do so. */
3319 if (!local_flag)
3320 return;
3322 /* Setup here to recover from confusing source code detected during this
3323 particular "edit". */
3325 save_pointers ();
3326 if (setjmp (source_confusion_recovery))
3328 restore_pointers ();
3329 notice ("%s: local declaration for function '%s' not inserted\n",
3330 pname, function_to_edit);
3331 return;
3334 /* We have already done a seek to the start of the line which should
3335 contain *the* open curly brace which begins the block in which we need
3336 to insert an explicit function declaration (to replace the implicit one).
3338 Now we scan that line, starting from the left, until we find the
3339 open curly brace we are looking for. Note that there may actually be
3340 multiple open curly braces on the given line, but we will be happy
3341 with the leftmost one no matter what. */
3343 start_of_block = clean_text_p;
3344 while (*start_of_block != '{' && *start_of_block != '\n')
3345 check_source (++start_of_block < clean_text_limit, 0);
3347 /* Note that the line from the original source could possibly
3348 contain *no* open curly braces! This happens if the line contains
3349 a macro call which expands into a chunk of text which includes a
3350 block (and that block's associated open and close curly braces).
3351 In cases like this, we give up, issue a warning, and do nothing. */
3353 if (*start_of_block != '{')
3355 if (!quiet_flag)
3356 notice ("\n%s: %d: warning: can't add declaration of '%s' into macro call\n",
3357 def_dec_p->file->hash_entry->symbol, def_dec_p->line,
3358 def_dec_p->hash_entry->symbol);
3359 return;
3362 /* Figure out what a nice (pretty) indentation would be for the new
3363 declaration we are adding. In order to do this, we must scan forward
3364 from the '{' until we find the first line which starts with some
3365 non-whitespace characters (i.e. real "token" material). */
3368 const char *ep = forward_to_next_token_char (start_of_block) - 1;
3369 const char *sp;
3371 /* Now we have ep pointing at the rightmost byte of some existing indent
3372 stuff. At least that is the hope.
3374 We can now just scan backwards and find the left end of the existing
3375 indentation string, and then copy it to the output buffer. */
3377 for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--)
3378 continue;
3380 /* Now write out the open { which began this block, and any following
3381 trash up to and including the last byte of the existing indent that
3382 we just found. */
3384 output_up_to (ep);
3386 /* Now we go ahead and insert the new declaration at this point.
3388 If the definition of the given function is in the same file that we
3389 are currently editing, and if its full ANSI declaration normally
3390 would start with the keyword `extern', suppress the `extern'. */
3393 const char *decl = def_dec_p->definition->ansi_decl;
3395 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
3396 decl += 7;
3397 output_string (decl);
3400 /* Finally, write out a new indent string, just like the preceding one
3401 that we found. This will typically include a newline as the first
3402 character of the indent string. */
3404 output_bytes (sp, (size_t) (ep - sp) + 1);
3408 /* Given a pointer to a file_info record, and a pointer to the beginning
3409 of a line (in the clean text buffer) which is assumed to contain the
3410 first "follower" token for the first function definition header in the
3411 given file, find a good place to insert some new global function
3412 declarations (which will replace scattered and imprecise implicit ones)
3413 and then insert the new explicit declaration at that point in the file. */
3415 static void
3416 add_global_decls (const file_info *file_p, const char *clean_text_p)
3418 const def_dec_info *dd_p;
3419 const char *scan_p;
3421 /* Setup here to recover from confusing source code detected during this
3422 particular "edit". */
3424 save_pointers ();
3425 if (setjmp (source_confusion_recovery))
3427 restore_pointers ();
3428 notice ("%s: global declarations for file '%s' not inserted\n",
3429 pname, shortpath (NULL, file_p->hash_entry->symbol));
3430 return;
3433 /* Start by finding a good location for adding the new explicit function
3434 declarations. To do this, we scan backwards, ignoring whitespace
3435 and comments and other junk until we find either a semicolon, or until
3436 we hit the beginning of the file. */
3438 scan_p = find_rightmost_formals_list (clean_text_p);
3439 for (;; --scan_p)
3441 if (scan_p < clean_text_base)
3442 break;
3443 check_source (scan_p > clean_read_ptr, 0);
3444 if (*scan_p == ';')
3445 break;
3448 /* scan_p now points either to a semicolon, or to just before the start
3449 of the whole file. */
3451 /* Now scan forward for the first non-whitespace character. In theory,
3452 this should be the first character of the following function definition
3453 header. We will put in the added declarations just prior to that. */
3455 scan_p++;
3456 while (ISSPACE ((const unsigned char)*scan_p))
3457 scan_p++;
3458 scan_p--;
3460 output_up_to (scan_p);
3462 /* Now write out full prototypes for all of the things that had been
3463 implicitly declared in this file (but only those for which we were
3464 actually able to find unique matching definitions). Avoid duplicates
3465 by marking things that we write out as we go. */
3468 int some_decls_added = 0;
3470 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3471 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
3473 const char *decl = dd_p->definition->ansi_decl;
3475 /* If the function for which we are inserting a declaration is
3476 actually defined later in the same file, then suppress the
3477 leading `extern' keyword (if there is one). */
3479 if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
3480 decl += 7;
3482 output_string ("\n");
3483 output_string (decl);
3484 some_decls_added = 1;
3485 ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
3487 if (some_decls_added)
3488 output_string ("\n\n");
3491 /* Unmark all of the definitions that we just marked. */
3493 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3494 if (dd_p->definition)
3495 ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
3498 #endif /* !defined (UNPROTOIZE) */
3500 /* Do the editing operation specifically for a function "definition". Note
3501 that editing operations for function "declarations" are handled by a
3502 separate routine above. */
3504 static void
3505 edit_fn_definition (const def_dec_info *def_dec_p,
3506 const char *volatile clean_text_p)
3508 const char *end_formals;
3509 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3511 /* Setup here to recover from confusing source code detected during this
3512 particular "edit". */
3514 save_pointers ();
3515 if (setjmp (source_confusion_recovery))
3517 restore_pointers ();
3518 notice ("%s: definition of function '%s' not converted\n",
3519 pname, function_to_edit);
3520 return;
3523 end_formals = find_rightmost_formals_list (clean_text_p);
3525 /* end_of_formals now points to the closing right paren of the rightmost
3526 formals list which is actually part of the `header' of the function
3527 definition that we are converting. */
3529 /* If the header of this function definition looks like it declares a
3530 function with a variable number of arguments, and if the way it does
3531 that is different from that way we would like it (i.e. varargs vs.
3532 stdarg) then issue a warning and leave the header unconverted. */
3534 if (other_variable_style_function (def_dec_p->ansi_decl))
3536 if (!quiet_flag)
3537 notice ("%s: %d: warning: definition of %s not converted\n",
3538 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3539 identify_lineno (end_formals),
3540 other_var_style);
3541 output_up_to (end_formals);
3542 return;
3545 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
3547 restore_pointers ();
3548 notice ("%s: definition of function '%s' not converted\n",
3549 pname, function_to_edit);
3550 return;
3553 /* Have to output the last right paren because this never gets flushed by
3554 edit_formals_list. */
3556 output_up_to (end_formals);
3558 #ifdef UNPROTOIZE
3560 const char *decl_p;
3561 const char *semicolon_p;
3562 const char *limit_p;
3563 const char *scan_p;
3564 int had_newlines = 0;
3566 /* Now write out the K&R style formal declarations, one per line. */
3568 decl_p = def_dec_p->formal_decls;
3569 limit_p = decl_p + strlen (decl_p);
3570 for (;decl_p < limit_p; decl_p = semicolon_p + 2)
3572 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
3573 continue;
3574 output_string ("\n");
3575 output_string (indent_string);
3576 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
3579 /* If there are no newlines between the end of the formals list and the
3580 start of the body, we should insert one now. */
3582 for (scan_p = end_formals+1; *scan_p != '{'; )
3584 if (*scan_p == '\n')
3586 had_newlines = 1;
3587 break;
3589 check_source (++scan_p < clean_text_limit, 0);
3591 if (!had_newlines)
3592 output_string ("\n");
3594 #else /* !defined (UNPROTOIZE) */
3595 /* If we are protoizing, there may be some flotsam & jetsam (like comments
3596 and preprocessing directives) after the old formals list but before
3597 the following { and we would like to preserve that stuff while effectively
3598 deleting the existing K&R formal parameter declarations. We do so here
3599 in a rather tricky way. Basically, we white out any stuff *except*
3600 the comments/pp-directives in the original text buffer, then, if there
3601 is anything in this area *other* than whitespace, we output it. */
3603 const char *end_formals_orig;
3604 const char *start_body;
3605 const char *start_body_orig;
3606 const char *scan;
3607 const char *scan_orig;
3608 int have_flotsam = 0;
3609 int have_newlines = 0;
3611 for (start_body = end_formals + 1; *start_body != '{';)
3612 check_source (++start_body < clean_text_limit, 0);
3614 end_formals_orig = orig_text_base + (end_formals - clean_text_base);
3615 start_body_orig = orig_text_base + (start_body - clean_text_base);
3616 scan = end_formals + 1;
3617 scan_orig = end_formals_orig + 1;
3618 for (; scan < start_body; scan++, scan_orig++)
3620 if (*scan == *scan_orig)
3622 have_newlines |= (*scan_orig == '\n');
3623 /* Leave identical whitespace alone. */
3624 if (!ISSPACE ((const unsigned char)*scan_orig))
3625 *((NONCONST char *) scan_orig) = ' '; /* identical - so whiteout */
3627 else
3628 have_flotsam = 1;
3630 if (have_flotsam)
3631 output_bytes (end_formals_orig + 1,
3632 (size_t) (start_body_orig - end_formals_orig) - 1);
3633 else
3634 if (have_newlines)
3635 output_string ("\n");
3636 else
3637 output_string (" ");
3638 clean_read_ptr = start_body - 1;
3640 #endif /* !defined (UNPROTOIZE) */
3643 /* Clean up the clean text buffer. Do this by converting comments and
3644 preprocessing directives into spaces. Also convert line continuations
3645 into whitespace. Also, whiteout string and character literals. */
3647 static void
3648 do_cleaning (char *new_clean_text_base, const char *new_clean_text_limit)
3650 char *scan_p;
3651 int non_whitespace_since_newline = 0;
3653 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
3655 switch (*scan_p)
3657 case '/': /* Handle comments. */
3658 if (scan_p[1] != '*')
3659 goto regular;
3660 non_whitespace_since_newline = 1;
3661 scan_p[0] = ' ';
3662 scan_p[1] = ' ';
3663 scan_p += 2;
3664 while (scan_p[1] != '/' || scan_p[0] != '*')
3666 if (!ISSPACE ((const unsigned char)*scan_p))
3667 *scan_p = ' ';
3668 ++scan_p;
3669 gcc_assert (scan_p < new_clean_text_limit);
3671 *scan_p++ = ' ';
3672 *scan_p = ' ';
3673 break;
3675 case '#': /* Handle pp directives. */
3676 if (non_whitespace_since_newline)
3677 goto regular;
3678 *scan_p = ' ';
3679 while (scan_p[1] != '\n' || scan_p[0] == '\\')
3681 if (!ISSPACE ((const unsigned char)*scan_p))
3682 *scan_p = ' ';
3683 ++scan_p;
3684 gcc_assert (scan_p < new_clean_text_limit);
3686 *scan_p++ = ' ';
3687 break;
3689 case '\'': /* Handle character literals. */
3690 non_whitespace_since_newline = 1;
3691 while (scan_p[1] != '\'' || scan_p[0] == '\\')
3693 if (scan_p[0] == '\\'
3694 && !ISSPACE ((const unsigned char) scan_p[1]))
3695 scan_p[1] = ' ';
3696 if (!ISSPACE ((const unsigned char)*scan_p))
3697 *scan_p = ' ';
3698 ++scan_p;
3699 gcc_assert (scan_p < new_clean_text_limit);
3701 *scan_p++ = ' ';
3702 break;
3704 case '"': /* Handle string literals. */
3705 non_whitespace_since_newline = 1;
3706 while (scan_p[1] != '"' || scan_p[0] == '\\')
3708 if (scan_p[0] == '\\'
3709 && !ISSPACE ((const unsigned char) scan_p[1]))
3710 scan_p[1] = ' ';
3711 if (!ISSPACE ((const unsigned char)*scan_p))
3712 *scan_p = ' ';
3713 ++scan_p;
3714 gcc_assert (scan_p < new_clean_text_limit);
3716 if (!ISSPACE ((const unsigned char)*scan_p))
3717 *scan_p = ' ';
3718 scan_p++;
3719 break;
3721 case '\\': /* Handle line continuations. */
3722 if (scan_p[1] != '\n')
3723 goto regular;
3724 *scan_p = ' ';
3725 break;
3727 case '\n':
3728 non_whitespace_since_newline = 0; /* Reset. */
3729 break;
3731 case ' ':
3732 case '\v':
3733 case '\t':
3734 case '\r':
3735 case '\f':
3736 case '\b':
3737 break; /* Whitespace characters. */
3739 default:
3740 regular:
3741 non_whitespace_since_newline = 1;
3742 break;
3747 /* Given a pointer to the closing right parenthesis for a particular formals
3748 list (in the clean text buffer) find the corresponding left parenthesis
3749 and return a pointer to it. */
3751 static const char *
3752 careful_find_l_paren (const char *p)
3754 const char *q;
3755 int paren_depth;
3757 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
3759 switch (*q)
3761 case ')':
3762 paren_depth++;
3763 break;
3764 case '(':
3765 paren_depth--;
3766 break;
3769 return ++q;
3772 /* Scan the clean text buffer for cases of function definitions that we
3773 don't really know about because they were preprocessed out when the
3774 aux info files were created.
3776 In this version of protoize/unprotoize we just give a warning for each
3777 one found. A later version may be able to at least unprotoize such
3778 missed items.
3780 Note that we may easily find all function definitions simply by
3781 looking for places where there is a left paren which is (ignoring
3782 whitespace) immediately followed by either a left-brace or by an
3783 upper or lower case letter. Whenever we find this combination, we
3784 have also found a function definition header.
3786 Finding function *declarations* using syntactic clues is much harder.
3787 I will probably try to do this in a later version though. */
3789 static void
3790 scan_for_missed_items (const file_info *file_p)
3792 static const char *scan_p;
3793 const char *limit = clean_text_limit - 3;
3794 static const char *backup_limit;
3796 backup_limit = clean_text_base - 1;
3798 for (scan_p = clean_text_base; scan_p < limit; scan_p++)
3800 if (*scan_p == ')')
3802 static const char *last_r_paren;
3803 const char *ahead_p;
3805 last_r_paren = scan_p;
3807 for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
3808 check_source (++ahead_p < limit, limit);
3810 scan_p = ahead_p - 1;
3812 if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
3814 const char *last_l_paren;
3815 const int lineno = identify_lineno (ahead_p);
3817 if (setjmp (source_confusion_recovery))
3818 continue;
3820 /* We know we have a function definition header. Now skip
3821 leftwards over all of its associated formals lists. */
3825 last_l_paren = careful_find_l_paren (last_r_paren);
3826 for (last_r_paren = last_l_paren-1;
3827 ISSPACE ((const unsigned char)*last_r_paren); )
3828 check_source (--last_r_paren >= backup_limit, backup_limit);
3830 while (*last_r_paren == ')');
3832 if (is_id_char (*last_r_paren))
3834 const char *id_limit = last_r_paren + 1;
3835 const char *id_start;
3836 size_t id_length;
3837 const def_dec_info *dd_p;
3839 for (id_start = id_limit-1; is_id_char (*id_start); )
3840 check_source (--id_start >= backup_limit, backup_limit);
3841 id_start++;
3842 backup_limit = id_start;
3843 if ((id_length = (size_t) (id_limit - id_start)) == 0)
3844 goto not_missed;
3847 char *func_name = alloca (id_length + 1);
3848 static const char * const stmt_keywords[]
3849 = { "if", "else", "do", "while", "for", "switch", "case", "return", 0 };
3850 const char * const *stmt_keyword;
3852 strncpy (func_name, id_start, id_length);
3853 func_name[id_length] = '\0';
3855 /* We must check here to see if we are actually looking at
3856 a statement rather than an actual function call. */
3858 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
3859 if (!strcmp (func_name, *stmt_keyword))
3860 goto not_missed;
3862 #if 0
3863 notice ("%s: found definition of '%s' at %s(%d)\n",
3864 pname,
3865 func_name,
3866 shortpath (NULL, file_p->hash_entry->symbol),
3867 identify_lineno (id_start));
3868 #endif /* 0 */
3869 /* We really should check for a match of the function name
3870 here also, but why bother. */
3872 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3873 if (dd_p->is_func_def && dd_p->line == lineno)
3874 goto not_missed;
3876 /* If we make it here, then we did not know about this
3877 function definition. */
3879 notice ("%s: %d: warning: '%s' excluded by preprocessing\n",
3880 shortpath (NULL, file_p->hash_entry->symbol),
3881 identify_lineno (id_start), func_name);
3882 notice ("%s: function definition not converted\n",
3883 pname);
3885 not_missed: ;
3892 /* Do all editing operations for a single source file (either a "base" file
3893 or an "include" file). To do this we read the file into memory, keep a
3894 virgin copy there, make another cleaned in-core copy of the original file
3895 (i.e. one in which all of the comments and preprocessing directives have
3896 been replaced with whitespace), then use these two in-core copies of the
3897 file to make a new edited in-core copy of the file. Finally, rename the
3898 original file (as a way of saving it), and then write the edited version
3899 of the file from core to a disk file of the same name as the original.
3901 Note that the trick of making a copy of the original sans comments &
3902 preprocessing directives make the editing a whole lot easier. */
3904 static void
3905 edit_file (const hash_table_entry *hp)
3907 struct stat stat_buf;
3908 const file_info *file_p = hp->fip;
3909 char *new_orig_text_base;
3910 char *new_orig_text_limit;
3911 char *new_clean_text_base;
3912 char *new_clean_text_limit;
3913 size_t orig_size;
3914 size_t repl_size;
3915 int first_definition_in_file;
3917 /* If we are not supposed to be converting this file, or if there is
3918 nothing in there which needs converting, just skip this file. */
3920 if (!needs_to_be_converted (file_p))
3921 return;
3923 convert_filename = file_p->hash_entry->symbol;
3925 /* Convert a file if it is in a directory where we want conversion
3926 and the file is not excluded. */
3928 if (!directory_specified_p (convert_filename)
3929 || file_excluded_p (convert_filename))
3931 if (!quiet_flag
3932 #ifdef UNPROTOIZE
3933 /* Don't even mention "system" include files unless we are
3934 protoizing. If we are protoizing, we mention these as a
3935 gentle way of prodding the user to convert his "system"
3936 include files to prototype format. */
3937 && !in_system_include_dir (convert_filename)
3938 #endif /* defined (UNPROTOIZE) */
3940 notice ("%s: '%s' not converted\n",
3941 pname, shortpath (NULL, convert_filename));
3942 return;
3945 /* Let the user know what we are up to. */
3947 if (nochange_flag)
3948 notice ("%s: would convert file '%s'\n",
3949 pname, shortpath (NULL, convert_filename));
3950 else
3951 notice ("%s: converting file '%s'\n",
3952 pname, shortpath (NULL, convert_filename));
3953 fflush (stderr);
3955 /* Find out the size (in bytes) of the original file. */
3957 /* The cast avoids an erroneous warning on AIX. */
3958 if (stat (convert_filename, &stat_buf) == -1)
3960 int errno_val = errno;
3961 notice ("%s: can't get status for file '%s': %s\n",
3962 pname, shortpath (NULL, convert_filename),
3963 xstrerror (errno_val));
3964 return;
3966 orig_size = stat_buf.st_size;
3968 /* Allocate a buffer to hold the original text. */
3970 orig_text_base = new_orig_text_base = xmalloc (orig_size + 2);
3971 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
3973 /* Allocate a buffer to hold the cleaned-up version of the original text. */
3975 clean_text_base = new_clean_text_base = xmalloc (orig_size + 2);
3976 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
3977 clean_read_ptr = clean_text_base - 1;
3979 /* Allocate a buffer that will hopefully be large enough to hold the entire
3980 converted output text. As an initial guess for the maximum size of the
3981 output buffer, use 125% of the size of the original + some extra. This
3982 buffer can be expanded later as needed. */
3984 repl_size = orig_size + (orig_size >> 2) + 4096;
3985 repl_text_base = xmalloc (repl_size + 2);
3986 repl_text_limit = repl_text_base + repl_size - 1;
3987 repl_write_ptr = repl_text_base - 1;
3990 int input_file;
3991 int fd_flags;
3993 /* Open the file to be converted in READ ONLY mode. */
3995 fd_flags = O_RDONLY;
3996 #ifdef O_BINARY
3997 /* Use binary mode to avoid having to deal with different EOL characters. */
3998 fd_flags |= O_BINARY;
3999 #endif
4000 if ((input_file = open (convert_filename, fd_flags, 0444)) == -1)
4002 int errno_val = errno;
4003 notice ("%s: can't open file '%s' for reading: %s\n",
4004 pname, shortpath (NULL, convert_filename),
4005 xstrerror (errno_val));
4006 return;
4009 /* Read the entire original source text file into the original text buffer
4010 in one swell fwoop. Then figure out where the end of the text is and
4011 make sure that it ends with a newline followed by a null. */
4013 if (safe_read (input_file, new_orig_text_base, orig_size) !=
4014 (int) orig_size)
4016 int errno_val = errno;
4017 close (input_file);
4018 notice ("\n%s: error reading input file '%s': %s\n",
4019 pname, shortpath (NULL, convert_filename),
4020 xstrerror (errno_val));
4021 return;
4024 close (input_file);
4027 if (orig_size == 0 || orig_text_limit[-1] != '\n')
4029 *new_orig_text_limit++ = '\n';
4030 orig_text_limit++;
4033 /* Create the cleaned up copy of the original text. */
4035 memcpy (new_clean_text_base, orig_text_base,
4036 (size_t) (orig_text_limit - orig_text_base));
4037 do_cleaning (new_clean_text_base, new_clean_text_limit);
4039 #if 0
4041 int clean_file;
4042 size_t clean_size = orig_text_limit - orig_text_base;
4043 char *const clean_filename = alloca (strlen (convert_filename) + 6 + 1);
4045 /* Open (and create) the clean file. */
4047 strcpy (clean_filename, convert_filename);
4048 strcat (clean_filename, ".clean");
4049 if ((clean_file = creat (clean_filename, 0666)) == -1)
4051 int errno_val = errno;
4052 notice ("%s: can't create/open clean file '%s': %s\n",
4053 pname, shortpath (NULL, clean_filename),
4054 xstrerror (errno_val));
4055 return;
4058 /* Write the clean file. */
4060 safe_write (clean_file, new_clean_text_base, clean_size, clean_filename);
4062 close (clean_file);
4064 #endif /* 0 */
4066 /* Do a simplified scan of the input looking for things that were not
4067 mentioned in the aux info files because of the fact that they were
4068 in a region of the source which was preprocessed-out (via #if or
4069 via #ifdef). */
4071 scan_for_missed_items (file_p);
4073 /* Setup to do line-oriented forward seeking in the clean text buffer. */
4075 last_known_line_number = 1;
4076 last_known_line_start = clean_text_base;
4078 /* Now get down to business and make all of the necessary edits. */
4081 const def_dec_info *def_dec_p;
4083 first_definition_in_file = 1;
4084 def_dec_p = file_p->defs_decs;
4085 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
4087 const char *clean_text_p = seek_to_line (def_dec_p->line);
4089 /* clean_text_p now points to the first character of the line which
4090 contains the `terminator' for the declaration or definition that
4091 we are about to process. */
4093 #ifndef UNPROTOIZE
4095 if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
4097 add_global_decls (def_dec_p->file, clean_text_p);
4098 first_definition_in_file = 0;
4101 /* Don't edit this item if it is already in prototype format or if it
4102 is a function declaration and we have found no corresponding
4103 definition. */
4105 if (def_dec_p->prototyped
4106 || (!def_dec_p->is_func_def && !def_dec_p->definition))
4107 continue;
4109 #endif /* !defined (UNPROTOIZE) */
4111 if (def_dec_p->is_func_def)
4112 edit_fn_definition (def_dec_p, clean_text_p);
4113 else
4114 #ifndef UNPROTOIZE
4115 if (def_dec_p->is_implicit)
4116 add_local_decl (def_dec_p, clean_text_p);
4117 else
4118 #endif /* !defined (UNPROTOIZE) */
4119 edit_fn_declaration (def_dec_p, clean_text_p);
4123 /* Finalize things. Output the last trailing part of the original text. */
4125 output_up_to (clean_text_limit - 1);
4127 /* If this is just a test run, stop now and just deallocate the buffers. */
4129 if (nochange_flag)
4131 free (new_orig_text_base);
4132 free (new_clean_text_base);
4133 free (repl_text_base);
4134 return;
4137 /* Change the name of the original input file. This is just a quick way of
4138 saving the original file. */
4140 if (!nosave_flag)
4142 char *new_filename
4143 = xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
4145 strcpy (new_filename, convert_filename);
4146 #ifdef __MSDOS__
4147 /* MSDOS filenames are restricted to 8.3 format, so we save `foo.c'
4148 as `foo.<save_suffix>'. */
4149 new_filename[(strlen (convert_filename) - 1] = '\0';
4150 #endif
4151 strcat (new_filename, save_suffix);
4153 /* Don't overwrite existing file. */
4154 if (access (new_filename, F_OK) == 0)
4156 if (!quiet_flag)
4157 notice ("%s: warning: file '%s' already saved in '%s'\n",
4158 pname,
4159 shortpath (NULL, convert_filename),
4160 shortpath (NULL, new_filename));
4162 else if (rename (convert_filename, new_filename) == -1)
4164 int errno_val = errno;
4165 notice ("%s: can't link file '%s' to '%s': %s\n",
4166 pname,
4167 shortpath (NULL, convert_filename),
4168 shortpath (NULL, new_filename),
4169 xstrerror (errno_val));
4170 return;
4174 if (unlink (convert_filename) == -1)
4176 int errno_val = errno;
4177 /* The file may have already been renamed. */
4178 if (errno_val != ENOENT)
4180 notice ("%s: can't delete file '%s': %s\n",
4181 pname, shortpath (NULL, convert_filename),
4182 xstrerror (errno_val));
4183 return;
4188 int output_file;
4190 /* Open (and create) the output file. */
4192 if ((output_file = creat (convert_filename, 0666)) == -1)
4194 int errno_val = errno;
4195 notice ("%s: can't create/open output file '%s': %s\n",
4196 pname, shortpath (NULL, convert_filename),
4197 xstrerror (errno_val));
4198 return;
4200 #ifdef O_BINARY
4201 /* Use binary mode to avoid changing the existing EOL character. */
4202 setmode (output_file, O_BINARY);
4203 #endif
4205 /* Write the output file. */
4208 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
4210 safe_write (output_file, repl_text_base, out_size, convert_filename);
4213 close (output_file);
4216 /* Deallocate the conversion buffers. */
4218 free (new_orig_text_base);
4219 free (new_clean_text_base);
4220 free (repl_text_base);
4222 /* Change the mode of the output file to match the original file. */
4224 /* The cast avoids an erroneous warning on AIX. */
4225 if (chmod (convert_filename, stat_buf.st_mode) == -1)
4227 int errno_val = errno;
4228 notice ("%s: can't change mode of file '%s': %s\n",
4229 pname, shortpath (NULL, convert_filename),
4230 xstrerror (errno_val));
4233 /* Note: We would try to change the owner and group of the output file
4234 to match those of the input file here, except that may not be a good
4235 thing to do because it might be misleading. Also, it might not even
4236 be possible to do that (on BSD systems with quotas for instance). */
4239 /* Do all of the individual steps needed to do the protoization (or
4240 unprotoization) of the files referenced in the aux_info files given
4241 in the command line. */
4243 static void
4244 do_processing (void)
4246 const char * const *base_pp;
4247 const char * const * const end_pps
4248 = &base_source_filenames[n_base_source_files];
4250 #ifndef UNPROTOIZE
4251 int syscalls_len;
4252 #endif /* !defined (UNPROTOIZE) */
4254 /* One-by-one, check (and create if necessary), open, and read all of the
4255 stuff in each aux_info file. After reading each aux_info file, the
4256 aux_info_file just read will be automatically deleted unless the
4257 keep_flag is set. */
4259 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
4260 process_aux_info_file (*base_pp, keep_flag, 0);
4262 #ifndef UNPROTOIZE
4264 /* Also open and read the special SYSCALLS.c aux_info file which gives us
4265 the prototypes for all of the standard system-supplied functions. */
4267 if (nondefault_syscalls_dir)
4269 syscalls_absolute_filename
4270 = xmalloc (strlen (nondefault_syscalls_dir) + 1
4271 + sizeof (syscalls_filename));
4272 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
4274 else
4276 GET_ENVIRONMENT (default_syscalls_dir, "GCC_EXEC_PREFIX");
4277 if (!default_syscalls_dir)
4279 default_syscalls_dir = standard_exec_prefix;
4281 syscalls_absolute_filename
4282 = xmalloc (strlen (default_syscalls_dir) + 0
4283 + strlen (target_machine) + 1
4284 + strlen (target_version) + 1
4285 + sizeof (syscalls_filename));
4286 strcpy (syscalls_absolute_filename, default_syscalls_dir);
4287 strcat (syscalls_absolute_filename, target_machine);
4288 strcat (syscalls_absolute_filename, "/");
4289 strcat (syscalls_absolute_filename, target_version);
4290 strcat (syscalls_absolute_filename, "/");
4293 syscalls_len = strlen (syscalls_absolute_filename);
4294 if (! IS_DIR_SEPARATOR (*(syscalls_absolute_filename + syscalls_len - 1)))
4296 *(syscalls_absolute_filename + syscalls_len++) = DIR_SEPARATOR;
4297 *(syscalls_absolute_filename + syscalls_len) = '\0';
4299 strcat (syscalls_absolute_filename, syscalls_filename);
4301 /* Call process_aux_info_file in such a way that it does not try to
4302 delete the SYSCALLS aux_info file. */
4304 process_aux_info_file (syscalls_absolute_filename, 1, 1);
4306 #endif /* !defined (UNPROTOIZE) */
4308 /* When we first read in all of the information from the aux_info files
4309 we saved in it descending line number order, because that was likely to
4310 be faster. Now however, we want the chains of def & dec records to
4311 appear in ascending line number order as we get further away from the
4312 file_info record that they hang from. The following line causes all of
4313 these lists to be rearranged into ascending line number order. */
4315 visit_each_hash_node (filename_primary, reverse_def_dec_list);
4317 #ifndef UNPROTOIZE
4319 /* Now do the "real" work. The following line causes each declaration record
4320 to be "visited". For each of these nodes, an attempt is made to match
4321 up the function declaration with a corresponding function definition,
4322 which should have a full prototype-format formals list with it. Once
4323 these match-ups are made, the conversion of the function declarations
4324 to prototype format can be made. */
4326 visit_each_hash_node (function_name_primary, connect_defs_and_decs);
4328 #endif /* !defined (UNPROTOIZE) */
4330 /* Now convert each file that can be converted (and needs to be). */
4332 visit_each_hash_node (filename_primary, edit_file);
4334 #ifndef UNPROTOIZE
4336 /* If we are working in cplusplus mode, try to rename all .c files to .C
4337 files. Don't panic if some of the renames don't work. */
4339 if (cplusplus_flag && !nochange_flag)
4340 visit_each_hash_node (filename_primary, rename_c_file);
4342 #endif /* !defined (UNPROTOIZE) */
4345 static const struct option longopts[] =
4347 {"version", 0, 0, 'V'},
4348 {"file_name", 0, 0, 'p'},
4349 {"quiet", 0, 0, 'q'},
4350 {"silent", 0, 0, 'q'},
4351 {"force", 0, 0, 'f'},
4352 {"keep", 0, 0, 'k'},
4353 {"nosave", 0, 0, 'N'},
4354 {"nochange", 0, 0, 'n'},
4355 {"compiler-options", 1, 0, 'c'},
4356 {"exclude", 1, 0, 'x'},
4357 {"directory", 1, 0, 'd'},
4358 #ifdef UNPROTOIZE
4359 {"indent", 1, 0, 'i'},
4360 #else
4361 {"local", 0, 0, 'l'},
4362 {"global", 0, 0, 'g'},
4363 {"c++", 0, 0, 'C'},
4364 {"syscalls-dir", 1, 0, 'B'},
4365 #endif
4366 {0, 0, 0, 0}
4369 extern int main (int, char **const);
4372 main (int argc, char **const argv)
4374 int longind;
4375 int c;
4376 const char *params = "";
4378 pname = strrchr (argv[0], DIR_SEPARATOR);
4379 #ifdef DIR_SEPARATOR_2
4381 char *slash;
4383 slash = strrchr (pname ? pname : argv[0], DIR_SEPARATOR_2);
4384 if (slash)
4385 pname = slash;
4387 #endif
4388 pname = pname ? pname+1 : argv[0];
4390 #ifdef SIGCHLD
4391 /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
4392 receive the signal. A different setting is inheritable */
4393 signal (SIGCHLD, SIG_DFL);
4394 #endif
4396 /* Unlock the stdio streams. */
4397 unlock_std_streams ();
4399 gcc_init_libintl ();
4401 cwd_buffer = getpwd ();
4402 if (!cwd_buffer)
4404 notice ("%s: cannot get working directory: %s\n",
4405 pname, xstrerror(errno));
4406 return (FATAL_EXIT_CODE);
4409 /* By default, convert the files in the current directory. */
4410 directory_list = string_list_cons (cwd_buffer, NULL);
4412 while ((c = getopt_long (argc, argv,
4413 #ifdef UNPROTOIZE
4414 "c:d:i:knNp:qvVx:",
4415 #else
4416 "B:c:Cd:gklnNp:qvVx:",
4417 #endif
4418 longopts, &longind)) != EOF)
4420 if (c == 0) /* Long option. */
4421 c = longopts[longind].val;
4422 switch (c)
4424 case 'p':
4425 compiler_file_name = optarg;
4426 break;
4427 case 'd':
4428 directory_list
4429 = string_list_cons (abspath (NULL, optarg), directory_list);
4430 break;
4431 case 'x':
4432 exclude_list = string_list_cons (optarg, exclude_list);
4433 break;
4435 case 'v':
4436 case 'V':
4437 version_flag = 1;
4438 break;
4439 case 'q':
4440 quiet_flag = 1;
4441 break;
4442 #if 0
4443 case 'f':
4444 force_flag = 1;
4445 break;
4446 #endif
4447 case 'n':
4448 nochange_flag = 1;
4449 keep_flag = 1;
4450 break;
4451 case 'N':
4452 nosave_flag = 1;
4453 break;
4454 case 'k':
4455 keep_flag = 1;
4456 break;
4457 case 'c':
4458 params = optarg;
4459 break;
4460 #ifdef UNPROTOIZE
4461 case 'i':
4462 indent_string = optarg;
4463 break;
4464 #else /* !defined (UNPROTOIZE) */
4465 case 'l':
4466 local_flag = 1;
4467 break;
4468 case 'g':
4469 global_flag = 1;
4470 break;
4471 case 'C':
4472 cplusplus_flag = 1;
4473 break;
4474 case 'B':
4475 nondefault_syscalls_dir = optarg;
4476 break;
4477 #endif /* !defined (UNPROTOIZE) */
4478 default:
4479 usage ();
4483 /* Set up compile_params based on -p and -c options. */
4484 munge_compile_params (params);
4486 n_base_source_files = argc - optind;
4488 /* Now actually make a list of the base source filenames. */
4490 base_source_filenames
4491 = xmalloc ((n_base_source_files + 1) * sizeof (char *));
4492 n_base_source_files = 0;
4493 for (; optind < argc; optind++)
4495 const char *path = abspath (NULL, argv[optind]);
4496 int len = strlen (path);
4498 if (path[len-1] == 'c' && path[len-2] == '.')
4499 base_source_filenames[n_base_source_files++] = path;
4500 else
4502 notice ("%s: input file names must have .c suffixes: %s\n",
4503 pname, shortpath (NULL, path));
4504 errors++;
4508 #ifndef UNPROTOIZE
4509 /* We are only interested in the very first identifier token in the
4510 definition of `va_list', so if there is more junk after that first
4511 identifier token, delete it from the `varargs_style_indicator'. */
4513 const char *cp;
4515 for (cp = varargs_style_indicator; ISIDNUM (*cp); cp++)
4516 continue;
4517 if (*cp != 0)
4518 varargs_style_indicator = savestring (varargs_style_indicator,
4519 cp - varargs_style_indicator);
4521 #endif /* !defined (UNPROTOIZE) */
4523 if (errors)
4524 usage ();
4525 else
4527 if (version_flag)
4528 fprintf (stderr, "%s %s%s\n", pname, pkgversion_string,
4529 version_string);
4530 do_processing ();
4533 return (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);