* rtl.h (global_rtx_index): New enum.
[official-gcc.git] / gcc / protoize.c
blob04aa7cfd5e982c98bc069ad4a9c231f66ba0e2ae
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 ptr += nchars;
621 left -= nchars;
623 return len - left;
626 /* Write LEN bytes at PTR to descriptor DESC,
627 retrying if necessary, and treating any real error as fatal. */
629 static void
630 safe_write (desc, ptr, len, out_fname)
631 int desc;
632 PTR ptr;
633 int len;
634 const char *out_fname;
636 while (len > 0) {
637 int written = write (desc, ptr, len);
638 if (written < 0)
640 int errno_val = errno;
641 #ifdef EINTR
642 if (errno_val == EINTR)
643 continue;
644 #endif
645 notice ("%s: error writing file `%s': %s\n",
646 pname, shortpath (NULL, out_fname), xstrerror (errno_val));
647 return;
649 ptr += written;
650 len -= written;
654 /* Get setup to recover in case the edit we are about to do goes awry. */
656 static void
657 save_pointers ()
659 saved_clean_read_ptr = clean_read_ptr;
660 saved_repl_write_ptr = repl_write_ptr;
663 /* Call this routine to recover our previous state whenever something looks
664 too confusing in the source code we are trying to edit. */
666 static void
667 restore_pointers ()
669 clean_read_ptr = saved_clean_read_ptr;
670 repl_write_ptr = saved_repl_write_ptr;
673 /* Return true if the given character is a valid identifier character. */
675 static int
676 is_id_char (ch)
677 int ch;
679 return (ISALNUM (ch) || (ch == '_') || (ch == '$'));
682 /* Give a message indicating the proper way to invoke this program and then
683 exit with non-zero status. */
685 static void
686 usage ()
688 #ifdef UNPROTOIZE
689 notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
690 pname, pname);
691 #else /* !defined (UNPROTOIZE) */
692 notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
693 pname, pname);
694 #endif /* !defined (UNPROTOIZE) */
695 exit (FATAL_EXIT_CODE);
698 /* Return true if the given filename (assumed to be an absolute filename)
699 designates a file residing anywhere beneath any one of the "system"
700 include directories. */
702 static int
703 in_system_include_dir (path)
704 const char *path;
706 struct default_include *p;
708 if (path[0] != '/')
709 abort (); /* Must be an absolutized filename. */
711 for (p = include_defaults; p->fname; p++)
712 if (!strncmp (path, p->fname, strlen (p->fname))
713 && path[strlen (p->fname)] == '/')
714 return 1;
715 return 0;
718 #if 0
719 /* Return true if the given filename designates a file that the user has
720 read access to and for which the user has write access to the containing
721 directory. */
723 static int
724 file_could_be_converted (const char *path)
726 char *const dir_name = (char *) alloca (strlen (path) + 1);
728 if (access (path, R_OK))
729 return 0;
732 char *dir_last_slash;
734 strcpy (dir_name, path);
735 dir_last_slash = strrchr (dir_name, '/');
736 if (dir_last_slash)
737 *dir_last_slash = '\0';
738 else
739 abort (); /* Should have been an absolutized filename. */
742 if (access (path, W_OK))
743 return 0;
745 return 1;
748 /* Return true if the given filename designates a file that we are allowed
749 to modify. Files which we should not attempt to modify are (a) "system"
750 include files, and (b) files which the user doesn't have write access to,
751 and (c) files which reside in directories which the user doesn't have
752 write access to. Unless requested to be quiet, give warnings about
753 files that we will not try to convert for one reason or another. An
754 exception is made for "system" include files, which we never try to
755 convert and for which we don't issue the usual warnings. */
757 static int
758 file_normally_convertible (const char *path)
760 char *const dir_name = alloca (strlen (path) + 1);
762 if (in_system_include_dir (path))
763 return 0;
766 char *dir_last_slash;
768 strcpy (dir_name, path);
769 dir_last_slash = strrchr (dir_name, '/');
770 if (dir_last_slash)
771 *dir_last_slash = '\0';
772 else
773 abort (); /* Should have been an absolutized filename. */
776 if (access (path, R_OK))
778 if (!quiet_flag)
779 notice ("%s: warning: no read access for file `%s'\n",
780 pname, shortpath (NULL, path));
781 return 0;
784 if (access (path, W_OK))
786 if (!quiet_flag)
787 notice ("%s: warning: no write access for file `%s'\n",
788 pname, shortpath (NULL, path));
789 return 0;
792 if (access (dir_name, W_OK))
794 if (!quiet_flag)
795 notice ("%s: warning: no write access for dir containing `%s'\n",
796 pname, shortpath (NULL, path));
797 return 0;
800 return 1;
802 #endif /* 0 */
804 #ifndef UNPROTOIZE
806 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X
807 file. Return false otherwise. */
809 static int
810 is_syscalls_file (fi_p)
811 const file_info *fi_p;
813 char const *f = fi_p->hash_entry->symbol;
814 size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
815 return sysl <= fl && strcmp (f + fl - sysl, syscalls_filename) == 0;
818 #endif /* !defined (UNPROTOIZE) */
820 /* Check to see if this file will need to have anything done to it on this
821 run. If there is nothing in the given file which both needs conversion
822 and for which we have the necessary stuff to do the conversion, return
823 false. Otherwise, return true.
825 Note that (for protoize) it is only valid to call this function *after*
826 the connections between declarations and definitions have all been made
827 by connect_defs_and_decs. */
829 static int
830 needs_to_be_converted (file_p)
831 const file_info *file_p;
833 const def_dec_info *ddp;
835 #ifndef UNPROTOIZE
837 if (is_syscalls_file (file_p))
838 return 0;
840 #endif /* !defined (UNPROTOIZE) */
842 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
844 if (
846 #ifndef UNPROTOIZE
848 /* ... and if we a protoizing and this function is in old style ... */
849 !ddp->prototyped
850 /* ... and if this a definition or is a decl with an associated def ... */
851 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
853 #else /* defined (UNPROTOIZE) */
855 /* ... and if we are unprotoizing and this function is in new style ... */
856 ddp->prototyped
858 #endif /* defined (UNPROTOIZE) */
860 /* ... then the containing file needs converting. */
861 return -1;
862 return 0;
865 /* Return 1 if the file name NAME is in a directory
866 that should be converted. */
868 static int
869 directory_specified_p (name)
870 const char *name;
872 struct string_list *p;
874 for (p = directory_list; p; p = p->next)
875 if (!strncmp (name, p->name, strlen (p->name))
876 && name[strlen (p->name)] == '/')
878 const char *q = name + strlen (p->name) + 1;
880 /* If there are more slashes, it's in a subdir, so
881 this match doesn't count. */
882 while (*q)
883 if (*q++ == '/')
884 goto lose;
885 return 1;
887 lose: ;
890 return 0;
893 /* Return 1 if the file named NAME should be excluded from conversion. */
895 static int
896 file_excluded_p (name)
897 const char *name;
899 struct string_list *p;
900 int len = strlen (name);
902 for (p = exclude_list; p; p = p->next)
903 if (!strcmp (name + len - strlen (p->name), p->name)
904 && name[len - strlen (p->name) - 1] == '/')
905 return 1;
907 return 0;
910 /* Construct a new element of a string_list.
911 STRING is the new element value, and REST holds the remaining elements. */
913 static struct string_list *
914 string_list_cons (string, rest)
915 const char *string;
916 struct string_list *rest;
918 struct string_list *temp
919 = (struct string_list *) xmalloc (sizeof (struct string_list));
921 temp->next = rest;
922 temp->name = string;
923 return temp;
926 /* ??? The GNU convention for mentioning function args in its comments
927 is to capitalize them. So change "hash_tab_p" to HASH_TAB_P below.
928 Likewise for all the other functions. */
930 /* Given a hash table, apply some function to each node in the table. The
931 table to traverse is given as the "hash_tab_p" argument, and the
932 function to be applied to each node in the table is given as "func"
933 argument. */
935 static void
936 visit_each_hash_node (hash_tab_p, func)
937 const hash_table_entry *hash_tab_p;
938 void (*func) PARAMS ((const hash_table_entry *));
940 const hash_table_entry *primary;
942 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
943 if (primary->symbol)
945 hash_table_entry *second;
947 (*func)(primary);
948 for (second = primary->hash_next; second; second = second->hash_next)
949 (*func) (second);
953 /* Initialize all of the fields of a new hash table entry, pointed
954 to by the "p" parameter. Note that the space to hold the entry
955 is assumed to have already been allocated before this routine is
956 called. */
958 static hash_table_entry *
959 add_symbol (p, s)
960 hash_table_entry *p;
961 const char *s;
963 p->hash_next = NULL;
964 p->symbol = xstrdup (s);
965 p->ddip = NULL;
966 p->fip = NULL;
967 return p;
970 /* Look for a particular function name or filename in the particular
971 hash table indicated by "hash_tab_p". If the name is not in the
972 given hash table, add it. Either way, return a pointer to the
973 hash table entry for the given name. */
975 static hash_table_entry *
976 lookup (hash_tab_p, search_symbol)
977 hash_table_entry *hash_tab_p;
978 const char *search_symbol;
980 int hash_value = 0;
981 const char *search_symbol_char_p = search_symbol;
982 hash_table_entry *p;
984 while (*search_symbol_char_p)
985 hash_value += *search_symbol_char_p++;
986 hash_value &= hash_mask;
987 p = &hash_tab_p[hash_value];
988 if (! p->symbol)
989 return add_symbol (p, search_symbol);
990 if (!strcmp (p->symbol, search_symbol))
991 return p;
992 while (p->hash_next)
994 p = p->hash_next;
995 if (!strcmp (p->symbol, search_symbol))
996 return p;
998 p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry));
999 p = p->hash_next;
1000 return add_symbol (p, search_symbol);
1003 /* Throw a def/dec record on the junk heap.
1005 Also, since we are not using this record anymore, free up all of the
1006 stuff it pointed to. */
1008 static void
1009 free_def_dec (p)
1010 def_dec_info *p;
1012 free ((NONCONST PTR) p->ansi_decl);
1014 #ifndef UNPROTOIZE
1016 const f_list_chain_item * curr;
1017 const f_list_chain_item * next;
1019 for (curr = p->f_list_chain; curr; curr = next)
1021 next = curr->chain_next;
1022 free ((NONCONST PTR) curr);
1025 #endif /* !defined (UNPROTOIZE) */
1027 free (p);
1030 /* Unexpand as many macro symbol as we can find.
1032 If the given line must be unexpanded, make a copy of it in the heap and
1033 return a pointer to the unexpanded copy. Otherwise return NULL. */
1035 static char *
1036 unexpand_if_needed (aux_info_line)
1037 const char *aux_info_line;
1039 static char *line_buf = 0;
1040 static int line_buf_size = 0;
1041 const unexpansion *unexp_p;
1042 int got_unexpanded = 0;
1043 const char *s;
1044 char *copy_p = line_buf;
1046 if (line_buf == 0)
1048 line_buf_size = 1024;
1049 line_buf = (char *) xmalloc (line_buf_size);
1052 copy_p = line_buf;
1054 /* Make a copy of the input string in line_buf, expanding as necessary. */
1056 for (s = aux_info_line; *s != '\n'; )
1058 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
1060 const char *in_p = unexp_p->expanded;
1061 size_t len = strlen (in_p);
1063 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1065 int size = strlen (unexp_p->contracted);
1066 got_unexpanded = 1;
1067 if (copy_p + size - line_buf >= line_buf_size)
1069 int offset = copy_p - line_buf;
1070 line_buf_size *= 2;
1071 line_buf_size += size;
1072 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1073 copy_p = line_buf + offset;
1075 strcpy (copy_p, unexp_p->contracted);
1076 copy_p += size;
1078 /* Assume the there will not be another replacement required
1079 within the text just replaced. */
1081 s += len;
1082 goto continue_outer;
1085 if (copy_p - line_buf == line_buf_size)
1087 int offset = copy_p - line_buf;
1088 line_buf_size *= 2;
1089 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1090 copy_p = line_buf + offset;
1092 *copy_p++ = *s++;
1093 continue_outer: ;
1095 if (copy_p + 2 - line_buf >= line_buf_size)
1097 int offset = copy_p - line_buf;
1098 line_buf_size *= 2;
1099 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1100 copy_p = line_buf + offset;
1102 *copy_p++ = '\n';
1103 *copy_p = '\0';
1105 return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
1108 /* Return the absolutized filename for the given relative
1109 filename. Note that if that filename is already absolute, it may
1110 still be returned in a modified form because this routine also
1111 eliminates redundant slashes and single dots and eliminates double
1112 dots to get a shortest possible filename from the given input
1113 filename. The absolutization of relative filenames is made by
1114 assuming that the given filename is to be taken as relative to
1115 the first argument (cwd) or to the current directory if cwd is
1116 NULL. */
1118 static char *
1119 abspath (cwd, rel_filename)
1120 const char *cwd;
1121 const char *rel_filename;
1123 /* Setup the current working directory as needed. */
1124 const char *cwd2 = (cwd) ? cwd : cwd_buffer;
1125 char *const abs_buffer
1126 = (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 2);
1127 char *endp = abs_buffer;
1128 char *outp, *inp;
1130 /* Copy the filename (possibly preceded by the current working
1131 directory name) into the absolutization buffer. */
1134 const char *src_p;
1136 if (rel_filename[0] != '/')
1138 src_p = cwd2;
1139 while ((*endp++ = *src_p++))
1140 continue;
1141 *(endp-1) = '/'; /* overwrite null */
1143 src_p = rel_filename;
1144 while ((*endp++ = *src_p++))
1145 continue;
1148 /* Now make a copy of abs_buffer into abs_buffer, shortening the
1149 filename (by taking out slashes and dots) as we go. */
1151 outp = inp = abs_buffer;
1152 *outp++ = *inp++; /* copy first slash */
1153 #if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
1154 if (inp[0] == '/')
1155 *outp++ = *inp++; /* copy second slash */
1156 #endif
1157 for (;;)
1159 if (!inp[0])
1160 break;
1161 else if (inp[0] == '/' && outp[-1] == '/')
1163 inp++;
1164 continue;
1166 else if (inp[0] == '.' && outp[-1] == '/')
1168 if (!inp[1])
1169 break;
1170 else if (inp[1] == '/')
1172 inp += 2;
1173 continue;
1175 else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/'))
1177 inp += (inp[2] == '/') ? 3 : 2;
1178 outp -= 2;
1179 while (outp >= abs_buffer && *outp != '/')
1180 outp--;
1181 if (outp < abs_buffer)
1183 /* Catch cases like /.. where we try to backup to a
1184 point above the absolute root of the logical file
1185 system. */
1187 notice ("%s: invalid file name: %s\n",
1188 pname, rel_filename);
1189 exit (FATAL_EXIT_CODE);
1191 *++outp = '\0';
1192 continue;
1195 *outp++ = *inp++;
1198 /* On exit, make sure that there is a trailing null, and make sure that
1199 the last character of the returned string is *not* a slash. */
1201 *outp = '\0';
1202 if (outp[-1] == '/')
1203 *--outp = '\0';
1205 /* Make a copy (in the heap) of the stuff left in the absolutization
1206 buffer and return a pointer to the copy. */
1208 return savestring (abs_buffer, outp - abs_buffer);
1211 /* Given a filename (and possibly a directory name from which the filename
1212 is relative) return a string which is the shortest possible
1213 equivalent for the corresponding full (absolutized) filename. The
1214 shortest possible equivalent may be constructed by converting the
1215 absolutized filename to be a relative filename (i.e. relative to
1216 the actual current working directory). However if a relative filename
1217 is longer, then the full absolute filename is returned.
1219 KNOWN BUG:
1221 Note that "simple-minded" conversion of any given type of filename (either
1222 relative or absolute) may not result in a valid equivalent filename if any
1223 subpart of the original filename is actually a symbolic link. */
1225 static const char *
1226 shortpath (cwd, filename)
1227 const char *cwd;
1228 const char *filename;
1230 char *rel_buffer;
1231 char *rel_buf_p;
1232 char *cwd_p = cwd_buffer;
1233 char *path_p;
1234 int unmatched_slash_count = 0;
1235 size_t filename_len = strlen (filename);
1237 path_p = abspath (cwd, filename);
1238 rel_buf_p = rel_buffer = (char *) xmalloc (filename_len);
1240 while (*cwd_p && (*cwd_p == *path_p))
1242 cwd_p++;
1243 path_p++;
1245 if (!*cwd_p && (!*path_p || *path_p == '/')) /* whole pwd matched */
1247 if (!*path_p) /* input *is* the current path! */
1248 return ".";
1249 else
1250 return ++path_p;
1252 else
1254 if (*path_p)
1256 --cwd_p;
1257 --path_p;
1258 while (*cwd_p != '/') /* backup to last slash */
1260 --cwd_p;
1261 --path_p;
1263 cwd_p++;
1264 path_p++;
1265 unmatched_slash_count++;
1268 /* Find out how many directory levels in cwd were *not* matched. */
1269 while (*cwd_p)
1270 if (*cwd_p++ == '/')
1271 unmatched_slash_count++;
1273 /* Now we know how long the "short name" will be.
1274 Reject it if longer than the input. */
1275 if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
1276 return filename;
1278 /* For each of them, put a `../' at the beginning of the short name. */
1279 while (unmatched_slash_count--)
1281 /* Give up if the result gets to be longer
1282 than the absolute path name. */
1283 if (rel_buffer + filename_len <= rel_buf_p + 3)
1284 return filename;
1285 *rel_buf_p++ = '.';
1286 *rel_buf_p++ = '.';
1287 *rel_buf_p++ = '/';
1290 /* Then tack on the unmatched part of the desired file's name. */
1293 if (rel_buffer + filename_len <= rel_buf_p)
1294 return filename;
1296 while ((*rel_buf_p++ = *path_p++));
1298 --rel_buf_p;
1299 if (*(rel_buf_p-1) == '/')
1300 *--rel_buf_p = '\0';
1301 return rel_buffer;
1305 /* Lookup the given filename in the hash table for filenames. If it is a
1306 new one, then the hash table info pointer will be null. In this case,
1307 we create a new file_info record to go with the filename, and we initialize
1308 that record with some reasonable values. */
1310 /* FILENAME was const, but that causes a warning on AIX when calling stat.
1311 That is probably a bug in AIX, but might as well avoid the warning. */
1313 static file_info *
1314 find_file (filename, do_not_stat)
1315 const char *filename;
1316 int do_not_stat;
1318 hash_table_entry *hash_entry_p;
1320 hash_entry_p = lookup (filename_primary, filename);
1321 if (hash_entry_p->fip)
1322 return hash_entry_p->fip;
1323 else
1325 struct stat stat_buf;
1326 file_info *file_p = (file_info *) xmalloc (sizeof (file_info));
1328 /* If we cannot get status on any given source file, give a warning
1329 and then just set its time of last modification to infinity. */
1331 if (do_not_stat)
1332 stat_buf.st_mtime = (time_t) 0;
1333 else
1335 if (stat (filename, &stat_buf) == -1)
1337 int errno_val = errno;
1338 notice ("%s: %s: can't get status: %s\n",
1339 pname, shortpath (NULL, filename),
1340 xstrerror (errno_val));
1341 stat_buf.st_mtime = (time_t) -1;
1345 hash_entry_p->fip = file_p;
1346 file_p->hash_entry = hash_entry_p;
1347 file_p->defs_decs = NULL;
1348 file_p->mtime = stat_buf.st_mtime;
1349 return file_p;
1353 /* Generate a fatal error because some part of the aux_info file is
1354 messed up. */
1356 static void
1357 aux_info_corrupted ()
1359 notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
1360 pname, current_aux_info_lineno);
1361 exit (FATAL_EXIT_CODE);
1364 /* ??? This comment is vague. Say what the condition is for. */
1365 /* Check to see that a condition is true. This is kind of like an assert. */
1367 static void
1368 check_aux_info (cond)
1369 int cond;
1371 if (! cond)
1372 aux_info_corrupted ();
1375 /* Given a pointer to the closing right parenthesis for a particular formals
1376 list (in an aux_info file) find the corresponding left parenthesis and
1377 return a pointer to it. */
1379 static const char *
1380 find_corresponding_lparen (p)
1381 const char *p;
1383 const char *q;
1384 int paren_depth;
1386 for (paren_depth = 1, q = p-1; paren_depth; q--)
1388 switch (*q)
1390 case ')':
1391 paren_depth++;
1392 break;
1393 case '(':
1394 paren_depth--;
1395 break;
1398 return ++q;
1401 /* Given a line from an aux info file, and a time at which the aux info
1402 file it came from was created, check to see if the item described in
1403 the line comes from a file which has been modified since the aux info
1404 file was created. If so, return non-zero, else return zero. */
1406 static int
1407 referenced_file_is_newer (l, aux_info_mtime)
1408 const char *l;
1409 time_t aux_info_mtime;
1411 const char *p;
1412 file_info *fi_p;
1413 char *filename;
1415 check_aux_info (l[0] == '/');
1416 check_aux_info (l[1] == '*');
1417 check_aux_info (l[2] == ' ');
1420 const char *filename_start = p = l + 3;
1422 while (*p != ':')
1423 p++;
1424 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1425 strncpy (filename, filename_start, (size_t) (p - filename_start));
1426 filename[p-filename_start] = '\0';
1429 /* Call find_file to find the file_info record associated with the file
1430 which contained this particular def or dec item. Note that this call
1431 may cause a new file_info record to be created if this is the first time
1432 that we have ever known about this particular file. */
1434 fi_p = find_file (abspath (invocation_filename, filename), 0);
1436 return (fi_p->mtime > aux_info_mtime);
1439 /* Given a line of info from the aux_info file, create a new
1440 def_dec_info record to remember all of the important information about
1441 a function definition or declaration.
1443 Link this record onto the list of such records for the particular file in
1444 which it occurred in proper (descending) line number order (for now).
1446 If there is an identical record already on the list for the file, throw
1447 this one away. Doing so takes care of the (useless and troublesome)
1448 duplicates which are bound to crop up due to multiple inclusions of any
1449 given individual header file.
1451 Finally, link the new def_dec record onto the list of such records
1452 pertaining to this particular function name. */
1454 static void
1455 save_def_or_dec (l, is_syscalls)
1456 const char *l;
1457 int is_syscalls;
1459 const char *p;
1460 const char *semicolon_p;
1461 def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info));
1463 #ifndef UNPROTOIZE
1464 def_dec_p->written = 0;
1465 #endif /* !defined (UNPROTOIZE) */
1467 /* Start processing the line by picking off 5 pieces of information from
1468 the left hand end of the line. These are filename, line number,
1469 new/old/implicit flag (new = ANSI prototype format), definition or
1470 declaration flag, and extern/static flag). */
1472 check_aux_info (l[0] == '/');
1473 check_aux_info (l[1] == '*');
1474 check_aux_info (l[2] == ' ');
1477 const char *filename_start = p = l + 3;
1478 char *filename;
1480 while (*p != ':')
1481 p++;
1482 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1483 strncpy (filename, filename_start, (size_t) (p - filename_start));
1484 filename[p-filename_start] = '\0';
1486 /* Call find_file to find the file_info record associated with the file
1487 which contained this particular def or dec item. Note that this call
1488 may cause a new file_info record to be created if this is the first time
1489 that we have ever known about this particular file.
1491 Note that we started out by forcing all of the base source file names
1492 (i.e. the names of the aux_info files with the .X stripped off) into the
1493 filenames hash table, and we simultaneously setup file_info records for
1494 all of these base file names (even if they may be useless later).
1495 The file_info records for all of these "base" file names (properly)
1496 act as file_info records for the "original" (i.e. un-included) files
1497 which were submitted to gcc for compilation (when the -aux-info
1498 option was used). */
1500 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1504 const char *line_number_start = ++p;
1505 char line_number[10];
1507 while (*p != ':')
1508 p++;
1509 strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1510 line_number[p-line_number_start] = '\0';
1511 def_dec_p->line = atoi (line_number);
1514 /* Check that this record describes a new-style, old-style, or implicit
1515 definition or declaration. */
1517 p++; /* Skip over the `:'. */
1518 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1520 /* Is this a new style (ANSI prototyped) definition or declaration? */
1522 def_dec_p->prototyped = (*p == 'N');
1524 #ifndef UNPROTOIZE
1526 /* Is this an implicit declaration? */
1528 def_dec_p->is_implicit = (*p == 'I');
1530 #endif /* !defined (UNPROTOIZE) */
1532 p++;
1534 check_aux_info ((*p == 'C') || (*p == 'F'));
1536 /* Is this item a function definition (F) or a declaration (C). Note that
1537 we treat item taken from the syscalls file as though they were function
1538 definitions regardless of what the stuff in the file says. */
1540 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1542 #ifndef UNPROTOIZE
1543 def_dec_p->definition = 0; /* Fill this in later if protoizing. */
1544 #endif /* !defined (UNPROTOIZE) */
1546 check_aux_info (*p++ == ' ');
1547 check_aux_info (*p++ == '*');
1548 check_aux_info (*p++ == '/');
1549 check_aux_info (*p++ == ' ');
1551 #ifdef UNPROTOIZE
1552 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1553 #else /* !defined (UNPROTOIZE) */
1554 if (!strncmp (p, "static", 6))
1555 def_dec_p->is_static = -1;
1556 else if (!strncmp (p, "extern", 6))
1557 def_dec_p->is_static = 0;
1558 else
1559 check_aux_info (0); /* Didn't find either `extern' or `static'. */
1560 #endif /* !defined (UNPROTOIZE) */
1563 const char *ansi_start = p;
1565 p += 6; /* Pass over the "static" or "extern". */
1567 /* We are now past the initial stuff. Search forward from here to find
1568 the terminating semicolon that should immediately follow the entire
1569 ANSI format function declaration. */
1571 while (*++p != ';')
1572 continue;
1574 semicolon_p = p;
1576 /* Make a copy of the ansi declaration part of the line from the aux_info
1577 file. */
1579 def_dec_p->ansi_decl
1580 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1582 /* Backup and point at the final right paren of the final argument list. */
1584 p--;
1586 #ifndef UNPROTOIZE
1587 def_dec_p->f_list_chain = NULL;
1588 #endif /* !defined (UNPROTOIZE) */
1590 while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
1591 if (*p != ')')
1593 free_def_dec (def_dec_p);
1594 return;
1598 /* Now isolate a whole set of formal argument lists, one-by-one. Normally,
1599 there will only be one list to isolate, but there could be more. */
1601 def_dec_p->f_list_count = 0;
1603 for (;;)
1605 const char *left_paren_p = find_corresponding_lparen (p);
1606 #ifndef UNPROTOIZE
1608 f_list_chain_item *cip
1609 = (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
1611 cip->formals_list
1612 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1614 /* Add the new chain item at the head of the current list. */
1616 cip->chain_next = def_dec_p->f_list_chain;
1617 def_dec_p->f_list_chain = cip;
1619 #endif /* !defined (UNPROTOIZE) */
1620 def_dec_p->f_list_count++;
1622 p = left_paren_p - 2;
1624 /* p must now point either to another right paren, or to the last
1625 character of the name of the function that was declared/defined.
1626 If p points to another right paren, then this indicates that we
1627 are dealing with multiple formals lists. In that case, there
1628 really should be another right paren preceding this right paren. */
1630 if (*p != ')')
1631 break;
1632 else
1633 check_aux_info (*--p == ')');
1638 const char *past_fn = p + 1;
1640 check_aux_info (*past_fn == ' ');
1642 /* Scan leftwards over the identifier that names the function. */
1644 while (is_id_char (*p))
1645 p--;
1646 p++;
1648 /* p now points to the leftmost character of the function name. */
1651 char *fn_string = (char *) alloca (past_fn - p + 1);
1653 strncpy (fn_string, p, (size_t) (past_fn - p));
1654 fn_string[past_fn-p] = '\0';
1655 def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1659 /* Look at all of the defs and decs for this function name that we have
1660 collected so far. If there is already one which is at the same
1661 line number in the same file, then we can discard this new def_dec_info
1662 record.
1664 As an extra assurance that any such pair of (nominally) identical
1665 function declarations are in fact identical, we also compare the
1666 ansi_decl parts of the lines from the aux_info files just to be on
1667 the safe side.
1669 This comparison will fail if (for instance) the user was playing
1670 messy games with the preprocessor which ultimately causes one
1671 function declaration in one header file to look differently when
1672 that file is included by two (or more) other files. */
1675 const def_dec_info *other;
1677 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1679 if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1681 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1683 notice ("%s:%d: declaration of function `%s' takes different forms\n",
1684 def_dec_p->file->hash_entry->symbol,
1685 def_dec_p->line,
1686 def_dec_p->hash_entry->symbol);
1687 exit (FATAL_EXIT_CODE);
1689 free_def_dec (def_dec_p);
1690 return;
1695 #ifdef UNPROTOIZE
1697 /* If we are doing unprotoizing, we must now setup the pointers that will
1698 point to the K&R name list and to the K&R argument declarations list.
1700 Note that if this is only a function declaration, then we should not
1701 expect to find any K&R style formals list following the ANSI-style
1702 formals list. This is because GCC knows that such information is
1703 useless in the case of function declarations (function definitions
1704 are a different story however).
1706 Since we are unprotoizing, we don't need any such lists anyway.
1707 All we plan to do is to delete all characters between ()'s in any
1708 case. */
1710 def_dec_p->formal_names = NULL;
1711 def_dec_p->formal_decls = NULL;
1713 if (def_dec_p->is_func_def)
1715 p = semicolon_p;
1716 check_aux_info (*++p == ' ');
1717 check_aux_info (*++p == '/');
1718 check_aux_info (*++p == '*');
1719 check_aux_info (*++p == ' ');
1720 check_aux_info (*++p == '(');
1723 const char *kr_names_start = ++p; /* Point just inside '('. */
1725 while (*p++ != ')')
1726 continue;
1727 p--; /* point to closing right paren */
1729 /* Make a copy of the K&R parameter names list. */
1731 def_dec_p->formal_names
1732 = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1735 check_aux_info (*++p == ' ');
1736 p++;
1738 /* p now points to the first character of the K&R style declarations
1739 list (if there is one) or to the star-slash combination that ends
1740 the comment in which such lists get embedded. */
1742 /* Make a copy of the K&R formal decls list and set the def_dec record
1743 to point to it. */
1745 if (*p == '*') /* Are there no K&R declarations? */
1747 check_aux_info (*++p == '/');
1748 def_dec_p->formal_decls = "";
1750 else
1752 const char *kr_decls_start = p;
1754 while (p[0] != '*' || p[1] != '/')
1755 p++;
1756 p--;
1758 check_aux_info (*p == ' ');
1760 def_dec_p->formal_decls
1761 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1764 /* Handle a special case. If we have a function definition marked as
1765 being in "old" style, and if its formal names list is empty, then
1766 it may actually have the string "void" in its real formals list
1767 in the original source code. Just to make sure, we will get setup
1768 to convert such things anyway.
1770 This kludge only needs to be here because of an insurmountable
1771 problem with generating .X files. */
1773 if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1774 def_dec_p->prototyped = 1;
1777 /* Since we are unprotoizing, if this item is already in old (K&R) style,
1778 we can just ignore it. If that is true, throw away the itme now. */
1780 if (!def_dec_p->prototyped)
1782 free_def_dec (def_dec_p);
1783 return;
1786 #endif /* defined (UNPROTOIZE) */
1788 /* Add this record to the head of the list of records pertaining to this
1789 particular function name. */
1791 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1792 def_dec_p->hash_entry->ddip = def_dec_p;
1794 /* Add this new def_dec_info record to the sorted list of def_dec_info
1795 records for this file. Note that we don't have to worry about duplicates
1796 (caused by multiple inclusions of header files) here because we have
1797 already eliminated duplicates above. */
1799 if (!def_dec_p->file->defs_decs)
1801 def_dec_p->file->defs_decs = def_dec_p;
1802 def_dec_p->next_in_file = NULL;
1804 else
1806 int line = def_dec_p->line;
1807 const def_dec_info *prev = NULL;
1808 const def_dec_info *curr = def_dec_p->file->defs_decs;
1809 const def_dec_info *next = curr->next_in_file;
1811 while (next && (line < curr->line))
1813 prev = curr;
1814 curr = next;
1815 next = next->next_in_file;
1817 if (line >= curr->line)
1819 def_dec_p->next_in_file = curr;
1820 if (prev)
1821 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1822 else
1823 def_dec_p->file->defs_decs = def_dec_p;
1825 else /* assert (next == NULL); */
1827 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
1828 /* assert (next == NULL); */
1829 def_dec_p->next_in_file = next;
1834 /* Set up the vector COMPILE_PARAMS which is the argument list for running GCC.
1835 Also set input_file_name_index and aux_info_file_name_index
1836 to the indices of the slots where the file names should go. */
1838 /* We initialize the vector by removing -g, -O, -S, -c, and -o options,
1839 and adding '-aux-info AUXFILE -S -o /dev/null INFILE' at the end. */
1841 static void
1842 munge_compile_params (params_list)
1843 const char *params_list;
1845 /* Build up the contents in a temporary vector
1846 that is so big that to has to be big enough. */
1847 const char **temp_params
1848 = (const char **) alloca ((strlen (params_list) + 8) * sizeof (char *));
1849 int param_count = 0;
1850 const char *param;
1852 temp_params[param_count++] = compiler_file_name;
1853 for (;;)
1855 while (ISSPACE ((const unsigned char)*params_list))
1856 params_list++;
1857 if (!*params_list)
1858 break;
1859 param = params_list;
1860 while (*params_list && !ISSPACE ((const unsigned char)*params_list))
1861 params_list++;
1862 if (param[0] != '-')
1863 temp_params[param_count++]
1864 = dupnstr (param, (size_t) (params_list - param));
1865 else
1867 switch (param[1])
1869 case 'g':
1870 case 'O':
1871 case 'S':
1872 case 'c':
1873 break; /* Don't copy these. */
1874 case 'o':
1875 while (ISSPACE ((const unsigned char)*params_list))
1876 params_list++;
1877 while (*params_list
1878 && !ISSPACE ((const unsigned char)*params_list))
1879 params_list++;
1880 break;
1881 default:
1882 temp_params[param_count++]
1883 = dupnstr (param, (size_t) (params_list - param));
1886 if (!*params_list)
1887 break;
1889 temp_params[param_count++] = "-aux-info";
1891 /* Leave room for the aux-info file name argument. */
1892 aux_info_file_name_index = param_count;
1893 temp_params[param_count++] = NULL;
1895 temp_params[param_count++] = "-S";
1896 temp_params[param_count++] = "-o";
1897 temp_params[param_count++] = "/dev/null";
1899 /* Leave room for the input file name argument. */
1900 input_file_name_index = param_count;
1901 temp_params[param_count++] = NULL;
1902 /* Terminate the list. */
1903 temp_params[param_count++] = NULL;
1905 /* Make a copy of the compile_params in heap space. */
1907 compile_params
1908 = (const char **) xmalloc (sizeof (char *) * (param_count+1));
1909 memcpy (compile_params, temp_params, sizeof (char *) * param_count);
1912 /* Do a recompilation for the express purpose of generating a new aux_info
1913 file to go with a specific base source file.
1915 The result is a boolean indicating success. */
1917 static int
1918 gen_aux_info_file (base_filename)
1919 const char *base_filename;
1921 if (!input_file_name_index)
1922 munge_compile_params ("");
1924 /* Store the full source file name in the argument vector. */
1925 compile_params[input_file_name_index] = shortpath (NULL, base_filename);
1926 /* Add .X to source file name to get aux-info file name. */
1927 compile_params[aux_info_file_name_index] =
1928 concat (compile_params[input_file_name_index], ".X", NULL);
1930 if (!quiet_flag)
1931 notice ("%s: compiling `%s'\n",
1932 pname, compile_params[input_file_name_index]);
1935 char *errmsg_fmt, *errmsg_arg;
1936 int wait_status, pid;
1938 pid = pexecute (compile_params[0], (char * const *) compile_params,
1939 pname, NULL, &errmsg_fmt, &errmsg_arg,
1940 PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
1942 if (pid == -1)
1944 int errno_val = errno;
1945 fprintf (stderr, "%s: ", pname);
1946 fprintf (stderr, errmsg_fmt, errmsg_arg);
1947 fprintf (stderr, ": %s\n", xstrerror (errno_val));
1948 return 0;
1951 pid = pwait (pid, &wait_status, 0);
1952 if (pid == -1)
1954 notice ("%s: wait: %s\n", pname, xstrerror (errno));
1955 return 0;
1957 if (WIFSIGNALED (wait_status))
1959 notice ("%s: subprocess got fatal signal %d\n",
1960 pname, WTERMSIG (wait_status));
1961 return 0;
1963 if (WIFEXITED (wait_status))
1965 if (WEXITSTATUS (wait_status) != 0)
1967 notice ("%s: %s exited with status %d\n",
1968 pname, compile_params[0], WEXITSTATUS (wait_status));
1969 return 0;
1971 return 1;
1973 abort ();
1977 /* Read in all of the information contained in a single aux_info file.
1978 Save all of the important stuff for later. */
1980 static void
1981 process_aux_info_file (base_source_filename, keep_it, is_syscalls)
1982 const char *base_source_filename;
1983 int keep_it;
1984 int is_syscalls;
1986 size_t base_len = strlen (base_source_filename);
1987 char * aux_info_filename
1988 = (char *) alloca (base_len + strlen (aux_info_suffix) + 1);
1989 char *aux_info_base;
1990 char *aux_info_limit;
1991 char *aux_info_relocated_name;
1992 const char *aux_info_second_line;
1993 time_t aux_info_mtime;
1994 size_t aux_info_size;
1995 int must_create;
1997 /* Construct the aux_info filename from the base source filename. */
1999 strcpy (aux_info_filename, base_source_filename);
2000 strcat (aux_info_filename, aux_info_suffix);
2002 /* Check that the aux_info file exists and is readable. If it does not
2003 exist, try to create it (once only). */
2005 /* If file doesn't exist, set must_create.
2006 Likewise if it exists and we can read it but it is obsolete.
2007 Otherwise, report an error. */
2008 must_create = 0;
2010 /* Come here with must_create set to 1 if file is out of date. */
2011 start_over: ;
2013 if (access (aux_info_filename, R_OK) == -1)
2015 if (errno == ENOENT)
2017 if (is_syscalls)
2019 notice ("%s: warning: missing SYSCALLS file `%s'\n",
2020 pname, aux_info_filename);
2021 return;
2023 must_create = 1;
2025 else
2027 int errno_val = errno;
2028 notice ("%s: can't read aux info file `%s': %s\n",
2029 pname, shortpath (NULL, aux_info_filename),
2030 xstrerror (errno_val));
2031 errors++;
2032 return;
2035 #if 0 /* There is code farther down to take care of this. */
2036 else
2038 struct stat s1, s2;
2039 stat (aux_info_file_name, &s1);
2040 stat (base_source_file_name, &s2);
2041 if (s2.st_mtime > s1.st_mtime)
2042 must_create = 1;
2044 #endif /* 0 */
2046 /* If we need a .X file, create it, and verify we can read it. */
2047 if (must_create)
2049 if (!gen_aux_info_file (base_source_filename))
2051 errors++;
2052 return;
2054 if (access (aux_info_filename, R_OK) == -1)
2056 int errno_val = errno;
2057 notice ("%s: can't read aux info file `%s': %s\n",
2058 pname, shortpath (NULL, aux_info_filename),
2059 xstrerror (errno_val));
2060 errors++;
2061 return;
2066 struct stat stat_buf;
2068 /* Get some status information about this aux_info file. */
2070 if (stat (aux_info_filename, &stat_buf) == -1)
2072 int errno_val = errno;
2073 notice ("%s: can't get status of aux info file `%s': %s\n",
2074 pname, shortpath (NULL, aux_info_filename),
2075 xstrerror (errno_val));
2076 errors++;
2077 return;
2080 /* Check on whether or not this aux_info file is zero length. If it is,
2081 then just ignore it and return. */
2083 if ((aux_info_size = stat_buf.st_size) == 0)
2084 return;
2086 /* Get the date/time of last modification for this aux_info file and
2087 remember it. We will have to check that any source files that it
2088 contains information about are at least this old or older. */
2090 aux_info_mtime = stat_buf.st_mtime;
2092 if (!is_syscalls)
2094 /* Compare mod time with the .c file; update .X file if obsolete.
2095 The code later on can fail to check the .c file
2096 if it did not directly define any functions. */
2098 if (stat (base_source_filename, &stat_buf) == -1)
2100 int errno_val = errno;
2101 notice ("%s: can't get status of aux info file `%s': %s\n",
2102 pname, shortpath (NULL, base_source_filename),
2103 xstrerror (errno_val));
2104 errors++;
2105 return;
2107 if (stat_buf.st_mtime > aux_info_mtime)
2109 must_create = 1;
2110 goto start_over;
2116 int aux_info_file;
2118 /* Open the aux_info file. */
2120 if ((aux_info_file = open (aux_info_filename, O_RDONLY, 0444 )) == -1)
2122 int errno_val = errno;
2123 notice ("%s: can't open aux info file `%s' for reading: %s\n",
2124 pname, shortpath (NULL, aux_info_filename),
2125 xstrerror (errno_val));
2126 return;
2129 /* Allocate space to hold the aux_info file in memory. */
2131 aux_info_base = xmalloc (aux_info_size + 1);
2132 aux_info_limit = aux_info_base + aux_info_size;
2133 *aux_info_limit = '\0';
2135 /* Read the aux_info file into memory. */
2137 if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
2138 (int) aux_info_size)
2140 int errno_val = errno;
2141 notice ("%s: error reading aux info file `%s': %s\n",
2142 pname, shortpath (NULL, aux_info_filename),
2143 xstrerror (errno_val));
2144 free (aux_info_base);
2145 close (aux_info_file);
2146 return;
2149 /* Close the aux info file. */
2151 if (close (aux_info_file))
2153 int errno_val = errno;
2154 notice ("%s: error closing aux info file `%s': %s\n",
2155 pname, shortpath (NULL, aux_info_filename),
2156 xstrerror (errno_val));
2157 free (aux_info_base);
2158 close (aux_info_file);
2159 return;
2163 /* Delete the aux_info file (unless requested not to). If the deletion
2164 fails for some reason, don't even worry about it. */
2166 if (must_create && !keep_it)
2167 if (unlink (aux_info_filename) == -1)
2169 int errno_val = errno;
2170 notice ("%s: can't delete aux info file `%s': %s\n",
2171 pname, shortpath (NULL, aux_info_filename),
2172 xstrerror (errno_val));
2175 /* Save a pointer into the first line of the aux_info file which
2176 contains the filename of the directory from which the compiler
2177 was invoked when the associated source file was compiled.
2178 This information is used later to help create complete
2179 filenames out of the (potentially) relative filenames in
2180 the aux_info file. */
2183 char *p = aux_info_base;
2185 while (*p != ':')
2186 p++;
2187 p++;
2188 while (*p == ' ')
2189 p++;
2190 invocation_filename = p; /* Save a pointer to first byte of path. */
2191 while (*p != ' ')
2192 p++;
2193 *p++ = '/';
2194 *p++ = '\0';
2195 while (*p++ != '\n')
2196 continue;
2197 aux_info_second_line = p;
2198 aux_info_relocated_name = 0;
2199 if (invocation_filename[0] != '/')
2201 /* INVOCATION_FILENAME is relative;
2202 append it to BASE_SOURCE_FILENAME's dir. */
2203 char *dir_end;
2204 aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
2205 strcpy (aux_info_relocated_name, base_source_filename);
2206 dir_end = strrchr (aux_info_relocated_name, '/');
2207 if (dir_end)
2208 dir_end++;
2209 else
2210 dir_end = aux_info_relocated_name;
2211 strcpy (dir_end, invocation_filename);
2212 invocation_filename = aux_info_relocated_name;
2218 const char *aux_info_p;
2220 /* Do a pre-pass on the lines in the aux_info file, making sure that all
2221 of the source files referenced in there are at least as old as this
2222 aux_info file itself. If not, go back and regenerate the aux_info
2223 file anew. Don't do any of this for the syscalls file. */
2225 if (!is_syscalls)
2227 current_aux_info_lineno = 2;
2229 for (aux_info_p = aux_info_second_line; *aux_info_p; )
2231 if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2233 free (aux_info_base);
2234 free (aux_info_relocated_name);
2235 if (keep_it && unlink (aux_info_filename) == -1)
2237 int errno_val = errno;
2238 notice ("%s: can't delete file `%s': %s\n",
2239 pname, shortpath (NULL, aux_info_filename),
2240 xstrerror (errno_val));
2241 return;
2243 must_create = 1;
2244 goto start_over;
2247 /* Skip over the rest of this line to start of next line. */
2249 while (*aux_info_p != '\n')
2250 aux_info_p++;
2251 aux_info_p++;
2252 current_aux_info_lineno++;
2256 /* Now do the real pass on the aux_info lines. Save their information in
2257 the in-core data base. */
2259 current_aux_info_lineno = 2;
2261 for (aux_info_p = aux_info_second_line; *aux_info_p;)
2263 char *unexpanded_line = unexpand_if_needed (aux_info_p);
2265 if (unexpanded_line)
2267 save_def_or_dec (unexpanded_line, is_syscalls);
2268 free (unexpanded_line);
2270 else
2271 save_def_or_dec (aux_info_p, is_syscalls);
2273 /* Skip over the rest of this line and get to start of next line. */
2275 while (*aux_info_p != '\n')
2276 aux_info_p++;
2277 aux_info_p++;
2278 current_aux_info_lineno++;
2282 free (aux_info_base);
2283 free (aux_info_relocated_name);
2286 #ifndef UNPROTOIZE
2288 /* Check an individual filename for a .c suffix. If the filename has this
2289 suffix, rename the file such that its suffix is changed to .C. This
2290 function implements the -C option. */
2292 static void
2293 rename_c_file (hp)
2294 const hash_table_entry *hp;
2296 const char *filename = hp->symbol;
2297 int last_char_index = strlen (filename) - 1;
2298 char *const new_filename = (char *) alloca (strlen (filename) + 1);
2300 /* Note that we don't care here if the given file was converted or not. It
2301 is possible that the given file was *not* converted, simply because there
2302 was nothing in it which actually required conversion. Even in this case,
2303 we want to do the renaming. Note that we only rename files with the .c
2304 suffix. */
2306 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.')
2307 return;
2309 strcpy (new_filename, filename);
2310 new_filename[last_char_index] = 'C';
2312 if (link (filename, new_filename) == -1)
2314 int errno_val = errno;
2315 notice ("%s: warning: can't link file `%s' to `%s': %s\n",
2316 pname, shortpath (NULL, filename),
2317 shortpath (NULL, new_filename), xstrerror (errno_val));
2318 errors++;
2319 return;
2322 if (unlink (filename) == -1)
2324 int errno_val = errno;
2325 notice ("%s: warning: can't delete file `%s': %s\n",
2326 pname, shortpath (NULL, filename), xstrerror (errno_val));
2327 errors++;
2328 return;
2332 #endif /* !defined (UNPROTOIZE) */
2334 /* Take the list of definitions and declarations attached to a particular
2335 file_info node and reverse the order of the list. This should get the
2336 list into an order such that the item with the lowest associated line
2337 number is nearest the head of the list. When these lists are originally
2338 built, they are in the opposite order. We want to traverse them in
2339 normal line number order later (i.e. lowest to highest) so reverse the
2340 order here. */
2342 static void
2343 reverse_def_dec_list (hp)
2344 const hash_table_entry *hp;
2346 file_info *file_p = hp->fip;
2347 def_dec_info *prev = NULL;
2348 def_dec_info *current = (def_dec_info *)file_p->defs_decs;
2350 if (!current)
2351 return; /* no list to reverse */
2353 prev = current;
2354 if (! (current = (def_dec_info *)current->next_in_file))
2355 return; /* can't reverse a single list element */
2357 prev->next_in_file = NULL;
2359 while (current)
2361 def_dec_info *next = (def_dec_info *)current->next_in_file;
2363 current->next_in_file = prev;
2364 prev = current;
2365 current = next;
2368 file_p->defs_decs = prev;
2371 #ifndef UNPROTOIZE
2373 /* Find the (only?) extern definition for a particular function name, starting
2374 from the head of the linked list of entries for the given name. If we
2375 cannot find an extern definition for the given function name, issue a
2376 warning and scrounge around for the next best thing, i.e. an extern
2377 function declaration with a prototype attached to it. Note that we only
2378 allow such substitutions for extern declarations and never for static
2379 declarations. That's because the only reason we allow them at all is
2380 to let un-prototyped function declarations for system-supplied library
2381 functions get their prototypes from our own extra SYSCALLS.c.X file which
2382 contains all of the correct prototypes for system functions. */
2384 static const def_dec_info *
2385 find_extern_def (head, user)
2386 const def_dec_info *head;
2387 const def_dec_info *user;
2389 const def_dec_info *dd_p;
2390 const def_dec_info *extern_def_p = NULL;
2391 int conflict_noted = 0;
2393 /* Don't act too stupid here. Somebody may try to convert an entire system
2394 in one swell fwoop (rather than one program at a time, as should be done)
2395 and in that case, we may find that there are multiple extern definitions
2396 of a given function name in the entire set of source files that we are
2397 converting. If however one of these definitions resides in exactly the
2398 same source file as the reference we are trying to satisfy then in that
2399 case it would be stupid for us to fail to realize that this one definition
2400 *must* be the precise one we are looking for.
2402 To make sure that we don't miss an opportunity to make this "same file"
2403 leap of faith, we do a prescan of the list of records relating to the
2404 given function name, and we look (on this first scan) *only* for a
2405 definition of the function which is in the same file as the reference
2406 we are currently trying to satisfy. */
2408 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2409 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2410 return dd_p;
2412 /* Now, since we have not found a definition in the same file as the
2413 reference, we scan the list again and consider all possibilities from
2414 all files. Here we may get conflicts with the things listed in the
2415 SYSCALLS.c.X file, but if that happens it only means that the source
2416 code being converted contains its own definition of a function which
2417 could have been supplied by libc.a. In such cases, we should avoid
2418 issuing the normal warning, and defer to the definition given in the
2419 user's own code. */
2421 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2422 if (dd_p->is_func_def && !dd_p->is_static)
2424 if (!extern_def_p) /* Previous definition? */
2425 extern_def_p = dd_p; /* Remember the first definition found. */
2426 else
2428 /* Ignore definition just found if it came from SYSCALLS.c.X. */
2430 if (is_syscalls_file (dd_p->file))
2431 continue;
2433 /* Quietly replace the definition previously found with the one
2434 just found if the previous one was from SYSCALLS.c.X. */
2436 if (is_syscalls_file (extern_def_p->file))
2438 extern_def_p = dd_p;
2439 continue;
2442 /* If we get here, then there is a conflict between two function
2443 declarations for the same function, both of which came from the
2444 user's own code. */
2446 if (!conflict_noted) /* first time we noticed? */
2448 conflict_noted = 1;
2449 notice ("%s: conflicting extern definitions of '%s'\n",
2450 pname, head->hash_entry->symbol);
2451 if (!quiet_flag)
2453 notice ("%s: declarations of '%s' will not be converted\n",
2454 pname, head->hash_entry->symbol);
2455 notice ("%s: conflict list for '%s' follows:\n",
2456 pname, head->hash_entry->symbol);
2457 fprintf (stderr, "%s: %s(%d): %s\n",
2458 pname,
2459 shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2460 extern_def_p->line, extern_def_p->ansi_decl);
2463 if (!quiet_flag)
2464 fprintf (stderr, "%s: %s(%d): %s\n",
2465 pname,
2466 shortpath (NULL, dd_p->file->hash_entry->symbol),
2467 dd_p->line, dd_p->ansi_decl);
2471 /* We want to err on the side of caution, so if we found multiple conflicting
2472 definitions for the same function, treat this as being that same as if we
2473 had found no definitions (i.e. return NULL). */
2475 if (conflict_noted)
2476 return NULL;
2478 if (!extern_def_p)
2480 /* We have no definitions for this function so do the next best thing.
2481 Search for an extern declaration already in prototype form. */
2483 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2484 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2486 extern_def_p = dd_p; /* save a pointer to the definition */
2487 if (!quiet_flag)
2488 notice ("%s: warning: using formals list from %s(%d) for function `%s'\n",
2489 pname,
2490 shortpath (NULL, dd_p->file->hash_entry->symbol),
2491 dd_p->line, dd_p->hash_entry->symbol);
2492 break;
2495 /* Gripe about unprototyped function declarations that we found no
2496 corresponding definition (or other source of prototype information)
2497 for.
2499 Gripe even if the unprototyped declaration we are worried about
2500 exists in a file in one of the "system" include directories. We
2501 can gripe about these because we should have at least found a
2502 corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
2503 didn't, then that means that the SYSCALLS.c.X file is missing some
2504 needed prototypes for this particular system. That is worth telling
2505 the user about! */
2507 if (!extern_def_p)
2509 const char *file = user->file->hash_entry->symbol;
2511 if (!quiet_flag)
2512 if (in_system_include_dir (file))
2514 /* Why copy this string into `needed' at all?
2515 Why not just use user->ansi_decl without copying? */
2516 char *needed = (char *) alloca (strlen (user->ansi_decl) + 1);
2517 char *p;
2519 strcpy (needed, user->ansi_decl);
2520 p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
2521 + strlen (user->hash_entry->symbol) + 2;
2522 /* Avoid having ??? in the string. */
2523 *p++ = '?';
2524 *p++ = '?';
2525 *p++ = '?';
2526 strcpy (p, ");");
2528 notice ("%s: %d: `%s' used but missing from SYSCALLS\n",
2529 shortpath (NULL, file), user->line,
2530 needed+7); /* Don't print "extern " */
2532 #if 0
2533 else
2534 notice ("%s: %d: warning: no extern definition for `%s'\n",
2535 shortpath (NULL, file), user->line,
2536 user->hash_entry->symbol);
2537 #endif
2540 return extern_def_p;
2543 /* Find the (only?) static definition for a particular function name in a
2544 given file. Here we get the function-name and the file info indirectly
2545 from the def_dec_info record pointer which is passed in. */
2547 static const def_dec_info *
2548 find_static_definition (user)
2549 const def_dec_info *user;
2551 const def_dec_info *head = user->hash_entry->ddip;
2552 const def_dec_info *dd_p;
2553 int num_static_defs = 0;
2554 const def_dec_info *static_def_p = NULL;
2556 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2557 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2559 static_def_p = dd_p; /* save a pointer to the definition */
2560 num_static_defs++;
2562 if (num_static_defs == 0)
2564 if (!quiet_flag)
2565 notice ("%s: warning: no static definition for `%s' in file `%s'\n",
2566 pname, head->hash_entry->symbol,
2567 shortpath (NULL, user->file->hash_entry->symbol));
2569 else if (num_static_defs > 1)
2571 notice ("%s: multiple static defs of `%s' in file `%s'\n",
2572 pname, head->hash_entry->symbol,
2573 shortpath (NULL, user->file->hash_entry->symbol));
2574 return NULL;
2576 return static_def_p;
2579 /* Find good prototype style formal argument lists for all of the function
2580 declarations which didn't have them before now.
2582 To do this we consider each function name one at a time. For each function
2583 name, we look at the items on the linked list of def_dec_info records for
2584 that particular name.
2586 Somewhere on this list we should find one (and only one) def_dec_info
2587 record which represents the actual function definition, and this record
2588 should have a nice formal argument list already associated with it.
2590 Thus, all we have to do is to connect up all of the other def_dec_info
2591 records for this particular function name to the special one which has
2592 the full-blown formals list.
2594 Of course it is a little more complicated than just that. See below for
2595 more details. */
2597 static void
2598 connect_defs_and_decs (hp)
2599 const hash_table_entry *hp;
2601 const def_dec_info *dd_p;
2602 const def_dec_info *extern_def_p = NULL;
2603 int first_extern_reference = 1;
2605 /* Traverse the list of definitions and declarations for this particular
2606 function name. For each item on the list, if it is a function
2607 definition (either old style or new style) then GCC has already been
2608 kind enough to produce a prototype for us, and it is associated with
2609 the item already, so declare the item as its own associated "definition".
2611 Also, for each item which is only a function declaration, but which
2612 nonetheless has its own prototype already (obviously supplied by the user)
2613 declare the item as its own definition.
2615 Note that when/if there are multiple user-supplied prototypes already
2616 present for multiple declarations of any given function, these multiple
2617 prototypes *should* all match exactly with one another and with the
2618 prototype for the actual function definition. We don't check for this
2619 here however, since we assume that the compiler must have already done
2620 this consistency checking when it was creating the .X files. */
2622 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2623 if (dd_p->prototyped)
2624 ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2626 /* Traverse the list of definitions and declarations for this particular
2627 function name. For each item on the list, if it is an extern function
2628 declaration and if it has no associated definition yet, go try to find
2629 the matching extern definition for the declaration.
2631 When looking for the matching function definition, warn the user if we
2632 fail to find one.
2634 If we find more that one function definition also issue a warning.
2636 Do the search for the matching definition only once per unique function
2637 name (and only when absolutely needed) so that we can avoid putting out
2638 redundant warning messages, and so that we will only put out warning
2639 messages when there is actually a reference (i.e. a declaration) for
2640 which we need to find a matching definition. */
2642 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2643 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2645 if (first_extern_reference)
2647 extern_def_p = find_extern_def (hp->ddip, dd_p);
2648 first_extern_reference = 0;
2650 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2653 /* Traverse the list of definitions and declarations for this particular
2654 function name. For each item on the list, if it is a static function
2655 declaration and if it has no associated definition yet, go try to find
2656 the matching static definition for the declaration within the same file.
2658 When looking for the matching function definition, warn the user if we
2659 fail to find one in the same file with the declaration, and refuse to
2660 convert this kind of cross-file static function declaration. After all,
2661 this is stupid practice and should be discouraged.
2663 We don't have to worry about the possibility that there is more than one
2664 matching function definition in the given file because that would have
2665 been flagged as an error by the compiler.
2667 Do the search for the matching definition only once per unique
2668 function-name/source-file pair (and only when absolutely needed) so that
2669 we can avoid putting out redundant warning messages, and so that we will
2670 only put out warning messages when there is actually a reference (i.e. a
2671 declaration) for which we actually need to find a matching definition. */
2673 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2674 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2676 const def_dec_info *dd_p2;
2677 const def_dec_info *static_def;
2679 /* We have now found a single static declaration for which we need to
2680 find a matching definition. We want to minimize the work (and the
2681 number of warnings), so we will find an appropriate (matching)
2682 static definition for this declaration, and then distribute it
2683 (as the definition for) any and all other static declarations
2684 for this function name which occur within the same file, and which
2685 do not already have definitions.
2687 Note that a trick is used here to prevent subsequent attempts to
2688 call find_static_definition for a given function-name & file
2689 if the first such call returns NULL. Essentially, we convert
2690 these NULL return values to -1, and put the -1 into the definition
2691 field for each other static declaration from the same file which
2692 does not already have an associated definition.
2693 This makes these other static declarations look like they are
2694 actually defined already when the outer loop here revisits them
2695 later on. Thus, the outer loop will skip over them. Later, we
2696 turn the -1's back to NULL's. */
2698 ((NONCONST def_dec_info *) dd_p)->definition =
2699 (static_def = find_static_definition (dd_p))
2700 ? static_def
2701 : (const def_dec_info *) -1;
2703 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2704 if (!dd_p2->is_func_def && dd_p2->is_static
2705 && !dd_p2->definition && (dd_p2->file == dd_p->file))
2706 ((NONCONST def_dec_info *)dd_p2)->definition = dd_p->definition;
2709 /* Convert any dummy (-1) definitions we created in the step above back to
2710 NULL's (as they should be). */
2712 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2713 if (dd_p->definition == (def_dec_info *) -1)
2714 ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2717 #endif /* !defined (UNPROTOIZE) */
2719 /* Give a pointer into the clean text buffer, return a number which is the
2720 original source line number that the given pointer points into. */
2722 static int
2723 identify_lineno (clean_p)
2724 const char *clean_p;
2726 int line_num = 1;
2727 const char *scan_p;
2729 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2730 if (*scan_p == '\n')
2731 line_num++;
2732 return line_num;
2735 /* Issue an error message and give up on doing this particular edit. */
2737 static void
2738 declare_source_confusing (clean_p)
2739 const char *clean_p;
2741 if (!quiet_flag)
2743 if (clean_p == 0)
2744 notice ("%s: %d: warning: source too confusing\n",
2745 shortpath (NULL, convert_filename), last_known_line_number);
2746 else
2747 notice ("%s: %d: warning: source too confusing\n",
2748 shortpath (NULL, convert_filename),
2749 identify_lineno (clean_p));
2751 longjmp (source_confusion_recovery, 1);
2754 /* Check that a condition which is expected to be true in the original source
2755 code is in fact true. If not, issue an error message and give up on
2756 converting this particular source file. */
2758 static void
2759 check_source (cond, clean_p)
2760 int cond;
2761 const char *clean_p;
2763 if (!cond)
2764 declare_source_confusing (clean_p);
2767 /* If we think of the in-core cleaned text buffer as a memory mapped
2768 file (with the variable last_known_line_start acting as sort of a
2769 file pointer) then we can imagine doing "seeks" on the buffer. The
2770 following routine implements a kind of "seek" operation for the in-core
2771 (cleaned) copy of the source file. When finished, it returns a pointer to
2772 the start of a given (numbered) line in the cleaned text buffer.
2774 Note that protoize only has to "seek" in the forward direction on the
2775 in-core cleaned text file buffers, and it never needs to back up.
2777 This routine is made a little bit faster by remembering the line number
2778 (and pointer value) supplied (and returned) from the previous "seek".
2779 This prevents us from always having to start all over back at the top
2780 of the in-core cleaned buffer again. */
2782 static const char *
2783 seek_to_line (n)
2784 int n;
2786 if (n < last_known_line_number)
2787 abort ();
2789 while (n > last_known_line_number)
2791 while (*last_known_line_start != '\n')
2792 check_source (++last_known_line_start < clean_text_limit, 0);
2793 last_known_line_start++;
2794 last_known_line_number++;
2796 return last_known_line_start;
2799 /* Given a pointer to a character in the cleaned text buffer, return a pointer
2800 to the next non-whitespace character which follows it. */
2802 static const char *
2803 forward_to_next_token_char (ptr)
2804 const char *ptr;
2806 for (++ptr; ISSPACE ((const unsigned char)*ptr);
2807 check_source (++ptr < clean_text_limit, 0))
2808 continue;
2809 return ptr;
2812 /* Copy a chunk of text of length `len' and starting at `str' to the current
2813 output buffer. Note that all attempts to add stuff to the current output
2814 buffer ultimately go through here. */
2816 static void
2817 output_bytes (str, len)
2818 const char *str;
2819 size_t len;
2821 if ((repl_write_ptr + 1) + len >= repl_text_limit)
2823 size_t new_size = (repl_text_limit - repl_text_base) << 1;
2824 char *new_buf = (char *) xrealloc (repl_text_base, new_size);
2826 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
2827 repl_text_base = new_buf;
2828 repl_text_limit = new_buf + new_size;
2830 memcpy (repl_write_ptr + 1, str, len);
2831 repl_write_ptr += len;
2834 /* Copy all bytes (except the trailing null) of a null terminated string to
2835 the current output buffer. */
2837 static void
2838 output_string (str)
2839 const char *str;
2841 output_bytes (str, strlen (str));
2844 /* Copy some characters from the original text buffer to the current output
2845 buffer.
2847 This routine takes a pointer argument `p' which is assumed to be a pointer
2848 into the cleaned text buffer. The bytes which are copied are the `original'
2849 equivalents for the set of bytes between the last value of `clean_read_ptr'
2850 and the argument value `p'.
2852 The set of bytes copied however, comes *not* from the cleaned text buffer,
2853 but rather from the direct counterparts of these bytes within the original
2854 text buffer.
2856 Thus, when this function is called, some bytes from the original text
2857 buffer (which may include original comments and preprocessing directives)
2858 will be copied into the output buffer.
2860 Note that the request implied when this routine is called includes the
2861 byte pointed to by the argument pointer `p'. */
2863 static void
2864 output_up_to (p)
2865 const char *p;
2867 size_t copy_length = (size_t) (p - clean_read_ptr);
2868 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
2870 if (copy_length == 0)
2871 return;
2873 output_bytes (copy_start, copy_length);
2874 clean_read_ptr = p;
2877 /* Given a pointer to a def_dec_info record which represents some form of
2878 definition of a function (perhaps a real definition, or in lieu of that
2879 perhaps just a declaration with a full prototype) return true if this
2880 function is one which we should avoid converting. Return false
2881 otherwise. */
2883 static int
2884 other_variable_style_function (ansi_header)
2885 const char *ansi_header;
2887 #ifdef UNPROTOIZE
2889 /* See if we have a stdarg function, or a function which has stdarg style
2890 parameters or a stdarg style return type. */
2892 return substr (ansi_header, "...") != 0;
2894 #else /* !defined (UNPROTOIZE) */
2896 /* See if we have a varargs function, or a function which has varargs style
2897 parameters or a varargs style return type. */
2899 const char *p;
2900 int len = strlen (varargs_style_indicator);
2902 for (p = ansi_header; p; )
2904 const char *candidate;
2906 if ((candidate = substr (p, varargs_style_indicator)) == 0)
2907 return 0;
2908 else
2909 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
2910 return 1;
2911 else
2912 p = candidate + 1;
2914 return 0;
2915 #endif /* !defined (UNPROTOIZE) */
2918 /* Do the editing operation specifically for a function "declaration". Note
2919 that editing for function "definitions" are handled in a separate routine
2920 below. */
2922 static void
2923 edit_fn_declaration (def_dec_p, clean_text_p)
2924 const def_dec_info *def_dec_p;
2925 const char *volatile clean_text_p;
2927 const char *start_formals;
2928 const char *end_formals;
2929 const char *function_to_edit = def_dec_p->hash_entry->symbol;
2930 size_t func_name_len = strlen (function_to_edit);
2931 const char *end_of_fn_name;
2933 #ifndef UNPROTOIZE
2935 const f_list_chain_item *this_f_list_chain_item;
2936 const def_dec_info *definition = def_dec_p->definition;
2938 /* If we are protoizing, and if we found no corresponding definition for
2939 this particular function declaration, then just leave this declaration
2940 exactly as it is. */
2942 if (!definition)
2943 return;
2945 /* If we are protoizing, and if the corresponding definition that we found
2946 for this particular function declaration defined an old style varargs
2947 function, then we want to issue a warning and just leave this function
2948 declaration unconverted. */
2950 if (other_variable_style_function (definition->ansi_decl))
2952 if (!quiet_flag)
2953 notice ("%s: %d: warning: varargs function declaration not converted\n",
2954 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
2955 def_dec_p->line);
2956 return;
2959 #endif /* !defined (UNPROTOIZE) */
2961 /* Setup here to recover from confusing source code detected during this
2962 particular "edit". */
2964 save_pointers ();
2965 if (setjmp (source_confusion_recovery))
2967 restore_pointers ();
2968 notice ("%s: declaration of function `%s' not converted\n",
2969 pname, function_to_edit);
2970 return;
2973 /* We are editing a function declaration. The line number we did a seek to
2974 contains the comma or semicolon which follows the declaration. Our job
2975 now is to scan backwards looking for the function name. This name *must*
2976 be followed by open paren (ignoring whitespace, of course). We need to
2977 replace everything between that open paren and the corresponding closing
2978 paren. If we are protoizing, we need to insert the prototype-style
2979 formals lists. If we are unprotoizing, we need to just delete everything
2980 between the pairs of opening and closing parens. */
2982 /* First move up to the end of the line. */
2984 while (*clean_text_p != '\n')
2985 check_source (++clean_text_p < clean_text_limit, 0);
2986 clean_text_p--; /* Point to just before the newline character. */
2988 /* Now we can scan backwards for the function name. */
2992 for (;;)
2994 /* Scan leftwards until we find some character which can be
2995 part of an identifier. */
2997 while (!is_id_char (*clean_text_p))
2998 check_source (--clean_text_p > clean_read_ptr, 0);
3000 /* Scan backwards until we find a char that cannot be part of an
3001 identifier. */
3003 while (is_id_char (*clean_text_p))
3004 check_source (--clean_text_p > clean_read_ptr, 0);
3006 /* Having found an "id break", see if the following id is the one
3007 that we are looking for. If so, then exit from this loop. */
3009 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
3011 char ch = *(clean_text_p + 1 + func_name_len);
3013 /* Must also check to see that the name in the source text
3014 ends where it should (in order to prevent bogus matches
3015 on similar but longer identifiers. */
3017 if (! is_id_char (ch))
3018 break; /* exit from loop */
3022 /* We have now found the first perfect match for the function name in
3023 our backward search. This may or may not be the actual function
3024 name at the start of the actual function declaration (i.e. we could
3025 have easily been mislead). We will try to avoid getting fooled too
3026 often by looking forward for the open paren which should follow the
3027 identifier we just found. We ignore whitespace while hunting. If
3028 the next non-whitespace byte we see is *not* an open left paren,
3029 then we must assume that we have been fooled and we start over
3030 again accordingly. Note that there is no guarantee, that even if
3031 we do see the open paren, that we are in the right place.
3032 Programmers do the strangest things sometimes! */
3034 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
3035 start_formals = forward_to_next_token_char (end_of_fn_name);
3037 while (*start_formals != '(');
3039 /* start_of_formals now points to the opening left paren which immediately
3040 follows the name of the function. */
3042 /* Note that there may be several formals lists which need to be modified
3043 due to the possibility that the return type of this function is a
3044 pointer-to-function type. If there are several formals lists, we
3045 convert them in left-to-right order here. */
3047 #ifndef UNPROTOIZE
3048 this_f_list_chain_item = definition->f_list_chain;
3049 #endif /* !defined (UNPROTOIZE) */
3051 for (;;)
3054 int depth;
3056 end_formals = start_formals + 1;
3057 depth = 1;
3058 for (; depth; check_source (++end_formals < clean_text_limit, 0))
3060 switch (*end_formals)
3062 case '(':
3063 depth++;
3064 break;
3065 case ')':
3066 depth--;
3067 break;
3070 end_formals--;
3073 /* end_formals now points to the closing right paren of the formals
3074 list whose left paren is pointed to by start_formals. */
3076 /* Now, if we are protoizing, we insert the new ANSI-style formals list
3077 attached to the associated definition of this function. If however
3078 we are unprotoizing, then we simply delete any formals list which
3079 may be present. */
3081 output_up_to (start_formals);
3082 #ifndef UNPROTOIZE
3083 if (this_f_list_chain_item)
3085 output_string (this_f_list_chain_item->formals_list);
3086 this_f_list_chain_item = this_f_list_chain_item->chain_next;
3088 else
3090 if (!quiet_flag)
3091 notice ("%s: warning: too many parameter lists in declaration of `%s'\n",
3092 pname, def_dec_p->hash_entry->symbol);
3093 check_source (0, end_formals); /* leave the declaration intact */
3095 #endif /* !defined (UNPROTOIZE) */
3096 clean_read_ptr = end_formals - 1;
3098 /* Now see if it looks like there may be another formals list associated
3099 with the function declaration that we are converting (following the
3100 formals list that we just converted. */
3103 const char *another_r_paren = forward_to_next_token_char (end_formals);
3105 if ((*another_r_paren != ')')
3106 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3108 #ifndef UNPROTOIZE
3109 if (this_f_list_chain_item)
3111 if (!quiet_flag)
3112 notice ("\n%s: warning: too few parameter lists in declaration of `%s'\n",
3113 pname, def_dec_p->hash_entry->symbol);
3114 check_source (0, start_formals); /* leave the decl intact */
3116 #endif /* !defined (UNPROTOIZE) */
3117 break;
3122 /* There does appear to be yet another formals list, so loop around
3123 again, and convert it also. */
3127 /* Edit a whole group of formals lists, starting with the rightmost one
3128 from some set of formals lists. This routine is called once (from the
3129 outside) for each function declaration which is converted. It is
3130 recursive however, and it calls itself once for each remaining formal
3131 list that lies to the left of the one it was originally called to work
3132 on. Thus, a whole set gets done in right-to-left order.
3134 This routine returns non-zero if it thinks that it should not be trying
3135 to convert this particular function definition (because the name of the
3136 function doesn't match the one expected). */
3138 static int
3139 edit_formals_lists (end_formals, f_list_count, def_dec_p)
3140 const char *end_formals;
3141 unsigned int f_list_count;
3142 const def_dec_info *def_dec_p;
3144 const char *start_formals;
3145 int depth;
3147 start_formals = end_formals - 1;
3148 depth = 1;
3149 for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3151 switch (*start_formals)
3153 case '(':
3154 depth--;
3155 break;
3156 case ')':
3157 depth++;
3158 break;
3161 start_formals++;
3163 /* start_formals now points to the opening left paren of the formals list. */
3165 f_list_count--;
3167 if (f_list_count)
3169 const char *next_end;
3171 /* There should be more formal lists to the left of here. */
3173 next_end = start_formals - 1;
3174 check_source (next_end > clean_read_ptr, 0);
3175 while (ISSPACE ((const unsigned char)*next_end))
3176 check_source (--next_end > clean_read_ptr, 0);
3177 check_source (*next_end == ')', next_end);
3178 check_source (--next_end > clean_read_ptr, 0);
3179 check_source (*next_end == ')', next_end);
3180 if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3181 return 1;
3184 /* Check that the function name in the header we are working on is the same
3185 as the one we would expect to find. If not, issue a warning and return
3186 non-zero. */
3188 if (f_list_count == 0)
3190 const char *expected = def_dec_p->hash_entry->symbol;
3191 const char *func_name_start;
3192 const char *func_name_limit;
3193 size_t func_name_len;
3195 for (func_name_limit = start_formals-1;
3196 ISSPACE ((const unsigned char)*func_name_limit); )
3197 check_source (--func_name_limit > clean_read_ptr, 0);
3199 for (func_name_start = func_name_limit++;
3200 is_id_char (*func_name_start);
3201 func_name_start--)
3202 check_source (func_name_start > clean_read_ptr, 0);
3203 func_name_start++;
3204 func_name_len = func_name_limit - func_name_start;
3205 if (func_name_len == 0)
3206 check_source (0, func_name_start);
3207 if (func_name_len != strlen (expected)
3208 || strncmp (func_name_start, expected, func_name_len))
3210 notice ("%s: %d: warning: found `%s' but expected `%s'\n",
3211 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3212 identify_lineno (func_name_start),
3213 dupnstr (func_name_start, func_name_len),
3214 expected);
3215 return 1;
3219 output_up_to (start_formals);
3221 #ifdef UNPROTOIZE
3222 if (f_list_count == 0)
3223 output_string (def_dec_p->formal_names);
3224 #else /* !defined (UNPROTOIZE) */
3226 unsigned f_list_depth;
3227 const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3229 /* At this point, the current value of f_list count says how many
3230 links we have to follow through the f_list_chain to get to the
3231 particular formals list that we need to output next. */
3233 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3234 flci_p = flci_p->chain_next;
3235 output_string (flci_p->formals_list);
3237 #endif /* !defined (UNPROTOIZE) */
3239 clean_read_ptr = end_formals - 1;
3240 return 0;
3243 /* Given a pointer to a byte in the clean text buffer which points to
3244 the beginning of a line that contains a "follower" token for a
3245 function definition header, do whatever is necessary to find the
3246 right closing paren for the rightmost formals list of the function
3247 definition header. */
3249 static const char *
3250 find_rightmost_formals_list (clean_text_p)
3251 const char *clean_text_p;
3253 const char *end_formals;
3255 /* We are editing a function definition. The line number we did a seek
3256 to contains the first token which immediately follows the entire set of
3257 formals lists which are part of this particular function definition
3258 header.
3260 Our job now is to scan leftwards in the clean text looking for the
3261 right-paren which is at the end of the function header's rightmost
3262 formals list.
3264 If we ignore whitespace, this right paren should be the first one we
3265 see which is (ignoring whitespace) immediately followed either by the
3266 open curly-brace beginning the function body or by an alphabetic
3267 character (in the case where the function definition is in old (K&R)
3268 style and there are some declarations of formal parameters). */
3270 /* It is possible that the right paren we are looking for is on the
3271 current line (together with its following token). Just in case that
3272 might be true, we start out here by skipping down to the right end of
3273 the current line before starting our scan. */
3275 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3276 continue;
3277 end_formals--;
3279 #ifdef UNPROTOIZE
3281 /* Now scan backwards while looking for the right end of the rightmost
3282 formals list associated with this function definition. */
3285 char ch;
3286 const char *l_brace_p;
3288 /* Look leftward and try to find a right-paren. */
3290 while (*end_formals != ')')
3292 if (ISSPACE ((unsigned char)*end_formals))
3293 while (ISSPACE ((unsigned char)*end_formals))
3294 check_source (--end_formals > clean_read_ptr, 0);
3295 else
3296 check_source (--end_formals > clean_read_ptr, 0);
3299 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3300 /* Since we are unprotoizing an ANSI-style (prototyped) function
3301 definition, there had better not be anything (except whitespace)
3302 between the end of the ANSI formals list and the beginning of the
3303 function body (i.e. the '{'). */
3305 check_source (ch == '{', l_brace_p);
3308 #else /* !defined (UNPROTOIZE) */
3310 /* Now scan backwards while looking for the right end of the rightmost
3311 formals list associated with this function definition. */
3313 while (1)
3315 char ch;
3316 const char *l_brace_p;
3318 /* Look leftward and try to find a right-paren. */
3320 while (*end_formals != ')')
3322 if (ISSPACE ((const unsigned char)*end_formals))
3323 while (ISSPACE ((const unsigned char)*end_formals))
3324 check_source (--end_formals > clean_read_ptr, 0);
3325 else
3326 check_source (--end_formals > clean_read_ptr, 0);
3329 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3331 /* Since it is possible that we found a right paren before the starting
3332 '{' of the body which IS NOT the one at the end of the real K&R
3333 formals list (say for instance, we found one embedded inside one of
3334 the old K&R formal parameter declarations) we have to check to be
3335 sure that this is in fact the right paren that we were looking for.
3337 The one we were looking for *must* be followed by either a '{' or
3338 by an alphabetic character, while others *cannot* validly be followed
3339 by such characters. */
3341 if ((ch == '{') || ISALPHA ((unsigned char)ch))
3342 break;
3344 /* At this point, we have found a right paren, but we know that it is
3345 not the one we were looking for, so backup one character and keep
3346 looking. */
3348 check_source (--end_formals > clean_read_ptr, 0);
3351 #endif /* !defined (UNPROTOIZE) */
3353 return end_formals;
3356 #ifndef UNPROTOIZE
3358 /* Insert into the output file a totally new declaration for a function
3359 which (up until now) was being called from within the current block
3360 without having been declared at any point such that the declaration
3361 was visible (i.e. in scope) at the point of the call.
3363 We need to add in explicit declarations for all such function calls
3364 in order to get the full benefit of prototype-based function call
3365 parameter type checking. */
3367 static void
3368 add_local_decl (def_dec_p, clean_text_p)
3369 const def_dec_info *def_dec_p;
3370 const char *clean_text_p;
3372 const char *start_of_block;
3373 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3375 /* Don't insert new local explicit declarations unless explicitly requested
3376 to do so. */
3378 if (!local_flag)
3379 return;
3381 /* Setup here to recover from confusing source code detected during this
3382 particular "edit". */
3384 save_pointers ();
3385 if (setjmp (source_confusion_recovery))
3387 restore_pointers ();
3388 notice ("%s: local declaration for function `%s' not inserted\n",
3389 pname, function_to_edit);
3390 return;
3393 /* We have already done a seek to the start of the line which should
3394 contain *the* open curly brace which begins the block in which we need
3395 to insert an explicit function declaration (to replace the implicit one).
3397 Now we scan that line, starting from the left, until we find the
3398 open curly brace we are looking for. Note that there may actually be
3399 multiple open curly braces on the given line, but we will be happy
3400 with the leftmost one no matter what. */
3402 start_of_block = clean_text_p;
3403 while (*start_of_block != '{' && *start_of_block != '\n')
3404 check_source (++start_of_block < clean_text_limit, 0);
3406 /* Note that the line from the original source could possibly
3407 contain *no* open curly braces! This happens if the line contains
3408 a macro call which expands into a chunk of text which includes a
3409 block (and that block's associated open and close curly braces).
3410 In cases like this, we give up, issue a warning, and do nothing. */
3412 if (*start_of_block != '{')
3414 if (!quiet_flag)
3415 notice ("\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
3416 def_dec_p->file->hash_entry->symbol, def_dec_p->line,
3417 def_dec_p->hash_entry->symbol);
3418 return;
3421 /* Figure out what a nice (pretty) indentation would be for the new
3422 declaration we are adding. In order to do this, we must scan forward
3423 from the '{' until we find the first line which starts with some
3424 non-whitespace characters (i.e. real "token" material). */
3427 const char *ep = forward_to_next_token_char (start_of_block) - 1;
3428 const char *sp;
3430 /* Now we have ep pointing at the rightmost byte of some existing indent
3431 stuff. At least that is the hope.
3433 We can now just scan backwards and find the left end of the existing
3434 indentation string, and then copy it to the output buffer. */
3436 for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--)
3437 continue;
3439 /* Now write out the open { which began this block, and any following
3440 trash up to and including the last byte of the existing indent that
3441 we just found. */
3443 output_up_to (ep);
3445 /* Now we go ahead and insert the new declaration at this point.
3447 If the definition of the given function is in the same file that we
3448 are currently editing, and if its full ANSI declaration normally
3449 would start with the keyword `extern', suppress the `extern'. */
3452 const char *decl = def_dec_p->definition->ansi_decl;
3454 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
3455 decl += 7;
3456 output_string (decl);
3459 /* Finally, write out a new indent string, just like the preceding one
3460 that we found. This will typically include a newline as the first
3461 character of the indent string. */
3463 output_bytes (sp, (size_t) (ep - sp) + 1);
3467 /* Given a pointer to a file_info record, and a pointer to the beginning
3468 of a line (in the clean text buffer) which is assumed to contain the
3469 first "follower" token for the first function definition header in the
3470 given file, find a good place to insert some new global function
3471 declarations (which will replace scattered and imprecise implicit ones)
3472 and then insert the new explicit declaration at that point in the file. */
3474 static void
3475 add_global_decls (file_p, clean_text_p)
3476 const file_info *file_p;
3477 const char *clean_text_p;
3479 const def_dec_info *dd_p;
3480 const char *scan_p;
3482 /* Setup here to recover from confusing source code detected during this
3483 particular "edit". */
3485 save_pointers ();
3486 if (setjmp (source_confusion_recovery))
3488 restore_pointers ();
3489 notice ("%s: global declarations for file `%s' not inserted\n",
3490 pname, shortpath (NULL, file_p->hash_entry->symbol));
3491 return;
3494 /* Start by finding a good location for adding the new explicit function
3495 declarations. To do this, we scan backwards, ignoring whitespace
3496 and comments and other junk until we find either a semicolon, or until
3497 we hit the beginning of the file. */
3499 scan_p = find_rightmost_formals_list (clean_text_p);
3500 for (;; --scan_p)
3502 if (scan_p < clean_text_base)
3503 break;
3504 check_source (scan_p > clean_read_ptr, 0);
3505 if (*scan_p == ';')
3506 break;
3509 /* scan_p now points either to a semicolon, or to just before the start
3510 of the whole file. */
3512 /* Now scan forward for the first non-whitespace character. In theory,
3513 this should be the first character of the following function definition
3514 header. We will put in the added declarations just prior to that. */
3516 scan_p++;
3517 while (ISSPACE ((const unsigned char)*scan_p))
3518 scan_p++;
3519 scan_p--;
3521 output_up_to (scan_p);
3523 /* Now write out full prototypes for all of the things that had been
3524 implicitly declared in this file (but only those for which we were
3525 actually able to find unique matching definitions). Avoid duplicates
3526 by marking things that we write out as we go. */
3529 int some_decls_added = 0;
3531 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3532 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
3534 const char *decl = dd_p->definition->ansi_decl;
3536 /* If the function for which we are inserting a declaration is
3537 actually defined later in the same file, then suppress the
3538 leading `extern' keyword (if there is one). */
3540 if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
3541 decl += 7;
3543 output_string ("\n");
3544 output_string (decl);
3545 some_decls_added = 1;
3546 ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
3548 if (some_decls_added)
3549 output_string ("\n\n");
3552 /* Unmark all of the definitions that we just marked. */
3554 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3555 if (dd_p->definition)
3556 ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
3559 #endif /* !defined (UNPROTOIZE) */
3561 /* Do the editing operation specifically for a function "definition". Note
3562 that editing operations for function "declarations" are handled by a
3563 separate routine above. */
3565 static void
3566 edit_fn_definition (def_dec_p, clean_text_p)
3567 const def_dec_info *def_dec_p;
3568 const char *clean_text_p;
3570 const char *end_formals;
3571 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3573 /* Setup here to recover from confusing source code detected during this
3574 particular "edit". */
3576 save_pointers ();
3577 if (setjmp (source_confusion_recovery))
3579 restore_pointers ();
3580 notice ("%s: definition of function `%s' not converted\n",
3581 pname, function_to_edit);
3582 return;
3585 end_formals = find_rightmost_formals_list (clean_text_p);
3587 /* end_of_formals now points to the closing right paren of the rightmost
3588 formals list which is actually part of the `header' of the function
3589 definition that we are converting. */
3591 /* If the header of this function definition looks like it declares a
3592 function with a variable number of arguments, and if the way it does
3593 that is different from that way we would like it (i.e. varargs vs.
3594 stdarg) then issue a warning and leave the header unconverted. */
3596 if (other_variable_style_function (def_dec_p->ansi_decl))
3598 if (!quiet_flag)
3599 notice ("%s: %d: warning: definition of %s not converted\n",
3600 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3601 identify_lineno (end_formals),
3602 other_var_style);
3603 output_up_to (end_formals);
3604 return;
3607 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
3609 restore_pointers ();
3610 notice ("%s: definition of function `%s' not converted\n",
3611 pname, function_to_edit);
3612 return;
3615 /* Have to output the last right paren because this never gets flushed by
3616 edit_formals_list. */
3618 output_up_to (end_formals);
3620 #ifdef UNPROTOIZE
3622 const char *decl_p;
3623 const char *semicolon_p;
3624 const char *limit_p;
3625 const char *scan_p;
3626 int had_newlines = 0;
3628 /* Now write out the K&R style formal declarations, one per line. */
3630 decl_p = def_dec_p->formal_decls;
3631 limit_p = decl_p + strlen (decl_p);
3632 for (;decl_p < limit_p; decl_p = semicolon_p + 2)
3634 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
3635 continue;
3636 output_string ("\n");
3637 output_string (indent_string);
3638 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
3641 /* If there are no newlines between the end of the formals list and the
3642 start of the body, we should insert one now. */
3644 for (scan_p = end_formals+1; *scan_p != '{'; )
3646 if (*scan_p == '\n')
3648 had_newlines = 1;
3649 break;
3651 check_source (++scan_p < clean_text_limit, 0);
3653 if (!had_newlines)
3654 output_string ("\n");
3656 #else /* !defined (UNPROTOIZE) */
3657 /* If we are protoizing, there may be some flotsam & jetsam (like comments
3658 and preprocessing directives) after the old formals list but before
3659 the following { and we would like to preserve that stuff while effectively
3660 deleting the existing K&R formal parameter declarations. We do so here
3661 in a rather tricky way. Basically, we white out any stuff *except*
3662 the comments/pp-directives in the original text buffer, then, if there
3663 is anything in this area *other* than whitespace, we output it. */
3665 const char *end_formals_orig;
3666 const char *start_body;
3667 const char *start_body_orig;
3668 const char *scan;
3669 const char *scan_orig;
3670 int have_flotsam = 0;
3671 int have_newlines = 0;
3673 for (start_body = end_formals + 1; *start_body != '{';)
3674 check_source (++start_body < clean_text_limit, 0);
3676 end_formals_orig = orig_text_base + (end_formals - clean_text_base);
3677 start_body_orig = orig_text_base + (start_body - clean_text_base);
3678 scan = end_formals + 1;
3679 scan_orig = end_formals_orig + 1;
3680 for (; scan < start_body; scan++, scan_orig++)
3682 if (*scan == *scan_orig)
3684 have_newlines |= (*scan_orig == '\n');
3685 /* Leave identical whitespace alone. */
3686 if (!ISSPACE ((const unsigned char)*scan_orig))
3687 *((NONCONST char *)scan_orig) = ' '; /* identical - so whiteout */
3689 else
3690 have_flotsam = 1;
3692 if (have_flotsam)
3693 output_bytes (end_formals_orig + 1,
3694 (size_t) (start_body_orig - end_formals_orig) - 1);
3695 else
3696 if (have_newlines)
3697 output_string ("\n");
3698 else
3699 output_string (" ");
3700 clean_read_ptr = start_body - 1;
3702 #endif /* !defined (UNPROTOIZE) */
3705 /* Clean up the clean text buffer. Do this by converting comments and
3706 preprocessing directives into spaces. Also convert line continuations
3707 into whitespace. Also, whiteout string and character literals. */
3709 static void
3710 do_cleaning (new_clean_text_base, new_clean_text_limit)
3711 char *new_clean_text_base;
3712 const char *new_clean_text_limit;
3714 char *scan_p;
3715 int non_whitespace_since_newline = 0;
3717 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
3719 switch (*scan_p)
3721 case '/': /* Handle comments. */
3722 if (scan_p[1] != '*')
3723 goto regular;
3724 non_whitespace_since_newline = 1;
3725 scan_p[0] = ' ';
3726 scan_p[1] = ' ';
3727 scan_p += 2;
3728 while (scan_p[1] != '/' || scan_p[0] != '*')
3730 if (!ISSPACE ((const unsigned char)*scan_p))
3731 *scan_p = ' ';
3732 if (++scan_p >= new_clean_text_limit)
3733 abort ();
3735 *scan_p++ = ' ';
3736 *scan_p = ' ';
3737 break;
3739 case '#': /* Handle pp directives. */
3740 if (non_whitespace_since_newline)
3741 goto regular;
3742 *scan_p = ' ';
3743 while (scan_p[1] != '\n' || scan_p[0] == '\\')
3745 if (!ISSPACE ((const unsigned char)*scan_p))
3746 *scan_p = ' ';
3747 if (++scan_p >= new_clean_text_limit)
3748 abort ();
3750 *scan_p++ = ' ';
3751 break;
3753 case '\'': /* Handle character literals. */
3754 non_whitespace_since_newline = 1;
3755 while (scan_p[1] != '\'' || scan_p[0] == '\\')
3757 if (scan_p[0] == '\\'
3758 && !ISSPACE ((const unsigned char)scan_p[1]))
3759 scan_p[1] = ' ';
3760 if (!ISSPACE ((const unsigned char)*scan_p))
3761 *scan_p = ' ';
3762 if (++scan_p >= new_clean_text_limit)
3763 abort ();
3765 *scan_p++ = ' ';
3766 break;
3768 case '"': /* Handle string literals. */
3769 non_whitespace_since_newline = 1;
3770 while (scan_p[1] != '"' || scan_p[0] == '\\')
3772 if (scan_p[0] == '\\'
3773 && !ISSPACE ((const unsigned char)scan_p[1]))
3774 scan_p[1] = ' ';
3775 if (!ISSPACE ((const unsigned char)*scan_p))
3776 *scan_p = ' ';
3777 if (++scan_p >= new_clean_text_limit)
3778 abort ();
3780 if (!ISSPACE ((const unsigned char)*scan_p))
3781 *scan_p = ' ';
3782 scan_p++;
3783 break;
3785 case '\\': /* Handle line continuations. */
3786 if (scan_p[1] != '\n')
3787 goto regular;
3788 *scan_p = ' ';
3789 break;
3791 case '\n':
3792 non_whitespace_since_newline = 0; /* Reset. */
3793 break;
3795 case ' ':
3796 case '\v':
3797 case '\t':
3798 case '\r':
3799 case '\f':
3800 case '\b':
3801 break; /* Whitespace characters. */
3803 default:
3804 regular:
3805 non_whitespace_since_newline = 1;
3806 break;
3811 /* Given a pointer to the closing right parenthesis for a particular formals
3812 list (in the clean text buffer) find the corresponding left parenthesis
3813 and return a pointer to it. */
3815 static const char *
3816 careful_find_l_paren (p)
3817 const char *p;
3819 const char *q;
3820 int paren_depth;
3822 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
3824 switch (*q)
3826 case ')':
3827 paren_depth++;
3828 break;
3829 case '(':
3830 paren_depth--;
3831 break;
3834 return ++q;
3837 /* Scan the clean text buffer for cases of function definitions that we
3838 don't really know about because they were preprocessed out when the
3839 aux info files were created.
3841 In this version of protoize/unprotoize we just give a warning for each
3842 one found. A later version may be able to at least unprotoize such
3843 missed items.
3845 Note that we may easily find all function definitions simply by
3846 looking for places where there is a left paren which is (ignoring
3847 whitespace) immediately followed by either a left-brace or by an
3848 upper or lower case letter. Whenever we find this combination, we
3849 have also found a function definition header.
3851 Finding function *declarations* using syntactic clues is much harder.
3852 I will probably try to do this in a later version though. */
3854 static void
3855 scan_for_missed_items (file_p)
3856 const file_info *file_p;
3858 static const char *scan_p;
3859 const char *limit = clean_text_limit - 3;
3860 static const char *backup_limit;
3862 backup_limit = clean_text_base - 1;
3864 for (scan_p = clean_text_base; scan_p < limit; scan_p++)
3866 if (*scan_p == ')')
3868 static const char *last_r_paren;
3869 const char *ahead_p;
3871 last_r_paren = scan_p;
3873 for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
3874 check_source (++ahead_p < limit, limit);
3876 scan_p = ahead_p - 1;
3878 if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
3880 const char *last_l_paren;
3881 const int lineno = identify_lineno (ahead_p);
3883 if (setjmp (source_confusion_recovery))
3884 continue;
3886 /* We know we have a function definition header. Now skip
3887 leftwards over all of its associated formals lists. */
3891 last_l_paren = careful_find_l_paren (last_r_paren);
3892 for (last_r_paren = last_l_paren-1;
3893 ISSPACE ((const unsigned char)*last_r_paren); )
3894 check_source (--last_r_paren >= backup_limit, backup_limit);
3896 while (*last_r_paren == ')');
3898 if (is_id_char (*last_r_paren))
3900 const char *id_limit = last_r_paren + 1;
3901 const char *id_start;
3902 size_t id_length;
3903 const def_dec_info *dd_p;
3905 for (id_start = id_limit-1; is_id_char (*id_start); )
3906 check_source (--id_start >= backup_limit, backup_limit);
3907 id_start++;
3908 backup_limit = id_start;
3909 if ((id_length = (size_t) (id_limit - id_start)) == 0)
3910 goto not_missed;
3913 char *func_name = (char *) alloca (id_length + 1);
3914 static const char * const stmt_keywords[]
3915 = { "if", "else", "do", "while", "for", "switch", "case", "return", 0 };
3916 const char * const *stmt_keyword;
3918 strncpy (func_name, id_start, id_length);
3919 func_name[id_length] = '\0';
3921 /* We must check here to see if we are actually looking at
3922 a statement rather than an actual function call. */
3924 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
3925 if (!strcmp (func_name, *stmt_keyword))
3926 goto not_missed;
3928 #if 0
3929 notice ("%s: found definition of `%s' at %s(%d)\n",
3930 pname,
3931 func_name,
3932 shortpath (NULL, file_p->hash_entry->symbol),
3933 identify_lineno (id_start));
3934 #endif /* 0 */
3935 /* We really should check for a match of the function name
3936 here also, but why bother. */
3938 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3939 if (dd_p->is_func_def && dd_p->line == lineno)
3940 goto not_missed;
3942 /* If we make it here, then we did not know about this
3943 function definition. */
3945 notice ("%s: %d: warning: `%s' excluded by preprocessing\n",
3946 shortpath (NULL, file_p->hash_entry->symbol),
3947 identify_lineno (id_start), func_name);
3948 notice ("%s: function definition not converted\n",
3949 pname);
3951 not_missed: ;
3958 /* Do all editing operations for a single source file (either a "base" file
3959 or an "include" file). To do this we read the file into memory, keep a
3960 virgin copy there, make another cleaned in-core copy of the original file
3961 (i.e. one in which all of the comments and preprocessing directives have
3962 been replaced with whitespace), then use these two in-core copies of the
3963 file to make a new edited in-core copy of the file. Finally, rename the
3964 original file (as a way of saving it), and then write the edited version
3965 of the file from core to a disk file of the same name as the original.
3967 Note that the trick of making a copy of the original sans comments &
3968 preprocessing directives make the editing a whole lot easier. */
3970 static void
3971 edit_file (hp)
3972 const hash_table_entry *hp;
3974 struct stat stat_buf;
3975 const file_info *file_p = hp->fip;
3976 char *new_orig_text_base;
3977 char *new_orig_text_limit;
3978 char *new_clean_text_base;
3979 char *new_clean_text_limit;
3980 size_t orig_size;
3981 size_t repl_size;
3982 int first_definition_in_file;
3984 /* If we are not supposed to be converting this file, or if there is
3985 nothing in there which needs converting, just skip this file. */
3987 if (!needs_to_be_converted (file_p))
3988 return;
3990 convert_filename = file_p->hash_entry->symbol;
3992 /* Convert a file if it is in a directory where we want conversion
3993 and the file is not excluded. */
3995 if (!directory_specified_p (convert_filename)
3996 || file_excluded_p (convert_filename))
3998 if (!quiet_flag
3999 #ifdef UNPROTOIZE
4000 /* Don't even mention "system" include files unless we are
4001 protoizing. If we are protoizing, we mention these as a
4002 gentle way of prodding the user to convert his "system"
4003 include files to prototype format. */
4004 && !in_system_include_dir (convert_filename)
4005 #endif /* defined (UNPROTOIZE) */
4007 notice ("%s: `%s' not converted\n",
4008 pname, shortpath (NULL, convert_filename));
4009 return;
4012 /* Let the user know what we are up to. */
4014 if (nochange_flag)
4015 notice ("%s: would convert file `%s'\n",
4016 pname, shortpath (NULL, convert_filename));
4017 else
4018 notice ("%s: converting file `%s'\n",
4019 pname, shortpath (NULL, convert_filename));
4020 fflush (stderr);
4022 /* Find out the size (in bytes) of the original file. */
4024 /* The cast avoids an erroneous warning on AIX. */
4025 if (stat (convert_filename, &stat_buf) == -1)
4027 int errno_val = errno;
4028 notice ("%s: can't get status for file `%s': %s\n",
4029 pname, shortpath (NULL, convert_filename),
4030 xstrerror (errno_val));
4031 return;
4033 orig_size = stat_buf.st_size;
4035 /* Allocate a buffer to hold the original text. */
4037 orig_text_base = new_orig_text_base = (char *) xmalloc (orig_size + 2);
4038 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
4040 /* Allocate a buffer to hold the cleaned-up version of the original text. */
4042 clean_text_base = new_clean_text_base = (char *) xmalloc (orig_size + 2);
4043 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
4044 clean_read_ptr = clean_text_base - 1;
4046 /* Allocate a buffer that will hopefully be large enough to hold the entire
4047 converted output text. As an initial guess for the maximum size of the
4048 output buffer, use 125% of the size of the original + some extra. This
4049 buffer can be expanded later as needed. */
4051 repl_size = orig_size + (orig_size >> 2) + 4096;
4052 repl_text_base = (char *) xmalloc (repl_size + 2);
4053 repl_text_limit = repl_text_base + repl_size - 1;
4054 repl_write_ptr = repl_text_base - 1;
4057 int input_file;
4059 /* Open the file to be converted in READ ONLY mode. */
4061 if ((input_file = open (convert_filename, O_RDONLY, 0444)) == -1)
4063 int errno_val = errno;
4064 notice ("%s: can't open file `%s' for reading: %s\n",
4065 pname, shortpath (NULL, convert_filename),
4066 xstrerror (errno_val));
4067 return;
4070 /* Read the entire original source text file into the original text buffer
4071 in one swell fwoop. Then figure out where the end of the text is and
4072 make sure that it ends with a newline followed by a null. */
4074 if (safe_read (input_file, new_orig_text_base, orig_size) !=
4075 (int) orig_size)
4077 int errno_val = errno;
4078 close (input_file);
4079 notice ("\n%s: error reading input file `%s': %s\n",
4080 pname, shortpath (NULL, convert_filename),
4081 xstrerror (errno_val));
4082 return;
4085 close (input_file);
4088 if (orig_size == 0 || orig_text_limit[-1] != '\n')
4090 *new_orig_text_limit++ = '\n';
4091 orig_text_limit++;
4094 /* Create the cleaned up copy of the original text. */
4096 memcpy (new_clean_text_base, orig_text_base,
4097 (size_t) (orig_text_limit - orig_text_base));
4098 do_cleaning (new_clean_text_base, new_clean_text_limit);
4100 #if 0
4102 int clean_file;
4103 size_t clean_size = orig_text_limit - orig_text_base;
4104 char *const clean_filename = (char *) alloca (strlen (convert_filename) + 6 + 1);
4106 /* Open (and create) the clean file. */
4108 strcpy (clean_filename, convert_filename);
4109 strcat (clean_filename, ".clean");
4110 if ((clean_file = creat (clean_filename, 0666)) == -1)
4112 int errno_val = errno;
4113 notice ("%s: can't create/open clean file `%s': %s\n",
4114 pname, shortpath (NULL, clean_filename),
4115 xstrerror (errno_val));
4116 return;
4119 /* Write the clean file. */
4121 safe_write (clean_file, new_clean_text_base, clean_size, clean_filename);
4123 close (clean_file);
4125 #endif /* 0 */
4127 /* Do a simplified scan of the input looking for things that were not
4128 mentioned in the aux info files because of the fact that they were
4129 in a region of the source which was preprocessed-out (via #if or
4130 via #ifdef). */
4132 scan_for_missed_items (file_p);
4134 /* Setup to do line-oriented forward seeking in the clean text buffer. */
4136 last_known_line_number = 1;
4137 last_known_line_start = clean_text_base;
4139 /* Now get down to business and make all of the necessary edits. */
4142 const def_dec_info *def_dec_p;
4144 first_definition_in_file = 1;
4145 def_dec_p = file_p->defs_decs;
4146 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
4148 const char *clean_text_p = seek_to_line (def_dec_p->line);
4150 /* clean_text_p now points to the first character of the line which
4151 contains the `terminator' for the declaration or definition that
4152 we are about to process. */
4154 #ifndef UNPROTOIZE
4156 if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
4158 add_global_decls (def_dec_p->file, clean_text_p);
4159 first_definition_in_file = 0;
4162 /* Don't edit this item if it is already in prototype format or if it
4163 is a function declaration and we have found no corresponding
4164 definition. */
4166 if (def_dec_p->prototyped
4167 || (!def_dec_p->is_func_def && !def_dec_p->definition))
4168 continue;
4170 #endif /* !defined (UNPROTOIZE) */
4172 if (def_dec_p->is_func_def)
4173 edit_fn_definition (def_dec_p, clean_text_p);
4174 else
4175 #ifndef UNPROTOIZE
4176 if (def_dec_p->is_implicit)
4177 add_local_decl (def_dec_p, clean_text_p);
4178 else
4179 #endif /* !defined (UNPROTOIZE) */
4180 edit_fn_declaration (def_dec_p, clean_text_p);
4184 /* Finalize things. Output the last trailing part of the original text. */
4186 output_up_to (clean_text_limit - 1);
4188 /* If this is just a test run, stop now and just deallocate the buffers. */
4190 if (nochange_flag)
4192 free (new_orig_text_base);
4193 free (new_clean_text_base);
4194 free (repl_text_base);
4195 return;
4198 /* Change the name of the original input file. This is just a quick way of
4199 saving the original file. */
4201 if (!nosave_flag)
4203 char *new_filename
4204 = (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
4206 strcpy (new_filename, convert_filename);
4207 strcat (new_filename, save_suffix);
4208 if (link (convert_filename, new_filename) == -1)
4210 int errno_val = errno;
4211 if (errno_val == EEXIST)
4213 if (!quiet_flag)
4214 notice ("%s: warning: file `%s' already saved in `%s'\n",
4215 pname,
4216 shortpath (NULL, convert_filename),
4217 shortpath (NULL, new_filename));
4219 else
4221 notice ("%s: can't link file `%s' to `%s': %s\n",
4222 pname,
4223 shortpath (NULL, convert_filename),
4224 shortpath (NULL, new_filename),
4225 xstrerror (errno_val));
4226 return;
4231 if (unlink (convert_filename) == -1)
4233 int errno_val = errno;
4234 notice ("%s: can't delete file `%s': %s\n",
4235 pname, shortpath (NULL, convert_filename),
4236 xstrerror (errno_val));
4237 return;
4241 int output_file;
4243 /* Open (and create) the output file. */
4245 if ((output_file = creat (convert_filename, 0666)) == -1)
4247 int errno_val = errno;
4248 notice ("%s: can't create/open output file `%s': %s\n",
4249 pname, shortpath (NULL, convert_filename),
4250 xstrerror (errno_val));
4251 return;
4254 /* Write the output file. */
4257 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
4259 safe_write (output_file, repl_text_base, out_size, convert_filename);
4262 close (output_file);
4265 /* Deallocate the conversion buffers. */
4267 free (new_orig_text_base);
4268 free (new_clean_text_base);
4269 free (repl_text_base);
4271 /* Change the mode of the output file to match the original file. */
4273 /* The cast avoids an erroneous warning on AIX. */
4274 if (chmod (convert_filename, stat_buf.st_mode) == -1)
4276 int errno_val = errno;
4277 notice ("%s: can't change mode of file `%s': %s\n",
4278 pname, shortpath (NULL, convert_filename),
4279 xstrerror (errno_val));
4282 /* Note: We would try to change the owner and group of the output file
4283 to match those of the input file here, except that may not be a good
4284 thing to do because it might be misleading. Also, it might not even
4285 be possible to do that (on BSD systems with quotas for instance). */
4288 /* Do all of the individual steps needed to do the protoization (or
4289 unprotoization) of the files referenced in the aux_info files given
4290 in the command line. */
4292 static void
4293 do_processing ()
4295 const char * const *base_pp;
4296 const char * const * const end_pps
4297 = &base_source_filenames[n_base_source_files];
4299 #ifndef UNPROTOIZE
4300 int syscalls_len;
4301 #endif /* !defined (UNPROTOIZE) */
4303 /* One-by-one, check (and create if necessary), open, and read all of the
4304 stuff in each aux_info file. After reading each aux_info file, the
4305 aux_info_file just read will be automatically deleted unless the
4306 keep_flag is set. */
4308 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
4309 process_aux_info_file (*base_pp, keep_flag, 0);
4311 #ifndef UNPROTOIZE
4313 /* Also open and read the special SYSCALLS.c aux_info file which gives us
4314 the prototypes for all of the standard system-supplied functions. */
4316 if (nondefault_syscalls_dir)
4318 syscalls_absolute_filename
4319 = (char *) xmalloc (strlen (nondefault_syscalls_dir) + 1
4320 + sizeof (syscalls_filename));
4321 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
4323 else
4325 GET_ENV_PATH_LIST (default_syscalls_dir, "GCC_EXEC_PREFIX");
4326 if (!default_syscalls_dir)
4328 default_syscalls_dir = standard_exec_prefix;
4330 syscalls_absolute_filename
4331 = (char *) xmalloc (strlen (default_syscalls_dir) + 0
4332 + strlen (target_machine) + 1
4333 + strlen (target_version) + 1
4334 + sizeof (syscalls_filename));
4335 strcpy (syscalls_absolute_filename, default_syscalls_dir);
4336 strcat (syscalls_absolute_filename, target_machine);
4337 strcat (syscalls_absolute_filename, "/");
4338 strcat (syscalls_absolute_filename, target_version);
4339 strcat (syscalls_absolute_filename, "/");
4342 syscalls_len = strlen (syscalls_absolute_filename);
4343 if (*(syscalls_absolute_filename + syscalls_len - 1) != '/')
4345 *(syscalls_absolute_filename + syscalls_len++) = '/';
4346 *(syscalls_absolute_filename + syscalls_len) = '\0';
4348 strcat (syscalls_absolute_filename, syscalls_filename);
4350 /* Call process_aux_info_file in such a way that it does not try to
4351 delete the SYSCALLS aux_info file. */
4353 process_aux_info_file (syscalls_absolute_filename, 1, 1);
4355 #endif /* !defined (UNPROTOIZE) */
4357 /* When we first read in all of the information from the aux_info files
4358 we saved in it descending line number order, because that was likely to
4359 be faster. Now however, we want the chains of def & dec records to
4360 appear in ascending line number order as we get further away from the
4361 file_info record that they hang from. The following line causes all of
4362 these lists to be rearranged into ascending line number order. */
4364 visit_each_hash_node (filename_primary, reverse_def_dec_list);
4366 #ifndef UNPROTOIZE
4368 /* Now do the "real" work. The following line causes each declaration record
4369 to be "visited". For each of these nodes, an attempt is made to match
4370 up the function declaration with a corresponding function definition,
4371 which should have a full prototype-format formals list with it. Once
4372 these match-ups are made, the conversion of the function declarations
4373 to prototype format can be made. */
4375 visit_each_hash_node (function_name_primary, connect_defs_and_decs);
4377 #endif /* !defined (UNPROTOIZE) */
4379 /* Now convert each file that can be converted (and needs to be). */
4381 visit_each_hash_node (filename_primary, edit_file);
4383 #ifndef UNPROTOIZE
4385 /* If we are working in cplusplus mode, try to rename all .c files to .C
4386 files. Don't panic if some of the renames don't work. */
4388 if (cplusplus_flag && !nochange_flag)
4389 visit_each_hash_node (filename_primary, rename_c_file);
4391 #endif /* !defined (UNPROTOIZE) */
4394 static struct option longopts[] =
4396 {"version", 0, 0, 'V'},
4397 {"file_name", 0, 0, 'p'},
4398 {"quiet", 0, 0, 'q'},
4399 {"silent", 0, 0, 'q'},
4400 {"force", 0, 0, 'f'},
4401 {"keep", 0, 0, 'k'},
4402 {"nosave", 0, 0, 'N'},
4403 {"nochange", 0, 0, 'n'},
4404 {"compiler-options", 1, 0, 'c'},
4405 {"exclude", 1, 0, 'x'},
4406 {"directory", 1, 0, 'd'},
4407 #ifdef UNPROTOIZE
4408 {"indent", 1, 0, 'i'},
4409 #else
4410 {"local", 0, 0, 'l'},
4411 {"global", 0, 0, 'g'},
4412 {"c++", 0, 0, 'C'},
4413 {"syscalls-dir", 1, 0, 'B'},
4414 #endif
4415 {0, 0, 0, 0}
4418 extern int main PARAMS ((int, char **const));
4421 main (argc, argv)
4422 int argc;
4423 char **const argv;
4425 int longind;
4426 int c;
4427 const char *params = "";
4429 pname = strrchr (argv[0], '/');
4430 pname = pname ? pname+1 : argv[0];
4432 #ifdef HAVE_LC_MESSAGES
4433 setlocale (LC_MESSAGES, "");
4434 #endif
4435 (void) bindtextdomain (PACKAGE, localedir);
4436 (void) textdomain (PACKAGE);
4438 cwd_buffer = getpwd ();
4439 if (!cwd_buffer)
4441 notice ("%s: cannot get working directory: %s\n",
4442 pname, xstrerror(errno));
4443 return (FATAL_EXIT_CODE);
4446 /* By default, convert the files in the current directory. */
4447 directory_list = string_list_cons (cwd_buffer, NULL);
4449 while ((c = getopt_long (argc, argv,
4450 #ifdef UNPROTOIZE
4451 "c:d:i:knNp:qvVx:",
4452 #else
4453 "B:c:Cd:gklnNp:qvVx:",
4454 #endif
4455 longopts, &longind)) != EOF)
4457 if (c == 0) /* Long option. */
4458 c = longopts[longind].val;
4459 switch (c)
4461 case 'p':
4462 compiler_file_name = optarg;
4463 break;
4464 case 'd':
4465 directory_list
4466 = string_list_cons (abspath (NULL, optarg), directory_list);
4467 break;
4468 case 'x':
4469 exclude_list = string_list_cons (optarg, exclude_list);
4470 break;
4472 case 'v':
4473 case 'V':
4474 version_flag = 1;
4475 break;
4476 case 'q':
4477 quiet_flag = 1;
4478 break;
4479 #if 0
4480 case 'f':
4481 force_flag = 1;
4482 break;
4483 #endif
4484 case 'n':
4485 nochange_flag = 1;
4486 keep_flag = 1;
4487 break;
4488 case 'N':
4489 nosave_flag = 1;
4490 break;
4491 case 'k':
4492 keep_flag = 1;
4493 break;
4494 case 'c':
4495 params = optarg;
4496 break;
4497 #ifdef UNPROTOIZE
4498 case 'i':
4499 indent_string = optarg;
4500 break;
4501 #else /* !defined (UNPROTOIZE) */
4502 case 'l':
4503 local_flag = 1;
4504 break;
4505 case 'g':
4506 global_flag = 1;
4507 break;
4508 case 'C':
4509 cplusplus_flag = 1;
4510 break;
4511 case 'B':
4512 nondefault_syscalls_dir = optarg;
4513 break;
4514 #endif /* !defined (UNPROTOIZE) */
4515 default:
4516 usage ();
4520 /* Set up compile_params based on -p and -c options. */
4521 munge_compile_params (params);
4523 n_base_source_files = argc - optind;
4525 /* Now actually make a list of the base source filenames. */
4527 base_source_filenames
4528 = (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *));
4529 n_base_source_files = 0;
4530 for (; optind < argc; optind++)
4532 const char *path = abspath (NULL, argv[optind]);
4533 int len = strlen (path);
4535 if (path[len-1] == 'c' && path[len-2] == '.')
4536 base_source_filenames[n_base_source_files++] = path;
4537 else
4539 notice ("%s: input file names must have .c suffixes: %s\n",
4540 pname, shortpath (NULL, path));
4541 errors++;
4545 #ifndef UNPROTOIZE
4546 /* We are only interested in the very first identifier token in the
4547 definition of `va_list', so if there is more junk after that first
4548 identifier token, delete it from the `varargs_style_indicator'. */
4550 const char *cp;
4552 for (cp = varargs_style_indicator;
4553 ISALNUM ((const unsigned char)*cp) || *cp == '_'; cp++)
4554 continue;
4555 if (*cp != 0)
4556 varargs_style_indicator = savestring (varargs_style_indicator,
4557 cp - varargs_style_indicator);
4559 #endif /* !defined (UNPROTOIZE) */
4561 if (errors)
4562 usage ();
4563 else
4565 if (version_flag)
4566 fprintf (stderr, "%s: %s\n", pname, version_string);
4567 do_processing ();
4570 return (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);