1 /* Protoize program - Written by Ron Guilmette at the Microelectronics
2 and Computer Technology Corporation (MCC). The author's current
3 E-mail address is <rfg@ncd.com>.
5 Copyright (C) 1989, 1992 Free Software Foundation, Inc.
7 This file is part of GNU CC.
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING. If not, write to
21 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 /* Any reasonable C++ compiler should have all of the same features
24 as __STDC__ plus more, so make sure that __STDC__ is defined if
25 __cplusplus is defined. */
27 #if defined(__cplusplus) && !defined(__STDC__)
29 #endif /* defined(__cplusplus) && !defined(__STDC__) */
31 #if defined(__GNUC__) || defined (__GNUG__)
32 #define VOLATILE volatile
43 #ifdef POSIX /* We should be able to define _POSIX_SOURCE unconditionally,
44 but some systems respond in buggy ways to it,
45 including Sunos 4.1.1. Which we don't classify as POSIX. */
46 /* In case this is a POSIX system with an ANSI C compiler,
47 ask for definition of all POSIX facilities. */
52 /* Users are not supposed to use _POSIX_SOURCE to say the
53 system is a POSIX system. That is not what _POSIX_SOURCE means! -- rms */
54 /* If the user asked for POSIX via _POSIX_SOURCE, turn on POSIX code. */
55 #if defined(_POSIX_SOURCE) && !defined(POSIX)
63 #include <sys/types.h>
66 #if ! defined (USG) || defined (SVR4)
73 #ifndef PATH_MAX /* <limits.h> defines this on most POSIX systems. */
74 #include <sys/param.h>
75 /* Sometimes <sys/param.h> defines these macros. */
95 extern char *sys_errlist[];
96 extern char *version_string;
98 /* Systems which are compatible only with POSIX 1003.1-1988 (but *not*
99 with POSIX 1003.1-1990), e.g. Ultrix 4.2, might not have
100 const qualifiers in the prototypes in the system include files.
101 Unfortunately, this can lead to GCC issuing lots of warnings for
102 calls to the following functions. To eliminate these warnings we
103 provide the following #defines. */
105 #define my_access(file,flag) access((char *)file, flag)
106 #define my_stat(file,pkt) stat((char *)file, pkt)
107 #define my_execvp(prog,argv) execvp((char *)prog, (char **)argv)
108 #define my_link(file1, file2) link((char *)file1, (char *)file2)
109 #define my_unlink(file) unlink((char *)file)
110 #define my_open(file, mode, flag) open((char *)file, mode, flag)
111 #define my_chmod(file, mode) chmod((char *)file, mode)
113 #if !(defined (USG) || defined (VMS) || defined (POSIX))
114 #define GUESSPATHLEN (MAXPATHLEN + 1)
115 #else /* (defined (USG) || defined (VMS) || defined (POSIX)) */
116 /* We actually use this as a starting point, not a limit. */
117 #define GUESSPATHLEN 200
118 #endif /* (defined (USG) || defined (VMS) || defined (POSIX)) */
120 /* Aliases for pointers to void.
121 These were made to facilitate compilation with other compilers. */
124 typedef void * pointer_type;
125 typedef const void * const_pointer_type;
127 typedef char * pointer_type;
128 typedef char * const_pointer_type;
139 #else /* !defined(POSIX) */
141 #define R_OK 4 /* Test for Read permission */
142 #define W_OK 2 /* Test for Write permission */
143 #define X_OK 1 /* Test for eXecute permission */
144 #define F_OK 0 /* Test for existence of File */
149 /* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
150 BSD systems) now provides getcwd as called for by POSIX. Allow for
151 the few exceptions to the general rule here. */
153 #if !(defined (USG) || defined (VMS))
154 extern char *getwd ();
155 #define getcwd(buf,len) getwd(buf)
156 #else /* (defined (USG) || defined (VMS)) */
157 extern char *getcwd ();
158 #endif /* (defined (USG) || defined (VMS)) */
160 /* Declaring stat or __flsbuf with a prototype
161 causes conflicts with system headers on some systems. */
164 extern VOLATILE void abort ();
168 #if 0 /* These conflict with stdio.h on some systems. */
169 extern int fprintf (FILE *, const char *, ...);
170 extern int printf (const char *, ...);
173 extern pointer_type malloc ();
174 extern pointer_type realloc ();
179 extern int fflush ();
184 #if 0 /* Causes trouble on some systems that define setjmp as a macro. */
185 extern int setjmp ();
186 extern void longjmp ();
189 extern char * strcat ();
190 extern int strcmp ();
191 extern char * strcpy ();
192 #if 0 /* size_t from sys/types.h may fail to match GCC.
193 If so, we would get a warning from this.
194 So do without the prototype. */
195 extern size_t strlen (const char *);
197 extern int strncmp ();
198 extern char * strncpy ();
199 extern char * strrchr ();
201 /* Fork is not declared because the declaration caused a conflict
203 #if !(defined (USG) || defined (VMS))
205 #endif /* (defined (USG) || defined (VMS)) */
207 #endif /* !defined (POSIX) */
209 /* Look for these where the `const' qualifier is intentionally cast aside. */
213 /* Define a STRINGIFY macro that's right for ANSI or traditional C. */
216 #define STRINGIFY(STRING) #STRING
218 #define STRINGIFY(STRING) "STRING"
221 /* POSIX systems will not have definitions for WIFEXITED or WEXITSTATUS.
222 Define them correctly and so that they work for all environments. */
225 #define WIFEXITED(status_word) ((*((int *)&status_word) & 0xff) == 0x00)
228 #define WEXITSTATUS(status_word) ((*((int *)&status_word) & 0xff00) >> 8)
230 /* Define a default place to find the SYSCALLS.X file. */
232 #ifndef STD_PROTO_DIR
233 #define STD_PROTO_DIR "/usr/local/lib"
234 #endif /* !defined (STD_PROTO_DIR) */
236 /* Suffix of aux_info files. */
238 static const char * const aux_info_suffix = ".X";
240 /* String to attach to filenames for saved versions of original files. */
242 static const char * const save_suffix = ".save";
246 /* File name of the file which contains descriptions of standard system
247 routines. Note that we never actually do anything with this file per se,
248 but we do read in its corresponding aux_info file. */
250 static const char * const syscalls_filename = "SYSCALLS.c";
252 /* Default place to find the above file. */
254 static const char * const default_syscalls_dir = STD_PROTO_DIR;
256 /* Variable to hold the complete absolutized filename of the SYSCALLS.c.X
259 static char * syscalls_absolute_filename;
261 #endif /* !defined (UNPROTOIZE) */
263 /* Type of the structure that holds information about macro unexpansions. */
265 struct unexpansion_struct {
266 const char *expanded;
267 const char *contracted;
269 typedef struct unexpansion_struct unexpansion;
271 /* A table of conversions that may need to be made for some (stupid) older
272 operating systems where these types are preprocessor macros rather than
273 typedefs (as they really ought to be).
275 WARNING: The contracted forms must be as small (or smaller) as the
276 expanded forms, or else havoc will ensue. */
278 static const unexpansion unexpansions[] = {
279 { "struct _iobuf", "FILE" },
283 /* The number of "primary" slots in the hash tables for filenames and for
284 function names. This can be as big or as small as you like, except that
285 it must be a power of two. */
287 #define HASH_TABLE_SIZE (1 << 9)
289 /* Bit mask to use when computing hash values. */
291 static const int hash_mask = (HASH_TABLE_SIZE - 1);
293 /* Make a table of default system include directories
294 just as it is done in cccp.c. */
296 #ifndef STANDARD_INCLUDE_DIR
297 #define STANDARD_INCLUDE_DIR "/usr/include"
300 #ifndef LOCAL_INCLUDE_DIR
301 #define LOCAL_INCLUDE_DIR "/usr/local/include"
304 struct default_include { char *fname; int cplusplus; } include_defaults[]
305 #ifdef INCLUDE_DEFAULTS
309 /* Pick up GNU C++ specific include files. */
310 { GPLUSPLUS_INCLUDE_DIR, 1},
311 { GCC_INCLUDE_DIR, 0},
313 /* For cross-compilation, this dir name is generated
314 automatically in Makefile.in. */
315 { CROSS_INCLUDE_DIR, 0 },
316 #else /* not CROSS_COMPILE */
317 { LOCAL_INCLUDE_DIR, 0},
318 /* Some systems have an extra dir of include files. */
319 #ifdef SYSTEM_INCLUDE_DIR
320 { SYSTEM_INCLUDE_DIR, 0},
322 { STANDARD_INCLUDE_DIR, 0},
323 #endif /* not CROSS_COMPILE */
326 #endif /* no INCLUDE_DEFAULTS */
328 /* Datatype for lists of directories or filenames. */
332 struct string_list *next;
335 /* List of directories in which files should be converted. */
337 struct string_list *directory_list;
339 /* List of file names which should not be converted.
340 A file is excluded if the end of its name, following a /,
341 matches one of the names in this list. */
343 struct string_list *exclude_list;
345 /* The name of the other style of variable-number-of-parameters functions
346 (i.e. the style that we want to leave unconverted because we don't yet
347 know how to convert them to this style. This string is used in warning
350 /* Also define here the string that we can search for in the parameter lists
351 taken from the .X files which will unambiguously indicate that we have
352 found a varargs style function. */
355 static const char * const other_var_style = "stdarg";
356 #else /* !defined (UNPROTOIZE) */
357 static const char * const other_var_style = "varargs";
358 /* Note that this is a string containing the expansion of va_alist.
359 But in `main' we discard all but the first token. */
360 static const char *varargs_style_indicator = STRINGIFY (va_alist);
361 #endif /* !defined (UNPROTOIZE) */
363 /* The following two types are used to create hash tables. In this program,
364 there are two hash tables which are used to store and quickly lookup two
365 different classes of strings. The first type of strings stored in the
366 first hash table are absolute filenames of files which protoize needs to
367 know about. The second type of strings (stored in the second hash table)
368 are function names. It is this second class of strings which really
369 inspired the use of the hash tables, because there may be a lot of them. */
371 typedef struct hash_table_entry_struct hash_table_entry;
373 /* Do some typedefs so that we don't have to write "struct" so often. */
375 typedef struct def_dec_info_struct def_dec_info;
376 typedef struct file_info_struct file_info;
377 typedef struct f_list_chain_item_struct f_list_chain_item;
379 /* In the struct below, note that the "_info" field has two different uses
380 depending on the type of hash table we are in (i.e. either the filenames
381 hash table or the function names hash table). In the filenames hash table
382 the info fields of the entries point to the file_info struct which is
383 associated with each filename (1 per filename). In the function names
384 hash table, the info field points to the head of a singly linked list of
385 def_dec_info entries which are all defs or decs of the function whose
386 name is pointed to by the "symbol" field. Keeping all of the defs/decs
387 for a given function name on a special list specifically for that function
388 name makes it quick and easy to find out all of the important information
389 about a given (named) function. */
391 struct hash_table_entry_struct {
392 hash_table_entry * hash_next; /* -> to secondary entries */
393 const char * symbol; /* -> to the hashed string */
395 const def_dec_info * _ddip;
399 #define ddip _info._ddip
400 #define fip _info._fip
402 /* Define a type specifically for our two hash tables. */
404 typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
406 /* The following struct holds all of the important information about any
407 single filename (e.g. file) which we need to know about. */
409 struct file_info_struct {
410 const hash_table_entry * hash_entry; /* -> to associated hash entry */
411 const def_dec_info * defs_decs; /* -> to chain of defs/decs */
412 time_t mtime; /* Time of last modification. */
415 /* Due to the possibility that functions may return pointers to functions,
416 (which may themselves have their own parameter lists) and due to the
417 fact that returned pointers-to-functions may be of type "pointer-to-
418 function-returning-pointer-to-function" (ad nauseum) we have to keep
419 an entire chain of ANSI style formal parameter lists for each function.
421 Normally, for any given function, there will only be one formals list
422 on the chain, but you never know.
424 Note that the head of each chain of formals lists is pointed to by the
425 `f_list_chain' field of the corresponding def_dec_info record.
427 For any given chain, the item at the head of the chain is the *leftmost*
428 parameter list seen in the actual C language function declaration. If
429 there are other members of the chain, then these are linked in left-to-right
430 order from the head of the chain. */
432 struct f_list_chain_item_struct {
433 const f_list_chain_item * chain_next; /* -> to next item on chain */
434 const char * formals_list; /* -> to formals list string */
437 /* The following struct holds all of the important information about any
438 single function definition or declaration which we need to know about.
439 Note that for unprotoize we don't need to know very much because we
440 never even create records for stuff that we don't intend to convert
441 (like for instance defs and decs which are already in old K&R format
442 and "implicit" function declarations). */
444 struct def_dec_info_struct {
445 const def_dec_info * next_in_file; /* -> to rest of chain for file */
446 file_info * file; /* -> file_info for containing file */
447 int line; /* source line number of def/dec */
448 const char * ansi_decl; /* -> left end of ansi decl */
449 hash_table_entry * hash_entry; /* -> hash entry for function name */
450 unsigned int is_func_def; /* = 0 means this is a declaration */
451 const def_dec_info * next_for_func; /* -> to rest of chain for func name */
452 unsigned int f_list_count; /* count of formals lists we expect */
453 char prototyped; /* = 0 means already prototyped */
455 const f_list_chain_item * f_list_chain; /* -> chain of formals lists */
456 const def_dec_info * definition; /* -> def/dec containing related def */
457 char is_static; /* = 0 means visiblilty is "extern" */
458 char is_implicit; /* != 0 for implicit func decl's */
459 char written; /* != 0 means written for implicit */
460 #else /* !defined (UNPROTOIZE) */
461 const char * formal_names; /* -> to list of names of formals */
462 const char * formal_decls; /* -> to string of formal declartions */
463 #endif /* !defined (UNPROTOIZE) */
466 /* Pointer to the tail component of the filename by which this program was
467 invoked. Used everywhere in error and warning messages. */
469 static const char *pname;
471 /* Error counter. Will be non-zero if we should give up at the next convenient
474 static int errors = 0;
477 /* ??? These comments should say what the flag mean as well as the options
480 /* File name to use for running gcc. Allows GCC 2 to be named
481 something other than gcc. */
482 static char *compiler_file_name = "gcc";
484 static int version_flag = 0; /* Print our version number. */
485 static int quiet_flag = 0; /* Don't print messages normally. */
486 static int nochange_flag = 0; /* Don't convert, just say what files
487 we would have converted. */
488 static int nosave_flag = 0; /* Don't save the old version. */
489 static int keep_flag = 0; /* Don't delete the .X files. */
490 static const char ** compile_params = 0; /* Option string for gcc. */
492 static const char *indent_string = " "; /* Indentation for newly
493 inserted parm decls. */
494 #else /* !defined (UNPROTOIZE) */
495 static int local_flag = 0; /* Insert new local decls (when?). */
496 static int global_flag = 0; /* set by -g option */
497 static int cplusplus_flag = 0; /* Rename converted files to *.C. */
498 static const char* nondefault_syscalls_dir = 0; /* Dir to look for
500 #endif /* !defined (UNPROTOIZE) */
502 /* An index into the compile_params array where we should insert the filename
503 parameter when we are ready to exec the C compiler. A zero value indicates
504 that we have not yet called munge_compile_params. */
506 static int filename_index = 0;
508 /* Count of command line arguments which were "filename" arguments. */
510 static int n_base_source_files = 0;
512 /* Points to a malloc'ed list of pointers to all of the filenames of base
513 source files which were specified on the command line. */
515 static const char **base_source_filenames;
517 /* Line number of the line within the current aux_info file that we
518 are currently processing. Used for error messages in case the prototypes
519 info file is corrupted somehow. */
521 static int current_aux_info_lineno;
523 /* Pointer to the name of the source file currently being converted. */
525 static const char *convert_filename;
527 /* Pointer to relative root string (taken from aux_info file) which indicates
528 where directory the user was in when he did the compilation step that
529 produced the containing aux_info file. */
531 static const char *invocation_filename;
533 /* Pointer to the base of the input buffer that holds the original text for the
534 source file currently being converted. */
536 static const char *orig_text_base;
538 /* Pointer to the byte just beyond the end of the input buffer that holds the
539 original text for the source file currently being converted. */
541 static const char *orig_text_limit;
543 /* Pointer to the base of the input buffer that holds the cleaned text for the
544 source file currently being converted. */
546 static const char *clean_text_base;
548 /* Pointer to the byte just beyond the end of the input buffer that holds the
549 cleaned text for the source file currently being converted. */
551 static const char *clean_text_limit;
553 /* Pointer to the last byte in the cleaned text buffer that we have already
554 (virtually) copied to the output buffer (or decided to ignore). */
556 static const char * clean_read_ptr;
558 /* Pointer to the base of the output buffer that holds the replacement text
559 for the source file currently being converted. */
561 static char *repl_text_base;
563 /* Pointer to the byte just beyond the end of the output buffer that holds the
564 replacement text for the source file currently being converted. */
566 static char *repl_text_limit;
568 /* Pointer to the last byte which has been stored into the output buffer.
569 The next byte to be stored should be stored just past where this points
572 static char * repl_write_ptr;
574 /* Pointer into the cleaned text buffer for the source file we are currently
575 converting. This points to the first character of the line that we last
576 did a "seek_to_line" to (see below). */
578 static const char *last_known_line_start;
580 /* Number of the line (in the cleaned text buffer) that we last did a
581 "seek_to_line" to. Will be one if we just read a new source file
582 into the cleaned text buffer. */
584 static int last_known_line_number;
586 /* The filenames hash table. */
588 static hash_table filename_primary;
590 /* The function names hash table. */
592 static hash_table function_name_primary;
594 /* The place to keep the recovery address which is used only in cases where
595 we get hopelessly confused by something in the cleaned original text. */
597 static jmp_buf source_confusion_recovery;
599 /* A pointer to the current directory filename (used by abspath). */
601 static char *cwd_buffer;
603 /* A place to save the read pointer until we are sure that an individual
604 attempt at editing will succeed. */
606 static const char * saved_clean_read_ptr;
608 /* A place to save the write pointer until we are sure that an individual
609 attempt at editing will succeed. */
611 static char * saved_repl_write_ptr;
613 /* Forward declaration. */
615 static const char *shortpath ();
617 /* Allocate some space, but check that the allocation was successful. */
618 /* alloca.c uses this, so don't make it static. */
626 rv = malloc (byte_count);
629 fprintf (stderr, "\n%s: fatal error: can't allocate %u more bytes of memory\n",
632 return 0; /* avoid warnings */
638 /* Reallocate some space, but check that the reallocation was successful. */
641 xrealloc (old_space, byte_count)
642 pointer_type old_space;
647 rv = realloc (old_space, byte_count);
650 fprintf (stderr, "\n%s: fatal error: can't allocate %u more bytes of memory\n",
653 return 0; /* avoid warnings */
659 /* Deallocate the area pointed to by an arbitrary pointer, but first, strip
660 the `const' qualifier from it and also make sure that the pointer value
665 const_pointer_type p;
668 free ((NONCONST pointer_type) p);
671 /* Make a copy of a string INPUT with size SIZE. */
674 savestring (input, size)
678 char *output = (char *) xmalloc (size + 1);
679 strcpy (output, input);
683 /* More 'friendly' abort that prints the line and file.
684 config.h can #define abort fancy_abort if you like that sort of thing. */
689 fprintf (stderr, "%s: internal abort\n", pname);
693 /* Make a duplicate of a given string in a newly allocated area. */
699 return strcpy ((char *) xmalloc (strlen (s) + 1), s);
702 /* Make a duplicate of the first N bytes of a given string in a newly
710 char *ret_val = strncpy ((char *) xmalloc (n + 1), s, n);
716 /* Return a pointer to the first occurance of s2 within s1 or NULL if s2
717 does not occur within s1. Assume neither s1 nor s2 are null pointers. */
722 const char *const s2;
730 for (p1 = s1, p2 = s2; c = *p2; p1++, p2++)
740 /* Get setup to recover in case the edit we are about to do goes awry. */
745 saved_clean_read_ptr = clean_read_ptr;
746 saved_repl_write_ptr = repl_write_ptr;
749 /* Call this routine to recover our previous state whenever something looks
750 too confusing in the source code we are trying to edit. */
755 clean_read_ptr = saved_clean_read_ptr;
756 repl_write_ptr = saved_repl_write_ptr;
759 /* Return true if the given character is a legal identifier character. */
765 return (isalnum (ch) || (ch == '_') || (ch == '$'));
768 /* Give a message indicating the proper way to invoke this program and then
769 exit with non-zero status. */
775 fprintf (stderr, "%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
777 #else /* !defined (UNPROTOIZE) */
778 fprintf (stderr, "%s: usage '%s [ -VqfnkNlgC ] [ -B <diname> ] [ filename ... ]'\n",
780 #endif /* !defined (UNPROTOIZE) */
784 /* Return true if the given filename (assumed to be an absolute filename)
785 designates a file residing anywhere beneath any one of the "system"
786 include directories. */
789 in_system_include_dir (path)
792 struct default_include *p;
795 abort (); /* Must be an absolutized filename. */
797 for (p = include_defaults; p->fname; p++)
798 if (!strncmp (path, p->fname, strlen (p->fname))
799 && path[strlen (p->fname)] == '/')
805 /* Return true if the given filename designates a file that the user has
806 read access to and for which the user has write access to the containing
810 file_could_be_converted (const char *path)
812 char *const dir_name = (char *) alloca (strlen (path) + 1);
814 if (my_access (path, R_OK))
818 char *dir_last_slash;
820 strcpy (dir_name, path);
821 dir_last_slash = strrchr (dir_name, '/');
823 *dir_last_slash = '\0';
825 abort (); /* Should have been an absolutized filename. */
828 if (my_access (path, W_OK))
834 /* Return true if the given filename designates a file that we are allowed
835 to modify. Files which we should not attempt to modify are (a) "system"
836 include files, and (b) files which the user doesn't have write access to,
837 and (c) files which reside in directories which the user doesn't have
838 write access to. Unless requested to be quiet, give warnings about
839 files that we will not try to convert for one reason or another. An
840 exception is made for "system" include files, which we never try to
841 convert and for which we don't issue the usual warnings. */
844 file_normally_convertable (const char *path)
846 char *const dir_name = alloca (strlen (path) + 1);
848 if (in_system_include_dir (path))
852 char *dir_last_slash;
854 strcpy (dir_name, path);
855 dir_last_slash = strrchr (dir_name, '/');
857 *dir_last_slash = '\0';
859 abort (); /* Should have been an absolutized filename. */
862 if (my_access (path, R_OK))
865 fprintf (stderr, "%s: warning: no read access for file `%s'\n",
866 pname, shortpath (NULL, path));
870 if (my_access (path, W_OK))
873 fprintf (stderr, "%s: warning: no write access for file `%s'\n",
874 pname, shortpath (NULL, path));
878 if (my_access (dir_name, W_OK))
881 fprintf (stderr, "%s: warning: no write access for dir containing `%s'\n",
882 pname, shortpath (NULL, path));
892 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X
893 file. Return false otherwise. */
896 is_syscalls_file (fi_p)
897 const file_info *fi_p;
899 return (substr (fi_p->hash_entry->symbol, syscalls_filename) != NULL);
902 #endif /* !defined (UNPROTOIZE) */
904 /* Check to see if this file will need to have anything done to it on this
905 run. If there is nothing in the given file which both needs conversion
906 and for which we have the necessary stuff to do the conversion, return
907 false. Otherwise, return true.
909 Note that (for protoize) it is only valid to call this function *after*
910 the connections between declarations and definitions have all been made
911 by connect_defs_and_decs. */
914 needs_to_be_converted (file_p)
915 const file_info *file_p;
917 const def_dec_info *ddp;
921 if (is_syscalls_file (file_p))
924 #endif /* !defined (UNPROTOIZE) */
926 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
932 /* ... and if we a protoizing and this function is in old style ... */
934 /* ... and if this a definition or is a decl with an associated def ... */
935 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
937 #else /* defined (UNPROTOIZE) */
939 /* ... and if we are unprotoizing and this function is in new style ... */
942 #endif /* defined (UNPROTOIZE) */
944 /* ... then the containing file needs converting. */
949 /* Return 1 if the file name NAME is in a directory
950 that should be converted. */
953 directory_specified_p (name)
956 struct string_list *p;
958 for (p = directory_list; p; p = p->next)
959 if (!strncmp (name, p->name, strlen (p->name))
960 && name[strlen (p->name)] == '/')
962 const char *q = name + strlen (p->name) + 1;
964 /* If there are more slashes, it's in a subdir, so
965 this match doesn't count. */
977 /* Return 1 if the file named NAME should be excluded from conversion. */
980 file_excluded_p (name)
983 struct string_list *p;
984 int len = strlen (name);
986 for (p = exclude_list; p; p = p->next)
987 if (!strcmp (name + len - strlen (p->name), p->name)
988 && name[len - strlen (p->name) - 1] == '/')
994 /* Construct a new element of a string_list.
995 STRING is the new element value, and REST holds the remaining elements. */
997 static struct string_list *
998 string_list_cons (string, rest)
1000 struct string_list *rest;
1002 struct string_list *temp
1003 = (struct string_list *) xmalloc (sizeof (struct string_list));
1006 temp->name = string;
1010 /* ??? The GNU convention for mentioning function args in its comments
1011 is to capitalize them. So change "hash_tab_p" to HASH_TAB_P below.
1012 Likewise for all the other functions. */
1014 /* Given a hash table, apply some function to each node in the table. The
1015 table to traverse is given as the "hash_tab_p" argument, and the
1016 function to be applied to each node in the table is given as "func"
1020 visit_each_hash_node (hash_tab_p, func)
1021 const hash_table_entry *hash_tab_p;
1024 const hash_table_entry *primary;
1026 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
1027 if (primary->symbol)
1029 hash_table_entry *second;
1032 for (second = primary->hash_next; second; second = second->hash_next)
1037 /* Initialize all of the fields of a new hash table entry, pointed
1038 to by the "p" parameter. Note that the space to hold the entry
1039 is assumed to have already been allocated before this routine is
1042 static hash_table_entry *
1044 hash_table_entry *p;
1047 p->hash_next = NULL;
1048 p->symbol = dupstr (s);
1054 /* Look for a particular function name or filename in the particular
1055 hash table indicated by "hash_tab_p". If the name is not in the
1056 given hash table, add it. Either way, return a pointer to the
1057 hash table entry for the given name. */
1059 static hash_table_entry *
1060 lookup (hash_tab_p, search_symbol)
1061 hash_table_entry *hash_tab_p;
1062 const char *search_symbol;
1065 const char *search_symbol_char_p = search_symbol;
1066 hash_table_entry *p;
1068 while (*search_symbol_char_p)
1069 hash_value += *search_symbol_char_p++;
1070 hash_value &= hash_mask;
1071 p = &hash_tab_p[hash_value];
1073 return add_symbol (p, search_symbol);
1074 if (!strcmp (p->symbol, search_symbol))
1076 while (p->hash_next)
1079 if (!strcmp (p->symbol, search_symbol))
1082 p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry));
1084 return add_symbol (p, search_symbol);
1087 /* Throw a def/dec record on the junk heap.
1089 Also, since we are not using this record anymore, free up all of the
1090 stuff it pointed to. */
1096 xfree (p->ansi_decl);
1100 const f_list_chain_item * curr;
1101 const f_list_chain_item * next;
1103 for (curr = p->f_list_chain; curr; curr = next)
1105 next = curr->chain_next;
1109 #endif /* !defined (UNPROTOIZE) */
1114 /* Unexpand as many macro symbol as we can find.
1116 If the given line must be unexpanded, make a copy of it in the heap and
1117 return a pointer to the unexpanded copy. Otherwise return NULL. */
1120 unexpand_if_needed (aux_info_line)
1121 const char *aux_info_line;
1123 static char *line_buf = 0;
1124 static int line_buf_size = 0;
1125 const unexpansion* unexp_p;
1126 int got_unexpanded = 0;
1128 char *copy_p = line_buf;
1132 line_buf_size = 1024;
1133 line_buf = (char *) xmalloc (line_buf_size);
1138 /* Make a copy of the input string in line_buf, expanding as necessary. */
1140 for (s = aux_info_line; *s != '\n'; )
1142 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
1144 const char *in_p = unexp_p->expanded;
1145 size_t len = strlen (in_p);
1147 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1149 int size = strlen (unexp_p->contracted);
1151 if (copy_p + size - line_buf >= line_buf_size)
1153 int offset = copy_p - line_buf;
1155 line_buf_size += size;
1156 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1157 copy_p = line_buf + offset;
1159 strcpy (copy_p, unexp_p->contracted);
1162 /* Assume the there will not be another replacement required
1163 within the text just replaced. */
1166 goto continue_outer;
1169 if (copy_p - line_buf == line_buf_size)
1171 int offset = copy_p - line_buf;
1173 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1174 copy_p = line_buf + offset;
1179 if (copy_p + 2 - line_buf >= line_buf_size)
1181 int offset = copy_p - line_buf;
1183 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1184 copy_p = line_buf + offset;
1189 return (got_unexpanded ? dupstr (line_buf) : 0);
1192 /* Return the absolutized filename for the given relative
1193 filename. Note that if that filename is already absolute, it may
1194 still be returned in a modified form because this routine also
1195 eliminates redundant slashes and single dots and eliminates double
1196 dots to get a shortest possible filename from the given input
1197 filename. The absolutization of relative filenames is made by
1198 assuming that the given filename is to be taken as relative to
1199 the first argument (cwd) or to the current directory if cwd is
1203 abspath (cwd, rel_filename)
1205 const char *rel_filename;
1207 /* Setup the current working directory as needed. */
1208 const char *cwd2 = (cwd) ? cwd : cwd_buffer;
1209 char *const abs_buffer
1210 = (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 1);
1211 char *endp = abs_buffer;
1214 /* Copy the filename (possibly preceeded by the current working
1215 directory name) into the absolutization buffer. */
1220 if (rel_filename[0] != '/')
1223 while (*endp++ = *src_p++)
1225 *(endp-1) = '/'; /* overwrite null */
1227 src_p = rel_filename;
1228 while (*endp++ = *src_p++)
1230 if (endp[-1] == '/')
1234 /* Now make a copy of abs_buffer into abs_buffer, shortening the
1235 filename (by taking out slashes and dots) as we go. */
1237 outp = inp = abs_buffer;
1238 *outp++ = *inp++; /* copy first slash */
1243 else if (inp[0] == '/' && outp[-1] == '/')
1248 else if (inp[0] == '.' && outp[-1] == '/')
1252 else if (inp[1] == '/')
1257 else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/'))
1259 inp += (inp[2] == '/') ? 3 : 2;
1261 while (outp >= abs_buffer && *outp != '/')
1263 if (outp < abs_buffer)
1265 /* Catch cases like /.. where we try to backup to a
1266 point above the absolute root of the logical file
1269 fprintf (stderr, "%s: invalid file name: %s\n",
1270 pname, rel_filename);
1280 /* On exit, make sure that there is a trailing null, and make sure that
1281 the last character of the returned string is *not* a slash. */
1284 if (outp[-1] == '/')
1287 /* Make a copy (in the heap) of the stuff left in the absolutization
1288 buffer and return a pointer to the copy. */
1290 return dupstr (abs_buffer);
1293 /* Given a filename (and possibly a directory name from which the filename
1294 is relative) return a string which is the shortest possible
1295 equivalent for the corresponding full (absolutized) filename. The
1296 shortest possible equivalent may be constructed by converting the
1297 absolutized filename to be a relative filename (i.e. relative to
1298 the actual current working directory). However if a relative filename
1299 is longer, then the full absolute filename is returned.
1303 Note that "simple-minded" conversion of any given type of filename (either
1304 relative or absolute) may not result in a valid equivalent filename if any
1305 subpart of the original filename is actually a symbolic link. */
1308 shortpath (cwd, filename)
1310 const char *filename;
1314 char *cwd_p = cwd_buffer;
1316 int unmatched_slash_count = 0;
1318 path_p = abspath (cwd, filename);
1319 rel_buf_p = rel_buffer = (char *) xmalloc (strlen (path_p) + 1);
1321 while (*cwd_p && (*cwd_p == *path_p))
1326 if (!*cwd_p) /* whole pwd matched */
1328 if (!*path_p) /* input *is* the current path! */
1339 while (*cwd_p != '/') /* backup to last slash */
1346 unmatched_slash_count++;
1349 if (*cwd_p++ == '/')
1350 unmatched_slash_count++;
1351 while (unmatched_slash_count--)
1357 while (*rel_buf_p++ = *path_p++)
1360 if (*(rel_buf_p-1) == '/')
1361 *--rel_buf_p = '\0';
1362 if (strlen (rel_buffer) > (unsigned) strlen (filename))
1363 strcpy (rel_buffer, filename);
1368 /* Lookup the given filename in the hash table for filenames. If it is a
1369 new one, then the hash table info pointer will be null. In this case,
1370 we create a new file_info record to go with the filename, and we initialize
1371 that record with some reasonable values. */
1374 find_file (filename, do_not_stat)
1377 /* FILENAME was const, but that causes a warning on AIX when calling stat.
1378 That is probably a bug in AIX, but might as well avoid the warning. */
1380 hash_table_entry *hash_entry_p;
1382 hash_entry_p = lookup (filename_primary, filename);
1383 if (hash_entry_p->fip)
1384 return hash_entry_p->fip;
1387 struct stat stat_buf;
1388 file_info *file_p = (file_info *) xmalloc (sizeof (file_info));
1390 /* If we cannot get status on any given source file, give a warning
1391 and then just set its time of last modification to infinity. */
1394 stat_buf.st_mtime = (time_t) 0;
1397 if (my_stat (filename, &stat_buf) == -1)
1399 fprintf (stderr, "%s: error: can't get status of `%s': %s\n",
1400 pname, shortpath (NULL, filename), sys_errlist[errno]);
1401 stat_buf.st_mtime = (time_t) -1;
1405 hash_entry_p->fip = file_p;
1406 file_p->hash_entry = hash_entry_p;
1407 file_p->defs_decs = NULL;
1408 file_p->mtime = stat_buf.st_mtime;
1413 /* Generate a fatal error because some part of the aux_info file is
1417 aux_info_corrupted ()
1419 fprintf (stderr, "\n%s: fatal error: aux info file corrupted at line %d\n",
1420 pname, current_aux_info_lineno);
1424 /* ??? This comment is vague. Say what the condition is for. */
1425 /* Check to see that a condition is true. This is kind of like an assert. */
1428 check_aux_info (cond)
1432 aux_info_corrupted ();
1435 /* Given a pointer to the closing right parenthesis for a particular formals
1436 list (in a aux_info file) find the corresponding left parenthesis and
1437 return a pointer to it. */
1440 find_corresponding_lparen (p)
1446 for (paren_depth = 1, q = p-1; paren_depth; q--)
1461 /* Given a line from an aux info file, and a time at which the aux info
1462 file it came from was created, check to see if the item described in
1463 the line comes from a file which has been modified since the aux info
1464 file was created. If so, return non-zero, else return zero. */
1467 referenced_file_is_newer (l, aux_info_mtime)
1469 time_t aux_info_mtime;
1475 check_aux_info (l[0] == '/');
1476 check_aux_info (l[1] == '*');
1477 check_aux_info (l[2] == ' ');
1480 const char *filename_start = p = l + 3;
1484 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1485 strncpy (filename, filename_start, (size_t) (p - filename_start));
1486 filename[p-filename_start] = '\0';
1489 /* Call find_file to find the file_info record associated with the file
1490 which contained this particular def or dec item. Note that this call
1491 may cause a new file_info record to be created if this is the first time
1492 that we have ever known about this particular file. */
1494 fi_p = find_file (abspath (invocation_filename, filename), 0);
1496 return (fi_p->mtime > aux_info_mtime);
1499 /* Given a line of info from the aux_info file, create a new
1500 def_dec_info record to remember all of the important information about
1501 a function definition or declaration.
1503 Link this record onto the list of such records for the particular file in
1504 which it occured in proper (descending) line number order (for now).
1506 If there is an identical record already on the list for the file, throw
1507 this one away. Doing so takes care of the (useless and troublesome)
1508 duplicates which are bound to crop up due to multiple inclusions of any
1509 given individual header file.
1511 Finally, link the new def_dec record onto the list of such records
1512 pertaining to this particular function name. */
1515 save_def_or_dec (l, is_syscalls)
1520 const char *semicolon_p;
1521 def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info));
1524 def_dec_p->written = 0;
1525 #endif /* !defined (UNPROTOIZE) */
1527 /* Start processing the line by picking off 5 pieces of information from
1528 the left hand end of the line. These are filename, line number,
1529 new/old/implicit flag (new = ANSI prototype format), definition or
1530 declaration flag, and extern/static flag). */
1532 check_aux_info (l[0] == '/');
1533 check_aux_info (l[1] == '*');
1534 check_aux_info (l[2] == ' ');
1537 const char *filename_start = p = l + 3;
1542 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1543 strncpy (filename, filename_start, (size_t) (p - filename_start));
1544 filename[p-filename_start] = '\0';
1546 /* Call find_file to find the file_info record associated with the file
1547 which contained this particular def or dec item. Note that this call
1548 may cause a new file_info record to be created if this is the first time
1549 that we have ever known about this particular file.
1551 Note that we started out by forcing all of the base source file names
1552 (i.e. the names of the aux_info files with the .X stripped off) into the
1553 filenames hash table, and we simultaneously setup file_info records for
1554 all of these base file names (even if they may be useless later).
1555 The file_info records for all of these "base" file names (properly)
1556 act as file_info records for the "original" (i.e. un-included) files
1557 which were submitted to gcc for compilation (when the -fgen-aux-info
1558 option was used). */
1560 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1564 const char *line_number_start = ++p;
1565 char line_number[10];
1569 strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1570 line_number[p-line_number_start] = '\0';
1571 def_dec_p->line = atoi (line_number);
1574 /* Check that this record describes a new-style, old-style, or implicit
1575 definition or declaration. */
1577 p++; /* Skip over the `:'. */
1578 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1580 /* Is this a new style (ANSI prototyped) definition or declaration? */
1582 def_dec_p->prototyped = (*p == 'N');
1586 /* Is this an implicit declaration? */
1588 def_dec_p->is_implicit = (*p == 'I');
1590 #endif /* !defined (UNPROTOIZE) */
1594 check_aux_info ((*p == 'C') || (*p == 'F'));
1596 /* Is this item a function definition (F) or a declaration (C). Note that
1597 we treat item taken from the syscalls file as though they were function
1598 definitions regardless of what the stuff in the file says. */
1600 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1603 def_dec_p->definition = 0; /* Fill this in later if protoizing. */
1604 #endif /* !defined (UNPROTOIZE) */
1606 check_aux_info (*p++ == ' ');
1607 check_aux_info (*p++ == '*');
1608 check_aux_info (*p++ == '/');
1609 check_aux_info (*p++ == ' ');
1612 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1613 #else /* !defined (UNPROTOIZE) */
1614 if (!strncmp (p, "static", 6))
1615 def_dec_p->is_static = -1;
1616 else if (!strncmp (p, "extern", 6))
1617 def_dec_p->is_static = 0;
1619 check_aux_info (0); /* Didn't find either `extern' or `static'. */
1620 #endif /* !defined (UNPROTOIZE) */
1623 const char *ansi_start = p;
1625 p += 6; /* Pass over the "static" or "extern". */
1627 /* We are now past the initial stuff. Search forward from here to find
1628 the terminating semicolon that should immediately follow the entire
1629 ANSI format function declaration. */
1636 /* Make a copy of the ansi declaration part of the line from the aux_info
1639 def_dec_p->ansi_decl
1640 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1643 /* Backup and point at the final right paren of the final argument list. */
1647 /* Now isolate a whole set of formal argument lists, one-by-one. Normally,
1648 there will only be one list to isolate, but there could be more. */
1650 def_dec_p->f_list_count = 0;
1653 def_dec_p->f_list_chain = NULL;
1654 #endif /* !defined (UNPROTOIZE) */
1658 const char *left_paren_p = find_corresponding_lparen (p);
1661 f_list_chain_item *cip =
1662 (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
1665 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1667 /* Add the new chain item at the head of the current list. */
1669 cip->chain_next = def_dec_p->f_list_chain;
1670 def_dec_p->f_list_chain = cip;
1672 #endif /* !defined (UNPROTOIZE) */
1673 def_dec_p->f_list_count++;
1675 p = left_paren_p - 2;
1677 /* p must now point either to another right paren, or to the last
1678 character of the name of the function that was declared/defined.
1679 If p points to another right paren, then this indicates that we
1680 are dealing with multiple formals lists. In that case, there
1681 really should be another right paren preceeding this right paren. */
1686 check_aux_info (*--p == ')');
1691 const char *past_fn = p + 1;
1693 check_aux_info (*past_fn == ' ');
1695 /* Scan leftwards over the identifier that names the function. */
1697 while (is_id_char (*p))
1701 /* p now points to the leftmost character of the function name. */
1704 char *fn_string = (char *) alloca (past_fn - p + 1);
1706 strncpy (fn_string, p, (size_t) (past_fn - p));
1707 fn_string[past_fn-p] = '\0';
1708 def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1712 /* Look at all of the defs and decs for this function name that we have
1713 collected so far. If there is already one which is at the same
1714 line number in the same file, then we can discard this new def_dec_info
1717 As an extra assurance that any such pair of (nominally) identical
1718 function declarations are in fact identical, we also compare the
1719 ansi_decl parts of the lines from the aux_info files just to be on
1722 This comparison will fail if (for instance) the user was playing
1723 messy games with the preprocessor which ultimately causes one
1724 function declaration in one header file to look differently when
1725 that file is included by two (or more) other files. */
1728 const def_dec_info *other;
1730 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1732 if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1734 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1736 fprintf (stderr, "%s: error: declaration of function `%s' at %s(%d) takes different forms\n",
1738 def_dec_p->hash_entry->symbol,
1739 def_dec_p->file->hash_entry->symbol,
1743 free_def_dec (def_dec_p);
1751 /* If we are doing unprotoizing, we must now setup the pointers that will
1752 point to the K&R name list and to the K&R argument declarations list.
1754 Note that if this is only a function declaration, then we should not
1755 expect to find any K&R style formals list following the ANSI-style
1756 formals list. This is because GCC knows that such information is
1757 useless in the case of function declarations (function definitions
1758 are a different story however).
1760 Since we are unprotoizing, we don't need any such lists anyway.
1761 All we plan to do is to delete all characters between ()'s in any
1764 def_dec_p->formal_names = NULL;
1765 def_dec_p->formal_decls = NULL;
1767 if (def_dec_p->is_func_def)
1770 check_aux_info (*++p == ' ');
1771 check_aux_info (*++p == '/');
1772 check_aux_info (*++p == '*');
1773 check_aux_info (*++p == ' ');
1774 check_aux_info (*++p == '(');
1777 const char *kr_names_start = ++p; /* Point just inside '('. */
1781 p--; /* point to closing right paren */
1783 /* Make a copy of the K&R parameter names list. */
1785 def_dec_p->formal_names
1786 = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1789 check_aux_info (*++p == ' ');
1792 /* p now points to the first character of the K&R style declarations
1793 list (if there is one) or to the star-slash combination that ends
1794 the comment in which such lists get embedded. */
1796 /* Make a copy of the K&R formal decls list and set the def_dec record
1799 if (*p == '*') /* Are there no K&R declarations? */
1801 check_aux_info (*++p == '/');
1802 def_dec_p->formal_decls = "";
1806 const char *kr_decls_start = p;
1808 while (p[0] != '*' || p[1] != '/')
1812 check_aux_info (*p == ' ');
1814 def_dec_p->formal_decls
1815 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1818 /* Handle a special case. If we have a function definition marked as
1819 being in "old" style, and if it's formal names list is empty, then
1820 it may actually have the string "void" in its real formals list
1821 in the original source code. Just to make sure, we will get setup
1822 to convert such things anyway.
1824 This kludge only needs to be here because of an insurmountable
1825 problem with generating .X files. */
1827 if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1828 def_dec_p->prototyped = 1;
1831 /* Since we are unprotoizing, if this item is already in old (K&R) style,
1832 we can just ignore it. If that is true, throw away the itme now. */
1834 if (!def_dec_p->prototyped)
1836 free_def_dec (def_dec_p);
1840 #endif /* defined (UNPROTOIZE) */
1842 /* Add this record to the head of the list of records pertaining to this
1843 particular function name. */
1845 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1846 def_dec_p->hash_entry->ddip = def_dec_p;
1848 /* Add this new def_dec_info record to the sorted list of def_dec_info
1849 records for this file. Note that we don't have to worry about duplicates
1850 (caused by multiple inclusions of header files) here because we have
1851 already eliminated duplicates above. */
1853 if (!def_dec_p->file->defs_decs)
1855 def_dec_p->file->defs_decs = def_dec_p;
1856 def_dec_p->next_in_file = NULL;
1860 int line = def_dec_p->line;
1861 const def_dec_info *prev = NULL;
1862 const def_dec_info *curr = def_dec_p->file->defs_decs;
1863 const def_dec_info *next = curr->next_in_file;
1865 while (next && (line < curr->line))
1869 next = next->next_in_file;
1871 if (line >= curr->line)
1873 def_dec_p->next_in_file = curr;
1875 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1877 def_dec_p->file->defs_decs = def_dec_p;
1879 else /* assert (next == NULL); */
1881 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
1882 /* assert (next == NULL); */
1883 def_dec_p->next_in_file = next;
1888 /* Rewrite the options list used to recompile base source files. All we are
1889 really doing here is removing -g, -O, -S, -c, and -o options, and then
1890 adding a final group of options like '-fgen-aux-info -S -o /dev/null'. */
1893 munge_compile_params (params_list)
1894 const char *params_list;
1897 = (char **) alloca ((strlen (params_list) + 6) * sizeof (char *));
1898 int param_count = 0;
1901 temp_params[param_count++] = compiler_file_name;
1904 while (isspace (*params_list))
1908 param = params_list;
1909 while (*params_list && !isspace (*params_list))
1911 if (param[0] != '-')
1912 temp_params[param_count++]
1913 = dupnstr (param, (size_t) (params_list - param));
1922 break; /* Don't copy these. */
1924 while (isspace (*params_list))
1926 while (*params_list && !isspace (*params_list))
1930 temp_params[param_count++]
1931 = dupnstr (param, (size_t) (params_list - param));
1937 temp_params[param_count++] = "-fgen-aux-info";
1938 temp_params[param_count++] = "-S";
1939 temp_params[param_count++] = "-o";
1940 temp_params[param_count++] = "/dev/null";
1942 /* Leave room for the filename argument and a terminating null pointer. */
1944 temp_params[filename_index = param_count++] = NULL;
1945 temp_params[param_count++] = NULL;
1947 /* Make a copy of the compile_params in heap space. */
1950 = (const char **) xmalloc (sizeof (char *) * (param_count+1));
1951 memcpy (compile_params, temp_params, sizeof (char *) * param_count);
1954 /* Do a recompilation for the express purpose of generating a new aux_info
1955 file to go with a specific base source file. */
1958 gen_aux_info_file (base_filename)
1959 const char *base_filename;
1963 if (!filename_index)
1964 munge_compile_params ("");
1966 compile_params[filename_index] = shortpath (NULL, base_filename);
1969 fprintf (stderr, "%s: compiling `%s'\n",
1970 pname, compile_params[filename_index]);
1972 if (child_pid = fork ())
1974 if (child_pid == -1)
1976 fprintf (stderr, "%s: error: could not fork process: %s\n",
1977 pname, sys_errlist[errno]);
1982 /* Print out the command line that the other process is now executing. */
1988 fputs ("\t", stderr);
1989 for (arg = compile_params; *arg; arg++)
1991 fputs (*arg, stderr);
1992 fputc (' ', stderr);
1994 fputc ('\n', stderr);
2002 if (wait (&wait_status) == -1)
2004 fprintf (stderr, "%s: error: wait for process failed: %s\n",
2005 pname, sys_errlist[errno]);
2008 if (!WIFEXITED (wait_status))
2010 kill (child_pid, 9);
2013 return (WEXITSTATUS (wait_status) == 0) ? 1 : 0;
2018 if (my_execvp (compile_params[0], (char *const *) compile_params))
2020 fprintf (stderr, "%s: error: execvp returned: %s\n",
2021 pname, sys_errlist[errno]);
2024 return 1; /* Never executed. */
2028 /* Read in all of the information contained in a single aux_info file.
2029 Save all of the important stuff for later. */
2032 process_aux_info_file (base_source_filename, keep_it, is_syscalls)
2033 const char *base_source_filename;
2037 char *const aux_info_filename
2038 = (char *) alloca (strlen (base_source_filename)
2039 + strlen (aux_info_suffix) + 1);
2040 char *aux_info_base;
2041 char *aux_info_limit;
2042 const char *aux_info_second_line;
2043 time_t aux_info_mtime;
2044 size_t aux_info_size;
2046 /* Construct the aux_info filename from the base source filename. */
2048 strcpy (aux_info_filename, base_source_filename);
2049 strcat (aux_info_filename, aux_info_suffix);
2051 /* Check that the aux_info file exists and is readable. If it does not
2052 exist, try to create it (once only). */
2060 if (my_access (aux_info_filename, R_OK) == -1)
2062 if (errno == ENOENT && retries == 0)
2066 fprintf (stderr, "%s: warning: missing SYSCALLS file `%s'\n",
2067 pname, aux_info_filename);
2070 if (!gen_aux_info_file (base_source_filename))
2077 fprintf (stderr, "%s: error: can't read aux info file `%s': %s\n",
2078 pname, shortpath (NULL, aux_info_filename),
2079 sys_errlist[errno]);
2087 struct stat stat_buf;
2089 /* Get some status information about this aux_info file. */
2091 if (my_stat (aux_info_filename, &stat_buf) == -1)
2093 fprintf (stderr, "%s: error: can't get status of aux info file `%s': %s\n",
2094 pname, shortpath (NULL, aux_info_filename),
2095 sys_errlist[errno]);
2100 /* Check on whether or not this aux_info file is zero length. If it is,
2101 then just ignore it and return. */
2103 if ((aux_info_size = stat_buf.st_size) == 0)
2106 /* Get the date/time of last modification for this aux_info file and
2107 remember it. We will have to check that any source files that it
2108 contains information about are at least this old or older. */
2110 aux_info_mtime = stat_buf.st_mtime;
2116 /* Open the aux_info file. */
2118 if ((aux_info_file = my_open (aux_info_filename, O_RDONLY, 0444 )) == -1)
2120 fprintf (stderr, "%s: error: can't open aux info file `%s' for reading: %s\n",
2121 pname, shortpath (NULL, aux_info_filename),
2122 sys_errlist[errno]);
2126 /* Allocate space to hold the aux_info file in memory. */
2128 aux_info_base = xmalloc (aux_info_size + 1);
2129 aux_info_limit = aux_info_base + aux_info_size;
2130 *aux_info_limit = '\0';
2132 /* Read the aux_info file into memory. */
2134 if (read (aux_info_file, aux_info_base, aux_info_size) != aux_info_size)
2136 fprintf (stderr, "%s: error: while reading aux info file `%s': %s\n",
2137 pname, shortpath (NULL, aux_info_filename),
2138 sys_errlist[errno]);
2139 free (aux_info_base);
2140 close (aux_info_file);
2144 /* Close the aux info file. */
2146 if (close (aux_info_file))
2148 fprintf (stderr, "%s: error: while closing aux info file `%s': %s\n",
2149 pname, shortpath (NULL, aux_info_filename),
2150 sys_errlist[errno]);
2151 free (aux_info_base);
2152 close (aux_info_file);
2157 /* Delete the aux_info file (unless requested not to). If the deletion
2158 fails for some reason, don't even worry about it. */
2161 if (my_unlink (aux_info_filename) == -1)
2162 fprintf (stderr, "%s: error: can't delete aux info file `%s': %s\n",
2163 pname, shortpath (NULL, aux_info_filename),
2164 sys_errlist[errno]);
2166 /* Save a pointer into the first line of the aux_info file which
2167 contains the filename of the directory from which the compiler
2168 was invoked when the associated source file was compiled.
2169 This information is used later to help create complete
2170 filenames out of the (potentially) relative filenames in
2171 the aux_info file. */
2174 char *p = aux_info_base;
2181 invocation_filename = p; /* Save a pointer to first byte of path. */
2186 while (*p++ != '\n')
2188 aux_info_second_line = p;
2193 const char *aux_info_p;
2195 /* Do a pre-pass on the lines in the aux_info file, making sure that all
2196 of the source files referenced in there are at least as old as this
2197 aux_info file itself. If not, go back and regenerate the aux_info
2198 file anew. Don't do any of this for the syscalls file. */
2202 current_aux_info_lineno = 2;
2204 for (aux_info_p = aux_info_second_line; *aux_info_p; )
2206 if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2208 free (aux_info_base);
2209 if (my_unlink (aux_info_filename) == -1)
2211 fprintf (stderr, "%s: error: can't delete file `%s': %s\n",
2212 pname, shortpath (NULL, aux_info_filename),
2213 sys_errlist[errno]);
2219 /* Skip over the rest of this line to start of next line. */
2221 while (*aux_info_p != '\n')
2224 current_aux_info_lineno++;
2228 /* Now do the real pass on the aux_info lines. Save their information in
2229 the in-core data base. */
2231 current_aux_info_lineno = 2;
2233 for (aux_info_p = aux_info_second_line; *aux_info_p;)
2235 char *unexpanded_line = unexpand_if_needed (aux_info_p);
2237 if (unexpanded_line)
2239 save_def_or_dec (unexpanded_line, is_syscalls);
2240 free (unexpanded_line);
2243 save_def_or_dec (aux_info_p, is_syscalls);
2245 /* Skip over the rest of this line and get to start of next line. */
2247 while (*aux_info_p != '\n')
2250 current_aux_info_lineno++;
2254 free (aux_info_base);
2259 /* Check an individual filename for a .c suffix. If the filename has this
2260 suffix, rename the file such that its suffix is changed to .C. This
2261 function implements the -C option. */
2265 const hash_table_entry *hp;
2267 const char *filename = hp->symbol;
2268 int last_char_index = strlen (filename) - 1;
2269 char *const new_filename = (char *) alloca (strlen (filename) + 1);
2271 /* Note that we don't care here if the given file was converted or not. It
2272 is possible that the given file was *not* converted, simply because there
2273 was nothing in it which actually required conversion. Even in this case,
2274 we want to do the renaming. Note that we only rename files with the .c
2277 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.')
2280 strcpy (new_filename, filename);
2281 new_filename[last_char_index] = 'C';
2283 if (my_link (filename, new_filename) == -1)
2285 fprintf (stderr, "%s: warning: can't link file `%s' to `%s': %s\n",
2286 pname, shortpath (NULL, filename),
2287 shortpath (NULL, new_filename), sys_errlist[errno]);
2292 if (my_unlink (filename) == -1)
2294 fprintf (stderr, "%s: warning: can't delete file `%s': %s\n",
2295 pname, shortpath (NULL, filename), sys_errlist[errno]);
2301 #endif /* !defined (UNPROTOIZE) */
2303 /* Take the list of definitions and declarations attached to a particular
2304 file_info node and reverse the order of the list. This should get the
2305 list into an order such that the item with the lowest associated line
2306 number is nearest the head of the list. When these lists are originally
2307 built, they are in the opposite order. We want to traverse them in
2308 normal line number order later (i.e. lowest to highest) so reverse the
2312 reverse_def_dec_list (hp)
2313 const hash_table_entry *hp;
2315 file_info *file_p = hp->fip;
2316 const def_dec_info *prev = NULL;
2317 const def_dec_info *current = file_p->defs_decs;
2319 if (!( current = file_p->defs_decs))
2320 return; /* no list to reverse */
2323 if (! (current = current->next_in_file))
2324 return; /* can't reverse a single list element */
2326 ((NONCONST def_dec_info *) prev)->next_in_file = NULL;
2330 const def_dec_info *next = current->next_in_file;
2332 ((NONCONST def_dec_info *) current)->next_in_file = prev;
2337 file_p->defs_decs = prev;
2342 /* Find the (only?) extern definition for a particular function name, starting
2343 from the head of the linked list of entries for the given name. If we
2344 cannot find an extern definition for the given function name, issue a
2345 warning and scrounge around for the next best thing, i.e. an extern
2346 function declaration with a prototype attached to it. Note that we only
2347 allow such substitutions for extern declarations and never for static
2348 declarations. That's because the only reason we allow them at all is
2349 to let un-prototyped function declarations for system-supplied library
2350 functions get their prototypes from our own extra SYSCALLS.c.X file which
2351 contains all of the correct prototypes for system functions. */
2353 static const def_dec_info *
2354 find_extern_def (head, user)
2355 const def_dec_info *head;
2356 const def_dec_info *user;
2358 const def_dec_info *dd_p;
2359 const def_dec_info *extern_def_p = NULL;
2360 int conflict_noted = 0;
2362 /* Don't act too stupid here. Somebody may try to convert an entire system
2363 in one swell fwoop (rather than one program at a time, as should be done)
2364 and in that case, we may find that there are multiple extern definitions
2365 of a given function name in the entire set of source files that we are
2366 converting. If however one of these definitions resides in exactly the
2367 same source file as the reference we are trying to satisfy then in that
2368 case it would be stupid for us to fail to realize that this one definition
2369 *must* be the precise one we are looking for.
2371 To make sure that we don't miss an opportunity to make this "same file"
2372 leap of faith, we do a prescan of the list of records relating to the
2373 given function name, and we look (on this first scan) *only* for a
2374 definition of the function which is in the same file as the reference
2375 we are currently trying to satisfy. */
2377 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2378 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2381 /* Now, since we have not found a definition in the same file as the
2382 reference, we scan the list again and consider all possibilities from
2383 all files. Here we may get conflicts with the things listed in the
2384 SYSCALLS.c.X file, but if that happens it only means that the source
2385 code being converted contains its own definition of a function which
2386 could have been supplied by libc.a. In such cases, we should avoid
2387 issuing the normal warning, and defer to the definition given in the
2390 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2391 if (dd_p->is_func_def && !dd_p->is_static)
2393 if (!extern_def_p) /* Previous definition? */
2394 extern_def_p = dd_p; /* Remember the first definition found. */
2397 /* Ignore definition just found if it came from SYSCALLS.c.X. */
2399 if (is_syscalls_file (dd_p->file))
2402 /* Quietly replace the definition previously found with the one
2403 just found if the previous one was from SYSCALLS.c.X. */
2405 if (is_syscalls_file (extern_def_p->file))
2407 extern_def_p = dd_p;
2411 /* If we get here, then there is a conflict between two function
2412 declarations for the same function, both of which came from the
2415 if (!conflict_noted) /* first time we noticed? */
2418 fprintf (stderr, "%s: error: conflicting extern definitions of '%s'\n",
2419 pname, head->hash_entry->symbol);
2422 fprintf (stderr, "%s: declarations of '%s' will not be converted\n",
2423 pname, head->hash_entry->symbol);
2424 fprintf (stderr, "%s: conflict list for '%s' follows:\n",
2425 pname, head->hash_entry->symbol);
2426 fprintf (stderr, "%s: %s(%d): %s\n",
2428 shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2429 extern_def_p->line, extern_def_p->ansi_decl);
2433 fprintf (stderr, "%s: %s(%d): %s\n",
2435 shortpath (NULL, dd_p->file->hash_entry->symbol),
2436 dd_p->line, dd_p->ansi_decl);
2440 /* We want to err on the side of caution, so if we found multiple conflicting
2441 definitions for the same function, treat this as being that same as if we
2442 had found no definitions (i.e. return NULL). */
2449 /* We have no definitions for this function so do the next best thing.
2450 Search for an extern declaration already in prototype form. */
2452 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2453 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2455 extern_def_p = dd_p; /* save a pointer to the definition */
2457 fprintf (stderr, "%s: warning: using formals list from %s(%d) for function `%s'\n",
2459 shortpath (NULL, dd_p->file->hash_entry->symbol),
2460 dd_p->line, dd_p->hash_entry->symbol);
2464 /* Gripe about unprototyped function declarations that we found no
2465 corresponding definition (or other source of prototype information)
2468 Gripe even if the unprototyped declaration we are worried about
2469 exists in a file in one of the "system" include directories. We
2470 can gripe about these because we should have at least found a
2471 corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
2472 didn't, then that means that the SYSCALLS.c.X file is missing some
2473 needed prototypes for this particular system. That is worth telling
2478 const char *file = user->file->hash_entry->symbol;
2481 if (in_system_include_dir (file))
2483 /* Why copy this string into `needed' at all?
2484 Why not just use user->ansi_decl without copying? */
2485 char *needed = (char *) alloca (strlen (user->ansi_decl) + 1);
2488 strcpy (needed, user->ansi_decl);
2489 p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
2490 + strlen (user->hash_entry->symbol) + 2;
2491 strcpy (p, "??\?);");
2493 fprintf (stderr, "%s: %d: `%s' used but missing from SYSCALLS\n",
2494 shortpath (NULL, file), user->line,
2495 needed+7); /* Don't print "extern " */
2498 fprintf (stderr, "%s: %d: warning: no extern definition for `%s'\n",
2499 shortpath (NULL, file), user->line,
2500 user->hash_entry->symbol);
2503 return extern_def_p;
2506 /* Find the (only?) static definition for a particular function name in a
2507 given file. Here we get the function-name and the file info indirectly
2508 from the def_dec_info record pointer which is passed in. */
2510 static const def_dec_info *
2511 find_static_definition (user)
2512 const def_dec_info *user;
2514 const def_dec_info *head = user->hash_entry->ddip;
2515 const def_dec_info *dd_p;
2516 int num_static_defs = 0;
2517 const def_dec_info *static_def_p = NULL;
2519 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2520 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2522 static_def_p = dd_p; /* save a pointer to the definition */
2525 if (num_static_defs == 0)
2528 fprintf (stderr, "%s: warning: no static definition for `%s' in file `%s'\n",
2529 pname, head->hash_entry->symbol,
2530 shortpath (NULL, user->file->hash_entry->symbol));
2532 else if (num_static_defs > 1)
2534 fprintf (stderr, "%s: error: multiple static defs of `%s' in file `%s'\n",
2535 pname, head->hash_entry->symbol,
2536 shortpath (NULL, user->file->hash_entry->symbol));
2539 return static_def_p;
2542 /* Find good prototype style formal argument lists for all of the function
2543 declarations which didn't have them before now.
2545 To do this we consider each function name one at a time. For each function
2546 name, we look at the items on the linked list of def_dec_info records for
2547 that particular name.
2549 Somewhere on this list we should find one (and only one) def_dec_info
2550 record which represents the actual function definition, and this record
2551 should have a nice formal argument list already associated with it.
2553 Thus, all we have to do is to connect up all of the other def_dec_info
2554 records for this particular function name to the special one which has
2555 the full-blown formals list.
2557 Of course it is a little more complicated than just that. See below for
2561 connect_defs_and_decs (hp)
2562 const hash_table_entry *hp;
2564 const def_dec_info *dd_p;
2565 const def_dec_info *extern_def_p = NULL;
2566 int first_extern_reference = 1;
2568 /* Traverse the list of definitions and declarations for this particular
2569 function name. For each item on the list, if it is a function
2570 definition (either old style or new style) then GCC has already been
2571 kind enough to produce a prototype for us, and it is associated with
2572 the item already, so declare the item as its own associated "definition".
2574 Also, for each item which is only a function declaration, but which
2575 nonetheless has its own prototype already (obviously supplied by the user)
2576 declare the item as it's own definition.
2578 Note that when/if there are multiple user-supplied prototypes already
2579 present for multiple declarations of any given function, these multiple
2580 prototypes *should* all match exactly with one another and with the
2581 prototype for the actual function definition. We don't check for this
2582 here however, since we assume that the compiler must have already done
2583 this consistancy checking when it was creating the .X files. */
2585 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2586 if (dd_p->prototyped)
2587 ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2589 /* Traverse the list of definitions and declarations for this particular
2590 function name. For each item on the list, if it is an extern function
2591 declaration and if it has no associated definition yet, go try to find
2592 the matching extern definition for the declaration.
2594 When looking for the matching function definition, warn the user if we
2597 If we find more that one function definition also issue a warning.
2599 Do the search for the matching definition only once per unique function
2600 name (and only when absolutely needed) so that we can avoid putting out
2601 redundant warning messages, and so that we will only put out warning
2602 messages when there is actually a reference (i.e. a declaration) for
2603 which we need to find a matching definition. */
2605 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2606 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2608 if (first_extern_reference)
2610 extern_def_p = find_extern_def (hp->ddip, dd_p);
2611 first_extern_reference = 0;
2613 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2616 /* Traverse the list of definitions and declarations for this particular
2617 function name. For each item on the list, if it is a static function
2618 declaration and if it has no associated definition yet, go try to find
2619 the matching static definition for the declaration within the same file.
2621 When looking for the matching function definition, warn the user if we
2622 fail to find one in the same file with the declaration, and refuse to
2623 convert this kind of cross-file static function declaration. After all,
2624 this is stupid practice and should be discouraged.
2626 We don't have to worry about the possibility that there is more than one
2627 matching function definition in the given file because that would have
2628 been flagged as an error by the compiler.
2630 Do the search for the matching definition only once per unique
2631 function-name/source-file pair (and only when absolutely needed) so that
2632 we can avoid putting out redundant warning messages, and so that we will
2633 only put out warning messages when there is actually a reference (i.e. a
2634 declaration) for which we actually need to find a matching definition. */
2636 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2637 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2639 const def_dec_info *dd_p2;
2640 const def_dec_info *static_def;
2642 /* We have now found a single static declaration for which we need to
2643 find a matching definition. We want to minimize the work (and the
2644 number of warnings), so we will find an appropriate (matching)
2645 static definition for this declaration, and then distribute it
2646 (as the definition for) any and all other static declarations
2647 for this function name which occur within the same file, and which
2648 do not already have definitions.
2650 Note that a trick is used here to prevent subsequent attempts to
2651 call find_static_definition for a given function-name & file
2652 if the first such call returns NULL. Essentially, we convert
2653 these NULL return values to -1, and put the -1 into the definition
2654 field for each other static declaration from the same file which
2655 does not already have an associated definition.
2656 This makes these other static declarations look like they are
2657 actually defined already when the outer loop here revisits them
2658 later on. Thus, the outer loop will skip over them. Later, we
2659 turn the -1's back to NULL's. */
2661 ((NONCONST def_dec_info *) dd_p)->definition =
2662 (static_def = find_static_definition (dd_p))
2664 : (const def_dec_info *) -1;
2666 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2667 if (!dd_p2->is_func_def && dd_p2->is_static
2668 && !dd_p2->definition && (dd_p2->file == dd_p->file))
2669 ((NONCONST def_dec_info *)dd_p2)->definition = dd_p->definition;
2672 /* Convert any dummy (-1) definitions we created in the step above back to
2673 NULL's (as they should be). */
2675 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2676 if (dd_p->definition == (def_dec_info *) -1)
2677 ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2680 #endif /* !defined (UNPROTOIZE) */
2682 /* Give a pointer into the clean text buffer, return a number which is the
2683 original source line number that the given pointer points into. */
2686 identify_lineno (clean_p)
2687 const char *clean_p;
2692 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2693 if (*scan_p == '\n')
2698 /* Issue an error message and give up on doing this particular edit. */
2701 declare_source_confusing (clean_p)
2702 const char *clean_p;
2707 fprintf (stderr, "%s: %d: warning: source too confusing\n",
2708 shortpath (NULL, convert_filename), last_known_line_number);
2710 fprintf (stderr, "%s: %d: warning: source too confusing\n",
2711 shortpath (NULL, convert_filename),
2712 identify_lineno (clean_p));
2714 longjmp (source_confusion_recovery, 1);
2717 /* Check that a condition which is expected to be true in the original source
2718 code is in fact true. If not, issue an error message and give up on
2719 converting this particular source file. */
2722 check_source (cond, clean_p)
2724 const char *clean_p;
2727 declare_source_confusing (clean_p);
2730 /* If we think of the in-core cleaned text buffer as a memory mapped
2731 file (with the variable last_known_line_start acting as sort of a
2732 file pointer) then we can imagine doing "seeks" on the buffer. The
2733 following routine implements a kind of "seek" operation for the in-core
2734 (cleaned) copy of the source file. When finished, it returns a pointer to
2735 the start of a given (numbered) line in the cleaned text buffer.
2737 Note that protoize only has to "seek" in the forward direction on the
2738 in-core cleaned text file buffers, and it never needs to back up.
2740 This routine is made a little bit faster by remembering the line number
2741 (and pointer value) supplied (and returned) from the previous "seek".
2742 This prevents us from always having to start all over back at the top
2743 of the in-core cleaned buffer again. */
2749 if (n < last_known_line_number)
2752 while (n > last_known_line_number)
2754 while (*last_known_line_start != '\n')
2755 check_source (++last_known_line_start < clean_text_limit, 0);
2756 last_known_line_start++;
2757 last_known_line_number++;
2759 return last_known_line_start;
2762 /* Given a pointer to a character in the cleaned text buffer, return a pointer
2763 to the next non-whitepace character which follows it. */
2766 forward_to_next_token_char (ptr)
2769 for (++ptr; isspace (*ptr); check_source (++ptr < clean_text_limit, 0))
2774 /* Copy a chunk of text of length `len' and starting at `str' to the current
2775 output buffer. Note that all attempts to add stuff to the current output
2776 buffer ultimately go through here. */
2779 output_bytes (str, len)
2783 if ((repl_write_ptr + 1) + len >= repl_text_limit)
2785 size_t new_size = (repl_text_limit - repl_text_base) << 1;
2786 char *new_buf = (char *) xrealloc (repl_text_base, new_size);
2788 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
2789 repl_text_base = new_buf;
2790 repl_text_limit = new_buf + new_size;
2792 memcpy (repl_write_ptr + 1, str, len);
2793 repl_write_ptr += len;
2796 /* Copy all bytes (except the trailing null) of a null terminated string to
2797 the current output buffer. */
2803 output_bytes (str, strlen (str));
2806 /* Copy some characters from the original text buffer to the current output
2809 This routine takes a pointer argument `p' which is assumed to be a pointer
2810 into the cleaned text buffer. The bytes which are copied are the `original'
2811 equivalents for the set of bytes between the last value of `clean_read_ptr'
2812 and the argument value `p'.
2814 The set of bytes copied however, comes *not* from the cleaned text buffer,
2815 but rather from the direct counterparts of these bytes within the original
2818 Thus, when this function is called, some bytes from the original text
2819 buffer (which may include original comments and preprocessing directives)
2820 will be copied into the output buffer.
2822 Note that the request implide when this routine is called includes the
2823 byte pointed to by the argument pointer `p'. */
2829 size_t copy_length = (size_t) (p - clean_read_ptr);
2830 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
2832 if (copy_length == 0)
2835 output_bytes (copy_start, copy_length);
2839 /* Given a pointer to a def_dec_info record which represents some form of
2840 definition of a function (perhaps a real definition, or in lieu of that
2841 perhaps just a declaration with a full prototype) return true if this
2842 function is one which we should avoid converting. Return false
2846 other_variable_style_function (ansi_header)
2847 const char *ansi_header;
2851 /* See if we have a stdarg function, or a function which has stdarg style
2852 parameters or a stdarg style return type. */
2854 return (int) substr (ansi_header, "...");
2856 #else /* !defined (UNPROTOIZE) */
2858 /* See if we have a varargs function, or a function which has varargs style
2859 parameters or a varargs style return type. */
2862 int len = strlen (varargs_style_indicator);
2864 for (p = ansi_header; p; )
2866 const char *candidate;
2868 if ((candidate = substr (p, varargs_style_indicator)) == 0)
2871 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
2877 #endif /* !defined (UNPROTOIZE) */
2880 /* Do the editing operation specifically for a function "declaration". Note
2881 that editing for function "definitions" are handled in a separate routine
2885 edit_fn_declaration (def_dec_p, clean_text_p)
2886 const def_dec_info *def_dec_p;
2887 const char *VOLATILE clean_text_p;
2889 const char *start_formals;
2890 const char *end_formals;
2891 const char *function_to_edit = def_dec_p->hash_entry->symbol;
2892 size_t func_name_len = strlen (function_to_edit);
2893 const char *end_of_fn_name;
2897 const f_list_chain_item *this_f_list_chain_item;
2898 const def_dec_info *definition = def_dec_p->definition;
2900 /* If we are protoizing, and if we found no corresponding definition for
2901 this particular function declaration, then just leave this declaration
2902 exactly as it is. */
2907 /* If we are protoizing, and if the corresponding definition that we found
2908 for this particular function declaration defined an old style varargs
2909 function, then we want to issue a warning and just leave this function
2910 declaration unconverted. */
2912 if (other_variable_style_function (definition->ansi_decl))
2915 fprintf (stderr, "%s: %d: warning: varargs function declaration not converted\n",
2916 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
2921 #endif /* !defined (UNPROTOIZE) */
2923 /* Setup here to recover from confusing source code detected during this
2924 particular "edit". */
2927 if (setjmp (source_confusion_recovery))
2929 restore_pointers ();
2930 fprintf (stderr, "%s: declaration of function `%s' not converted\n",
2931 pname, function_to_edit);
2935 /* We are editing a function declaration. The line number we did a seek to
2936 contains the comma or semicolon which follows the declaration. Our job
2937 now is to scan backwards looking for the function name. This name *must*
2938 be followed by open paren (ignoring whitespace, of course). We need to
2939 replace everything between that open paren and the corresponding closing
2940 paren. If we are protoizing, we need to insert the prototype-style
2941 formals lists. If we are unprotoizing, we need to just delete everything
2942 between the pairs of opening and closing parens. */
2944 /* First move up to the end of the line. */
2946 while (*clean_text_p != '\n')
2947 check_source (++clean_text_p < clean_text_limit, 0);
2948 clean_text_p--; /* Point to just before the newline character. */
2950 /* Now we can scan backwards for the function name. */
2956 /* Scan leftwards until we find some character which can be
2957 part of an identifier. */
2959 while (!is_id_char (*clean_text_p))
2960 check_source (--clean_text_p > clean_read_ptr, 0);
2962 /* Scan backwards until we find a char that cannot be part of an
2965 while (is_id_char (*clean_text_p))
2966 check_source (--clean_text_p > clean_read_ptr, 0);
2968 /* Having found an "id break", see if the following id is the one
2969 that we are looking for. If so, then exit from this loop. */
2971 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
2973 char ch = *(clean_text_p + 1 + func_name_len);
2975 /* Must also check to see that the name in the source text
2976 ends where it should (in order to prevent bogus matches
2977 on similar but longer identifiers. */
2979 if (! is_id_char (ch))
2980 break; /* exit from loop */
2984 /* We have now found the first perfect match for the function name in
2985 our backward search. This may or may not be the actual function
2986 name at the start of the actual function declaration (i.e. we could
2987 have easily been mislead). We will try to avoid getting fooled too
2988 often by looking forward for the open paren which should follow the
2989 identifier we just found. We ignore whitespace while hunting. If
2990 the next non-whitespace byte we see is *not* an open left paren,
2991 then we must assume that we have been fooled and we start over
2992 again accordingly. Note that there is no guarrantee, that even if
2993 we do see the open paren, that we are in the right place.
2994 Programmers do the strangest things sometimes! */
2996 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
2997 start_formals = forward_to_next_token_char (end_of_fn_name);
2999 while (*start_formals != '(');
3001 /* start_of_formals now points to the opening left paren which immediately
3002 follows the name of the function. */
3004 /* Note that there may be several formals lists which need to be modified
3005 due to the possibility that the return type of this function is a
3006 pointer-to-function type. If there are several formals lists, we
3007 convert them in left-to-right order here. */
3010 this_f_list_chain_item = definition->f_list_chain;
3011 #endif /* !defined (UNPROTOIZE) */
3018 end_formals = start_formals + 1;
3020 for (; depth; check_source (++end_formals < clean_text_limit, 0))
3022 switch (*end_formals)
3035 /* end_formals now points to the closing right paren of the formals
3036 list whose left paren is pointed to by start_formals. */
3038 /* Now, if we are protoizing, we insert the new ANSI-style formals list
3039 attached to the associated definition of this function. If however
3040 we are unprotoizing, then we simply delete any formals list which
3043 output_up_to (start_formals);
3045 if (this_f_list_chain_item)
3047 output_string (this_f_list_chain_item->formals_list);
3048 this_f_list_chain_item = this_f_list_chain_item->chain_next;
3053 fprintf (stderr, "%s: warning: too many parameter lists in declaration of `%s'\n",
3054 pname, def_dec_p->hash_entry->symbol);
3055 check_source (0, end_formals); /* leave the declaration intact */
3057 #endif /* !defined (UNPROTOIZE) */
3058 clean_read_ptr = end_formals - 1;
3060 /* Now see if it looks like there may be another formals list associated
3061 with the function declaration that we are converting (following the
3062 formals list that we just converted. */
3065 const char *another_r_paren = forward_to_next_token_char (end_formals);
3067 if ((*another_r_paren != ')')
3068 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3071 if (this_f_list_chain_item)
3074 fprintf (stderr, "\n%s: warning: too few parameter lists in declaration of `%s'\n",
3075 pname, def_dec_p->hash_entry->symbol);
3076 check_source (0, start_formals); /* leave the decl intact */
3078 #endif /* !defined (UNPROTOIZE) */
3084 /* There does appear to be yet another formals list, so loop around
3085 again, and convert it also. */
3089 /* Edit a whole group of formals lists, starting with the rightmost one
3090 from some set of formals lists. This routine is called once (from the
3091 outside) for each function declaration which is converted. It is
3092 recursive however, and it calls itself once for each remaining formal
3093 list that lies to the left of the one it was originally called to work
3094 on. Thus, a whole set gets done in right-to-left order.
3096 This routine returns non-zero if it thinks that it should not be trying
3097 to convert this particular function definition (because the name of the
3098 function doesn't match the one expected). */
3101 edit_formals_lists (end_formals, f_list_count, def_dec_p)
3102 const char *end_formals;
3103 unsigned int f_list_count;
3104 const def_dec_info *def_dec_p;
3106 const char *start_formals;
3109 start_formals = end_formals - 1;
3111 for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3113 switch (*start_formals)
3125 /* start_formals now points to the opening left paren of the formals list. */
3131 const char *next_end;
3133 /* There should be more formal lists to the left of here. */
3135 next_end = start_formals - 1;
3136 check_source (next_end > clean_read_ptr, 0);
3137 while (isspace (*next_end))
3138 check_source (--next_end > clean_read_ptr, 0);
3139 check_source (*next_end == ')', next_end);
3140 check_source (--next_end > clean_read_ptr, 0);
3141 check_source (*next_end == ')', next_end);
3142 if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3146 /* Check that the function name in the header we are working on is the same
3147 as the one we would expect to find. If not, issue a warning and return
3150 if (f_list_count == 0)
3152 const char *expected = def_dec_p->hash_entry->symbol;
3153 const char *func_name_start;
3154 const char *func_name_limit;
3155 size_t func_name_len;
3157 for (func_name_limit = start_formals-1; isspace (*func_name_limit); )
3158 check_source (--func_name_limit > clean_read_ptr, 0);
3160 for (func_name_start = func_name_limit++;
3161 is_id_char (*func_name_start);
3163 check_source (func_name_start > clean_read_ptr, 0);
3165 func_name_len = func_name_limit - func_name_start;
3166 if (func_name_len == 0)
3167 check_source (0, func_name_start);
3168 if (func_name_len != strlen (expected)
3169 || strncmp (func_name_start, expected, func_name_len))
3171 fprintf (stderr, "%s: %d: warning: found `%s' but expected `%s'\n",
3172 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3173 identify_lineno (func_name_start),
3174 dupnstr (func_name_start, func_name_len),
3180 output_up_to (start_formals);
3183 if (f_list_count == 0)
3184 output_string (def_dec_p->formal_names);
3185 #else /* !defined (UNPROTOIZE) */
3187 unsigned f_list_depth;
3188 const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3190 /* At this point, the current value of f_list count says how many
3191 links we have to follow through the f_list_chain to get to the
3192 particular formals list that we need to output next. */
3194 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3195 flci_p = flci_p->chain_next;
3196 output_string (flci_p->formals_list);
3198 #endif /* !defined (UNPROTOIZE) */
3200 clean_read_ptr = end_formals - 1;
3204 /* Given a pointer to a byte in the clean text buffer which points to the
3205 beginning of a line that contains a "follower" token for a function
3206 definition header, do whatever is necessary to find the right closing
3207 paren for the rightmost formals list of the function definition header.
3211 find_rightmost_formals_list (clean_text_p)
3212 const char *clean_text_p;
3214 const char *end_formals;
3216 /* We are editing a function definition. The line number we did a seek
3217 to contains the first token which immediately follows the entire set of
3218 formals lists which are part of this particular function definition
3221 Our job now is to scan leftwards in the clean text looking for the
3222 right-paren which is at the end of the function header's rightmost
3225 If we ignore whitespace, this right paren should be the first one we
3226 see which is (ignoring whitespace) immediately followed either by the
3227 open curly-brace beginning the function body or by an alphabetic
3228 character (in the case where the function definition is in old (K&R)
3229 style and there are some declarations of formal parameters). */
3231 /* It is possible that the right paren we are looking for is on the
3232 current line (together with its following token). Just in case that
3233 might be true, we start out here by skipping down to the right end of
3234 the current line before starting our scan. */
3236 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3242 /* Now scan backwards while looking for the right end of the rightmost
3243 formals list associated with this function definition. */
3247 const char *l_brace_p;
3249 /* Look leftward and try to find a right-paren. */
3251 while (*end_formals != ')')
3253 if (isspace (*end_formals))
3254 while (isspace (*end_formals))
3255 check_source (--end_formals > clean_read_ptr, 0);
3257 check_source (--end_formals > clean_read_ptr, 0);
3260 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3261 /* Since we are unprotoizing an ANSI-style (prototyped) function
3262 definition, there had better not be anything (except whitespace)
3263 between the end of the ANSI formals list and the beginning of the
3264 function body (i.e. the '{'). */
3266 check_source (ch == '{', l_brace_p);
3269 #else /* !defined (UNPROTOIZE) */
3271 /* Now scan backwards while looking for the right end of the rightmost
3272 formals list associated with this function definition. */
3277 const char *l_brace_p;
3279 /* Look leftward and try to find a right-paren. */
3281 while (*end_formals != ')')
3283 if (isspace (*end_formals))
3284 while (isspace (*end_formals))
3285 check_source (--end_formals > clean_read_ptr, 0);
3287 check_source (--end_formals > clean_read_ptr, 0);
3290 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3292 /* Since it is possible that we found a right paren before the starting
3293 '{' of the body which IS NOT the one at the end of the real K&R
3294 formals list (say for instance, we found one embedded inside one of
3295 the old K&R formal parameter declarations) we have to check to be
3296 sure that this is in fact the right paren that we were looking for.
3298 The one we were looking for *must* be followed by either a '{' or
3299 by an alphabetic character, while others *cannot* legally be followed
3300 by such characters. */
3302 if ((ch == '{') || isalpha (ch))
3305 /* At this point, we have found a right paren, but we know that it is
3306 not the one we were looking for, so backup one character and keep
3309 check_source (--end_formals > clean_read_ptr, 0);
3312 #endif /* !defined (UNPROTOIZE) */
3319 /* Insert into the output file a totally new declaration for a function
3320 which (up until now) was being called from within the current block
3321 without having been declared at any point such that the declaration
3322 was visible (i.e. in scope) at the point of the call.
3324 We need to add in explicit declarations for all such function calls
3325 in order to get the full benefit of prototype-based function call
3326 parameter type checking. */
3329 add_local_decl (def_dec_p, clean_text_p)
3330 const def_dec_info *def_dec_p;
3331 const char *clean_text_p;
3333 const char *start_of_block;
3334 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3336 /* Don't insert new local explicit declarations unless explicitly requested
3342 /* Setup here to recover from confusing source code detected during this
3343 particular "edit". */
3346 if (setjmp (source_confusion_recovery))
3348 restore_pointers ();
3349 fprintf (stderr, "%s: local declaration for function `%s' not inserted\n",
3350 pname, function_to_edit);
3354 /* We have already done a seek to the start of the line which should
3355 contain *the* open curly brace which begins the block in which we need
3356 to insert an explicit function declaration (to replace the implicit one).
3358 Now we scan that line, starting from the left, until we find the
3359 open curly brace we are looking for. Note that there may actually be
3360 multiple open curly braces on the given line, but we will be happy
3361 with the leftmost one no matter what. */
3363 start_of_block = clean_text_p;
3364 while (*start_of_block != '{' && *start_of_block != '\n')
3365 check_source (++start_of_block < clean_text_limit, 0);
3367 /* Note that the line from the original source could possibly
3368 contain *no* open curly braces! This happens if the line contains
3369 a macro call which expands into a chunk of text which includes a
3370 block (and that block's associated open and close curly braces).
3371 In cases like this, we give up, issue a warning, and do nothing. */
3373 if (*start_of_block != '{')
3377 "\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
3378 def_dec_p->file->hash_entry->symbol, def_dec_p->line,
3379 def_dec_p->hash_entry->symbol);
3383 /* Figure out what a nice (pretty) indentation would be for the new
3384 declaration we are adding. In order to do this, we must scan forward
3385 from the '{' until we find the first line which starts with some
3386 non-whitespace characters (i.e. real "token" material). */
3389 const char *ep = forward_to_next_token_char (start_of_block) - 1;
3392 /* Now we have ep pointing at the rightmost byte of some existing indent
3393 stuff. At least that is the hope.
3395 We can now just scan backwards and find the left end of the existing
3396 indentation string, and then copy it to the output buffer. */
3398 for (sp = ep; isspace (*sp) && *sp != '\n'; sp--)
3401 /* Now write out the open { which began this block, and any following
3402 trash up to and including the last byte of the existing indent that
3407 /* Now we go ahead and insert the new declaration at this point.
3409 If the definition of the given function is in the same file that we
3410 are currently editing, and if its full ANSI declaration normally
3411 would start with the keyword `extern', suppress the `extern'. */
3414 const char *decl = def_dec_p->definition->ansi_decl;
3416 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
3418 output_string (decl);
3421 /* Finally, write out a new indent string, just like the preceeding one
3422 that we found. This will typically include a newline as the first
3423 character of the indent string. */
3425 output_bytes (sp, (size_t) (ep - sp) + 1);
3429 /* Given a pointer to a file_info record, and a pointer to the beginning
3430 of a line (in the clean text buffer) which is assumed to contain the
3431 first "follower" token for the first function definition header in the
3432 given file, find a good place to insert some new global function
3433 declarations (which will replace scattered and imprecise implicit ones)
3434 and then insert the new explicit declaration at that point in the file. */
3437 add_global_decls (file_p, clean_text_p)
3438 const file_info *file_p;
3439 const char *clean_text_p;
3441 const def_dec_info *dd_p;
3444 /* Setup here to recover from confusing source code detected during this
3445 particular "edit". */
3448 if (setjmp (source_confusion_recovery))
3450 restore_pointers ();
3451 fprintf (stderr, "%s: global declarations for file `%s' not inserted\n",
3452 pname, shortpath (NULL, file_p->hash_entry->symbol));
3456 /* Start by finding a good location for adding the new explicit function
3457 declarations. To do this, we scan backwards, ignoring whitespace
3458 and comments and other junk until we find either a semicolon, or until
3459 we hit the beginning of the file. */
3461 scan_p = find_rightmost_formals_list (clean_text_p);
3464 if (scan_p < clean_text_base)
3466 check_source (scan_p > clean_read_ptr, 0);
3471 /* scan_p now points either to a semicolon, or to just before the start
3472 of the whole file. */
3474 /* Now scan forward for the first non-whitespace character. In theory,
3475 this should be the first character of the following function definition
3476 header. We will put in the added declarations just prior to that. */
3479 while (isspace (*scan_p))
3483 output_up_to (scan_p);
3485 /* Now write out full prototypes for all of the things that had been
3486 implicitly declared in this file (but only those for which we were
3487 actually able to find unique matching definitions). Avoid duplicates
3488 by marking things that we write out as we go. */
3491 int some_decls_added = 0;
3493 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3494 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
3496 const char *decl = dd_p->definition->ansi_decl;
3498 /* If the function for which we are inserting a declaration is
3499 actually defined later in the same file, then suppress the
3500 leading `extern' keyword (if there is one). */
3502 if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
3505 output_string ("\n");
3506 output_string (decl);
3507 some_decls_added = 1;
3508 ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
3510 if (some_decls_added)
3511 output_string ("\n\n");
3514 /* Unmark all of the definitions that we just marked. */
3516 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3517 if (dd_p->definition)
3518 ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
3521 #endif /* !defined (UNPROTOIZE) */
3523 /* Do the editing operation specifically for a function "definition". Note
3524 that editing operations for function "declarations" are handled by a
3525 separate routine above. */
3528 edit_fn_definition (def_dec_p, clean_text_p)
3529 const def_dec_info *def_dec_p;
3530 const char *clean_text_p;
3532 const char *end_formals;
3533 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3535 /* Setup here to recover from confusing source code detected during this
3536 particular "edit". */
3539 if (setjmp (source_confusion_recovery))
3541 restore_pointers ();
3542 fprintf (stderr, "%s: definition of function `%s' not converted\n",
3543 pname, function_to_edit);
3547 end_formals = find_rightmost_formals_list (clean_text_p);
3549 /* end_of_formals now points to the closing right paren of the rightmost
3550 formals list which is actually part of the `header' of the function
3551 definition that we are converting. */
3553 /* If the header of this function definition looks like it declares a
3554 function with a variable number of arguments, and if the way it does
3555 that is different from that way we would like it (i.e. varargs vs.
3556 stdarg) then issue a warning and leave the header unconverted. */
3558 if (other_variable_style_function (def_dec_p->ansi_decl))
3561 fprintf (stderr, "%s: %d: warning: definition of %s not converted\n",
3562 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3563 identify_lineno (end_formals),
3565 output_up_to (end_formals);
3569 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
3571 restore_pointers ();
3572 fprintf (stderr, "%s: definition of function `%s' not converted\n",
3573 pname, function_to_edit);
3577 /* Have to output the last right paren because this never gets flushed by
3578 edit_formals_list. */
3580 output_up_to (end_formals);
3585 const char *semicolon_p;
3586 const char *limit_p;
3588 int had_newlines = 0;
3590 /* Now write out the K&R style formal declarations, one per line. */
3592 decl_p = def_dec_p->formal_decls;
3593 limit_p = decl_p + strlen (decl_p);
3594 for (;decl_p < limit_p; decl_p = semicolon_p + 2)
3596 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
3598 output_string ("\n");
3599 output_string (indent_string);
3600 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
3603 /* If there are no newlines between the end of the formals list and the
3604 start of the body, we should insert one now. */
3606 for (scan_p = end_formals+1; *scan_p != '{'; )
3608 if (*scan_p == '\n')
3613 check_source (++scan_p < clean_text_limit, 0);
3616 output_string ("\n");
3618 #else /* !defined (UNPROTOIZE) */
3619 /* If we are protoizing, there may be some flotsum & jetsum (like comments
3620 and preprocessing directives) after the old formals list but before
3621 the following { and we would like to preserve that stuff while effectively
3622 deleting the existing K&R formal parameter declarations. We do so here
3623 in a rather tricky way. Basically, we white out any stuff *except*
3624 the comments/pp-directives in the original text buffer, then, if there
3625 is anything in this area *other* than whitespace, we output it. */
3627 const char *end_formals_orig;
3628 const char *start_body;
3629 const char *start_body_orig;
3631 const char *scan_orig;
3632 int have_flotsum = 0;
3633 int have_newlines = 0;
3635 for (start_body = end_formals + 1; *start_body != '{';)
3636 check_source (++start_body < clean_text_limit, 0);
3638 end_formals_orig = orig_text_base + (end_formals - clean_text_base);
3639 start_body_orig = orig_text_base + (start_body - clean_text_base);
3640 scan = end_formals + 1;
3641 scan_orig = end_formals_orig + 1;
3642 for (; scan < start_body; scan++, scan_orig++)
3644 if (*scan == *scan_orig)
3646 have_newlines |= (*scan_orig == '\n');
3647 /* Leave identical whitespace alone. */
3648 if (!isspace (*scan_orig))
3649 *((NONCONST char *)scan_orig) = ' '; /* identical - so whiteout */
3655 output_bytes (end_formals_orig + 1,
3656 (size_t) (start_body_orig - end_formals_orig) - 1);
3659 output_string ("\n");
3661 output_string (" ");
3662 clean_read_ptr = start_body - 1;
3664 #endif /* !defined (UNPROTOIZE) */
3667 /* Clean up the clean text buffer. Do this by converting comments and
3668 preprocessor directives into spaces. Also convert line continuations
3669 into whitespace. Also, whiteout string and character literals. */
3672 do_cleaning (new_clean_text_base, new_clean_text_limit)
3673 char *new_clean_text_base;
3674 char *new_clean_text_limit;
3677 int non_whitespace_since_newline = 0;
3679 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
3683 case '/': /* Handle comments. */
3684 if (scan_p[1] != '*')
3686 non_whitespace_since_newline = 1;
3690 while (scan_p[1] != '/' || scan_p[0] != '*')
3692 if (!isspace (*scan_p))
3694 if (++scan_p >= new_clean_text_limit)
3701 case '#': /* Handle pp directives. */
3702 if (non_whitespace_since_newline)
3705 while (scan_p[1] != '\n' || scan_p[0] == '\\')
3707 if (!isspace (*scan_p))
3709 if (++scan_p >= new_clean_text_limit)
3715 case '\'': /* Handle character literals. */
3716 non_whitespace_since_newline = 1;
3717 while (scan_p[1] != '\'' || scan_p[0] == '\\')
3719 if (scan_p[0] == '\\' && !isspace (scan_p[1]))
3721 if (!isspace (*scan_p))
3723 if (++scan_p >= new_clean_text_limit)
3729 case '"': /* Handle string literals. */
3730 non_whitespace_since_newline = 1;
3731 while (scan_p[1] != '"' || scan_p[0] == '\\')
3733 if (scan_p[0] == '\\' && !isspace (scan_p[1]))
3735 if (!isspace (*scan_p))
3737 if (++scan_p >= new_clean_text_limit)
3743 case '\\': /* Handle line continuations. */
3744 if (scan_p[1] != '\n')
3750 non_whitespace_since_newline = 0; /* Reset. */
3759 break; /* Whitespace characters. */
3763 non_whitespace_since_newline = 1;
3769 /* Given a pointer to the closing right parenthesis for a particular formals
3770 list (in the clean text buffer) find the corresponding left parenthesis
3771 and return a pointer to it. */
3774 careful_find_l_paren (p)
3780 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
3795 /* Scan the clean text buffer for cases of function definitions that we
3796 don't really know about because they were preprocessed out when the
3797 aux info files were created.
3799 In this version of protoize/unprotoize we just give a warning for each
3800 one found. A later version may be able to at least unprotoize such
3803 Note that we may easily find all function definitions simply by
3804 looking for places where there is a left paren which is (ignoring
3805 whitespace) immediately followed by either a left-brace or by an
3806 upper or lower case letter. Whenever we find this combination, we
3807 have also found a function definition header.
3809 Finding function *declarations* using syntactic clues is much harder.
3810 I will probably try to do this in a later version though. */
3813 scan_for_missed_items (file_p)
3814 const file_info *file_p;
3816 static const char *scan_p;
3817 const char *limit = clean_text_limit - 3;
3818 static const char *backup_limit;
3820 backup_limit = clean_text_base - 1;
3822 for (scan_p = clean_text_base; scan_p < limit; scan_p++)
3826 static const char *last_r_paren;
3827 const char *ahead_p;
3829 last_r_paren = scan_p;
3831 for (ahead_p = scan_p + 1; isspace (*ahead_p); )
3832 check_source (++ahead_p < limit, limit);
3834 scan_p = ahead_p - 1;
3836 if (isalpha (*ahead_p) || *ahead_p == '{')
3838 const char *last_l_paren;
3839 const int lineno = identify_lineno (ahead_p);
3841 if (setjmp (source_confusion_recovery))
3844 /* We know we have a function definition header. Now skip
3845 leftwards over all of its associated formals lists. */
3849 last_l_paren = careful_find_l_paren (last_r_paren);
3850 for (last_r_paren = last_l_paren-1; isspace (*last_r_paren); )
3851 check_source (--last_r_paren >= backup_limit, backup_limit);
3853 while (*last_r_paren == ')');
3855 if (is_id_char (*last_r_paren))
3857 const char *id_limit = last_r_paren + 1;
3858 const char *id_start;
3860 const def_dec_info *dd_p;
3862 for (id_start = id_limit-1; is_id_char (*id_start); )
3863 check_source (--id_start >= backup_limit, backup_limit);
3865 backup_limit = id_start;
3866 if ((id_length = (size_t) (id_limit - id_start)) == 0)
3870 char *func_name = (char *) alloca (id_length + 1);
3871 static const char * const stmt_keywords[]
3872 = { "if", "while", "for", "switch", "return", 0 };
3873 const char * const *stmt_keyword;
3875 strncpy (func_name, id_start, id_length);
3876 func_name[id_length] = '\0';
3878 /* We must check here to see if we are actually looking at
3879 a statement rather than an actual function call. */
3881 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
3882 if (!strcmp (func_name, *stmt_keyword))
3886 fprintf (stderr, "%s: found definition of `%s' at %s(%d)\n",
3889 shortpath (NULL, file_p->hash_entry->symbol),
3890 identify_lineno (id_start));
3892 /* We really should check for a match of the function name
3893 here also, but why bother. */
3895 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3896 if (dd_p->is_func_def && dd_p->line == lineno)
3899 /* If we make it here, then we did not know about this
3900 function definition. */
3902 fprintf (stderr, "%s: %d: warning: `%s' was #if 0\n",
3903 shortpath (NULL, file_p->hash_entry->symbol),
3904 identify_lineno (id_start), func_name);
3905 fprintf (stderr, "%s: function definition not converted\n",
3915 /* Do all editing operations for a single source file (either a "base" file
3916 or an "include" file). To do this we read the file into memory, keep a
3917 virgin copy there, make another cleaned in-core copy of the original file
3918 (i.e. one in which all of the comments and preprocessor directives have
3919 been replaced with whitespace), then use these two in-core copies of the
3920 file to make a new edited in-core copy of the file. Finally, rename the
3921 original file (as a way of saving it), and then write the edited version
3922 of the file from core to a disk file of the same name as the original.
3924 Note that the trick of making a copy of the original sans comments &
3925 preprocessor directives make the editing a whole lot easier. */
3929 const hash_table_entry *hp;
3931 struct stat stat_buf;
3932 const file_info *file_p = hp->fip;
3933 char *new_orig_text_base;
3934 char *new_orig_text_limit;
3935 char *new_clean_text_base;
3936 char *new_clean_text_limit;
3939 int first_definition_in_file;
3941 /* If we are not supposed to be converting this file, or if there is
3942 nothing in there which needs converting, just skip this file. */
3944 if (!needs_to_be_converted (file_p))
3947 convert_filename = file_p->hash_entry->symbol;
3949 /* Convert a file if it is in a directory where we want conversion
3950 and the file is not excluded. */
3952 if (!directory_specified_p (convert_filename)
3953 || file_excluded_p (convert_filename))
3957 /* Don't even mention "system" include files unless we are
3958 protoizing. If we are protoizing, we mention these as a
3959 gentile way of prodding the user to convert his "system"
3960 include files to prototype format. */
3961 && !in_system_include_dir (convert_filename)
3962 #endif /* defined (UNPROTOIZE) */
3964 fprintf (stderr, "%s: file `%s' not converted\n",
3965 pname, shortpath (NULL, convert_filename));
3969 /* Let the user know what we are up to. */
3972 fprintf (stderr, "%s: would convert file `%s'\n",
3973 pname, shortpath (NULL, convert_filename));
3975 fprintf (stderr, "%s: converting file `%s'\n",
3976 pname, shortpath (NULL, convert_filename));
3979 /* Find out the size (in bytes) of the original file. */
3981 /* The cast avoids an erroneous warning on AIX. */
3982 if (my_stat ((char *)convert_filename, &stat_buf) == -1)
3984 fprintf (stderr, "%s: error: can't get status for file `%s': %s\n",
3985 pname, shortpath (NULL, convert_filename), sys_errlist[errno]);
3988 orig_size = stat_buf.st_size;
3990 /* Allocate a buffer to hold the original text. */
3992 orig_text_base = new_orig_text_base = (char *) xmalloc (orig_size + 2);
3993 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
3995 /* Allocate a buffer to hold the cleaned-up version of the original text. */
3997 clean_text_base = new_clean_text_base = (char *) xmalloc (orig_size + 2);
3998 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
3999 clean_read_ptr = clean_text_base - 1;
4001 /* Allocate a buffer that will hopefully be large enough to hold the entire
4002 converted output text. As an initial guess for the maximum size of the
4003 output buffer, use 125% of the size of the original + some extra. This
4004 buffer can be expanded later as needed. */
4006 repl_size = orig_size + (orig_size >> 2) + 4096;
4007 repl_text_base = (char *) xmalloc (repl_size + 2);
4008 repl_text_limit = repl_text_base + repl_size - 1;
4009 repl_write_ptr = repl_text_base - 1;
4014 /* Open the file to be converted in READ ONLY mode. */
4016 if ((input_file = my_open (convert_filename, O_RDONLY, 0444)) == -1)
4018 fprintf (stderr, "%s: error: can't open file `%s' for reading: %s\n",
4019 pname, shortpath (NULL, convert_filename),
4020 sys_errlist[errno]);
4024 /* Read the entire original source text file into the original text buffer
4025 in one swell fwoop. Then figure out where the end of the text is and
4026 make sure that it ends with a newline followed by a null. */
4028 if (read (input_file, new_orig_text_base, orig_size) != orig_size)
4031 fprintf (stderr, "\n%s: error: while reading input file `%s': %s\n",
4032 pname, shortpath (NULL, convert_filename),
4033 sys_errlist[errno]);
4040 if (orig_size == 0 || orig_text_limit[-1] != '\n')
4042 *new_orig_text_limit++ = '\n';
4046 /* Create the cleaned up copy of the original text. */
4048 memcpy (new_clean_text_base, orig_text_base,
4049 (size_t) (orig_text_limit - orig_text_base));
4050 do_cleaning (new_clean_text_base, new_clean_text_limit);
4055 size_t clean_size = orig_text_limit - orig_text_base;
4056 char *const clean_filename = (char *) alloca (strlen (convert_filename) + 6 + 1);
4058 /* Open (and create) the clean file. */
4060 strcpy (clean_filename, convert_filename);
4061 strcat (clean_filename, ".clean");
4062 if ((clean_file = creat (clean_filename, 0666)) == -1)
4064 fprintf (stderr, "%s: error: can't create/open clean file `%s': %s\n",
4065 pname, shortpath (NULL, clean_filename),
4066 sys_errlist[errno]);
4070 /* Write the clean file. */
4072 if (write (clean_file, new_clean_text_base, clean_size) != clean_size)
4073 fprintf (stderr, "%s: error: while writing file `%s': %s\n",
4074 pname, shortpath (NULL, clean_filename), sys_errlist[errno]);
4080 /* Do a simplified scan of the input looking for things that were not
4081 mentioned in the aux info files because of the fact that they were
4082 in a region of the source which was preprocessed-out (via #if or
4085 scan_for_missed_items (file_p);
4087 /* Setup to do line-oriented forward seeking in the clean text buffer. */
4089 last_known_line_number = 1;
4090 last_known_line_start = clean_text_base;
4092 /* Now get down to business and make all of the necessary edits. */
4095 const def_dec_info *def_dec_p;
4097 first_definition_in_file = 1;
4098 def_dec_p = file_p->defs_decs;
4099 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
4101 const char *clean_text_p = seek_to_line (def_dec_p->line);
4103 /* clean_text_p now points to the first character of the line which
4104 contains the `terminator' for the declaration or definition that
4105 we are about to process. */
4109 if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
4111 add_global_decls (def_dec_p->file, clean_text_p);
4112 first_definition_in_file = 0;
4115 /* Don't edit this item if it is already in prototype format or if it
4116 is a function declaration and we have found no corresponding
4119 if (def_dec_p->prototyped
4120 || (!def_dec_p->is_func_def && !def_dec_p->definition))
4123 #endif /* !defined (UNPROTOIZE) */
4125 if (def_dec_p->is_func_def)
4126 edit_fn_definition (def_dec_p, clean_text_p);
4129 if (def_dec_p->is_implicit)
4130 add_local_decl (def_dec_p, clean_text_p);
4132 #endif /* !defined (UNPROTOIZE) */
4133 edit_fn_declaration (def_dec_p, clean_text_p);
4137 /* Finalize things. Output the last trailing part of the original text. */
4139 output_up_to (clean_text_limit - 1);
4141 /* If this is just a test run, stop now and just deallocate the buffers. */
4145 free (new_orig_text_base);
4146 free (new_clean_text_base);
4147 free (repl_text_base);
4151 /* Change the name of the original input file. This is just a quick way of
4152 saving the original file. */
4156 char *new_filename =
4157 (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
4159 strcpy (new_filename, convert_filename);
4160 strcat (new_filename, save_suffix);
4161 if (my_link (convert_filename, new_filename) == -1)
4163 if (errno == EEXIST)
4166 fprintf (stderr, "%s: warning: file `%s' already saved in `%s'\n",
4168 shortpath (NULL, convert_filename),
4169 shortpath (NULL, new_filename));
4173 fprintf (stderr, "%s: error: can't link file `%s' to `%s': %s\n",
4175 shortpath (NULL, convert_filename),
4176 shortpath (NULL, new_filename),
4177 sys_errlist[errno]);
4183 if (my_unlink (convert_filename) == -1)
4185 fprintf (stderr, "%s: error: can't delete file `%s': %s\n",
4186 pname, shortpath (NULL, convert_filename), sys_errlist[errno]);
4193 /* Open (and create) the output file. */
4195 if ((output_file = creat (convert_filename, 0666)) == -1)
4197 fprintf (stderr, "%s: error: can't create/open output file `%s': %s\n",
4198 pname, shortpath (NULL, convert_filename),
4199 sys_errlist[errno]);
4203 /* Write the output file. */
4206 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
4208 if (write (output_file, repl_text_base, out_size) != out_size)
4209 fprintf (stderr, "%s: error: while writing file `%s': %s\n",
4210 pname, shortpath (NULL, convert_filename),
4211 sys_errlist[errno]);
4214 close (output_file);
4217 /* Deallocate the conversion buffers. */
4219 free (new_orig_text_base);
4220 free (new_clean_text_base);
4221 free (repl_text_base);
4223 /* Change the mode of the output file to match the original file. */
4225 /* The cast avoids an erroneous warning on AIX. */
4226 if (my_chmod ((char *)convert_filename, stat_buf.st_mode) == -1)
4227 fprintf (stderr, "%s: error: can't change mode of file `%s': %s\n",
4228 pname, shortpath (NULL, convert_filename), sys_errlist[errno]);
4230 /* Note: We would try to change the owner and group of the output file
4231 to match those of the input file here, except that may not be a good
4232 thing to do because it might be misleading. Also, it might not even
4233 be possible to do that (on BSD systems with quotas for instance). */
4236 /* Do all of the individual steps needed to do the protoization (or
4237 unprotoization) of the files referenced in the aux_info files given
4238 in the command line. */
4243 const char * const *base_pp;
4244 const char * const * const end_pps
4245 = &base_source_filenames[n_base_source_files];
4249 #endif /* !defined (UNPROTOIZE) */
4251 /* One-by-one, check (and create if necessary), open, and read all of the
4252 stuff in each aux_info file. After reading each aux_info file, the
4253 aux_info_file just read will be automatically deleted unless the
4254 keep_flag is set. */
4256 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
4257 process_aux_info_file (*base_pp, keep_flag, 0);
4261 /* Also open and read the special SYSCALLS.c aux_info file which gives us
4262 the prototypes for all of the standard system-supplied functions. */
4264 if (nondefault_syscalls_dir)
4266 syscalls_absolute_filename
4267 = (char *) xmalloc (strlen (nondefault_syscalls_dir)
4268 + strlen (syscalls_filename) + 2);
4269 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
4273 syscalls_absolute_filename
4274 = (char *) xmalloc (strlen (default_syscalls_dir)
4275 + strlen (syscalls_filename) + 2);
4276 strcpy (syscalls_absolute_filename, default_syscalls_dir);
4279 syscalls_len = strlen (syscalls_absolute_filename);
4280 if (*(syscalls_absolute_filename + syscalls_len - 1) != '/')
4282 *(syscalls_absolute_filename + syscalls_len++) = '/';
4283 *(syscalls_absolute_filename + syscalls_len) = '\0';
4285 strcat (syscalls_absolute_filename, syscalls_filename);
4287 /* Call process_aux_info_file in such a way that it does not try to
4288 delete the SYSCALLS aux_info file. */
4290 process_aux_info_file (syscalls_absolute_filename, 1, 1);
4292 #endif /* !defined (UNPROTOIZE) */
4294 /* When we first read in all of the information from the aux_info files
4295 we saved in it decending line number order, because that was likely to
4296 be faster. Now however, we want the chains of def & dec records to
4297 appear in ascending line number order as we get further away from the
4298 file_info record that they hang from. The following line causes all of
4299 these lists to be rearranged into ascending line number order. */
4301 visit_each_hash_node (filename_primary, reverse_def_dec_list);
4305 /* Now do the "real" work. The following line causes each declaration record
4306 to be "visited". For each of these nodes, an attempt is made to match
4307 up the function declaration with a corresponding function definition,
4308 which should have a full prototype-format formals list with it. Once
4309 these match-ups are made, the conversion of the function declarations
4310 to prototype format can be made. */
4312 visit_each_hash_node (function_name_primary, connect_defs_and_decs);
4314 #endif /* !defined (UNPROTOIZE) */
4316 /* Now convert each file that can be converted (and needs to be). */
4318 visit_each_hash_node (filename_primary, edit_file);
4322 /* If we are working in cplusplus mode, try to rename all .c files to .C
4323 files. Don't panic if some of the renames don't work. */
4325 if (cplusplus_flag && !nochange_flag)
4326 visit_each_hash_node (filename_primary, rename_c_file);
4328 #endif /* !defined (UNPROTOIZE) */
4331 static struct option longopts[] =
4333 {"version", 0, 0, 'V'},
4334 {"file_name", 0, 0, 'p'},
4335 {"quiet", 0, 0, 'q'},
4336 {"silent", 0, 0, 'q'},
4337 {"force", 0, 0, 'f'},
4338 {"keep", 0, 0, 'k'},
4339 {"nosave", 0, 0, 'N'},
4340 {"nochange", 0, 0, 'n'},
4341 {"compiler-options", 1, 0, 'c'},
4342 {"exclude", 1, 0, 'x'},
4343 {"directory", 1, 0, 'd'},
4345 {"indent", 1, 0, 'i'},
4347 {"local", 0, 0, 'l'},
4348 {"global", 0, 0, 'g'},
4350 {"syscalls-dir", 1, 0, 'B'},
4364 pname = strrchr (argv[0], '/');
4365 pname = pname ? pname+1 : argv[0];
4367 /* Read the working directory, avoiding arbitrary limit. */
4368 size = GUESSPATHLEN;
4373 cwd_buffer = (char *) xmalloc (size);
4374 value = getcwd (cwd_buffer, size);
4375 if (value != 0 || errno != ERANGE)
4381 /* By default, convert the files in the current directory. */
4382 directory_list = string_list_cons (cwd_buffer, NULL);
4384 while ((c = getopt_long (argc, argv,
4388 "B:c:Cd:gklnNp:qVx:",
4390 longopts, &longind)) != EOF)
4392 if (c == 0) /* Long option. */
4393 c = longopts[longind].val;
4397 compiler_file_name = optarg;
4401 = string_list_cons (abspath (NULL, optarg), directory_list);
4404 exclude_list = string_list_cons (optarg, exclude_list);
4429 munge_compile_params (optarg);
4433 indent_string = optarg;
4435 #else /* !defined (UNPROTOIZE) */
4446 nondefault_syscalls_dir = optarg;
4448 #endif /* !defined (UNPROTOIZE) */
4454 n_base_source_files = argc - optind;
4456 /* Now actually make a list of the base source filenames. */
4458 base_source_filenames =
4459 (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *));
4460 n_base_source_files = 0;
4461 for (; optind < argc; optind++)
4463 const char *path = abspath (NULL, argv[optind]);
4464 int len = strlen (path);
4466 if (path[len-1] == 'c' && path[len-2] == '.')
4467 base_source_filenames[n_base_source_files++] = path;
4470 fprintf (stderr, "%s: input file names must have .c suffixes: %s\n",
4471 pname, shortpath (NULL, path));
4477 /* We are only interested in the very first identifier token in the
4478 definition of `va_list', so if there is more junk after that first
4479 identifier token, delete it from the `varargs_style_indicator'. */
4483 for (cp = varargs_style_indicator; isalnum (*cp) || *cp == '_'; cp++)
4486 varargs_style_indicator = savestring (varargs_style_indicator,
4487 cp - varargs_style_indicator);
4489 #endif /* !defined (UNPROTOIZE) */
4496 fprintf (stderr, "%s: %s\n", pname, version_string);