1 /* Protoize program - Original version by Ron Guilmette at MCC.
3 Copyright (C) 1989, 1992 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* Any reasonable C++ compiler should have all of the same features
22 as __STDC__ plus more, so make sure that __STDC__ is defined if
23 __cplusplus is defined. */
25 #if defined(__cplusplus) && !defined(__STDC__)
27 #endif /* defined(__cplusplus) && !defined(__STDC__) */
29 #if defined(__GNUC__) || defined (__GNUG__)
30 #define VOLATILE volatile
41 #ifdef POSIX /* We should be able to define _POSIX_SOURCE unconditionally,
42 but some systems respond in buggy ways to it,
43 including Sunos 4.1.1. Which we don't classify as POSIX. */
44 /* In case this is a POSIX system with an ANSI C compiler,
45 ask for definition of all POSIX facilities. */
50 /* Users are not supposed to use _POSIX_SOURCE to say the
51 system is a POSIX system. That is not what _POSIX_SOURCE means! -- rms */
52 /* If the user asked for POSIX via _POSIX_SOURCE, turn on POSIX code. */
53 #if defined(_POSIX_SOURCE) && !defined(POSIX)
61 #include <sys/types.h>
64 #if ! defined (USG) || defined (SVR4)
71 #ifndef PATH_MAX /* <limits.h> defines this on most POSIX systems. */
72 #include <sys/param.h>
73 /* Sometimes <sys/param.h> defines these macros. */
93 extern char *sys_errlist[];
94 extern char *version_string;
96 /* Systems which are compatible only with POSIX 1003.1-1988 (but *not*
97 with POSIX 1003.1-1990), e.g. Ultrix 4.2, might not have
98 const qualifiers in the prototypes in the system include files.
99 Unfortunately, this can lead to GCC issuing lots of warnings for
100 calls to the following functions. To eliminate these warnings we
101 provide the following #defines. */
103 #define my_access(file,flag) access((char *)file, flag)
104 #define my_stat(file,pkt) stat((char *)file, pkt)
105 #define my_execvp(prog,argv) execvp((char *)prog, (char **)argv)
106 #define my_link(file1, file2) link((char *)file1, (char *)file2)
107 #define my_unlink(file) unlink((char *)file)
108 #define my_open(file, mode, flag) open((char *)file, mode, flag)
109 #define my_chmod(file, mode) chmod((char *)file, mode)
111 #if !(defined (USG) || defined (VMS) || defined (POSIX))
112 #define GUESSPATHLEN (MAXPATHLEN + 1)
113 #else /* (defined (USG) || defined (VMS) || defined (POSIX)) */
114 /* We actually use this as a starting point, not a limit. */
115 #define GUESSPATHLEN 200
116 #endif /* (defined (USG) || defined (VMS) || defined (POSIX)) */
118 /* Aliases for pointers to void.
119 These were made to facilitate compilation with other compilers. */
122 typedef void * pointer_type;
123 typedef const void * const_pointer_type;
125 typedef char * pointer_type;
126 typedef char * const_pointer_type;
137 #else /* !defined(POSIX) */
139 #define R_OK 4 /* Test for Read permission */
140 #define W_OK 2 /* Test for Write permission */
141 #define X_OK 1 /* Test for eXecute permission */
142 #define F_OK 0 /* Test for existence of File */
147 /* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
148 BSD systems) now provides getcwd as called for by POSIX. Allow for
149 the few exceptions to the general rule here. */
151 #if !(defined (USG) || defined (VMS))
152 extern char *getwd ();
153 #define getcwd(buf,len) getwd(buf)
154 #else /* (defined (USG) || defined (VMS)) */
155 extern char *getcwd ();
156 #endif /* (defined (USG) || defined (VMS)) */
158 /* Declaring stat or __flsbuf with a prototype
159 causes conflicts with system headers on some systems. */
162 extern VOLATILE void abort ();
166 #if 0 /* These conflict with stdio.h on some systems. */
167 extern int fprintf (FILE *, const char *, ...);
168 extern int printf (const char *, ...);
171 extern pointer_type malloc ();
172 extern pointer_type realloc ();
177 extern int fflush ();
182 #if 0 /* Causes trouble on some systems that define setjmp as a macro. */
183 extern int setjmp ();
184 extern void longjmp ();
187 extern char * strcat ();
188 extern int strcmp ();
189 extern char * strcpy ();
190 #if 0 /* size_t from sys/types.h may fail to match GCC.
191 If so, we would get a warning from this.
192 So do without the prototype. */
193 extern size_t strlen (const char *);
195 extern int strncmp ();
196 extern char * strncpy ();
197 extern char * strrchr ();
199 /* Fork is not declared because the declaration caused a conflict
201 #if !(defined (USG) || defined (VMS))
203 #endif /* (defined (USG) || defined (VMS)) */
205 #endif /* !defined (POSIX) */
207 /* Look for these where the `const' qualifier is intentionally cast aside. */
211 /* Define a STRINGIFY macro that's right for ANSI or traditional C. */
214 #define STRINGIFY(STRING) #STRING
216 #define STRINGIFY(STRING) "STRING"
219 /* POSIX systems will not have definitions for WIFEXITED or WEXITSTATUS.
220 Define them correctly and so that they work for all environments. */
223 #define WIFEXITED(status_word) ((*((int *)&status_word) & 0xff) == 0x00)
226 #define WEXITSTATUS(status_word) ((*((int *)&status_word) & 0xff00) >> 8)
228 /* Define a default place to find the SYSCALLS.X file. */
230 #ifndef STD_PROTO_DIR
231 #define STD_PROTO_DIR "/usr/local/lib"
232 #endif /* !defined (STD_PROTO_DIR) */
234 /* Suffix of aux_info files. */
236 static const char * const aux_info_suffix = ".X";
238 /* String to attach to filenames for saved versions of original files. */
240 static const char * const save_suffix = ".save";
244 /* File name of the file which contains descriptions of standard system
245 routines. Note that we never actually do anything with this file per se,
246 but we do read in its corresponding aux_info file. */
248 static const char * const syscalls_filename = "SYSCALLS.c";
250 /* Default place to find the above file. */
252 static const char * const default_syscalls_dir = STD_PROTO_DIR;
254 /* Variable to hold the complete absolutized filename of the SYSCALLS.c.X
257 static char * syscalls_absolute_filename;
259 #endif /* !defined (UNPROTOIZE) */
261 /* Type of the structure that holds information about macro unexpansions. */
263 struct unexpansion_struct {
264 const char *expanded;
265 const char *contracted;
267 typedef struct unexpansion_struct unexpansion;
269 /* A table of conversions that may need to be made for some (stupid) older
270 operating systems where these types are preprocessor macros rather than
271 typedefs (as they really ought to be).
273 WARNING: The contracted forms must be as small (or smaller) as the
274 expanded forms, or else havoc will ensue. */
276 static const unexpansion unexpansions[] = {
277 { "struct _iobuf", "FILE" },
281 /* The number of "primary" slots in the hash tables for filenames and for
282 function names. This can be as big or as small as you like, except that
283 it must be a power of two. */
285 #define HASH_TABLE_SIZE (1 << 9)
287 /* Bit mask to use when computing hash values. */
289 static const int hash_mask = (HASH_TABLE_SIZE - 1);
291 /* Make a table of default system include directories
292 just as it is done in cccp.c. */
294 #ifndef STANDARD_INCLUDE_DIR
295 #define STANDARD_INCLUDE_DIR "/usr/include"
298 #ifndef LOCAL_INCLUDE_DIR
299 #define LOCAL_INCLUDE_DIR "/usr/local/include"
302 struct default_include { char *fname; int cplusplus; } include_defaults[]
303 #ifdef INCLUDE_DEFAULTS
307 /* Pick up GNU C++ specific include files. */
308 { GPLUSPLUS_INCLUDE_DIR, 1},
309 { GCC_INCLUDE_DIR, 0},
311 /* For cross-compilation, this dir name is generated
312 automatically in Makefile.in. */
313 { CROSS_INCLUDE_DIR, 0 },
314 #else /* not CROSS_COMPILE */
315 { LOCAL_INCLUDE_DIR, 0},
316 /* Some systems have an extra dir of include files. */
317 #ifdef SYSTEM_INCLUDE_DIR
318 { SYSTEM_INCLUDE_DIR, 0},
320 { STANDARD_INCLUDE_DIR, 0},
321 #endif /* not CROSS_COMPILE */
324 #endif /* no INCLUDE_DEFAULTS */
326 /* Datatype for lists of directories or filenames. */
330 struct string_list *next;
333 /* List of directories in which files should be converted. */
335 struct string_list *directory_list;
337 /* List of file names which should not be converted.
338 A file is excluded if the end of its name, following a /,
339 matches one of the names in this list. */
341 struct string_list *exclude_list;
343 /* The name of the other style of variable-number-of-parameters functions
344 (i.e. the style that we want to leave unconverted because we don't yet
345 know how to convert them to this style. This string is used in warning
348 /* Also define here the string that we can search for in the parameter lists
349 taken from the .X files which will unambiguously indicate that we have
350 found a varargs style function. */
353 static const char * const other_var_style = "stdarg";
354 #else /* !defined (UNPROTOIZE) */
355 static const char * const other_var_style = "varargs";
356 /* Note that this is a string containing the expansion of va_alist.
357 But in `main' we discard all but the first token. */
358 static const char *varargs_style_indicator = STRINGIFY (va_alist);
359 #endif /* !defined (UNPROTOIZE) */
361 /* The following two types are used to create hash tables. In this program,
362 there are two hash tables which are used to store and quickly lookup two
363 different classes of strings. The first type of strings stored in the
364 first hash table are absolute filenames of files which protoize needs to
365 know about. The second type of strings (stored in the second hash table)
366 are function names. It is this second class of strings which really
367 inspired the use of the hash tables, because there may be a lot of them. */
369 typedef struct hash_table_entry_struct hash_table_entry;
371 /* Do some typedefs so that we don't have to write "struct" so often. */
373 typedef struct def_dec_info_struct def_dec_info;
374 typedef struct file_info_struct file_info;
375 typedef struct f_list_chain_item_struct f_list_chain_item;
377 /* In the struct below, note that the "_info" field has two different uses
378 depending on the type of hash table we are in (i.e. either the filenames
379 hash table or the function names hash table). In the filenames hash table
380 the info fields of the entries point to the file_info struct which is
381 associated with each filename (1 per filename). In the function names
382 hash table, the info field points to the head of a singly linked list of
383 def_dec_info entries which are all defs or decs of the function whose
384 name is pointed to by the "symbol" field. Keeping all of the defs/decs
385 for a given function name on a special list specifically for that function
386 name makes it quick and easy to find out all of the important information
387 about a given (named) function. */
389 struct hash_table_entry_struct {
390 hash_table_entry * hash_next; /* -> to secondary entries */
391 const char * symbol; /* -> to the hashed string */
393 const def_dec_info * _ddip;
397 #define ddip _info._ddip
398 #define fip _info._fip
400 /* Define a type specifically for our two hash tables. */
402 typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
404 /* The following struct holds all of the important information about any
405 single filename (e.g. file) which we need to know about. */
407 struct file_info_struct {
408 const hash_table_entry * hash_entry; /* -> to associated hash entry */
409 const def_dec_info * defs_decs; /* -> to chain of defs/decs */
410 time_t mtime; /* Time of last modification. */
413 /* Due to the possibility that functions may return pointers to functions,
414 (which may themselves have their own parameter lists) and due to the
415 fact that returned pointers-to-functions may be of type "pointer-to-
416 function-returning-pointer-to-function" (ad nauseum) we have to keep
417 an entire chain of ANSI style formal parameter lists for each function.
419 Normally, for any given function, there will only be one formals list
420 on the chain, but you never know.
422 Note that the head of each chain of formals lists is pointed to by the
423 `f_list_chain' field of the corresponding def_dec_info record.
425 For any given chain, the item at the head of the chain is the *leftmost*
426 parameter list seen in the actual C language function declaration. If
427 there are other members of the chain, then these are linked in left-to-right
428 order from the head of the chain. */
430 struct f_list_chain_item_struct {
431 const f_list_chain_item * chain_next; /* -> to next item on chain */
432 const char * formals_list; /* -> to formals list string */
435 /* The following struct holds all of the important information about any
436 single function definition or declaration which we need to know about.
437 Note that for unprotoize we don't need to know very much because we
438 never even create records for stuff that we don't intend to convert
439 (like for instance defs and decs which are already in old K&R format
440 and "implicit" function declarations). */
442 struct def_dec_info_struct {
443 const def_dec_info * next_in_file; /* -> to rest of chain for file */
444 file_info * file; /* -> file_info for containing file */
445 int line; /* source line number of def/dec */
446 const char * ansi_decl; /* -> left end of ansi decl */
447 hash_table_entry * hash_entry; /* -> hash entry for function name */
448 unsigned int is_func_def; /* = 0 means this is a declaration */
449 const def_dec_info * next_for_func; /* -> to rest of chain for func name */
450 unsigned int f_list_count; /* count of formals lists we expect */
451 char prototyped; /* = 0 means already prototyped */
453 const f_list_chain_item * f_list_chain; /* -> chain of formals lists */
454 const def_dec_info * definition; /* -> def/dec containing related def */
455 char is_static; /* = 0 means visiblilty is "extern" */
456 char is_implicit; /* != 0 for implicit func decl's */
457 char written; /* != 0 means written for implicit */
458 #else /* !defined (UNPROTOIZE) */
459 const char * formal_names; /* -> to list of names of formals */
460 const char * formal_decls; /* -> to string of formal declartions */
461 #endif /* !defined (UNPROTOIZE) */
464 /* Pointer to the tail component of the filename by which this program was
465 invoked. Used everywhere in error and warning messages. */
467 static const char *pname;
469 /* Error counter. Will be non-zero if we should give up at the next convenient
472 static int errors = 0;
475 /* ??? These comments should say what the flag mean as well as the options
478 /* File name to use for running gcc. Allows GCC 2 to be named
479 something other than gcc. */
480 static char *compiler_file_name = "gcc";
482 static int version_flag = 0; /* Print our version number. */
483 static int quiet_flag = 0; /* Don't print messages normally. */
484 static int nochange_flag = 0; /* Don't convert, just say what files
485 we would have converted. */
486 static int nosave_flag = 0; /* Don't save the old version. */
487 static int keep_flag = 0; /* Don't delete the .X files. */
488 static const char ** compile_params = 0; /* Option string for gcc. */
490 static const char *indent_string = " "; /* Indentation for newly
491 inserted parm decls. */
492 #else /* !defined (UNPROTOIZE) */
493 static int local_flag = 0; /* Insert new local decls (when?). */
494 static int global_flag = 0; /* set by -g option */
495 static int cplusplus_flag = 0; /* Rename converted files to *.C. */
496 static const char* nondefault_syscalls_dir = 0; /* Dir to look for
498 #endif /* !defined (UNPROTOIZE) */
500 /* An index into the compile_params array where we should insert the filename
501 parameter when we are ready to exec the C compiler. A zero value indicates
502 that we have not yet called munge_compile_params. */
504 static int filename_index = 0;
506 /* Count of command line arguments which were "filename" arguments. */
508 static int n_base_source_files = 0;
510 /* Points to a malloc'ed list of pointers to all of the filenames of base
511 source files which were specified on the command line. */
513 static const char **base_source_filenames;
515 /* Line number of the line within the current aux_info file that we
516 are currently processing. Used for error messages in case the prototypes
517 info file is corrupted somehow. */
519 static int current_aux_info_lineno;
521 /* Pointer to the name of the source file currently being converted. */
523 static const char *convert_filename;
525 /* Pointer to relative root string (taken from aux_info file) which indicates
526 where directory the user was in when he did the compilation step that
527 produced the containing aux_info file. */
529 static const char *invocation_filename;
531 /* Pointer to the base of the input buffer that holds the original text for the
532 source file currently being converted. */
534 static const char *orig_text_base;
536 /* Pointer to the byte just beyond the end of the input buffer that holds the
537 original text for the source file currently being converted. */
539 static const char *orig_text_limit;
541 /* Pointer to the base of the input buffer that holds the cleaned text for the
542 source file currently being converted. */
544 static const char *clean_text_base;
546 /* Pointer to the byte just beyond the end of the input buffer that holds the
547 cleaned text for the source file currently being converted. */
549 static const char *clean_text_limit;
551 /* Pointer to the last byte in the cleaned text buffer that we have already
552 (virtually) copied to the output buffer (or decided to ignore). */
554 static const char * clean_read_ptr;
556 /* Pointer to the base of the output buffer that holds the replacement text
557 for the source file currently being converted. */
559 static char *repl_text_base;
561 /* Pointer to the byte just beyond the end of the output buffer that holds the
562 replacement text for the source file currently being converted. */
564 static char *repl_text_limit;
566 /* Pointer to the last byte which has been stored into the output buffer.
567 The next byte to be stored should be stored just past where this points
570 static char * repl_write_ptr;
572 /* Pointer into the cleaned text buffer for the source file we are currently
573 converting. This points to the first character of the line that we last
574 did a "seek_to_line" to (see below). */
576 static const char *last_known_line_start;
578 /* Number of the line (in the cleaned text buffer) that we last did a
579 "seek_to_line" to. Will be one if we just read a new source file
580 into the cleaned text buffer. */
582 static int last_known_line_number;
584 /* The filenames hash table. */
586 static hash_table filename_primary;
588 /* The function names hash table. */
590 static hash_table function_name_primary;
592 /* The place to keep the recovery address which is used only in cases where
593 we get hopelessly confused by something in the cleaned original text. */
595 static jmp_buf source_confusion_recovery;
597 /* A pointer to the current directory filename (used by abspath). */
599 static char *cwd_buffer;
601 /* A place to save the read pointer until we are sure that an individual
602 attempt at editing will succeed. */
604 static const char * saved_clean_read_ptr;
606 /* A place to save the write pointer until we are sure that an individual
607 attempt at editing will succeed. */
609 static char * saved_repl_write_ptr;
611 /* Forward declaration. */
613 static const char *shortpath ();
615 /* Allocate some space, but check that the allocation was successful. */
616 /* alloca.c uses this, so don't make it static. */
624 rv = malloc (byte_count);
627 fprintf (stderr, "\n%s: fatal error: can't allocate %u more bytes of memory\n",
630 return 0; /* avoid warnings */
636 /* Reallocate some space, but check that the reallocation was successful. */
639 xrealloc (old_space, byte_count)
640 pointer_type old_space;
645 rv = realloc (old_space, byte_count);
648 fprintf (stderr, "\n%s: fatal error: can't allocate %u more bytes of memory\n",
651 return 0; /* avoid warnings */
657 /* Deallocate the area pointed to by an arbitrary pointer, but first, strip
658 the `const' qualifier from it and also make sure that the pointer value
663 const_pointer_type p;
666 free ((NONCONST pointer_type) p);
669 /* Make a copy of a string INPUT with size SIZE. */
672 savestring (input, size)
676 char *output = (char *) xmalloc (size + 1);
677 strcpy (output, input);
681 /* More 'friendly' abort that prints the line and file.
682 config.h can #define abort fancy_abort if you like that sort of thing. */
687 fprintf (stderr, "%s: internal abort\n", pname);
691 /* Make a duplicate of a given string in a newly allocated area. */
697 return strcpy ((char *) xmalloc (strlen (s) + 1), s);
700 /* Make a duplicate of the first N bytes of a given string in a newly
708 char *ret_val = strncpy ((char *) xmalloc (n + 1), s, n);
714 /* Return a pointer to the first occurance of s2 within s1 or NULL if s2
715 does not occur within s1. Assume neither s1 nor s2 are null pointers. */
720 const char *const s2;
728 for (p1 = s1, p2 = s2; c = *p2; p1++, p2++)
738 /* Get setup to recover in case the edit we are about to do goes awry. */
743 saved_clean_read_ptr = clean_read_ptr;
744 saved_repl_write_ptr = repl_write_ptr;
747 /* Call this routine to recover our previous state whenever something looks
748 too confusing in the source code we are trying to edit. */
753 clean_read_ptr = saved_clean_read_ptr;
754 repl_write_ptr = saved_repl_write_ptr;
757 /* Return true if the given character is a legal identifier character. */
763 return (isalnum (ch) || (ch == '_') || (ch == '$'));
766 /* Give a message indicating the proper way to invoke this program and then
767 exit with non-zero status. */
773 fprintf (stderr, "%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
775 #else /* !defined (UNPROTOIZE) */
776 fprintf (stderr, "%s: usage '%s [ -VqfnkNlgC ] [ -B <diname> ] [ filename ... ]'\n",
778 #endif /* !defined (UNPROTOIZE) */
782 /* Return true if the given filename (assumed to be an absolute filename)
783 designates a file residing anywhere beneath any one of the "system"
784 include directories. */
787 in_system_include_dir (path)
790 struct default_include *p;
793 abort (); /* Must be an absolutized filename. */
795 for (p = include_defaults; p->fname; p++)
796 if (!strncmp (path, p->fname, strlen (p->fname))
797 && path[strlen (p->fname)] == '/')
803 /* Return true if the given filename designates a file that the user has
804 read access to and for which the user has write access to the containing
808 file_could_be_converted (const char *path)
810 char *const dir_name = (char *) alloca (strlen (path) + 1);
812 if (my_access (path, R_OK))
816 char *dir_last_slash;
818 strcpy (dir_name, path);
819 dir_last_slash = strrchr (dir_name, '/');
821 *dir_last_slash = '\0';
823 abort (); /* Should have been an absolutized filename. */
826 if (my_access (path, W_OK))
832 /* Return true if the given filename designates a file that we are allowed
833 to modify. Files which we should not attempt to modify are (a) "system"
834 include files, and (b) files which the user doesn't have write access to,
835 and (c) files which reside in directories which the user doesn't have
836 write access to. Unless requested to be quiet, give warnings about
837 files that we will not try to convert for one reason or another. An
838 exception is made for "system" include files, which we never try to
839 convert and for which we don't issue the usual warnings. */
842 file_normally_convertable (const char *path)
844 char *const dir_name = alloca (strlen (path) + 1);
846 if (in_system_include_dir (path))
850 char *dir_last_slash;
852 strcpy (dir_name, path);
853 dir_last_slash = strrchr (dir_name, '/');
855 *dir_last_slash = '\0';
857 abort (); /* Should have been an absolutized filename. */
860 if (my_access (path, R_OK))
863 fprintf (stderr, "%s: warning: no read access for file `%s'\n",
864 pname, shortpath (NULL, path));
868 if (my_access (path, W_OK))
871 fprintf (stderr, "%s: warning: no write access for file `%s'\n",
872 pname, shortpath (NULL, path));
876 if (my_access (dir_name, W_OK))
879 fprintf (stderr, "%s: warning: no write access for dir containing `%s'\n",
880 pname, shortpath (NULL, path));
890 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X
891 file. Return false otherwise. */
894 is_syscalls_file (fi_p)
895 const file_info *fi_p;
897 return (substr (fi_p->hash_entry->symbol, syscalls_filename) != NULL);
900 #endif /* !defined (UNPROTOIZE) */
902 /* Check to see if this file will need to have anything done to it on this
903 run. If there is nothing in the given file which both needs conversion
904 and for which we have the necessary stuff to do the conversion, return
905 false. Otherwise, return true.
907 Note that (for protoize) it is only valid to call this function *after*
908 the connections between declarations and definitions have all been made
909 by connect_defs_and_decs. */
912 needs_to_be_converted (file_p)
913 const file_info *file_p;
915 const def_dec_info *ddp;
919 if (is_syscalls_file (file_p))
922 #endif /* !defined (UNPROTOIZE) */
924 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
930 /* ... and if we a protoizing and this function is in old style ... */
932 /* ... and if this a definition or is a decl with an associated def ... */
933 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
935 #else /* defined (UNPROTOIZE) */
937 /* ... and if we are unprotoizing and this function is in new style ... */
940 #endif /* defined (UNPROTOIZE) */
942 /* ... then the containing file needs converting. */
947 /* Return 1 if the file name NAME is in a directory
948 that should be converted. */
951 directory_specified_p (name)
954 struct string_list *p;
956 for (p = directory_list; p; p = p->next)
957 if (!strncmp (name, p->name, strlen (p->name))
958 && name[strlen (p->name)] == '/')
960 const char *q = name + strlen (p->name) + 1;
962 /* If there are more slashes, it's in a subdir, so
963 this match doesn't count. */
975 /* Return 1 if the file named NAME should be excluded from conversion. */
978 file_excluded_p (name)
981 struct string_list *p;
982 int len = strlen (name);
984 for (p = exclude_list; p; p = p->next)
985 if (!strcmp (name + len - strlen (p->name), p->name)
986 && name[len - strlen (p->name) - 1] == '/')
992 /* Construct a new element of a string_list.
993 STRING is the new element value, and REST holds the remaining elements. */
995 static struct string_list *
996 string_list_cons (string, rest)
998 struct string_list *rest;
1000 struct string_list *temp
1001 = (struct string_list *) xmalloc (sizeof (struct string_list));
1004 temp->name = string;
1008 /* ??? The GNU convention for mentioning function args in its comments
1009 is to capitalize them. So change "hash_tab_p" to HASH_TAB_P below.
1010 Likewise for all the other functions. */
1012 /* Given a hash table, apply some function to each node in the table. The
1013 table to traverse is given as the "hash_tab_p" argument, and the
1014 function to be applied to each node in the table is given as "func"
1018 visit_each_hash_node (hash_tab_p, func)
1019 const hash_table_entry *hash_tab_p;
1022 const hash_table_entry *primary;
1024 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
1025 if (primary->symbol)
1027 hash_table_entry *second;
1030 for (second = primary->hash_next; second; second = second->hash_next)
1035 /* Initialize all of the fields of a new hash table entry, pointed
1036 to by the "p" parameter. Note that the space to hold the entry
1037 is assumed to have already been allocated before this routine is
1040 static hash_table_entry *
1042 hash_table_entry *p;
1045 p->hash_next = NULL;
1046 p->symbol = dupstr (s);
1052 /* Look for a particular function name or filename in the particular
1053 hash table indicated by "hash_tab_p". If the name is not in the
1054 given hash table, add it. Either way, return a pointer to the
1055 hash table entry for the given name. */
1057 static hash_table_entry *
1058 lookup (hash_tab_p, search_symbol)
1059 hash_table_entry *hash_tab_p;
1060 const char *search_symbol;
1063 const char *search_symbol_char_p = search_symbol;
1064 hash_table_entry *p;
1066 while (*search_symbol_char_p)
1067 hash_value += *search_symbol_char_p++;
1068 hash_value &= hash_mask;
1069 p = &hash_tab_p[hash_value];
1071 return add_symbol (p, search_symbol);
1072 if (!strcmp (p->symbol, search_symbol))
1074 while (p->hash_next)
1077 if (!strcmp (p->symbol, search_symbol))
1080 p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry));
1082 return add_symbol (p, search_symbol);
1085 /* Throw a def/dec record on the junk heap.
1087 Also, since we are not using this record anymore, free up all of the
1088 stuff it pointed to. */
1094 xfree (p->ansi_decl);
1098 const f_list_chain_item * curr;
1099 const f_list_chain_item * next;
1101 for (curr = p->f_list_chain; curr; curr = next)
1103 next = curr->chain_next;
1107 #endif /* !defined (UNPROTOIZE) */
1112 /* Unexpand as many macro symbol as we can find.
1114 If the given line must be unexpanded, make a copy of it in the heap and
1115 return a pointer to the unexpanded copy. Otherwise return NULL. */
1118 unexpand_if_needed (aux_info_line)
1119 const char *aux_info_line;
1121 static char *line_buf = 0;
1122 static int line_buf_size = 0;
1123 const unexpansion* unexp_p;
1124 int got_unexpanded = 0;
1126 char *copy_p = line_buf;
1130 line_buf_size = 1024;
1131 line_buf = (char *) xmalloc (line_buf_size);
1136 /* Make a copy of the input string in line_buf, expanding as necessary. */
1138 for (s = aux_info_line; *s != '\n'; )
1140 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
1142 const char *in_p = unexp_p->expanded;
1143 size_t len = strlen (in_p);
1145 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1147 int size = strlen (unexp_p->contracted);
1149 if (copy_p + size - line_buf >= line_buf_size)
1151 int offset = copy_p - line_buf;
1153 line_buf_size += size;
1154 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1155 copy_p = line_buf + offset;
1157 strcpy (copy_p, unexp_p->contracted);
1160 /* Assume the there will not be another replacement required
1161 within the text just replaced. */
1164 goto continue_outer;
1167 if (copy_p - line_buf == line_buf_size)
1169 int offset = copy_p - line_buf;
1171 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1172 copy_p = line_buf + offset;
1177 if (copy_p + 2 - line_buf >= line_buf_size)
1179 int offset = copy_p - line_buf;
1181 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1182 copy_p = line_buf + offset;
1187 return (got_unexpanded ? dupstr (line_buf) : 0);
1190 /* Return the absolutized filename for the given relative
1191 filename. Note that if that filename is already absolute, it may
1192 still be returned in a modified form because this routine also
1193 eliminates redundant slashes and single dots and eliminates double
1194 dots to get a shortest possible filename from the given input
1195 filename. The absolutization of relative filenames is made by
1196 assuming that the given filename is to be taken as relative to
1197 the first argument (cwd) or to the current directory if cwd is
1201 abspath (cwd, rel_filename)
1203 const char *rel_filename;
1205 /* Setup the current working directory as needed. */
1206 const char *cwd2 = (cwd) ? cwd : cwd_buffer;
1207 char *const abs_buffer
1208 = (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 2);
1209 char *endp = abs_buffer;
1212 /* Copy the filename (possibly preceded by the current working
1213 directory name) into the absolutization buffer. */
1218 if (rel_filename[0] != '/')
1221 while (*endp++ = *src_p++)
1223 *(endp-1) = '/'; /* overwrite null */
1225 src_p = rel_filename;
1226 while (*endp++ = *src_p++)
1228 if (endp[-1] == '/')
1232 /* Now make a copy of abs_buffer into abs_buffer, shortening the
1233 filename (by taking out slashes and dots) as we go. */
1235 outp = inp = abs_buffer;
1236 *outp++ = *inp++; /* copy first slash */
1241 else if (inp[0] == '/' && outp[-1] == '/')
1246 else if (inp[0] == '.' && outp[-1] == '/')
1250 else if (inp[1] == '/')
1255 else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/'))
1257 inp += (inp[2] == '/') ? 3 : 2;
1259 while (outp >= abs_buffer && *outp != '/')
1261 if (outp < abs_buffer)
1263 /* Catch cases like /.. where we try to backup to a
1264 point above the absolute root of the logical file
1267 fprintf (stderr, "%s: invalid file name: %s\n",
1268 pname, rel_filename);
1278 /* On exit, make sure that there is a trailing null, and make sure that
1279 the last character of the returned string is *not* a slash. */
1282 if (outp[-1] == '/')
1285 /* Make a copy (in the heap) of the stuff left in the absolutization
1286 buffer and return a pointer to the copy. */
1288 return dupstr (abs_buffer);
1291 /* Given a filename (and possibly a directory name from which the filename
1292 is relative) return a string which is the shortest possible
1293 equivalent for the corresponding full (absolutized) filename. The
1294 shortest possible equivalent may be constructed by converting the
1295 absolutized filename to be a relative filename (i.e. relative to
1296 the actual current working directory). However if a relative filename
1297 is longer, then the full absolute filename is returned.
1301 Note that "simple-minded" conversion of any given type of filename (either
1302 relative or absolute) may not result in a valid equivalent filename if any
1303 subpart of the original filename is actually a symbolic link. */
1306 shortpath (cwd, filename)
1308 const char *filename;
1312 char *cwd_p = cwd_buffer;
1314 int unmatched_slash_count = 0;
1316 path_p = abspath (cwd, filename);
1317 rel_buf_p = rel_buffer = (char *) xmalloc (strlen (path_p) + 1);
1319 while (*cwd_p && (*cwd_p == *path_p))
1324 if (!*cwd_p) /* whole pwd matched */
1326 if (!*path_p) /* input *is* the current path! */
1337 while (*cwd_p != '/') /* backup to last slash */
1344 unmatched_slash_count++;
1347 if (*cwd_p++ == '/')
1348 unmatched_slash_count++;
1349 while (unmatched_slash_count--)
1355 while (*rel_buf_p++ = *path_p++)
1358 if (*(rel_buf_p-1) == '/')
1359 *--rel_buf_p = '\0';
1360 if (strlen (rel_buffer) > (unsigned) strlen (filename))
1361 strcpy (rel_buffer, filename);
1366 /* Lookup the given filename in the hash table for filenames. If it is a
1367 new one, then the hash table info pointer will be null. In this case,
1368 we create a new file_info record to go with the filename, and we initialize
1369 that record with some reasonable values. */
1372 find_file (filename, do_not_stat)
1375 /* FILENAME was const, but that causes a warning on AIX when calling stat.
1376 That is probably a bug in AIX, but might as well avoid the warning. */
1378 hash_table_entry *hash_entry_p;
1380 hash_entry_p = lookup (filename_primary, filename);
1381 if (hash_entry_p->fip)
1382 return hash_entry_p->fip;
1385 struct stat stat_buf;
1386 file_info *file_p = (file_info *) xmalloc (sizeof (file_info));
1388 /* If we cannot get status on any given source file, give a warning
1389 and then just set its time of last modification to infinity. */
1392 stat_buf.st_mtime = (time_t) 0;
1395 if (my_stat (filename, &stat_buf) == -1)
1397 fprintf (stderr, "%s: error: can't get status of `%s': %s\n",
1398 pname, shortpath (NULL, filename), sys_errlist[errno]);
1399 stat_buf.st_mtime = (time_t) -1;
1403 hash_entry_p->fip = file_p;
1404 file_p->hash_entry = hash_entry_p;
1405 file_p->defs_decs = NULL;
1406 file_p->mtime = stat_buf.st_mtime;
1411 /* Generate a fatal error because some part of the aux_info file is
1415 aux_info_corrupted ()
1417 fprintf (stderr, "\n%s: fatal error: aux info file corrupted at line %d\n",
1418 pname, current_aux_info_lineno);
1422 /* ??? This comment is vague. Say what the condition is for. */
1423 /* Check to see that a condition is true. This is kind of like an assert. */
1426 check_aux_info (cond)
1430 aux_info_corrupted ();
1433 /* Given a pointer to the closing right parenthesis for a particular formals
1434 list (in a aux_info file) find the corresponding left parenthesis and
1435 return a pointer to it. */
1438 find_corresponding_lparen (p)
1444 for (paren_depth = 1, q = p-1; paren_depth; q--)
1459 /* Given a line from an aux info file, and a time at which the aux info
1460 file it came from was created, check to see if the item described in
1461 the line comes from a file which has been modified since the aux info
1462 file was created. If so, return non-zero, else return zero. */
1465 referenced_file_is_newer (l, aux_info_mtime)
1467 time_t aux_info_mtime;
1473 check_aux_info (l[0] == '/');
1474 check_aux_info (l[1] == '*');
1475 check_aux_info (l[2] == ' ');
1478 const char *filename_start = p = l + 3;
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';
1487 /* Call find_file to find the file_info record associated with the file
1488 which contained this particular def or dec item. Note that this call
1489 may cause a new file_info record to be created if this is the first time
1490 that we have ever known about this particular file. */
1492 fi_p = find_file (abspath (invocation_filename, filename), 0);
1494 return (fi_p->mtime > aux_info_mtime);
1497 /* Given a line of info from the aux_info file, create a new
1498 def_dec_info record to remember all of the important information about
1499 a function definition or declaration.
1501 Link this record onto the list of such records for the particular file in
1502 which it occurred in proper (descending) line number order (for now).
1504 If there is an identical record already on the list for the file, throw
1505 this one away. Doing so takes care of the (useless and troublesome)
1506 duplicates which are bound to crop up due to multiple inclusions of any
1507 given individual header file.
1509 Finally, link the new def_dec record onto the list of such records
1510 pertaining to this particular function name. */
1513 save_def_or_dec (l, is_syscalls)
1518 const char *semicolon_p;
1519 def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info));
1522 def_dec_p->written = 0;
1523 #endif /* !defined (UNPROTOIZE) */
1525 /* Start processing the line by picking off 5 pieces of information from
1526 the left hand end of the line. These are filename, line number,
1527 new/old/implicit flag (new = ANSI prototype format), definition or
1528 declaration flag, and extern/static flag). */
1530 check_aux_info (l[0] == '/');
1531 check_aux_info (l[1] == '*');
1532 check_aux_info (l[2] == ' ');
1535 const char *filename_start = p = l + 3;
1540 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1541 strncpy (filename, filename_start, (size_t) (p - filename_start));
1542 filename[p-filename_start] = '\0';
1544 /* Call find_file to find the file_info record associated with the file
1545 which contained this particular def or dec item. Note that this call
1546 may cause a new file_info record to be created if this is the first time
1547 that we have ever known about this particular file.
1549 Note that we started out by forcing all of the base source file names
1550 (i.e. the names of the aux_info files with the .X stripped off) into the
1551 filenames hash table, and we simultaneously setup file_info records for
1552 all of these base file names (even if they may be useless later).
1553 The file_info records for all of these "base" file names (properly)
1554 act as file_info records for the "original" (i.e. un-included) files
1555 which were submitted to gcc for compilation (when the -fgen-aux-info
1556 option was used). */
1558 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1562 const char *line_number_start = ++p;
1563 char line_number[10];
1567 strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1568 line_number[p-line_number_start] = '\0';
1569 def_dec_p->line = atoi (line_number);
1572 /* Check that this record describes a new-style, old-style, or implicit
1573 definition or declaration. */
1575 p++; /* Skip over the `:'. */
1576 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1578 /* Is this a new style (ANSI prototyped) definition or declaration? */
1580 def_dec_p->prototyped = (*p == 'N');
1584 /* Is this an implicit declaration? */
1586 def_dec_p->is_implicit = (*p == 'I');
1588 #endif /* !defined (UNPROTOIZE) */
1592 check_aux_info ((*p == 'C') || (*p == 'F'));
1594 /* Is this item a function definition (F) or a declaration (C). Note that
1595 we treat item taken from the syscalls file as though they were function
1596 definitions regardless of what the stuff in the file says. */
1598 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1601 def_dec_p->definition = 0; /* Fill this in later if protoizing. */
1602 #endif /* !defined (UNPROTOIZE) */
1604 check_aux_info (*p++ == ' ');
1605 check_aux_info (*p++ == '*');
1606 check_aux_info (*p++ == '/');
1607 check_aux_info (*p++ == ' ');
1610 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1611 #else /* !defined (UNPROTOIZE) */
1612 if (!strncmp (p, "static", 6))
1613 def_dec_p->is_static = -1;
1614 else if (!strncmp (p, "extern", 6))
1615 def_dec_p->is_static = 0;
1617 check_aux_info (0); /* Didn't find either `extern' or `static'. */
1618 #endif /* !defined (UNPROTOIZE) */
1621 const char *ansi_start = p;
1623 p += 6; /* Pass over the "static" or "extern". */
1625 /* We are now past the initial stuff. Search forward from here to find
1626 the terminating semicolon that should immediately follow the entire
1627 ANSI format function declaration. */
1634 /* Make a copy of the ansi declaration part of the line from the aux_info
1637 def_dec_p->ansi_decl
1638 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1641 /* Backup and point at the final right paren of the final argument list. */
1645 /* Now isolate a whole set of formal argument lists, one-by-one. Normally,
1646 there will only be one list to isolate, but there could be more. */
1648 def_dec_p->f_list_count = 0;
1651 def_dec_p->f_list_chain = NULL;
1652 #endif /* !defined (UNPROTOIZE) */
1656 const char *left_paren_p = find_corresponding_lparen (p);
1659 f_list_chain_item *cip =
1660 (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
1663 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1665 /* Add the new chain item at the head of the current list. */
1667 cip->chain_next = def_dec_p->f_list_chain;
1668 def_dec_p->f_list_chain = cip;
1670 #endif /* !defined (UNPROTOIZE) */
1671 def_dec_p->f_list_count++;
1673 p = left_paren_p - 2;
1675 /* p must now point either to another right paren, or to the last
1676 character of the name of the function that was declared/defined.
1677 If p points to another right paren, then this indicates that we
1678 are dealing with multiple formals lists. In that case, there
1679 really should be another right paren preceding this right paren. */
1684 check_aux_info (*--p == ')');
1689 const char *past_fn = p + 1;
1691 check_aux_info (*past_fn == ' ');
1693 /* Scan leftwards over the identifier that names the function. */
1695 while (is_id_char (*p))
1699 /* p now points to the leftmost character of the function name. */
1702 char *fn_string = (char *) alloca (past_fn - p + 1);
1704 strncpy (fn_string, p, (size_t) (past_fn - p));
1705 fn_string[past_fn-p] = '\0';
1706 def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1710 /* Look at all of the defs and decs for this function name that we have
1711 collected so far. If there is already one which is at the same
1712 line number in the same file, then we can discard this new def_dec_info
1715 As an extra assurance that any such pair of (nominally) identical
1716 function declarations are in fact identical, we also compare the
1717 ansi_decl parts of the lines from the aux_info files just to be on
1720 This comparison will fail if (for instance) the user was playing
1721 messy games with the preprocessor which ultimately causes one
1722 function declaration in one header file to look differently when
1723 that file is included by two (or more) other files. */
1726 const def_dec_info *other;
1728 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1730 if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1732 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1734 fprintf (stderr, "%s: error: declaration of function `%s' at %s(%d) takes different forms\n",
1736 def_dec_p->hash_entry->symbol,
1737 def_dec_p->file->hash_entry->symbol,
1741 free_def_dec (def_dec_p);
1749 /* If we are doing unprotoizing, we must now setup the pointers that will
1750 point to the K&R name list and to the K&R argument declarations list.
1752 Note that if this is only a function declaration, then we should not
1753 expect to find any K&R style formals list following the ANSI-style
1754 formals list. This is because GCC knows that such information is
1755 useless in the case of function declarations (function definitions
1756 are a different story however).
1758 Since we are unprotoizing, we don't need any such lists anyway.
1759 All we plan to do is to delete all characters between ()'s in any
1762 def_dec_p->formal_names = NULL;
1763 def_dec_p->formal_decls = NULL;
1765 if (def_dec_p->is_func_def)
1768 check_aux_info (*++p == ' ');
1769 check_aux_info (*++p == '/');
1770 check_aux_info (*++p == '*');
1771 check_aux_info (*++p == ' ');
1772 check_aux_info (*++p == '(');
1775 const char *kr_names_start = ++p; /* Point just inside '('. */
1779 p--; /* point to closing right paren */
1781 /* Make a copy of the K&R parameter names list. */
1783 def_dec_p->formal_names
1784 = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1787 check_aux_info (*++p == ' ');
1790 /* p now points to the first character of the K&R style declarations
1791 list (if there is one) or to the star-slash combination that ends
1792 the comment in which such lists get embedded. */
1794 /* Make a copy of the K&R formal decls list and set the def_dec record
1797 if (*p == '*') /* Are there no K&R declarations? */
1799 check_aux_info (*++p == '/');
1800 def_dec_p->formal_decls = "";
1804 const char *kr_decls_start = p;
1806 while (p[0] != '*' || p[1] != '/')
1810 check_aux_info (*p == ' ');
1812 def_dec_p->formal_decls
1813 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1816 /* Handle a special case. If we have a function definition marked as
1817 being in "old" style, and if it's formal names list is empty, then
1818 it may actually have the string "void" in its real formals list
1819 in the original source code. Just to make sure, we will get setup
1820 to convert such things anyway.
1822 This kludge only needs to be here because of an insurmountable
1823 problem with generating .X files. */
1825 if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1826 def_dec_p->prototyped = 1;
1829 /* Since we are unprotoizing, if this item is already in old (K&R) style,
1830 we can just ignore it. If that is true, throw away the itme now. */
1832 if (!def_dec_p->prototyped)
1834 free_def_dec (def_dec_p);
1838 #endif /* defined (UNPROTOIZE) */
1840 /* Add this record to the head of the list of records pertaining to this
1841 particular function name. */
1843 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1844 def_dec_p->hash_entry->ddip = def_dec_p;
1846 /* Add this new def_dec_info record to the sorted list of def_dec_info
1847 records for this file. Note that we don't have to worry about duplicates
1848 (caused by multiple inclusions of header files) here because we have
1849 already eliminated duplicates above. */
1851 if (!def_dec_p->file->defs_decs)
1853 def_dec_p->file->defs_decs = def_dec_p;
1854 def_dec_p->next_in_file = NULL;
1858 int line = def_dec_p->line;
1859 const def_dec_info *prev = NULL;
1860 const def_dec_info *curr = def_dec_p->file->defs_decs;
1861 const def_dec_info *next = curr->next_in_file;
1863 while (next && (line < curr->line))
1867 next = next->next_in_file;
1869 if (line >= curr->line)
1871 def_dec_p->next_in_file = curr;
1873 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1875 def_dec_p->file->defs_decs = def_dec_p;
1877 else /* assert (next == NULL); */
1879 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
1880 /* assert (next == NULL); */
1881 def_dec_p->next_in_file = next;
1886 /* Rewrite the options list used to recompile base source files. All we are
1887 really doing here is removing -g, -O, -S, -c, and -o options, and then
1888 adding a final group of options like '-fgen-aux-info -S -o /dev/null'. */
1891 munge_compile_params (params_list)
1892 const char *params_list;
1895 = (char **) alloca ((strlen (params_list) + 6) * sizeof (char *));
1896 int param_count = 0;
1899 temp_params[param_count++] = compiler_file_name;
1902 while (isspace (*params_list))
1906 param = params_list;
1907 while (*params_list && !isspace (*params_list))
1909 if (param[0] != '-')
1910 temp_params[param_count++]
1911 = dupnstr (param, (size_t) (params_list - param));
1920 break; /* Don't copy these. */
1922 while (isspace (*params_list))
1924 while (*params_list && !isspace (*params_list))
1928 temp_params[param_count++]
1929 = dupnstr (param, (size_t) (params_list - param));
1935 temp_params[param_count++] = "-fgen-aux-info";
1936 temp_params[param_count++] = "-S";
1937 temp_params[param_count++] = "-o";
1938 temp_params[param_count++] = "/dev/null";
1940 /* Leave room for the filename argument and a terminating null pointer. */
1942 temp_params[filename_index = param_count++] = NULL;
1943 temp_params[param_count++] = NULL;
1945 /* Make a copy of the compile_params in heap space. */
1948 = (const char **) xmalloc (sizeof (char *) * (param_count+1));
1949 memcpy (compile_params, temp_params, sizeof (char *) * param_count);
1952 /* Do a recompilation for the express purpose of generating a new aux_info
1953 file to go with a specific base source file. */
1956 gen_aux_info_file (base_filename)
1957 const char *base_filename;
1961 if (!filename_index)
1962 munge_compile_params ("");
1964 compile_params[filename_index] = shortpath (NULL, base_filename);
1967 fprintf (stderr, "%s: compiling `%s'\n",
1968 pname, compile_params[filename_index]);
1970 if (child_pid = fork ())
1972 if (child_pid == -1)
1974 fprintf (stderr, "%s: error: could not fork process: %s\n",
1975 pname, sys_errlist[errno]);
1980 /* Print out the command line that the other process is now executing. */
1986 fputs ("\t", stderr);
1987 for (arg = compile_params; *arg; arg++)
1989 fputs (*arg, stderr);
1990 fputc (' ', stderr);
1992 fputc ('\n', stderr);
2000 if (wait (&wait_status) == -1)
2002 fprintf (stderr, "%s: error: wait for process failed: %s\n",
2003 pname, sys_errlist[errno]);
2006 if (!WIFEXITED (wait_status))
2008 kill (child_pid, 9);
2011 return (WEXITSTATUS (wait_status) == 0) ? 1 : 0;
2016 if (my_execvp (compile_params[0], (char *const *) compile_params))
2018 fprintf (stderr, "%s: error: execvp returned: %s\n",
2019 pname, sys_errlist[errno]);
2022 return 1; /* Never executed. */
2026 /* Read in all of the information contained in a single aux_info file.
2027 Save all of the important stuff for later. */
2030 process_aux_info_file (base_source_filename, keep_it, is_syscalls)
2031 const char *base_source_filename;
2035 char *const aux_info_filename
2036 = (char *) alloca (strlen (base_source_filename)
2037 + strlen (aux_info_suffix) + 1);
2038 char *aux_info_base;
2039 char *aux_info_limit;
2040 const char *aux_info_second_line;
2041 time_t aux_info_mtime;
2042 size_t aux_info_size;
2044 /* Construct the aux_info filename from the base source filename. */
2046 strcpy (aux_info_filename, base_source_filename);
2047 strcat (aux_info_filename, aux_info_suffix);
2049 /* Check that the aux_info file exists and is readable. If it does not
2050 exist, try to create it (once only). */
2058 if (my_access (aux_info_filename, R_OK) == -1)
2060 if (errno == ENOENT && retries == 0)
2064 fprintf (stderr, "%s: warning: missing SYSCALLS file `%s'\n",
2065 pname, aux_info_filename);
2068 if (!gen_aux_info_file (base_source_filename))
2075 fprintf (stderr, "%s: error: can't read aux info file `%s': %s\n",
2076 pname, shortpath (NULL, aux_info_filename),
2077 sys_errlist[errno]);
2085 struct stat stat_buf;
2087 /* Get some status information about this aux_info file. */
2089 if (my_stat (aux_info_filename, &stat_buf) == -1)
2091 fprintf (stderr, "%s: error: can't get status of aux info file `%s': %s\n",
2092 pname, shortpath (NULL, aux_info_filename),
2093 sys_errlist[errno]);
2098 /* Check on whether or not this aux_info file is zero length. If it is,
2099 then just ignore it and return. */
2101 if ((aux_info_size = stat_buf.st_size) == 0)
2104 /* Get the date/time of last modification for this aux_info file and
2105 remember it. We will have to check that any source files that it
2106 contains information about are at least this old or older. */
2108 aux_info_mtime = stat_buf.st_mtime;
2114 /* Open the aux_info file. */
2116 if ((aux_info_file = my_open (aux_info_filename, O_RDONLY, 0444 )) == -1)
2118 fprintf (stderr, "%s: error: can't open aux info file `%s' for reading: %s\n",
2119 pname, shortpath (NULL, aux_info_filename),
2120 sys_errlist[errno]);
2124 /* Allocate space to hold the aux_info file in memory. */
2126 aux_info_base = xmalloc (aux_info_size + 1);
2127 aux_info_limit = aux_info_base + aux_info_size;
2128 *aux_info_limit = '\0';
2130 /* Read the aux_info file into memory. */
2132 if (read (aux_info_file, aux_info_base, aux_info_size) != aux_info_size)
2134 fprintf (stderr, "%s: error: while reading aux info file `%s': %s\n",
2135 pname, shortpath (NULL, aux_info_filename),
2136 sys_errlist[errno]);
2137 free (aux_info_base);
2138 close (aux_info_file);
2142 /* Close the aux info file. */
2144 if (close (aux_info_file))
2146 fprintf (stderr, "%s: error: while closing aux info file `%s': %s\n",
2147 pname, shortpath (NULL, aux_info_filename),
2148 sys_errlist[errno]);
2149 free (aux_info_base);
2150 close (aux_info_file);
2155 /* Delete the aux_info file (unless requested not to). If the deletion
2156 fails for some reason, don't even worry about it. */
2159 if (my_unlink (aux_info_filename) == -1)
2160 fprintf (stderr, "%s: error: can't delete aux info file `%s': %s\n",
2161 pname, shortpath (NULL, aux_info_filename),
2162 sys_errlist[errno]);
2164 /* Save a pointer into the first line of the aux_info file which
2165 contains the filename of the directory from which the compiler
2166 was invoked when the associated source file was compiled.
2167 This information is used later to help create complete
2168 filenames out of the (potentially) relative filenames in
2169 the aux_info file. */
2172 char *p = aux_info_base;
2179 invocation_filename = p; /* Save a pointer to first byte of path. */
2184 while (*p++ != '\n')
2186 aux_info_second_line = p;
2191 const char *aux_info_p;
2193 /* Do a pre-pass on the lines in the aux_info file, making sure that all
2194 of the source files referenced in there are at least as old as this
2195 aux_info file itself. If not, go back and regenerate the aux_info
2196 file anew. Don't do any of this for the syscalls file. */
2200 current_aux_info_lineno = 2;
2202 for (aux_info_p = aux_info_second_line; *aux_info_p; )
2204 if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2206 free (aux_info_base);
2207 if (my_unlink (aux_info_filename) == -1)
2209 fprintf (stderr, "%s: error: can't delete file `%s': %s\n",
2210 pname, shortpath (NULL, aux_info_filename),
2211 sys_errlist[errno]);
2217 /* Skip over the rest of this line to start of next line. */
2219 while (*aux_info_p != '\n')
2222 current_aux_info_lineno++;
2226 /* Now do the real pass on the aux_info lines. Save their information in
2227 the in-core data base. */
2229 current_aux_info_lineno = 2;
2231 for (aux_info_p = aux_info_second_line; *aux_info_p;)
2233 char *unexpanded_line = unexpand_if_needed (aux_info_p);
2235 if (unexpanded_line)
2237 save_def_or_dec (unexpanded_line, is_syscalls);
2238 free (unexpanded_line);
2241 save_def_or_dec (aux_info_p, is_syscalls);
2243 /* Skip over the rest of this line and get to start of next line. */
2245 while (*aux_info_p != '\n')
2248 current_aux_info_lineno++;
2252 free (aux_info_base);
2257 /* Check an individual filename for a .c suffix. If the filename has this
2258 suffix, rename the file such that its suffix is changed to .C. This
2259 function implements the -C option. */
2263 const hash_table_entry *hp;
2265 const char *filename = hp->symbol;
2266 int last_char_index = strlen (filename) - 1;
2267 char *const new_filename = (char *) alloca (strlen (filename) + 1);
2269 /* Note that we don't care here if the given file was converted or not. It
2270 is possible that the given file was *not* converted, simply because there
2271 was nothing in it which actually required conversion. Even in this case,
2272 we want to do the renaming. Note that we only rename files with the .c
2275 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.')
2278 strcpy (new_filename, filename);
2279 new_filename[last_char_index] = 'C';
2281 if (my_link (filename, new_filename) == -1)
2283 fprintf (stderr, "%s: warning: can't link file `%s' to `%s': %s\n",
2284 pname, shortpath (NULL, filename),
2285 shortpath (NULL, new_filename), sys_errlist[errno]);
2290 if (my_unlink (filename) == -1)
2292 fprintf (stderr, "%s: warning: can't delete file `%s': %s\n",
2293 pname, shortpath (NULL, filename), sys_errlist[errno]);
2299 #endif /* !defined (UNPROTOIZE) */
2301 /* Take the list of definitions and declarations attached to a particular
2302 file_info node and reverse the order of the list. This should get the
2303 list into an order such that the item with the lowest associated line
2304 number is nearest the head of the list. When these lists are originally
2305 built, they are in the opposite order. We want to traverse them in
2306 normal line number order later (i.e. lowest to highest) so reverse the
2310 reverse_def_dec_list (hp)
2311 const hash_table_entry *hp;
2313 file_info *file_p = hp->fip;
2314 const def_dec_info *prev = NULL;
2315 const def_dec_info *current = file_p->defs_decs;
2317 if (!( current = file_p->defs_decs))
2318 return; /* no list to reverse */
2321 if (! (current = current->next_in_file))
2322 return; /* can't reverse a single list element */
2324 ((NONCONST def_dec_info *) prev)->next_in_file = NULL;
2328 const def_dec_info *next = current->next_in_file;
2330 ((NONCONST def_dec_info *) current)->next_in_file = prev;
2335 file_p->defs_decs = prev;
2340 /* Find the (only?) extern definition for a particular function name, starting
2341 from the head of the linked list of entries for the given name. If we
2342 cannot find an extern definition for the given function name, issue a
2343 warning and scrounge around for the next best thing, i.e. an extern
2344 function declaration with a prototype attached to it. Note that we only
2345 allow such substitutions for extern declarations and never for static
2346 declarations. That's because the only reason we allow them at all is
2347 to let un-prototyped function declarations for system-supplied library
2348 functions get their prototypes from our own extra SYSCALLS.c.X file which
2349 contains all of the correct prototypes for system functions. */
2351 static const def_dec_info *
2352 find_extern_def (head, user)
2353 const def_dec_info *head;
2354 const def_dec_info *user;
2356 const def_dec_info *dd_p;
2357 const def_dec_info *extern_def_p = NULL;
2358 int conflict_noted = 0;
2360 /* Don't act too stupid here. Somebody may try to convert an entire system
2361 in one swell fwoop (rather than one program at a time, as should be done)
2362 and in that case, we may find that there are multiple extern definitions
2363 of a given function name in the entire set of source files that we are
2364 converting. If however one of these definitions resides in exactly the
2365 same source file as the reference we are trying to satisfy then in that
2366 case it would be stupid for us to fail to realize that this one definition
2367 *must* be the precise one we are looking for.
2369 To make sure that we don't miss an opportunity to make this "same file"
2370 leap of faith, we do a prescan of the list of records relating to the
2371 given function name, and we look (on this first scan) *only* for a
2372 definition of the function which is in the same file as the reference
2373 we are currently trying to satisfy. */
2375 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2376 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2379 /* Now, since we have not found a definition in the same file as the
2380 reference, we scan the list again and consider all possibilities from
2381 all files. Here we may get conflicts with the things listed in the
2382 SYSCALLS.c.X file, but if that happens it only means that the source
2383 code being converted contains its own definition of a function which
2384 could have been supplied by libc.a. In such cases, we should avoid
2385 issuing the normal warning, and defer to the definition given in the
2388 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2389 if (dd_p->is_func_def && !dd_p->is_static)
2391 if (!extern_def_p) /* Previous definition? */
2392 extern_def_p = dd_p; /* Remember the first definition found. */
2395 /* Ignore definition just found if it came from SYSCALLS.c.X. */
2397 if (is_syscalls_file (dd_p->file))
2400 /* Quietly replace the definition previously found with the one
2401 just found if the previous one was from SYSCALLS.c.X. */
2403 if (is_syscalls_file (extern_def_p->file))
2405 extern_def_p = dd_p;
2409 /* If we get here, then there is a conflict between two function
2410 declarations for the same function, both of which came from the
2413 if (!conflict_noted) /* first time we noticed? */
2416 fprintf (stderr, "%s: error: conflicting extern definitions of '%s'\n",
2417 pname, head->hash_entry->symbol);
2420 fprintf (stderr, "%s: declarations of '%s' will not be converted\n",
2421 pname, head->hash_entry->symbol);
2422 fprintf (stderr, "%s: conflict list for '%s' follows:\n",
2423 pname, head->hash_entry->symbol);
2424 fprintf (stderr, "%s: %s(%d): %s\n",
2426 shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2427 extern_def_p->line, extern_def_p->ansi_decl);
2431 fprintf (stderr, "%s: %s(%d): %s\n",
2433 shortpath (NULL, dd_p->file->hash_entry->symbol),
2434 dd_p->line, dd_p->ansi_decl);
2438 /* We want to err on the side of caution, so if we found multiple conflicting
2439 definitions for the same function, treat this as being that same as if we
2440 had found no definitions (i.e. return NULL). */
2447 /* We have no definitions for this function so do the next best thing.
2448 Search for an extern declaration already in prototype form. */
2450 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2451 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2453 extern_def_p = dd_p; /* save a pointer to the definition */
2455 fprintf (stderr, "%s: warning: using formals list from %s(%d) for function `%s'\n",
2457 shortpath (NULL, dd_p->file->hash_entry->symbol),
2458 dd_p->line, dd_p->hash_entry->symbol);
2462 /* Gripe about unprototyped function declarations that we found no
2463 corresponding definition (or other source of prototype information)
2466 Gripe even if the unprototyped declaration we are worried about
2467 exists in a file in one of the "system" include directories. We
2468 can gripe about these because we should have at least found a
2469 corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
2470 didn't, then that means that the SYSCALLS.c.X file is missing some
2471 needed prototypes for this particular system. That is worth telling
2476 const char *file = user->file->hash_entry->symbol;
2479 if (in_system_include_dir (file))
2481 /* Why copy this string into `needed' at all?
2482 Why not just use user->ansi_decl without copying? */
2483 char *needed = (char *) alloca (strlen (user->ansi_decl) + 1);
2486 strcpy (needed, user->ansi_decl);
2487 p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
2488 + strlen (user->hash_entry->symbol) + 2;
2489 strcpy (p, "??\?);");
2491 fprintf (stderr, "%s: %d: `%s' used but missing from SYSCALLS\n",
2492 shortpath (NULL, file), user->line,
2493 needed+7); /* Don't print "extern " */
2496 fprintf (stderr, "%s: %d: warning: no extern definition for `%s'\n",
2497 shortpath (NULL, file), user->line,
2498 user->hash_entry->symbol);
2501 return extern_def_p;
2504 /* Find the (only?) static definition for a particular function name in a
2505 given file. Here we get the function-name and the file info indirectly
2506 from the def_dec_info record pointer which is passed in. */
2508 static const def_dec_info *
2509 find_static_definition (user)
2510 const def_dec_info *user;
2512 const def_dec_info *head = user->hash_entry->ddip;
2513 const def_dec_info *dd_p;
2514 int num_static_defs = 0;
2515 const def_dec_info *static_def_p = NULL;
2517 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2518 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2520 static_def_p = dd_p; /* save a pointer to the definition */
2523 if (num_static_defs == 0)
2526 fprintf (stderr, "%s: warning: no static definition for `%s' in file `%s'\n",
2527 pname, head->hash_entry->symbol,
2528 shortpath (NULL, user->file->hash_entry->symbol));
2530 else if (num_static_defs > 1)
2532 fprintf (stderr, "%s: error: multiple static defs of `%s' in file `%s'\n",
2533 pname, head->hash_entry->symbol,
2534 shortpath (NULL, user->file->hash_entry->symbol));
2537 return static_def_p;
2540 /* Find good prototype style formal argument lists for all of the function
2541 declarations which didn't have them before now.
2543 To do this we consider each function name one at a time. For each function
2544 name, we look at the items on the linked list of def_dec_info records for
2545 that particular name.
2547 Somewhere on this list we should find one (and only one) def_dec_info
2548 record which represents the actual function definition, and this record
2549 should have a nice formal argument list already associated with it.
2551 Thus, all we have to do is to connect up all of the other def_dec_info
2552 records for this particular function name to the special one which has
2553 the full-blown formals list.
2555 Of course it is a little more complicated than just that. See below for
2559 connect_defs_and_decs (hp)
2560 const hash_table_entry *hp;
2562 const def_dec_info *dd_p;
2563 const def_dec_info *extern_def_p = NULL;
2564 int first_extern_reference = 1;
2566 /* Traverse the list of definitions and declarations for this particular
2567 function name. For each item on the list, if it is a function
2568 definition (either old style or new style) then GCC has already been
2569 kind enough to produce a prototype for us, and it is associated with
2570 the item already, so declare the item as its own associated "definition".
2572 Also, for each item which is only a function declaration, but which
2573 nonetheless has its own prototype already (obviously supplied by the user)
2574 declare the item as it's own definition.
2576 Note that when/if there are multiple user-supplied prototypes already
2577 present for multiple declarations of any given function, these multiple
2578 prototypes *should* all match exactly with one another and with the
2579 prototype for the actual function definition. We don't check for this
2580 here however, since we assume that the compiler must have already done
2581 this consistency checking when it was creating the .X files. */
2583 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2584 if (dd_p->prototyped)
2585 ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2587 /* Traverse the list of definitions and declarations for this particular
2588 function name. For each item on the list, if it is an extern function
2589 declaration and if it has no associated definition yet, go try to find
2590 the matching extern definition for the declaration.
2592 When looking for the matching function definition, warn the user if we
2595 If we find more that one function definition also issue a warning.
2597 Do the search for the matching definition only once per unique function
2598 name (and only when absolutely needed) so that we can avoid putting out
2599 redundant warning messages, and so that we will only put out warning
2600 messages when there is actually a reference (i.e. a declaration) for
2601 which we need to find a matching definition. */
2603 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2604 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2606 if (first_extern_reference)
2608 extern_def_p = find_extern_def (hp->ddip, dd_p);
2609 first_extern_reference = 0;
2611 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2614 /* Traverse the list of definitions and declarations for this particular
2615 function name. For each item on the list, if it is a static function
2616 declaration and if it has no associated definition yet, go try to find
2617 the matching static definition for the declaration within the same file.
2619 When looking for the matching function definition, warn the user if we
2620 fail to find one in the same file with the declaration, and refuse to
2621 convert this kind of cross-file static function declaration. After all,
2622 this is stupid practice and should be discouraged.
2624 We don't have to worry about the possibility that there is more than one
2625 matching function definition in the given file because that would have
2626 been flagged as an error by the compiler.
2628 Do the search for the matching definition only once per unique
2629 function-name/source-file pair (and only when absolutely needed) so that
2630 we can avoid putting out redundant warning messages, and so that we will
2631 only put out warning messages when there is actually a reference (i.e. a
2632 declaration) for which we actually need to find a matching definition. */
2634 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2635 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2637 const def_dec_info *dd_p2;
2638 const def_dec_info *static_def;
2640 /* We have now found a single static declaration for which we need to
2641 find a matching definition. We want to minimize the work (and the
2642 number of warnings), so we will find an appropriate (matching)
2643 static definition for this declaration, and then distribute it
2644 (as the definition for) any and all other static declarations
2645 for this function name which occur within the same file, and which
2646 do not already have definitions.
2648 Note that a trick is used here to prevent subsequent attempts to
2649 call find_static_definition for a given function-name & file
2650 if the first such call returns NULL. Essentially, we convert
2651 these NULL return values to -1, and put the -1 into the definition
2652 field for each other static declaration from the same file which
2653 does not already have an associated definition.
2654 This makes these other static declarations look like they are
2655 actually defined already when the outer loop here revisits them
2656 later on. Thus, the outer loop will skip over them. Later, we
2657 turn the -1's back to NULL's. */
2659 ((NONCONST def_dec_info *) dd_p)->definition =
2660 (static_def = find_static_definition (dd_p))
2662 : (const def_dec_info *) -1;
2664 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2665 if (!dd_p2->is_func_def && dd_p2->is_static
2666 && !dd_p2->definition && (dd_p2->file == dd_p->file))
2667 ((NONCONST def_dec_info *)dd_p2)->definition = dd_p->definition;
2670 /* Convert any dummy (-1) definitions we created in the step above back to
2671 NULL's (as they should be). */
2673 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2674 if (dd_p->definition == (def_dec_info *) -1)
2675 ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2678 #endif /* !defined (UNPROTOIZE) */
2680 /* Give a pointer into the clean text buffer, return a number which is the
2681 original source line number that the given pointer points into. */
2684 identify_lineno (clean_p)
2685 const char *clean_p;
2690 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2691 if (*scan_p == '\n')
2696 /* Issue an error message and give up on doing this particular edit. */
2699 declare_source_confusing (clean_p)
2700 const char *clean_p;
2705 fprintf (stderr, "%s: %d: warning: source too confusing\n",
2706 shortpath (NULL, convert_filename), last_known_line_number);
2708 fprintf (stderr, "%s: %d: warning: source too confusing\n",
2709 shortpath (NULL, convert_filename),
2710 identify_lineno (clean_p));
2712 longjmp (source_confusion_recovery, 1);
2715 /* Check that a condition which is expected to be true in the original source
2716 code is in fact true. If not, issue an error message and give up on
2717 converting this particular source file. */
2720 check_source (cond, clean_p)
2722 const char *clean_p;
2725 declare_source_confusing (clean_p);
2728 /* If we think of the in-core cleaned text buffer as a memory mapped
2729 file (with the variable last_known_line_start acting as sort of a
2730 file pointer) then we can imagine doing "seeks" on the buffer. The
2731 following routine implements a kind of "seek" operation for the in-core
2732 (cleaned) copy of the source file. When finished, it returns a pointer to
2733 the start of a given (numbered) line in the cleaned text buffer.
2735 Note that protoize only has to "seek" in the forward direction on the
2736 in-core cleaned text file buffers, and it never needs to back up.
2738 This routine is made a little bit faster by remembering the line number
2739 (and pointer value) supplied (and returned) from the previous "seek".
2740 This prevents us from always having to start all over back at the top
2741 of the in-core cleaned buffer again. */
2747 if (n < last_known_line_number)
2750 while (n > last_known_line_number)
2752 while (*last_known_line_start != '\n')
2753 check_source (++last_known_line_start < clean_text_limit, 0);
2754 last_known_line_start++;
2755 last_known_line_number++;
2757 return last_known_line_start;
2760 /* Given a pointer to a character in the cleaned text buffer, return a pointer
2761 to the next non-whitepace character which follows it. */
2764 forward_to_next_token_char (ptr)
2767 for (++ptr; isspace (*ptr); check_source (++ptr < clean_text_limit, 0))
2772 /* Copy a chunk of text of length `len' and starting at `str' to the current
2773 output buffer. Note that all attempts to add stuff to the current output
2774 buffer ultimately go through here. */
2777 output_bytes (str, len)
2781 if ((repl_write_ptr + 1) + len >= repl_text_limit)
2783 size_t new_size = (repl_text_limit - repl_text_base) << 1;
2784 char *new_buf = (char *) xrealloc (repl_text_base, new_size);
2786 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
2787 repl_text_base = new_buf;
2788 repl_text_limit = new_buf + new_size;
2790 memcpy (repl_write_ptr + 1, str, len);
2791 repl_write_ptr += len;
2794 /* Copy all bytes (except the trailing null) of a null terminated string to
2795 the current output buffer. */
2801 output_bytes (str, strlen (str));
2804 /* Copy some characters from the original text buffer to the current output
2807 This routine takes a pointer argument `p' which is assumed to be a pointer
2808 into the cleaned text buffer. The bytes which are copied are the `original'
2809 equivalents for the set of bytes between the last value of `clean_read_ptr'
2810 and the argument value `p'.
2812 The set of bytes copied however, comes *not* from the cleaned text buffer,
2813 but rather from the direct counterparts of these bytes within the original
2816 Thus, when this function is called, some bytes from the original text
2817 buffer (which may include original comments and preprocessing directives)
2818 will be copied into the output buffer.
2820 Note that the request implide when this routine is called includes the
2821 byte pointed to by the argument pointer `p'. */
2827 size_t copy_length = (size_t) (p - clean_read_ptr);
2828 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
2830 if (copy_length == 0)
2833 output_bytes (copy_start, copy_length);
2837 /* Given a pointer to a def_dec_info record which represents some form of
2838 definition of a function (perhaps a real definition, or in lieu of that
2839 perhaps just a declaration with a full prototype) return true if this
2840 function is one which we should avoid converting. Return false
2844 other_variable_style_function (ansi_header)
2845 const char *ansi_header;
2849 /* See if we have a stdarg function, or a function which has stdarg style
2850 parameters or a stdarg style return type. */
2852 return (int) substr (ansi_header, "...");
2854 #else /* !defined (UNPROTOIZE) */
2856 /* See if we have a varargs function, or a function which has varargs style
2857 parameters or a varargs style return type. */
2860 int len = strlen (varargs_style_indicator);
2862 for (p = ansi_header; p; )
2864 const char *candidate;
2866 if ((candidate = substr (p, varargs_style_indicator)) == 0)
2869 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
2875 #endif /* !defined (UNPROTOIZE) */
2878 /* Do the editing operation specifically for a function "declaration". Note
2879 that editing for function "definitions" are handled in a separate routine
2883 edit_fn_declaration (def_dec_p, clean_text_p)
2884 const def_dec_info *def_dec_p;
2885 const char *VOLATILE clean_text_p;
2887 const char *start_formals;
2888 const char *end_formals;
2889 const char *function_to_edit = def_dec_p->hash_entry->symbol;
2890 size_t func_name_len = strlen (function_to_edit);
2891 const char *end_of_fn_name;
2895 const f_list_chain_item *this_f_list_chain_item;
2896 const def_dec_info *definition = def_dec_p->definition;
2898 /* If we are protoizing, and if we found no corresponding definition for
2899 this particular function declaration, then just leave this declaration
2900 exactly as it is. */
2905 /* If we are protoizing, and if the corresponding definition that we found
2906 for this particular function declaration defined an old style varargs
2907 function, then we want to issue a warning and just leave this function
2908 declaration unconverted. */
2910 if (other_variable_style_function (definition->ansi_decl))
2913 fprintf (stderr, "%s: %d: warning: varargs function declaration not converted\n",
2914 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
2919 #endif /* !defined (UNPROTOIZE) */
2921 /* Setup here to recover from confusing source code detected during this
2922 particular "edit". */
2925 if (setjmp (source_confusion_recovery))
2927 restore_pointers ();
2928 fprintf (stderr, "%s: declaration of function `%s' not converted\n",
2929 pname, function_to_edit);
2933 /* We are editing a function declaration. The line number we did a seek to
2934 contains the comma or semicolon which follows the declaration. Our job
2935 now is to scan backwards looking for the function name. This name *must*
2936 be followed by open paren (ignoring whitespace, of course). We need to
2937 replace everything between that open paren and the corresponding closing
2938 paren. If we are protoizing, we need to insert the prototype-style
2939 formals lists. If we are unprotoizing, we need to just delete everything
2940 between the pairs of opening and closing parens. */
2942 /* First move up to the end of the line. */
2944 while (*clean_text_p != '\n')
2945 check_source (++clean_text_p < clean_text_limit, 0);
2946 clean_text_p--; /* Point to just before the newline character. */
2948 /* Now we can scan backwards for the function name. */
2954 /* Scan leftwards until we find some character which can be
2955 part of an identifier. */
2957 while (!is_id_char (*clean_text_p))
2958 check_source (--clean_text_p > clean_read_ptr, 0);
2960 /* Scan backwards until we find a char that cannot be part of an
2963 while (is_id_char (*clean_text_p))
2964 check_source (--clean_text_p > clean_read_ptr, 0);
2966 /* Having found an "id break", see if the following id is the one
2967 that we are looking for. If so, then exit from this loop. */
2969 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
2971 char ch = *(clean_text_p + 1 + func_name_len);
2973 /* Must also check to see that the name in the source text
2974 ends where it should (in order to prevent bogus matches
2975 on similar but longer identifiers. */
2977 if (! is_id_char (ch))
2978 break; /* exit from loop */
2982 /* We have now found the first perfect match for the function name in
2983 our backward search. This may or may not be the actual function
2984 name at the start of the actual function declaration (i.e. we could
2985 have easily been mislead). We will try to avoid getting fooled too
2986 often by looking forward for the open paren which should follow the
2987 identifier we just found. We ignore whitespace while hunting. If
2988 the next non-whitespace byte we see is *not* an open left paren,
2989 then we must assume that we have been fooled and we start over
2990 again accordingly. Note that there is no guarrantee, that even if
2991 we do see the open paren, that we are in the right place.
2992 Programmers do the strangest things sometimes! */
2994 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
2995 start_formals = forward_to_next_token_char (end_of_fn_name);
2997 while (*start_formals != '(');
2999 /* start_of_formals now points to the opening left paren which immediately
3000 follows the name of the function. */
3002 /* Note that there may be several formals lists which need to be modified
3003 due to the possibility that the return type of this function is a
3004 pointer-to-function type. If there are several formals lists, we
3005 convert them in left-to-right order here. */
3008 this_f_list_chain_item = definition->f_list_chain;
3009 #endif /* !defined (UNPROTOIZE) */
3016 end_formals = start_formals + 1;
3018 for (; depth; check_source (++end_formals < clean_text_limit, 0))
3020 switch (*end_formals)
3033 /* end_formals now points to the closing right paren of the formals
3034 list whose left paren is pointed to by start_formals. */
3036 /* Now, if we are protoizing, we insert the new ANSI-style formals list
3037 attached to the associated definition of this function. If however
3038 we are unprotoizing, then we simply delete any formals list which
3041 output_up_to (start_formals);
3043 if (this_f_list_chain_item)
3045 output_string (this_f_list_chain_item->formals_list);
3046 this_f_list_chain_item = this_f_list_chain_item->chain_next;
3051 fprintf (stderr, "%s: warning: too many parameter lists in declaration of `%s'\n",
3052 pname, def_dec_p->hash_entry->symbol);
3053 check_source (0, end_formals); /* leave the declaration intact */
3055 #endif /* !defined (UNPROTOIZE) */
3056 clean_read_ptr = end_formals - 1;
3058 /* Now see if it looks like there may be another formals list associated
3059 with the function declaration that we are converting (following the
3060 formals list that we just converted. */
3063 const char *another_r_paren = forward_to_next_token_char (end_formals);
3065 if ((*another_r_paren != ')')
3066 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3069 if (this_f_list_chain_item)
3072 fprintf (stderr, "\n%s: warning: too few parameter lists in declaration of `%s'\n",
3073 pname, def_dec_p->hash_entry->symbol);
3074 check_source (0, start_formals); /* leave the decl intact */
3076 #endif /* !defined (UNPROTOIZE) */
3082 /* There does appear to be yet another formals list, so loop around
3083 again, and convert it also. */
3087 /* Edit a whole group of formals lists, starting with the rightmost one
3088 from some set of formals lists. This routine is called once (from the
3089 outside) for each function declaration which is converted. It is
3090 recursive however, and it calls itself once for each remaining formal
3091 list that lies to the left of the one it was originally called to work
3092 on. Thus, a whole set gets done in right-to-left order.
3094 This routine returns non-zero if it thinks that it should not be trying
3095 to convert this particular function definition (because the name of the
3096 function doesn't match the one expected). */
3099 edit_formals_lists (end_formals, f_list_count, def_dec_p)
3100 const char *end_formals;
3101 unsigned int f_list_count;
3102 const def_dec_info *def_dec_p;
3104 const char *start_formals;
3107 start_formals = end_formals - 1;
3109 for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3111 switch (*start_formals)
3123 /* start_formals now points to the opening left paren of the formals list. */
3129 const char *next_end;
3131 /* There should be more formal lists to the left of here. */
3133 next_end = start_formals - 1;
3134 check_source (next_end > clean_read_ptr, 0);
3135 while (isspace (*next_end))
3136 check_source (--next_end > clean_read_ptr, 0);
3137 check_source (*next_end == ')', next_end);
3138 check_source (--next_end > clean_read_ptr, 0);
3139 check_source (*next_end == ')', next_end);
3140 if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3144 /* Check that the function name in the header we are working on is the same
3145 as the one we would expect to find. If not, issue a warning and return
3148 if (f_list_count == 0)
3150 const char *expected = def_dec_p->hash_entry->symbol;
3151 const char *func_name_start;
3152 const char *func_name_limit;
3153 size_t func_name_len;
3155 for (func_name_limit = start_formals-1; isspace (*func_name_limit); )
3156 check_source (--func_name_limit > clean_read_ptr, 0);
3158 for (func_name_start = func_name_limit++;
3159 is_id_char (*func_name_start);
3161 check_source (func_name_start > clean_read_ptr, 0);
3163 func_name_len = func_name_limit - func_name_start;
3164 if (func_name_len == 0)
3165 check_source (0, func_name_start);
3166 if (func_name_len != strlen (expected)
3167 || strncmp (func_name_start, expected, func_name_len))
3169 fprintf (stderr, "%s: %d: warning: found `%s' but expected `%s'\n",
3170 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3171 identify_lineno (func_name_start),
3172 dupnstr (func_name_start, func_name_len),
3178 output_up_to (start_formals);
3181 if (f_list_count == 0)
3182 output_string (def_dec_p->formal_names);
3183 #else /* !defined (UNPROTOIZE) */
3185 unsigned f_list_depth;
3186 const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3188 /* At this point, the current value of f_list count says how many
3189 links we have to follow through the f_list_chain to get to the
3190 particular formals list that we need to output next. */
3192 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3193 flci_p = flci_p->chain_next;
3194 output_string (flci_p->formals_list);
3196 #endif /* !defined (UNPROTOIZE) */
3198 clean_read_ptr = end_formals - 1;
3202 /* Given a pointer to a byte in the clean text buffer which points to the
3203 beginning of a line that contains a "follower" token for a function
3204 definition header, do whatever is necessary to find the right closing
3205 paren for the rightmost formals list of the function definition header.
3209 find_rightmost_formals_list (clean_text_p)
3210 const char *clean_text_p;
3212 const char *end_formals;
3214 /* We are editing a function definition. The line number we did a seek
3215 to contains the first token which immediately follows the entire set of
3216 formals lists which are part of this particular function definition
3219 Our job now is to scan leftwards in the clean text looking for the
3220 right-paren which is at the end of the function header's rightmost
3223 If we ignore whitespace, this right paren should be the first one we
3224 see which is (ignoring whitespace) immediately followed either by the
3225 open curly-brace beginning the function body or by an alphabetic
3226 character (in the case where the function definition is in old (K&R)
3227 style and there are some declarations of formal parameters). */
3229 /* It is possible that the right paren we are looking for is on the
3230 current line (together with its following token). Just in case that
3231 might be true, we start out here by skipping down to the right end of
3232 the current line before starting our scan. */
3234 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3240 /* Now scan backwards while looking for the right end of the rightmost
3241 formals list associated with this function definition. */
3245 const char *l_brace_p;
3247 /* Look leftward and try to find a right-paren. */
3249 while (*end_formals != ')')
3251 if (isspace (*end_formals))
3252 while (isspace (*end_formals))
3253 check_source (--end_formals > clean_read_ptr, 0);
3255 check_source (--end_formals > clean_read_ptr, 0);
3258 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3259 /* Since we are unprotoizing an ANSI-style (prototyped) function
3260 definition, there had better not be anything (except whitespace)
3261 between the end of the ANSI formals list and the beginning of the
3262 function body (i.e. the '{'). */
3264 check_source (ch == '{', l_brace_p);
3267 #else /* !defined (UNPROTOIZE) */
3269 /* Now scan backwards while looking for the right end of the rightmost
3270 formals list associated with this function definition. */
3275 const char *l_brace_p;
3277 /* Look leftward and try to find a right-paren. */
3279 while (*end_formals != ')')
3281 if (isspace (*end_formals))
3282 while (isspace (*end_formals))
3283 check_source (--end_formals > clean_read_ptr, 0);
3285 check_source (--end_formals > clean_read_ptr, 0);
3288 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3290 /* Since it is possible that we found a right paren before the starting
3291 '{' of the body which IS NOT the one at the end of the real K&R
3292 formals list (say for instance, we found one embedded inside one of
3293 the old K&R formal parameter declarations) we have to check to be
3294 sure that this is in fact the right paren that we were looking for.
3296 The one we were looking for *must* be followed by either a '{' or
3297 by an alphabetic character, while others *cannot* legally be followed
3298 by such characters. */
3300 if ((ch == '{') || isalpha (ch))
3303 /* At this point, we have found a right paren, but we know that it is
3304 not the one we were looking for, so backup one character and keep
3307 check_source (--end_formals > clean_read_ptr, 0);
3310 #endif /* !defined (UNPROTOIZE) */
3317 /* Insert into the output file a totally new declaration for a function
3318 which (up until now) was being called from within the current block
3319 without having been declared at any point such that the declaration
3320 was visible (i.e. in scope) at the point of the call.
3322 We need to add in explicit declarations for all such function calls
3323 in order to get the full benefit of prototype-based function call
3324 parameter type checking. */
3327 add_local_decl (def_dec_p, clean_text_p)
3328 const def_dec_info *def_dec_p;
3329 const char *clean_text_p;
3331 const char *start_of_block;
3332 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3334 /* Don't insert new local explicit declarations unless explicitly requested
3340 /* Setup here to recover from confusing source code detected during this
3341 particular "edit". */
3344 if (setjmp (source_confusion_recovery))
3346 restore_pointers ();
3347 fprintf (stderr, "%s: local declaration for function `%s' not inserted\n",
3348 pname, function_to_edit);
3352 /* We have already done a seek to the start of the line which should
3353 contain *the* open curly brace which begins the block in which we need
3354 to insert an explicit function declaration (to replace the implicit one).
3356 Now we scan that line, starting from the left, until we find the
3357 open curly brace we are looking for. Note that there may actually be
3358 multiple open curly braces on the given line, but we will be happy
3359 with the leftmost one no matter what. */
3361 start_of_block = clean_text_p;
3362 while (*start_of_block != '{' && *start_of_block != '\n')
3363 check_source (++start_of_block < clean_text_limit, 0);
3365 /* Note that the line from the original source could possibly
3366 contain *no* open curly braces! This happens if the line contains
3367 a macro call which expands into a chunk of text which includes a
3368 block (and that block's associated open and close curly braces).
3369 In cases like this, we give up, issue a warning, and do nothing. */
3371 if (*start_of_block != '{')
3375 "\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
3376 def_dec_p->file->hash_entry->symbol, def_dec_p->line,
3377 def_dec_p->hash_entry->symbol);
3381 /* Figure out what a nice (pretty) indentation would be for the new
3382 declaration we are adding. In order to do this, we must scan forward
3383 from the '{' until we find the first line which starts with some
3384 non-whitespace characters (i.e. real "token" material). */
3387 const char *ep = forward_to_next_token_char (start_of_block) - 1;
3390 /* Now we have ep pointing at the rightmost byte of some existing indent
3391 stuff. At least that is the hope.
3393 We can now just scan backwards and find the left end of the existing
3394 indentation string, and then copy it to the output buffer. */
3396 for (sp = ep; isspace (*sp) && *sp != '\n'; sp--)
3399 /* Now write out the open { which began this block, and any following
3400 trash up to and including the last byte of the existing indent that
3405 /* Now we go ahead and insert the new declaration at this point.
3407 If the definition of the given function is in the same file that we
3408 are currently editing, and if its full ANSI declaration normally
3409 would start with the keyword `extern', suppress the `extern'. */
3412 const char *decl = def_dec_p->definition->ansi_decl;
3414 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
3416 output_string (decl);
3419 /* Finally, write out a new indent string, just like the preceding one
3420 that we found. This will typically include a newline as the first
3421 character of the indent string. */
3423 output_bytes (sp, (size_t) (ep - sp) + 1);
3427 /* Given a pointer to a file_info record, and a pointer to the beginning
3428 of a line (in the clean text buffer) which is assumed to contain the
3429 first "follower" token for the first function definition header in the
3430 given file, find a good place to insert some new global function
3431 declarations (which will replace scattered and imprecise implicit ones)
3432 and then insert the new explicit declaration at that point in the file. */
3435 add_global_decls (file_p, clean_text_p)
3436 const file_info *file_p;
3437 const char *clean_text_p;
3439 const def_dec_info *dd_p;
3442 /* Setup here to recover from confusing source code detected during this
3443 particular "edit". */
3446 if (setjmp (source_confusion_recovery))
3448 restore_pointers ();
3449 fprintf (stderr, "%s: global declarations for file `%s' not inserted\n",
3450 pname, shortpath (NULL, file_p->hash_entry->symbol));
3454 /* Start by finding a good location for adding the new explicit function
3455 declarations. To do this, we scan backwards, ignoring whitespace
3456 and comments and other junk until we find either a semicolon, or until
3457 we hit the beginning of the file. */
3459 scan_p = find_rightmost_formals_list (clean_text_p);
3462 if (scan_p < clean_text_base)
3464 check_source (scan_p > clean_read_ptr, 0);
3469 /* scan_p now points either to a semicolon, or to just before the start
3470 of the whole file. */
3472 /* Now scan forward for the first non-whitespace character. In theory,
3473 this should be the first character of the following function definition
3474 header. We will put in the added declarations just prior to that. */
3477 while (isspace (*scan_p))
3481 output_up_to (scan_p);
3483 /* Now write out full prototypes for all of the things that had been
3484 implicitly declared in this file (but only those for which we were
3485 actually able to find unique matching definitions). Avoid duplicates
3486 by marking things that we write out as we go. */
3489 int some_decls_added = 0;
3491 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3492 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
3494 const char *decl = dd_p->definition->ansi_decl;
3496 /* If the function for which we are inserting a declaration is
3497 actually defined later in the same file, then suppress the
3498 leading `extern' keyword (if there is one). */
3500 if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
3503 output_string ("\n");
3504 output_string (decl);
3505 some_decls_added = 1;
3506 ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
3508 if (some_decls_added)
3509 output_string ("\n\n");
3512 /* Unmark all of the definitions that we just marked. */
3514 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3515 if (dd_p->definition)
3516 ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
3519 #endif /* !defined (UNPROTOIZE) */
3521 /* Do the editing operation specifically for a function "definition". Note
3522 that editing operations for function "declarations" are handled by a
3523 separate routine above. */
3526 edit_fn_definition (def_dec_p, clean_text_p)
3527 const def_dec_info *def_dec_p;
3528 const char *clean_text_p;
3530 const char *end_formals;
3531 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3533 /* Setup here to recover from confusing source code detected during this
3534 particular "edit". */
3537 if (setjmp (source_confusion_recovery))
3539 restore_pointers ();
3540 fprintf (stderr, "%s: definition of function `%s' not converted\n",
3541 pname, function_to_edit);
3545 end_formals = find_rightmost_formals_list (clean_text_p);
3547 /* end_of_formals now points to the closing right paren of the rightmost
3548 formals list which is actually part of the `header' of the function
3549 definition that we are converting. */
3551 /* If the header of this function definition looks like it declares a
3552 function with a variable number of arguments, and if the way it does
3553 that is different from that way we would like it (i.e. varargs vs.
3554 stdarg) then issue a warning and leave the header unconverted. */
3556 if (other_variable_style_function (def_dec_p->ansi_decl))
3559 fprintf (stderr, "%s: %d: warning: definition of %s not converted\n",
3560 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3561 identify_lineno (end_formals),
3563 output_up_to (end_formals);
3567 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
3569 restore_pointers ();
3570 fprintf (stderr, "%s: definition of function `%s' not converted\n",
3571 pname, function_to_edit);
3575 /* Have to output the last right paren because this never gets flushed by
3576 edit_formals_list. */
3578 output_up_to (end_formals);
3583 const char *semicolon_p;
3584 const char *limit_p;
3586 int had_newlines = 0;
3588 /* Now write out the K&R style formal declarations, one per line. */
3590 decl_p = def_dec_p->formal_decls;
3591 limit_p = decl_p + strlen (decl_p);
3592 for (;decl_p < limit_p; decl_p = semicolon_p + 2)
3594 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
3596 output_string ("\n");
3597 output_string (indent_string);
3598 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
3601 /* If there are no newlines between the end of the formals list and the
3602 start of the body, we should insert one now. */
3604 for (scan_p = end_formals+1; *scan_p != '{'; )
3606 if (*scan_p == '\n')
3611 check_source (++scan_p < clean_text_limit, 0);
3614 output_string ("\n");
3616 #else /* !defined (UNPROTOIZE) */
3617 /* If we are protoizing, there may be some flotsum & jetsum (like comments
3618 and preprocessing directives) after the old formals list but before
3619 the following { and we would like to preserve that stuff while effectively
3620 deleting the existing K&R formal parameter declarations. We do so here
3621 in a rather tricky way. Basically, we white out any stuff *except*
3622 the comments/pp-directives in the original text buffer, then, if there
3623 is anything in this area *other* than whitespace, we output it. */
3625 const char *end_formals_orig;
3626 const char *start_body;
3627 const char *start_body_orig;
3629 const char *scan_orig;
3630 int have_flotsum = 0;
3631 int have_newlines = 0;
3633 for (start_body = end_formals + 1; *start_body != '{';)
3634 check_source (++start_body < clean_text_limit, 0);
3636 end_formals_orig = orig_text_base + (end_formals - clean_text_base);
3637 start_body_orig = orig_text_base + (start_body - clean_text_base);
3638 scan = end_formals + 1;
3639 scan_orig = end_formals_orig + 1;
3640 for (; scan < start_body; scan++, scan_orig++)
3642 if (*scan == *scan_orig)
3644 have_newlines |= (*scan_orig == '\n');
3645 /* Leave identical whitespace alone. */
3646 if (!isspace (*scan_orig))
3647 *((NONCONST char *)scan_orig) = ' '; /* identical - so whiteout */
3653 output_bytes (end_formals_orig + 1,
3654 (size_t) (start_body_orig - end_formals_orig) - 1);
3657 output_string ("\n");
3659 output_string (" ");
3660 clean_read_ptr = start_body - 1;
3662 #endif /* !defined (UNPROTOIZE) */
3665 /* Clean up the clean text buffer. Do this by converting comments and
3666 preprocessor directives into spaces. Also convert line continuations
3667 into whitespace. Also, whiteout string and character literals. */
3670 do_cleaning (new_clean_text_base, new_clean_text_limit)
3671 char *new_clean_text_base;
3672 char *new_clean_text_limit;
3675 int non_whitespace_since_newline = 0;
3677 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
3681 case '/': /* Handle comments. */
3682 if (scan_p[1] != '*')
3684 non_whitespace_since_newline = 1;
3688 while (scan_p[1] != '/' || scan_p[0] != '*')
3690 if (!isspace (*scan_p))
3692 if (++scan_p >= new_clean_text_limit)
3699 case '#': /* Handle pp directives. */
3700 if (non_whitespace_since_newline)
3703 while (scan_p[1] != '\n' || scan_p[0] == '\\')
3705 if (!isspace (*scan_p))
3707 if (++scan_p >= new_clean_text_limit)
3713 case '\'': /* Handle character literals. */
3714 non_whitespace_since_newline = 1;
3715 while (scan_p[1] != '\'' || scan_p[0] == '\\')
3717 if (scan_p[0] == '\\' && !isspace (scan_p[1]))
3719 if (!isspace (*scan_p))
3721 if (++scan_p >= new_clean_text_limit)
3727 case '"': /* Handle string literals. */
3728 non_whitespace_since_newline = 1;
3729 while (scan_p[1] != '"' || scan_p[0] == '\\')
3731 if (scan_p[0] == '\\' && !isspace (scan_p[1]))
3733 if (!isspace (*scan_p))
3735 if (++scan_p >= new_clean_text_limit)
3741 case '\\': /* Handle line continuations. */
3742 if (scan_p[1] != '\n')
3748 non_whitespace_since_newline = 0; /* Reset. */
3757 break; /* Whitespace characters. */
3761 non_whitespace_since_newline = 1;
3767 /* Given a pointer to the closing right parenthesis for a particular formals
3768 list (in the clean text buffer) find the corresponding left parenthesis
3769 and return a pointer to it. */
3772 careful_find_l_paren (p)
3778 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
3793 /* Scan the clean text buffer for cases of function definitions that we
3794 don't really know about because they were preprocessed out when the
3795 aux info files were created.
3797 In this version of protoize/unprotoize we just give a warning for each
3798 one found. A later version may be able to at least unprotoize such
3801 Note that we may easily find all function definitions simply by
3802 looking for places where there is a left paren which is (ignoring
3803 whitespace) immediately followed by either a left-brace or by an
3804 upper or lower case letter. Whenever we find this combination, we
3805 have also found a function definition header.
3807 Finding function *declarations* using syntactic clues is much harder.
3808 I will probably try to do this in a later version though. */
3811 scan_for_missed_items (file_p)
3812 const file_info *file_p;
3814 static const char *scan_p;
3815 const char *limit = clean_text_limit - 3;
3816 static const char *backup_limit;
3818 backup_limit = clean_text_base - 1;
3820 for (scan_p = clean_text_base; scan_p < limit; scan_p++)
3824 static const char *last_r_paren;
3825 const char *ahead_p;
3827 last_r_paren = scan_p;
3829 for (ahead_p = scan_p + 1; isspace (*ahead_p); )
3830 check_source (++ahead_p < limit, limit);
3832 scan_p = ahead_p - 1;
3834 if (isalpha (*ahead_p) || *ahead_p == '{')
3836 const char *last_l_paren;
3837 const int lineno = identify_lineno (ahead_p);
3839 if (setjmp (source_confusion_recovery))
3842 /* We know we have a function definition header. Now skip
3843 leftwards over all of its associated formals lists. */
3847 last_l_paren = careful_find_l_paren (last_r_paren);
3848 for (last_r_paren = last_l_paren-1; isspace (*last_r_paren); )
3849 check_source (--last_r_paren >= backup_limit, backup_limit);
3851 while (*last_r_paren == ')');
3853 if (is_id_char (*last_r_paren))
3855 const char *id_limit = last_r_paren + 1;
3856 const char *id_start;
3858 const def_dec_info *dd_p;
3860 for (id_start = id_limit-1; is_id_char (*id_start); )
3861 check_source (--id_start >= backup_limit, backup_limit);
3863 backup_limit = id_start;
3864 if ((id_length = (size_t) (id_limit - id_start)) == 0)
3868 char *func_name = (char *) alloca (id_length + 1);
3869 static const char * const stmt_keywords[]
3870 = { "if", "while", "for", "switch", "return", 0 };
3871 const char * const *stmt_keyword;
3873 strncpy (func_name, id_start, id_length);
3874 func_name[id_length] = '\0';
3876 /* We must check here to see if we are actually looking at
3877 a statement rather than an actual function call. */
3879 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
3880 if (!strcmp (func_name, *stmt_keyword))
3884 fprintf (stderr, "%s: found definition of `%s' at %s(%d)\n",
3887 shortpath (NULL, file_p->hash_entry->symbol),
3888 identify_lineno (id_start));
3890 /* We really should check for a match of the function name
3891 here also, but why bother. */
3893 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3894 if (dd_p->is_func_def && dd_p->line == lineno)
3897 /* If we make it here, then we did not know about this
3898 function definition. */
3900 fprintf (stderr, "%s: %d: warning: `%s' was #if 0\n",
3901 shortpath (NULL, file_p->hash_entry->symbol),
3902 identify_lineno (id_start), func_name);
3903 fprintf (stderr, "%s: function definition not converted\n",
3913 /* Do all editing operations for a single source file (either a "base" file
3914 or an "include" file). To do this we read the file into memory, keep a
3915 virgin copy there, make another cleaned in-core copy of the original file
3916 (i.e. one in which all of the comments and preprocessor directives have
3917 been replaced with whitespace), then use these two in-core copies of the
3918 file to make a new edited in-core copy of the file. Finally, rename the
3919 original file (as a way of saving it), and then write the edited version
3920 of the file from core to a disk file of the same name as the original.
3922 Note that the trick of making a copy of the original sans comments &
3923 preprocessor directives make the editing a whole lot easier. */
3927 const hash_table_entry *hp;
3929 struct stat stat_buf;
3930 const file_info *file_p = hp->fip;
3931 char *new_orig_text_base;
3932 char *new_orig_text_limit;
3933 char *new_clean_text_base;
3934 char *new_clean_text_limit;
3937 int first_definition_in_file;
3939 /* If we are not supposed to be converting this file, or if there is
3940 nothing in there which needs converting, just skip this file. */
3942 if (!needs_to_be_converted (file_p))
3945 convert_filename = file_p->hash_entry->symbol;
3947 /* Convert a file if it is in a directory where we want conversion
3948 and the file is not excluded. */
3950 if (!directory_specified_p (convert_filename)
3951 || file_excluded_p (convert_filename))
3955 /* Don't even mention "system" include files unless we are
3956 protoizing. If we are protoizing, we mention these as a
3957 gentile way of prodding the user to convert his "system"
3958 include files to prototype format. */
3959 && !in_system_include_dir (convert_filename)
3960 #endif /* defined (UNPROTOIZE) */
3962 fprintf (stderr, "%s: file `%s' not converted\n",
3963 pname, shortpath (NULL, convert_filename));
3967 /* Let the user know what we are up to. */
3970 fprintf (stderr, "%s: would convert file `%s'\n",
3971 pname, shortpath (NULL, convert_filename));
3973 fprintf (stderr, "%s: converting file `%s'\n",
3974 pname, shortpath (NULL, convert_filename));
3977 /* Find out the size (in bytes) of the original file. */
3979 /* The cast avoids an erroneous warning on AIX. */
3980 if (my_stat ((char *)convert_filename, &stat_buf) == -1)
3982 fprintf (stderr, "%s: error: can't get status for file `%s': %s\n",
3983 pname, shortpath (NULL, convert_filename), sys_errlist[errno]);
3986 orig_size = stat_buf.st_size;
3988 /* Allocate a buffer to hold the original text. */
3990 orig_text_base = new_orig_text_base = (char *) xmalloc (orig_size + 2);
3991 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
3993 /* Allocate a buffer to hold the cleaned-up version of the original text. */
3995 clean_text_base = new_clean_text_base = (char *) xmalloc (orig_size + 2);
3996 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
3997 clean_read_ptr = clean_text_base - 1;
3999 /* Allocate a buffer that will hopefully be large enough to hold the entire
4000 converted output text. As an initial guess for the maximum size of the
4001 output buffer, use 125% of the size of the original + some extra. This
4002 buffer can be expanded later as needed. */
4004 repl_size = orig_size + (orig_size >> 2) + 4096;
4005 repl_text_base = (char *) xmalloc (repl_size + 2);
4006 repl_text_limit = repl_text_base + repl_size - 1;
4007 repl_write_ptr = repl_text_base - 1;
4012 /* Open the file to be converted in READ ONLY mode. */
4014 if ((input_file = my_open (convert_filename, O_RDONLY, 0444)) == -1)
4016 fprintf (stderr, "%s: error: can't open file `%s' for reading: %s\n",
4017 pname, shortpath (NULL, convert_filename),
4018 sys_errlist[errno]);
4022 /* Read the entire original source text file into the original text buffer
4023 in one swell fwoop. Then figure out where the end of the text is and
4024 make sure that it ends with a newline followed by a null. */
4026 if (read (input_file, new_orig_text_base, orig_size) != orig_size)
4029 fprintf (stderr, "\n%s: error: while reading input file `%s': %s\n",
4030 pname, shortpath (NULL, convert_filename),
4031 sys_errlist[errno]);
4038 if (orig_size == 0 || orig_text_limit[-1] != '\n')
4040 *new_orig_text_limit++ = '\n';
4044 /* Create the cleaned up copy of the original text. */
4046 memcpy (new_clean_text_base, orig_text_base,
4047 (size_t) (orig_text_limit - orig_text_base));
4048 do_cleaning (new_clean_text_base, new_clean_text_limit);
4053 size_t clean_size = orig_text_limit - orig_text_base;
4054 char *const clean_filename = (char *) alloca (strlen (convert_filename) + 6 + 1);
4056 /* Open (and create) the clean file. */
4058 strcpy (clean_filename, convert_filename);
4059 strcat (clean_filename, ".clean");
4060 if ((clean_file = creat (clean_filename, 0666)) == -1)
4062 fprintf (stderr, "%s: error: can't create/open clean file `%s': %s\n",
4063 pname, shortpath (NULL, clean_filename),
4064 sys_errlist[errno]);
4068 /* Write the clean file. */
4070 if (write (clean_file, new_clean_text_base, clean_size) != clean_size)
4071 fprintf (stderr, "%s: error: while writing file `%s': %s\n",
4072 pname, shortpath (NULL, clean_filename), sys_errlist[errno]);
4078 /* Do a simplified scan of the input looking for things that were not
4079 mentioned in the aux info files because of the fact that they were
4080 in a region of the source which was preprocessed-out (via #if or
4083 scan_for_missed_items (file_p);
4085 /* Setup to do line-oriented forward seeking in the clean text buffer. */
4087 last_known_line_number = 1;
4088 last_known_line_start = clean_text_base;
4090 /* Now get down to business and make all of the necessary edits. */
4093 const def_dec_info *def_dec_p;
4095 first_definition_in_file = 1;
4096 def_dec_p = file_p->defs_decs;
4097 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
4099 const char *clean_text_p = seek_to_line (def_dec_p->line);
4101 /* clean_text_p now points to the first character of the line which
4102 contains the `terminator' for the declaration or definition that
4103 we are about to process. */
4107 if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
4109 add_global_decls (def_dec_p->file, clean_text_p);
4110 first_definition_in_file = 0;
4113 /* Don't edit this item if it is already in prototype format or if it
4114 is a function declaration and we have found no corresponding
4117 if (def_dec_p->prototyped
4118 || (!def_dec_p->is_func_def && !def_dec_p->definition))
4121 #endif /* !defined (UNPROTOIZE) */
4123 if (def_dec_p->is_func_def)
4124 edit_fn_definition (def_dec_p, clean_text_p);
4127 if (def_dec_p->is_implicit)
4128 add_local_decl (def_dec_p, clean_text_p);
4130 #endif /* !defined (UNPROTOIZE) */
4131 edit_fn_declaration (def_dec_p, clean_text_p);
4135 /* Finalize things. Output the last trailing part of the original text. */
4137 output_up_to (clean_text_limit - 1);
4139 /* If this is just a test run, stop now and just deallocate the buffers. */
4143 free (new_orig_text_base);
4144 free (new_clean_text_base);
4145 free (repl_text_base);
4149 /* Change the name of the original input file. This is just a quick way of
4150 saving the original file. */
4154 char *new_filename =
4155 (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
4157 strcpy (new_filename, convert_filename);
4158 strcat (new_filename, save_suffix);
4159 if (my_link (convert_filename, new_filename) == -1)
4161 if (errno == EEXIST)
4164 fprintf (stderr, "%s: warning: file `%s' already saved in `%s'\n",
4166 shortpath (NULL, convert_filename),
4167 shortpath (NULL, new_filename));
4171 fprintf (stderr, "%s: error: can't link file `%s' to `%s': %s\n",
4173 shortpath (NULL, convert_filename),
4174 shortpath (NULL, new_filename),
4175 sys_errlist[errno]);
4181 if (my_unlink (convert_filename) == -1)
4183 fprintf (stderr, "%s: error: can't delete file `%s': %s\n",
4184 pname, shortpath (NULL, convert_filename), sys_errlist[errno]);
4191 /* Open (and create) the output file. */
4193 if ((output_file = creat (convert_filename, 0666)) == -1)
4195 fprintf (stderr, "%s: error: can't create/open output file `%s': %s\n",
4196 pname, shortpath (NULL, convert_filename),
4197 sys_errlist[errno]);
4201 /* Write the output file. */
4204 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
4206 if (write (output_file, repl_text_base, out_size) != out_size)
4207 fprintf (stderr, "%s: error: while writing file `%s': %s\n",
4208 pname, shortpath (NULL, convert_filename),
4209 sys_errlist[errno]);
4212 close (output_file);
4215 /* Deallocate the conversion buffers. */
4217 free (new_orig_text_base);
4218 free (new_clean_text_base);
4219 free (repl_text_base);
4221 /* Change the mode of the output file to match the original file. */
4223 /* The cast avoids an erroneous warning on AIX. */
4224 if (my_chmod ((char *)convert_filename, stat_buf.st_mode) == -1)
4225 fprintf (stderr, "%s: error: can't change mode of file `%s': %s\n",
4226 pname, shortpath (NULL, convert_filename), sys_errlist[errno]);
4228 /* Note: We would try to change the owner and group of the output file
4229 to match those of the input file here, except that may not be a good
4230 thing to do because it might be misleading. Also, it might not even
4231 be possible to do that (on BSD systems with quotas for instance). */
4234 /* Do all of the individual steps needed to do the protoization (or
4235 unprotoization) of the files referenced in the aux_info files given
4236 in the command line. */
4241 const char * const *base_pp;
4242 const char * const * const end_pps
4243 = &base_source_filenames[n_base_source_files];
4247 #endif /* !defined (UNPROTOIZE) */
4249 /* One-by-one, check (and create if necessary), open, and read all of the
4250 stuff in each aux_info file. After reading each aux_info file, the
4251 aux_info_file just read will be automatically deleted unless the
4252 keep_flag is set. */
4254 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
4255 process_aux_info_file (*base_pp, keep_flag, 0);
4259 /* Also open and read the special SYSCALLS.c aux_info file which gives us
4260 the prototypes for all of the standard system-supplied functions. */
4262 if (nondefault_syscalls_dir)
4264 syscalls_absolute_filename
4265 = (char *) xmalloc (strlen (nondefault_syscalls_dir)
4266 + strlen (syscalls_filename) + 2);
4267 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
4271 syscalls_absolute_filename
4272 = (char *) xmalloc (strlen (default_syscalls_dir)
4273 + strlen (syscalls_filename) + 2);
4274 strcpy (syscalls_absolute_filename, default_syscalls_dir);
4277 syscalls_len = strlen (syscalls_absolute_filename);
4278 if (*(syscalls_absolute_filename + syscalls_len - 1) != '/')
4280 *(syscalls_absolute_filename + syscalls_len++) = '/';
4281 *(syscalls_absolute_filename + syscalls_len) = '\0';
4283 strcat (syscalls_absolute_filename, syscalls_filename);
4285 /* Call process_aux_info_file in such a way that it does not try to
4286 delete the SYSCALLS aux_info file. */
4288 process_aux_info_file (syscalls_absolute_filename, 1, 1);
4290 #endif /* !defined (UNPROTOIZE) */
4292 /* When we first read in all of the information from the aux_info files
4293 we saved in it decending line number order, because that was likely to
4294 be faster. Now however, we want the chains of def & dec records to
4295 appear in ascending line number order as we get further away from the
4296 file_info record that they hang from. The following line causes all of
4297 these lists to be rearranged into ascending line number order. */
4299 visit_each_hash_node (filename_primary, reverse_def_dec_list);
4303 /* Now do the "real" work. The following line causes each declaration record
4304 to be "visited". For each of these nodes, an attempt is made to match
4305 up the function declaration with a corresponding function definition,
4306 which should have a full prototype-format formals list with it. Once
4307 these match-ups are made, the conversion of the function declarations
4308 to prototype format can be made. */
4310 visit_each_hash_node (function_name_primary, connect_defs_and_decs);
4312 #endif /* !defined (UNPROTOIZE) */
4314 /* Now convert each file that can be converted (and needs to be). */
4316 visit_each_hash_node (filename_primary, edit_file);
4320 /* If we are working in cplusplus mode, try to rename all .c files to .C
4321 files. Don't panic if some of the renames don't work. */
4323 if (cplusplus_flag && !nochange_flag)
4324 visit_each_hash_node (filename_primary, rename_c_file);
4326 #endif /* !defined (UNPROTOIZE) */
4329 static struct option longopts[] =
4331 {"version", 0, 0, 'V'},
4332 {"file_name", 0, 0, 'p'},
4333 {"quiet", 0, 0, 'q'},
4334 {"silent", 0, 0, 'q'},
4335 {"force", 0, 0, 'f'},
4336 {"keep", 0, 0, 'k'},
4337 {"nosave", 0, 0, 'N'},
4338 {"nochange", 0, 0, 'n'},
4339 {"compiler-options", 1, 0, 'c'},
4340 {"exclude", 1, 0, 'x'},
4341 {"directory", 1, 0, 'd'},
4343 {"indent", 1, 0, 'i'},
4345 {"local", 0, 0, 'l'},
4346 {"global", 0, 0, 'g'},
4348 {"syscalls-dir", 1, 0, 'B'},
4362 pname = strrchr (argv[0], '/');
4363 pname = pname ? pname+1 : argv[0];
4365 /* Read the working directory, avoiding arbitrary limit. */
4366 size = GUESSPATHLEN;
4371 cwd_buffer = (char *) xmalloc (size);
4372 value = getcwd (cwd_buffer, size);
4373 if (value != 0 || errno != ERANGE)
4379 /* By default, convert the files in the current directory. */
4380 directory_list = string_list_cons (cwd_buffer, NULL);
4382 while ((c = getopt_long (argc, argv,
4386 "B:c:Cd:gklnNp:qVx:",
4388 longopts, &longind)) != EOF)
4390 if (c == 0) /* Long option. */
4391 c = longopts[longind].val;
4395 compiler_file_name = optarg;
4399 = string_list_cons (abspath (NULL, optarg), directory_list);
4402 exclude_list = string_list_cons (optarg, exclude_list);
4427 munge_compile_params (optarg);
4431 indent_string = optarg;
4433 #else /* !defined (UNPROTOIZE) */
4444 nondefault_syscalls_dir = optarg;
4446 #endif /* !defined (UNPROTOIZE) */
4452 n_base_source_files = argc - optind;
4454 /* Now actually make a list of the base source filenames. */
4456 base_source_filenames =
4457 (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *));
4458 n_base_source_files = 0;
4459 for (; optind < argc; optind++)
4461 const char *path = abspath (NULL, argv[optind]);
4462 int len = strlen (path);
4464 if (path[len-1] == 'c' && path[len-2] == '.')
4465 base_source_filenames[n_base_source_files++] = path;
4468 fprintf (stderr, "%s: input file names must have .c suffixes: %s\n",
4469 pname, shortpath (NULL, path));
4475 /* We are only interested in the very first identifier token in the
4476 definition of `va_list', so if there is more junk after that first
4477 identifier token, delete it from the `varargs_style_indicator'. */
4481 for (cp = varargs_style_indicator; isalnum (*cp) || *cp == '_'; cp++)
4484 varargs_style_indicator = savestring (varargs_style_indicator,
4485 cp - varargs_style_indicator);
4487 #endif /* !defined (UNPROTOIZE) */
4494 fprintf (stderr, "%s: %s\n", pname, version_string);