OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [protoize.c] - Blame information for rev 20

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.