]> gcc.gnu.org Git - gcc.git/blob - gcc/protoize.c
Edit to add a missing $(exeext) for CCCP.
[gcc.git] / gcc / protoize.c
1 /* Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com).
2 Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Any reasonable C++ compiler should have all of the same features
22 as __STDC__ plus more, so make sure that __STDC__ is defined if
23 __cplusplus is defined. */
24
25 #if defined(__cplusplus) && !defined(__STDC__)
26 #define __STDC__ 1
27 #endif /* defined(__cplusplus) && !defined(__STDC__) */
28
29 #if defined(__GNUC__) || defined (__GNUG__)
30 #define VOLATILE volatile
31 #else
32 #define VOLATILE
33 #endif
34
35 #ifndef __STDC__
36 #define const
37 #define volatile
38 #endif
39
40 #include "config.h"
41
42 #if 0
43 /* Users are not supposed to use _POSIX_SOURCE to say the
44 system is a POSIX system. That is not what _POSIX_SOURCE means! -- rms */
45 /* If the user asked for POSIX via _POSIX_SOURCE, turn on POSIX code. */
46 #if defined(_POSIX_SOURCE) && !defined(POSIX)
47 #define POSIX
48 #endif
49 #endif /* 0 */
50
51 #ifdef POSIX /* We should be able to define _POSIX_SOURCE unconditionally,
52 but some systems respond in buggy ways to it,
53 including SunOS 4.1.1. Which we don't classify as POSIX. */
54 /* In case this is a POSIX system with an ANSI C compiler,
55 ask for definition of all POSIX facilities. */
56 #undef _POSIX_SOURCE
57 #define _POSIX_SOURCE
58 #endif
59
60 #include <varargs.h>
61 /* On some systems stdio.h includes stdarg.h;
62 we must bring in varargs.h first. */
63 #include <stdio.h>
64 #include <ctype.h>
65 #include <errno.h>
66 #include <sys/types.h>
67 #include <sys/stat.h>
68 #ifndef _WIN32
69 #if defined(POSIX) || defined(CONCURRENT)
70 #include <dirent.h>
71 #else
72 #include <sys/dir.h>
73 #endif
74 #endif
75 #include <setjmp.h>
76
77 /* Include getopt.h for the sake of getopt_long.
78 We don't need the declaration of getopt, and it could conflict
79 with something from a system header file, so effectively nullify that. */
80 #define getopt getopt_loser
81 #include "getopt.h"
82 #undef getopt
83
84 #ifndef errno
85 extern int errno;
86 #endif
87
88 #ifndef HAVE_STRERROR
89 extern int sys_nerr;
90 #if defined(bsd4_4)
91 extern const char *const sys_errlist[];
92 #else
93 extern char *sys_errlist[];
94 #endif
95 #else
96 extern char *strerror();
97 #endif
98
99 extern char *version_string;
100
101 /* Systems which are compatible only with POSIX 1003.1-1988 (but *not*
102 with POSIX 1003.1-1990), e.g. Ultrix 4.2, might not have
103 const qualifiers in the prototypes in the system include files.
104 Unfortunately, this can lead to GCC issuing lots of warnings for
105 calls to the following functions. To eliminate these warnings we
106 provide the following #defines. */
107
108 #define my_access(file,flag) access((char *)file, flag)
109 #define my_stat(file,pkt) stat((char *)file, pkt)
110 #define my_execvp(prog,argv) execvp((char *)prog, (char **)argv)
111 #define my_link(file1, file2) link((char *)file1, (char *)file2)
112 #define my_unlink(file) unlink((char *)file)
113 #define my_open(file, mode, flag) open((char *)file, mode, flag)
114 #define my_chmod(file, mode) chmod((char *)file, mode)
115
116 extern char *getpwd ();
117
118 /* Aliases for pointers to void.
119 These were made to facilitate compilation with old brain-dead DEC C
120 compilers which didn't properly grok `void*' types. */
121
122 #ifdef __STDC__
123 typedef void * pointer_type;
124 typedef const void * const_pointer_type;
125 #else
126 typedef char * pointer_type;
127 typedef char * const_pointer_type;
128 #endif
129
130 #if defined(POSIX)
131
132 #include <stdlib.h>
133 #include <unistd.h>
134 #include <signal.h>
135 #include <fcntl.h>
136 #include <sys/wait.h>
137
138 #else /* !defined(POSIX) */
139
140 #define R_OK 4 /* Test for Read permission */
141 #define W_OK 2 /* Test for Write permission */
142 #define X_OK 1 /* Test for eXecute permission */
143 #define F_OK 0 /* Test for existence of File */
144
145 #ifndef O_RDONLY
146 #define O_RDONLY 0
147 #endif
148
149 #ifndef O_WRONLY
150 #define O_WRONLY 1
151 #endif
152
153 #ifndef WIFSIGNALED
154 #define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
155 #endif
156 #ifndef WTERMSIG
157 #define WTERMSIG(S) ((S) & 0x7f)
158 #endif
159 #ifndef WIFEXITED
160 #define WIFEXITED(S) (((S) & 0xff) == 0)
161 #endif
162 #ifndef WEXITSTATUS
163 #define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
164 #endif
165
166 /* Declaring stat or __flsbuf with a prototype
167 causes conflicts with system headers on some systems. */
168
169 #ifndef abort
170 typedef void voidfn ();
171 extern VOLATILE voidfn abort;
172 #endif
173 #ifndef _WIN32
174 extern int kill ();
175 #endif
176 extern int creat ();
177 #if 0 /* These conflict with stdio.h on some systems. */
178 extern int fprintf (FILE *, const char *, ...);
179 extern int printf (const char *, ...);
180 extern int open (const char *, int, ...);
181 #endif /* 0 */
182 extern void exit ();
183 extern void free ();
184 extern int read ();
185 extern int write ();
186 extern int close ();
187 extern int fflush ();
188 extern int atoi ();
189 extern int puts ();
190 extern int fputs ();
191 extern int fputc ();
192 extern int link ();
193 extern int unlink ();
194 extern int access ();
195 extern int execvp ();
196
197 #if 0 /* size_t from sys/types.h may fail to match GCC.
198 If so, we would get a warning from this. */
199 extern size_t strlen ()
200 #endif
201
202 /* Fork is not declared because the declaration caused a conflict
203 on the HPPA. */
204 #if !(defined (USG) || defined (VMS))
205 #define fork vfork
206 #endif /* (defined (USG) || defined (VMS)) */
207
208 #endif /* !defined (POSIX) */
209
210 extern char *rindex ();
211
212 /* Look for these where the `const' qualifier is intentionally cast aside. */
213
214 #define NONCONST
215
216 /* Define a STRINGIFY macro that's right for ANSI or traditional C. */
217
218 #ifdef __STDC__
219 #define STRINGIFY(STRING) #STRING
220 #else
221 #define STRINGIFY(STRING) "STRING"
222 #endif
223
224 /* Define a default place to find the SYSCALLS.X file. */
225
226 #ifndef STD_PROTO_DIR
227 #define STD_PROTO_DIR "/usr/local/lib"
228 #endif /* !defined (STD_PROTO_DIR) */
229
230 /* Suffix of aux_info files. */
231
232 static const char * const aux_info_suffix = ".X";
233
234 /* String to attach to filenames for saved versions of original files. */
235
236 static const char * const save_suffix = ".save";
237
238 #ifndef UNPROTOIZE
239
240 /* File name of the file which contains descriptions of standard system
241 routines. Note that we never actually do anything with this file per se,
242 but we do read in its corresponding aux_info file. */
243
244 static const char syscalls_filename[] = "SYSCALLS.c";
245
246 /* Default place to find the above file. */
247
248 static const char * const default_syscalls_dir = STD_PROTO_DIR;
249
250 /* Variable to hold the complete absolutized filename of the SYSCALLS.c.X
251 file. */
252
253 static char * syscalls_absolute_filename;
254
255 #endif /* !defined (UNPROTOIZE) */
256
257 /* Type of the structure that holds information about macro unexpansions. */
258
259 struct unexpansion_struct {
260 const char *expanded;
261 const char *contracted;
262 };
263 typedef struct unexpansion_struct unexpansion;
264
265 /* A table of conversions that may need to be made for some (stupid) older
266 operating systems where these types are preprocessor macros rather than
267 typedefs (as they really ought to be).
268
269 WARNING: The contracted forms must be as small (or smaller) as the
270 expanded forms, or else havoc will ensue. */
271
272 static const unexpansion unexpansions[] = {
273 { "struct _iobuf", "FILE" },
274 { 0, 0 }
275 };
276
277 /* The number of "primary" slots in the hash tables for filenames and for
278 function names. This can be as big or as small as you like, except that
279 it must be a power of two. */
280
281 #define HASH_TABLE_SIZE (1 << 9)
282
283 /* Bit mask to use when computing hash values. */
284
285 static const int hash_mask = (HASH_TABLE_SIZE - 1);
286
287 /* Make a table of default system include directories
288 just as it is done in cccp.c. */
289
290 #ifndef STANDARD_INCLUDE_DIR
291 #define STANDARD_INCLUDE_DIR "/usr/include"
292 #endif
293
294 #ifndef LOCAL_INCLUDE_DIR
295 #define LOCAL_INCLUDE_DIR "/usr/local/include"
296 #endif
297
298 struct default_include { const char *fname; int x1, x2; } include_defaults[]
299 #ifdef INCLUDE_DEFAULTS
300 = INCLUDE_DEFAULTS;
301 #else
302 = {
303 /* Pick up GNU C++ specific include files. */
304 { GPLUSPLUS_INCLUDE_DIR, 1, 1 },
305 #ifdef CROSS_COMPILE
306 /* This is the dir for fixincludes. Put it just before
307 the files that we fix. */
308 { GCC_INCLUDE_DIR, 0, 0 },
309 /* For cross-compilation, this dir name is generated
310 automatically in Makefile.in. */
311 { CROSS_INCLUDE_DIR, 0, 0 },
312 /* This is another place that the target system's headers might be. */
313 { TOOL_INCLUDE_DIR, 0, 0 },
314 #else /* not CROSS_COMPILE */
315 /* This should be /use/local/include and should come before
316 the fixincludes-fixed header files. */
317 { LOCAL_INCLUDE_DIR, 0, 1 },
318 /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
319 Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */
320 { TOOL_INCLUDE_DIR, 0, 0 },
321 /* This is the dir for fixincludes. Put it just before
322 the files that we fix. */
323 { GCC_INCLUDE_DIR, 0, 0 },
324 /* Some systems have an extra dir of include files. */
325 #ifdef SYSTEM_INCLUDE_DIR
326 { SYSTEM_INCLUDE_DIR, 0, 0 },
327 #endif
328 { STANDARD_INCLUDE_DIR, 0, 0},
329 #endif /* not CROSS_COMPILE */
330 { 0, 0, 0}
331 };
332 #endif /* no INCLUDE_DEFAULTS */
333
334 /* Datatype for lists of directories or filenames. */
335 struct string_list
336 {
337 char *name;
338 struct string_list *next;
339 };
340
341 /* List of directories in which files should be converted. */
342
343 struct string_list *directory_list;
344
345 /* List of file names which should not be converted.
346 A file is excluded if the end of its name, following a /,
347 matches one of the names in this list. */
348
349 struct string_list *exclude_list;
350
351 /* The name of the other style of variable-number-of-parameters functions
352 (i.e. the style that we want to leave unconverted because we don't yet
353 know how to convert them to this style. This string is used in warning
354 messages. */
355
356 /* Also define here the string that we can search for in the parameter lists
357 taken from the .X files which will unambiguously indicate that we have
358 found a varargs style function. */
359
360 #ifdef UNPROTOIZE
361 static const char * const other_var_style = "stdarg";
362 #else /* !defined (UNPROTOIZE) */
363 static const char * const other_var_style = "varargs";
364 /* Note that this is a string containing the expansion of va_alist.
365 But in `main' we discard all but the first token. */
366 static const char *varargs_style_indicator = STRINGIFY (va_alist);
367 #endif /* !defined (UNPROTOIZE) */
368
369 /* The following two types are used to create hash tables. In this program,
370 there are two hash tables which are used to store and quickly lookup two
371 different classes of strings. The first type of strings stored in the
372 first hash table are absolute filenames of files which protoize needs to
373 know about. The second type of strings (stored in the second hash table)
374 are function names. It is this second class of strings which really
375 inspired the use of the hash tables, because there may be a lot of them. */
376
377 typedef struct hash_table_entry_struct hash_table_entry;
378
379 /* Do some typedefs so that we don't have to write "struct" so often. */
380
381 typedef struct def_dec_info_struct def_dec_info;
382 typedef struct file_info_struct file_info;
383 typedef struct f_list_chain_item_struct f_list_chain_item;
384
385 /* In the struct below, note that the "_info" field has two different uses
386 depending on the type of hash table we are in (i.e. either the filenames
387 hash table or the function names hash table). In the filenames hash table
388 the info fields of the entries point to the file_info struct which is
389 associated with each filename (1 per filename). In the function names
390 hash table, the info field points to the head of a singly linked list of
391 def_dec_info entries which are all defs or decs of the function whose
392 name is pointed to by the "symbol" field. Keeping all of the defs/decs
393 for a given function name on a special list specifically for that function
394 name makes it quick and easy to find out all of the important information
395 about a given (named) function. */
396
397 struct hash_table_entry_struct {
398 hash_table_entry * hash_next; /* -> to secondary entries */
399 const char * symbol; /* -> to the hashed string */
400 union {
401 const def_dec_info * _ddip;
402 file_info * _fip;
403 } _info;
404 };
405 #define ddip _info._ddip
406 #define fip _info._fip
407
408 /* Define a type specifically for our two hash tables. */
409
410 typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
411
412 /* The following struct holds all of the important information about any
413 single filename (e.g. file) which we need to know about. */
414
415 struct file_info_struct {
416 const hash_table_entry * hash_entry; /* -> to associated hash entry */
417 const def_dec_info * defs_decs; /* -> to chain of defs/decs */
418 time_t mtime; /* Time of last modification. */
419 };
420
421 /* Due to the possibility that functions may return pointers to functions,
422 (which may themselves have their own parameter lists) and due to the
423 fact that returned pointers-to-functions may be of type "pointer-to-
424 function-returning-pointer-to-function" (ad nauseum) we have to keep
425 an entire chain of ANSI style formal parameter lists for each function.
426
427 Normally, for any given function, there will only be one formals list
428 on the chain, but you never know.
429
430 Note that the head of each chain of formals lists is pointed to by the
431 `f_list_chain' field of the corresponding def_dec_info record.
432
433 For any given chain, the item at the head of the chain is the *leftmost*
434 parameter list seen in the actual C language function declaration. If
435 there are other members of the chain, then these are linked in left-to-right
436 order from the head of the chain. */
437
438 struct f_list_chain_item_struct {
439 const f_list_chain_item * chain_next; /* -> to next item on chain */
440 const char * formals_list; /* -> to formals list string */
441 };
442
443 /* The following struct holds all of the important information about any
444 single function definition or declaration which we need to know about.
445 Note that for unprotoize we don't need to know very much because we
446 never even create records for stuff that we don't intend to convert
447 (like for instance defs and decs which are already in old K&R format
448 and "implicit" function declarations). */
449
450 struct def_dec_info_struct {
451 const def_dec_info * next_in_file; /* -> to rest of chain for file */
452 file_info * file; /* -> file_info for containing file */
453 int line; /* source line number of def/dec */
454 const char * ansi_decl; /* -> left end of ansi decl */
455 hash_table_entry * hash_entry; /* -> hash entry for function name */
456 unsigned int is_func_def; /* = 0 means this is a declaration */
457 const def_dec_info * next_for_func; /* -> to rest of chain for func name */
458 unsigned int f_list_count; /* count of formals lists we expect */
459 char prototyped; /* = 0 means already prototyped */
460 #ifndef UNPROTOIZE
461 const f_list_chain_item * f_list_chain; /* -> chain of formals lists */
462 const def_dec_info * definition; /* -> def/dec containing related def */
463 char is_static; /* = 0 means visibility is "extern" */
464 char is_implicit; /* != 0 for implicit func decl's */
465 char written; /* != 0 means written for implicit */
466 #else /* !defined (UNPROTOIZE) */
467 const char * formal_names; /* -> to list of names of formals */
468 const char * formal_decls; /* -> to string of formal declarations */
469 #endif /* !defined (UNPROTOIZE) */
470 };
471
472 /* Pointer to the tail component of the filename by which this program was
473 invoked. Used everywhere in error and warning messages. */
474
475 static const char *pname;
476
477 /* Error counter. Will be non-zero if we should give up at the next convenient
478 stopping point. */
479
480 static int errors = 0;
481
482 /* Option flags. */
483 /* ??? These comments should say what the flag mean as well as the options
484 that set them. */
485
486 /* File name to use for running gcc. Allows GCC 2 to be named
487 something other than gcc. */
488 static const char *compiler_file_name = "gcc";
489
490 static int version_flag = 0; /* Print our version number. */
491 static int quiet_flag = 0; /* Don't print messages normally. */
492 static int nochange_flag = 0; /* Don't convert, just say what files
493 we would have converted. */
494 static int nosave_flag = 0; /* Don't save the old version. */
495 static int keep_flag = 0; /* Don't delete the .X files. */
496 static const char ** compile_params = 0; /* Option string for gcc. */
497 #ifdef UNPROTOIZE
498 static const char *indent_string = " "; /* Indentation for newly
499 inserted parm decls. */
500 #else /* !defined (UNPROTOIZE) */
501 static int local_flag = 0; /* Insert new local decls (when?). */
502 static int global_flag = 0; /* set by -g option */
503 static int cplusplus_flag = 0; /* Rename converted files to *.C. */
504 static const char* nondefault_syscalls_dir = 0; /* Dir to look for
505 SYSCALLS.c.X in. */
506 #endif /* !defined (UNPROTOIZE) */
507
508 /* An index into the compile_params array where we should insert the source
509 file name when we are ready to exec the C compiler. A zero value indicates
510 that we have not yet called munge_compile_params. */
511
512 static int input_file_name_index = 0;
513
514 /* An index into the compile_params array where we should insert the filename
515 for the aux info file, when we run the C compiler. */
516 static int aux_info_file_name_index = 0;
517
518 /* Count of command line arguments which were "filename" arguments. */
519
520 static int n_base_source_files = 0;
521
522 /* Points to a malloc'ed list of pointers to all of the filenames of base
523 source files which were specified on the command line. */
524
525 static const char **base_source_filenames;
526
527 /* Line number of the line within the current aux_info file that we
528 are currently processing. Used for error messages in case the prototypes
529 info file is corrupted somehow. */
530
531 static int current_aux_info_lineno;
532
533 /* Pointer to the name of the source file currently being converted. */
534
535 static const char *convert_filename;
536
537 /* Pointer to relative root string (taken from aux_info file) which indicates
538 where directory the user was in when he did the compilation step that
539 produced the containing aux_info file. */
540
541 static const char *invocation_filename;
542
543 /* Pointer to the base of the input buffer that holds the original text for the
544 source file currently being converted. */
545
546 static const char *orig_text_base;
547
548 /* Pointer to the byte just beyond the end of the input buffer that holds the
549 original text for the source file currently being converted. */
550
551 static const char *orig_text_limit;
552
553 /* Pointer to the base of the input buffer that holds the cleaned text for the
554 source file currently being converted. */
555
556 static const char *clean_text_base;
557
558 /* Pointer to the byte just beyond the end of the input buffer that holds the
559 cleaned text for the source file currently being converted. */
560
561 static const char *clean_text_limit;
562
563 /* Pointer to the last byte in the cleaned text buffer that we have already
564 (virtually) copied to the output buffer (or decided to ignore). */
565
566 static const char * clean_read_ptr;
567
568 /* Pointer to the base of the output buffer that holds the replacement text
569 for the source file currently being converted. */
570
571 static char *repl_text_base;
572
573 /* Pointer to the byte just beyond the end of the output buffer that holds the
574 replacement text for the source file currently being converted. */
575
576 static char *repl_text_limit;
577
578 /* Pointer to the last byte which has been stored into the output buffer.
579 The next byte to be stored should be stored just past where this points
580 to. */
581
582 static char * repl_write_ptr;
583
584 /* Pointer into the cleaned text buffer for the source file we are currently
585 converting. This points to the first character of the line that we last
586 did a "seek_to_line" to (see below). */
587
588 static const char *last_known_line_start;
589
590 /* Number of the line (in the cleaned text buffer) that we last did a
591 "seek_to_line" to. Will be one if we just read a new source file
592 into the cleaned text buffer. */
593
594 static int last_known_line_number;
595
596 /* The filenames hash table. */
597
598 static hash_table filename_primary;
599
600 /* The function names hash table. */
601
602 static hash_table function_name_primary;
603
604 /* The place to keep the recovery address which is used only in cases where
605 we get hopelessly confused by something in the cleaned original text. */
606
607 static jmp_buf source_confusion_recovery;
608
609 /* A pointer to the current directory filename (used by abspath). */
610
611 static char *cwd_buffer;
612
613 /* A place to save the read pointer until we are sure that an individual
614 attempt at editing will succeed. */
615
616 static const char * saved_clean_read_ptr;
617
618 /* A place to save the write pointer until we are sure that an individual
619 attempt at editing will succeed. */
620
621 static char * saved_repl_write_ptr;
622
623 /* Forward declaration. */
624
625 static const char *shortpath ();
626 \f
627 char *
628 my_strerror(e)
629 int e;
630 {
631
632 #ifdef HAVE_STRERROR
633 return strerror(e);
634
635 #else
636
637 static char buffer[30];
638 if (!e)
639 return "";
640
641 if (e > 0 && e < sys_nerr)
642 return sys_errlist[e];
643
644 sprintf (buffer, "Unknown error %d", e);
645 return buffer;
646 #endif
647 }
648 \f
649 /* Allocate some space, but check that the allocation was successful. */
650 /* alloca.c uses this, so don't make it static. */
651
652 pointer_type
653 xmalloc (byte_count)
654 size_t byte_count;
655 {
656 pointer_type rv;
657
658 rv = (pointer_type) malloc (byte_count);
659 if (rv == NULL)
660 {
661 fprintf (stderr, "\n%s: virtual memory exceeded\n", pname);
662 exit (1);
663 return 0; /* avoid warnings */
664 }
665 else
666 return rv;
667 }
668
669 /* Reallocate some space, but check that the reallocation was successful. */
670
671 pointer_type
672 xrealloc (old_space, byte_count)
673 pointer_type old_space;
674 size_t byte_count;
675 {
676 pointer_type rv;
677
678 rv = (pointer_type) realloc (old_space, byte_count);
679 if (rv == NULL)
680 {
681 fprintf (stderr, "\n%s: virtual memory exceeded\n", pname);
682 exit (1);
683 return 0; /* avoid warnings */
684 }
685 else
686 return rv;
687 }
688
689 /* Deallocate the area pointed to by an arbitrary pointer, but first, strip
690 the `const' qualifier from it and also make sure that the pointer value
691 is non-null. */
692
693 void
694 xfree (p)
695 const_pointer_type p;
696 {
697 if (p)
698 free ((NONCONST pointer_type) p);
699 }
700
701 /* Make a copy of a string INPUT with size SIZE. */
702
703 static char *
704 savestring (input, size)
705 const char *input;
706 unsigned int size;
707 {
708 char *output = (char *) xmalloc (size + 1);
709 strcpy (output, input);
710 return output;
711 }
712
713 /* Make a copy of the concatenation of INPUT1 and INPUT2. */
714
715 static char *
716 savestring2 (input1, size1, input2, size2)
717 const char *input1;
718 unsigned int size1;
719 const char *input2;
720 unsigned int size2;
721 {
722 char *output = (char *) xmalloc (size1 + size2 + 1);
723 strcpy (output, input1);
724 strcpy (&output[size1], input2);
725 return output;
726 }
727
728 /* More 'friendly' abort that prints the line and file.
729 config.h can #define abort fancy_abort if you like that sort of thing. */
730
731 void
732 fancy_abort ()
733 {
734 fprintf (stderr, "%s: internal abort\n", pname);
735 exit (1);
736 }
737 \f
738 /* Make a duplicate of the first N bytes of a given string in a newly
739 allocated area. */
740
741 static char *
742 dupnstr (s, n)
743 const char *s;
744 size_t n;
745 {
746 char *ret_val = (char *) xmalloc (n + 1);
747
748 strncpy (ret_val, s, n);
749 ret_val[n] = '\0';
750 return ret_val;
751 }
752
753 /* Return a pointer to the first occurrence of s2 within s1 or NULL if s2
754 does not occur within s1. Assume neither s1 nor s2 are null pointers. */
755
756 static const char *
757 substr (s1, s2)
758 const char *s1;
759 const char *const s2;
760 {
761 for (; *s1 ; s1++)
762 {
763 const char *p1;
764 const char *p2;
765 int c;
766
767 for (p1 = s1, p2 = s2; c = *p2; p1++, p2++)
768 if (*p1 != c)
769 goto outer;
770 return s1;
771 outer:
772 ;
773 }
774 return 0;
775 }
776 \f
777 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
778 retrying if necessary. Return the actual number of bytes read. */
779
780 static int
781 safe_read (desc, ptr, len)
782 int desc;
783 char *ptr;
784 int len;
785 {
786 int left = len;
787 while (left > 0) {
788 int nchars = read (desc, ptr, left);
789 if (nchars < 0)
790 {
791 #ifdef EINTR
792 if (errno == EINTR)
793 continue;
794 #endif
795 return nchars;
796 }
797 if (nchars == 0)
798 break;
799 ptr += nchars;
800 left -= nchars;
801 }
802 return len - left;
803 }
804
805 /* Write LEN bytes at PTR to descriptor DESC,
806 retrying if necessary, and treating any real error as fatal. */
807
808 static void
809 safe_write (desc, ptr, len, out_fname)
810 int desc;
811 char *ptr;
812 int len;
813 char *out_fname;
814 {
815 while (len > 0) {
816 int written = write (desc, ptr, len);
817 if (written < 0)
818 {
819 #ifdef EINTR
820 if (errno == EINTR)
821 continue;
822 #endif
823 fprintf (stderr, "%s: error writing file `%s': %s\n",
824 pname, shortpath (NULL, out_fname), my_strerror(errno));
825 return;
826 }
827 ptr += written;
828 len -= written;
829 }
830 }
831 \f
832 /* Get setup to recover in case the edit we are about to do goes awry. */
833
834 void
835 save_pointers ()
836 {
837 saved_clean_read_ptr = clean_read_ptr;
838 saved_repl_write_ptr = repl_write_ptr;
839 }
840
841 /* Call this routine to recover our previous state whenever something looks
842 too confusing in the source code we are trying to edit. */
843
844 void
845 restore_pointers ()
846 {
847 clean_read_ptr = saved_clean_read_ptr;
848 repl_write_ptr = saved_repl_write_ptr;
849 }
850
851 /* Return true if the given character is a valid identifier character. */
852
853 static int
854 is_id_char (ch)
855 char ch;
856 {
857 return (isalnum (ch) || (ch == '_') || (ch == '$'));
858 }
859
860 /* Give a message indicating the proper way to invoke this program and then
861 exit with non-zero status. */
862
863 static void
864 usage ()
865 {
866 #ifdef UNPROTOIZE
867 fprintf (stderr, "%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
868 pname, pname);
869 #else /* !defined (UNPROTOIZE) */
870 fprintf (stderr, "%s: usage '%s [ -VqfnkNlgC ] [ -B <diname> ] [ filename ... ]'\n",
871 pname, pname);
872 #endif /* !defined (UNPROTOIZE) */
873 exit (1);
874 }
875
876 /* Return true if the given filename (assumed to be an absolute filename)
877 designates a file residing anywhere beneath any one of the "system"
878 include directories. */
879
880 static int
881 in_system_include_dir (path)
882 const char *path;
883 {
884 struct default_include *p;
885
886 if (path[0] != '/')
887 abort (); /* Must be an absolutized filename. */
888
889 for (p = include_defaults; p->fname; p++)
890 if (!strncmp (path, p->fname, strlen (p->fname))
891 && path[strlen (p->fname)] == '/')
892 return 1;
893 return 0;
894 }
895 \f
896 #if 0
897 /* Return true if the given filename designates a file that the user has
898 read access to and for which the user has write access to the containing
899 directory. */
900
901 static int
902 file_could_be_converted (const char *path)
903 {
904 char *const dir_name = (char *) alloca (strlen (path) + 1);
905
906 if (my_access (path, R_OK))
907 return 0;
908
909 {
910 char *dir_last_slash;
911
912 strcpy (dir_name, path);
913 dir_last_slash = rindex (dir_name, '/');
914 if (dir_last_slash)
915 *dir_last_slash = '\0';
916 else
917 abort (); /* Should have been an absolutized filename. */
918 }
919
920 if (my_access (path, W_OK))
921 return 0;
922
923 return 1;
924 }
925
926 /* Return true if the given filename designates a file that we are allowed
927 to modify. Files which we should not attempt to modify are (a) "system"
928 include files, and (b) files which the user doesn't have write access to,
929 and (c) files which reside in directories which the user doesn't have
930 write access to. Unless requested to be quiet, give warnings about
931 files that we will not try to convert for one reason or another. An
932 exception is made for "system" include files, which we never try to
933 convert and for which we don't issue the usual warnings. */
934
935 static int
936 file_normally_convertible (const char *path)
937 {
938 char *const dir_name = alloca (strlen (path) + 1);
939
940 if (in_system_include_dir (path))
941 return 0;
942
943 {
944 char *dir_last_slash;
945
946 strcpy (dir_name, path);
947 dir_last_slash = rindex (dir_name, '/');
948 if (dir_last_slash)
949 *dir_last_slash = '\0';
950 else
951 abort (); /* Should have been an absolutized filename. */
952 }
953
954 if (my_access (path, R_OK))
955 {
956 if (!quiet_flag)
957 fprintf (stderr, "%s: warning: no read access for file `%s'\n",
958 pname, shortpath (NULL, path));
959 return 0;
960 }
961
962 if (my_access (path, W_OK))
963 {
964 if (!quiet_flag)
965 fprintf (stderr, "%s: warning: no write access for file `%s'\n",
966 pname, shortpath (NULL, path));
967 return 0;
968 }
969
970 if (my_access (dir_name, W_OK))
971 {
972 if (!quiet_flag)
973 fprintf (stderr, "%s: warning: no write access for dir containing `%s'\n",
974 pname, shortpath (NULL, path));
975 return 0;
976 }
977
978 return 1;
979 }
980 #endif /* 0 */
981 \f
982 #ifndef UNPROTOIZE
983
984 /* Return true if the given file_info struct refers to the special SYSCALLS.c.X
985 file. Return false otherwise. */
986
987 static int
988 is_syscalls_file (fi_p)
989 const file_info *fi_p;
990 {
991 char const *f = fi_p->hash_entry->symbol;
992 size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
993 return sysl <= fl && strcmp (f + fl - sysl, syscalls_filename) == 0;
994 }
995
996 #endif /* !defined (UNPROTOIZE) */
997
998 /* Check to see if this file will need to have anything done to it on this
999 run. If there is nothing in the given file which both needs conversion
1000 and for which we have the necessary stuff to do the conversion, return
1001 false. Otherwise, return true.
1002
1003 Note that (for protoize) it is only valid to call this function *after*
1004 the connections between declarations and definitions have all been made
1005 by connect_defs_and_decs. */
1006
1007 static int
1008 needs_to_be_converted (file_p)
1009 const file_info *file_p;
1010 {
1011 const def_dec_info *ddp;
1012
1013 #ifndef UNPROTOIZE
1014
1015 if (is_syscalls_file (file_p))
1016 return 0;
1017
1018 #endif /* !defined (UNPROTOIZE) */
1019
1020 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
1021
1022 if (
1023
1024 #ifndef UNPROTOIZE
1025
1026 /* ... and if we a protoizing and this function is in old style ... */
1027 !ddp->prototyped
1028 /* ... and if this a definition or is a decl with an associated def ... */
1029 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
1030
1031 #else /* defined (UNPROTOIZE) */
1032
1033 /* ... and if we are unprotoizing and this function is in new style ... */
1034 ddp->prototyped
1035
1036 #endif /* defined (UNPROTOIZE) */
1037 )
1038 /* ... then the containing file needs converting. */
1039 return -1;
1040 return 0;
1041 }
1042
1043 /* Return 1 if the file name NAME is in a directory
1044 that should be converted. */
1045
1046 static int
1047 directory_specified_p (name)
1048 const char *name;
1049 {
1050 struct string_list *p;
1051
1052 for (p = directory_list; p; p = p->next)
1053 if (!strncmp (name, p->name, strlen (p->name))
1054 && name[strlen (p->name)] == '/')
1055 {
1056 const char *q = name + strlen (p->name) + 1;
1057
1058 /* If there are more slashes, it's in a subdir, so
1059 this match doesn't count. */
1060 while (*q)
1061 if (*q++ == '/')
1062 goto lose;
1063 return 1;
1064
1065 lose: ;
1066 }
1067
1068 return 0;
1069 }
1070
1071 /* Return 1 if the file named NAME should be excluded from conversion. */
1072
1073 static int
1074 file_excluded_p (name)
1075 const char *name;
1076 {
1077 struct string_list *p;
1078 int len = strlen (name);
1079
1080 for (p = exclude_list; p; p = p->next)
1081 if (!strcmp (name + len - strlen (p->name), p->name)
1082 && name[len - strlen (p->name) - 1] == '/')
1083 return 1;
1084
1085 return 0;
1086 }
1087
1088 /* Construct a new element of a string_list.
1089 STRING is the new element value, and REST holds the remaining elements. */
1090
1091 static struct string_list *
1092 string_list_cons (string, rest)
1093 char *string;
1094 struct string_list *rest;
1095 {
1096 struct string_list *temp
1097 = (struct string_list *) xmalloc (sizeof (struct string_list));
1098
1099 temp->next = rest;
1100 temp->name = string;
1101 return temp;
1102 }
1103 \f
1104 /* ??? The GNU convention for mentioning function args in its comments
1105 is to capitalize them. So change "hash_tab_p" to HASH_TAB_P below.
1106 Likewise for all the other functions. */
1107
1108 /* Given a hash table, apply some function to each node in the table. The
1109 table to traverse is given as the "hash_tab_p" argument, and the
1110 function to be applied to each node in the table is given as "func"
1111 argument. */
1112
1113 static void
1114 visit_each_hash_node (hash_tab_p, func)
1115 const hash_table_entry *hash_tab_p;
1116 void (*func)();
1117 {
1118 const hash_table_entry *primary;
1119
1120 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
1121 if (primary->symbol)
1122 {
1123 hash_table_entry *second;
1124
1125 (*func)(primary);
1126 for (second = primary->hash_next; second; second = second->hash_next)
1127 (*func) (second);
1128 }
1129 }
1130
1131 /* Initialize all of the fields of a new hash table entry, pointed
1132 to by the "p" parameter. Note that the space to hold the entry
1133 is assumed to have already been allocated before this routine is
1134 called. */
1135
1136 static hash_table_entry *
1137 add_symbol (p, s)
1138 hash_table_entry *p;
1139 const char *s;
1140 {
1141 p->hash_next = NULL;
1142 p->symbol = savestring (s, strlen (s));
1143 p->ddip = NULL;
1144 p->fip = NULL;
1145 return p;
1146 }
1147
1148 /* Look for a particular function name or filename in the particular
1149 hash table indicated by "hash_tab_p". If the name is not in the
1150 given hash table, add it. Either way, return a pointer to the
1151 hash table entry for the given name. */
1152
1153 static hash_table_entry *
1154 lookup (hash_tab_p, search_symbol)
1155 hash_table_entry *hash_tab_p;
1156 const char *search_symbol;
1157 {
1158 int hash_value = 0;
1159 const char *search_symbol_char_p = search_symbol;
1160 hash_table_entry *p;
1161
1162 while (*search_symbol_char_p)
1163 hash_value += *search_symbol_char_p++;
1164 hash_value &= hash_mask;
1165 p = &hash_tab_p[hash_value];
1166 if (! p->symbol)
1167 return add_symbol (p, search_symbol);
1168 if (!strcmp (p->symbol, search_symbol))
1169 return p;
1170 while (p->hash_next)
1171 {
1172 p = p->hash_next;
1173 if (!strcmp (p->symbol, search_symbol))
1174 return p;
1175 }
1176 p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry));
1177 p = p->hash_next;
1178 return add_symbol (p, search_symbol);
1179 }
1180 \f
1181 /* Throw a def/dec record on the junk heap.
1182
1183 Also, since we are not using this record anymore, free up all of the
1184 stuff it pointed to. */
1185
1186 static void
1187 free_def_dec (p)
1188 def_dec_info *p;
1189 {
1190 xfree (p->ansi_decl);
1191
1192 #ifndef UNPROTOIZE
1193 {
1194 const f_list_chain_item * curr;
1195 const f_list_chain_item * next;
1196
1197 for (curr = p->f_list_chain; curr; curr = next)
1198 {
1199 next = curr->chain_next;
1200 xfree (curr);
1201 }
1202 }
1203 #endif /* !defined (UNPROTOIZE) */
1204
1205 xfree (p);
1206 }
1207
1208 /* Unexpand as many macro symbol as we can find.
1209
1210 If the given line must be unexpanded, make a copy of it in the heap and
1211 return a pointer to the unexpanded copy. Otherwise return NULL. */
1212
1213 static char *
1214 unexpand_if_needed (aux_info_line)
1215 const char *aux_info_line;
1216 {
1217 static char *line_buf = 0;
1218 static int line_buf_size = 0;
1219 const unexpansion* unexp_p;
1220 int got_unexpanded = 0;
1221 const char *s;
1222 char *copy_p = line_buf;
1223
1224 if (line_buf == 0)
1225 {
1226 line_buf_size = 1024;
1227 line_buf = (char *) xmalloc (line_buf_size);
1228 }
1229
1230 copy_p = line_buf;
1231
1232 /* Make a copy of the input string in line_buf, expanding as necessary. */
1233
1234 for (s = aux_info_line; *s != '\n'; )
1235 {
1236 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
1237 {
1238 const char *in_p = unexp_p->expanded;
1239 size_t len = strlen (in_p);
1240
1241 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1242 {
1243 int size = strlen (unexp_p->contracted);
1244 got_unexpanded = 1;
1245 if (copy_p + size - line_buf >= line_buf_size)
1246 {
1247 int offset = copy_p - line_buf;
1248 line_buf_size *= 2;
1249 line_buf_size += size;
1250 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1251 copy_p = line_buf + offset;
1252 }
1253 strcpy (copy_p, unexp_p->contracted);
1254 copy_p += size;
1255
1256 /* Assume the there will not be another replacement required
1257 within the text just replaced. */
1258
1259 s += len;
1260 goto continue_outer;
1261 }
1262 }
1263 if (copy_p - line_buf == line_buf_size)
1264 {
1265 int offset = copy_p - line_buf;
1266 line_buf_size *= 2;
1267 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1268 copy_p = line_buf + offset;
1269 }
1270 *copy_p++ = *s++;
1271 continue_outer: ;
1272 }
1273 if (copy_p + 2 - line_buf >= line_buf_size)
1274 {
1275 int offset = copy_p - line_buf;
1276 line_buf_size *= 2;
1277 line_buf = (char *) xrealloc (line_buf, line_buf_size);
1278 copy_p = line_buf + offset;
1279 }
1280 *copy_p++ = '\n';
1281 *copy_p = '\0';
1282
1283 return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
1284 }
1285 \f
1286 /* Return the absolutized filename for the given relative
1287 filename. Note that if that filename is already absolute, it may
1288 still be returned in a modified form because this routine also
1289 eliminates redundant slashes and single dots and eliminates double
1290 dots to get a shortest possible filename from the given input
1291 filename. The absolutization of relative filenames is made by
1292 assuming that the given filename is to be taken as relative to
1293 the first argument (cwd) or to the current directory if cwd is
1294 NULL. */
1295
1296 static char *
1297 abspath (cwd, rel_filename)
1298 const char *cwd;
1299 const char *rel_filename;
1300 {
1301 /* Setup the current working directory as needed. */
1302 const char *cwd2 = (cwd) ? cwd : cwd_buffer;
1303 char *const abs_buffer
1304 = (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 2);
1305 char *endp = abs_buffer;
1306 char *outp, *inp;
1307
1308 /* Copy the filename (possibly preceded by the current working
1309 directory name) into the absolutization buffer. */
1310
1311 {
1312 const char *src_p;
1313
1314 if (rel_filename[0] != '/')
1315 {
1316 src_p = cwd2;
1317 while (*endp++ = *src_p++)
1318 continue;
1319 *(endp-1) = '/'; /* overwrite null */
1320 }
1321 src_p = rel_filename;
1322 while (*endp++ = *src_p++)
1323 continue;
1324 }
1325
1326 /* Now make a copy of abs_buffer into abs_buffer, shortening the
1327 filename (by taking out slashes and dots) as we go. */
1328
1329 outp = inp = abs_buffer;
1330 *outp++ = *inp++; /* copy first slash */
1331 #ifdef apollo
1332 if (inp[0] == '/')
1333 *outp++ = *inp++; /* copy second slash */
1334 #endif
1335 for (;;)
1336 {
1337 if (!inp[0])
1338 break;
1339 else if (inp[0] == '/' && outp[-1] == '/')
1340 {
1341 inp++;
1342 continue;
1343 }
1344 else if (inp[0] == '.' && outp[-1] == '/')
1345 {
1346 if (!inp[1])
1347 break;
1348 else if (inp[1] == '/')
1349 {
1350 inp += 2;
1351 continue;
1352 }
1353 else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/'))
1354 {
1355 inp += (inp[2] == '/') ? 3 : 2;
1356 outp -= 2;
1357 while (outp >= abs_buffer && *outp != '/')
1358 outp--;
1359 if (outp < abs_buffer)
1360 {
1361 /* Catch cases like /.. where we try to backup to a
1362 point above the absolute root of the logical file
1363 system. */
1364
1365 fprintf (stderr, "%s: invalid file name: %s\n",
1366 pname, rel_filename);
1367 exit (1);
1368 }
1369 *++outp = '\0';
1370 continue;
1371 }
1372 }
1373 *outp++ = *inp++;
1374 }
1375
1376 /* On exit, make sure that there is a trailing null, and make sure that
1377 the last character of the returned string is *not* a slash. */
1378
1379 *outp = '\0';
1380 if (outp[-1] == '/')
1381 *--outp = '\0';
1382
1383 /* Make a copy (in the heap) of the stuff left in the absolutization
1384 buffer and return a pointer to the copy. */
1385
1386 return savestring (abs_buffer, outp - abs_buffer);
1387 }
1388 \f
1389 /* Given a filename (and possibly a directory name from which the filename
1390 is relative) return a string which is the shortest possible
1391 equivalent for the corresponding full (absolutized) filename. The
1392 shortest possible equivalent may be constructed by converting the
1393 absolutized filename to be a relative filename (i.e. relative to
1394 the actual current working directory). However if a relative filename
1395 is longer, then the full absolute filename is returned.
1396
1397 KNOWN BUG:
1398
1399 Note that "simple-minded" conversion of any given type of filename (either
1400 relative or absolute) may not result in a valid equivalent filename if any
1401 subpart of the original filename is actually a symbolic link. */
1402
1403 static const char *
1404 shortpath (cwd, filename)
1405 const char *cwd;
1406 const char *filename;
1407 {
1408 char *rel_buffer;
1409 char *rel_buf_p;
1410 char *cwd_p = cwd_buffer;
1411 char *path_p;
1412 int unmatched_slash_count = 0;
1413 size_t filename_len = strlen (filename);
1414
1415 path_p = abspath (cwd, filename);
1416 rel_buf_p = rel_buffer = (char *) xmalloc (filename_len);
1417
1418 while (*cwd_p && (*cwd_p == *path_p))
1419 {
1420 cwd_p++;
1421 path_p++;
1422 }
1423 if (!*cwd_p && (!*path_p || *path_p == '/')) /* whole pwd matched */
1424 {
1425 if (!*path_p) /* input *is* the current path! */
1426 return ".";
1427 else
1428 return ++path_p;
1429 }
1430 else
1431 {
1432 if (*path_p)
1433 {
1434 --cwd_p;
1435 --path_p;
1436 while (*cwd_p != '/') /* backup to last slash */
1437 {
1438 --cwd_p;
1439 --path_p;
1440 }
1441 cwd_p++;
1442 path_p++;
1443 unmatched_slash_count++;
1444 }
1445
1446 /* Find out how many directory levels in cwd were *not* matched. */
1447 while (*cwd_p)
1448 if (*cwd_p++ == '/')
1449 unmatched_slash_count++;
1450
1451 /* Now we know how long the "short name" will be.
1452 Reject it if longer than the input. */
1453 if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
1454 return filename;
1455
1456 /* For each of them, put a `../' at the beginning of the short name. */
1457 while (unmatched_slash_count--)
1458 {
1459 /* Give up if the result gets to be longer
1460 than the absolute path name. */
1461 if (rel_buffer + filename_len <= rel_buf_p + 3)
1462 return filename;
1463 *rel_buf_p++ = '.';
1464 *rel_buf_p++ = '.';
1465 *rel_buf_p++ = '/';
1466 }
1467
1468 /* Then tack on the unmatched part of the desired file's name. */
1469 do
1470 {
1471 if (rel_buffer + filename_len <= rel_buf_p)
1472 return filename;
1473 }
1474 while (*rel_buf_p++ = *path_p++);
1475
1476 --rel_buf_p;
1477 if (*(rel_buf_p-1) == '/')
1478 *--rel_buf_p = '\0';
1479 return rel_buffer;
1480 }
1481 }
1482 \f
1483 /* Lookup the given filename in the hash table for filenames. If it is a
1484 new one, then the hash table info pointer will be null. In this case,
1485 we create a new file_info record to go with the filename, and we initialize
1486 that record with some reasonable values. */
1487
1488 /* FILENAME was const, but that causes a warning on AIX when calling stat.
1489 That is probably a bug in AIX, but might as well avoid the warning. */
1490
1491 static file_info *
1492 find_file (filename, do_not_stat)
1493 char *filename;
1494 int do_not_stat;
1495 {
1496 hash_table_entry *hash_entry_p;
1497
1498 hash_entry_p = lookup (filename_primary, filename);
1499 if (hash_entry_p->fip)
1500 return hash_entry_p->fip;
1501 else
1502 {
1503 struct stat stat_buf;
1504 file_info *file_p = (file_info *) xmalloc (sizeof (file_info));
1505
1506 /* If we cannot get status on any given source file, give a warning
1507 and then just set its time of last modification to infinity. */
1508
1509 if (do_not_stat)
1510 stat_buf.st_mtime = (time_t) 0;
1511 else
1512 {
1513 if (my_stat (filename, &stat_buf) == -1)
1514 {
1515 fprintf (stderr, "%s: %s: can't get status: %s\n",
1516 pname, shortpath (NULL, filename), my_strerror(errno));
1517 stat_buf.st_mtime = (time_t) -1;
1518 }
1519 }
1520
1521 hash_entry_p->fip = file_p;
1522 file_p->hash_entry = hash_entry_p;
1523 file_p->defs_decs = NULL;
1524 file_p->mtime = stat_buf.st_mtime;
1525 return file_p;
1526 }
1527 }
1528
1529 /* Generate a fatal error because some part of the aux_info file is
1530 messed up. */
1531
1532 static void
1533 aux_info_corrupted ()
1534 {
1535 fprintf (stderr, "\n%s: fatal error: aux info file corrupted at line %d\n",
1536 pname, current_aux_info_lineno);
1537 exit (1);
1538 }
1539
1540 /* ??? This comment is vague. Say what the condition is for. */
1541 /* Check to see that a condition is true. This is kind of like an assert. */
1542
1543 static void
1544 check_aux_info (cond)
1545 int cond;
1546 {
1547 if (! cond)
1548 aux_info_corrupted ();
1549 }
1550
1551 /* Given a pointer to the closing right parenthesis for a particular formals
1552 list (in an aux_info file) find the corresponding left parenthesis and
1553 return a pointer to it. */
1554
1555 static const char *
1556 find_corresponding_lparen (p)
1557 const char *p;
1558 {
1559 const char *q;
1560 int paren_depth;
1561
1562 for (paren_depth = 1, q = p-1; paren_depth; q--)
1563 {
1564 switch (*q)
1565 {
1566 case ')':
1567 paren_depth++;
1568 break;
1569 case '(':
1570 paren_depth--;
1571 break;
1572 }
1573 }
1574 return ++q;
1575 }
1576 \f
1577 /* Given a line from an aux info file, and a time at which the aux info
1578 file it came from was created, check to see if the item described in
1579 the line comes from a file which has been modified since the aux info
1580 file was created. If so, return non-zero, else return zero. */
1581
1582 static int
1583 referenced_file_is_newer (l, aux_info_mtime)
1584 const char *l;
1585 time_t aux_info_mtime;
1586 {
1587 const char *p;
1588 file_info *fi_p;
1589 char *filename;
1590
1591 check_aux_info (l[0] == '/');
1592 check_aux_info (l[1] == '*');
1593 check_aux_info (l[2] == ' ');
1594
1595 {
1596 const char *filename_start = p = l + 3;
1597
1598 while (*p != ':')
1599 p++;
1600 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1601 strncpy (filename, filename_start, (size_t) (p - filename_start));
1602 filename[p-filename_start] = '\0';
1603 }
1604
1605 /* Call find_file to find the file_info record associated with the file
1606 which contained this particular def or dec item. Note that this call
1607 may cause a new file_info record to be created if this is the first time
1608 that we have ever known about this particular file. */
1609
1610 fi_p = find_file (abspath (invocation_filename, filename), 0);
1611
1612 return (fi_p->mtime > aux_info_mtime);
1613 }
1614 \f
1615 /* Given a line of info from the aux_info file, create a new
1616 def_dec_info record to remember all of the important information about
1617 a function definition or declaration.
1618
1619 Link this record onto the list of such records for the particular file in
1620 which it occurred in proper (descending) line number order (for now).
1621
1622 If there is an identical record already on the list for the file, throw
1623 this one away. Doing so takes care of the (useless and troublesome)
1624 duplicates which are bound to crop up due to multiple inclusions of any
1625 given individual header file.
1626
1627 Finally, link the new def_dec record onto the list of such records
1628 pertaining to this particular function name. */
1629
1630 static void
1631 save_def_or_dec (l, is_syscalls)
1632 const char *l;
1633 int is_syscalls;
1634 {
1635 const char *p;
1636 const char *semicolon_p;
1637 def_dec_info *def_dec_p = (def_dec_info *) xmalloc (sizeof (def_dec_info));
1638
1639 #ifndef UNPROTOIZE
1640 def_dec_p->written = 0;
1641 #endif /* !defined (UNPROTOIZE) */
1642
1643 /* Start processing the line by picking off 5 pieces of information from
1644 the left hand end of the line. These are filename, line number,
1645 new/old/implicit flag (new = ANSI prototype format), definition or
1646 declaration flag, and extern/static flag). */
1647
1648 check_aux_info (l[0] == '/');
1649 check_aux_info (l[1] == '*');
1650 check_aux_info (l[2] == ' ');
1651
1652 {
1653 const char *filename_start = p = l + 3;
1654 char *filename;
1655
1656 while (*p != ':')
1657 p++;
1658 filename = (char *) alloca ((size_t) (p - filename_start) + 1);
1659 strncpy (filename, filename_start, (size_t) (p - filename_start));
1660 filename[p-filename_start] = '\0';
1661
1662 /* Call find_file to find the file_info record associated with the file
1663 which contained this particular def or dec item. Note that this call
1664 may cause a new file_info record to be created if this is the first time
1665 that we have ever known about this particular file.
1666
1667 Note that we started out by forcing all of the base source file names
1668 (i.e. the names of the aux_info files with the .X stripped off) into the
1669 filenames hash table, and we simultaneously setup file_info records for
1670 all of these base file names (even if they may be useless later).
1671 The file_info records for all of these "base" file names (properly)
1672 act as file_info records for the "original" (i.e. un-included) files
1673 which were submitted to gcc for compilation (when the -aux-info
1674 option was used). */
1675
1676 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1677 }
1678
1679 {
1680 const char *line_number_start = ++p;
1681 char line_number[10];
1682
1683 while (*p != ':')
1684 p++;
1685 strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1686 line_number[p-line_number_start] = '\0';
1687 def_dec_p->line = atoi (line_number);
1688 }
1689
1690 /* Check that this record describes a new-style, old-style, or implicit
1691 definition or declaration. */
1692
1693 p++; /* Skip over the `:'. */
1694 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1695
1696 /* Is this a new style (ANSI prototyped) definition or declaration? */
1697
1698 def_dec_p->prototyped = (*p == 'N');
1699
1700 #ifndef UNPROTOIZE
1701
1702 /* Is this an implicit declaration? */
1703
1704 def_dec_p->is_implicit = (*p == 'I');
1705
1706 #endif /* !defined (UNPROTOIZE) */
1707
1708 p++;
1709
1710 check_aux_info ((*p == 'C') || (*p == 'F'));
1711
1712 /* Is this item a function definition (F) or a declaration (C). Note that
1713 we treat item taken from the syscalls file as though they were function
1714 definitions regardless of what the stuff in the file says. */
1715
1716 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1717
1718 #ifndef UNPROTOIZE
1719 def_dec_p->definition = 0; /* Fill this in later if protoizing. */
1720 #endif /* !defined (UNPROTOIZE) */
1721
1722 check_aux_info (*p++ == ' ');
1723 check_aux_info (*p++ == '*');
1724 check_aux_info (*p++ == '/');
1725 check_aux_info (*p++ == ' ');
1726
1727 #ifdef UNPROTOIZE
1728 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1729 #else /* !defined (UNPROTOIZE) */
1730 if (!strncmp (p, "static", 6))
1731 def_dec_p->is_static = -1;
1732 else if (!strncmp (p, "extern", 6))
1733 def_dec_p->is_static = 0;
1734 else
1735 check_aux_info (0); /* Didn't find either `extern' or `static'. */
1736 #endif /* !defined (UNPROTOIZE) */
1737
1738 {
1739 const char *ansi_start = p;
1740
1741 p += 6; /* Pass over the "static" or "extern". */
1742
1743 /* We are now past the initial stuff. Search forward from here to find
1744 the terminating semicolon that should immediately follow the entire
1745 ANSI format function declaration. */
1746
1747 while (*++p != ';')
1748 continue;
1749
1750 semicolon_p = p;
1751
1752 /* Make a copy of the ansi declaration part of the line from the aux_info
1753 file. */
1754
1755 def_dec_p->ansi_decl
1756 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1757
1758 /* Backup and point at the final right paren of the final argument list. */
1759
1760 p--;
1761
1762 #ifndef UNPROTOIZE
1763 def_dec_p->f_list_chain = NULL;
1764 #endif /* !defined (UNPROTOIZE) */
1765
1766 while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
1767 if (*p != ')')
1768 {
1769 free_def_dec (def_dec_p);
1770 return;
1771 }
1772 }
1773
1774 /* Now isolate a whole set of formal argument lists, one-by-one. Normally,
1775 there will only be one list to isolate, but there could be more. */
1776
1777 def_dec_p->f_list_count = 0;
1778
1779 for (;;)
1780 {
1781 const char *left_paren_p = find_corresponding_lparen (p);
1782 #ifndef UNPROTOIZE
1783 {
1784 f_list_chain_item *cip =
1785 (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
1786
1787 cip->formals_list
1788 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1789
1790 /* Add the new chain item at the head of the current list. */
1791
1792 cip->chain_next = def_dec_p->f_list_chain;
1793 def_dec_p->f_list_chain = cip;
1794 }
1795 #endif /* !defined (UNPROTOIZE) */
1796 def_dec_p->f_list_count++;
1797
1798 p = left_paren_p - 2;
1799
1800 /* p must now point either to another right paren, or to the last
1801 character of the name of the function that was declared/defined.
1802 If p points to another right paren, then this indicates that we
1803 are dealing with multiple formals lists. In that case, there
1804 really should be another right paren preceding this right paren. */
1805
1806 if (*p != ')')
1807 break;
1808 else
1809 check_aux_info (*--p == ')');
1810 }
1811
1812
1813 {
1814 const char *past_fn = p + 1;
1815
1816 check_aux_info (*past_fn == ' ');
1817
1818 /* Scan leftwards over the identifier that names the function. */
1819
1820 while (is_id_char (*p))
1821 p--;
1822 p++;
1823
1824 /* p now points to the leftmost character of the function name. */
1825
1826 {
1827 char *fn_string = (char *) alloca (past_fn - p + 1);
1828
1829 strncpy (fn_string, p, (size_t) (past_fn - p));
1830 fn_string[past_fn-p] = '\0';
1831 def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1832 }
1833 }
1834
1835 /* Look at all of the defs and decs for this function name that we have
1836 collected so far. If there is already one which is at the same
1837 line number in the same file, then we can discard this new def_dec_info
1838 record.
1839
1840 As an extra assurance that any such pair of (nominally) identical
1841 function declarations are in fact identical, we also compare the
1842 ansi_decl parts of the lines from the aux_info files just to be on
1843 the safe side.
1844
1845 This comparison will fail if (for instance) the user was playing
1846 messy games with the preprocessor which ultimately causes one
1847 function declaration in one header file to look differently when
1848 that file is included by two (or more) other files. */
1849
1850 {
1851 const def_dec_info *other;
1852
1853 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1854 {
1855 if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1856 {
1857 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1858 {
1859 fprintf (stderr, "%s:%d: declaration of function `%s' takes different forms\n",
1860 def_dec_p->file->hash_entry->symbol,
1861 def_dec_p->line,
1862 def_dec_p->hash_entry->symbol);
1863 exit (1);
1864 }
1865 free_def_dec (def_dec_p);
1866 return;
1867 }
1868 }
1869 }
1870
1871 #ifdef UNPROTOIZE
1872
1873 /* If we are doing unprotoizing, we must now setup the pointers that will
1874 point to the K&R name list and to the K&R argument declarations list.
1875
1876 Note that if this is only a function declaration, then we should not
1877 expect to find any K&R style formals list following the ANSI-style
1878 formals list. This is because GCC knows that such information is
1879 useless in the case of function declarations (function definitions
1880 are a different story however).
1881
1882 Since we are unprotoizing, we don't need any such lists anyway.
1883 All we plan to do is to delete all characters between ()'s in any
1884 case. */
1885
1886 def_dec_p->formal_names = NULL;
1887 def_dec_p->formal_decls = NULL;
1888
1889 if (def_dec_p->is_func_def)
1890 {
1891 p = semicolon_p;
1892 check_aux_info (*++p == ' ');
1893 check_aux_info (*++p == '/');
1894 check_aux_info (*++p == '*');
1895 check_aux_info (*++p == ' ');
1896 check_aux_info (*++p == '(');
1897
1898 {
1899 const char *kr_names_start = ++p; /* Point just inside '('. */
1900
1901 while (*p++ != ')')
1902 continue;
1903 p--; /* point to closing right paren */
1904
1905 /* Make a copy of the K&R parameter names list. */
1906
1907 def_dec_p->formal_names
1908 = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1909 }
1910
1911 check_aux_info (*++p == ' ');
1912 p++;
1913
1914 /* p now points to the first character of the K&R style declarations
1915 list (if there is one) or to the star-slash combination that ends
1916 the comment in which such lists get embedded. */
1917
1918 /* Make a copy of the K&R formal decls list and set the def_dec record
1919 to point to it. */
1920
1921 if (*p == '*') /* Are there no K&R declarations? */
1922 {
1923 check_aux_info (*++p == '/');
1924 def_dec_p->formal_decls = "";
1925 }
1926 else
1927 {
1928 const char *kr_decls_start = p;
1929
1930 while (p[0] != '*' || p[1] != '/')
1931 p++;
1932 p--;
1933
1934 check_aux_info (*p == ' ');
1935
1936 def_dec_p->formal_decls
1937 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1938 }
1939
1940 /* Handle a special case. If we have a function definition marked as
1941 being in "old" style, and if it's formal names list is empty, then
1942 it may actually have the string "void" in its real formals list
1943 in the original source code. Just to make sure, we will get setup
1944 to convert such things anyway.
1945
1946 This kludge only needs to be here because of an insurmountable
1947 problem with generating .X files. */
1948
1949 if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1950 def_dec_p->prototyped = 1;
1951 }
1952
1953 /* Since we are unprotoizing, if this item is already in old (K&R) style,
1954 we can just ignore it. If that is true, throw away the itme now. */
1955
1956 if (!def_dec_p->prototyped)
1957 {
1958 free_def_dec (def_dec_p);
1959 return;
1960 }
1961
1962 #endif /* defined (UNPROTOIZE) */
1963
1964 /* Add this record to the head of the list of records pertaining to this
1965 particular function name. */
1966
1967 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1968 def_dec_p->hash_entry->ddip = def_dec_p;
1969
1970 /* Add this new def_dec_info record to the sorted list of def_dec_info
1971 records for this file. Note that we don't have to worry about duplicates
1972 (caused by multiple inclusions of header files) here because we have
1973 already eliminated duplicates above. */
1974
1975 if (!def_dec_p->file->defs_decs)
1976 {
1977 def_dec_p->file->defs_decs = def_dec_p;
1978 def_dec_p->next_in_file = NULL;
1979 }
1980 else
1981 {
1982 int line = def_dec_p->line;
1983 const def_dec_info *prev = NULL;
1984 const def_dec_info *curr = def_dec_p->file->defs_decs;
1985 const def_dec_info *next = curr->next_in_file;
1986
1987 while (next && (line < curr->line))
1988 {
1989 prev = curr;
1990 curr = next;
1991 next = next->next_in_file;
1992 }
1993 if (line >= curr->line)
1994 {
1995 def_dec_p->next_in_file = curr;
1996 if (prev)
1997 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1998 else
1999 def_dec_p->file->defs_decs = def_dec_p;
2000 }
2001 else /* assert (next == NULL); */
2002 {
2003 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
2004 /* assert (next == NULL); */
2005 def_dec_p->next_in_file = next;
2006 }
2007 }
2008 }
2009 \f
2010 /* Set up the vector COMPILE_PARAMS which is the argument list for running GCC.
2011 Also set input_file_name_index and aux_info_file_name_index
2012 to the indices of the slots where the file names should go. */
2013
2014 /* We initialize the vector by removing -g, -O, -S, -c, and -o options,
2015 and adding '-aux-info AUXFILE -S -o /dev/null INFILE' at the end. */
2016
2017 static void
2018 munge_compile_params (params_list)
2019 const char *params_list;
2020 {
2021 /* Build up the contents in a temporary vector
2022 that is so big that to has to be big enough. */
2023 const char **temp_params
2024 = (const char **) alloca ((strlen (params_list) + 8) * sizeof (char *));
2025 int param_count = 0;
2026 const char *param;
2027
2028 temp_params[param_count++] = compiler_file_name;
2029 for (;;)
2030 {
2031 while (isspace (*params_list))
2032 params_list++;
2033 if (!*params_list)
2034 break;
2035 param = params_list;
2036 while (*params_list && !isspace (*params_list))
2037 params_list++;
2038 if (param[0] != '-')
2039 temp_params[param_count++]
2040 = dupnstr (param, (size_t) (params_list - param));
2041 else
2042 {
2043 switch (param[1])
2044 {
2045 case 'g':
2046 case 'O':
2047 case 'S':
2048 case 'c':
2049 break; /* Don't copy these. */
2050 case 'o':
2051 while (isspace (*params_list))
2052 params_list++;
2053 while (*params_list && !isspace (*params_list))
2054 params_list++;
2055 break;
2056 default:
2057 temp_params[param_count++]
2058 = dupnstr (param, (size_t) (params_list - param));
2059 }
2060 }
2061 if (!*params_list)
2062 break;
2063 }
2064 temp_params[param_count++] = "-aux-info";
2065
2066 /* Leave room for the aux-info file name argument. */
2067 aux_info_file_name_index = param_count;
2068 temp_params[param_count++] = NULL;
2069
2070 temp_params[param_count++] = "-S";
2071 temp_params[param_count++] = "-o";
2072 temp_params[param_count++] = "/dev/null";
2073
2074 /* Leave room for the input file name argument. */
2075 input_file_name_index = param_count;
2076 temp_params[param_count++] = NULL;
2077 /* Terminate the list. */
2078 temp_params[param_count++] = NULL;
2079
2080 /* Make a copy of the compile_params in heap space. */
2081
2082 compile_params
2083 = (const char **) xmalloc (sizeof (char *) * (param_count+1));
2084 memcpy (compile_params, temp_params, sizeof (char *) * param_count);
2085 }
2086
2087 /* Do a recompilation for the express purpose of generating a new aux_info
2088 file to go with a specific base source file. */
2089
2090 static int
2091 gen_aux_info_file (base_filename)
2092 const char *base_filename;
2093 {
2094 int child_pid;
2095
2096 if (!input_file_name_index)
2097 munge_compile_params ("");
2098
2099 /* Store the full source file name in the argument vector. */
2100 compile_params[input_file_name_index] = shortpath (NULL, base_filename);
2101 /* Add .X to source file name to get aux-info file name. */
2102 compile_params[aux_info_file_name_index]
2103 = savestring2 (compile_params[input_file_name_index],
2104 strlen (compile_params[input_file_name_index]),
2105 ".X",
2106 2);
2107
2108 if (!quiet_flag)
2109 fprintf (stderr, "%s: compiling `%s'\n",
2110 pname, compile_params[input_file_name_index]);
2111
2112 if (child_pid = fork ())
2113 {
2114 if (child_pid == -1)
2115 {
2116 fprintf (stderr, "%s: could not fork process: %s\n",
2117 pname, my_strerror(errno));
2118 return 0;
2119 }
2120
2121 #if 0
2122 /* Print out the command line that the other process is now executing. */
2123
2124 if (!quiet_flag)
2125 {
2126 const char **arg;
2127
2128 fputs ("\t", stderr);
2129 for (arg = compile_params; *arg; arg++)
2130 {
2131 fputs (*arg, stderr);
2132 fputc (' ', stderr);
2133 }
2134 fputc ('\n', stderr);
2135 fflush (stderr);
2136 }
2137 #endif /* 0 */
2138
2139 {
2140 int wait_status;
2141
2142 if (wait (&wait_status) == -1)
2143 {
2144 fprintf (stderr, "%s: wait failed: %s\n",
2145 pname, my_strerror(errno));
2146 return 0;
2147 }
2148 if (WIFSIGNALED (wait_status))
2149 {
2150 fprintf (stderr, "%s: subprocess got fatal signal %d",
2151 pname, WTERMSIG (wait_status));
2152 return 0;
2153 }
2154 if (WIFEXITED (wait_status) && WEXITSTATUS (wait_status) != 0)
2155 {
2156 fprintf (stderr, "%s: %s exited with status %d\n",
2157 pname, base_filename, WEXITSTATUS (wait_status));
2158 return 0;
2159 }
2160 return 1;
2161 }
2162 }
2163 else
2164 {
2165 if (my_execvp (compile_params[0], (char *const *) compile_params))
2166 {
2167 int e = errno, f = fileno (stderr);
2168 write (f, pname, strlen (pname));
2169 write (f, ": ", 2);
2170 write (f, compile_params[0], strlen (compile_params[0]));
2171 write (f, ": ", 2);
2172 #ifdef HAVE_STRERROR
2173 {
2174 char *p = strerror(e);
2175 write (f, p, strlen (p));
2176 }
2177 #else
2178 write (f, sys_errlist[e], strlen (sys_errlist[e]));
2179 #endif
2180 write (f, "\n", 1);
2181 _exit (1);
2182 }
2183 return 1; /* Never executed. */
2184 }
2185 }
2186 \f
2187 /* Read in all of the information contained in a single aux_info file.
2188 Save all of the important stuff for later. */
2189
2190 static void
2191 process_aux_info_file (base_source_filename, keep_it, is_syscalls)
2192 const char *base_source_filename;
2193 int keep_it;
2194 int is_syscalls;
2195 {
2196 size_t base_len = strlen (base_source_filename);
2197 char * aux_info_filename
2198 = (char *) alloca (base_len + strlen (aux_info_suffix) + 1);
2199 char *aux_info_base;
2200 char *aux_info_limit;
2201 char *aux_info_relocated_name;
2202 const char *aux_info_second_line;
2203 time_t aux_info_mtime;
2204 size_t aux_info_size;
2205 int must_create;
2206
2207 /* Construct the aux_info filename from the base source filename. */
2208
2209 strcpy (aux_info_filename, base_source_filename);
2210 strcat (aux_info_filename, aux_info_suffix);
2211
2212 /* Check that the aux_info file exists and is readable. If it does not
2213 exist, try to create it (once only). */
2214
2215 /* If file doesn't exist, set must_create.
2216 Likewise if it exists and we can read it but it is obsolete.
2217 Otherwise, report an error. */
2218 must_create = 0;
2219
2220 /* Come here with must_create set to 1 if file is out of date. */
2221 start_over: ;
2222
2223 if (my_access (aux_info_filename, R_OK) == -1)
2224 {
2225 if (errno == ENOENT)
2226 {
2227 if (is_syscalls)
2228 {
2229 fprintf (stderr, "%s: warning: missing SYSCALLS file `%s'\n",
2230 pname, aux_info_filename);
2231 return;
2232 }
2233 must_create = 1;
2234 }
2235 else
2236 {
2237 fprintf (stderr, "%s: can't read aux info file `%s': %s\n",
2238 pname, shortpath (NULL, aux_info_filename),
2239 my_strerror(errno));
2240 errors++;
2241 return;
2242 }
2243 }
2244 #if 0 /* There is code farther down to take care of this. */
2245 else
2246 {
2247 struct stat s1, s2;
2248 stat (aux_info_file_name, &s1);
2249 stat (base_source_file_name, &s2);
2250 if (s2.st_mtime > s1.st_mtime)
2251 must_create = 1;
2252 }
2253 #endif /* 0 */
2254
2255 /* If we need a .X file, create it, and verify we can read it. */
2256 if (must_create)
2257 {
2258 if (!gen_aux_info_file (base_source_filename))
2259 {
2260 errors++;
2261 return;
2262 }
2263 if (my_access (aux_info_filename, R_OK) == -1)
2264 {
2265 fprintf (stderr, "%s: can't read aux info file `%s': %s\n",
2266 pname, shortpath (NULL, aux_info_filename),
2267 my_strerror(errno));
2268 errors++;
2269 return;
2270 }
2271 }
2272
2273 {
2274 struct stat stat_buf;
2275
2276 /* Get some status information about this aux_info file. */
2277
2278 if (my_stat (aux_info_filename, &stat_buf) == -1)
2279 {
2280 fprintf (stderr, "%s: can't get status of aux info file `%s': %s\n",
2281 pname, shortpath (NULL, aux_info_filename),
2282 my_strerror(errno));
2283 errors++;
2284 return;
2285 }
2286
2287 /* Check on whether or not this aux_info file is zero length. If it is,
2288 then just ignore it and return. */
2289
2290 if ((aux_info_size = stat_buf.st_size) == 0)
2291 return;
2292
2293 /* Get the date/time of last modification for this aux_info file and
2294 remember it. We will have to check that any source files that it
2295 contains information about are at least this old or older. */
2296
2297 aux_info_mtime = stat_buf.st_mtime;
2298
2299 if (!is_syscalls)
2300 {
2301 /* Compare mod time with the .c file; update .X file if obsolete.
2302 The code later on can fail to check the .c file
2303 if it did not directly define any functions. */
2304
2305 if (my_stat (base_source_filename, &stat_buf) == -1)
2306 {
2307 fprintf (stderr, "%s: can't get status of aux info file `%s': %s\n",
2308 pname, shortpath (NULL, base_source_filename),
2309 my_strerror(errno));
2310 errors++;
2311 return;
2312 }
2313 if (stat_buf.st_mtime > aux_info_mtime)
2314 {
2315 must_create = 1;
2316 goto start_over;
2317 }
2318 }
2319 }
2320
2321 {
2322 int aux_info_file;
2323
2324 /* Open the aux_info file. */
2325
2326 if ((aux_info_file = my_open (aux_info_filename, O_RDONLY, 0444 )) == -1)
2327 {
2328 fprintf (stderr, "%s: can't open aux info file `%s' for reading: %s\n",
2329 pname, shortpath (NULL, aux_info_filename),
2330 my_strerror(errno));
2331 return;
2332 }
2333
2334 /* Allocate space to hold the aux_info file in memory. */
2335
2336 aux_info_base = xmalloc (aux_info_size + 1);
2337 aux_info_limit = aux_info_base + aux_info_size;
2338 *aux_info_limit = '\0';
2339
2340 /* Read the aux_info file into memory. */
2341
2342 if (safe_read (aux_info_file, aux_info_base, aux_info_size) != aux_info_size)
2343 {
2344 fprintf (stderr, "%s: error reading aux info file `%s': %s\n",
2345 pname, shortpath (NULL, aux_info_filename),
2346 my_strerror(errno));
2347 free (aux_info_base);
2348 close (aux_info_file);
2349 return;
2350 }
2351
2352 /* Close the aux info file. */
2353
2354 if (close (aux_info_file))
2355 {
2356 fprintf (stderr, "%s: error closing aux info file `%s': %s\n",
2357 pname, shortpath (NULL, aux_info_filename),
2358 my_strerror(errno));
2359 free (aux_info_base);
2360 close (aux_info_file);
2361 return;
2362 }
2363 }
2364
2365 /* Delete the aux_info file (unless requested not to). If the deletion
2366 fails for some reason, don't even worry about it. */
2367
2368 if (must_create && !keep_it)
2369 if (my_unlink (aux_info_filename) == -1)
2370 fprintf (stderr, "%s: can't delete aux info file `%s': %s\n",
2371 pname, shortpath (NULL, aux_info_filename),
2372 my_strerror(errno));
2373
2374 /* Save a pointer into the first line of the aux_info file which
2375 contains the filename of the directory from which the compiler
2376 was invoked when the associated source file was compiled.
2377 This information is used later to help create complete
2378 filenames out of the (potentially) relative filenames in
2379 the aux_info file. */
2380
2381 {
2382 char *p = aux_info_base;
2383
2384 while (*p != ':')
2385 p++;
2386 p++;
2387 while (*p == ' ')
2388 p++;
2389 invocation_filename = p; /* Save a pointer to first byte of path. */
2390 while (*p != ' ')
2391 p++;
2392 *p++ = '/';
2393 *p++ = '\0';
2394 while (*p++ != '\n')
2395 continue;
2396 aux_info_second_line = p;
2397 aux_info_relocated_name = 0;
2398 if (invocation_filename[0] != '/')
2399 {
2400 /* INVOCATION_FILENAME is relative;
2401 append it to BASE_SOURCE_FILENAME's dir. */
2402 char *dir_end;
2403 aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
2404 strcpy (aux_info_relocated_name, base_source_filename);
2405 dir_end = rindex (aux_info_relocated_name, '/');
2406 if (dir_end)
2407 dir_end++;
2408 else
2409 dir_end = aux_info_relocated_name;
2410 strcpy (dir_end, invocation_filename);
2411 invocation_filename = aux_info_relocated_name;
2412 }
2413 }
2414
2415
2416 {
2417 const char *aux_info_p;
2418
2419 /* Do a pre-pass on the lines in the aux_info file, making sure that all
2420 of the source files referenced in there are at least as old as this
2421 aux_info file itself. If not, go back and regenerate the aux_info
2422 file anew. Don't do any of this for the syscalls file. */
2423
2424 if (!is_syscalls)
2425 {
2426 current_aux_info_lineno = 2;
2427
2428 for (aux_info_p = aux_info_second_line; *aux_info_p; )
2429 {
2430 if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2431 {
2432 free (aux_info_base);
2433 xfree (aux_info_relocated_name);
2434 if (keep_it && my_unlink (aux_info_filename) == -1)
2435 {
2436 fprintf (stderr, "%s: can't delete file `%s': %s\n",
2437 pname, shortpath (NULL, aux_info_filename),
2438 my_strerror(errno));
2439 return;
2440 }
2441 must_create = 1;
2442 goto start_over;
2443 }
2444
2445 /* Skip over the rest of this line to start of next line. */
2446
2447 while (*aux_info_p != '\n')
2448 aux_info_p++;
2449 aux_info_p++;
2450 current_aux_info_lineno++;
2451 }
2452 }
2453
2454 /* Now do the real pass on the aux_info lines. Save their information in
2455 the in-core data base. */
2456
2457 current_aux_info_lineno = 2;
2458
2459 for (aux_info_p = aux_info_second_line; *aux_info_p;)
2460 {
2461 char *unexpanded_line = unexpand_if_needed (aux_info_p);
2462
2463 if (unexpanded_line)
2464 {
2465 save_def_or_dec (unexpanded_line, is_syscalls);
2466 free (unexpanded_line);
2467 }
2468 else
2469 save_def_or_dec (aux_info_p, is_syscalls);
2470
2471 /* Skip over the rest of this line and get to start of next line. */
2472
2473 while (*aux_info_p != '\n')
2474 aux_info_p++;
2475 aux_info_p++;
2476 current_aux_info_lineno++;
2477 }
2478 }
2479
2480 free (aux_info_base);
2481 xfree (aux_info_relocated_name);
2482 }
2483 \f
2484 #ifndef UNPROTOIZE
2485
2486 /* Check an individual filename for a .c suffix. If the filename has this
2487 suffix, rename the file such that its suffix is changed to .C. This
2488 function implements the -C option. */
2489
2490 static void
2491 rename_c_file (hp)
2492 const hash_table_entry *hp;
2493 {
2494 const char *filename = hp->symbol;
2495 int last_char_index = strlen (filename) - 1;
2496 char *const new_filename = (char *) alloca (strlen (filename) + 1);
2497
2498 /* Note that we don't care here if the given file was converted or not. It
2499 is possible that the given file was *not* converted, simply because there
2500 was nothing in it which actually required conversion. Even in this case,
2501 we want to do the renaming. Note that we only rename files with the .c
2502 suffix. */
2503
2504 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.')
2505 return;
2506
2507 strcpy (new_filename, filename);
2508 new_filename[last_char_index] = 'C';
2509
2510 if (my_link (filename, new_filename) == -1)
2511 {
2512 fprintf (stderr, "%s: warning: can't link file `%s' to `%s': %s\n",
2513 pname, shortpath (NULL, filename),
2514 shortpath (NULL, new_filename), my_strerror(errno));
2515 errors++;
2516 return;
2517 }
2518
2519 if (my_unlink (filename) == -1)
2520 {
2521 fprintf (stderr, "%s: warning: can't delete file `%s': %s\n",
2522 pname, shortpath (NULL, filename), my_strerror(errno));
2523 errors++;
2524 return;
2525 }
2526 }
2527
2528 #endif /* !defined (UNPROTOIZE) */
2529 \f
2530 /* Take the list of definitions and declarations attached to a particular
2531 file_info node and reverse the order of the list. This should get the
2532 list into an order such that the item with the lowest associated line
2533 number is nearest the head of the list. When these lists are originally
2534 built, they are in the opposite order. We want to traverse them in
2535 normal line number order later (i.e. lowest to highest) so reverse the
2536 order here. */
2537
2538 static void
2539 reverse_def_dec_list (hp)
2540 const hash_table_entry *hp;
2541 {
2542 file_info *file_p = hp->fip;
2543 const def_dec_info *prev = NULL;
2544 const def_dec_info *current = file_p->defs_decs;
2545
2546 if (!( current = file_p->defs_decs))
2547 return; /* no list to reverse */
2548
2549 prev = current;
2550 if (! (current = current->next_in_file))
2551 return; /* can't reverse a single list element */
2552
2553 ((NONCONST def_dec_info *) prev)->next_in_file = NULL;
2554
2555 while (current)
2556 {
2557 const def_dec_info *next = current->next_in_file;
2558
2559 ((NONCONST def_dec_info *) current)->next_in_file = prev;
2560 prev = current;
2561 current = next;
2562 }
2563
2564 file_p->defs_decs = prev;
2565 }
2566
2567 #ifndef UNPROTOIZE
2568
2569 /* Find the (only?) extern definition for a particular function name, starting
2570 from the head of the linked list of entries for the given name. If we
2571 cannot find an extern definition for the given function name, issue a
2572 warning and scrounge around for the next best thing, i.e. an extern
2573 function declaration with a prototype attached to it. Note that we only
2574 allow such substitutions for extern declarations and never for static
2575 declarations. That's because the only reason we allow them at all is
2576 to let un-prototyped function declarations for system-supplied library
2577 functions get their prototypes from our own extra SYSCALLS.c.X file which
2578 contains all of the correct prototypes for system functions. */
2579
2580 static const def_dec_info *
2581 find_extern_def (head, user)
2582 const def_dec_info *head;
2583 const def_dec_info *user;
2584 {
2585 const def_dec_info *dd_p;
2586 const def_dec_info *extern_def_p = NULL;
2587 int conflict_noted = 0;
2588
2589 /* Don't act too stupid here. Somebody may try to convert an entire system
2590 in one swell fwoop (rather than one program at a time, as should be done)
2591 and in that case, we may find that there are multiple extern definitions
2592 of a given function name in the entire set of source files that we are
2593 converting. If however one of these definitions resides in exactly the
2594 same source file as the reference we are trying to satisfy then in that
2595 case it would be stupid for us to fail to realize that this one definition
2596 *must* be the precise one we are looking for.
2597
2598 To make sure that we don't miss an opportunity to make this "same file"
2599 leap of faith, we do a prescan of the list of records relating to the
2600 given function name, and we look (on this first scan) *only* for a
2601 definition of the function which is in the same file as the reference
2602 we are currently trying to satisfy. */
2603
2604 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2605 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2606 return dd_p;
2607
2608 /* Now, since we have not found a definition in the same file as the
2609 reference, we scan the list again and consider all possibilities from
2610 all files. Here we may get conflicts with the things listed in the
2611 SYSCALLS.c.X file, but if that happens it only means that the source
2612 code being converted contains its own definition of a function which
2613 could have been supplied by libc.a. In such cases, we should avoid
2614 issuing the normal warning, and defer to the definition given in the
2615 user's own code. */
2616
2617 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2618 if (dd_p->is_func_def && !dd_p->is_static)
2619 {
2620 if (!extern_def_p) /* Previous definition? */
2621 extern_def_p = dd_p; /* Remember the first definition found. */
2622 else
2623 {
2624 /* Ignore definition just found if it came from SYSCALLS.c.X. */
2625
2626 if (is_syscalls_file (dd_p->file))
2627 continue;
2628
2629 /* Quietly replace the definition previously found with the one
2630 just found if the previous one was from SYSCALLS.c.X. */
2631
2632 if (is_syscalls_file (extern_def_p->file))
2633 {
2634 extern_def_p = dd_p;
2635 continue;
2636 }
2637
2638 /* If we get here, then there is a conflict between two function
2639 declarations for the same function, both of which came from the
2640 user's own code. */
2641
2642 if (!conflict_noted) /* first time we noticed? */
2643 {
2644 conflict_noted = 1;
2645 fprintf (stderr, "%s: conflicting extern definitions of '%s'\n",
2646 pname, head->hash_entry->symbol);
2647 if (!quiet_flag)
2648 {
2649 fprintf (stderr, "%s: declarations of '%s' will not be converted\n",
2650 pname, head->hash_entry->symbol);
2651 fprintf (stderr, "%s: conflict list for '%s' follows:\n",
2652 pname, head->hash_entry->symbol);
2653 fprintf (stderr, "%s: %s(%d): %s\n",
2654 pname,
2655 shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2656 extern_def_p->line, extern_def_p->ansi_decl);
2657 }
2658 }
2659 if (!quiet_flag)
2660 fprintf (stderr, "%s: %s(%d): %s\n",
2661 pname,
2662 shortpath (NULL, dd_p->file->hash_entry->symbol),
2663 dd_p->line, dd_p->ansi_decl);
2664 }
2665 }
2666
2667 /* We want to err on the side of caution, so if we found multiple conflicting
2668 definitions for the same function, treat this as being that same as if we
2669 had found no definitions (i.e. return NULL). */
2670
2671 if (conflict_noted)
2672 return NULL;
2673
2674 if (!extern_def_p)
2675 {
2676 /* We have no definitions for this function so do the next best thing.
2677 Search for an extern declaration already in prototype form. */
2678
2679 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2680 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2681 {
2682 extern_def_p = dd_p; /* save a pointer to the definition */
2683 if (!quiet_flag)
2684 fprintf (stderr, "%s: warning: using formals list from %s(%d) for function `%s'\n",
2685 pname,
2686 shortpath (NULL, dd_p->file->hash_entry->symbol),
2687 dd_p->line, dd_p->hash_entry->symbol);
2688 break;
2689 }
2690
2691 /* Gripe about unprototyped function declarations that we found no
2692 corresponding definition (or other source of prototype information)
2693 for.
2694
2695 Gripe even if the unprototyped declaration we are worried about
2696 exists in a file in one of the "system" include directories. We
2697 can gripe about these because we should have at least found a
2698 corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
2699 didn't, then that means that the SYSCALLS.c.X file is missing some
2700 needed prototypes for this particular system. That is worth telling
2701 the user about! */
2702
2703 if (!extern_def_p)
2704 {
2705 const char *file = user->file->hash_entry->symbol;
2706
2707 if (!quiet_flag)
2708 if (in_system_include_dir (file))
2709 {
2710 /* Why copy this string into `needed' at all?
2711 Why not just use user->ansi_decl without copying? */
2712 char *needed = (char *) alloca (strlen (user->ansi_decl) + 1);
2713 char *p;
2714
2715 strcpy (needed, user->ansi_decl);
2716 p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
2717 + strlen (user->hash_entry->symbol) + 2;
2718 /* Avoid having ??? in the string. */
2719 *p++ = '?';
2720 *p++ = '?';
2721 *p++ = '?';
2722 strcpy (p, ");");
2723
2724 fprintf (stderr, "%s: %d: `%s' used but missing from SYSCALLS\n",
2725 shortpath (NULL, file), user->line,
2726 needed+7); /* Don't print "extern " */
2727 }
2728 #if 0
2729 else
2730 fprintf (stderr, "%s: %d: warning: no extern definition for `%s'\n",
2731 shortpath (NULL, file), user->line,
2732 user->hash_entry->symbol);
2733 #endif
2734 }
2735 }
2736 return extern_def_p;
2737 }
2738 \f
2739 /* Find the (only?) static definition for a particular function name in a
2740 given file. Here we get the function-name and the file info indirectly
2741 from the def_dec_info record pointer which is passed in. */
2742
2743 static const def_dec_info *
2744 find_static_definition (user)
2745 const def_dec_info *user;
2746 {
2747 const def_dec_info *head = user->hash_entry->ddip;
2748 const def_dec_info *dd_p;
2749 int num_static_defs = 0;
2750 const def_dec_info *static_def_p = NULL;
2751
2752 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2753 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2754 {
2755 static_def_p = dd_p; /* save a pointer to the definition */
2756 num_static_defs++;
2757 }
2758 if (num_static_defs == 0)
2759 {
2760 if (!quiet_flag)
2761 fprintf (stderr, "%s: warning: no static definition for `%s' in file `%s'\n",
2762 pname, head->hash_entry->symbol,
2763 shortpath (NULL, user->file->hash_entry->symbol));
2764 }
2765 else if (num_static_defs > 1)
2766 {
2767 fprintf (stderr, "%s: multiple static defs of `%s' in file `%s'\n",
2768 pname, head->hash_entry->symbol,
2769 shortpath (NULL, user->file->hash_entry->symbol));
2770 return NULL;
2771 }
2772 return static_def_p;
2773 }
2774
2775 /* Find good prototype style formal argument lists for all of the function
2776 declarations which didn't have them before now.
2777
2778 To do this we consider each function name one at a time. For each function
2779 name, we look at the items on the linked list of def_dec_info records for
2780 that particular name.
2781
2782 Somewhere on this list we should find one (and only one) def_dec_info
2783 record which represents the actual function definition, and this record
2784 should have a nice formal argument list already associated with it.
2785
2786 Thus, all we have to do is to connect up all of the other def_dec_info
2787 records for this particular function name to the special one which has
2788 the full-blown formals list.
2789
2790 Of course it is a little more complicated than just that. See below for
2791 more details. */
2792
2793 static void
2794 connect_defs_and_decs (hp)
2795 const hash_table_entry *hp;
2796 {
2797 const def_dec_info *dd_p;
2798 const def_dec_info *extern_def_p = NULL;
2799 int first_extern_reference = 1;
2800
2801 /* Traverse the list of definitions and declarations for this particular
2802 function name. For each item on the list, if it is a function
2803 definition (either old style or new style) then GCC has already been
2804 kind enough to produce a prototype for us, and it is associated with
2805 the item already, so declare the item as its own associated "definition".
2806
2807 Also, for each item which is only a function declaration, but which
2808 nonetheless has its own prototype already (obviously supplied by the user)
2809 declare the item as it's own definition.
2810
2811 Note that when/if there are multiple user-supplied prototypes already
2812 present for multiple declarations of any given function, these multiple
2813 prototypes *should* all match exactly with one another and with the
2814 prototype for the actual function definition. We don't check for this
2815 here however, since we assume that the compiler must have already done
2816 this consistency checking when it was creating the .X files. */
2817
2818 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2819 if (dd_p->prototyped)
2820 ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2821
2822 /* Traverse the list of definitions and declarations for this particular
2823 function name. For each item on the list, if it is an extern function
2824 declaration and if it has no associated definition yet, go try to find
2825 the matching extern definition for the declaration.
2826
2827 When looking for the matching function definition, warn the user if we
2828 fail to find one.
2829
2830 If we find more that one function definition also issue a warning.
2831
2832 Do the search for the matching definition only once per unique function
2833 name (and only when absolutely needed) so that we can avoid putting out
2834 redundant warning messages, and so that we will only put out warning
2835 messages when there is actually a reference (i.e. a declaration) for
2836 which we need to find a matching definition. */
2837
2838 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2839 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2840 {
2841 if (first_extern_reference)
2842 {
2843 extern_def_p = find_extern_def (hp->ddip, dd_p);
2844 first_extern_reference = 0;
2845 }
2846 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2847 }
2848
2849 /* Traverse the list of definitions and declarations for this particular
2850 function name. For each item on the list, if it is a static function
2851 declaration and if it has no associated definition yet, go try to find
2852 the matching static definition for the declaration within the same file.
2853
2854 When looking for the matching function definition, warn the user if we
2855 fail to find one in the same file with the declaration, and refuse to
2856 convert this kind of cross-file static function declaration. After all,
2857 this is stupid practice and should be discouraged.
2858
2859 We don't have to worry about the possibility that there is more than one
2860 matching function definition in the given file because that would have
2861 been flagged as an error by the compiler.
2862
2863 Do the search for the matching definition only once per unique
2864 function-name/source-file pair (and only when absolutely needed) so that
2865 we can avoid putting out redundant warning messages, and so that we will
2866 only put out warning messages when there is actually a reference (i.e. a
2867 declaration) for which we actually need to find a matching definition. */
2868
2869 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2870 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2871 {
2872 const def_dec_info *dd_p2;
2873 const def_dec_info *static_def;
2874
2875 /* We have now found a single static declaration for which we need to
2876 find a matching definition. We want to minimize the work (and the
2877 number of warnings), so we will find an appropriate (matching)
2878 static definition for this declaration, and then distribute it
2879 (as the definition for) any and all other static declarations
2880 for this function name which occur within the same file, and which
2881 do not already have definitions.
2882
2883 Note that a trick is used here to prevent subsequent attempts to
2884 call find_static_definition for a given function-name & file
2885 if the first such call returns NULL. Essentially, we convert
2886 these NULL return values to -1, and put the -1 into the definition
2887 field for each other static declaration from the same file which
2888 does not already have an associated definition.
2889 This makes these other static declarations look like they are
2890 actually defined already when the outer loop here revisits them
2891 later on. Thus, the outer loop will skip over them. Later, we
2892 turn the -1's back to NULL's. */
2893
2894 ((NONCONST def_dec_info *) dd_p)->definition =
2895 (static_def = find_static_definition (dd_p))
2896 ? static_def
2897 : (const def_dec_info *) -1;
2898
2899 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2900 if (!dd_p2->is_func_def && dd_p2->is_static
2901 && !dd_p2->definition && (dd_p2->file == dd_p->file))
2902 ((NONCONST def_dec_info *)dd_p2)->definition = dd_p->definition;
2903 }
2904
2905 /* Convert any dummy (-1) definitions we created in the step above back to
2906 NULL's (as they should be). */
2907
2908 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2909 if (dd_p->definition == (def_dec_info *) -1)
2910 ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2911 }
2912
2913 #endif /* !defined (UNPROTOIZE) */
2914
2915 /* Give a pointer into the clean text buffer, return a number which is the
2916 original source line number that the given pointer points into. */
2917
2918 static int
2919 identify_lineno (clean_p)
2920 const char *clean_p;
2921 {
2922 int line_num = 1;
2923 const char *scan_p;
2924
2925 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2926 if (*scan_p == '\n')
2927 line_num++;
2928 return line_num;
2929 }
2930
2931 /* Issue an error message and give up on doing this particular edit. */
2932
2933 static void
2934 declare_source_confusing (clean_p)
2935 const char *clean_p;
2936 {
2937 if (!quiet_flag)
2938 {
2939 if (clean_p == 0)
2940 fprintf (stderr, "%s: %d: warning: source too confusing\n",
2941 shortpath (NULL, convert_filename), last_known_line_number);
2942 else
2943 fprintf (stderr, "%s: %d: warning: source too confusing\n",
2944 shortpath (NULL, convert_filename),
2945 identify_lineno (clean_p));
2946 }
2947 longjmp (source_confusion_recovery, 1);
2948 }
2949
2950 /* Check that a condition which is expected to be true in the original source
2951 code is in fact true. If not, issue an error message and give up on
2952 converting this particular source file. */
2953
2954 static void
2955 check_source (cond, clean_p)
2956 int cond;
2957 const char *clean_p;
2958 {
2959 if (!cond)
2960 declare_source_confusing (clean_p);
2961 }
2962
2963 /* If we think of the in-core cleaned text buffer as a memory mapped
2964 file (with the variable last_known_line_start acting as sort of a
2965 file pointer) then we can imagine doing "seeks" on the buffer. The
2966 following routine implements a kind of "seek" operation for the in-core
2967 (cleaned) copy of the source file. When finished, it returns a pointer to
2968 the start of a given (numbered) line in the cleaned text buffer.
2969
2970 Note that protoize only has to "seek" in the forward direction on the
2971 in-core cleaned text file buffers, and it never needs to back up.
2972
2973 This routine is made a little bit faster by remembering the line number
2974 (and pointer value) supplied (and returned) from the previous "seek".
2975 This prevents us from always having to start all over back at the top
2976 of the in-core cleaned buffer again. */
2977
2978 static const char *
2979 seek_to_line (n)
2980 int n;
2981 {
2982 if (n < last_known_line_number)
2983 abort ();
2984
2985 while (n > last_known_line_number)
2986 {
2987 while (*last_known_line_start != '\n')
2988 check_source (++last_known_line_start < clean_text_limit, 0);
2989 last_known_line_start++;
2990 last_known_line_number++;
2991 }
2992 return last_known_line_start;
2993 }
2994
2995 /* Given a pointer to a character in the cleaned text buffer, return a pointer
2996 to the next non-whitepace character which follows it. */
2997
2998 static const char *
2999 forward_to_next_token_char (ptr)
3000 const char *ptr;
3001 {
3002 for (++ptr; isspace (*ptr); check_source (++ptr < clean_text_limit, 0))
3003 continue;
3004 return ptr;
3005 }
3006
3007 /* Copy a chunk of text of length `len' and starting at `str' to the current
3008 output buffer. Note that all attempts to add stuff to the current output
3009 buffer ultimately go through here. */
3010
3011 static void
3012 output_bytes (str, len)
3013 const char *str;
3014 size_t len;
3015 {
3016 if ((repl_write_ptr + 1) + len >= repl_text_limit)
3017 {
3018 size_t new_size = (repl_text_limit - repl_text_base) << 1;
3019 char *new_buf = (char *) xrealloc (repl_text_base, new_size);
3020
3021 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
3022 repl_text_base = new_buf;
3023 repl_text_limit = new_buf + new_size;
3024 }
3025 memcpy (repl_write_ptr + 1, str, len);
3026 repl_write_ptr += len;
3027 }
3028
3029 /* Copy all bytes (except the trailing null) of a null terminated string to
3030 the current output buffer. */
3031
3032 static void
3033 output_string (str)
3034 const char *str;
3035 {
3036 output_bytes (str, strlen (str));
3037 }
3038
3039 /* Copy some characters from the original text buffer to the current output
3040 buffer.
3041
3042 This routine takes a pointer argument `p' which is assumed to be a pointer
3043 into the cleaned text buffer. The bytes which are copied are the `original'
3044 equivalents for the set of bytes between the last value of `clean_read_ptr'
3045 and the argument value `p'.
3046
3047 The set of bytes copied however, comes *not* from the cleaned text buffer,
3048 but rather from the direct counterparts of these bytes within the original
3049 text buffer.
3050
3051 Thus, when this function is called, some bytes from the original text
3052 buffer (which may include original comments and preprocessing directives)
3053 will be copied into the output buffer.
3054
3055 Note that the request implied when this routine is called includes the
3056 byte pointed to by the argument pointer `p'. */
3057
3058 static void
3059 output_up_to (p)
3060 const char *p;
3061 {
3062 size_t copy_length = (size_t) (p - clean_read_ptr);
3063 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
3064
3065 if (copy_length == 0)
3066 return;
3067
3068 output_bytes (copy_start, copy_length);
3069 clean_read_ptr = p;
3070 }
3071
3072 /* Given a pointer to a def_dec_info record which represents some form of
3073 definition of a function (perhaps a real definition, or in lieu of that
3074 perhaps just a declaration with a full prototype) return true if this
3075 function is one which we should avoid converting. Return false
3076 otherwise. */
3077
3078 static int
3079 other_variable_style_function (ansi_header)
3080 const char *ansi_header;
3081 {
3082 #ifdef UNPROTOIZE
3083
3084 /* See if we have a stdarg function, or a function which has stdarg style
3085 parameters or a stdarg style return type. */
3086
3087 return substr (ansi_header, "...") != 0;
3088
3089 #else /* !defined (UNPROTOIZE) */
3090
3091 /* See if we have a varargs function, or a function which has varargs style
3092 parameters or a varargs style return type. */
3093
3094 const char *p;
3095 int len = strlen (varargs_style_indicator);
3096
3097 for (p = ansi_header; p; )
3098 {
3099 const char *candidate;
3100
3101 if ((candidate = substr (p, varargs_style_indicator)) == 0)
3102 return 0;
3103 else
3104 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
3105 return 1;
3106 else
3107 p = candidate + 1;
3108 }
3109 return 0;
3110 #endif /* !defined (UNPROTOIZE) */
3111 }
3112
3113 /* Do the editing operation specifically for a function "declaration". Note
3114 that editing for function "definitions" are handled in a separate routine
3115 below. */
3116
3117 static void
3118 edit_fn_declaration (def_dec_p, clean_text_p)
3119 const def_dec_info *def_dec_p;
3120 const char *volatile clean_text_p;
3121 {
3122 const char *start_formals;
3123 const char *end_formals;
3124 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3125 size_t func_name_len = strlen (function_to_edit);
3126 const char *end_of_fn_name;
3127
3128 #ifndef UNPROTOIZE
3129
3130 const f_list_chain_item *this_f_list_chain_item;
3131 const def_dec_info *definition = def_dec_p->definition;
3132
3133 /* If we are protoizing, and if we found no corresponding definition for
3134 this particular function declaration, then just leave this declaration
3135 exactly as it is. */
3136
3137 if (!definition)
3138 return;
3139
3140 /* If we are protoizing, and if the corresponding definition that we found
3141 for this particular function declaration defined an old style varargs
3142 function, then we want to issue a warning and just leave this function
3143 declaration unconverted. */
3144
3145 if (other_variable_style_function (definition->ansi_decl))
3146 {
3147 if (!quiet_flag)
3148 fprintf (stderr, "%s: %d: warning: varargs function declaration not converted\n",
3149 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3150 def_dec_p->line);
3151 return;
3152 }
3153
3154 #endif /* !defined (UNPROTOIZE) */
3155
3156 /* Setup here to recover from confusing source code detected during this
3157 particular "edit". */
3158
3159 save_pointers ();
3160 if (setjmp (source_confusion_recovery))
3161 {
3162 restore_pointers ();
3163 fprintf (stderr, "%s: declaration of function `%s' not converted\n",
3164 pname, function_to_edit);
3165 return;
3166 }
3167
3168 /* We are editing a function declaration. The line number we did a seek to
3169 contains the comma or semicolon which follows the declaration. Our job
3170 now is to scan backwards looking for the function name. This name *must*
3171 be followed by open paren (ignoring whitespace, of course). We need to
3172 replace everything between that open paren and the corresponding closing
3173 paren. If we are protoizing, we need to insert the prototype-style
3174 formals lists. If we are unprotoizing, we need to just delete everything
3175 between the pairs of opening and closing parens. */
3176
3177 /* First move up to the end of the line. */
3178
3179 while (*clean_text_p != '\n')
3180 check_source (++clean_text_p < clean_text_limit, 0);
3181 clean_text_p--; /* Point to just before the newline character. */
3182
3183 /* Now we can scan backwards for the function name. */
3184
3185 do
3186 {
3187 for (;;)
3188 {
3189 /* Scan leftwards until we find some character which can be
3190 part of an identifier. */
3191
3192 while (!is_id_char (*clean_text_p))
3193 check_source (--clean_text_p > clean_read_ptr, 0);
3194
3195 /* Scan backwards until we find a char that cannot be part of an
3196 identifier. */
3197
3198 while (is_id_char (*clean_text_p))
3199 check_source (--clean_text_p > clean_read_ptr, 0);
3200
3201 /* Having found an "id break", see if the following id is the one
3202 that we are looking for. If so, then exit from this loop. */
3203
3204 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
3205 {
3206 char ch = *(clean_text_p + 1 + func_name_len);
3207
3208 /* Must also check to see that the name in the source text
3209 ends where it should (in order to prevent bogus matches
3210 on similar but longer identifiers. */
3211
3212 if (! is_id_char (ch))
3213 break; /* exit from loop */
3214 }
3215 }
3216
3217 /* We have now found the first perfect match for the function name in
3218 our backward search. This may or may not be the actual function
3219 name at the start of the actual function declaration (i.e. we could
3220 have easily been mislead). We will try to avoid getting fooled too
3221 often by looking forward for the open paren which should follow the
3222 identifier we just found. We ignore whitespace while hunting. If
3223 the next non-whitespace byte we see is *not* an open left paren,
3224 then we must assume that we have been fooled and we start over
3225 again accordingly. Note that there is no guarantee, that even if
3226 we do see the open paren, that we are in the right place.
3227 Programmers do the strangest things sometimes! */
3228
3229 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
3230 start_formals = forward_to_next_token_char (end_of_fn_name);
3231 }
3232 while (*start_formals != '(');
3233
3234 /* start_of_formals now points to the opening left paren which immediately
3235 follows the name of the function. */
3236
3237 /* Note that there may be several formals lists which need to be modified
3238 due to the possibility that the return type of this function is a
3239 pointer-to-function type. If there are several formals lists, we
3240 convert them in left-to-right order here. */
3241
3242 #ifndef UNPROTOIZE
3243 this_f_list_chain_item = definition->f_list_chain;
3244 #endif /* !defined (UNPROTOIZE) */
3245
3246 for (;;)
3247 {
3248 {
3249 int depth;
3250
3251 end_formals = start_formals + 1;
3252 depth = 1;
3253 for (; depth; check_source (++end_formals < clean_text_limit, 0))
3254 {
3255 switch (*end_formals)
3256 {
3257 case '(':
3258 depth++;
3259 break;
3260 case ')':
3261 depth--;
3262 break;
3263 }
3264 }
3265 end_formals--;
3266 }
3267
3268 /* end_formals now points to the closing right paren of the formals
3269 list whose left paren is pointed to by start_formals. */
3270
3271 /* Now, if we are protoizing, we insert the new ANSI-style formals list
3272 attached to the associated definition of this function. If however
3273 we are unprotoizing, then we simply delete any formals list which
3274 may be present. */
3275
3276 output_up_to (start_formals);
3277 #ifndef UNPROTOIZE
3278 if (this_f_list_chain_item)
3279 {
3280 output_string (this_f_list_chain_item->formals_list);
3281 this_f_list_chain_item = this_f_list_chain_item->chain_next;
3282 }
3283 else
3284 {
3285 if (!quiet_flag)
3286 fprintf (stderr, "%s: warning: too many parameter lists in declaration of `%s'\n",
3287 pname, def_dec_p->hash_entry->symbol);
3288 check_source (0, end_formals); /* leave the declaration intact */
3289 }
3290 #endif /* !defined (UNPROTOIZE) */
3291 clean_read_ptr = end_formals - 1;
3292
3293 /* Now see if it looks like there may be another formals list associated
3294 with the function declaration that we are converting (following the
3295 formals list that we just converted. */
3296
3297 {
3298 const char *another_r_paren = forward_to_next_token_char (end_formals);
3299
3300 if ((*another_r_paren != ')')
3301 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3302 {
3303 #ifndef UNPROTOIZE
3304 if (this_f_list_chain_item)
3305 {
3306 if (!quiet_flag)
3307 fprintf (stderr, "\n%s: warning: too few parameter lists in declaration of `%s'\n",
3308 pname, def_dec_p->hash_entry->symbol);
3309 check_source (0, start_formals); /* leave the decl intact */
3310 }
3311 #endif /* !defined (UNPROTOIZE) */
3312 break;
3313
3314 }
3315 }
3316
3317 /* There does appear to be yet another formals list, so loop around
3318 again, and convert it also. */
3319 }
3320 }
3321
3322 /* Edit a whole group of formals lists, starting with the rightmost one
3323 from some set of formals lists. This routine is called once (from the
3324 outside) for each function declaration which is converted. It is
3325 recursive however, and it calls itself once for each remaining formal
3326 list that lies to the left of the one it was originally called to work
3327 on. Thus, a whole set gets done in right-to-left order.
3328
3329 This routine returns non-zero if it thinks that it should not be trying
3330 to convert this particular function definition (because the name of the
3331 function doesn't match the one expected). */
3332
3333 static int
3334 edit_formals_lists (end_formals, f_list_count, def_dec_p)
3335 const char *end_formals;
3336 unsigned int f_list_count;
3337 const def_dec_info *def_dec_p;
3338 {
3339 const char *start_formals;
3340 int depth;
3341
3342 start_formals = end_formals - 1;
3343 depth = 1;
3344 for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3345 {
3346 switch (*start_formals)
3347 {
3348 case '(':
3349 depth--;
3350 break;
3351 case ')':
3352 depth++;
3353 break;
3354 }
3355 }
3356 start_formals++;
3357
3358 /* start_formals now points to the opening left paren of the formals list. */
3359
3360 f_list_count--;
3361
3362 if (f_list_count)
3363 {
3364 const char *next_end;
3365
3366 /* There should be more formal lists to the left of here. */
3367
3368 next_end = start_formals - 1;
3369 check_source (next_end > clean_read_ptr, 0);
3370 while (isspace (*next_end))
3371 check_source (--next_end > clean_read_ptr, 0);
3372 check_source (*next_end == ')', next_end);
3373 check_source (--next_end > clean_read_ptr, 0);
3374 check_source (*next_end == ')', next_end);
3375 if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3376 return 1;
3377 }
3378
3379 /* Check that the function name in the header we are working on is the same
3380 as the one we would expect to find. If not, issue a warning and return
3381 non-zero. */
3382
3383 if (f_list_count == 0)
3384 {
3385 const char *expected = def_dec_p->hash_entry->symbol;
3386 const char *func_name_start;
3387 const char *func_name_limit;
3388 size_t func_name_len;
3389
3390 for (func_name_limit = start_formals-1; isspace (*func_name_limit); )
3391 check_source (--func_name_limit > clean_read_ptr, 0);
3392
3393 for (func_name_start = func_name_limit++;
3394 is_id_char (*func_name_start);
3395 func_name_start--)
3396 check_source (func_name_start > clean_read_ptr, 0);
3397 func_name_start++;
3398 func_name_len = func_name_limit - func_name_start;
3399 if (func_name_len == 0)
3400 check_source (0, func_name_start);
3401 if (func_name_len != strlen (expected)
3402 || strncmp (func_name_start, expected, func_name_len))
3403 {
3404 fprintf (stderr, "%s: %d: warning: found `%s' but expected `%s'\n",
3405 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3406 identify_lineno (func_name_start),
3407 dupnstr (func_name_start, func_name_len),
3408 expected);
3409 return 1;
3410 }
3411 }
3412
3413 output_up_to (start_formals);
3414
3415 #ifdef UNPROTOIZE
3416 if (f_list_count == 0)
3417 output_string (def_dec_p->formal_names);
3418 #else /* !defined (UNPROTOIZE) */
3419 {
3420 unsigned f_list_depth;
3421 const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3422
3423 /* At this point, the current value of f_list count says how many
3424 links we have to follow through the f_list_chain to get to the
3425 particular formals list that we need to output next. */
3426
3427 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3428 flci_p = flci_p->chain_next;
3429 output_string (flci_p->formals_list);
3430 }
3431 #endif /* !defined (UNPROTOIZE) */
3432
3433 clean_read_ptr = end_formals - 1;
3434 return 0;
3435 }
3436
3437 /* Given a pointer to a byte in the clean text buffer which points to the
3438 beginning of a line that contains a "follower" token for a function
3439 definition header, do whatever is necessary to find the right closing
3440 paren for the rightmost formals list of the function definition header.
3441 */
3442
3443 static const char *
3444 find_rightmost_formals_list (clean_text_p)
3445 const char *clean_text_p;
3446 {
3447 const char *end_formals;
3448
3449 /* We are editing a function definition. The line number we did a seek
3450 to contains the first token which immediately follows the entire set of
3451 formals lists which are part of this particular function definition
3452 header.
3453
3454 Our job now is to scan leftwards in the clean text looking for the
3455 right-paren which is at the end of the function header's rightmost
3456 formals list.
3457
3458 If we ignore whitespace, this right paren should be the first one we
3459 see which is (ignoring whitespace) immediately followed either by the
3460 open curly-brace beginning the function body or by an alphabetic
3461 character (in the case where the function definition is in old (K&R)
3462 style and there are some declarations of formal parameters). */
3463
3464 /* It is possible that the right paren we are looking for is on the
3465 current line (together with its following token). Just in case that
3466 might be true, we start out here by skipping down to the right end of
3467 the current line before starting our scan. */
3468
3469 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3470 continue;
3471 end_formals--;
3472
3473 #ifdef UNPROTOIZE
3474
3475 /* Now scan backwards while looking for the right end of the rightmost
3476 formals list associated with this function definition. */
3477
3478 {
3479 char ch;
3480 const char *l_brace_p;
3481
3482 /* Look leftward and try to find a right-paren. */
3483
3484 while (*end_formals != ')')
3485 {
3486 if (isspace (*end_formals))
3487 while (isspace (*end_formals))
3488 check_source (--end_formals > clean_read_ptr, 0);
3489 else
3490 check_source (--end_formals > clean_read_ptr, 0);
3491 }
3492
3493 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3494 /* Since we are unprotoizing an ANSI-style (prototyped) function
3495 definition, there had better not be anything (except whitespace)
3496 between the end of the ANSI formals list and the beginning of the
3497 function body (i.e. the '{'). */
3498
3499 check_source (ch == '{', l_brace_p);
3500 }
3501
3502 #else /* !defined (UNPROTOIZE) */
3503
3504 /* Now scan backwards while looking for the right end of the rightmost
3505 formals list associated with this function definition. */
3506
3507 while (1)
3508 {
3509 char ch;
3510 const char *l_brace_p;
3511
3512 /* Look leftward and try to find a right-paren. */
3513
3514 while (*end_formals != ')')
3515 {
3516 if (isspace (*end_formals))
3517 while (isspace (*end_formals))
3518 check_source (--end_formals > clean_read_ptr, 0);
3519 else
3520 check_source (--end_formals > clean_read_ptr, 0);
3521 }
3522
3523 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3524
3525 /* Since it is possible that we found a right paren before the starting
3526 '{' of the body which IS NOT the one at the end of the real K&R
3527 formals list (say for instance, we found one embedded inside one of
3528 the old K&R formal parameter declarations) we have to check to be
3529 sure that this is in fact the right paren that we were looking for.
3530
3531 The one we were looking for *must* be followed by either a '{' or
3532 by an alphabetic character, while others *cannot* validly be followed
3533 by such characters. */
3534
3535 if ((ch == '{') || isalpha (ch))
3536 break;
3537
3538 /* At this point, we have found a right paren, but we know that it is
3539 not the one we were looking for, so backup one character and keep
3540 looking. */
3541
3542 check_source (--end_formals > clean_read_ptr, 0);
3543 }
3544
3545 #endif /* !defined (UNPROTOIZE) */
3546
3547 return end_formals;
3548 }
3549
3550 #ifndef UNPROTOIZE
3551
3552 /* Insert into the output file a totally new declaration for a function
3553 which (up until now) was being called from within the current block
3554 without having been declared at any point such that the declaration
3555 was visible (i.e. in scope) at the point of the call.
3556
3557 We need to add in explicit declarations for all such function calls
3558 in order to get the full benefit of prototype-based function call
3559 parameter type checking. */
3560
3561 static void
3562 add_local_decl (def_dec_p, clean_text_p)
3563 const def_dec_info *def_dec_p;
3564 const char *clean_text_p;
3565 {
3566 const char *start_of_block;
3567 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3568
3569 /* Don't insert new local explicit declarations unless explicitly requested
3570 to do so. */
3571
3572 if (!local_flag)
3573 return;
3574
3575 /* Setup here to recover from confusing source code detected during this
3576 particular "edit". */
3577
3578 save_pointers ();
3579 if (setjmp (source_confusion_recovery))
3580 {
3581 restore_pointers ();
3582 fprintf (stderr, "%s: local declaration for function `%s' not inserted\n",
3583 pname, function_to_edit);
3584 return;
3585 }
3586
3587 /* We have already done a seek to the start of the line which should
3588 contain *the* open curly brace which begins the block in which we need
3589 to insert an explicit function declaration (to replace the implicit one).
3590
3591 Now we scan that line, starting from the left, until we find the
3592 open curly brace we are looking for. Note that there may actually be
3593 multiple open curly braces on the given line, but we will be happy
3594 with the leftmost one no matter what. */
3595
3596 start_of_block = clean_text_p;
3597 while (*start_of_block != '{' && *start_of_block != '\n')
3598 check_source (++start_of_block < clean_text_limit, 0);
3599
3600 /* Note that the line from the original source could possibly
3601 contain *no* open curly braces! This happens if the line contains
3602 a macro call which expands into a chunk of text which includes a
3603 block (and that block's associated open and close curly braces).
3604 In cases like this, we give up, issue a warning, and do nothing. */
3605
3606 if (*start_of_block != '{')
3607 {
3608 if (!quiet_flag)
3609 fprintf (stderr,
3610 "\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
3611 def_dec_p->file->hash_entry->symbol, def_dec_p->line,
3612 def_dec_p->hash_entry->symbol);
3613 return;
3614 }
3615
3616 /* Figure out what a nice (pretty) indentation would be for the new
3617 declaration we are adding. In order to do this, we must scan forward
3618 from the '{' until we find the first line which starts with some
3619 non-whitespace characters (i.e. real "token" material). */
3620
3621 {
3622 const char *ep = forward_to_next_token_char (start_of_block) - 1;
3623 const char *sp;
3624
3625 /* Now we have ep pointing at the rightmost byte of some existing indent
3626 stuff. At least that is the hope.
3627
3628 We can now just scan backwards and find the left end of the existing
3629 indentation string, and then copy it to the output buffer. */
3630
3631 for (sp = ep; isspace (*sp) && *sp != '\n'; sp--)
3632 continue;
3633
3634 /* Now write out the open { which began this block, and any following
3635 trash up to and including the last byte of the existing indent that
3636 we just found. */
3637
3638 output_up_to (ep);
3639
3640 /* Now we go ahead and insert the new declaration at this point.
3641
3642 If the definition of the given function is in the same file that we
3643 are currently editing, and if its full ANSI declaration normally
3644 would start with the keyword `extern', suppress the `extern'. */
3645
3646 {
3647 const char *decl = def_dec_p->definition->ansi_decl;
3648
3649 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
3650 decl += 7;
3651 output_string (decl);
3652 }
3653
3654 /* Finally, write out a new indent string, just like the preceding one
3655 that we found. This will typically include a newline as the first
3656 character of the indent string. */
3657
3658 output_bytes (sp, (size_t) (ep - sp) + 1);
3659 }
3660 }
3661
3662 /* Given a pointer to a file_info record, and a pointer to the beginning
3663 of a line (in the clean text buffer) which is assumed to contain the
3664 first "follower" token for the first function definition header in the
3665 given file, find a good place to insert some new global function
3666 declarations (which will replace scattered and imprecise implicit ones)
3667 and then insert the new explicit declaration at that point in the file. */
3668
3669 static void
3670 add_global_decls (file_p, clean_text_p)
3671 const file_info *file_p;
3672 const char *clean_text_p;
3673 {
3674 const def_dec_info *dd_p;
3675 const char *scan_p;
3676
3677 /* Setup here to recover from confusing source code detected during this
3678 particular "edit". */
3679
3680 save_pointers ();
3681 if (setjmp (source_confusion_recovery))
3682 {
3683 restore_pointers ();
3684 fprintf (stderr, "%s: global declarations for file `%s' not inserted\n",
3685 pname, shortpath (NULL, file_p->hash_entry->symbol));
3686 return;
3687 }
3688
3689 /* Start by finding a good location for adding the new explicit function
3690 declarations. To do this, we scan backwards, ignoring whitespace
3691 and comments and other junk until we find either a semicolon, or until
3692 we hit the beginning of the file. */
3693
3694 scan_p = find_rightmost_formals_list (clean_text_p);
3695 for (;; --scan_p)
3696 {
3697 if (scan_p < clean_text_base)
3698 break;
3699 check_source (scan_p > clean_read_ptr, 0);
3700 if (*scan_p == ';')
3701 break;
3702 }
3703
3704 /* scan_p now points either to a semicolon, or to just before the start
3705 of the whole file. */
3706
3707 /* Now scan forward for the first non-whitespace character. In theory,
3708 this should be the first character of the following function definition
3709 header. We will put in the added declarations just prior to that. */
3710
3711 scan_p++;
3712 while (isspace (*scan_p))
3713 scan_p++;
3714 scan_p--;
3715
3716 output_up_to (scan_p);
3717
3718 /* Now write out full prototypes for all of the things that had been
3719 implicitly declared in this file (but only those for which we were
3720 actually able to find unique matching definitions). Avoid duplicates
3721 by marking things that we write out as we go. */
3722
3723 {
3724 int some_decls_added = 0;
3725
3726 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3727 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
3728 {
3729 const char *decl = dd_p->definition->ansi_decl;
3730
3731 /* If the function for which we are inserting a declaration is
3732 actually defined later in the same file, then suppress the
3733 leading `extern' keyword (if there is one). */
3734
3735 if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
3736 decl += 7;
3737
3738 output_string ("\n");
3739 output_string (decl);
3740 some_decls_added = 1;
3741 ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
3742 }
3743 if (some_decls_added)
3744 output_string ("\n\n");
3745 }
3746
3747 /* Unmark all of the definitions that we just marked. */
3748
3749 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3750 if (dd_p->definition)
3751 ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
3752 }
3753
3754 #endif /* !defined (UNPROTOIZE) */
3755
3756 /* Do the editing operation specifically for a function "definition". Note
3757 that editing operations for function "declarations" are handled by a
3758 separate routine above. */
3759
3760 static void
3761 edit_fn_definition (def_dec_p, clean_text_p)
3762 const def_dec_info *def_dec_p;
3763 const char *clean_text_p;
3764 {
3765 const char *end_formals;
3766 const char *function_to_edit = def_dec_p->hash_entry->symbol;
3767
3768 /* Setup here to recover from confusing source code detected during this
3769 particular "edit". */
3770
3771 save_pointers ();
3772 if (setjmp (source_confusion_recovery))
3773 {
3774 restore_pointers ();
3775 fprintf (stderr, "%s: definition of function `%s' not converted\n",
3776 pname, function_to_edit);
3777 return;
3778 }
3779
3780 end_formals = find_rightmost_formals_list (clean_text_p);
3781
3782 /* end_of_formals now points to the closing right paren of the rightmost
3783 formals list which is actually part of the `header' of the function
3784 definition that we are converting. */
3785
3786 /* If the header of this function definition looks like it declares a
3787 function with a variable number of arguments, and if the way it does
3788 that is different from that way we would like it (i.e. varargs vs.
3789 stdarg) then issue a warning and leave the header unconverted. */
3790
3791 if (other_variable_style_function (def_dec_p->ansi_decl))
3792 {
3793 if (!quiet_flag)
3794 fprintf (stderr, "%s: %d: warning: definition of %s not converted\n",
3795 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3796 identify_lineno (end_formals),
3797 other_var_style);
3798 output_up_to (end_formals);
3799 return;
3800 }
3801
3802 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
3803 {
3804 restore_pointers ();
3805 fprintf (stderr, "%s: definition of function `%s' not converted\n",
3806 pname, function_to_edit);
3807 return;
3808 }
3809
3810 /* Have to output the last right paren because this never gets flushed by
3811 edit_formals_list. */
3812
3813 output_up_to (end_formals);
3814
3815 #ifdef UNPROTOIZE
3816 {
3817 const char *decl_p;
3818 const char *semicolon_p;
3819 const char *limit_p;
3820 const char *scan_p;
3821 int had_newlines = 0;
3822
3823 /* Now write out the K&R style formal declarations, one per line. */
3824
3825 decl_p = def_dec_p->formal_decls;
3826 limit_p = decl_p + strlen (decl_p);
3827 for (;decl_p < limit_p; decl_p = semicolon_p + 2)
3828 {
3829 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
3830 continue;
3831 output_string ("\n");
3832 output_string (indent_string);
3833 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
3834 }
3835
3836 /* If there are no newlines between the end of the formals list and the
3837 start of the body, we should insert one now. */
3838
3839 for (scan_p = end_formals+1; *scan_p != '{'; )
3840 {
3841 if (*scan_p == '\n')
3842 {
3843 had_newlines = 1;
3844 break;
3845 }
3846 check_source (++scan_p < clean_text_limit, 0);
3847 }
3848 if (!had_newlines)
3849 output_string ("\n");
3850 }
3851 #else /* !defined (UNPROTOIZE) */
3852 /* If we are protoizing, there may be some flotsam & jetsam (like comments
3853 and preprocessing directives) after the old formals list but before
3854 the following { and we would like to preserve that stuff while effectively
3855 deleting the existing K&R formal parameter declarations. We do so here
3856 in a rather tricky way. Basically, we white out any stuff *except*
3857 the comments/pp-directives in the original text buffer, then, if there
3858 is anything in this area *other* than whitespace, we output it. */
3859 {
3860 const char *end_formals_orig;
3861 const char *start_body;
3862 const char *start_body_orig;
3863 const char *scan;
3864 const char *scan_orig;
3865 int have_flotsam = 0;
3866 int have_newlines = 0;
3867
3868 for (start_body = end_formals + 1; *start_body != '{';)
3869 check_source (++start_body < clean_text_limit, 0);
3870
3871 end_formals_orig = orig_text_base + (end_formals - clean_text_base);
3872 start_body_orig = orig_text_base + (start_body - clean_text_base);
3873 scan = end_formals + 1;
3874 scan_orig = end_formals_orig + 1;
3875 for (; scan < start_body; scan++, scan_orig++)
3876 {
3877 if (*scan == *scan_orig)
3878 {
3879 have_newlines |= (*scan_orig == '\n');
3880 /* Leave identical whitespace alone. */
3881 if (!isspace (*scan_orig))
3882 *((NONCONST char *)scan_orig) = ' '; /* identical - so whiteout */
3883 }
3884 else
3885 have_flotsam = 1;
3886 }
3887 if (have_flotsam)
3888 output_bytes (end_formals_orig + 1,
3889 (size_t) (start_body_orig - end_formals_orig) - 1);
3890 else
3891 if (have_newlines)
3892 output_string ("\n");
3893 else
3894 output_string (" ");
3895 clean_read_ptr = start_body - 1;
3896 }
3897 #endif /* !defined (UNPROTOIZE) */
3898 }
3899
3900 /* Clean up the clean text buffer. Do this by converting comments and
3901 preprocessing directives into spaces. Also convert line continuations
3902 into whitespace. Also, whiteout string and character literals. */
3903
3904 static void
3905 do_cleaning (new_clean_text_base, new_clean_text_limit)
3906 char *new_clean_text_base;
3907 char *new_clean_text_limit;
3908 {
3909 char *scan_p;
3910 int non_whitespace_since_newline = 0;
3911
3912 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
3913 {
3914 switch (*scan_p)
3915 {
3916 case '/': /* Handle comments. */
3917 if (scan_p[1] != '*')
3918 goto regular;
3919 non_whitespace_since_newline = 1;
3920 scan_p[0] = ' ';
3921 scan_p[1] = ' ';
3922 scan_p += 2;
3923 while (scan_p[1] != '/' || scan_p[0] != '*')
3924 {
3925 if (!isspace (*scan_p))
3926 *scan_p = ' ';
3927 if (++scan_p >= new_clean_text_limit)
3928 abort ();
3929 }
3930 *scan_p++ = ' ';
3931 *scan_p = ' ';
3932 break;
3933
3934 case '#': /* Handle pp directives. */
3935 if (non_whitespace_since_newline)
3936 goto regular;
3937 *scan_p = ' ';
3938 while (scan_p[1] != '\n' || scan_p[0] == '\\')
3939 {
3940 if (!isspace (*scan_p))
3941 *scan_p = ' ';
3942 if (++scan_p >= new_clean_text_limit)
3943 abort ();
3944 }
3945 *scan_p++ = ' ';
3946 break;
3947
3948 case '\'': /* Handle character literals. */
3949 non_whitespace_since_newline = 1;
3950 while (scan_p[1] != '\'' || scan_p[0] == '\\')
3951 {
3952 if (scan_p[0] == '\\' && !isspace (scan_p[1]))
3953 scan_p[1] = ' ';
3954 if (!isspace (*scan_p))
3955 *scan_p = ' ';
3956 if (++scan_p >= new_clean_text_limit)
3957 abort ();
3958 }
3959 *scan_p++ = ' ';
3960 break;
3961
3962 case '"': /* Handle string literals. */
3963 non_whitespace_since_newline = 1;
3964 while (scan_p[1] != '"' || scan_p[0] == '\\')
3965 {
3966 if (scan_p[0] == '\\' && !isspace (scan_p[1]))
3967 scan_p[1] = ' ';
3968 if (!isspace (*scan_p))
3969 *scan_p = ' ';
3970 if (++scan_p >= new_clean_text_limit)
3971 abort ();
3972 }
3973 *scan_p++ = ' ';
3974 break;
3975
3976 case '\\': /* Handle line continuations. */
3977 if (scan_p[1] != '\n')
3978 goto regular;
3979 *scan_p = ' ';
3980 break;
3981
3982 case '\n':
3983 non_whitespace_since_newline = 0; /* Reset. */
3984 break;
3985
3986 case ' ':
3987 case '\v':
3988 case '\t':
3989 case '\r':
3990 case '\f':
3991 case '\b':
3992 break; /* Whitespace characters. */
3993
3994 default:
3995 regular:
3996 non_whitespace_since_newline = 1;
3997 break;
3998 }
3999 }
4000 }
4001
4002 /* Given a pointer to the closing right parenthesis for a particular formals
4003 list (in the clean text buffer) find the corresponding left parenthesis
4004 and return a pointer to it. */
4005
4006 static const char *
4007 careful_find_l_paren (p)
4008 const char *p;
4009 {
4010 const char *q;
4011 int paren_depth;
4012
4013 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
4014 {
4015 switch (*q)
4016 {
4017 case ')':
4018 paren_depth++;
4019 break;
4020 case '(':
4021 paren_depth--;
4022 break;
4023 }
4024 }
4025 return ++q;
4026 }
4027
4028 /* Scan the clean text buffer for cases of function definitions that we
4029 don't really know about because they were preprocessed out when the
4030 aux info files were created.
4031
4032 In this version of protoize/unprotoize we just give a warning for each
4033 one found. A later version may be able to at least unprotoize such
4034 missed items.
4035
4036 Note that we may easily find all function definitions simply by
4037 looking for places where there is a left paren which is (ignoring
4038 whitespace) immediately followed by either a left-brace or by an
4039 upper or lower case letter. Whenever we find this combination, we
4040 have also found a function definition header.
4041
4042 Finding function *declarations* using syntactic clues is much harder.
4043 I will probably try to do this in a later version though. */
4044
4045 static void
4046 scan_for_missed_items (file_p)
4047 const file_info *file_p;
4048 {
4049 static const char *scan_p;
4050 const char *limit = clean_text_limit - 3;
4051 static const char *backup_limit;
4052
4053 backup_limit = clean_text_base - 1;
4054
4055 for (scan_p = clean_text_base; scan_p < limit; scan_p++)
4056 {
4057 if (*scan_p == ')')
4058 {
4059 static const char *last_r_paren;
4060 const char *ahead_p;
4061
4062 last_r_paren = scan_p;
4063
4064 for (ahead_p = scan_p + 1; isspace (*ahead_p); )
4065 check_source (++ahead_p < limit, limit);
4066
4067 scan_p = ahead_p - 1;
4068
4069 if (isalpha (*ahead_p) || *ahead_p == '{')
4070 {
4071 const char *last_l_paren;
4072 const int lineno = identify_lineno (ahead_p);
4073
4074 if (setjmp (source_confusion_recovery))
4075 continue;
4076
4077 /* We know we have a function definition header. Now skip
4078 leftwards over all of its associated formals lists. */
4079
4080 do
4081 {
4082 last_l_paren = careful_find_l_paren (last_r_paren);
4083 for (last_r_paren = last_l_paren-1; isspace (*last_r_paren); )
4084 check_source (--last_r_paren >= backup_limit, backup_limit);
4085 }
4086 while (*last_r_paren == ')');
4087
4088 if (is_id_char (*last_r_paren))
4089 {
4090 const char *id_limit = last_r_paren + 1;
4091 const char *id_start;
4092 size_t id_length;
4093 const def_dec_info *dd_p;
4094
4095 for (id_start = id_limit-1; is_id_char (*id_start); )
4096 check_source (--id_start >= backup_limit, backup_limit);
4097 id_start++;
4098 backup_limit = id_start;
4099 if ((id_length = (size_t) (id_limit - id_start)) == 0)
4100 goto not_missed;
4101
4102 {
4103 char *func_name = (char *) alloca (id_length + 1);
4104 static const char * const stmt_keywords[]
4105 = { "if", "else", "do", "while", "for", "switch", "case", "return", 0 };
4106 const char * const *stmt_keyword;
4107
4108 strncpy (func_name, id_start, id_length);
4109 func_name[id_length] = '\0';
4110
4111 /* We must check here to see if we are actually looking at
4112 a statement rather than an actual function call. */
4113
4114 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
4115 if (!strcmp (func_name, *stmt_keyword))
4116 goto not_missed;
4117
4118 #if 0
4119 fprintf (stderr, "%s: found definition of `%s' at %s(%d)\n",
4120 pname,
4121 func_name,
4122 shortpath (NULL, file_p->hash_entry->symbol),
4123 identify_lineno (id_start));
4124 #endif /* 0 */
4125 /* We really should check for a match of the function name
4126 here also, but why bother. */
4127
4128 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
4129 if (dd_p->is_func_def && dd_p->line == lineno)
4130 goto not_missed;
4131
4132 /* If we make it here, then we did not know about this
4133 function definition. */
4134
4135 fprintf (stderr, "%s: %d: warning: `%s' excluded by preprocessing\n",
4136 shortpath (NULL, file_p->hash_entry->symbol),
4137 identify_lineno (id_start), func_name);
4138 fprintf (stderr, "%s: function definition not converted\n",
4139 pname);
4140 }
4141 not_missed: ;
4142 }
4143 }
4144 }
4145 }
4146 }
4147
4148 /* Do all editing operations for a single source file (either a "base" file
4149 or an "include" file). To do this we read the file into memory, keep a
4150 virgin copy there, make another cleaned in-core copy of the original file
4151 (i.e. one in which all of the comments and preprocessing directives have
4152 been replaced with whitespace), then use these two in-core copies of the
4153 file to make a new edited in-core copy of the file. Finally, rename the
4154 original file (as a way of saving it), and then write the edited version
4155 of the file from core to a disk file of the same name as the original.
4156
4157 Note that the trick of making a copy of the original sans comments &
4158 preprocessing directives make the editing a whole lot easier. */
4159
4160 static void
4161 edit_file (hp)
4162 const hash_table_entry *hp;
4163 {
4164 struct stat stat_buf;
4165 const file_info *file_p = hp->fip;
4166 char *new_orig_text_base;
4167 char *new_orig_text_limit;
4168 char *new_clean_text_base;
4169 char *new_clean_text_limit;
4170 size_t orig_size;
4171 size_t repl_size;
4172 int first_definition_in_file;
4173
4174 /* If we are not supposed to be converting this file, or if there is
4175 nothing in there which needs converting, just skip this file. */
4176
4177 if (!needs_to_be_converted (file_p))
4178 return;
4179
4180 convert_filename = file_p->hash_entry->symbol;
4181
4182 /* Convert a file if it is in a directory where we want conversion
4183 and the file is not excluded. */
4184
4185 if (!directory_specified_p (convert_filename)
4186 || file_excluded_p (convert_filename))
4187 {
4188 if (!quiet_flag
4189 #ifdef UNPROTOIZE
4190 /* Don't even mention "system" include files unless we are
4191 protoizing. If we are protoizing, we mention these as a
4192 gentle way of prodding the user to convert his "system"
4193 include files to prototype format. */
4194 && !in_system_include_dir (convert_filename)
4195 #endif /* defined (UNPROTOIZE) */
4196 )
4197 fprintf (stderr, "%s: `%s' not converted\n",
4198 pname, shortpath (NULL, convert_filename));
4199 return;
4200 }
4201
4202 /* Let the user know what we are up to. */
4203
4204 if (nochange_flag)
4205 fprintf (stderr, "%s: would convert file `%s'\n",
4206 pname, shortpath (NULL, convert_filename));
4207 else
4208 fprintf (stderr, "%s: converting file `%s'\n",
4209 pname, shortpath (NULL, convert_filename));
4210 fflush (stderr);
4211
4212 /* Find out the size (in bytes) of the original file. */
4213
4214 /* The cast avoids an erroneous warning on AIX. */
4215 if (my_stat ((char *)convert_filename, &stat_buf) == -1)
4216 {
4217 fprintf (stderr, "%s: can't get status for file `%s': %s\n",
4218 pname, shortpath (NULL, convert_filename), my_strerror(errno));
4219 return;
4220 }
4221 orig_size = stat_buf.st_size;
4222
4223 /* Allocate a buffer to hold the original text. */
4224
4225 orig_text_base = new_orig_text_base = (char *) xmalloc (orig_size + 2);
4226 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
4227
4228 /* Allocate a buffer to hold the cleaned-up version of the original text. */
4229
4230 clean_text_base = new_clean_text_base = (char *) xmalloc (orig_size + 2);
4231 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
4232 clean_read_ptr = clean_text_base - 1;
4233
4234 /* Allocate a buffer that will hopefully be large enough to hold the entire
4235 converted output text. As an initial guess for the maximum size of the
4236 output buffer, use 125% of the size of the original + some extra. This
4237 buffer can be expanded later as needed. */
4238
4239 repl_size = orig_size + (orig_size >> 2) + 4096;
4240 repl_text_base = (char *) xmalloc (repl_size + 2);
4241 repl_text_limit = repl_text_base + repl_size - 1;
4242 repl_write_ptr = repl_text_base - 1;
4243
4244 {
4245 int input_file;
4246
4247 /* Open the file to be converted in READ ONLY mode. */
4248
4249 if ((input_file = my_open (convert_filename, O_RDONLY, 0444)) == -1)
4250 {
4251 fprintf (stderr, "%s: can't open file `%s' for reading: %s\n",
4252 pname, shortpath (NULL, convert_filename),
4253 my_strerror(errno));
4254 return;
4255 }
4256
4257 /* Read the entire original source text file into the original text buffer
4258 in one swell fwoop. Then figure out where the end of the text is and
4259 make sure that it ends with a newline followed by a null. */
4260
4261 if (safe_read (input_file, new_orig_text_base, orig_size) != orig_size)
4262 {
4263 close (input_file);
4264 fprintf (stderr, "\n%s: error reading input file `%s': %s\n",
4265 pname, shortpath (NULL, convert_filename),
4266 my_strerror(errno));
4267 return;
4268 }
4269
4270 close (input_file);
4271 }
4272
4273 if (orig_size == 0 || orig_text_limit[-1] != '\n')
4274 {
4275 *new_orig_text_limit++ = '\n';
4276 orig_text_limit++;
4277 }
4278
4279 /* Create the cleaned up copy of the original text. */
4280
4281 memcpy (new_clean_text_base, orig_text_base,
4282 (size_t) (orig_text_limit - orig_text_base));
4283 do_cleaning (new_clean_text_base, new_clean_text_limit);
4284
4285 #if 0
4286 {
4287 int clean_file;
4288 size_t clean_size = orig_text_limit - orig_text_base;
4289 char *const clean_filename = (char *) alloca (strlen (convert_filename) + 6 + 1);
4290
4291 /* Open (and create) the clean file. */
4292
4293 strcpy (clean_filename, convert_filename);
4294 strcat (clean_filename, ".clean");
4295 if ((clean_file = creat (clean_filename, 0666)) == -1)
4296 {
4297 fprintf (stderr, "%s: can't create/open clean file `%s': %s\n",
4298 pname, shortpath (NULL, clean_filename),
4299 my_strerror(errno));
4300 return;
4301 }
4302
4303 /* Write the clean file. */
4304
4305 safe_write (clean_file, new_clean_text_base, clean_size, clean_filename);
4306
4307 close (clean_file);
4308 }
4309 #endif /* 0 */
4310
4311 /* Do a simplified scan of the input looking for things that were not
4312 mentioned in the aux info files because of the fact that they were
4313 in a region of the source which was preprocessed-out (via #if or
4314 via #ifdef). */
4315
4316 scan_for_missed_items (file_p);
4317
4318 /* Setup to do line-oriented forward seeking in the clean text buffer. */
4319
4320 last_known_line_number = 1;
4321 last_known_line_start = clean_text_base;
4322
4323 /* Now get down to business and make all of the necessary edits. */
4324
4325 {
4326 const def_dec_info *def_dec_p;
4327
4328 first_definition_in_file = 1;
4329 def_dec_p = file_p->defs_decs;
4330 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
4331 {
4332 const char *clean_text_p = seek_to_line (def_dec_p->line);
4333
4334 /* clean_text_p now points to the first character of the line which
4335 contains the `terminator' for the declaration or definition that
4336 we are about to process. */
4337
4338 #ifndef UNPROTOIZE
4339
4340 if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
4341 {
4342 add_global_decls (def_dec_p->file, clean_text_p);
4343 first_definition_in_file = 0;
4344 }
4345
4346 /* Don't edit this item if it is already in prototype format or if it
4347 is a function declaration and we have found no corresponding
4348 definition. */
4349
4350 if (def_dec_p->prototyped
4351 || (!def_dec_p->is_func_def && !def_dec_p->definition))
4352 continue;
4353
4354 #endif /* !defined (UNPROTOIZE) */
4355
4356 if (def_dec_p->is_func_def)
4357 edit_fn_definition (def_dec_p, clean_text_p);
4358 else
4359 #ifndef UNPROTOIZE
4360 if (def_dec_p->is_implicit)
4361 add_local_decl (def_dec_p, clean_text_p);
4362 else
4363 #endif /* !defined (UNPROTOIZE) */
4364 edit_fn_declaration (def_dec_p, clean_text_p);
4365 }
4366 }
4367
4368 /* Finalize things. Output the last trailing part of the original text. */
4369
4370 output_up_to (clean_text_limit - 1);
4371
4372 /* If this is just a test run, stop now and just deallocate the buffers. */
4373
4374 if (nochange_flag)
4375 {
4376 free (new_orig_text_base);
4377 free (new_clean_text_base);
4378 free (repl_text_base);
4379 return;
4380 }
4381
4382 /* Change the name of the original input file. This is just a quick way of
4383 saving the original file. */
4384
4385 if (!nosave_flag)
4386 {
4387 char *new_filename =
4388 (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
4389
4390 strcpy (new_filename, convert_filename);
4391 strcat (new_filename, save_suffix);
4392 if (my_link (convert_filename, new_filename) == -1)
4393 {
4394 if (errno == EEXIST)
4395 {
4396 if (!quiet_flag)
4397 fprintf (stderr, "%s: warning: file `%s' already saved in `%s'\n",
4398 pname,
4399 shortpath (NULL, convert_filename),
4400 shortpath (NULL, new_filename));
4401 }
4402 else
4403 {
4404 fprintf (stderr, "%s: can't link file `%s' to `%s': %s\n",
4405 pname,
4406 shortpath (NULL, convert_filename),
4407 shortpath (NULL, new_filename),
4408 my_strerror(errno));
4409 return;
4410 }
4411 }
4412 }
4413
4414 if (my_unlink (convert_filename) == -1)
4415 {
4416 fprintf (stderr, "%s: can't delete file `%s': %s\n",
4417 pname, shortpath (NULL, convert_filename), my_strerror(errno));
4418 return;
4419 }
4420
4421 {
4422 int output_file;
4423
4424 /* Open (and create) the output file. */
4425
4426 if ((output_file = creat (convert_filename, 0666)) == -1)
4427 {
4428 fprintf (stderr, "%s: can't create/open output file `%s': %s\n",
4429 pname, shortpath (NULL, convert_filename),
4430 my_strerror(errno));
4431 return;
4432 }
4433
4434 /* Write the output file. */
4435
4436 {
4437 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
4438
4439 safe_write (output_file, repl_text_base, out_size, convert_filename);
4440 }
4441
4442 close (output_file);
4443 }
4444
4445 /* Deallocate the conversion buffers. */
4446
4447 free (new_orig_text_base);
4448 free (new_clean_text_base);
4449 free (repl_text_base);
4450
4451 /* Change the mode of the output file to match the original file. */
4452
4453 /* The cast avoids an erroneous warning on AIX. */
4454 if (my_chmod ((char *)convert_filename, stat_buf.st_mode) == -1)
4455 fprintf (stderr, "%s: can't change mode of file `%s': %s\n",
4456 pname, shortpath (NULL, convert_filename), my_strerror(errno));
4457
4458 /* Note: We would try to change the owner and group of the output file
4459 to match those of the input file here, except that may not be a good
4460 thing to do because it might be misleading. Also, it might not even
4461 be possible to do that (on BSD systems with quotas for instance). */
4462 }
4463
4464 /* Do all of the individual steps needed to do the protoization (or
4465 unprotoization) of the files referenced in the aux_info files given
4466 in the command line. */
4467
4468 static void
4469 do_processing ()
4470 {
4471 const char * const *base_pp;
4472 const char * const * const end_pps
4473 = &base_source_filenames[n_base_source_files];
4474
4475 #ifndef UNPROTOIZE
4476 int syscalls_len;
4477 #endif /* !defined (UNPROTOIZE) */
4478
4479 /* One-by-one, check (and create if necessary), open, and read all of the
4480 stuff in each aux_info file. After reading each aux_info file, the
4481 aux_info_file just read will be automatically deleted unless the
4482 keep_flag is set. */
4483
4484 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
4485 process_aux_info_file (*base_pp, keep_flag, 0);
4486
4487 #ifndef UNPROTOIZE
4488
4489 /* Also open and read the special SYSCALLS.c aux_info file which gives us
4490 the prototypes for all of the standard system-supplied functions. */
4491
4492 if (nondefault_syscalls_dir)
4493 {
4494 syscalls_absolute_filename
4495 = (char *) xmalloc (strlen (nondefault_syscalls_dir)
4496 + sizeof (syscalls_filename) + 1);
4497 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
4498 }
4499 else
4500 {
4501 syscalls_absolute_filename
4502 = (char *) xmalloc (strlen (default_syscalls_dir)
4503 + sizeof (syscalls_filename) + 1);
4504 strcpy (syscalls_absolute_filename, default_syscalls_dir);
4505 }
4506
4507 syscalls_len = strlen (syscalls_absolute_filename);
4508 if (*(syscalls_absolute_filename + syscalls_len - 1) != '/')
4509 {
4510 *(syscalls_absolute_filename + syscalls_len++) = '/';
4511 *(syscalls_absolute_filename + syscalls_len) = '\0';
4512 }
4513 strcat (syscalls_absolute_filename, syscalls_filename);
4514
4515 /* Call process_aux_info_file in such a way that it does not try to
4516 delete the SYSCALLS aux_info file. */
4517
4518 process_aux_info_file (syscalls_absolute_filename, 1, 1);
4519
4520 #endif /* !defined (UNPROTOIZE) */
4521
4522 /* When we first read in all of the information from the aux_info files
4523 we saved in it descending line number order, because that was likely to
4524 be faster. Now however, we want the chains of def & dec records to
4525 appear in ascending line number order as we get further away from the
4526 file_info record that they hang from. The following line causes all of
4527 these lists to be rearranged into ascending line number order. */
4528
4529 visit_each_hash_node (filename_primary, reverse_def_dec_list);
4530
4531 #ifndef UNPROTOIZE
4532
4533 /* Now do the "real" work. The following line causes each declaration record
4534 to be "visited". For each of these nodes, an attempt is made to match
4535 up the function declaration with a corresponding function definition,
4536 which should have a full prototype-format formals list with it. Once
4537 these match-ups are made, the conversion of the function declarations
4538 to prototype format can be made. */
4539
4540 visit_each_hash_node (function_name_primary, connect_defs_and_decs);
4541
4542 #endif /* !defined (UNPROTOIZE) */
4543
4544 /* Now convert each file that can be converted (and needs to be). */
4545
4546 visit_each_hash_node (filename_primary, edit_file);
4547
4548 #ifndef UNPROTOIZE
4549
4550 /* If we are working in cplusplus mode, try to rename all .c files to .C
4551 files. Don't panic if some of the renames don't work. */
4552
4553 if (cplusplus_flag && !nochange_flag)
4554 visit_each_hash_node (filename_primary, rename_c_file);
4555
4556 #endif /* !defined (UNPROTOIZE) */
4557 }
4558 \f
4559 static struct option longopts[] =
4560 {
4561 {"version", 0, 0, 'V'},
4562 {"file_name", 0, 0, 'p'},
4563 {"quiet", 0, 0, 'q'},
4564 {"silent", 0, 0, 'q'},
4565 {"force", 0, 0, 'f'},
4566 {"keep", 0, 0, 'k'},
4567 {"nosave", 0, 0, 'N'},
4568 {"nochange", 0, 0, 'n'},
4569 {"compiler-options", 1, 0, 'c'},
4570 {"exclude", 1, 0, 'x'},
4571 {"directory", 1, 0, 'd'},
4572 #ifdef UNPROTOIZE
4573 {"indent", 1, 0, 'i'},
4574 #else
4575 {"local", 0, 0, 'l'},
4576 {"global", 0, 0, 'g'},
4577 {"c++", 0, 0, 'C'},
4578 {"syscalls-dir", 1, 0, 'B'},
4579 #endif
4580 {0, 0, 0, 0}
4581 };
4582
4583 int
4584 main (argc, argv)
4585 int argc;
4586 char **const argv;
4587 {
4588 int longind;
4589 int c;
4590 const char *params = "";
4591
4592 pname = rindex (argv[0], '/');
4593 pname = pname ? pname+1 : argv[0];
4594
4595 cwd_buffer = getpwd ();
4596 if (!cwd_buffer)
4597 {
4598 fprintf (stderr, "%s: cannot get working directory: %s\n",
4599 pname, my_strerror(errno));
4600 exit (1);
4601 }
4602
4603 /* By default, convert the files in the current directory. */
4604 directory_list = string_list_cons (cwd_buffer, NULL);
4605
4606 while ((c = getopt_long (argc, argv,
4607 #ifdef UNPROTOIZE
4608 "c:d:i:knNp:qvVx:",
4609 #else
4610 "B:c:Cd:gklnNp:qvVx:",
4611 #endif
4612 longopts, &longind)) != EOF)
4613 {
4614 if (c == 0) /* Long option. */
4615 c = longopts[longind].val;
4616 switch (c)
4617 {
4618 case 'p':
4619 compiler_file_name = optarg;
4620 break;
4621 case 'd':
4622 directory_list
4623 = string_list_cons (abspath (NULL, optarg), directory_list);
4624 break;
4625 case 'x':
4626 exclude_list = string_list_cons (optarg, exclude_list);
4627 break;
4628
4629 case 'v':
4630 case 'V':
4631 version_flag = 1;
4632 break;
4633 case 'q':
4634 quiet_flag = 1;
4635 break;
4636 #if 0
4637 case 'f':
4638 force_flag = 1;
4639 break;
4640 #endif
4641 case 'n':
4642 nochange_flag = 1;
4643 keep_flag = 1;
4644 break;
4645 case 'N':
4646 nosave_flag = 1;
4647 break;
4648 case 'k':
4649 keep_flag = 1;
4650 break;
4651 case 'c':
4652 params = optarg;
4653 break;
4654 #ifdef UNPROTOIZE
4655 case 'i':
4656 indent_string = optarg;
4657 break;
4658 #else /* !defined (UNPROTOIZE) */
4659 case 'l':
4660 local_flag = 1;
4661 break;
4662 case 'g':
4663 global_flag = 1;
4664 break;
4665 case 'C':
4666 cplusplus_flag = 1;
4667 break;
4668 case 'B':
4669 nondefault_syscalls_dir = optarg;
4670 break;
4671 #endif /* !defined (UNPROTOIZE) */
4672 default:
4673 usage ();
4674 }
4675 }
4676
4677 /* Set up compile_params based on -p and -c options. */
4678 munge_compile_params (params);
4679
4680 n_base_source_files = argc - optind;
4681
4682 /* Now actually make a list of the base source filenames. */
4683
4684 base_source_filenames =
4685 (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *));
4686 n_base_source_files = 0;
4687 for (; optind < argc; optind++)
4688 {
4689 const char *path = abspath (NULL, argv[optind]);
4690 int len = strlen (path);
4691
4692 if (path[len-1] == 'c' && path[len-2] == '.')
4693 base_source_filenames[n_base_source_files++] = path;
4694 else
4695 {
4696 fprintf (stderr, "%s: input file names must have .c suffixes: %s\n",
4697 pname, shortpath (NULL, path));
4698 errors++;
4699 }
4700 }
4701
4702 #ifndef UNPROTOIZE
4703 /* We are only interested in the very first identifier token in the
4704 definition of `va_list', so if there is more junk after that first
4705 identifier token, delete it from the `varargs_style_indicator'. */
4706 {
4707 const char *cp;
4708
4709 for (cp = varargs_style_indicator; isalnum (*cp) || *cp == '_'; cp++)
4710 continue;
4711 if (*cp != 0)
4712 varargs_style_indicator = savestring (varargs_style_indicator,
4713 cp - varargs_style_indicator);
4714 }
4715 #endif /* !defined (UNPROTOIZE) */
4716
4717 if (errors)
4718 usage ();
4719 else
4720 {
4721 if (version_flag)
4722 fprintf (stderr, "%s: %s\n", pname, version_string);
4723 do_processing ();
4724 }
4725 if (errors)
4726 exit (1);
4727 else
4728 exit (0);
4729 return 1;
4730 }
This page took 0.246016 seconds and 5 git commands to generate.