* optimize.c (initialize_inlined_parameters): Take FN to which the
[official-gcc.git] / gcc / protoize.c
blob8b518512da2dca842f97546aeaa0d6e8e208f284
1 /* Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com).
2 Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "intl.h"
25 #include <setjmp.h>
26 #include <signal.h>
27 #undef abort
29 /* Include getopt.h for the sake of getopt_long. */
30 #include "getopt.h"
32 extern char *version_string;
34 static void usage PARAMS ((void)) ATTRIBUTE_NORETURN;
35 static void aux_info_corrupted PARAMS ((void)) ATTRIBUTE_NORETURN;
36 static void declare_source_confusing PARAMS ((const char *)) ATTRIBUTE_NORETURN;
37 static const char *shortpath PARAMS ((const char *, const char *));
38 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
39 static void notice PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
40 static char *savestring PARAMS ((const char *, unsigned int));
41 static char *dupnstr PARAMS ((const char *, size_t));
42 static const char *substr PARAMS ((const char *, const char * const));
43 static int safe_read PARAMS ((int, PTR, int));
44 static void safe_write PARAMS ((int, PTR, int, const char *));
45 static void save_pointers PARAMS ((void));
46 static void restore_pointers PARAMS ((void));
47 static int is_id_char PARAMS ((int));
48 static int in_system_include_dir PARAMS ((const char *));
49 static int directory_specified_p PARAMS ((const char *));
50 static int file_excluded_p PARAMS ((const char *));
51 static char *unexpand_if_needed PARAMS ((const char *));
52 static char *abspath PARAMS ((const char *, const char *));
53 static void check_aux_info PARAMS ((int));
54 static const char *find_corresponding_lparen PARAMS ((const char *));
55 static int referenced_file_is_newer PARAMS ((const char *, time_t));
56 static void save_def_or_dec PARAMS ((const char *, int));
57 static void munge_compile_params PARAMS ((const char *));
58 static int gen_aux_info_file PARAMS ((const char *));
59 static void process_aux_info_file PARAMS ((const char *, int, int));
60 static int identify_lineno PARAMS ((const char *));
61 static void check_source PARAMS ((int, const char *));
62 static const char *seek_to_line PARAMS ((int));
63 static const char *forward_to_next_token_char PARAMS ((const char *));
64 static void output_bytes PARAMS ((const char *, size_t));
65 static void output_string PARAMS ((const char *));
66 static void output_up_to PARAMS ((const char *));
67 static int other_variable_style_function PARAMS ((const char *));
68 static const char *find_rightmost_formals_list PARAMS ((const char *));
69 static void do_cleaning PARAMS ((char *, const char *));
70 static const char *careful_find_l_paren PARAMS ((const char *));
71 static void do_processing PARAMS ((void));
73 /* Look for these where the `const' qualifier is intentionally cast aside. */
74 #define NONCONST
76 /* Define a default place to find the SYSCALLS.X file. */
78 #ifndef UNPROTOIZE
80 #ifndef STANDARD_EXEC_PREFIX
81 #define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
82 #endif /* !defined STANDARD_EXEC_PREFIX */
84 static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX;
85 static const char * const target_machine = DEFAULT_TARGET_MACHINE;
86 static const char * const target_version = DEFAULT_TARGET_VERSION;
88 #ifndef GET_ENV_PATH_LIST
89 #define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
90 #endif
92 #endif /* !defined (UNPROTOIZE) */
94 /* Suffix of aux_info files. */
96 static const char * const aux_info_suffix = ".X";
98 /* String to attach to filenames for saved versions of original files. */
100 static const char * const save_suffix = ".save";
102 #ifndef UNPROTOIZE
104 /* File name of the file which contains descriptions of standard system
105 routines. Note that we never actually do anything with this file per se,
106 but we do read in its corresponding aux_info file. */
108 static const char syscalls_filename[] = "SYSCALLS.c";
110 /* Default place to find the above file. */
112 static const char * default_syscalls_dir;
114 /* Variable to hold the complete absolutized filename of the SYSCALLS.c.X
115 file. */
117 static char * syscalls_absolute_filename;
119 #endif /* !defined (UNPROTOIZE) */
121 /* Type of the structure that holds information about macro unexpansions. */
123 struct unexpansion_struct {
124 const char *expanded;
125 const char *contracted;
127 typedef struct unexpansion_struct unexpansion;
129 /* A table of conversions that may need to be made for some (stupid) older
130 operating systems where these types are preprocessor macros rather than
131 typedefs (as they really ought to be).
133 WARNING: The contracted forms must be as small (or smaller) as the
134 expanded forms, or else havoc will ensue. */
136 static const unexpansion unexpansions[] = {
137 { "struct _iobuf", "FILE" },
138 { 0, 0 }
141 /* The number of "primary" slots in the hash tables for filenames and for
142 function names. This can be as big or as small as you like, except that
143 it must be a power of two. */
145 #define HASH_TABLE_SIZE (1 << 9)
147 /* Bit mask to use when computing hash values. */
149 static const int hash_mask = (HASH_TABLE_SIZE - 1);
151 /* Make a table of default system include directories
152 just as it is done in cccp.c. */
154 #ifndef STANDARD_INCLUDE_DIR
155 #define STANDARD_INCLUDE_DIR "/usr/include"
156 #endif
158 #ifndef LOCAL_INCLUDE_DIR
159 #define LOCAL_INCLUDE_DIR "/usr/local/include"
160 #endif
162 struct default_include { const char *fname;
163 const char *component;
164 int x1, x2; } include_defaults[]
165 #ifdef INCLUDE_DEFAULTS
166 = INCLUDE_DEFAULTS;
167 #else
169 /* Pick up GNU C++ specific include files. */
170 { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
171 #ifdef CROSS_COMPILE
172 /* This is the dir for fixincludes. Put it just before
173 the files that we fix. */
174 { GCC_INCLUDE_DIR, "GCC", 0, 0 },
175 /* For cross-compilation, this dir name is generated
176 automatically in Makefile.in. */
177 { CROSS_INCLUDE_DIR, 0, 0, 0 },
178 /* This is another place that the target system's headers might be. */
179 { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
180 #else /* not CROSS_COMPILE */
181 /* This should be /use/local/include and should come before
182 the fixincludes-fixed header files. */
183 { LOCAL_INCLUDE_DIR, 0, 0, 1 },
184 /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
185 Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */
186 { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
187 /* This is the dir for fixincludes. Put it just before
188 the files that we fix. */
189 { GCC_INCLUDE_DIR, "GCC", 0, 0 },
190 /* Some systems have an extra dir of include files. */
191 #ifdef SYSTEM_INCLUDE_DIR
192 { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
193 #endif
194 { STANDARD_INCLUDE_DIR, 0, 0, 0},
195 #endif /* not CROSS_COMPILE */
196 { 0, 0, 0, 0}
198 #endif /* no INCLUDE_DEFAULTS */
200 /* Datatype for lists of directories or filenames. */
201 struct string_list
203 const char *name;
204 struct string_list *next;
207 static struct string_list *string_list_cons PARAMS ((const char *,
208 struct string_list *));
210 /* List of directories in which files should be converted. */
212 struct string_list *directory_list;
214 /* List of file names which should not be converted.
215 A file is excluded if the end of its name, following a /,
216 matches one of the names in this list. */
218 struct string_list *exclude_list;
220 /* The name of the other style of variable-number-of-parameters functions
221 (i.e. the style that we want to leave unconverted because we don't yet
222 know how to convert them to this style. This string is used in warning
223 messages. */
225 /* Also define here the string that we can search for in the parameter lists
226 taken from the .X files which will unambiguously indicate that we have
227 found a varargs style function. */
229 #ifdef UNPROTOIZE
230 static const char * const other_var_style = "stdarg";
231 #else /* !defined (UNPROTOIZE) */
232 static const char * const other_var_style = "varargs";
233 /* Note that this is a string containing the expansion of va_alist.
234 But in `main' we discard all but the first token. */
235 static const char *varargs_style_indicator = STRINGIFY (va_alist);
236 #endif /* !defined (UNPROTOIZE) */
238 /* The following two types are used to create hash tables. In this program,
239 there are two hash tables which are used to store and quickly lookup two
240 different classes of strings. The first type of strings stored in the
241 first hash table are absolute filenames of files which protoize needs to
242 know about. The second type of strings (stored in the second hash table)
243 are function names. It is this second class of strings which really
244 inspired the use of the hash tables, because there may be a lot of them. */
246 typedef struct hash_table_entry_struct hash_table_entry;
248 /* Do some typedefs so that we don't have to write "struct" so often. */
250 typedef struct def_dec_info_struct def_dec_info;
251 typedef struct file_info_struct file_info;
252 typedef struct f_list_chain_item_struct f_list_chain_item;
254 #ifndef UNPROTOIZE
255 static int is_syscalls_file PARAMS ((const file_info *));
256 static void rename_c_file PARAMS ((const hash_table_entry *));
257 static const def_dec_info *find_extern_def PARAMS ((const def_dec_info *,
258 const def_dec_info *));
259 static const def_dec_info *find_static_definition PARAMS ((const def_dec_info *));
260 static void connect_defs_and_decs PARAMS ((const hash_table_entry *));
261 static void add_local_decl PARAMS ((const def_dec_info *, const char *));
262 static void add_global_decls PARAMS ((const file_info *, const char *));
263 #endif /* ! UNPROTOIZE */
264 static int needs_to_be_converted PARAMS ((const file_info *));
265 static void visit_each_hash_node PARAMS ((const hash_table_entry *,
266 void (*)(const hash_table_entry *)));
267 static hash_table_entry *add_symbol PARAMS ((hash_table_entry *, const char *));
268 static hash_table_entry *lookup PARAMS ((hash_table_entry *, const char *));
269 static void free_def_dec PARAMS ((def_dec_info *));
270 static file_info *find_file PARAMS ((const char *, int));
271 static void reverse_def_dec_list PARAMS ((const hash_table_entry *));
272 static void edit_fn_declaration PARAMS ((const def_dec_info *, const char *));
273 static int edit_formals_lists PARAMS ((const char *, unsigned int,
274 const def_dec_info *));
275 static void edit_fn_definition PARAMS ((const def_dec_info *, const char *));
276 static void scan_for_missed_items PARAMS ((const file_info *));
277 static void edit_file PARAMS ((const hash_table_entry *));
279 /* In the struct below, note that the "_info" field has two different uses
280 depending on the type of hash table we are in (i.e. either the filenames
281 hash table or the function names hash table). In the filenames hash table
282 the info fields of the entries point to the file_info struct which is
283 associated with each filename (1 per filename). In the function names
284 hash table, the info field points to the head of a singly linked list of
285 def_dec_info entries which are all defs or decs of the function whose
286 name is pointed to by the "symbol" field. Keeping all of the defs/decs
287 for a given function name on a special list specifically for that function
288 name makes it quick and easy to find out all of the important information
289 about a given (named) function. */
291 struct hash_table_entry_struct {
292 hash_table_entry * hash_next; /* -> to secondary entries */
293 const char * symbol; /* -> to the hashed string */
294 union {
295 const def_dec_info * _ddip;
296 file_info * _fip;
297 } _info;
299 #define ddip _info._ddip
300 #define fip _info._fip
302 /* Define a type specifically for our two hash tables. */
304 typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
306 /* The following struct holds all of the important information about any
307 single filename (e.g. file) which we need to know about. */
309 struct file_info_struct {
310 const hash_table_entry * hash_entry; /* -> to associated hash entry */
311 const def_dec_info * defs_decs; /* -> to chain of defs/decs */
312 time_t mtime; /* Time of last modification. */
315 /* Due to the possibility that functions may return pointers to functions,
316 (which may themselves have their own parameter lists) and due to the
317 fact that returned pointers-to-functions may be of type "pointer-to-
318 function-returning-pointer-to-function" (ad nauseum) we have to keep
319 an entire chain of ANSI style formal parameter lists for each function.
321 Normally, for any given function, there will only be one formals list
322 on the chain, but you never know.
324 Note that the head of each chain of formals lists is pointed to by the
325 `f_list_chain' field of the corresponding def_dec_info record.
327 For any given chain, the item at the head of the chain is the *leftmost*
328 parameter list seen in the actual C language function declaration. If
329 there are other members of the chain, then these are linked in left-to-right
330 order from the head of the chain. */
332 struct f_list_chain_item_struct {
333 const f_list_chain_item * chain_next; /* -> to next item on chain */
334 const char * formals_list; /* -> to formals list string */
337 /* The following struct holds all of the important information about any
338 single function definition or declaration which we need to know about.
339 Note that for unprotoize we don't need to know very much because we
340 never even create records for stuff that we don't intend to convert
341 (like for instance defs and decs which are already in old K&R format
342 and "implicit" function declarations). */
344 struct def_dec_info_struct {
345 const def_dec_info * next_in_file; /* -> to rest of chain for file */
346 file_info * file; /* -> file_info for containing file */
347 int line; /* source line number of def/dec */
348 const char * ansi_decl; /* -> left end of ansi decl */
349 hash_table_entry * hash_entry; /* -> hash entry for function name */
350 unsigned int is_func_def; /* = 0 means this is a declaration */
351 const def_dec_info * next_for_func; /* -> to rest of chain for func name */
352 unsigned int f_list_count; /* count of formals lists we expect */
353 char prototyped; /* = 0 means already prototyped */
354 #ifndef UNPROTOIZE
355 const f_list_chain_item * f_list_chain; /* -> chain of formals lists */
356 const def_dec_info * definition; /* -> def/dec containing related def */
357 char is_static; /* = 0 means visibility is "extern" */
358 char is_implicit; /* != 0 for implicit func decl's */
359 char written; /* != 0 means written for implicit */
360 #else /* !defined (UNPROTOIZE) */
361 const char * formal_names; /* -> to list of names of formals */
362 const char * formal_decls; /* -> to string of formal declarations */
363 #endif /* !defined (UNPROTOIZE) */
366 /* Pointer to the tail component of the filename by which this program was
367 invoked. Used everywhere in error and warning messages. */
369 static const char *pname;
371 /* Error counter. Will be non-zero if we should give up at the next convenient
372 stopping point. */
374 static int errors = 0;
376 /* Option flags. */
377 /* ??? These comments should say what the flag mean as well as the options
378 that set them. */
380 /* File name to use for running gcc. Allows GCC 2 to be named
381 something other than gcc. */
382 static const char *compiler_file_name = "gcc";
384 static int version_flag = 0; /* Print our version number. */
385 static int quiet_flag = 0; /* Don't print messages normally. */
386 static int nochange_flag = 0; /* Don't convert, just say what files
387 we would have converted. */
388 static int nosave_flag = 0; /* Don't save the old version. */
389 static int keep_flag = 0; /* Don't delete the .X files. */
390 static const char ** compile_params = 0; /* Option string for gcc. */
391 #ifdef UNPROTOIZE
392 static const char *indent_string = " "; /* Indentation for newly
393 inserted parm decls. */
394 #else /* !defined (UNPROTOIZE) */
395 static int local_flag = 0; /* Insert new local decls (when?). */
396 static int global_flag = 0; /* set by -g option */
397 static int cplusplus_flag = 0; /* Rename converted files to *.C. */
398 static const char *nondefault_syscalls_dir = 0; /* Dir to look for
399 SYSCALLS.c.X in. */
400 #endif /* !defined (UNPROTOIZE) */
402 /* An index into the compile_params array where we should insert the source
403 file name when we are ready to exec the C compiler. A zero value indicates
404 that we have not yet called munge_compile_params. */
406 static int input_file_name_index = 0;
408 /* An index into the compile_params array where we should insert the filename
409 for the aux info file, when we run the C compiler. */
410 static int aux_info_file_name_index = 0;
412 /* Count of command line arguments which were "filename" arguments. */
414 static int n_base_source_files = 0;
416 /* Points to a malloc'ed list of pointers to all of the filenames of base
417 source files which were specified on the command line. */
419 static const char **base_source_filenames;
421 /* Line number of the line within the current aux_info file that we
422 are currently processing. Used for error messages in case the prototypes
423 info file is corrupted somehow. */
425 static int current_aux_info_lineno;
427 /* Pointer to the name of the source file currently being converted. */
429 static const char *convert_filename;
431 /* Pointer to relative root string (taken from aux_info file) which indicates
432 where directory the user was in when he did the compilation step that
433 produced the containing aux_info file. */
435 static const char *invocation_filename;
437 /* Pointer to the base of the input buffer that holds the original text for the
438 source file currently being converted. */
440 static const char *orig_text_base;
442 /* Pointer to the byte just beyond the end of the input buffer that holds the
443 original text for the source file currently being converted. */
445 static const char *orig_text_limit;
447 /* Pointer to the base of the input buffer that holds the cleaned text for the
448 source file currently being converted. */
450 static const char *clean_text_base;
452 /* Pointer to the byte just beyond the end of the input buffer that holds the
453 cleaned text for the source file currently being converted. */
455 static const char *clean_text_limit;
457 /* Pointer to the last byte in the cleaned text buffer that we have already
458 (virtually) copied to the output buffer (or decided to ignore). */
460 static const char * clean_read_ptr;
462 /* Pointer to the base of the output buffer that holds the replacement text
463 for the source file currently being converted. */
465 static char *repl_text_base;
467 /* Pointer to the byte just beyond the end of the output buffer that holds the
468 replacement text for the source file currently being converted. */
470 static char *repl_text_limit;
472 /* Pointer to the last byte which has been stored into the output buffer.
473 The next byte to be stored should be stored just past where this points
474 to. */
476 static char * repl_write_ptr;
478 /* Pointer into the cleaned text buffer for the source file we are currently
479 converting. This points to the first character of the line that we last
480 did a "seek_to_line" to (see below). */
482 static const char *last_known_line_start;
484 /* Number of the line (in the cleaned text buffer) that we last did a
485 "seek_to_line" to. Will be one if we just read a new source file
486 into the cleaned text buffer. */
488 static int last_known_line_number;
490 /* The filenames hash table. */
492 static hash_table filename_primary;
494 /* The function names hash table. */
496 static hash_table function_name_primary;
498 /* The place to keep the recovery address which is used only in cases where
499 we get hopelessly confused by something in the cleaned original text. */
501 static jmp_buf source_confusion_recovery;
503 /* A pointer to the current directory filename (used by abspath). */
505 static char *cwd_buffer;
507 /* A place to save the read pointer until we are sure that an individual
508 attempt at editing will succeed. */
510 static const char * saved_clean_read_ptr;
512 /* A place to save the write pointer until we are sure that an individual
513 attempt at editing will succeed. */
515 static char * saved_repl_write_ptr;
517 /* Translate and output an error message. */
518 static void
519 notice VPARAMS ((const char *msgid, ...))
521 #ifndef ANSI_PROTOTYPES
522 const char *msgid;
523 #endif
524 va_list ap;
526 VA_START (ap, msgid);
528 #ifndef ANSI_PROTOTYPES
529 msgid = va_arg (ap, const char *);
530 #endif
532 vfprintf (stderr, _(msgid), ap);
533 va_end (ap);
537 /* Make a copy of a string INPUT with size SIZE. */
539 static char *
540 savestring (input, size)
541 const char *input;
542 unsigned int size;
544 char *output = (char *) xmalloc (size + 1);
545 strcpy (output, input);
546 return output;
549 /* More 'friendly' abort that prints the line and file.
550 config.h can #define abort fancy_abort if you like that sort of thing. */
552 void
553 fancy_abort ()
555 notice ("%s: internal abort\n", pname);
556 exit (FATAL_EXIT_CODE);
559 /* Make a duplicate of the first N bytes of a given string in a newly
560 allocated area. */
562 static char *
563 dupnstr (s, n)
564 const char *s;
565 size_t n;
567 char *ret_val = (char *) xmalloc (n + 1);
569 strncpy (ret_val, s, n);
570 ret_val[n] = '\0';
571 return ret_val;
574 /* Return a pointer to the first occurrence of s2 within s1 or NULL if s2
575 does not occur within s1. Assume neither s1 nor s2 are null pointers. */
577 static const char *
578 substr (s1, s2)
579 const char *s1;
580 const char *const s2;
582 for (; *s1 ; s1++)
584 const char *p1;
585 const char *p2;
586 int c;
588 for (p1 = s1, p2 = s2; (c = *p2); p1++, p2++)
589 if (*p1 != c)
590 goto outer;
591 return s1;
592 outer:
595 return 0;
598 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
599 retrying if necessary. Return the actual number of bytes read. */
601 static int
602 safe_read (desc, ptr, len)
603 int desc;
604 PTR ptr;
605 int len;
607 int left = len;
608 while (left > 0) {
609 int nchars = read (desc, ptr, left);
610 if (nchars < 0)
612 #ifdef EINTR
613 if (errno == EINTR)
614 continue;
615 #endif
616 return nchars;
618 if (nchars == 0)
619 break;
620 /* Arithmetic on void pointers is a gcc extention. */
621 ptr = (char *) ptr + nchars;
622 left -= nchars;
624 return len - left;
627 /* Write LEN bytes at PTR to descriptor DESC,
628 retrying if necessary, and treating any real error as fatal. */
630 static void
631 safe_write (desc, ptr, len, out_fname)
632 int desc;
633 PTR ptr;
634 int len;
635 const char *out_fname;
637 while (len > 0) {
638 int written = write (desc, ptr, len);
639 if (written < 0)
641 int errno_val = errno;
642 #ifdef EINTR
643 if (errno_val == EINTR)
644 continue;
645 #endif
646 notice ("%s: error writing file `%s': %s\n",
647 pname, shortpath (NULL, out_fname), xstrerror (errno_val));
648 return;
650 /* Arithmetic on void pointers is a gcc extention. */
651 ptr = (char *) ptr + written;
652 len -= written;
656 /* Get setup to recover in case the edit we are about to do goes awry. */
658 static void
659 save_pointers ()
661 saved_clean_read_ptr = clean_read_ptr;
662 saved_repl_write_ptr = repl_write_ptr;
665 /* Call this routine to recover our previous state whenever something looks
666 too confusing in the source code we are trying to edit. */
668 static void
669 restore_pointers ()
671 clean_read_ptr = saved_clean_read_ptr;
672 repl_write_ptr = saved_repl_write_ptr;
675 /* Return true if the given character is a valid identifier character. */
677 static int
678 is_id_char (ch)
679 int ch;
681 return (ISALNUM (ch) || (ch == '_') || (ch == '$'));
684 /* Give a message indicating the proper way to invoke this program and then
685 exit with non-zero status. */
687 static void
688 usage ()
690 #ifdef UNPROTOIZE
691 notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
692 pname, pname);
693 #else /* !defined (UNPROTOIZE) */
694 notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
695 pname, pname);
696 #endif /* !defined (UNPROTOIZE) */
697 exit (FATAL_EXIT_CODE);
700 /* Return true if the given filename (assumed to be an absolute filename)
701 designates a file residing anywhere beneath any one of the "system"
702 include directories. */
704 static int
705 in_system_include_dir (path)
706 const char *path;
708 struct default_include *p;
710 if (path[0] != '/')
711 abort (); /* Must be an absolutized filename. */
713 for (p = include_defaults; p->fname; p++)
714 if (!strncmp (path, p->fname, strlen (p->fname))
715 && path[strlen (p->fname)] == '/')
716 return 1;
717 return 0;
720 #if 0
721 /* Return true if the given filename designates a file that the user has
722 read access to and for which the user has write access to the containing
723 directory. */
725 static int
726 file_could_be_converted (const char *path)
728 char *const dir_name = (char *) alloca (strlen (path) + 1);
730 if (access (path, R_OK))
731 return 0;
734 char *dir_last_slash;
736 strcpy (dir_name, path);
737 dir_last_slash = strrchr (dir_name, '/');
738 if (dir_last_slash)
739 *dir_last_slash = '\0';
740 else
741 abort (); /* Should have been an absolutized filename. */
744 if (access (path, W_OK))
745 return 0;
747 return 1;
750 /* Return true if the given filename designates a file that we are allowed
751 to modify. Files which we should not attempt to modify are (a) "system"
752 include files, and (b) files which the user doesn't have write access to,
753 and (c) files which reside in directories which the user doesn't have
754 write access to. Unless requested to be quiet, give warnings about
755 files that we will not try to convert for one reason or another. An
756 exception is made for "system" include files, which we never try to
757 convert and for which we don't issue the usual warnings. */
759 static int
760 file_normally_convertible (const char *path)
762 char *const dir_name = alloca (strlen (path) + 1);
764 if (in_system_include_dir (path))
765 return 0;
768 char *dir_last_slash;
770 strcpy (dir_name, path);
771 dir_last_slash = strrchr (dir_name, '/');
772 if (dir_last_slash)
773 *dir_last_slash = '\0';
774 else
775 abort (); /* Should have been an absolutized filename. */
778 if (access (path, R_OK))
780 if (!quiet_flag)
781 notice ("%s: warning: no read access for file `%s'\n",
782 pname, shortpath (NULL, path));
783 return 0;
786 if (access (path, W_OK))
788 if (!quiet_flag)
789 notice ("%s: warning: no write access for file `%s'\n",
790 pname, shortpath (NULL, path));
791 return 0;
794 if (access (dir_name, W_OK))
796 if (!quiet_flag)
797 notice ("%s: warning: no write access for dir containing `%s'\n",
798 pname, shortpath (NULL, path));
799 return 0;
802 return 1;
804 #endif /* 0 */
806 #ifndef UNPROTOIZE
808 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X
809 file. Return false otherwise. */
811 static int
812 is_syscalls_file (fi_p)
813 const file_info *fi_p;
815 char const *f = fi_p->hash_entry->symbol;
816 size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
817 return sysl <= fl && strcmp (f + fl - sysl, syscalls_filename) == 0;
820 #endif /* !defined (UNPROTOIZE) */
822 /* Check to see if this file will need to have anything done to it on this
823 run. If there is nothing in the given file which both needs conversion
824 and for which we have the necessary stuff to do the conversion, return
825 false. Otherwise, return true.
827 Note that (for protoize) it is only valid to call this function *after*
828 the connections between declarations and definitions have all been made
829 by connect_defs_and_decs. */
831 static int
832 needs_to_be_converted (file_p)
833 const file_info *file_p;
835 const def_dec_info *ddp;
837 #ifndef UNPROTOIZE
839 if (is_syscalls_file (file_p))
840 return 0;
842 #endif /* !defined (UNPROTOIZE) */
844 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
846 if (
848 #ifndef UNPROTOIZE
850 /* ... and if we a protoizing and this function is in old style ... */
851 !ddp->prototyped
852 /* ... and if this a definition or is a decl with an associated def ... */
853 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
855 #else /* defined (UNPROTOIZE) */
857 /* ... and if we are unprotoizing and this function is in new style ... */
858 ddp->prototyped
860 #endif /* defined (UNPROTOIZE) */
862 /* ... then the containing file needs converting. */
863 return -1;
864 return 0;
867 /* Return 1 if the file name NAME is in a directory
868 that should be converted. */
870 static int
871 directory_specified_p (name)
872 const char *name;
874 struct string_list *p;
876 for (p = directory_list; p; p = p->next)
877 if (!strncmp (name, p->name, strlen (p->name))
878 && name[strlen (p->name)] == '/')
880 const char *q = name + strlen (p->name) + 1;
882 /* If there are more slashes, it's in a subdir, so
883 this match doesn't count. */
884 while (*q)
885 if (*q++ == '/')
886 goto lose;
887 return 1;
889 lose: ;
892 return 0;
895 /* Return 1 if the file named NAME should be excluded from conversion. */
897 static int
898 file_excluded_p (name)
899 const char *name;
901 struct string_list *p;
902 int len = strlen (name);
904 for (p = exclude_list; p; p = p->next)
905 if (!strcmp (name + len - strlen (p->name), p->name)
906 && name[len - strlen (p->name) - 1] == '/')
907 return 1;
909 return 0;
912 /* Construct a new element of a string_list.
913 STRING is the new element value, and REST holds the remaining elements. */
915 static struct string_list *
916 string_list_cons (string, rest)
917 const char *string;
918 struct string_list *rest;
920 struct string_list *temp
921 = (struct string_list *) xmalloc (sizeof (struct string_list));
923 temp->next = rest;
924 temp->name = string;
925 return temp;
928 /* ??? The GNU convention for mentioning function args in its comments
929 is to capitalize them. So change "hash_tab_p" to HASH_TAB_P below.
930 Likewise for all the other functions. */
932 /* Given a hash table, apply some function to each node in the table. The
933 table to traverse is given as the "hash_tab_p" argument, and the
934 function to be applied to each node in the table is given as "func"
935 argument. */
937 static void
938 visit_each_hash_node (hash_tab_p, func)
939 const hash_table_entry *hash_tab_p;
940 void (*func) PARAMS ((const hash_table_entry *));
942 const hash_table_entry *primary;
944 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
945 if (primary->symbol)
947 hash_table_entry *second;
949 (*func)(primary);
950 for (second = primary->hash_next; second; second = second->hash_next)
951 (*func) (second);
955 /* Initialize all of the fields of a new hash table entry, pointed
956 to by the "p" parameter. Note that the space to hold the entry
957 is assumed to have already been allocated before this routine is
958 called. */
960 static hash_table_entry *
961 add_symbol (p, s)
962 hash_table_entry *p;
963 const char *s;
965 p->hash_next = NULL;
966 p->symbol = xstrdup (s);
967 p->ddip = NULL;
968 p->fip = NULL;
969 return p;
972 /* Look for a particular function name or filename in the particular
973 hash table indicated by "hash_tab_p". If the name is not in the
974 given hash table, add it. Either way, return a pointer to the
975 hash table entry for the given name. */
977 static hash_table_entry *
978 lookup (hash_tab_p, search_symbol)
979 hash_table_entry *hash_tab_p;
980 const char *search_symbol;
982 int hash_value = 0;
983 const char *search_symbol_char_p = search_symbol;
984 hash_table_entry *p;
986 while (*search_symbol_char_p)
987 hash_value += *search_symbol_char_p++;
988 hash_value &= hash_mask;
989 p = &hash_tab_p[hash_value];
990 if (! p->symbol)
991 return add_symbol (p, search_symbol);
992 if (!strcmp (p->symbol, search_symbol))
993 return p;
994 while (p->hash_next)
996 p = p->hash_next;
997 if (!strcmp (p->symbol, search_symbol))
998 return p;
1000 p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry));
1001 p = p->hash_next;
1002 return add_symbol (p, search_symbol);
1005 /* Throw a def/dec record on the junk heap.
1007 Also, since we are not using this record anymore, free up all of the
1008 stuff it pointed to. */
1010 static void
1011 free_def_dec (p)
1012 def_dec_info *p;
1014 free ((NONCONST PTR) p->ansi_decl);
1016 #ifndef UNPROTOIZE
1018 const f_list_chain_item * curr;
1019 const f_list_chain_item * next;
1021 for (curr = p->f_list_chain; curr; curr = next)
1023 next = curr->chain_next;
1024 free ((NONCONST PTR) curr);
1027 #endif /* !defined (UNPROTOIZE) */
1029 free (p);
1032 /* Unexpand as many macro symbol as we can find.
1034 If the given line must be unexpanded, make a copy of it in the heap and
1035 return a pointer to the unexpanded copy. Otherwise return NULL. */
1037 static char *
1038 unexpand_if_needed (aux_info_line)
1039 const char *aux_info_line;
1041 static char *line_buf = 0;
1042 static int line_buf_size = 0;
1043 const unexpansion *unexp_p;
1044 int got_unexpanded = 0;
1045 const char *s;
1046 char *copy_p = line_buf;
1048 if (line_buf == 0)
1050 line_buf_size = 1024;
1051 line_buf = (char *) xmalloc (line_buf_size);
1054 copy_p = line_buf;
1056 /* Make a copy of the input string in line_buf, expanding as necessary. */
1058 for (s = aux_info_line; *s != '\n'; )
1060 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
1062 const char *in_p = unexp_p->expanded;
1063 size_t len = strlen (in_p);
1065 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1067 int size = strlen (unexp_p->contracted);
1068 got_unexpanded = 1;
1069 if (copy_p + size - line_buf >= line_buf_size)
1071 int offset = copy_p - line_buf;
1072 line_buf_size *= 2;
1073 line_buf_size += size;
1074 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1075 copy_p = line_buf + offset;
1077 strcpy (copy_p, unexp_p->contracted);
1078 copy_p += size;
1080 /* Assume the there will not be another replacement required
1081 within the text just replaced. */
1083 s += len;
1084 goto continue_outer;
1087 if (copy_p - line_buf == line_buf_size)
1089 int offset = copy_p - line_buf;
1090 line_buf_size *= 2;
1091 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1092 copy_p = line_buf + offset;
1094 *copy_p++ = *s++;
1095 continue_outer: ;
1097 if (copy_p + 2 - line_buf >= line_buf_size)
1099 int offset = copy_p - line_buf;
1100 line_buf_size *= 2;
1101 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1102 copy_p = line_buf + offset;
1104 *copy_p++ = '\n';
1105 *copy_p = '\0';
1107 return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
1110 /* Return the absolutized filename for the given relative
1111 filename. Note that if that filename is already absolute, it may
1112 still be returned in a modified form because this routine also
1113 eliminates redundant slashes and single dots and eliminates double
1114 dots to get a shortest possible filename from the given input
1115 filename. The absolutization of relative filenames is made by
1116 assuming that the given filename is to be taken as relative to
1117 the first argument (cwd) or to the current directory if cwd is
1118 NULL. */
1120 static char *
1121 abspath (cwd, rel_filename)
1122 const char *cwd;
1123 const char *rel_filename;
1125 /* Setup the current working directory as needed. */
1126 const char *cwd2 = (cwd) ? cwd : cwd_buffer;
1127 char *const abs_buffer
1128 = (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 2);
1129 char *endp = abs_buffer;
1130 char *outp, *inp;
1132 /* Copy the filename (possibly preceded by the current working
1133 directory name) into the absolutization buffer. */
1136 const char *src_p;
1138 if (rel_filename[0] != '/')
1140 src_p = cwd2;
1141 while ((*endp++ = *src_p++))
1142 continue;
1143 *(endp-1) = '/'; /* overwrite null */
1145 src_p = rel_filename;
1146 while ((*endp++ = *src_p++))
1147 continue;
1150 /* Now make a copy of abs_buffer into abs_buffer, shortening the
1151 filename (by taking out slashes and dots) as we go. */
1153 outp = inp = abs_buffer;
1154 *outp++ = *inp++; /* copy first slash */
1155 #if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
1156 if (inp[0] == '/')
1157 *outp++ = *inp++; /* copy second slash */
1158 #endif
1159 for (;;)
1161 if (!inp[0])
1162 break;
1163 else if (inp[0] == '/' && outp[-1] == '/')
1165 inp++;
1166 continue;
1168 else if (inp[0] == '.' && outp[-1] == '/')
1170 if (!inp[1])
1171 break;
1172 else if (inp[1] == '/')
1174 inp += 2;
1175 continue;
1177 else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/'))
1179 inp += (inp[2] == '/') ? 3 : 2;
1180 outp -= 2;
1181 while (outp >= abs_buffer && *outp != '/')
1182 outp--;
1183 if (outp < abs_buffer)
1185 /* Catch cases like /.. where we try to backup to a
1186 point above the absolute root of the logical file
1187 system. */
1189 notice ("%s: invalid file name: %s\n",
1190 pname, rel_filename);
1191 exit (FATAL_EXIT_CODE);
1193 *++outp = '\0';
1194 continue;
1197 *outp++ = *inp++;
1200 /* On exit, make sure that there is a trailing null, and make sure that
1201 the last character of the returned string is *not* a slash. */
1203 *outp = '\0';
1204 if (outp[-1] == '/')
1205 *--outp = '\0';
1207 /* Make a copy (in the heap) of the stuff left in the absolutization
1208 buffer and return a pointer to the copy. */
1210 return savestring (abs_buffer, outp - abs_buffer);
1213 /* Given a filename (and possibly a directory name from which the filename
1214 is relative) return a string which is the shortest possible
1215 equivalent for the corresponding full (absolutized) filename. The
1216 shortest possible equivalent may be constructed by converting the
1217 absolutized filename to be a relative filename (i.e. relative to
1218 the actual current working directory). However if a relative filename
1219 is longer, then the full absolute filename is returned.
1221 KNOWN BUG:
1223 Note that "simple-minded" conversion of any given type of filename (either
1224 relative or absolute) may not result in a valid equivalent filename if any
1225 subpart of the original filename is actually a symbolic link. */
1227 static const char *
1228 shortpath (cwd, filename)
1229 const char *cwd;
1230 const char *filename;
1232 char *rel_buffer;
1233 char *rel_buf_p;
1234 char *cwd_p = cwd_buffer;
1235 char *path_p;
1236 int unmatched_slash_count = 0;
1237 size_t filename_len = strlen (filename);
1239 path_p = abspath (cwd, filename);
1240 rel_buf_p = rel_buffer = (char *) xmalloc (filename_len);
1242 while (*cwd_p && (*cwd_p == *path_p))
1244 cwd_p++;
1245 path_p++;
1247 if (!*cwd_p && (!*path_p || *path_p == '/')) /* whole pwd matched */
1249 if (!*path_p) /* input *is* the current path! */
1250 return ".";
1251 else
1252 return ++path_p;
1254 else
1256 if (*path_p)
1258 --cwd_p;
1259 --path_p;
1260 while (*cwd_p != '/') /* backup to last slash */
1262 --cwd_p;
1263 --path_p;
1265 cwd_p++;
1266 path_p++;
1267 unmatched_slash_count++;
1270 /* Find out how many directory levels in cwd were *not* matched. */
1271 while (*cwd_p)
1272 if (*cwd_p++ == '/')
1273 unmatched_slash_count++;
1275 /* Now we know how long the "short name" will be.
1276 Reject it if longer than the input. */
1277 if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
1278 return filename;
1280 /* For each of them, put a `../' at the beginning of the short name. */
1281 while (unmatched_slash_count--)
1283 /* Give up if the result gets to be longer
1284 than the absolute path name. */
1285 if (rel_buffer + filename_len <= rel_buf_p + 3)
1286 return filename;
1287 *rel_buf_p++ = '.';
1288 *rel_buf_p++ = '.';
1289 *rel_buf_p++ = '/';
1292 /* Then tack on the unmatched part of the desired file's name. */
1295 if (rel_buffer + filename_len <= rel_buf_p)
1296 return filename;
1298 while ((*rel_buf_p++ = *path_p++));
1300 --rel_buf_p;
1301 if (*(rel_buf_p-1) == '/')
1302 *--rel_buf_p = '\0';
1303 return rel_buffer;
1307 /* Lookup the given filename in the hash table for filenames. If it is a
1308 new one, then the hash table info pointer will be null. In this case,
1309 we create a new file_info record to go with the filename, and we initialize
1310 that record with some reasonable values. */
1312 /* FILENAME was const, but that causes a warning on AIX when calling stat.
1313 That is probably a bug in AIX, but might as well avoid the warning. */
1315 static file_info *
1316 find_file (filename, do_not_stat)
1317 const char *filename;
1318 int do_not_stat;
1320 hash_table_entry *hash_entry_p;
1322 hash_entry_p = lookup (filename_primary, filename);
1323 if (hash_entry_p->fip)
1324 return hash_entry_p->fip;
1325 else
1327 struct stat stat_buf;
1328 file_info *file_p = (file_info *) xmalloc (sizeof (file_info));
1330 /* If we cannot get status on any given source file, give a warning
1331 and then just set its time of last modification to infinity. */
1333 if (do_not_stat)
1334 stat_buf.st_mtime = (time_t) 0;
1335 else
1337 if (stat (filename, &stat_buf) == -1)
1339 int errno_val = errno;
1340 notice ("%s: %s: can't get status: %s\n",
1341 pname, shortpath (NULL, filename),
1342 xstrerror (errno_val));
1343 stat_buf.st_mtime = (time_t) -1;
1347 hash_entry_p->fip = file_p;
1348 file_p->hash_entry = hash_entry_p;
1349 file_p->defs_decs = NULL;
1350 file_p->mtime = stat_buf.st_mtime;
1351 return file_p;
1355 /* Generate a fatal error because some part of the aux_info file is
1356 messed up. */
1358 static void
1359 aux_info_corrupted ()
1361 notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
1362 pname, current_aux_info_lineno);
1363 exit (FATAL_EXIT_CODE);
1366 /* ??? This comment is vague. Say what the condition is for. */
1367 /* Check to see that a condition is true. This is kind of like an assert. */
1369 static void
1370 check_aux_info (cond)
1371 int cond;
1373 if (! cond)
1374 aux_info_corrupted ();
1377 /* Given a pointer to the closing right parenthesis for a particular formals
1378 list (in an aux_info file) find the corresponding left parenthesis and
1379 return a pointer to it. */
1381 static const char *
1382 find_corresponding_lparen (p)
1383 const char *p;
1385 const char *q;
1386 int paren_depth;
1388 for (paren_depth = 1, q = p-1; paren_depth; q--)
1390 switch (*q)
1392 case ')':
1393 paren_depth++;
1394 break;
1395 case '(':
1396 paren_depth--;
1397 break;
1400 return ++q;
1403 /* Given a line from an aux info file, and a time at which the aux info
1404 file it came from was created, check to see if the item described in
1405 the line comes from a file which has been modified since the aux info
1406 file was created. If so, return non-zero, else return zero. */
1408 static int
1409 referenced_file_is_newer (l, aux_info_mtime)
1410 const char *l;
1411 time_t aux_info_mtime;
1413 const char *p;
1414 file_info *fi_p;
1415 char *filename;
1417 check_aux_info (l[0] == '/');
1418 check_aux_info (l[1] == '*');
1419 check_aux_info (l[2] == ' ');
1422 const char *filename_start = p = l + 3;
1424 while (*p != ':')
1425 p++;
1426 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1427 strncpy (filename, filename_start, (size_t) (p - filename_start));
1428 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 fi_p = find_file (abspath (invocation_filename, filename), 0);
1438 return (fi_p->mtime > aux_info_mtime);
1441 /* Given a line of info from the aux_info file, create a new
1442 def_dec_info record to remember all of the important information about
1443 a function definition or declaration.
1445 Link this record onto the list of such records for the particular file in
1446 which it occurred in proper (descending) line number order (for now).
1448 If there is an identical record already on the list for the file, throw
1449 this one away. Doing so takes care of the (useless and troublesome)
1450 duplicates which are bound to crop up due to multiple inclusions of any
1451 given individual header file.
1453 Finally, link the new def_dec record onto the list of such records
1454 pertaining to this particular function name. */
1456 static void
1457 save_def_or_dec (l, is_syscalls)
1458 const char *l;
1459 int is_syscalls;
1461 const char *p;
1462 const char *semicolon_p;
1463 def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info));
1465 #ifndef UNPROTOIZE
1466 def_dec_p->written = 0;
1467 #endif /* !defined (UNPROTOIZE) */
1469 /* Start processing the line by picking off 5 pieces of information from
1470 the left hand end of the line. These are filename, line number,
1471 new/old/implicit flag (new = ANSI prototype format), definition or
1472 declaration flag, and extern/static flag). */
1474 check_aux_info (l[0] == '/');
1475 check_aux_info (l[1] == '*');
1476 check_aux_info (l[2] == ' ');
1479 const char *filename_start = p = l + 3;
1480 char *filename;
1482 while (*p != ':')
1483 p++;
1484 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1485 strncpy (filename, filename_start, (size_t) (p - filename_start));
1486 filename[p-filename_start] = '\0';
1488 /* Call find_file to find the file_info record associated with the file
1489 which contained this particular def or dec item. Note that this call
1490 may cause a new file_info record to be created if this is the first time
1491 that we have ever known about this particular file.
1493 Note that we started out by forcing all of the base source file names
1494 (i.e. the names of the aux_info files with the .X stripped off) into the
1495 filenames hash table, and we simultaneously setup file_info records for
1496 all of these base file names (even if they may be useless later).
1497 The file_info records for all of these "base" file names (properly)
1498 act as file_info records for the "original" (i.e. un-included) files
1499 which were submitted to gcc for compilation (when the -aux-info
1500 option was used). */
1502 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1506 const char *line_number_start = ++p;
1507 char line_number[10];
1509 while (*p != ':')
1510 p++;
1511 strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1512 line_number[p-line_number_start] = '\0';
1513 def_dec_p->line = atoi (line_number);
1516 /* Check that this record describes a new-style, old-style, or implicit
1517 definition or declaration. */
1519 p++; /* Skip over the `:'. */
1520 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1522 /* Is this a new style (ANSI prototyped) definition or declaration? */
1524 def_dec_p->prototyped = (*p == 'N');
1526 #ifndef UNPROTOIZE
1528 /* Is this an implicit declaration? */
1530 def_dec_p->is_implicit = (*p == 'I');
1532 #endif /* !defined (UNPROTOIZE) */
1534 p++;
1536 check_aux_info ((*p == 'C') || (*p == 'F'));
1538 /* Is this item a function definition (F) or a declaration (C). Note that
1539 we treat item taken from the syscalls file as though they were function
1540 definitions regardless of what the stuff in the file says. */
1542 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1544 #ifndef UNPROTOIZE
1545 def_dec_p->definition = 0; /* Fill this in later if protoizing. */
1546 #endif /* !defined (UNPROTOIZE) */
1548 check_aux_info (*p++ == ' ');
1549 check_aux_info (*p++ == '*');
1550 check_aux_info (*p++ == '/');
1551 check_aux_info (*p++ == ' ');
1553 #ifdef UNPROTOIZE
1554 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1555 #else /* !defined (UNPROTOIZE) */
1556 if (!strncmp (p, "static", 6))
1557 def_dec_p->is_static = -1;
1558 else if (!strncmp (p, "extern", 6))
1559 def_dec_p->is_static = 0;
1560 else
1561 check_aux_info (0); /* Didn't find either `extern' or `static'. */
1562 #endif /* !defined (UNPROTOIZE) */
1565 const char *ansi_start = p;
1567 p += 6; /* Pass over the "static" or "extern". */
1569 /* We are now past the initial stuff. Search forward from here to find
1570 the terminating semicolon that should immediately follow the entire
1571 ANSI format function declaration. */
1573 while (*++p != ';')
1574 continue;
1576 semicolon_p = p;
1578 /* Make a copy of the ansi declaration part of the line from the aux_info
1579 file. */
1581 def_dec_p->ansi_decl
1582 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1584 /* Backup and point at the final right paren of the final argument list. */
1586 p--;
1588 #ifndef UNPROTOIZE
1589 def_dec_p->f_list_chain = NULL;
1590 #endif /* !defined (UNPROTOIZE) */
1592 while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
1593 if (*p != ')')
1595 free_def_dec (def_dec_p);
1596 return;
1600 /* Now isolate a whole set of formal argument lists, one-by-one. Normally,
1601 there will only be one list to isolate, but there could be more. */
1603 def_dec_p->f_list_count = 0;
1605 for (;;)
1607 const char *left_paren_p = find_corresponding_lparen (p);
1608 #ifndef UNPROTOIZE
1610 f_list_chain_item *cip
1611 = (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
1613 cip->formals_list
1614 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1616 /* Add the new chain item at the head of the current list. */
1618 cip->chain_next = def_dec_p->f_list_chain;
1619 def_dec_p->f_list_chain = cip;
1621 #endif /* !defined (UNPROTOIZE) */
1622 def_dec_p->f_list_count++;
1624 p = left_paren_p - 2;
1626 /* p must now point either to another right paren, or to the last
1627 character of the name of the function that was declared/defined.
1628 If p points to another right paren, then this indicates that we
1629 are dealing with multiple formals lists. In that case, there
1630 really should be another right paren preceding this right paren. */
1632 if (*p != ')')
1633 break;
1634 else
1635 check_aux_info (*--p == ')');
1640 const char *past_fn = p + 1;
1642 check_aux_info (*past_fn == ' ');
1644 /* Scan leftwards over the identifier that names the function. */
1646 while (is_id_char (*p))
1647 p--;
1648 p++;
1650 /* p now points to the leftmost character of the function name. */
1653 char *fn_string = (char *) alloca (past_fn - p + 1);
1655 strncpy (fn_string, p, (size_t) (past_fn - p));
1656 fn_string[past_fn-p] = '\0';
1657 def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1661 /* Look at all of the defs and decs for this function name that we have
1662 collected so far. If there is already one which is at the same
1663 line number in the same file, then we can discard this new def_dec_info
1664 record.
1666 As an extra assurance that any such pair of (nominally) identical
1667 function declarations are in fact identical, we also compare the
1668 ansi_decl parts of the lines from the aux_info files just to be on
1669 the safe side.
1671 This comparison will fail if (for instance) the user was playing
1672 messy games with the preprocessor which ultimately causes one
1673 function declaration in one header file to look differently when
1674 that file is included by two (or more) other files. */
1677 const def_dec_info *other;
1679 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1681 if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1683 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1685 notice ("%s:%d: declaration of function `%s' takes different forms\n",
1686 def_dec_p->file->hash_entry->symbol,
1687 def_dec_p->line,
1688 def_dec_p->hash_entry->symbol);
1689 exit (FATAL_EXIT_CODE);
1691 free_def_dec (def_dec_p);
1692 return;
1697 #ifdef UNPROTOIZE
1699 /* If we are doing unprotoizing, we must now setup the pointers that will
1700 point to the K&R name list and to the K&R argument declarations list.
1702 Note that if this is only a function declaration, then we should not
1703 expect to find any K&R style formals list following the ANSI-style
1704 formals list. This is because GCC knows that such information is
1705 useless in the case of function declarations (function definitions
1706 are a different story however).
1708 Since we are unprotoizing, we don't need any such lists anyway.
1709 All we plan to do is to delete all characters between ()'s in any
1710 case. */
1712 def_dec_p->formal_names = NULL;
1713 def_dec_p->formal_decls = NULL;
1715 if (def_dec_p->is_func_def)
1717 p = semicolon_p;
1718 check_aux_info (*++p == ' ');
1719 check_aux_info (*++p == '/');
1720 check_aux_info (*++p == '*');
1721 check_aux_info (*++p == ' ');
1722 check_aux_info (*++p == '(');
1725 const char *kr_names_start = ++p; /* Point just inside '('. */
1727 while (*p++ != ')')
1728 continue;
1729 p--; /* point to closing right paren */
1731 /* Make a copy of the K&R parameter names list. */
1733 def_dec_p->formal_names
1734 = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1737 check_aux_info (*++p == ' ');
1738 p++;
1740 /* p now points to the first character of the K&R style declarations
1741 list (if there is one) or to the star-slash combination that ends
1742 the comment in which such lists get embedded. */
1744 /* Make a copy of the K&R formal decls list and set the def_dec record
1745 to point to it. */
1747 if (*p == '*') /* Are there no K&R declarations? */
1749 check_aux_info (*++p == '/');
1750 def_dec_p->formal_decls = "";
1752 else
1754 const char *kr_decls_start = p;
1756 while (p[0] != '*' || p[1] != '/')
1757 p++;
1758 p--;
1760 check_aux_info (*p == ' ');
1762 def_dec_p->formal_decls
1763 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1766 /* Handle a special case. If we have a function definition marked as
1767 being in "old" style, and if its formal names list is empty, then
1768 it may actually have the string "void" in its real formals list
1769 in the original source code. Just to make sure, we will get setup
1770 to convert such things anyway.
1772 This kludge only needs to be here because of an insurmountable
1773 problem with generating .X files. */
1775 if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1776 def_dec_p->prototyped = 1;
1779 /* Since we are unprotoizing, if this item is already in old (K&R) style,
1780 we can just ignore it. If that is true, throw away the itme now. */
1782 if (!def_dec_p->prototyped)
1784 free_def_dec (def_dec_p);
1785 return;
1788 #endif /* defined (UNPROTOIZE) */
1790 /* Add this record to the head of the list of records pertaining to this
1791 particular function name. */
1793 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1794 def_dec_p->hash_entry->ddip = def_dec_p;
1796 /* Add this new def_dec_info record to the sorted list of def_dec_info
1797 records for this file. Note that we don't have to worry about duplicates
1798 (caused by multiple inclusions of header files) here because we have
1799 already eliminated duplicates above. */
1801 if (!def_dec_p->file->defs_decs)
1803 def_dec_p->file->defs_decs = def_dec_p;
1804 def_dec_p->next_in_file = NULL;
1806 else
1808 int line = def_dec_p->line;
1809 const def_dec_info *prev = NULL;
1810 const def_dec_info *curr = def_dec_p->file->defs_decs;
1811 const def_dec_info *next = curr->next_in_file;
1813 while (next && (line < curr->line))
1815 prev = curr;
1816 curr = next;
1817 next = next->next_in_file;
1819 if (line >= curr->line)
1821 def_dec_p->next_in_file = curr;
1822 if (prev)
1823 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1824 else
1825 def_dec_p->file->defs_decs = def_dec_p;
1827 else /* assert (next == NULL); */
1829 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
1830 /* assert (next == NULL); */
1831 def_dec_p->next_in_file = next;
1836 /* Set up the vector COMPILE_PARAMS which is the argument list for running GCC.
1837 Also set input_file_name_index and aux_info_file_name_index
1838 to the indices of the slots where the file names should go. */
1840 /* We initialize the vector by removing -g, -O, -S, -c, and -o options,
1841 and adding '-aux-info AUXFILE -S -o /dev/null INFILE' at the end. */
1843 static void
1844 munge_compile_params (params_list)
1845 const char *params_list;
1847 /* Build up the contents in a temporary vector
1848 that is so big that to has to be big enough. */
1849 const char **temp_params
1850 = (const char **) alloca ((strlen (params_list) + 8) * sizeof (char *));
1851 int param_count = 0;
1852 const char *param;
1854 temp_params[param_count++] = compiler_file_name;
1855 for (;;)
1857 while (ISSPACE ((const unsigned char)*params_list))
1858 params_list++;
1859 if (!*params_list)
1860 break;
1861 param = params_list;
1862 while (*params_list && !ISSPACE ((const unsigned char)*params_list))
1863 params_list++;
1864 if (param[0] != '-')
1865 temp_params[param_count++]
1866 = dupnstr (param, (size_t) (params_list - param));
1867 else
1869 switch (param[1])
1871 case 'g':
1872 case 'O':
1873 case 'S':
1874 case 'c':
1875 break; /* Don't copy these. */
1876 case 'o':
1877 while (ISSPACE ((const unsigned char)*params_list))
1878 params_list++;
1879 while (*params_list
1880 && !ISSPACE ((const unsigned char)*params_list))
1881 params_list++;
1882 break;
1883 default:
1884 temp_params[param_count++]
1885 = dupnstr (param, (size_t) (params_list - param));
1888 if (!*params_list)
1889 break;
1891 temp_params[param_count++] = "-aux-info";
1893 /* Leave room for the aux-info file name argument. */
1894 aux_info_file_name_index = param_count;
1895 temp_params[param_count++] = NULL;
1897 temp_params[param_count++] = "-S";
1898 temp_params[param_count++] = "-o";
1899 temp_params[param_count++] = "/dev/null";
1901 /* Leave room for the input file name argument. */
1902 input_file_name_index = param_count;
1903 temp_params[param_count++] = NULL;
1904 /* Terminate the list. */
1905 temp_params[param_count++] = NULL;
1907 /* Make a copy of the compile_params in heap space. */
1909 compile_params
1910 = (const char **) xmalloc (sizeof (char *) * (param_count+1));
1911 memcpy (compile_params, temp_params, sizeof (char *) * param_count);
1914 /* Do a recompilation for the express purpose of generating a new aux_info
1915 file to go with a specific base source file.
1917 The result is a boolean indicating success. */
1919 static int
1920 gen_aux_info_file (base_filename)
1921 const char *base_filename;
1923 if (!input_file_name_index)
1924 munge_compile_params ("");
1926 /* Store the full source file name in the argument vector. */
1927 compile_params[input_file_name_index] = shortpath (NULL, base_filename);
1928 /* Add .X to source file name to get aux-info file name. */
1929 compile_params[aux_info_file_name_index] =
1930 concat (compile_params[input_file_name_index], ".X", NULL);
1932 if (!quiet_flag)
1933 notice ("%s: compiling `%s'\n",
1934 pname, compile_params[input_file_name_index]);
1937 char *errmsg_fmt, *errmsg_arg;
1938 int wait_status, pid;
1940 pid = pexecute (compile_params[0], (char * const *) compile_params,
1941 pname, NULL, &errmsg_fmt, &errmsg_arg,
1942 PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
1944 if (pid == -1)
1946 int errno_val = errno;
1947 fprintf (stderr, "%s: ", pname);
1948 fprintf (stderr, errmsg_fmt, errmsg_arg);
1949 fprintf (stderr, ": %s\n", xstrerror (errno_val));
1950 return 0;
1953 pid = pwait (pid, &wait_status, 0);
1954 if (pid == -1)
1956 notice ("%s: wait: %s\n", pname, xstrerror (errno));
1957 return 0;
1959 if (WIFSIGNALED (wait_status))
1961 notice ("%s: subprocess got fatal signal %d\n",
1962 pname, WTERMSIG (wait_status));
1963 return 0;
1965 if (WIFEXITED (wait_status))
1967 if (WEXITSTATUS (wait_status) != 0)
1969 notice ("%s: %s exited with status %d\n",
1970 pname, compile_params[0], WEXITSTATUS (wait_status));
1971 return 0;
1973 return 1;
1975 abort ();
1979 /* Read in all of the information contained in a single aux_info file.
1980 Save all of the important stuff for later. */
1982 static void
1983 process_aux_info_file (base_source_filename, keep_it, is_syscalls)
1984 const char *base_source_filename;
1985 int keep_it;
1986 int is_syscalls;
1988 size_t base_len = strlen (base_source_filename);
1989 char * aux_info_filename
1990 = (char *) alloca (base_len + strlen (aux_info_suffix) + 1);
1991 char *aux_info_base;
1992 char *aux_info_limit;
1993 char *aux_info_relocated_name;
1994 const char *aux_info_second_line;
1995 time_t aux_info_mtime;
1996 size_t aux_info_size;
1997 int must_create;
1999 /* Construct the aux_info filename from the base source filename. */
2001 strcpy (aux_info_filename, base_source_filename);
2002 strcat (aux_info_filename, aux_info_suffix);
2004 /* Check that the aux_info file exists and is readable. If it does not
2005 exist, try to create it (once only). */
2007 /* If file doesn't exist, set must_create.
2008 Likewise if it exists and we can read it but it is obsolete.
2009 Otherwise, report an error. */
2010 must_create = 0;
2012 /* Come here with must_create set to 1 if file is out of date. */
2013 start_over: ;
2015 if (access (aux_info_filename, R_OK) == -1)
2017 if (errno == ENOENT)
2019 if (is_syscalls)
2021 notice ("%s: warning: missing SYSCALLS file `%s'\n",
2022 pname, aux_info_filename);
2023 return;
2025 must_create = 1;
2027 else
2029 int errno_val = errno;
2030 notice ("%s: can't read aux info file `%s': %s\n",
2031 pname, shortpath (NULL, aux_info_filename),
2032 xstrerror (errno_val));
2033 errors++;
2034 return;
2037 #if 0 /* There is code farther down to take care of this. */
2038 else
2040 struct stat s1, s2;
2041 stat (aux_info_file_name, &s1);
2042 stat (base_source_file_name, &s2);
2043 if (s2.st_mtime > s1.st_mtime)
2044 must_create = 1;
2046 #endif /* 0 */
2048 /* If we need a .X file, create it, and verify we can read it. */
2049 if (must_create)
2051 if (!gen_aux_info_file (base_source_filename))
2053 errors++;
2054 return;
2056 if (access (aux_info_filename, R_OK) == -1)
2058 int errno_val = errno;
2059 notice ("%s: can't read aux info file `%s': %s\n",
2060 pname, shortpath (NULL, aux_info_filename),
2061 xstrerror (errno_val));
2062 errors++;
2063 return;
2068 struct stat stat_buf;
2070 /* Get some status information about this aux_info file. */
2072 if (stat (aux_info_filename, &stat_buf) == -1)
2074 int errno_val = errno;
2075 notice ("%s: can't get status of aux info file `%s': %s\n",
2076 pname, shortpath (NULL, aux_info_filename),
2077 xstrerror (errno_val));
2078 errors++;
2079 return;
2082 /* Check on whether or not this aux_info file is zero length. If it is,
2083 then just ignore it and return. */
2085 if ((aux_info_size = stat_buf.st_size) == 0)
2086 return;
2088 /* Get the date/time of last modification for this aux_info file and
2089 remember it. We will have to check that any source files that it
2090 contains information about are at least this old or older. */
2092 aux_info_mtime = stat_buf.st_mtime;
2094 if (!is_syscalls)
2096 /* Compare mod time with the .c file; update .X file if obsolete.
2097 The code later on can fail to check the .c file
2098 if it did not directly define any functions. */
2100 if (stat (base_source_filename, &stat_buf) == -1)
2102 int errno_val = errno;
2103 notice ("%s: can't get status of aux info file `%s': %s\n",
2104 pname, shortpath (NULL, base_source_filename),
2105 xstrerror (errno_val));
2106 errors++;
2107 return;
2109 if (stat_buf.st_mtime > aux_info_mtime)
2111 must_create = 1;
2112 goto start_over;
2118 int aux_info_file;
2120 /* Open the aux_info file. */
2122 if ((aux_info_file = open (aux_info_filename, O_RDONLY, 0444 )) == -1)
2124 int errno_val = errno;
2125 notice ("%s: can't open aux info file `%s' for reading: %s\n",
2126 pname, shortpath (NULL, aux_info_filename),
2127 xstrerror (errno_val));
2128 return;
2131 /* Allocate space to hold the aux_info file in memory. */
2133 aux_info_base = xmalloc (aux_info_size + 1);
2134 aux_info_limit = aux_info_base + aux_info_size;
2135 *aux_info_limit = '\0';
2137 /* Read the aux_info file into memory. */
2139 if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
2140 (int) aux_info_size)
2142 int errno_val = errno;
2143 notice ("%s: error reading aux info file `%s': %s\n",
2144 pname, shortpath (NULL, aux_info_filename),
2145 xstrerror (errno_val));
2146 free (aux_info_base);
2147 close (aux_info_file);
2148 return;
2151 /* Close the aux info file. */
2153 if (close (aux_info_file))
2155 int errno_val = errno;
2156 notice ("%s: error closing aux info file `%s': %s\n",
2157 pname, shortpath (NULL, aux_info_filename),
2158 xstrerror (errno_val));
2159 free (aux_info_base);
2160 close (aux_info_file);
2161 return;
2165 /* Delete the aux_info file (unless requested not to). If the deletion
2166 fails for some reason, don't even worry about it. */
2168 if (must_create && !keep_it)
2169 if (unlink (aux_info_filename) == -1)
2171 int errno_val = errno;
2172 notice ("%s: can't delete aux info file `%s': %s\n",
2173 pname, shortpath (NULL, aux_info_filename),
2174 xstrerror (errno_val));
2177 /* Save a pointer into the first line of the aux_info file which
2178 contains the filename of the directory from which the compiler
2179 was invoked when the associated source file was compiled.
2180 This information is used later to help create complete
2181 filenames out of the (potentially) relative filenames in
2182 the aux_info file. */
2185 char *p = aux_info_base;
2187 while (*p != ':')
2188 p++;
2189 p++;
2190 while (*p == ' ')
2191 p++;
2192 invocation_filename = p; /* Save a pointer to first byte of path. */
2193 while (*p != ' ')
2194 p++;
2195 *p++ = '/';
2196 *p++ = '\0';
2197 while (*p++ != '\n')
2198 continue;
2199 aux_info_second_line = p;
2200 aux_info_relocated_name = 0;
2201 if (invocation_filename[0] != '/')
2203 /* INVOCATION_FILENAME is relative;
2204 append it to BASE_SOURCE_FILENAME's dir. */
2205 char *dir_end;
2206 aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
2207 strcpy (aux_info_relocated_name, base_source_filename);
2208 dir_end = strrchr (aux_info_relocated_name, '/');
2209 if (dir_end)
2210 dir_end++;
2211 else
2212 dir_end = aux_info_relocated_name;
2213 strcpy (dir_end, invocation_filename);
2214 invocation_filename = aux_info_relocated_name;
2220 const char *aux_info_p;
2222 /* Do a pre-pass on the lines in the aux_info file, making sure that all
2223 of the source files referenced in there are at least as old as this
2224 aux_info file itself. If not, go back and regenerate the aux_info
2225 file anew. Don't do any of this for the syscalls file. */
2227 if (!is_syscalls)
2229 current_aux_info_lineno = 2;
2231 for (aux_info_p = aux_info_second_line; *aux_info_p; )
2233 if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2235 free (aux_info_base);
2236 free (aux_info_relocated_name);
2237 if (keep_it && unlink (aux_info_filename) == -1)
2239 int errno_val = errno;
2240 notice ("%s: can't delete file `%s': %s\n",
2241 pname, shortpath (NULL, aux_info_filename),
2242 xstrerror (errno_val));
2243 return;
2245 must_create = 1;
2246 goto start_over;
2249 /* Skip over the rest of this line to start of next line. */
2251 while (*aux_info_p != '\n')
2252 aux_info_p++;
2253 aux_info_p++;
2254 current_aux_info_lineno++;
2258 /* Now do the real pass on the aux_info lines. Save their information in
2259 the in-core data base. */
2261 current_aux_info_lineno = 2;
2263 for (aux_info_p = aux_info_second_line; *aux_info_p;)
2265 char *unexpanded_line = unexpand_if_needed (aux_info_p);
2267 if (unexpanded_line)
2269 save_def_or_dec (unexpanded_line, is_syscalls);
2270 free (unexpanded_line);
2272 else
2273 save_def_or_dec (aux_info_p, is_syscalls);
2275 /* Skip over the rest of this line and get to start of next line. */
2277 while (*aux_info_p != '\n')
2278 aux_info_p++;
2279 aux_info_p++;
2280 current_aux_info_lineno++;
2284 free (aux_info_base);
2285 free (aux_info_relocated_name);
2288 #ifndef UNPROTOIZE
2290 /* Check an individual filename for a .c suffix. If the filename has this
2291 suffix, rename the file such that its suffix is changed to .C. This
2292 function implements the -C option. */
2294 static void
2295 rename_c_file (hp)
2296 const hash_table_entry *hp;
2298 const char *filename = hp->symbol;
2299 int last_char_index = strlen (filename) - 1;
2300 char *const new_filename = (char *) alloca (strlen (filename) + 1);
2302 /* Note that we don't care here if the given file was converted or not. It
2303 is possible that the given file was *not* converted, simply because there
2304 was nothing in it which actually required conversion. Even in this case,
2305 we want to do the renaming. Note that we only rename files with the .c
2306 suffix. */
2308 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.')
2309 return;
2311 strcpy (new_filename, filename);
2312 new_filename[last_char_index] = 'C';
2314 if (link (filename, new_filename) == -1)
2316 int errno_val = errno;
2317 notice ("%s: warning: can't link file `%s' to `%s': %s\n",
2318 pname, shortpath (NULL, filename),
2319 shortpath (NULL, new_filename), xstrerror (errno_val));
2320 errors++;
2321 return;
2324 if (unlink (filename) == -1)
2326 int errno_val = errno;
2327 notice ("%s: warning: can't delete file `%s': %s\n",
2328 pname, shortpath (NULL, filename), xstrerror (errno_val));
2329 errors++;
2330 return;
2334 #endif /* !defined (UNPROTOIZE) */
2336 /* Take the list of definitions and declarations attached to a particular
2337 file_info node and reverse the order of the list. This should get the
2338 list into an order such that the item with the lowest associated line
2339 number is nearest the head of the list. When these lists are originally
2340 built, they are in the opposite order. We want to traverse them in
2341 normal line number order later (i.e. lowest to highest) so reverse the
2342 order here. */
2344 static void
2345 reverse_def_dec_list (hp)
2346 const hash_table_entry *hp;
2348 file_info *file_p = hp->fip;
2349 def_dec_info *prev = NULL;
2350 def_dec_info *current = (def_dec_info *)file_p->defs_decs;
2352 if (!current)
2353 return; /* no list to reverse */
2355 prev = current;
2356 if (! (current = (def_dec_info *)current->next_in_file))
2357 return; /* can't reverse a single list element */
2359 prev->next_in_file = NULL;
2361 while (current)
2363 def_dec_info *next = (def_dec_info *)current->next_in_file;
2365 current->next_in_file = prev;
2366 prev = current;
2367 current = next;
2370 file_p->defs_decs = prev;
2373 #ifndef UNPROTOIZE
2375 /* Find the (only?) extern definition for a particular function name, starting
2376 from the head of the linked list of entries for the given name. If we
2377 cannot find an extern definition for the given function name, issue a
2378 warning and scrounge around for the next best thing, i.e. an extern
2379 function declaration with a prototype attached to it. Note that we only
2380 allow such substitutions for extern declarations and never for static
2381 declarations. That's because the only reason we allow them at all is
2382 to let un-prototyped function declarations for system-supplied library
2383 functions get their prototypes from our own extra SYSCALLS.c.X file which
2384 contains all of the correct prototypes for system functions. */
2386 static const def_dec_info *
2387 find_extern_def (head, user)
2388 const def_dec_info *head;
2389 const def_dec_info *user;
2391 const def_dec_info *dd_p;
2392 const def_dec_info *extern_def_p = NULL;
2393 int conflict_noted = 0;
2395 /* Don't act too stupid here. Somebody may try to convert an entire system
2396 in one swell fwoop (rather than one program at a time, as should be done)
2397 and in that case, we may find that there are multiple extern definitions
2398 of a given function name in the entire set of source files that we are
2399 converting. If however one of these definitions resides in exactly the
2400 same source file as the reference we are trying to satisfy then in that
2401 case it would be stupid for us to fail to realize that this one definition
2402 *must* be the precise one we are looking for.
2404 To make sure that we don't miss an opportunity to make this "same file"
2405 leap of faith, we do a prescan of the list of records relating to the
2406 given function name, and we look (on this first scan) *only* for a
2407 definition of the function which is in the same file as the reference
2408 we are currently trying to satisfy. */
2410 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2411 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2412 return dd_p;
2414 /* Now, since we have not found a definition in the same file as the
2415 reference, we scan the list again and consider all possibilities from
2416 all files. Here we may get conflicts with the things listed in the
2417 SYSCALLS.c.X file, but if that happens it only means that the source
2418 code being converted contains its own definition of a function which
2419 could have been supplied by libc.a. In such cases, we should avoid
2420 issuing the normal warning, and defer to the definition given in the
2421 user's own code. */
2423 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2424 if (dd_p->is_func_def && !dd_p->is_static)
2426 if (!extern_def_p) /* Previous definition? */
2427 extern_def_p = dd_p; /* Remember the first definition found. */
2428 else
2430 /* Ignore definition just found if it came from SYSCALLS.c.X. */
2432 if (is_syscalls_file (dd_p->file))
2433 continue;
2435 /* Quietly replace the definition previously found with the one
2436 just found if the previous one was from SYSCALLS.c.X. */
2438 if (is_syscalls_file (extern_def_p->file))
2440 extern_def_p = dd_p;
2441 continue;
2444 /* If we get here, then there is a conflict between two function
2445 declarations for the same function, both of which came from the
2446 user's own code. */
2448 if (!conflict_noted) /* first time we noticed? */
2450 conflict_noted = 1;
2451 notice ("%s: conflicting extern definitions of '%s'\n",
2452 pname, head->hash_entry->symbol);
2453 if (!quiet_flag)
2455 notice ("%s: declarations of '%s' will not be converted\n",
2456 pname, head->hash_entry->symbol);
2457 notice ("%s: conflict list for '%s' follows:\n",
2458 pname, head->hash_entry->symbol);
2459 fprintf (stderr, "%s: %s(%d): %s\n",
2460 pname,
2461 shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2462 extern_def_p->line, extern_def_p->ansi_decl);
2465 if (!quiet_flag)
2466 fprintf (stderr, "%s: %s(%d): %s\n",
2467 pname,
2468 shortpath (NULL, dd_p->file->hash_entry->symbol),
2469 dd_p->line, dd_p->ansi_decl);
2473 /* We want to err on the side of caution, so if we found multiple conflicting
2474 definitions for the same function, treat this as being that same as if we
2475 had found no definitions (i.e. return NULL). */
2477 if (conflict_noted)
2478 return NULL;
2480 if (!extern_def_p)
2482 /* We have no definitions for this function so do the next best thing.
2483 Search for an extern declaration already in prototype form. */
2485 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2486 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2488 extern_def_p = dd_p; /* save a pointer to the definition */
2489 if (!quiet_flag)
2490 notice ("%s: warning: using formals list from %s(%d) for function `%s'\n",
2491 pname,
2492 shortpath (NULL, dd_p->file->hash_entry->symbol),
2493 dd_p->line, dd_p->hash_entry->symbol);
2494 break;
2497 /* Gripe about unprototyped function declarations that we found no
2498 corresponding definition (or other source of prototype information)
2499 for.
2501 Gripe even if the unprototyped declaration we are worried about
2502 exists in a file in one of the "system" include directories. We
2503 can gripe about these because we should have at least found a
2504 corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
2505 didn't, then that means that the SYSCALLS.c.X file is missing some
2506 needed prototypes for this particular system. That is worth telling
2507 the user about! */
2509 if (!extern_def_p)
2511 const char *file = user->file->hash_entry->symbol;
2513 if (!quiet_flag)
2514 if (in_system_include_dir (file))
2516 /* Why copy this string into `needed' at all?
2517 Why not just use user->ansi_decl without copying? */
2518 char *needed = (char *) alloca (strlen (user->ansi_decl) + 1);
2519 char *p;
2521 strcpy (needed, user->ansi_decl);
2522 p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
2523 + strlen (user->hash_entry->symbol) + 2;
2524 /* Avoid having ??? in the string. */
2525 *p++ = '?';
2526 *p++ = '?';
2527 *p++ = '?';
2528 strcpy (p, ");");
2530 notice ("%s: %d: `%s' used but missing from SYSCALLS\n",
2531 shortpath (NULL, file), user->line,
2532 needed+7); /* Don't print "extern " */
2534 #if 0
2535 else
2536 notice ("%s: %d: warning: no extern definition for `%s'\n",
2537 shortpath (NULL, file), user->line,
2538 user->hash_entry->symbol);
2539 #endif
2542 return extern_def_p;
2545 /* Find the (only?) static definition for a particular function name in a
2546 given file. Here we get the function-name and the file info indirectly
2547 from the def_dec_info record pointer which is passed in. */
2549 static const def_dec_info *
2550 find_static_definition (user)
2551 const def_dec_info *user;
2553 const def_dec_info *head = user->hash_entry->ddip;
2554 const def_dec_info *dd_p;
2555 int num_static_defs = 0;
2556 const def_dec_info *static_def_p = NULL;
2558 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2559 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2561 static_def_p = dd_p; /* save a pointer to the definition */
2562 num_static_defs++;
2564 if (num_static_defs == 0)
2566 if (!quiet_flag)
2567 notice ("%s: warning: no static definition for `%s' in file `%s'\n",
2568 pname, head->hash_entry->symbol,
2569 shortpath (NULL, user->file->hash_entry->symbol));
2571 else if (num_static_defs > 1)
2573 notice ("%s: multiple static defs of `%s' in file `%s'\n",
2574 pname, head->hash_entry->symbol,
2575 shortpath (NULL, user->file->hash_entry->symbol));
2576 return NULL;
2578 return static_def_p;
2581 /* Find good prototype style formal argument lists for all of the function
2582 declarations which didn't have them before now.
2584 To do this we consider each function name one at a time. For each function
2585 name, we look at the items on the linked list of def_dec_info records for
2586 that particular name.
2588 Somewhere on this list we should find one (and only one) def_dec_info
2589 record which represents the actual function definition, and this record
2590 should have a nice formal argument list already associated with it.
2592 Thus, all we have to do is to connect up all of the other def_dec_info
2593 records for this particular function name to the special one which has
2594 the full-blown formals list.
2596 Of course it is a little more complicated than just that. See below for
2597 more details. */
2599 static void
2600 connect_defs_and_decs (hp)
2601 const hash_table_entry *hp;
2603 const def_dec_info *dd_p;
2604 const def_dec_info *extern_def_p = NULL;
2605 int first_extern_reference = 1;
2607 /* Traverse the list of definitions and declarations for this particular
2608 function name. For each item on the list, if it is a function
2609 definition (either old style or new style) then GCC has already been
2610 kind enough to produce a prototype for us, and it is associated with
2611 the item already, so declare the item as its own associated "definition".
2613 Also, for each item which is only a function declaration, but which
2614 nonetheless has its own prototype already (obviously supplied by the user)
2615 declare the item as its own definition.
2617 Note that when/if there are multiple user-supplied prototypes already
2618 present for multiple declarations of any given function, these multiple
2619 prototypes *should* all match exactly with one another and with the
2620 prototype for the actual function definition. We don't check for this
2621 here however, since we assume that the compiler must have already done
2622 this consistency checking when it was creating the .X files. */
2624 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2625 if (dd_p->prototyped)
2626 ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2628 /* Traverse the list of definitions and declarations for this particular
2629 function name. For each item on the list, if it is an extern function
2630 declaration and if it has no associated definition yet, go try to find
2631 the matching extern definition for the declaration.
2633 When looking for the matching function definition, warn the user if we
2634 fail to find one.
2636 If we find more that one function definition also issue a warning.
2638 Do the search for the matching definition only once per unique function
2639 name (and only when absolutely needed) so that we can avoid putting out
2640 redundant warning messages, and so that we will only put out warning
2641 messages when there is actually a reference (i.e. a declaration) for
2642 which we need to find a matching definition. */
2644 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2645 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2647 if (first_extern_reference)
2649 extern_def_p = find_extern_def (hp->ddip, dd_p);
2650 first_extern_reference = 0;
2652 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2655 /* Traverse the list of definitions and declarations for this particular
2656 function name. For each item on the list, if it is a static function
2657 declaration and if it has no associated definition yet, go try to find
2658 the matching static definition for the declaration within the same file.
2660 When looking for the matching function definition, warn the user if we
2661 fail to find one in the same file with the declaration, and refuse to
2662 convert this kind of cross-file static function declaration. After all,
2663 this is stupid practice and should be discouraged.
2665 We don't have to worry about the possibility that there is more than one
2666 matching function definition in the given file because that would have
2667 been flagged as an error by the compiler.
2669 Do the search for the matching definition only once per unique
2670 function-name/source-file pair (and only when absolutely needed) so that
2671 we can avoid putting out redundant warning messages, and so that we will
2672 only put out warning messages when there is actually a reference (i.e. a
2673 declaration) for which we actually need to find a matching definition. */
2675 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2676 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2678 const def_dec_info *dd_p2;
2679 const def_dec_info *static_def;
2681 /* We have now found a single static declaration for which we need to
2682 find a matching definition. We want to minimize the work (and the
2683 number of warnings), so we will find an appropriate (matching)
2684 static definition for this declaration, and then distribute it
2685 (as the definition for) any and all other static declarations
2686 for this function name which occur within the same file, and which
2687 do not already have definitions.
2689 Note that a trick is used here to prevent subsequent attempts to
2690 call find_static_definition for a given function-name & file
2691 if the first such call returns NULL. Essentially, we convert
2692 these NULL return values to -1, and put the -1 into the definition
2693 field for each other static declaration from the same file which
2694 does not already have an associated definition.
2695 This makes these other static declarations look like they are
2696 actually defined already when the outer loop here revisits them
2697 later on. Thus, the outer loop will skip over them. Later, we
2698 turn the -1's back to NULL's. */
2700 ((NONCONST def_dec_info *) dd_p)->definition =
2701 (static_def = find_static_definition (dd_p))
2702 ? static_def
2703 : (const def_dec_info *) -1;
2705 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2706 if (!dd_p2->is_func_def && dd_p2->is_static
2707 && !dd_p2->definition && (dd_p2->file == dd_p->file))
2708 ((NONCONST def_dec_info *)dd_p2)->definition = dd_p->definition;
2711 /* Convert any dummy (-1) definitions we created in the step above back to
2712 NULL's (as they should be). */
2714 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2715 if (dd_p->definition == (def_dec_info *) -1)
2716 ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2719 #endif /* !defined (UNPROTOIZE) */
2721 /* Give a pointer into the clean text buffer, return a number which is the
2722 original source line number that the given pointer points into. */
2724 static int
2725 identify_lineno (clean_p)
2726 const char *clean_p;
2728 int line_num = 1;
2729 const char *scan_p;
2731 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2732 if (*scan_p == '\n')
2733 line_num++;
2734 return line_num;
2737 /* Issue an error message and give up on doing this particular edit. */
2739 static void
2740 declare_source_confusing (clean_p)
2741 const char *clean_p;
2743 if (!quiet_flag)
2745 if (clean_p == 0)
2746 notice ("%s: %d: warning: source too confusing\n",
2747 shortpath (NULL, convert_filename), last_known_line_number);
2748 else
2749 notice ("%s: %d: warning: source too confusing\n",
2750 shortpath (NULL, convert_filename),
2751 identify_lineno (clean_p));
2753 longjmp (source_confusion_recovery, 1);
2756 /* Check that a condition which is expected to be true in the original source
2757 code is in fact true. If not, issue an error message and give up on
2758 converting this particular source file. */
2760 static void
2761 check_source (cond, clean_p)
2762 int cond;
2763 const char *clean_p;
2765 if (!cond)
2766 declare_source_confusing (clean_p);
2769 /* If we think of the in-core cleaned text buffer as a memory mapped
2770 file (with the variable last_known_line_start acting as sort of a
2771 file pointer) then we can imagine doing "seeks" on the buffer. The
2772 following routine implements a kind of "seek" operation for the in-core
2773 (cleaned) copy of the source file. When finished, it returns a pointer to
2774 the start of a given (numbered) line in the cleaned text buffer.
2776 Note that protoize only has to "seek" in the forward direction on the
2777 in-core cleaned text file buffers, and it never needs to back up.
2779 This routine is made a little bit faster by remembering the line number
2780 (and pointer value) supplied (and returned) from the previous "seek".
2781 This prevents us from always having to start all over back at the top
2782 of the in-core cleaned buffer again. */
2784 static const char *
2785 seek_to_line (n)
2786 int n;
2788 if (n < last_known_line_number)
2789 abort ();
2791 while (n > last_known_line_number)
2793 while (*last_known_line_start != '\n')
2794 check_source (++last_known_line_start < clean_text_limit, 0);
2795 last_known_line_start++;
2796 last_known_line_number++;
2798 return last_known_line_start;
2801 /* Given a pointer to a character in the cleaned text buffer, return a pointer
2802 to the next non-whitespace character which follows it. */
2804 static const char *
2805 forward_to_next_token_char (ptr)
2806 const char *ptr;
2808 for (++ptr; ISSPACE ((const unsigned char)*ptr);
2809 check_source (++ptr < clean_text_limit, 0))
2810 continue;
2811 return ptr;
2814 /* Copy a chunk of text of length `len' and starting at `str' to the current
2815 output buffer. Note that all attempts to add stuff to the current output
2816 buffer ultimately go through here. */
2818 static void
2819 output_bytes (str, len)
2820 const char *str;
2821 size_t len;
2823 if ((repl_write_ptr + 1) + len >= repl_text_limit)
2825 size_t new_size = (repl_text_limit - repl_text_base) << 1;
2826 char *new_buf = (char *) xrealloc (repl_text_base, new_size);
2828 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
2829 repl_text_base = new_buf;
2830 repl_text_limit = new_buf + new_size;
2832 memcpy (repl_write_ptr + 1, str, len);
2833 repl_write_ptr += len;
2836 /* Copy all bytes (except the trailing null) of a null terminated string to
2837 the current output buffer. */
2839 static void
2840 output_string (str)
2841 const char *str;
2843 output_bytes (str, strlen (str));
2846 /* Copy some characters from the original text buffer to the current output
2847 buffer.
2849 This routine takes a pointer argument `p' which is assumed to be a pointer
2850 into the cleaned text buffer. The bytes which are copied are the `original'
2851 equivalents for the set of bytes between the last value of `clean_read_ptr'
2852 and the argument value `p'.
2854 The set of bytes copied however, comes *not* from the cleaned text buffer,
2855 but rather from the direct counterparts of these bytes within the original
2856 text buffer.
2858 Thus, when this function is called, some bytes from the original text
2859 buffer (which may include original comments and preprocessing directives)
2860 will be copied into the output buffer.
2862 Note that the request implied when this routine is called includes the
2863 byte pointed to by the argument pointer `p'. */
2865 static void
2866 output_up_to (p)
2867 const char *p;
2869 size_t copy_length = (size_t) (p - clean_read_ptr);
2870 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
2872 if (copy_length == 0)
2873 return;
2875 output_bytes (copy_start, copy_length);
2876 clean_read_ptr = p;
2879 /* Given a pointer to a def_dec_info record which represents some form of
2880 definition of a function (perhaps a real definition, or in lieu of that
2881 perhaps just a declaration with a full prototype) return true if this
2882 function is one which we should avoid converting. Return false
2883 otherwise. */
2885 static int
2886 other_variable_style_function (ansi_header)
2887 const char *ansi_header;
2889 #ifdef UNPROTOIZE
2891 /* See if we have a stdarg function, or a function which has stdarg style
2892 parameters or a stdarg style return type. */
2894 return substr (ansi_header, "...") != 0;
2896 #else /* !defined (UNPROTOIZE) */
2898 /* See if we have a varargs function, or a function which has varargs style
2899 parameters or a varargs style return type. */
2901 const char *p;
2902 int len = strlen (varargs_style_indicator);
2904 for (p = ansi_header; p; )
2906 const char *candidate;
2908 if ((candidate = substr (p, varargs_style_indicator)) == 0)
2909 return 0;
2910 else
2911 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
2912 return 1;
2913 else
2914 p = candidate + 1;
2916 return 0;
2917 #endif /* !defined (UNPROTOIZE) */
2920 /* Do the editing operation specifically for a function "declaration". Note
2921 that editing for function "definitions" are handled in a separate routine
2922 below. */
2924 static void
2925 edit_fn_declaration (def_dec_p, clean_text_p)
2926 const def_dec_info *def_dec_p;
2927 const char *volatile clean_text_p;
2929 const char *start_formals;
2930 const char *end_formals;
2931 const char *function_to_edit = def_dec_p->hash_entry->symbol;
2932 size_t func_name_len = strlen (function_to_edit);
2933 const char *end_of_fn_name;
2935 #ifndef UNPROTOIZE
2937 const f_list_chain_item *this_f_list_chain_item;
2938 const def_dec_info *definition = def_dec_p->definition;
2940 /* If we are protoizing, and if we found no corresponding definition for
2941 this particular function declaration, then just leave this declaration
2942 exactly as it is. */
2944 if (!definition)
2945 return;
2947 /* If we are protoizing, and if the corresponding definition that we found
2948 for this particular function declaration defined an old style varargs
2949 function, then we want to issue a warning and just leave this function
2950 declaration unconverted. */
2952 if (other_variable_style_function (definition->ansi_decl))
2954 if (!quiet_flag)
2955 notice ("%s: %d: warning: varargs function declaration not converted\n",
2956 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
2957 def_dec_p->line);
2958 return;
2961 #endif /* !defined (UNPROTOIZE) */
2963 /* Setup here to recover from confusing source code detected during this
2964 particular "edit". */
2966 save_pointers ();
2967 if (setjmp (source_confusion_recovery))
2969 restore_pointers ();
2970 notice ("%s: declaration of function `%s' not converted\n",
2971 pname, function_to_edit);
2972 return;
2975 /* We are editing a function declaration. The line number we did a seek to
2976 contains the comma or semicolon which follows the declaration. Our job
2977 now is to scan backwards looking for the function name. This name *must*
2978 be followed by open paren (ignoring whitespace, of course). We need to
2979 replace everything between that open paren and the corresponding closing
2980 paren. If we are protoizing, we need to insert the prototype-style
2981 formals lists. If we are unprotoizing, we need to just delete everything
2982 between the pairs of opening and closing parens. */
2984 /* First move up to the end of the line. */
2986 while (*clean_text_p != '\n')
2987 check_source (++clean_text_p < clean_text_limit, 0);
2988 clean_text_p--; /* Point to just before the newline character. */
2990 /* Now we can scan backwards for the function name. */
2994 for (;;)
2996 /* Scan leftwards until we find some character which can be
2997 part of an identifier. */
2999 while (!is_id_char (*clean_text_p))
3000 check_source (--clean_text_p > clean_read_ptr, 0);
3002 /* Scan backwards until we find a char that cannot be part of an
3003 identifier. */
3005 while (is_id_char (*clean_text_p))
3006 check_source (--clean_text_p > clean_read_ptr, 0);
3008 /* Having found an "id break", see if the following id is the one
3009 that we are looking for. If so, then exit from this loop. */
3011 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
3013 char ch = *(clean_text_p + 1 + func_name_len);
3015 /* Must also check to see that the name in the source text
3016 ends where it should (in order to prevent bogus matches
3017 on similar but longer identifiers. */
3019 if (! is_id_char (ch))
3020 break; /* exit from loop */
3024 /* We have now found the first perfect match for the function name in
3025 our backward search. This may or may not be the actual function
3026 name at the start of the actual function declaration (i.e. we could
3027 have easily been mislead). We will try to avoid getting fooled too
3028 often by looking forward for the open paren which should follow the
3029 identifier we just found. We ignore whitespace while hunting. If
3030 the next non-whitespace byte we see is *not* an open left paren,
3031 then we must assume that we have been fooled and we start over
3032 again accordingly. Note that there is no guarantee, that even if
3033 we do see the open paren, that we are in the right place.
3034 Programmers do the strangest things sometimes! */
3036 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
3037 start_formals = forward_to_next_token_char (end_of_fn_name);
3039 while (*start_formals != '(');
3041 /* start_of_formals now points to the opening left paren which immediately
3042 follows the name of the function. */
3044 /* Note that there may be several formals lists which need to be modified
3045 due to the possibility that the return type of this function is a
3046 pointer-to-function type. If there are several formals lists, we
3047 convert them in left-to-right order here. */
3049 #ifndef UNPROTOIZE
3050 this_f_list_chain_item = definition->f_list_chain;
3051 #endif /* !defined (UNPROTOIZE) */
3053 for (;;)
3056 int depth;
3058 end_formals = start_formals + 1;
3059 depth = 1;
3060 for (; depth; check_source (++end_formals < clean_text_limit, 0))
3062 switch (*end_formals)
3064 case '(':
3065 depth++;
3066 break;
3067 case ')':
3068 depth--;
3069 break;
3072 end_formals--;
3075 /* end_formals now points to the closing right paren of the formals
3076 list whose left paren is pointed to by start_formals. */
3078 /* Now, if we are protoizing, we insert the new ANSI-style formals list
3079 attached to the associated definition of this function. If however
3080 we are unprotoizing, then we simply delete any formals list which
3081 may be present. */
3083 output_up_to (start_formals);
3084 #ifndef UNPROTOIZE
3085 if (this_f_list_chain_item)
3087 output_string (this_f_list_chain_item->formals_list);
3088 this_f_list_chain_item = this_f_list_chain_item->chain_next;
3090 else
3092 if (!quiet_flag)
3093 notice ("%s: warning: too many parameter lists in declaration of `%s'\n",
3094 pname, def_dec_p->hash_entry->symbol);
3095 check_source (0, end_formals); /* leave the declaration intact */
3097 #endif /* !defined (UNPROTOIZE) */
3098 clean_read_ptr = end_formals - 1;
3100 /* Now see if it looks like there may be another formals list associated
3101 with the function declaration that we are converting (following the
3102 formals list that we just converted. */
3105 const char *another_r_paren = forward_to_next_token_char (end_formals);
3107 if ((*another_r_paren != ')')
3108 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3110 #ifndef UNPROTOIZE
3111 if (this_f_list_chain_item)
3113 if (!quiet_flag)
3114 notice ("\n%s: warning: too few parameter lists in declaration of `%s'\n",
3115 pname, def_dec_p->hash_entry->symbol);
3116 check_source (0, start_formals); /* leave the decl intact */
3118 #endif /* !defined (UNPROTOIZE) */
3119 break;
3124 /* There does appear to be yet another formals list, so loop around
3125 again, and convert it also. */
3129 /* Edit a whole group of formals lists, starting with the rightmost one
3130 from some set of formals lists. This routine is called once (from the
3131 outside) for each function declaration which is converted. It is
3132 recursive however, and it calls itself once for each remaining formal
3133 list that lies to the left of the one it was originally called to work
3134 on. Thus, a whole set gets done in right-to-left order.
3136 This routine returns non-zero if it thinks that it should not be trying
3137 to convert this particular function definition (because the name of the
3138 function doesn't match the one expected). */
3140 static int
3141 edit_formals_lists (end_formals, f_list_count, def_dec_p)
3142 const char *end_formals;
3143 unsigned int f_list_count;
3144 const def_dec_info *def_dec_p;
3146 const char *start_formals;
3147 int depth;
3149 start_formals = end_formals - 1;
3150 depth = 1;
3151 for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3153 switch (*start_formals)
3155 case '(':
3156 depth--;
3157 break;
3158 case ')':
3159 depth++;
3160 break;
3163 start_formals++;
3165 /* start_formals now points to the opening left paren of the formals list. */
3167 f_list_count--;
3169 if (f_list_count)
3171 const char *next_end;
3173 /* There should be more formal lists to the left of here. */
3175 next_end = start_formals - 1;
3176 check_source (next_end > clean_read_ptr, 0);
3177 while (ISSPACE ((const unsigned char)*next_end))
3178 check_source (--next_end > clean_read_ptr, 0);
3179 check_source (*next_end == ')', next_end);
3180 check_source (--next_end > clean_read_ptr, 0);
3181 check_source (*next_end == ')', next_end);
3182 if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3183 return 1;
3186 /* Check that the function name in the header we are working on is the same
3187 as the one we would expect to find. If not, issue a warning and return
3188 non-zero. */
3190 if (f_list_count == 0)
3192 const char *expected = def_dec_p->hash_entry->symbol;
3193 const char *func_name_start;
3194 const char *func_name_limit;
3195 size_t func_name_len;
3197 for (func_name_limit = start_formals-1;
3198 ISSPACE ((const unsigned char)*func_name_limit); )
3199 check_source (--func_name_limit > clean_read_ptr, 0);
3201 for (func_name_start = func_name_limit++;
3202 is_id_char (*func_name_start);
3203 func_name_start--)
3204 check_source (func_name_start > clean_read_ptr, 0);
3205 func_name_start++;
3206 func_name_len = func_name_limit - func_name_start;
3207 if (func_name_len == 0)
3208 check_source (0, func_name_start);
3209 if (func_name_len != strlen (expected)
3210 || strncmp (func_name_start, expected, func_name_len))
3212 notice ("%s: %d: warning: found `%s' but expected `%s'\n",
3213 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3214 identify_lineno (func_name_start),
3215 dupnstr (func_name_start, func_name_len),
3216 expected);
3217 return 1;
3221 output_up_to (start_formals);
3223 #ifdef UNPROTOIZE
3224 if (f_list_count == 0)
3225 output_string (def_dec_p->formal_names);
3226 #else /* !defined (UNPROTOIZE) */
3228 unsigned f_list_depth;
3229 const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3231 /* At this point, the current value of f_list count says how many
3232 links we have to follow through the f_list_chain to get to the
3233 particular formals list that we need to output next. */
3235 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3236 flci_p = flci_p->chain_next;
3237 output_string (flci_p->formals_list);
3239 #endif /* !defined (UNPROTOIZE) */
3241 clean_read_ptr = end_formals - 1;
3242 return 0;
3245 /* Given a pointer to a byte in the clean text buffer which points to
3246 the beginning of a line that contains a "follower" token for a
3247 function definition header, do whatever is necessary to find the
3248 right closing paren for the rightmost formals list of the function
3249 definition header. */
3251 static const char *
3252 find_rightmost_formals_list (clean_text_p)
3253 const char *clean_text_p;
3255 const char *end_formals;
3257 /* We are editing a function definition. The line number we did a seek
3258 to contains the first token which immediately follows the entire set of
3259 formals lists which are part of this particular function definition
3260 header.
3262 Our job now is to scan leftwards in the clean text looking for the
3263 right-paren which is at the end of the function header's rightmost
3264 formals list.
3266 If we ignore whitespace, this right paren should be the first one we
3267 see which is (ignoring whitespace) immediately followed either by the
3268 open curly-brace beginning the function body or by an alphabetic
3269 character (in the case where the function definition is in old (K&R)
3270 style and there are some declarations of formal parameters). */
3272 /* It is possible that the right paren we are looking for is on the
3273 current line (together with its following token). Just in case that
3274 might be true, we start out here by skipping down to the right end of
3275 the current line before starting our scan. */
3277 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3278 continue;
3279 end_formals--;
3281 #ifdef UNPROTOIZE
3283 /* Now scan backwards while looking for the right end of the rightmost
3284 formals list associated with this function definition. */
3287 char ch;
3288 const char *l_brace_p;
3290 /* Look leftward and try to find a right-paren. */
3292 while (*end_formals != ')')
3294 if (ISSPACE ((unsigned char)*end_formals))
3295 while (ISSPACE ((unsigned char)*end_formals))
3296 check_source (--end_formals > clean_read_ptr, 0);
3297 else
3298 check_source (--end_formals > clean_read_ptr, 0);
3301 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3302 /* Since we are unprotoizing an ANSI-style (prototyped) function
3303 definition, there had better not be anything (except whitespace)
3304 between the end of the ANSI formals list and the beginning of the
3305 function body (i.e. the '{'). */
3307 check_source (ch == '{', l_brace_p);
3310 #else /* !defined (UNPROTOIZE) */
3312 /* Now scan backwards while looking for the right end of the rightmost
3313 formals list associated with this function definition. */
3315 while (1)
3317 char ch;
3318 const char *l_brace_p;
3320 /* Look leftward and try to find a right-paren. */
3322 while (*end_formals != ')')
3324 if (ISSPACE ((const unsigned char)*end_formals))
3325 while (ISSPACE ((const unsigned char)*end_formals))
3326 check_source (--end_formals > clean_read_ptr, 0);
3327 else
3328 check_source (--end_formals > clean_read_ptr, 0);
3331 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3333 /* Since it is possible that we found a right paren before the starting
3334 '{' of the body which IS NOT the one at the end of the real K&R
3335 formals list (say for instance, we found one embedded inside one of
3336 the old K&R formal parameter declarations) we have to check to be
3337 sure that this is in fact the right paren that we were looking for.
3339 The one we were looking for *must* be followed by either a '{' or
3340 by an alphabetic character, while others *cannot* validly be followed
3341 by such characters. */
3343 if ((ch == '{') || ISALPHA ((unsigned char)ch))
3344 break;
3346 /* At this point, we have found a right paren, but we know that it is
3347 not the one we were looking for, so backup one character and keep
3348 looking. */
3350 check_source (--end_formals > clean_read_ptr, 0);
3353 #endif /* !defined (UNPROTOIZE) */
3355 return end_formals;
3358 #ifndef UNPROTOIZE
3360 /* Insert into the output file a totally new declaration for a function
3361 which (up until now) was being called from within the current block
3362 without having been declared at any point such that the declaration
3363 was visible (i.e. in scope) at the point of the call.
3365 We need to add in explicit declarations for all such function calls
3366 in order to get the full benefit of prototype-based function call
3367 parameter type checking. */
3369 static void
3370 add_local_decl (def_dec_p, clean_text_p)
3371 const def_dec_info *def_dec_p;
3372 const char *clean_text_p;
3374 const char *start_of_block;
3375 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3377 /* Don't insert new local explicit declarations unless explicitly requested
3378 to do so. */
3380 if (!local_flag)
3381 return;
3383 /* Setup here to recover from confusing source code detected during this
3384 particular "edit". */
3386 save_pointers ();
3387 if (setjmp (source_confusion_recovery))
3389 restore_pointers ();
3390 notice ("%s: local declaration for function `%s' not inserted\n",
3391 pname, function_to_edit);
3392 return;
3395 /* We have already done a seek to the start of the line which should
3396 contain *the* open curly brace which begins the block in which we need
3397 to insert an explicit function declaration (to replace the implicit one).
3399 Now we scan that line, starting from the left, until we find the
3400 open curly brace we are looking for. Note that there may actually be
3401 multiple open curly braces on the given line, but we will be happy
3402 with the leftmost one no matter what. */
3404 start_of_block = clean_text_p;
3405 while (*start_of_block != '{' && *start_of_block != '\n')
3406 check_source (++start_of_block < clean_text_limit, 0);
3408 /* Note that the line from the original source could possibly
3409 contain *no* open curly braces! This happens if the line contains
3410 a macro call which expands into a chunk of text which includes a
3411 block (and that block's associated open and close curly braces).
3412 In cases like this, we give up, issue a warning, and do nothing. */
3414 if (*start_of_block != '{')
3416 if (!quiet_flag)
3417 notice ("\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
3418 def_dec_p->file->hash_entry->symbol, def_dec_p->line,
3419 def_dec_p->hash_entry->symbol);
3420 return;
3423 /* Figure out what a nice (pretty) indentation would be for the new
3424 declaration we are adding. In order to do this, we must scan forward
3425 from the '{' until we find the first line which starts with some
3426 non-whitespace characters (i.e. real "token" material). */
3429 const char *ep = forward_to_next_token_char (start_of_block) - 1;
3430 const char *sp;
3432 /* Now we have ep pointing at the rightmost byte of some existing indent
3433 stuff. At least that is the hope.
3435 We can now just scan backwards and find the left end of the existing
3436 indentation string, and then copy it to the output buffer. */
3438 for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--)
3439 continue;
3441 /* Now write out the open { which began this block, and any following
3442 trash up to and including the last byte of the existing indent that
3443 we just found. */
3445 output_up_to (ep);
3447 /* Now we go ahead and insert the new declaration at this point.
3449 If the definition of the given function is in the same file that we
3450 are currently editing, and if its full ANSI declaration normally
3451 would start with the keyword `extern', suppress the `extern'. */
3454 const char *decl = def_dec_p->definition->ansi_decl;
3456 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
3457 decl += 7;
3458 output_string (decl);
3461 /* Finally, write out a new indent string, just like the preceding one
3462 that we found. This will typically include a newline as the first
3463 character of the indent string. */
3465 output_bytes (sp, (size_t) (ep - sp) + 1);
3469 /* Given a pointer to a file_info record, and a pointer to the beginning
3470 of a line (in the clean text buffer) which is assumed to contain the
3471 first "follower" token for the first function definition header in the
3472 given file, find a good place to insert some new global function
3473 declarations (which will replace scattered and imprecise implicit ones)
3474 and then insert the new explicit declaration at that point in the file. */
3476 static void
3477 add_global_decls (file_p, clean_text_p)
3478 const file_info *file_p;
3479 const char *clean_text_p;
3481 const def_dec_info *dd_p;
3482 const char *scan_p;
3484 /* Setup here to recover from confusing source code detected during this
3485 particular "edit". */
3487 save_pointers ();
3488 if (setjmp (source_confusion_recovery))
3490 restore_pointers ();
3491 notice ("%s: global declarations for file `%s' not inserted\n",
3492 pname, shortpath (NULL, file_p->hash_entry->symbol));
3493 return;
3496 /* Start by finding a good location for adding the new explicit function
3497 declarations. To do this, we scan backwards, ignoring whitespace
3498 and comments and other junk until we find either a semicolon, or until
3499 we hit the beginning of the file. */
3501 scan_p = find_rightmost_formals_list (clean_text_p);
3502 for (;; --scan_p)
3504 if (scan_p < clean_text_base)
3505 break;
3506 check_source (scan_p > clean_read_ptr, 0);
3507 if (*scan_p == ';')
3508 break;
3511 /* scan_p now points either to a semicolon, or to just before the start
3512 of the whole file. */
3514 /* Now scan forward for the first non-whitespace character. In theory,
3515 this should be the first character of the following function definition
3516 header. We will put in the added declarations just prior to that. */
3518 scan_p++;
3519 while (ISSPACE ((const unsigned char)*scan_p))
3520 scan_p++;
3521 scan_p--;
3523 output_up_to (scan_p);
3525 /* Now write out full prototypes for all of the things that had been
3526 implicitly declared in this file (but only those for which we were
3527 actually able to find unique matching definitions). Avoid duplicates
3528 by marking things that we write out as we go. */
3531 int some_decls_added = 0;
3533 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3534 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
3536 const char *decl = dd_p->definition->ansi_decl;
3538 /* If the function for which we are inserting a declaration is
3539 actually defined later in the same file, then suppress the
3540 leading `extern' keyword (if there is one). */
3542 if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
3543 decl += 7;
3545 output_string ("\n");
3546 output_string (decl);
3547 some_decls_added = 1;
3548 ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
3550 if (some_decls_added)
3551 output_string ("\n\n");
3554 /* Unmark all of the definitions that we just marked. */
3556 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3557 if (dd_p->definition)
3558 ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
3561 #endif /* !defined (UNPROTOIZE) */
3563 /* Do the editing operation specifically for a function "definition". Note
3564 that editing operations for function "declarations" are handled by a
3565 separate routine above. */
3567 static void
3568 edit_fn_definition (def_dec_p, clean_text_p)
3569 const def_dec_info *def_dec_p;
3570 const char *clean_text_p;
3572 const char *end_formals;
3573 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3575 /* Setup here to recover from confusing source code detected during this
3576 particular "edit". */
3578 save_pointers ();
3579 if (setjmp (source_confusion_recovery))
3581 restore_pointers ();
3582 notice ("%s: definition of function `%s' not converted\n",
3583 pname, function_to_edit);
3584 return;
3587 end_formals = find_rightmost_formals_list (clean_text_p);
3589 /* end_of_formals now points to the closing right paren of the rightmost
3590 formals list which is actually part of the `header' of the function
3591 definition that we are converting. */
3593 /* If the header of this function definition looks like it declares a
3594 function with a variable number of arguments, and if the way it does
3595 that is different from that way we would like it (i.e. varargs vs.
3596 stdarg) then issue a warning and leave the header unconverted. */
3598 if (other_variable_style_function (def_dec_p->ansi_decl))
3600 if (!quiet_flag)
3601 notice ("%s: %d: warning: definition of %s not converted\n",
3602 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3603 identify_lineno (end_formals),
3604 other_var_style);
3605 output_up_to (end_formals);
3606 return;
3609 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
3611 restore_pointers ();
3612 notice ("%s: definition of function `%s' not converted\n",
3613 pname, function_to_edit);
3614 return;
3617 /* Have to output the last right paren because this never gets flushed by
3618 edit_formals_list. */
3620 output_up_to (end_formals);
3622 #ifdef UNPROTOIZE
3624 const char *decl_p;
3625 const char *semicolon_p;
3626 const char *limit_p;
3627 const char *scan_p;
3628 int had_newlines = 0;
3630 /* Now write out the K&R style formal declarations, one per line. */
3632 decl_p = def_dec_p->formal_decls;
3633 limit_p = decl_p + strlen (decl_p);
3634 for (;decl_p < limit_p; decl_p = semicolon_p + 2)
3636 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
3637 continue;
3638 output_string ("\n");
3639 output_string (indent_string);
3640 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
3643 /* If there are no newlines between the end of the formals list and the
3644 start of the body, we should insert one now. */
3646 for (scan_p = end_formals+1; *scan_p != '{'; )
3648 if (*scan_p == '\n')
3650 had_newlines = 1;
3651 break;
3653 check_source (++scan_p < clean_text_limit, 0);
3655 if (!had_newlines)
3656 output_string ("\n");
3658 #else /* !defined (UNPROTOIZE) */
3659 /* If we are protoizing, there may be some flotsam & jetsam (like comments
3660 and preprocessing directives) after the old formals list but before
3661 the following { and we would like to preserve that stuff while effectively
3662 deleting the existing K&R formal parameter declarations. We do so here
3663 in a rather tricky way. Basically, we white out any stuff *except*
3664 the comments/pp-directives in the original text buffer, then, if there
3665 is anything in this area *other* than whitespace, we output it. */
3667 const char *end_formals_orig;
3668 const char *start_body;
3669 const char *start_body_orig;
3670 const char *scan;
3671 const char *scan_orig;
3672 int have_flotsam = 0;
3673 int have_newlines = 0;
3675 for (start_body = end_formals + 1; *start_body != '{';)
3676 check_source (++start_body < clean_text_limit, 0);
3678 end_formals_orig = orig_text_base + (end_formals - clean_text_base);
3679 start_body_orig = orig_text_base + (start_body - clean_text_base);
3680 scan = end_formals + 1;
3681 scan_orig = end_formals_orig + 1;
3682 for (; scan < start_body; scan++, scan_orig++)
3684 if (*scan == *scan_orig)
3686 have_newlines |= (*scan_orig == '\n');
3687 /* Leave identical whitespace alone. */
3688 if (!ISSPACE ((const unsigned char)*scan_orig))
3689 *((NONCONST char *)scan_orig) = ' '; /* identical - so whiteout */
3691 else
3692 have_flotsam = 1;
3694 if (have_flotsam)
3695 output_bytes (end_formals_orig + 1,
3696 (size_t) (start_body_orig - end_formals_orig) - 1);
3697 else
3698 if (have_newlines)
3699 output_string ("\n");
3700 else
3701 output_string (" ");
3702 clean_read_ptr = start_body - 1;
3704 #endif /* !defined (UNPROTOIZE) */
3707 /* Clean up the clean text buffer. Do this by converting comments and
3708 preprocessing directives into spaces. Also convert line continuations
3709 into whitespace. Also, whiteout string and character literals. */
3711 static void
3712 do_cleaning (new_clean_text_base, new_clean_text_limit)
3713 char *new_clean_text_base;
3714 const char *new_clean_text_limit;
3716 char *scan_p;
3717 int non_whitespace_since_newline = 0;
3719 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
3721 switch (*scan_p)
3723 case '/': /* Handle comments. */
3724 if (scan_p[1] != '*')
3725 goto regular;
3726 non_whitespace_since_newline = 1;
3727 scan_p[0] = ' ';
3728 scan_p[1] = ' ';
3729 scan_p += 2;
3730 while (scan_p[1] != '/' || scan_p[0] != '*')
3732 if (!ISSPACE ((const unsigned char)*scan_p))
3733 *scan_p = ' ';
3734 if (++scan_p >= new_clean_text_limit)
3735 abort ();
3737 *scan_p++ = ' ';
3738 *scan_p = ' ';
3739 break;
3741 case '#': /* Handle pp directives. */
3742 if (non_whitespace_since_newline)
3743 goto regular;
3744 *scan_p = ' ';
3745 while (scan_p[1] != '\n' || scan_p[0] == '\\')
3747 if (!ISSPACE ((const unsigned char)*scan_p))
3748 *scan_p = ' ';
3749 if (++scan_p >= new_clean_text_limit)
3750 abort ();
3752 *scan_p++ = ' ';
3753 break;
3755 case '\'': /* Handle character literals. */
3756 non_whitespace_since_newline = 1;
3757 while (scan_p[1] != '\'' || scan_p[0] == '\\')
3759 if (scan_p[0] == '\\'
3760 && !ISSPACE ((const unsigned char)scan_p[1]))
3761 scan_p[1] = ' ';
3762 if (!ISSPACE ((const unsigned char)*scan_p))
3763 *scan_p = ' ';
3764 if (++scan_p >= new_clean_text_limit)
3765 abort ();
3767 *scan_p++ = ' ';
3768 break;
3770 case '"': /* Handle string literals. */
3771 non_whitespace_since_newline = 1;
3772 while (scan_p[1] != '"' || scan_p[0] == '\\')
3774 if (scan_p[0] == '\\'
3775 && !ISSPACE ((const unsigned char)scan_p[1]))
3776 scan_p[1] = ' ';
3777 if (!ISSPACE ((const unsigned char)*scan_p))
3778 *scan_p = ' ';
3779 if (++scan_p >= new_clean_text_limit)
3780 abort ();
3782 if (!ISSPACE ((const unsigned char)*scan_p))
3783 *scan_p = ' ';
3784 scan_p++;
3785 break;
3787 case '\\': /* Handle line continuations. */
3788 if (scan_p[1] != '\n')
3789 goto regular;
3790 *scan_p = ' ';
3791 break;
3793 case '\n':
3794 non_whitespace_since_newline = 0; /* Reset. */
3795 break;
3797 case ' ':
3798 case '\v':
3799 case '\t':
3800 case '\r':
3801 case '\f':
3802 case '\b':
3803 break; /* Whitespace characters. */
3805 default:
3806 regular:
3807 non_whitespace_since_newline = 1;
3808 break;
3813 /* Given a pointer to the closing right parenthesis for a particular formals
3814 list (in the clean text buffer) find the corresponding left parenthesis
3815 and return a pointer to it. */
3817 static const char *
3818 careful_find_l_paren (p)
3819 const char *p;
3821 const char *q;
3822 int paren_depth;
3824 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
3826 switch (*q)
3828 case ')':
3829 paren_depth++;
3830 break;
3831 case '(':
3832 paren_depth--;
3833 break;
3836 return ++q;
3839 /* Scan the clean text buffer for cases of function definitions that we
3840 don't really know about because they were preprocessed out when the
3841 aux info files were created.
3843 In this version of protoize/unprotoize we just give a warning for each
3844 one found. A later version may be able to at least unprotoize such
3845 missed items.
3847 Note that we may easily find all function definitions simply by
3848 looking for places where there is a left paren which is (ignoring
3849 whitespace) immediately followed by either a left-brace or by an
3850 upper or lower case letter. Whenever we find this combination, we
3851 have also found a function definition header.
3853 Finding function *declarations* using syntactic clues is much harder.
3854 I will probably try to do this in a later version though. */
3856 static void
3857 scan_for_missed_items (file_p)
3858 const file_info *file_p;
3860 static const char *scan_p;
3861 const char *limit = clean_text_limit - 3;
3862 static const char *backup_limit;
3864 backup_limit = clean_text_base - 1;
3866 for (scan_p = clean_text_base; scan_p < limit; scan_p++)
3868 if (*scan_p == ')')
3870 static const char *last_r_paren;
3871 const char *ahead_p;
3873 last_r_paren = scan_p;
3875 for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
3876 check_source (++ahead_p < limit, limit);
3878 scan_p = ahead_p - 1;
3880 if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
3882 const char *last_l_paren;
3883 const int lineno = identify_lineno (ahead_p);
3885 if (setjmp (source_confusion_recovery))
3886 continue;
3888 /* We know we have a function definition header. Now skip
3889 leftwards over all of its associated formals lists. */
3893 last_l_paren = careful_find_l_paren (last_r_paren);
3894 for (last_r_paren = last_l_paren-1;
3895 ISSPACE ((const unsigned char)*last_r_paren); )
3896 check_source (--last_r_paren >= backup_limit, backup_limit);
3898 while (*last_r_paren == ')');
3900 if (is_id_char (*last_r_paren))
3902 const char *id_limit = last_r_paren + 1;
3903 const char *id_start;
3904 size_t id_length;
3905 const def_dec_info *dd_p;
3907 for (id_start = id_limit-1; is_id_char (*id_start); )
3908 check_source (--id_start >= backup_limit, backup_limit);
3909 id_start++;
3910 backup_limit = id_start;
3911 if ((id_length = (size_t) (id_limit - id_start)) == 0)
3912 goto not_missed;
3915 char *func_name = (char *) alloca (id_length + 1);
3916 static const char * const stmt_keywords[]
3917 = { "if", "else", "do", "while", "for", "switch", "case", "return", 0 };
3918 const char * const *stmt_keyword;
3920 strncpy (func_name, id_start, id_length);
3921 func_name[id_length] = '\0';
3923 /* We must check here to see if we are actually looking at
3924 a statement rather than an actual function call. */
3926 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
3927 if (!strcmp (func_name, *stmt_keyword))
3928 goto not_missed;
3930 #if 0
3931 notice ("%s: found definition of `%s' at %s(%d)\n",
3932 pname,
3933 func_name,
3934 shortpath (NULL, file_p->hash_entry->symbol),
3935 identify_lineno (id_start));
3936 #endif /* 0 */
3937 /* We really should check for a match of the function name
3938 here also, but why bother. */
3940 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3941 if (dd_p->is_func_def && dd_p->line == lineno)
3942 goto not_missed;
3944 /* If we make it here, then we did not know about this
3945 function definition. */
3947 notice ("%s: %d: warning: `%s' excluded by preprocessing\n",
3948 shortpath (NULL, file_p->hash_entry->symbol),
3949 identify_lineno (id_start), func_name);
3950 notice ("%s: function definition not converted\n",
3951 pname);
3953 not_missed: ;
3960 /* Do all editing operations for a single source file (either a "base" file
3961 or an "include" file). To do this we read the file into memory, keep a
3962 virgin copy there, make another cleaned in-core copy of the original file
3963 (i.e. one in which all of the comments and preprocessing directives have
3964 been replaced with whitespace), then use these two in-core copies of the
3965 file to make a new edited in-core copy of the file. Finally, rename the
3966 original file (as a way of saving it), and then write the edited version
3967 of the file from core to a disk file of the same name as the original.
3969 Note that the trick of making a copy of the original sans comments &
3970 preprocessing directives make the editing a whole lot easier. */
3972 static void
3973 edit_file (hp)
3974 const hash_table_entry *hp;
3976 struct stat stat_buf;
3977 const file_info *file_p = hp->fip;
3978 char *new_orig_text_base;
3979 char *new_orig_text_limit;
3980 char *new_clean_text_base;
3981 char *new_clean_text_limit;
3982 size_t orig_size;
3983 size_t repl_size;
3984 int first_definition_in_file;
3986 /* If we are not supposed to be converting this file, or if there is
3987 nothing in there which needs converting, just skip this file. */
3989 if (!needs_to_be_converted (file_p))
3990 return;
3992 convert_filename = file_p->hash_entry->symbol;
3994 /* Convert a file if it is in a directory where we want conversion
3995 and the file is not excluded. */
3997 if (!directory_specified_p (convert_filename)
3998 || file_excluded_p (convert_filename))
4000 if (!quiet_flag
4001 #ifdef UNPROTOIZE
4002 /* Don't even mention "system" include files unless we are
4003 protoizing. If we are protoizing, we mention these as a
4004 gentle way of prodding the user to convert his "system"
4005 include files to prototype format. */
4006 && !in_system_include_dir (convert_filename)
4007 #endif /* defined (UNPROTOIZE) */
4009 notice ("%s: `%s' not converted\n",
4010 pname, shortpath (NULL, convert_filename));
4011 return;
4014 /* Let the user know what we are up to. */
4016 if (nochange_flag)
4017 notice ("%s: would convert file `%s'\n",
4018 pname, shortpath (NULL, convert_filename));
4019 else
4020 notice ("%s: converting file `%s'\n",
4021 pname, shortpath (NULL, convert_filename));
4022 fflush (stderr);
4024 /* Find out the size (in bytes) of the original file. */
4026 /* The cast avoids an erroneous warning on AIX. */
4027 if (stat (convert_filename, &stat_buf) == -1)
4029 int errno_val = errno;
4030 notice ("%s: can't get status for file `%s': %s\n",
4031 pname, shortpath (NULL, convert_filename),
4032 xstrerror (errno_val));
4033 return;
4035 orig_size = stat_buf.st_size;
4037 /* Allocate a buffer to hold the original text. */
4039 orig_text_base = new_orig_text_base = (char *) xmalloc (orig_size + 2);
4040 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
4042 /* Allocate a buffer to hold the cleaned-up version of the original text. */
4044 clean_text_base = new_clean_text_base = (char *) xmalloc (orig_size + 2);
4045 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
4046 clean_read_ptr = clean_text_base - 1;
4048 /* Allocate a buffer that will hopefully be large enough to hold the entire
4049 converted output text. As an initial guess for the maximum size of the
4050 output buffer, use 125% of the size of the original + some extra. This
4051 buffer can be expanded later as needed. */
4053 repl_size = orig_size + (orig_size >> 2) + 4096;
4054 repl_text_base = (char *) xmalloc (repl_size + 2);
4055 repl_text_limit = repl_text_base + repl_size - 1;
4056 repl_write_ptr = repl_text_base - 1;
4059 int input_file;
4061 /* Open the file to be converted in READ ONLY mode. */
4063 if ((input_file = open (convert_filename, O_RDONLY, 0444)) == -1)
4065 int errno_val = errno;
4066 notice ("%s: can't open file `%s' for reading: %s\n",
4067 pname, shortpath (NULL, convert_filename),
4068 xstrerror (errno_val));
4069 return;
4072 /* Read the entire original source text file into the original text buffer
4073 in one swell fwoop. Then figure out where the end of the text is and
4074 make sure that it ends with a newline followed by a null. */
4076 if (safe_read (input_file, new_orig_text_base, orig_size) !=
4077 (int) orig_size)
4079 int errno_val = errno;
4080 close (input_file);
4081 notice ("\n%s: error reading input file `%s': %s\n",
4082 pname, shortpath (NULL, convert_filename),
4083 xstrerror (errno_val));
4084 return;
4087 close (input_file);
4090 if (orig_size == 0 || orig_text_limit[-1] != '\n')
4092 *new_orig_text_limit++ = '\n';
4093 orig_text_limit++;
4096 /* Create the cleaned up copy of the original text. */
4098 memcpy (new_clean_text_base, orig_text_base,
4099 (size_t) (orig_text_limit - orig_text_base));
4100 do_cleaning (new_clean_text_base, new_clean_text_limit);
4102 #if 0
4104 int clean_file;
4105 size_t clean_size = orig_text_limit - orig_text_base;
4106 char *const clean_filename = (char *) alloca (strlen (convert_filename) + 6 + 1);
4108 /* Open (and create) the clean file. */
4110 strcpy (clean_filename, convert_filename);
4111 strcat (clean_filename, ".clean");
4112 if ((clean_file = creat (clean_filename, 0666)) == -1)
4114 int errno_val = errno;
4115 notice ("%s: can't create/open clean file `%s': %s\n",
4116 pname, shortpath (NULL, clean_filename),
4117 xstrerror (errno_val));
4118 return;
4121 /* Write the clean file. */
4123 safe_write (clean_file, new_clean_text_base, clean_size, clean_filename);
4125 close (clean_file);
4127 #endif /* 0 */
4129 /* Do a simplified scan of the input looking for things that were not
4130 mentioned in the aux info files because of the fact that they were
4131 in a region of the source which was preprocessed-out (via #if or
4132 via #ifdef). */
4134 scan_for_missed_items (file_p);
4136 /* Setup to do line-oriented forward seeking in the clean text buffer. */
4138 last_known_line_number = 1;
4139 last_known_line_start = clean_text_base;
4141 /* Now get down to business and make all of the necessary edits. */
4144 const def_dec_info *def_dec_p;
4146 first_definition_in_file = 1;
4147 def_dec_p = file_p->defs_decs;
4148 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
4150 const char *clean_text_p = seek_to_line (def_dec_p->line);
4152 /* clean_text_p now points to the first character of the line which
4153 contains the `terminator' for the declaration or definition that
4154 we are about to process. */
4156 #ifndef UNPROTOIZE
4158 if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
4160 add_global_decls (def_dec_p->file, clean_text_p);
4161 first_definition_in_file = 0;
4164 /* Don't edit this item if it is already in prototype format or if it
4165 is a function declaration and we have found no corresponding
4166 definition. */
4168 if (def_dec_p->prototyped
4169 || (!def_dec_p->is_func_def && !def_dec_p->definition))
4170 continue;
4172 #endif /* !defined (UNPROTOIZE) */
4174 if (def_dec_p->is_func_def)
4175 edit_fn_definition (def_dec_p, clean_text_p);
4176 else
4177 #ifndef UNPROTOIZE
4178 if (def_dec_p->is_implicit)
4179 add_local_decl (def_dec_p, clean_text_p);
4180 else
4181 #endif /* !defined (UNPROTOIZE) */
4182 edit_fn_declaration (def_dec_p, clean_text_p);
4186 /* Finalize things. Output the last trailing part of the original text. */
4188 output_up_to (clean_text_limit - 1);
4190 /* If this is just a test run, stop now and just deallocate the buffers. */
4192 if (nochange_flag)
4194 free (new_orig_text_base);
4195 free (new_clean_text_base);
4196 free (repl_text_base);
4197 return;
4200 /* Change the name of the original input file. This is just a quick way of
4201 saving the original file. */
4203 if (!nosave_flag)
4205 char *new_filename
4206 = (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
4208 strcpy (new_filename, convert_filename);
4209 strcat (new_filename, save_suffix);
4210 if (link (convert_filename, new_filename) == -1)
4212 int errno_val = errno;
4213 if (errno_val == EEXIST)
4215 if (!quiet_flag)
4216 notice ("%s: warning: file `%s' already saved in `%s'\n",
4217 pname,
4218 shortpath (NULL, convert_filename),
4219 shortpath (NULL, new_filename));
4221 else
4223 notice ("%s: can't link file `%s' to `%s': %s\n",
4224 pname,
4225 shortpath (NULL, convert_filename),
4226 shortpath (NULL, new_filename),
4227 xstrerror (errno_val));
4228 return;
4233 if (unlink (convert_filename) == -1)
4235 int errno_val = errno;
4236 notice ("%s: can't delete file `%s': %s\n",
4237 pname, shortpath (NULL, convert_filename),
4238 xstrerror (errno_val));
4239 return;
4243 int output_file;
4245 /* Open (and create) the output file. */
4247 if ((output_file = creat (convert_filename, 0666)) == -1)
4249 int errno_val = errno;
4250 notice ("%s: can't create/open output file `%s': %s\n",
4251 pname, shortpath (NULL, convert_filename),
4252 xstrerror (errno_val));
4253 return;
4256 /* Write the output file. */
4259 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
4261 safe_write (output_file, repl_text_base, out_size, convert_filename);
4264 close (output_file);
4267 /* Deallocate the conversion buffers. */
4269 free (new_orig_text_base);
4270 free (new_clean_text_base);
4271 free (repl_text_base);
4273 /* Change the mode of the output file to match the original file. */
4275 /* The cast avoids an erroneous warning on AIX. */
4276 if (chmod (convert_filename, stat_buf.st_mode) == -1)
4278 int errno_val = errno;
4279 notice ("%s: can't change mode of file `%s': %s\n",
4280 pname, shortpath (NULL, convert_filename),
4281 xstrerror (errno_val));
4284 /* Note: We would try to change the owner and group of the output file
4285 to match those of the input file here, except that may not be a good
4286 thing to do because it might be misleading. Also, it might not even
4287 be possible to do that (on BSD systems with quotas for instance). */
4290 /* Do all of the individual steps needed to do the protoization (or
4291 unprotoization) of the files referenced in the aux_info files given
4292 in the command line. */
4294 static void
4295 do_processing ()
4297 const char * const *base_pp;
4298 const char * const * const end_pps
4299 = &base_source_filenames[n_base_source_files];
4301 #ifndef UNPROTOIZE
4302 int syscalls_len;
4303 #endif /* !defined (UNPROTOIZE) */
4305 /* One-by-one, check (and create if necessary), open, and read all of the
4306 stuff in each aux_info file. After reading each aux_info file, the
4307 aux_info_file just read will be automatically deleted unless the
4308 keep_flag is set. */
4310 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
4311 process_aux_info_file (*base_pp, keep_flag, 0);
4313 #ifndef UNPROTOIZE
4315 /* Also open and read the special SYSCALLS.c aux_info file which gives us
4316 the prototypes for all of the standard system-supplied functions. */
4318 if (nondefault_syscalls_dir)
4320 syscalls_absolute_filename
4321 = (char *) xmalloc (strlen (nondefault_syscalls_dir) + 1
4322 + sizeof (syscalls_filename));
4323 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
4325 else
4327 GET_ENV_PATH_LIST (default_syscalls_dir, "GCC_EXEC_PREFIX");
4328 if (!default_syscalls_dir)
4330 default_syscalls_dir = standard_exec_prefix;
4332 syscalls_absolute_filename
4333 = (char *) xmalloc (strlen (default_syscalls_dir) + 0
4334 + strlen (target_machine) + 1
4335 + strlen (target_version) + 1
4336 + sizeof (syscalls_filename));
4337 strcpy (syscalls_absolute_filename, default_syscalls_dir);
4338 strcat (syscalls_absolute_filename, target_machine);
4339 strcat (syscalls_absolute_filename, "/");
4340 strcat (syscalls_absolute_filename, target_version);
4341 strcat (syscalls_absolute_filename, "/");
4344 syscalls_len = strlen (syscalls_absolute_filename);
4345 if (*(syscalls_absolute_filename + syscalls_len - 1) != '/')
4347 *(syscalls_absolute_filename + syscalls_len++) = '/';
4348 *(syscalls_absolute_filename + syscalls_len) = '\0';
4350 strcat (syscalls_absolute_filename, syscalls_filename);
4352 /* Call process_aux_info_file in such a way that it does not try to
4353 delete the SYSCALLS aux_info file. */
4355 process_aux_info_file (syscalls_absolute_filename, 1, 1);
4357 #endif /* !defined (UNPROTOIZE) */
4359 /* When we first read in all of the information from the aux_info files
4360 we saved in it descending line number order, because that was likely to
4361 be faster. Now however, we want the chains of def & dec records to
4362 appear in ascending line number order as we get further away from the
4363 file_info record that they hang from. The following line causes all of
4364 these lists to be rearranged into ascending line number order. */
4366 visit_each_hash_node (filename_primary, reverse_def_dec_list);
4368 #ifndef UNPROTOIZE
4370 /* Now do the "real" work. The following line causes each declaration record
4371 to be "visited". For each of these nodes, an attempt is made to match
4372 up the function declaration with a corresponding function definition,
4373 which should have a full prototype-format formals list with it. Once
4374 these match-ups are made, the conversion of the function declarations
4375 to prototype format can be made. */
4377 visit_each_hash_node (function_name_primary, connect_defs_and_decs);
4379 #endif /* !defined (UNPROTOIZE) */
4381 /* Now convert each file that can be converted (and needs to be). */
4383 visit_each_hash_node (filename_primary, edit_file);
4385 #ifndef UNPROTOIZE
4387 /* If we are working in cplusplus mode, try to rename all .c files to .C
4388 files. Don't panic if some of the renames don't work. */
4390 if (cplusplus_flag && !nochange_flag)
4391 visit_each_hash_node (filename_primary, rename_c_file);
4393 #endif /* !defined (UNPROTOIZE) */
4396 static struct option longopts[] =
4398 {"version", 0, 0, 'V'},
4399 {"file_name", 0, 0, 'p'},
4400 {"quiet", 0, 0, 'q'},
4401 {"silent", 0, 0, 'q'},
4402 {"force", 0, 0, 'f'},
4403 {"keep", 0, 0, 'k'},
4404 {"nosave", 0, 0, 'N'},
4405 {"nochange", 0, 0, 'n'},
4406 {"compiler-options", 1, 0, 'c'},
4407 {"exclude", 1, 0, 'x'},
4408 {"directory", 1, 0, 'd'},
4409 #ifdef UNPROTOIZE
4410 {"indent", 1, 0, 'i'},
4411 #else
4412 {"local", 0, 0, 'l'},
4413 {"global", 0, 0, 'g'},
4414 {"c++", 0, 0, 'C'},
4415 {"syscalls-dir", 1, 0, 'B'},
4416 #endif
4417 {0, 0, 0, 0}
4420 extern int main PARAMS ((int, char **const));
4423 main (argc, argv)
4424 int argc;
4425 char **const argv;
4427 int longind;
4428 int c;
4429 const char *params = "";
4431 pname = strrchr (argv[0], '/');
4432 pname = pname ? pname+1 : argv[0];
4434 #ifdef HAVE_LC_MESSAGES
4435 setlocale (LC_MESSAGES, "");
4436 #endif
4437 (void) bindtextdomain (PACKAGE, localedir);
4438 (void) textdomain (PACKAGE);
4440 cwd_buffer = getpwd ();
4441 if (!cwd_buffer)
4443 notice ("%s: cannot get working directory: %s\n",
4444 pname, xstrerror(errno));
4445 return (FATAL_EXIT_CODE);
4448 /* By default, convert the files in the current directory. */
4449 directory_list = string_list_cons (cwd_buffer, NULL);
4451 while ((c = getopt_long (argc, argv,
4452 #ifdef UNPROTOIZE
4453 "c:d:i:knNp:qvVx:",
4454 #else
4455 "B:c:Cd:gklnNp:qvVx:",
4456 #endif
4457 longopts, &longind)) != EOF)
4459 if (c == 0) /* Long option. */
4460 c = longopts[longind].val;
4461 switch (c)
4463 case 'p':
4464 compiler_file_name = optarg;
4465 break;
4466 case 'd':
4467 directory_list
4468 = string_list_cons (abspath (NULL, optarg), directory_list);
4469 break;
4470 case 'x':
4471 exclude_list = string_list_cons (optarg, exclude_list);
4472 break;
4474 case 'v':
4475 case 'V':
4476 version_flag = 1;
4477 break;
4478 case 'q':
4479 quiet_flag = 1;
4480 break;
4481 #if 0
4482 case 'f':
4483 force_flag = 1;
4484 break;
4485 #endif
4486 case 'n':
4487 nochange_flag = 1;
4488 keep_flag = 1;
4489 break;
4490 case 'N':
4491 nosave_flag = 1;
4492 break;
4493 case 'k':
4494 keep_flag = 1;
4495 break;
4496 case 'c':
4497 params = optarg;
4498 break;
4499 #ifdef UNPROTOIZE
4500 case 'i':
4501 indent_string = optarg;
4502 break;
4503 #else /* !defined (UNPROTOIZE) */
4504 case 'l':
4505 local_flag = 1;
4506 break;
4507 case 'g':
4508 global_flag = 1;
4509 break;
4510 case 'C':
4511 cplusplus_flag = 1;
4512 break;
4513 case 'B':
4514 nondefault_syscalls_dir = optarg;
4515 break;
4516 #endif /* !defined (UNPROTOIZE) */
4517 default:
4518 usage ();
4522 /* Set up compile_params based on -p and -c options. */
4523 munge_compile_params (params);
4525 n_base_source_files = argc - optind;
4527 /* Now actually make a list of the base source filenames. */
4529 base_source_filenames
4530 = (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *));
4531 n_base_source_files = 0;
4532 for (; optind < argc; optind++)
4534 const char *path = abspath (NULL, argv[optind]);
4535 int len = strlen (path);
4537 if (path[len-1] == 'c' && path[len-2] == '.')
4538 base_source_filenames[n_base_source_files++] = path;
4539 else
4541 notice ("%s: input file names must have .c suffixes: %s\n",
4542 pname, shortpath (NULL, path));
4543 errors++;
4547 #ifndef UNPROTOIZE
4548 /* We are only interested in the very first identifier token in the
4549 definition of `va_list', so if there is more junk after that first
4550 identifier token, delete it from the `varargs_style_indicator'. */
4552 const char *cp;
4554 for (cp = varargs_style_indicator;
4555 ISALNUM ((const unsigned char)*cp) || *cp == '_'; cp++)
4556 continue;
4557 if (*cp != 0)
4558 varargs_style_indicator = savestring (varargs_style_indicator,
4559 cp - varargs_style_indicator);
4561 #endif /* !defined (UNPROTOIZE) */
4563 if (errors)
4564 usage ();
4565 else
4567 if (version_flag)
4568 fprintf (stderr, "%s: %s\n", pname, version_string);
4569 do_processing ();
4572 return (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);