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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [protoize.c] - Blame information for rev 820

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

Line No. Rev Author Line
1 38 julius
/* 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, 2007 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 3, 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 COPYING3.  If not see
19
<http://www.gnu.org/licenses/>.  */
20
 
21
#include "config.h"
22
#include "system.h"
23
#include "coretypes.h"
24
#include "tm.h"
25
#include "intl.h"
26
#include "cppdefault.h"
27
 
28
#include <setjmp.h>
29
#include <signal.h>
30
#if ! defined( SIGCHLD ) && defined( SIGCLD )
31
#  define SIGCHLD SIGCLD
32
#endif
33
#ifdef HAVE_UNISTD_H
34
#include <unistd.h>
35
#endif
36
#include "version.h"
37
 
38
/* Include getopt.h for the sake of getopt_long.  */
39
#include "getopt.h"
40
 
41
/* Macro to see if the path elements match.  */
42
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
43
#define IS_SAME_PATH_CHAR(a,b) (TOUPPER (a) == TOUPPER (b))
44
#else
45
#define IS_SAME_PATH_CHAR(a,b) ((a) == (b))
46
#endif
47
 
48
/* Macro to see if the paths match.  */
49
#define IS_SAME_PATH(a,b) (FILENAME_CMP (a, b) == 0)
50
 
51
/* Suffix for aux-info files.  */
52
#ifdef __MSDOS__
53
#define AUX_INFO_SUFFIX "X"
54
#else
55
#define AUX_INFO_SUFFIX ".X"
56
#endif
57
 
58
/* Suffix for saved files.  */
59
#ifdef __MSDOS__
60
#define SAVE_SUFFIX "sav"
61
#else
62
#define SAVE_SUFFIX ".save"
63
#endif
64
 
65
/* Suffix for renamed C++ files.  */
66
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
67
#define CPLUS_FILE_SUFFIX "cc"
68
#else
69
#define CPLUS_FILE_SUFFIX "C"
70
#endif
71
 
72
static void usage (void) ATTRIBUTE_NORETURN;
73
static void aux_info_corrupted (void) ATTRIBUTE_NORETURN;
74
static void declare_source_confusing (const char *) ATTRIBUTE_NORETURN;
75
static const char *shortpath (const char *, const char *);
76
static void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
77
static char *savestring (const char *, unsigned int);
78
static char *dupnstr (const char *, size_t);
79
static int safe_read (int, void *, int);
80
static void safe_write (int, void *, int, const char *);
81
static void save_pointers (void);
82
static void restore_pointers (void);
83
static int is_id_char (int);
84
static int in_system_include_dir (const char *);
85
static int directory_specified_p (const char *);
86
static int file_excluded_p (const char *);
87
static char *unexpand_if_needed (const char *);
88
static char *abspath (const char *, const char *);
89
static void check_aux_info (int);
90
static const char *find_corresponding_lparen (const char *);
91
static int referenced_file_is_newer (const char *, time_t);
92
static void save_def_or_dec (const char *, int);
93
static void munge_compile_params (const char *);
94
static int gen_aux_info_file (const char *);
95
static void process_aux_info_file (const char *, int, int);
96
static int identify_lineno (const char *);
97
static void check_source (int, const char *);
98
static const char *seek_to_line (int);
99
static const char *forward_to_next_token_char (const char *);
100
static void output_bytes (const char *, size_t);
101
static void output_string (const char *);
102
static void output_up_to (const char *);
103
static int other_variable_style_function (const char *);
104
static const char *find_rightmost_formals_list (const char *);
105
static void do_cleaning (char *, const char *);
106
static const char *careful_find_l_paren (const char *);
107
static void do_processing (void);
108
 
109
/* Look for these where the `const' qualifier is intentionally cast aside.  */
110
#define NONCONST
111
 
112
/* Define a default place to find the SYSCALLS.X file.  */
113
 
114
#ifndef UNPROTOIZE
115
 
116
#ifndef STANDARD_EXEC_PREFIX
117
#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
118
#endif /* !defined STANDARD_EXEC_PREFIX */
119
 
120
static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX;
121
static const char * const target_machine = DEFAULT_TARGET_MACHINE;
122
static const char * const target_version = DEFAULT_TARGET_VERSION;
123
 
124
#endif /* !defined (UNPROTOIZE) */
125
 
126
/* Suffix of aux_info files.  */
127
 
128
static const char * const aux_info_suffix = AUX_INFO_SUFFIX;
129
 
130
/* String to attach to filenames for saved versions of original files.  */
131
 
132
static const char * const save_suffix = SAVE_SUFFIX;
133
 
134
#ifndef UNPROTOIZE
135
 
136
/* String to attach to C filenames renamed to C++.  */
137
 
138
static const char * const cplus_suffix = CPLUS_FILE_SUFFIX;
139
 
140
/* File name of the file which contains descriptions of standard system
141
   routines.  Note that we never actually do anything with this file per se,
142
   but we do read in its corresponding aux_info file.  */
143
 
144
static const char syscalls_filename[] = "SYSCALLS.c";
145
 
146
/* Default place to find the above file.  */
147
 
148
static const char * default_syscalls_dir;
149
 
150
/* Variable to hold the complete absolutized filename of the SYSCALLS.c.X
151
   file.  */
152
 
153
static char * syscalls_absolute_filename;
154
 
155
#endif /* !defined (UNPROTOIZE) */
156
 
157
/* Type of the structure that holds information about macro unexpansions.  */
158
 
159
struct unexpansion_struct {
160
  const char *const expanded;
161
  const char *const contracted;
162
};
163
typedef struct unexpansion_struct unexpansion;
164
 
165
/* A table of conversions that may need to be made for some (stupid) older
166
   operating systems where these types are preprocessor macros rather than
167
   typedefs (as they really ought to be).
168
 
169
   WARNING: The contracted forms must be as small (or smaller) as the
170
   expanded forms, or else havoc will ensue.  */
171
 
172
static const unexpansion unexpansions[] = {
173
  { "struct _iobuf", "FILE" },
174
  { 0, 0 }
175
};
176
 
177
/* The number of "primary" slots in the hash tables for filenames and for
178
   function names.  This can be as big or as small as you like, except that
179
   it must be a power of two.  */
180
 
181
#define HASH_TABLE_SIZE         (1 << 9)
182
 
183
/* Bit mask to use when computing hash values.  */
184
 
185
static const int hash_mask = (HASH_TABLE_SIZE - 1);
186
 
187
 
188
/* Datatype for lists of directories or filenames.  */
189
struct string_list
190
{
191
  const char *name;
192
  struct string_list *next;
193
};
194
 
195
static struct string_list *string_list_cons (const char *,
196
                                             struct string_list *);
197
 
198
/* List of directories in which files should be converted.  */
199
 
200
struct string_list *directory_list;
201
 
202
/* List of file names which should not be converted.
203
   A file is excluded if the end of its name, following a /,
204
   matches one of the names in this list.  */
205
 
206
struct string_list *exclude_list;
207
 
208
/* The name of the other style of variable-number-of-parameters functions
209
   (i.e. the style that we want to leave unconverted because we don't yet
210
   know how to convert them to this style.  This string is used in warning
211
   messages.  */
212
 
213
/* Also define here the string that we can search for in the parameter lists
214
   taken from the .X files which will unambiguously indicate that we have
215
   found a varargs style function.  */
216
 
217
#ifdef UNPROTOIZE
218
static const char * const other_var_style = "stdarg";
219
#else /* !defined (UNPROTOIZE) */
220
static const char * const other_var_style = "varargs";
221
static const char *varargs_style_indicator = "va_alist";
222
#endif /* !defined (UNPROTOIZE) */
223
 
224
/* The following two types are used to create hash tables.  In this program,
225
   there are two hash tables which are used to store and quickly lookup two
226
   different classes of strings.  The first type of strings stored in the
227
   first hash table are absolute filenames of files which protoize needs to
228
   know about.  The second type of strings (stored in the second hash table)
229
   are function names.  It is this second class of strings which really
230
   inspired the use of the hash tables, because there may be a lot of them.  */
231
 
232
typedef struct hash_table_entry_struct hash_table_entry;
233
 
234
/* Do some typedefs so that we don't have to write "struct" so often.  */
235
 
236
typedef struct def_dec_info_struct def_dec_info;
237
typedef struct file_info_struct file_info;
238
typedef struct f_list_chain_item_struct f_list_chain_item;
239
 
240
#ifndef UNPROTOIZE
241
static int is_syscalls_file (const file_info *);
242
static void rename_c_file (const hash_table_entry *);
243
static const def_dec_info *find_extern_def (const def_dec_info *,
244
                                            const def_dec_info *);
245
static const def_dec_info *find_static_definition (const def_dec_info *);
246
static void connect_defs_and_decs (const hash_table_entry *);
247
static void add_local_decl (const def_dec_info *, const char *);
248
static void add_global_decls (const file_info *, const char *);
249
#endif /* ! UNPROTOIZE */
250
static int needs_to_be_converted (const file_info *);
251
static void visit_each_hash_node (const hash_table_entry *,
252
                                  void (*)(const hash_table_entry *));
253
static hash_table_entry *add_symbol (hash_table_entry *, const char *);
254
static hash_table_entry *lookup (hash_table_entry *, const char *);
255
static void free_def_dec (def_dec_info *);
256
static file_info *find_file (const char *, int);
257
static void reverse_def_dec_list (const hash_table_entry *);
258
static void edit_fn_declaration (const def_dec_info *, const char *);
259
static int edit_formals_lists (const char *, unsigned int,
260
                               const def_dec_info *);
261
static void edit_fn_definition (const def_dec_info *, const char *);
262
static void scan_for_missed_items (const file_info *);
263
static void edit_file (const hash_table_entry *);
264
 
265
/* In the struct below, note that the "_info" field has two different uses
266
   depending on the type of hash table we are in (i.e. either the filenames
267
   hash table or the function names hash table).  In the filenames hash table
268
   the info fields of the entries point to the file_info struct which is
269
   associated with each filename (1 per filename).  In the function names
270
   hash table, the info field points to the head of a singly linked list of
271
   def_dec_info entries which are all defs or decs of the function whose
272
   name is pointed to by the "symbol" field.  Keeping all of the defs/decs
273
   for a given function name on a special list specifically for that function
274
   name makes it quick and easy to find out all of the important information
275
   about a given (named) function.  */
276
 
277
struct hash_table_entry_struct {
278
  hash_table_entry *            hash_next;      /* -> to secondary entries */
279
  const char *                  symbol;         /* -> to the hashed string */
280
  union {
281
    const def_dec_info *        _ddip;
282
    file_info *                 _fip;
283
  } _info;
284
};
285
#define ddip _info._ddip
286
#define fip _info._fip
287
 
288
/* Define a type specifically for our two hash tables.  */
289
 
290
typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
291
 
292
/* The following struct holds all of the important information about any
293
   single filename (e.g. file) which we need to know about.  */
294
 
295
struct file_info_struct {
296
  const hash_table_entry *      hash_entry; /* -> to associated hash entry */
297
  const def_dec_info *          defs_decs;  /* -> to chain of defs/decs */
298
  time_t                        mtime;      /* Time of last modification.  */
299
};
300
 
301
/* Due to the possibility that functions may return pointers to functions,
302
   (which may themselves have their own parameter lists) and due to the
303
   fact that returned pointers-to-functions may be of type "pointer-to-
304
   function-returning-pointer-to-function" (ad nauseum) we have to keep
305
   an entire chain of ANSI style formal parameter lists for each function.
306
 
307
   Normally, for any given function, there will only be one formals list
308
   on the chain, but you never know.
309
 
310
   Note that the head of each chain of formals lists is pointed to by the
311
   `f_list_chain' field of the corresponding def_dec_info record.
312
 
313
   For any given chain, the item at the head of the chain is the *leftmost*
314
   parameter list seen in the actual C language function declaration.  If
315
   there are other members of the chain, then these are linked in left-to-right
316
   order from the head of the chain.  */
317
 
318
struct f_list_chain_item_struct {
319
  const f_list_chain_item *     chain_next;     /* -> to next item on chain */
320
  const char *                  formals_list;   /* -> to formals list string */
321
};
322
 
323
/* The following struct holds all of the important information about any
324
   single function definition or declaration which we need to know about.
325
   Note that for unprotoize we don't need to know very much because we
326
   never even create records for stuff that we don't intend to convert
327
   (like for instance defs and decs which are already in old K&R format
328
   and "implicit" function declarations).  */
329
 
330
struct def_dec_info_struct {
331
  const def_dec_info *  next_in_file;   /* -> to rest of chain for file */
332
  file_info *           file;           /* -> file_info for containing file */
333
  int                   line;           /* source line number of def/dec */
334
  const char *          ansi_decl;      /* -> left end of ansi decl */
335
  hash_table_entry *    hash_entry;     /* -> hash entry for function name */
336
  unsigned int          is_func_def;    /* = 0 means this is a declaration */
337
  const def_dec_info *  next_for_func;  /* -> to rest of chain for func name */
338
  unsigned int          f_list_count;   /* count of formals lists we expect */
339
  char                  prototyped;     /* = 0 means already prototyped */
340
#ifndef UNPROTOIZE
341
  const f_list_chain_item * f_list_chain;       /* -> chain of formals lists */
342
  const def_dec_info *  definition;     /* -> def/dec containing related def */
343
  char                  is_static;      /* = 0 means visibility is "extern"  */
344
  char                  is_implicit;    /* != 0 for implicit func decl's */
345
  char                  written;        /* != 0 means written for implicit */
346
#else /* !defined (UNPROTOIZE) */
347
  const char *          formal_names;   /* -> to list of names of formals */
348
  const char *          formal_decls;   /* -> to string of formal declarations */
349
#endif /* !defined (UNPROTOIZE) */
350
};
351
 
352
/* Pointer to the tail component of the filename by which this program was
353
   invoked.  Used everywhere in error and warning messages.  */
354
 
355
static const char *pname;
356
 
357
/* Error counter.  Will be nonzero if we should give up at the next convenient
358
   stopping point.  */
359
 
360
static int errors = 0;
361
 
362
/* Option flags.  */
363
/* ??? The variables are not marked static because some of them have
364
   the same names as gcc variables declared in options.h.  */
365
/* ??? These comments should say what the flag mean as well as the options
366
   that set them.  */
367
 
368
/* File name to use for running gcc.  Allows GCC 2 to be named
369
   something other than gcc.  */
370
static const char *compiler_file_name = "gcc";
371
 
372
int version_flag = 0;            /* Print our version number.  */
373
int quiet_flag = 0;              /* Don't print messages normally.  */
374
int nochange_flag = 0;           /* Don't convert, just say what files
375
                                   we would have converted.  */
376
int nosave_flag = 0;             /* Don't save the old version.  */
377
int keep_flag = 0;               /* Don't delete the .X files.  */
378
static const char ** compile_params = 0; /* Option string for gcc.  */
379
#ifdef UNPROTOIZE
380
static const char *indent_string = "     ";     /* Indentation for newly
381
                                                   inserted parm decls.  */
382
#else /* !defined (UNPROTOIZE) */
383
int local_flag = 0;              /* Insert new local decls (when?).  */
384
int global_flag = 0;             /* set by -g option */
385
int cplusplus_flag = 0;          /* Rename converted files to *.C.  */
386
static const char *nondefault_syscalls_dir = 0; /* Dir to look for
387
                                                   SYSCALLS.c.X in.  */
388
#endif /* !defined (UNPROTOIZE) */
389
 
390
/* An index into the compile_params array where we should insert the source
391
   file name when we are ready to exec the C compiler.  A zero value indicates
392
   that we have not yet called munge_compile_params.  */
393
 
394
static int input_file_name_index = 0;
395
 
396
/* An index into the compile_params array where we should insert the filename
397
   for the aux info file, when we run the C compiler.  */
398
static int aux_info_file_name_index = 0;
399
 
400
/* Count of command line arguments which were "filename" arguments.  */
401
 
402
static int n_base_source_files = 0;
403
 
404
/* Points to a malloc'ed list of pointers to all of the filenames of base
405
   source files which were specified on the command line.  */
406
 
407
static const char **base_source_filenames;
408
 
409
/* Line number of the line within the current aux_info file that we
410
   are currently processing.  Used for error messages in case the prototypes
411
   info file is corrupted somehow.  */
412
 
413
static int current_aux_info_lineno;
414
 
415
/* Pointer to the name of the source file currently being converted.  */
416
 
417
static const char *convert_filename;
418
 
419
/* Pointer to relative root string (taken from aux_info file) which indicates
420
   where directory the user was in when he did the compilation step that
421
   produced the containing aux_info file.  */
422
 
423
static const char *invocation_filename;
424
 
425
/* Pointer to the base of the input buffer that holds the original text for the
426
   source file currently being converted.  */
427
 
428
static const char *orig_text_base;
429
 
430
/* Pointer to the byte just beyond the end of the input buffer that holds the
431
   original text for the source file currently being converted.  */
432
 
433
static const char *orig_text_limit;
434
 
435
/* Pointer to the base of the input buffer that holds the cleaned text for the
436
   source file currently being converted.  */
437
 
438
static const char *clean_text_base;
439
 
440
/* Pointer to the byte just beyond the end of the input buffer that holds the
441
   cleaned text for the source file currently being converted.  */
442
 
443
static const char *clean_text_limit;
444
 
445
/* Pointer to the last byte in the cleaned text buffer that we have already
446
   (virtually) copied to the output buffer (or decided to ignore).  */
447
 
448
static const char * clean_read_ptr;
449
 
450
/* Pointer to the base of the output buffer that holds the replacement text
451
   for the source file currently being converted.  */
452
 
453
static char *repl_text_base;
454
 
455
/* Pointer to the byte just beyond the end of the output buffer that holds the
456
   replacement text for the source file currently being converted.  */
457
 
458
static char *repl_text_limit;
459
 
460
/* Pointer to the last byte which has been stored into the output buffer.
461
   The next byte to be stored should be stored just past where this points
462
   to.  */
463
 
464
static char * repl_write_ptr;
465
 
466
/* Pointer into the cleaned text buffer for the source file we are currently
467
   converting.  This points to the first character of the line that we last
468
   did a "seek_to_line" to (see below).  */
469
 
470
static const char *last_known_line_start;
471
 
472
/* Number of the line (in the cleaned text buffer) that we last did a
473
   "seek_to_line" to.  Will be one if we just read a new source file
474
   into the cleaned text buffer.  */
475
 
476
static int last_known_line_number;
477
 
478
/* The filenames hash table.  */
479
 
480
static hash_table filename_primary;
481
 
482
/* The function names hash table.  */
483
 
484
static hash_table function_name_primary;
485
 
486
/* The place to keep the recovery address which is used only in cases where
487
   we get hopelessly confused by something in the cleaned original text.  */
488
 
489
static jmp_buf source_confusion_recovery;
490
 
491
/* A pointer to the current directory filename (used by abspath).  */
492
 
493
static char *cwd_buffer;
494
 
495
/* A place to save the read pointer until we are sure that an individual
496
   attempt at editing will succeed.  */
497
 
498
static const char * saved_clean_read_ptr;
499
 
500
/* A place to save the write pointer until we are sure that an individual
501
   attempt at editing will succeed.  */
502
 
503
static char * saved_repl_write_ptr;
504
 
505
/* Translate and output an error message.  */
506
static void
507
notice (const char *cmsgid, ...)
508
{
509
  va_list ap;
510
 
511
  va_start (ap, cmsgid);
512
  vfprintf (stderr, _(cmsgid), ap);
513
  va_end (ap);
514
}
515
 
516
 
517
/* Make a copy of a string INPUT with size SIZE.  */
518
 
519
static char *
520
savestring (const char *input, unsigned int size)
521
{
522
  char *output = xmalloc (size + 1);
523
  strcpy (output, input);
524
  return output;
525
}
526
 
527
 
528
/* Make a duplicate of the first N bytes of a given string in a newly
529
   allocated area.  */
530
 
531
static char *
532
dupnstr (const char *s, size_t n)
533
{
534
  char *ret_val = xmalloc (n + 1);
535
 
536
  strncpy (ret_val, s, n);
537
  ret_val[n] = '\0';
538
  return ret_val;
539
}
540
 
541
/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
542
   retrying if necessary.  Return the actual number of bytes read.  */
543
 
544
static int
545
safe_read (int desc, void *ptr, int len)
546
{
547
  int left = len;
548
  while (left > 0) {
549
    int nchars = read (desc, ptr, left);
550
    if (nchars < 0)
551
      {
552
#ifdef EINTR
553
        if (errno == EINTR)
554
          continue;
555
#endif
556
        return nchars;
557
      }
558
    if (nchars == 0)
559
      break;
560
    /* Arithmetic on void pointers is a gcc extension.  */
561
    ptr = (char *) ptr + nchars;
562
    left -= nchars;
563
  }
564
  return len - left;
565
}
566
 
567
/* Write LEN bytes at PTR to descriptor DESC,
568
   retrying if necessary, and treating any real error as fatal.  */
569
 
570
static void
571
safe_write (int desc, void *ptr, int len, const char *out_fname)
572
{
573
  while (len > 0) {
574
    int written = write (desc, ptr, len);
575
    if (written < 0)
576
      {
577
        int errno_val = errno;
578
#ifdef EINTR
579
        if (errno_val == EINTR)
580
          continue;
581
#endif
582
        notice ("%s: error writing file '%s': %s\n",
583
                pname, shortpath (NULL, out_fname), xstrerror (errno_val));
584
        return;
585
      }
586
    /* Arithmetic on void pointers is a gcc extension.  */
587
    ptr = (char *) ptr + written;
588
    len -= written;
589
  }
590
}
591
 
592
/* Get setup to recover in case the edit we are about to do goes awry.  */
593
 
594
static void
595
save_pointers (void)
596
{
597
  saved_clean_read_ptr = clean_read_ptr;
598
  saved_repl_write_ptr = repl_write_ptr;
599
}
600
 
601
/* Call this routine to recover our previous state whenever something looks
602
   too confusing in the source code we are trying to edit.  */
603
 
604
static void
605
restore_pointers (void)
606
{
607
  clean_read_ptr = saved_clean_read_ptr;
608
  repl_write_ptr = saved_repl_write_ptr;
609
}
610
 
611
/* Return true if the given character is a valid identifier character.  */
612
 
613
static int
614
is_id_char (int ch)
615
{
616
  return (ISIDNUM (ch) || (ch == '$'));
617
}
618
 
619
/* Give a message indicating the proper way to invoke this program and then
620
   exit with nonzero status.  */
621
 
622
static void
623
usage (void)
624
{
625
#ifdef UNPROTOIZE
626
  notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
627
          pname, pname);
628
#else /* !defined (UNPROTOIZE) */
629
  notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
630
          pname, pname);
631
#endif /* !defined (UNPROTOIZE) */
632
  exit (FATAL_EXIT_CODE);
633
}
634
 
635
/* Return true if the given filename (assumed to be an absolute filename)
636
   designates a file residing anywhere beneath any one of the "system"
637
   include directories.  */
638
 
639
static int
640
in_system_include_dir (const char *path)
641
{
642
  const struct default_include *p;
643
 
644
  gcc_assert (IS_ABSOLUTE_PATH (path));
645
 
646
  for (p = cpp_include_defaults; p->fname; p++)
647
    if (!strncmp (path, p->fname, strlen (p->fname))
648
        && IS_DIR_SEPARATOR (path[strlen (p->fname)]))
649
      return 1;
650
  return 0;
651
}
652
 
653
#if 0
654
/* Return true if the given filename designates a file that the user has
655
   read access to and for which the user has write access to the containing
656
   directory.  */
657
 
658
static int
659
file_could_be_converted (const char *path)
660
{
661
  char *const dir_name = alloca (strlen (path) + 1);
662
 
663
  if (access (path, R_OK))
664
    return 0;
665
 
666
  {
667
    char *dir_last_slash;
668
 
669
    strcpy (dir_name, path);
670
    dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
671
#ifdef DIR_SEPARATOR_2
672
    {
673
      char *slash;
674
 
675
      slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
676
                       DIR_SEPARATOR_2);
677
      if (slash)
678
        dir_last_slash = slash;
679
    }
680
#endif
681
    gcc_assert (dir_last_slash);
682
    *dir_last_slash = '\0';
683
  }
684
 
685
  if (access (path, W_OK))
686
    return 0;
687
 
688
  return 1;
689
}
690
 
691
/* Return true if the given filename designates a file that we are allowed
692
   to modify.  Files which we should not attempt to modify are (a) "system"
693
   include files, and (b) files which the user doesn't have write access to,
694
   and (c) files which reside in directories which the user doesn't have
695
   write access to.  Unless requested to be quiet, give warnings about
696
   files that we will not try to convert for one reason or another.  An
697
   exception is made for "system" include files, which we never try to
698
   convert and for which we don't issue the usual warnings.  */
699
 
700
static int
701
file_normally_convertible (const char *path)
702
{
703
  char *const dir_name = alloca (strlen (path) + 1);
704
 
705
  if (in_system_include_dir (path))
706
    return 0;
707
 
708
  {
709
    char *dir_last_slash;
710
 
711
    strcpy (dir_name, path);
712
    dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
713
#ifdef DIR_SEPARATOR_2
714
    {
715
      char *slash;
716
 
717
      slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
718
                       DIR_SEPARATOR_2);
719
      if (slash)
720
        dir_last_slash = slash;
721
    }
722
#endif
723
    gcc_assert (dir_last_slash);
724
    *dir_last_slash = '\0';
725
  }
726
 
727
  if (access (path, R_OK))
728
    {
729
      if (!quiet_flag)
730
        notice ("%s: warning: no read access for file '%s'\n",
731
                pname, shortpath (NULL, path));
732
      return 0;
733
    }
734
 
735
  if (access (path, W_OK))
736
    {
737
      if (!quiet_flag)
738
        notice ("%s: warning: no write access for file '%s'\n",
739
                pname, shortpath (NULL, path));
740
      return 0;
741
    }
742
 
743
  if (access (dir_name, W_OK))
744
    {
745
      if (!quiet_flag)
746
        notice ("%s: warning: no write access for dir containing '%s'\n",
747
                pname, shortpath (NULL, path));
748
      return 0;
749
    }
750
 
751
  return 1;
752
}
753
#endif /* 0 */
754
 
755
#ifndef UNPROTOIZE
756
 
757
/* Return true if the given file_info struct refers to the special SYSCALLS.c.X
758
   file.  Return false otherwise.  */
759
 
760
static int
761
is_syscalls_file (const file_info *fi_p)
762
{
763
  char const *f = fi_p->hash_entry->symbol;
764
  size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
765
  return sysl <= fl  &&  strcmp (f + fl - sysl, syscalls_filename) == 0;
766
}
767
 
768
#endif /* !defined (UNPROTOIZE) */
769
 
770
/* Check to see if this file will need to have anything done to it on this
771
   run.  If there is nothing in the given file which both needs conversion
772
   and for which we have the necessary stuff to do the conversion, return
773
   false.  Otherwise, return true.
774
 
775
   Note that (for protoize) it is only valid to call this function *after*
776
   the connections between declarations and definitions have all been made
777
   by connect_defs_and_decs.  */
778
 
779
static int
780
needs_to_be_converted (const file_info *file_p)
781
{
782
  const def_dec_info *ddp;
783
 
784
#ifndef UNPROTOIZE
785
 
786
  if (is_syscalls_file (file_p))
787
    return 0;
788
 
789
#endif /* !defined (UNPROTOIZE) */
790
 
791
  for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
792
 
793
    if (
794
 
795
#ifndef UNPROTOIZE
796
 
797
      /* ... and if we a protoizing and this function is in old style ...  */
798
      !ddp->prototyped
799
      /* ... and if this a definition or is a decl with an associated def ...  */
800
      && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
801
 
802
#else /* defined (UNPROTOIZE) */
803
 
804
      /* ... and if we are unprotoizing and this function is in new style ...  */
805
      ddp->prototyped
806
 
807
#endif /* defined (UNPROTOIZE) */
808
      )
809
          /* ... then the containing file needs converting.  */
810
          return -1;
811
  return 0;
812
}
813
 
814
/* Return 1 if the file name NAME is in a directory
815
   that should be converted.  */
816
 
817
static int
818
directory_specified_p (const char *name)
819
{
820
  struct string_list *p;
821
 
822
  for (p = directory_list; p; p = p->next)
823
    if (!strncmp (name, p->name, strlen (p->name))
824
        && IS_DIR_SEPARATOR (name[strlen (p->name)]))
825
      {
826
        const char *q = name + strlen (p->name) + 1;
827
 
828
        /* If there are more slashes, it's in a subdir, so
829
           this match doesn't count.  */
830
        while (*q++)
831
          if (IS_DIR_SEPARATOR (*(q-1)))
832
            goto lose;
833
        return 1;
834
 
835
      lose: ;
836
      }
837
 
838
  return 0;
839
}
840
 
841
/* Return 1 if the file named NAME should be excluded from conversion.  */
842
 
843
static int
844
file_excluded_p (const char *name)
845
{
846
  struct string_list *p;
847
  int len = strlen (name);
848
 
849
  for (p = exclude_list; p; p = p->next)
850
    if (!strcmp (name + len - strlen (p->name), p->name)
851
        && IS_DIR_SEPARATOR (name[len - strlen (p->name) - 1]))
852
      return 1;
853
 
854
  return 0;
855
}
856
 
857
/* Construct a new element of a string_list.
858
   STRING is the new element value, and REST holds the remaining elements.  */
859
 
860
static struct string_list *
861
string_list_cons (const char *string, struct string_list *rest)
862
{
863
  struct string_list *temp = xmalloc (sizeof (struct string_list));
864
 
865
  temp->next = rest;
866
  temp->name = string;
867
  return temp;
868
}
869
 
870
/* ??? The GNU convention for mentioning function args in its comments
871
   is to capitalize them.  So change "hash_tab_p" to HASH_TAB_P below.
872
   Likewise for all the other functions.  */
873
 
874
/* Given a hash table, apply some function to each node in the table. The
875
   table to traverse is given as the "hash_tab_p" argument, and the
876
   function to be applied to each node in the table is given as "func"
877
   argument.  */
878
 
879
static void
880
visit_each_hash_node (const hash_table_entry *hash_tab_p,
881
                      void (*func) (const hash_table_entry *))
882
{
883
  const hash_table_entry *primary;
884
 
885
  for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
886
    if (primary->symbol)
887
      {
888
        hash_table_entry *second;
889
 
890
        (*func)(primary);
891
        for (second = primary->hash_next; second; second = second->hash_next)
892
          (*func) (second);
893
      }
894
}
895
 
896
/* Initialize all of the fields of a new hash table entry, pointed
897
   to by the "p" parameter.  Note that the space to hold the entry
898
   is assumed to have already been allocated before this routine is
899
   called.  */
900
 
901
static hash_table_entry *
902
add_symbol (hash_table_entry *p, const char *s)
903
{
904
  p->hash_next = NULL;
905
  p->symbol = xstrdup (s);
906
  p->ddip = NULL;
907
  p->fip = NULL;
908
  return p;
909
}
910
 
911
/* Look for a particular function name or filename in the particular
912
   hash table indicated by "hash_tab_p".  If the name is not in the
913
   given hash table, add it.  Either way, return a pointer to the
914
   hash table entry for the given name.  */
915
 
916
static hash_table_entry *
917
lookup (hash_table_entry *hash_tab_p, const char *search_symbol)
918
{
919
  int hash_value = 0;
920
  const char *search_symbol_char_p = search_symbol;
921
  hash_table_entry *p;
922
 
923
  while (*search_symbol_char_p)
924
    hash_value += *search_symbol_char_p++;
925
  hash_value &= hash_mask;
926
  p = &hash_tab_p[hash_value];
927
  if (! p->symbol)
928
      return add_symbol (p, search_symbol);
929
  if (!strcmp (p->symbol, search_symbol))
930
    return p;
931
  while (p->hash_next)
932
    {
933
      p = p->hash_next;
934
      if (!strcmp (p->symbol, search_symbol))
935
        return p;
936
    }
937
  p->hash_next = xmalloc (sizeof (hash_table_entry));
938
  p = p->hash_next;
939
  return add_symbol (p, search_symbol);
940
}
941
 
942
/* Throw a def/dec record on the junk heap.
943
 
944
   Also, since we are not using this record anymore, free up all of the
945
   stuff it pointed to.  */
946
 
947
static void
948
free_def_dec (def_dec_info *p)
949
{
950
  free ((NONCONST void *) p->ansi_decl);
951
 
952
#ifndef UNPROTOIZE
953
  {
954
    const f_list_chain_item * curr;
955
    const f_list_chain_item * next;
956
 
957
    for (curr = p->f_list_chain; curr; curr = next)
958
      {
959
        next = curr->chain_next;
960
        free ((NONCONST void *) curr);
961
      }
962
  }
963
#endif /* !defined (UNPROTOIZE) */
964
 
965
  free (p);
966
}
967
 
968
/* Unexpand as many macro symbols as we can find.
969
 
970
   If the given line must be unexpanded, make a copy of it in the heap and
971
   return a pointer to the unexpanded copy.  Otherwise return NULL.  */
972
 
973
static char *
974
unexpand_if_needed (const char *aux_info_line)
975
{
976
  static char *line_buf = 0;
977
  static int line_buf_size = 0;
978
  const unexpansion *unexp_p;
979
  int got_unexpanded = 0;
980
  const char *s;
981
  char *copy_p = line_buf;
982
 
983
  if (line_buf == 0)
984
    {
985
      line_buf_size = 1024;
986
      line_buf = xmalloc (line_buf_size);
987
    }
988
 
989
  copy_p = line_buf;
990
 
991
  /* Make a copy of the input string in line_buf, expanding as necessary.  */
992
 
993
  for (s = aux_info_line; *s != '\n'; )
994
    {
995
      for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
996
        {
997
          const char *in_p = unexp_p->expanded;
998
          size_t len = strlen (in_p);
999
 
1000
          if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
1001
            {
1002
              int size = strlen (unexp_p->contracted);
1003
              got_unexpanded = 1;
1004
              if (copy_p + size - line_buf >= line_buf_size)
1005
                {
1006
                  int offset = copy_p - line_buf;
1007
                  line_buf_size *= 2;
1008
                  line_buf_size += size;
1009
                  line_buf = xrealloc (line_buf, line_buf_size);
1010
                  copy_p = line_buf + offset;
1011
                }
1012
              strcpy (copy_p, unexp_p->contracted);
1013
              copy_p += size;
1014
 
1015
              /* Assume that there will not be another replacement required
1016
                 within the text just replaced.  */
1017
 
1018
              s += len;
1019
              goto continue_outer;
1020
            }
1021
        }
1022
      if (copy_p - line_buf == line_buf_size)
1023
        {
1024
          int offset = copy_p - line_buf;
1025
          line_buf_size *= 2;
1026
          line_buf = xrealloc (line_buf, line_buf_size);
1027
          copy_p = line_buf + offset;
1028
        }
1029
      *copy_p++ = *s++;
1030
continue_outer: ;
1031
    }
1032
  if (copy_p + 2 - line_buf >= line_buf_size)
1033
    {
1034
      int offset = copy_p - line_buf;
1035
      line_buf_size *= 2;
1036
      line_buf = xrealloc (line_buf, line_buf_size);
1037
      copy_p = line_buf + offset;
1038
    }
1039
  *copy_p++ = '\n';
1040
  *copy_p = '\0';
1041
 
1042
  return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
1043
}
1044
 
1045
/* Return the absolutized filename for the given relative
1046
   filename.  Note that if that filename is already absolute, it may
1047
   still be returned in a modified form because this routine also
1048
   eliminates redundant slashes and single dots and eliminates double
1049
   dots to get a shortest possible filename from the given input
1050
   filename.  The absolutization of relative filenames is made by
1051
   assuming that the given filename is to be taken as relative to
1052
   the first argument (cwd) or to the current directory if cwd is
1053
   NULL.  */
1054
 
1055
static char *
1056
abspath (const char *cwd, const char *rel_filename)
1057
{
1058
  /* Setup the current working directory as needed.  */
1059
  const char *const cwd2 = (cwd) ? cwd : cwd_buffer;
1060
  char *const abs_buffer = alloca (strlen (cwd2) + strlen (rel_filename) + 2);
1061
  char *endp = abs_buffer;
1062
  char *outp, *inp;
1063
 
1064
  /* Copy the  filename (possibly preceded by the current working
1065
     directory name) into the absolutization buffer.  */
1066
 
1067
  {
1068
    const char *src_p;
1069
 
1070
    if (! IS_ABSOLUTE_PATH (rel_filename))
1071
      {
1072
        src_p = cwd2;
1073
        while ((*endp++ = *src_p++))
1074
          continue;
1075
        *(endp-1) = DIR_SEPARATOR;              /* overwrite null */
1076
      }
1077
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
1078
    else if (IS_DIR_SEPARATOR (rel_filename[0]))
1079
      {
1080
        /* A path starting with a directory separator is considered absolute
1081
           for dos based filesystems, but it's really not -- it's just the
1082
           convention used throughout GCC and it works. However, in this
1083
           case, we still need to prepend the drive spec from cwd_buffer.  */
1084
        *endp++ = cwd2[0];
1085
        *endp++ = cwd2[1];
1086
      }
1087
#endif
1088
    src_p = rel_filename;
1089
    while ((*endp++ = *src_p++))
1090
      continue;
1091
  }
1092
 
1093
  /* Now make a copy of abs_buffer into abs_buffer, shortening the
1094
     filename (by taking out slashes and dots) as we go.  */
1095
 
1096
  outp = inp = abs_buffer;
1097
  *outp++ = *inp++;             /* copy first slash */
1098
#if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
1099
  if (IS_DIR_SEPARATOR (inp[0]))
1100
    *outp++ = *inp++;           /* copy second slash */
1101
#endif
1102
  for (;;)
1103
    {
1104
      if (!inp[0])
1105
        break;
1106
      else if (IS_DIR_SEPARATOR (inp[0]) && IS_DIR_SEPARATOR (outp[-1]))
1107
        {
1108
          inp++;
1109
          continue;
1110
        }
1111
      else if (inp[0] == '.' && IS_DIR_SEPARATOR (outp[-1]))
1112
        {
1113
          if (!inp[1])
1114
            break;
1115
          else if (IS_DIR_SEPARATOR (inp[1]))
1116
            {
1117
              inp += 2;
1118
              continue;
1119
            }
1120
          else if ((inp[1] == '.') && (inp[2] == 0
1121
                                       || IS_DIR_SEPARATOR (inp[2])))
1122
            {
1123
              inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2;
1124
              outp -= 2;
1125
              while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*outp))
1126
                outp--;
1127
              if (outp < abs_buffer)
1128
                {
1129
                  /* Catch cases like /.. where we try to backup to a
1130
                     point above the absolute root of the logical file
1131
                     system.  */
1132
 
1133
                  notice ("%s: invalid file name: %s\n",
1134
                          pname, rel_filename);
1135
                  exit (FATAL_EXIT_CODE);
1136
                }
1137
              *++outp = '\0';
1138
              continue;
1139
            }
1140
        }
1141
      *outp++ = *inp++;
1142
    }
1143
 
1144
  /* On exit, make sure that there is a trailing null, and make sure that
1145
     the last character of the returned string is *not* a slash.  */
1146
 
1147
  *outp = '\0';
1148
  if (IS_DIR_SEPARATOR (outp[-1]))
1149
    *--outp  = '\0';
1150
 
1151
  /* Make a copy (in the heap) of the stuff left in the absolutization
1152
     buffer and return a pointer to the copy.  */
1153
 
1154
  return savestring (abs_buffer, outp - abs_buffer);
1155
}
1156
 
1157
/* Given a filename (and possibly a directory name from which the filename
1158
   is relative) return a string which is the shortest possible
1159
   equivalent for the corresponding full (absolutized) filename.  The
1160
   shortest possible equivalent may be constructed by converting the
1161
   absolutized filename to be a relative filename (i.e. relative to
1162
   the actual current working directory).  However if a relative filename
1163
   is longer, then the full absolute filename is returned.
1164
 
1165
   KNOWN BUG:
1166
 
1167
   Note that "simple-minded" conversion of any given type of filename (either
1168
   relative or absolute) may not result in a valid equivalent filename if any
1169
   subpart of the original filename is actually a symbolic link.  */
1170
 
1171
static const char *
1172
shortpath (const char *cwd, const char *filename)
1173
{
1174
  char *rel_buffer;
1175
  char *rel_buf_p;
1176
  char *cwd_p = cwd_buffer;
1177
  char *path_p;
1178
  int unmatched_slash_count = 0;
1179
  size_t filename_len = strlen (filename);
1180
 
1181
  path_p = abspath (cwd, filename);
1182
  rel_buf_p = rel_buffer = xmalloc (filename_len);
1183
 
1184
  while (*cwd_p && IS_SAME_PATH_CHAR (*cwd_p, *path_p))
1185
    {
1186
      cwd_p++;
1187
      path_p++;
1188
    }
1189
  if (!*cwd_p && (!*path_p || IS_DIR_SEPARATOR (*path_p)))
1190
    {
1191
      /* whole pwd matched */
1192
      if (!*path_p)             /* input *is* the current path! */
1193
        return ".";
1194
      else
1195
        return ++path_p;
1196
    }
1197
  else
1198
    {
1199
      if (*path_p)
1200
        {
1201
          --cwd_p;
1202
          --path_p;
1203
          while (! IS_DIR_SEPARATOR (*cwd_p))     /* backup to last slash */
1204
            {
1205
              --cwd_p;
1206
              --path_p;
1207
            }
1208
          cwd_p++;
1209
          path_p++;
1210
          unmatched_slash_count++;
1211
        }
1212
 
1213
      /* Find out how many directory levels in cwd were *not* matched.  */
1214
      while (*cwd_p++)
1215
        if (IS_DIR_SEPARATOR (*(cwd_p-1)))
1216
          unmatched_slash_count++;
1217
 
1218
      /* Now we know how long the "short name" will be.
1219
         Reject it if longer than the input.  */
1220
      if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
1221
        return filename;
1222
 
1223
      /* For each of them, put a `../' at the beginning of the short name.  */
1224
      while (unmatched_slash_count--)
1225
        {
1226
          /* Give up if the result gets to be longer
1227
             than the absolute path name.  */
1228
          if (rel_buffer + filename_len <= rel_buf_p + 3)
1229
            return filename;
1230
          *rel_buf_p++ = '.';
1231
          *rel_buf_p++ = '.';
1232
          *rel_buf_p++ = DIR_SEPARATOR;
1233
        }
1234
 
1235
      /* Then tack on the unmatched part of the desired file's name.  */
1236
      do
1237
        {
1238
          if (rel_buffer + filename_len <= rel_buf_p)
1239
            return filename;
1240
        }
1241
      while ((*rel_buf_p++ = *path_p++));
1242
 
1243
      --rel_buf_p;
1244
      if (IS_DIR_SEPARATOR (*(rel_buf_p-1)))
1245
        *--rel_buf_p = '\0';
1246
      return rel_buffer;
1247
    }
1248
}
1249
 
1250
/* Lookup the given filename in the hash table for filenames.  If it is a
1251
   new one, then the hash table info pointer will be null.  In this case,
1252
   we create a new file_info record to go with the filename, and we initialize
1253
   that record with some reasonable values.  */
1254
 
1255
/* FILENAME was const, but that causes a warning on AIX when calling stat.
1256
   That is probably a bug in AIX, but might as well avoid the warning.  */
1257
 
1258
static file_info *
1259
find_file (const char *filename, int do_not_stat)
1260
{
1261
  hash_table_entry *hash_entry_p;
1262
 
1263
  hash_entry_p = lookup (filename_primary, filename);
1264
  if (hash_entry_p->fip)
1265
    return hash_entry_p->fip;
1266
  else
1267
    {
1268
      struct stat stat_buf;
1269
      file_info *file_p = xmalloc (sizeof (file_info));
1270
 
1271
      /* If we cannot get status on any given source file, give a warning
1272
         and then just set its time of last modification to infinity.  */
1273
 
1274
      if (do_not_stat)
1275
        stat_buf.st_mtime = (time_t) 0;
1276
      else
1277
        {
1278
          if (stat (filename, &stat_buf) == -1)
1279
            {
1280
              int errno_val = errno;
1281
              notice ("%s: %s: can't get status: %s\n",
1282
                      pname, shortpath (NULL, filename),
1283
                      xstrerror (errno_val));
1284
              stat_buf.st_mtime = (time_t) -1;
1285
            }
1286
        }
1287
 
1288
      hash_entry_p->fip = file_p;
1289
      file_p->hash_entry = hash_entry_p;
1290
      file_p->defs_decs = NULL;
1291
      file_p->mtime = stat_buf.st_mtime;
1292
      return file_p;
1293
    }
1294
}
1295
 
1296
/* Generate a fatal error because some part of the aux_info file is
1297
   messed up.  */
1298
 
1299
static void
1300
aux_info_corrupted (void)
1301
{
1302
  notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
1303
          pname, current_aux_info_lineno);
1304
  exit (FATAL_EXIT_CODE);
1305
}
1306
 
1307
/* ??? This comment is vague.  Say what the condition is for.  */
1308
/* Check to see that a condition is true.  This is kind of like an assert.  */
1309
 
1310
static void
1311
check_aux_info (int cond)
1312
{
1313
  if (! cond)
1314
    aux_info_corrupted ();
1315
}
1316
 
1317
/* Given a pointer to the closing right parenthesis for a particular formals
1318
   list (in an aux_info file) find the corresponding left parenthesis and
1319
   return a pointer to it.  */
1320
 
1321
static const char *
1322
find_corresponding_lparen (const char *p)
1323
{
1324
  const char *q;
1325
  int paren_depth;
1326
 
1327
  for (paren_depth = 1, q = p-1; paren_depth; q--)
1328
    {
1329
      switch (*q)
1330
        {
1331
        case ')':
1332
          paren_depth++;
1333
          break;
1334
        case '(':
1335
          paren_depth--;
1336
          break;
1337
        }
1338
    }
1339
  return ++q;
1340
}
1341
 
1342
/* Given a line from  an aux info file, and a time at which the aux info
1343
   file it came from was created, check to see if the item described in
1344
   the line comes from a file which has been modified since the aux info
1345
   file was created.  If so, return nonzero, else return zero.  */
1346
 
1347
static int
1348
referenced_file_is_newer (const char *l, time_t aux_info_mtime)
1349
{
1350
  const char *p;
1351
  file_info *fi_p;
1352
  char *filename;
1353
 
1354
  check_aux_info (l[0] == '/');
1355
  check_aux_info (l[1] == '*');
1356
  check_aux_info (l[2] == ' ');
1357
 
1358
  {
1359
    const char *filename_start = p = l + 3;
1360
 
1361
    while (*p != ':'
1362
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
1363
           || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1364
#endif
1365
           )
1366
      p++;
1367
    filename = alloca ((size_t) (p - filename_start) + 1);
1368
    strncpy (filename, filename_start, (size_t) (p - filename_start));
1369
    filename[p-filename_start] = '\0';
1370
  }
1371
 
1372
  /* Call find_file to find the file_info record associated with the file
1373
     which contained this particular def or dec item.  Note that this call
1374
     may cause a new file_info record to be created if this is the first time
1375
     that we have ever known about this particular file.  */
1376
 
1377
  fi_p = find_file (abspath (invocation_filename, filename), 0);
1378
 
1379
  return (fi_p->mtime > aux_info_mtime);
1380
}
1381
 
1382
/* Given a line of info from the aux_info file, create a new
1383
   def_dec_info record to remember all of the important information about
1384
   a function definition or declaration.
1385
 
1386
   Link this record onto the list of such records for the particular file in
1387
   which it occurred in proper (descending) line number order (for now).
1388
 
1389
   If there is an identical record already on the list for the file, throw
1390
   this one away.  Doing so takes care of the (useless and troublesome)
1391
   duplicates which are bound to crop up due to multiple inclusions of any
1392
   given individual header file.
1393
 
1394
   Finally, link the new def_dec record onto the list of such records
1395
   pertaining to this particular function name.  */
1396
 
1397
static void
1398
save_def_or_dec (const char *l, int is_syscalls)
1399
{
1400
  const char *p;
1401
  const char *semicolon_p;
1402
  def_dec_info *def_dec_p = xmalloc (sizeof (def_dec_info));
1403
 
1404
#ifndef UNPROTOIZE
1405
  def_dec_p->written = 0;
1406
#endif /* !defined (UNPROTOIZE) */
1407
 
1408
  /* Start processing the line by picking off 5 pieces of information from
1409
     the left hand end of the line.  These are filename, line number,
1410
     new/old/implicit flag (new = ANSI prototype format), definition or
1411
     declaration flag, and extern/static flag).  */
1412
 
1413
  check_aux_info (l[0] == '/');
1414
  check_aux_info (l[1] == '*');
1415
  check_aux_info (l[2] == ' ');
1416
 
1417
  {
1418
    const char *filename_start = p = l + 3;
1419
    char *filename;
1420
 
1421
    while (*p != ':'
1422
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
1423
           || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1424
#endif
1425
           )
1426
      p++;
1427
    filename = alloca ((size_t) (p - filename_start) + 1);
1428
    strncpy (filename, filename_start, (size_t) (p - filename_start));
1429
    filename[p-filename_start] = '\0';
1430
 
1431
    /* Call find_file to find the file_info record associated with the file
1432
       which contained this particular def or dec item.  Note that this call
1433
       may cause a new file_info record to be created if this is the first time
1434
       that we have ever known about this particular file.
1435
 
1436
       Note that we started out by forcing all of the base source file names
1437
       (i.e. the names of the aux_info files with the .X stripped off) into the
1438
       filenames hash table, and we simultaneously setup file_info records for
1439
       all of these base file names (even if they may be useless later).
1440
       The file_info records for all of these "base" file names (properly)
1441
       act as file_info records for the "original" (i.e. un-included) files
1442
       which were submitted to gcc for compilation (when the -aux-info
1443
       option was used).  */
1444
 
1445
    def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
1446
  }
1447
 
1448
  {
1449
    const char *line_number_start = ++p;
1450
    char line_number[10];
1451
 
1452
    while (*p != ':'
1453
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
1454
           || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
1455
#endif
1456
           )
1457
      p++;
1458
    strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
1459
    line_number[p-line_number_start] = '\0';
1460
    def_dec_p->line = atoi (line_number);
1461
  }
1462
 
1463
  /* Check that this record describes a new-style, old-style, or implicit
1464
     definition or declaration.  */
1465
 
1466
  p++;  /* Skip over the `:'.  */
1467
  check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
1468
 
1469
  /* Is this a new style (ANSI prototyped) definition or declaration? */
1470
 
1471
  def_dec_p->prototyped = (*p == 'N');
1472
 
1473
#ifndef UNPROTOIZE
1474
 
1475
  /* Is this an implicit declaration? */
1476
 
1477
  def_dec_p->is_implicit = (*p == 'I');
1478
 
1479
#endif /* !defined (UNPROTOIZE) */
1480
 
1481
  p++;
1482
 
1483
  check_aux_info ((*p == 'C') || (*p == 'F'));
1484
 
1485
  /* Is this item a function definition (F) or a declaration (C).  Note that
1486
     we treat item taken from the syscalls file as though they were function
1487
     definitions regardless of what the stuff in the file says.  */
1488
 
1489
  def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
1490
 
1491
#ifndef UNPROTOIZE
1492
  def_dec_p->definition = 0;     /* Fill this in later if protoizing.  */
1493
#endif /* !defined (UNPROTOIZE) */
1494
 
1495
  check_aux_info (*p++ == ' ');
1496
  check_aux_info (*p++ == '*');
1497
  check_aux_info (*p++ == '/');
1498
  check_aux_info (*p++ == ' ');
1499
 
1500
#ifdef UNPROTOIZE
1501
  check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
1502
#else /* !defined (UNPROTOIZE) */
1503
  if (!strncmp (p, "static", 6))
1504
    def_dec_p->is_static = -1;
1505
  else if (!strncmp (p, "extern", 6))
1506
    def_dec_p->is_static = 0;
1507
  else
1508
    check_aux_info (0);  /* Didn't find either `extern' or `static'.  */
1509
#endif /* !defined (UNPROTOIZE) */
1510
 
1511
  {
1512
    const char *ansi_start = p;
1513
 
1514
    p += 6;     /* Pass over the "static" or "extern".  */
1515
 
1516
    /* We are now past the initial stuff.  Search forward from here to find
1517
       the terminating semicolon that should immediately follow the entire
1518
       ANSI format function declaration.  */
1519
 
1520
    while (*++p != ';')
1521
      continue;
1522
 
1523
    semicolon_p = p;
1524
 
1525
    /* Make a copy of the ansi declaration part of the line from the aux_info
1526
       file.  */
1527
 
1528
    def_dec_p->ansi_decl
1529
      = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
1530
 
1531
    /* Backup and point at the final right paren of the final argument list.  */
1532
 
1533
    p--;
1534
 
1535
#ifndef UNPROTOIZE
1536
    def_dec_p->f_list_chain = NULL;
1537
#endif /* !defined (UNPROTOIZE) */
1538
 
1539
    while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
1540
    if (*p != ')')
1541
      {
1542
        free_def_dec (def_dec_p);
1543
        return;
1544
      }
1545
  }
1546
 
1547
  /* Now isolate a whole set of formal argument lists, one-by-one.  Normally,
1548
     there will only be one list to isolate, but there could be more.  */
1549
 
1550
  def_dec_p->f_list_count = 0;
1551
 
1552
  for (;;)
1553
    {
1554
      const char *left_paren_p = find_corresponding_lparen (p);
1555
#ifndef UNPROTOIZE
1556
      {
1557
        f_list_chain_item *cip = xmalloc (sizeof (f_list_chain_item));
1558
 
1559
        cip->formals_list
1560
          = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
1561
 
1562
        /* Add the new chain item at the head of the current list.  */
1563
 
1564
        cip->chain_next = def_dec_p->f_list_chain;
1565
        def_dec_p->f_list_chain = cip;
1566
      }
1567
#endif /* !defined (UNPROTOIZE) */
1568
      def_dec_p->f_list_count++;
1569
 
1570
      p = left_paren_p - 2;
1571
 
1572
      /* p must now point either to another right paren, or to the last
1573
         character of the name of the function that was declared/defined.
1574
         If p points to another right paren, then this indicates that we
1575
         are dealing with multiple formals lists.  In that case, there
1576
         really should be another right paren preceding this right paren.  */
1577
 
1578
      if (*p != ')')
1579
        break;
1580
      else
1581
        check_aux_info (*--p == ')');
1582
    }
1583
 
1584
 
1585
  {
1586
    const char *past_fn = p + 1;
1587
 
1588
    check_aux_info (*past_fn == ' ');
1589
 
1590
    /* Scan leftwards over the identifier that names the function.  */
1591
 
1592
    while (is_id_char (*p))
1593
      p--;
1594
    p++;
1595
 
1596
    /* p now points to the leftmost character of the function name.  */
1597
 
1598
    {
1599
      char *fn_string = alloca (past_fn - p + 1);
1600
 
1601
      strncpy (fn_string, p, (size_t) (past_fn - p));
1602
      fn_string[past_fn-p] = '\0';
1603
      def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
1604
    }
1605
  }
1606
 
1607
  /* Look at all of the defs and decs for this function name that we have
1608
     collected so far.  If there is already one which is at the same
1609
     line number in the same file, then we can discard this new def_dec_info
1610
     record.
1611
 
1612
     As an extra assurance that any such pair of (nominally) identical
1613
     function declarations are in fact identical, we also compare the
1614
     ansi_decl parts of the lines from the aux_info files just to be on
1615
     the safe side.
1616
 
1617
     This comparison will fail if (for instance) the user was playing
1618
     messy games with the preprocessor which ultimately causes one
1619
     function declaration in one header file to look differently when
1620
     that file is included by two (or more) other files.  */
1621
 
1622
  {
1623
    const def_dec_info *other;
1624
 
1625
    for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
1626
      {
1627
        if (def_dec_p->line == other->line && def_dec_p->file == other->file)
1628
          {
1629
            if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
1630
              {
1631
                notice ("%s:%d: declaration of function '%s' takes different forms\n",
1632
                        def_dec_p->file->hash_entry->symbol,
1633
                        def_dec_p->line,
1634
                        def_dec_p->hash_entry->symbol);
1635
                exit (FATAL_EXIT_CODE);
1636
              }
1637
            free_def_dec (def_dec_p);
1638
            return;
1639
          }
1640
      }
1641
  }
1642
 
1643
#ifdef UNPROTOIZE
1644
 
1645
  /* If we are doing unprotoizing, we must now setup the pointers that will
1646
     point to the K&R name list and to the K&R argument declarations list.
1647
 
1648
     Note that if this is only a function declaration, then we should not
1649
     expect to find any K&R style formals list following the ANSI-style
1650
     formals list.  This is because GCC knows that such information is
1651
     useless in the case of function declarations (function definitions
1652
     are a different story however).
1653
 
1654
     Since we are unprotoizing, we don't need any such lists anyway.
1655
     All we plan to do is to delete all characters between ()'s in any
1656
     case.  */
1657
 
1658
  def_dec_p->formal_names = NULL;
1659
  def_dec_p->formal_decls = NULL;
1660
 
1661
  if (def_dec_p->is_func_def)
1662
    {
1663
      p = semicolon_p;
1664
      check_aux_info (*++p == ' ');
1665
      check_aux_info (*++p == '/');
1666
      check_aux_info (*++p == '*');
1667
      check_aux_info (*++p == ' ');
1668
      check_aux_info (*++p == '(');
1669
 
1670
      {
1671
        const char *kr_names_start = ++p;   /* Point just inside '('.  */
1672
 
1673
        while (*p++ != ')')
1674
          continue;
1675
        p--;            /* point to closing right paren */
1676
 
1677
        /* Make a copy of the K&R parameter names list.  */
1678
 
1679
        def_dec_p->formal_names
1680
          = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
1681
      }
1682
 
1683
      check_aux_info (*++p == ' ');
1684
      p++;
1685
 
1686
      /* p now points to the first character of the K&R style declarations
1687
         list (if there is one) or to the star-slash combination that ends
1688
         the comment in which such lists get embedded.  */
1689
 
1690
      /* Make a copy of the K&R formal decls list and set the def_dec record
1691
         to point to it.  */
1692
 
1693
      if (*p == '*')            /* Are there no K&R declarations? */
1694
        {
1695
          check_aux_info (*++p == '/');
1696
          def_dec_p->formal_decls = "";
1697
        }
1698
      else
1699
        {
1700
          const char *kr_decls_start = p;
1701
 
1702
          while (p[0] != '*' || p[1] != '/')
1703
            p++;
1704
          p--;
1705
 
1706
          check_aux_info (*p == ' ');
1707
 
1708
          def_dec_p->formal_decls
1709
            = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
1710
        }
1711
 
1712
      /* Handle a special case.  If we have a function definition marked as
1713
         being in "old" style, and if its formal names list is empty, then
1714
         it may actually have the string "void" in its real formals list
1715
         in the original source code.  Just to make sure, we will get setup
1716
         to convert such things anyway.
1717
 
1718
         This kludge only needs to be here because of an insurmountable
1719
         problem with generating .X files.  */
1720
 
1721
      if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
1722
        def_dec_p->prototyped = 1;
1723
    }
1724
 
1725
  /* Since we are unprotoizing, if this item is already in old (K&R) style,
1726
     we can just ignore it.  If that is true, throw away the itme now.  */
1727
 
1728
  if (!def_dec_p->prototyped)
1729
    {
1730
      free_def_dec (def_dec_p);
1731
      return;
1732
    }
1733
 
1734
#endif /* defined (UNPROTOIZE) */
1735
 
1736
  /* Add this record to the head of the list of records pertaining to this
1737
     particular function name.  */
1738
 
1739
  def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
1740
  def_dec_p->hash_entry->ddip = def_dec_p;
1741
 
1742
  /* Add this new def_dec_info record to the sorted list of def_dec_info
1743
     records for this file.  Note that we don't have to worry about duplicates
1744
     (caused by multiple inclusions of header files) here because we have
1745
     already eliminated duplicates above.  */
1746
 
1747
  if (!def_dec_p->file->defs_decs)
1748
    {
1749
      def_dec_p->file->defs_decs = def_dec_p;
1750
      def_dec_p->next_in_file = NULL;
1751
    }
1752
  else
1753
    {
1754
      int line = def_dec_p->line;
1755
      const def_dec_info *prev = NULL;
1756
      const def_dec_info *curr = def_dec_p->file->defs_decs;
1757
      const def_dec_info *next = curr->next_in_file;
1758
 
1759
      while (next && (line < curr->line))
1760
        {
1761
          prev = curr;
1762
          curr = next;
1763
          next = next->next_in_file;
1764
        }
1765
      if (line >= curr->line)
1766
        {
1767
          def_dec_p->next_in_file = curr;
1768
          if (prev)
1769
            ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
1770
          else
1771
            def_dec_p->file->defs_decs = def_dec_p;
1772
        }
1773
      else      /* assert (next == NULL); */
1774
        {
1775
          ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
1776
          /* assert (next == NULL); */
1777
          def_dec_p->next_in_file = next;
1778
        }
1779
    }
1780
}
1781
 
1782
/* Set up the vector COMPILE_PARAMS which is the argument list for running GCC.
1783
   Also set input_file_name_index and aux_info_file_name_index
1784
   to the indices of the slots where the file names should go.  */
1785
 
1786
/* We initialize the vector by  removing -g, -O, -S, -c, and -o options,
1787
   and adding '-aux-info AUXFILE -S  -o /dev/null INFILE' at the end.  */
1788
 
1789
static void
1790
munge_compile_params (const char *params_list)
1791
{
1792
  /* Build up the contents in a temporary vector
1793
     that is so big that to has to be big enough.  */
1794
  const char **temp_params
1795
    = alloca ((strlen (params_list) + 8) * sizeof (char *));
1796
  int param_count = 0;
1797
  const char *param;
1798
  struct stat st;
1799
 
1800
  temp_params[param_count++] = compiler_file_name;
1801
  for (;;)
1802
    {
1803
      while (ISSPACE ((const unsigned char)*params_list))
1804
        params_list++;
1805
      if (!*params_list)
1806
        break;
1807
      param = params_list;
1808
      while (*params_list && !ISSPACE ((const unsigned char)*params_list))
1809
        params_list++;
1810
      if (param[0] != '-')
1811
        temp_params[param_count++]
1812
          = dupnstr (param, (size_t) (params_list - param));
1813
      else
1814
        {
1815
          switch (param[1])
1816
            {
1817
            case 'g':
1818
            case 'O':
1819
            case 'S':
1820
            case 'c':
1821
              break;            /* Don't copy these.  */
1822
            case 'o':
1823
              while (ISSPACE ((const unsigned char)*params_list))
1824
                params_list++;
1825
              while (*params_list
1826
                     && !ISSPACE ((const unsigned char)*params_list))
1827
                params_list++;
1828
              break;
1829
            default:
1830
              temp_params[param_count++]
1831
                = dupnstr (param, (size_t) (params_list - param));
1832
            }
1833
        }
1834
      if (!*params_list)
1835
        break;
1836
    }
1837
  temp_params[param_count++] = "-aux-info";
1838
 
1839
  /* Leave room for the aux-info file name argument.  */
1840
  aux_info_file_name_index = param_count;
1841
  temp_params[param_count++] = NULL;
1842
 
1843
  temp_params[param_count++] = "-S";
1844
  temp_params[param_count++] = "-o";
1845
 
1846
  if ((stat (HOST_BIT_BUCKET, &st) == 0)
1847
      && (!S_ISDIR (st.st_mode))
1848
      && (access (HOST_BIT_BUCKET, W_OK) == 0))
1849
    temp_params[param_count++] = HOST_BIT_BUCKET;
1850
  else
1851
    /* FIXME: This is hardly likely to be right, if HOST_BIT_BUCKET is not
1852
       writable.  But until this is rejigged to use make_temp_file(), this
1853
       is the best we can do.  */
1854
    temp_params[param_count++] = "/dev/null";
1855
 
1856
  /* Leave room for the input file name argument.  */
1857
  input_file_name_index = param_count;
1858
  temp_params[param_count++] = NULL;
1859
  /* Terminate the list.  */
1860
  temp_params[param_count++] = NULL;
1861
 
1862
  /* Make a copy of the compile_params in heap space.  */
1863
 
1864
  compile_params = xmalloc (sizeof (char *) * (param_count+1));
1865
  memcpy (compile_params, temp_params, sizeof (char *) * param_count);
1866
}
1867
 
1868
/* Do a recompilation for the express purpose of generating a new aux_info
1869
   file to go with a specific base source file.
1870
 
1871
   The result is a boolean indicating success.  */
1872
 
1873
static int
1874
gen_aux_info_file (const char *base_filename)
1875
{
1876
  if (!input_file_name_index)
1877
    munge_compile_params ("");
1878
 
1879
  /* Store the full source file name in the argument vector.  */
1880
  compile_params[input_file_name_index] = shortpath (NULL, base_filename);
1881
  /* Add .X to source file name to get aux-info file name.  */
1882
  compile_params[aux_info_file_name_index] =
1883
    concat (compile_params[input_file_name_index], aux_info_suffix, NULL);
1884
 
1885
  if (!quiet_flag)
1886
    notice ("%s: compiling '%s'\n",
1887
            pname, compile_params[input_file_name_index]);
1888
 
1889
  {
1890
    char *errmsg_fmt, *errmsg_arg;
1891
    int wait_status, pid;
1892
 
1893
    pid = pexecute (compile_params[0], (char * const *) compile_params,
1894
                    pname, NULL, &errmsg_fmt, &errmsg_arg,
1895
                    PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
1896
 
1897
    if (pid == -1)
1898
      {
1899
        int errno_val = errno;
1900
        fprintf (stderr, "%s: ", pname);
1901
        fprintf (stderr, errmsg_fmt, errmsg_arg);
1902
        fprintf (stderr, ": %s\n", xstrerror (errno_val));
1903
        return 0;
1904
      }
1905
 
1906
    pid = pwait (pid, &wait_status, 0);
1907
    if (pid == -1)
1908
      {
1909
        notice ("%s: wait: %s\n", pname, xstrerror (errno));
1910
        return 0;
1911
      }
1912
    if (WIFSIGNALED (wait_status))
1913
      {
1914
        notice ("%s: subprocess got fatal signal %d\n",
1915
                pname, WTERMSIG (wait_status));
1916
        return 0;
1917
      }
1918
    if (WIFEXITED (wait_status))
1919
      {
1920
        if (WEXITSTATUS (wait_status) != 0)
1921
          {
1922
            notice ("%s: %s exited with status %d\n",
1923
                    pname, compile_params[0], WEXITSTATUS (wait_status));
1924
            return 0;
1925
          }
1926
        return 1;
1927
      }
1928
    gcc_unreachable ();
1929
  }
1930
}
1931
 
1932
/* Read in all of the information contained in a single aux_info file.
1933
   Save all of the important stuff for later.  */
1934
 
1935
static void
1936
process_aux_info_file (const char *base_source_filename, int keep_it,
1937
                       int is_syscalls)
1938
{
1939
  size_t base_len = strlen (base_source_filename);
1940
  char * aux_info_filename = alloca (base_len + strlen (aux_info_suffix) + 1);
1941
  char *aux_info_base;
1942
  char *aux_info_limit;
1943
  char *aux_info_relocated_name;
1944
  const char *aux_info_second_line;
1945
  time_t aux_info_mtime;
1946
  size_t aux_info_size;
1947
  int must_create;
1948
 
1949
  /* Construct the aux_info filename from the base source filename.  */
1950
 
1951
  strcpy (aux_info_filename, base_source_filename);
1952
  strcat (aux_info_filename, aux_info_suffix);
1953
 
1954
  /* Check that the aux_info file exists and is readable.  If it does not
1955
     exist, try to create it (once only).  */
1956
 
1957
  /* If file doesn't exist, set must_create.
1958
     Likewise if it exists and we can read it but it is obsolete.
1959
     Otherwise, report an error.  */
1960
  must_create = 0;
1961
 
1962
  /* Come here with must_create set to 1 if file is out of date.  */
1963
start_over: ;
1964
 
1965
  if (access (aux_info_filename, R_OK) == -1)
1966
    {
1967
      if (errno == ENOENT)
1968
        {
1969
          if (is_syscalls)
1970
            {
1971
              notice ("%s: warning: missing SYSCALLS file '%s'\n",
1972
                      pname, aux_info_filename);
1973
              return;
1974
            }
1975
          must_create = 1;
1976
        }
1977
      else
1978
        {
1979
          int errno_val = errno;
1980
          notice ("%s: can't read aux info file '%s': %s\n",
1981
                  pname, shortpath (NULL, aux_info_filename),
1982
                  xstrerror (errno_val));
1983
          errors++;
1984
          return;
1985
        }
1986
    }
1987
#if 0 /* There is code farther down to take care of this.  */
1988
  else
1989
    {
1990
      struct stat s1, s2;
1991
      stat (aux_info_file_name, &s1);
1992
      stat (base_source_file_name, &s2);
1993
      if (s2.st_mtime > s1.st_mtime)
1994
        must_create = 1;
1995
    }
1996
#endif /* 0 */
1997
 
1998
  /* If we need a .X file, create it, and verify we can read it.  */
1999
  if (must_create)
2000
    {
2001
      if (!gen_aux_info_file (base_source_filename))
2002
        {
2003
          errors++;
2004
          return;
2005
        }
2006
      if (access (aux_info_filename, R_OK) == -1)
2007
        {
2008
          int errno_val = errno;
2009
          notice ("%s: can't read aux info file '%s': %s\n",
2010
                  pname, shortpath (NULL, aux_info_filename),
2011
                  xstrerror (errno_val));
2012
          errors++;
2013
          return;
2014
        }
2015
    }
2016
 
2017
  {
2018
    struct stat stat_buf;
2019
 
2020
    /* Get some status information about this aux_info file.  */
2021
 
2022
    if (stat (aux_info_filename, &stat_buf) == -1)
2023
      {
2024
        int errno_val = errno;
2025
        notice ("%s: can't get status of aux info file '%s': %s\n",
2026
                pname, shortpath (NULL, aux_info_filename),
2027
                xstrerror (errno_val));
2028
        errors++;
2029
        return;
2030
      }
2031
 
2032
    /* Check on whether or not this aux_info file is zero length.  If it is,
2033
       then just ignore it and return.  */
2034
 
2035
    if ((aux_info_size = stat_buf.st_size) == 0)
2036
      return;
2037
 
2038
    /* Get the date/time of last modification for this aux_info file and
2039
       remember it.  We will have to check that any source files that it
2040
       contains information about are at least this old or older.  */
2041
 
2042
    aux_info_mtime = stat_buf.st_mtime;
2043
 
2044
    if (!is_syscalls)
2045
      {
2046
        /* Compare mod time with the .c file; update .X file if obsolete.
2047
           The code later on can fail to check the .c file
2048
           if it did not directly define any functions.  */
2049
 
2050
        if (stat (base_source_filename, &stat_buf) == -1)
2051
          {
2052
            int errno_val = errno;
2053
            notice ("%s: can't get status of aux info file '%s': %s\n",
2054
                    pname, shortpath (NULL, base_source_filename),
2055
                    xstrerror (errno_val));
2056
            errors++;
2057
            return;
2058
          }
2059
        if (stat_buf.st_mtime > aux_info_mtime)
2060
          {
2061
            must_create = 1;
2062
            goto start_over;
2063
          }
2064
      }
2065
  }
2066
 
2067
  {
2068
    int aux_info_file;
2069
    int fd_flags;
2070
 
2071
    /* Open the aux_info file.  */
2072
 
2073
    fd_flags = O_RDONLY;
2074
#ifdef O_BINARY
2075
    /* Use binary mode to avoid having to deal with different EOL characters.  */
2076
    fd_flags |= O_BINARY;
2077
#endif
2078
    if ((aux_info_file = open (aux_info_filename, fd_flags, 0444 )) == -1)
2079
      {
2080
        int errno_val = errno;
2081
        notice ("%s: can't open aux info file '%s' for reading: %s\n",
2082
                pname, shortpath (NULL, aux_info_filename),
2083
                xstrerror (errno_val));
2084
        return;
2085
      }
2086
 
2087
    /* Allocate space to hold the aux_info file in memory.  */
2088
 
2089
    aux_info_base = xmalloc (aux_info_size + 1);
2090
    aux_info_limit = aux_info_base + aux_info_size;
2091
    *aux_info_limit = '\0';
2092
 
2093
    /* Read the aux_info file into memory.  */
2094
 
2095
    if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
2096
        (int) aux_info_size)
2097
      {
2098
        int errno_val = errno;
2099
        notice ("%s: error reading aux info file '%s': %s\n",
2100
                pname, shortpath (NULL, aux_info_filename),
2101
                xstrerror (errno_val));
2102
        free (aux_info_base);
2103
        close (aux_info_file);
2104
        return;
2105
      }
2106
 
2107
    /* Close the aux info file.  */
2108
 
2109
    if (close (aux_info_file))
2110
      {
2111
        int errno_val = errno;
2112
        notice ("%s: error closing aux info file '%s': %s\n",
2113
                pname, shortpath (NULL, aux_info_filename),
2114
                xstrerror (errno_val));
2115
        free (aux_info_base);
2116
        close (aux_info_file);
2117
        return;
2118
      }
2119
  }
2120
 
2121
  /* Delete the aux_info file (unless requested not to).  If the deletion
2122
     fails for some reason, don't even worry about it.  */
2123
 
2124
  if (must_create && !keep_it)
2125
    if (unlink (aux_info_filename) == -1)
2126
      {
2127
        int errno_val = errno;
2128
        notice ("%s: can't delete aux info file '%s': %s\n",
2129
                pname, shortpath (NULL, aux_info_filename),
2130
                xstrerror (errno_val));
2131
      }
2132
 
2133
  /* Save a pointer into the first line of the aux_info file which
2134
     contains the filename of the directory from which the compiler
2135
     was invoked when the associated source file was compiled.
2136
     This information is used later to help create complete
2137
     filenames out of the (potentially) relative filenames in
2138
     the aux_info file.  */
2139
 
2140
  {
2141
    char *p = aux_info_base;
2142
 
2143
    while (*p != ':'
2144
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
2145
           || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
2146
#endif
2147
           )
2148
      p++;
2149
    p++;
2150
    while (*p == ' ')
2151
      p++;
2152
    invocation_filename = p;    /* Save a pointer to first byte of path.  */
2153
    while (*p != ' ')
2154
      p++;
2155
    *p++ = DIR_SEPARATOR;
2156
    *p++ = '\0';
2157
    while (*p++ != '\n')
2158
      continue;
2159
    aux_info_second_line = p;
2160
    aux_info_relocated_name = 0;
2161
    if (! IS_ABSOLUTE_PATH (invocation_filename))
2162
      {
2163
        /* INVOCATION_FILENAME is relative;
2164
           append it to BASE_SOURCE_FILENAME's dir.  */
2165
        char *dir_end;
2166
        aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
2167
        strcpy (aux_info_relocated_name, base_source_filename);
2168
        dir_end = strrchr (aux_info_relocated_name, DIR_SEPARATOR);
2169
#ifdef DIR_SEPARATOR_2
2170
        {
2171
          char *slash;
2172
 
2173
          slash = strrchr (dir_end ? dir_end : aux_info_relocated_name,
2174
                           DIR_SEPARATOR_2);
2175
          if (slash)
2176
            dir_end = slash;
2177
        }
2178
#endif
2179
        if (dir_end)
2180
          dir_end++;
2181
        else
2182
          dir_end = aux_info_relocated_name;
2183
        strcpy (dir_end, invocation_filename);
2184
        invocation_filename = aux_info_relocated_name;
2185
      }
2186
  }
2187
 
2188
 
2189
  {
2190
    const char *aux_info_p;
2191
 
2192
    /* Do a pre-pass on the lines in the aux_info file, making sure that all
2193
       of the source files referenced in there are at least as old as this
2194
       aux_info file itself.  If not, go back and regenerate the aux_info
2195
       file anew.  Don't do any of this for the syscalls file.  */
2196
 
2197
    if (!is_syscalls)
2198
      {
2199
        current_aux_info_lineno = 2;
2200
 
2201
        for (aux_info_p = aux_info_second_line; *aux_info_p; )
2202
          {
2203
            if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
2204
              {
2205
                free (aux_info_base);
2206
                free (aux_info_relocated_name);
2207
                if (keep_it && unlink (aux_info_filename) == -1)
2208
                  {
2209
                    int errno_val = errno;
2210
                    notice ("%s: can't delete file '%s': %s\n",
2211
                            pname, shortpath (NULL, aux_info_filename),
2212
                            xstrerror (errno_val));
2213
                    return;
2214
                  }
2215
                must_create = 1;
2216
                goto start_over;
2217
              }
2218
 
2219
            /* Skip over the rest of this line to start of next line.  */
2220
 
2221
            while (*aux_info_p != '\n')
2222
              aux_info_p++;
2223
            aux_info_p++;
2224
            current_aux_info_lineno++;
2225
          }
2226
      }
2227
 
2228
    /* Now do the real pass on the aux_info lines.  Save their information in
2229
       the in-core data base.  */
2230
 
2231
    current_aux_info_lineno = 2;
2232
 
2233
    for (aux_info_p = aux_info_second_line; *aux_info_p;)
2234
      {
2235
        char *unexpanded_line = unexpand_if_needed (aux_info_p);
2236
 
2237
        if (unexpanded_line)
2238
          {
2239
            save_def_or_dec (unexpanded_line, is_syscalls);
2240
            free (unexpanded_line);
2241
          }
2242
        else
2243
          save_def_or_dec (aux_info_p, is_syscalls);
2244
 
2245
        /* Skip over the rest of this line and get to start of next line.  */
2246
 
2247
        while (*aux_info_p != '\n')
2248
          aux_info_p++;
2249
        aux_info_p++;
2250
        current_aux_info_lineno++;
2251
      }
2252
  }
2253
 
2254
  free (aux_info_base);
2255
  free (aux_info_relocated_name);
2256
}
2257
 
2258
#ifndef UNPROTOIZE
2259
 
2260
/* Check an individual filename for a .c suffix.  If the filename has this
2261
   suffix, rename the file such that its suffix is changed to .C.  This
2262
   function implements the -C option.  */
2263
 
2264
static void
2265
rename_c_file (const hash_table_entry *hp)
2266
{
2267
  const char *filename = hp->symbol;
2268
  int last_char_index = strlen (filename) - 1;
2269
  char *const new_filename = alloca (strlen (filename)
2270
                                     + strlen (cplus_suffix) + 1);
2271
 
2272
  /* Note that we don't care here if the given file was converted or not.  It
2273
     is possible that the given file was *not* converted, simply because there
2274
     was nothing in it which actually required conversion.  Even in this case,
2275
     we want to do the renaming.  Note that we only rename files with the .c
2276
     suffix (except for the syscalls file, which is left alone).  */
2277
 
2278
  if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.'
2279
      || IS_SAME_PATH (syscalls_absolute_filename, filename))
2280
    return;
2281
 
2282
  strcpy (new_filename, filename);
2283
  strcpy (&new_filename[last_char_index], cplus_suffix);
2284
 
2285
  if (rename (filename, new_filename) == -1)
2286
    {
2287
      int errno_val = errno;
2288
      notice ("%s: warning: can't rename file '%s' to '%s': %s\n",
2289
              pname, shortpath (NULL, filename),
2290
              shortpath (NULL, new_filename), xstrerror (errno_val));
2291
      errors++;
2292
      return;
2293
    }
2294
}
2295
 
2296
#endif /* !defined (UNPROTOIZE) */
2297
 
2298
/* Take the list of definitions and declarations attached to a particular
2299
   file_info node and reverse the order of the list.  This should get the
2300
   list into an order such that the item with the lowest associated line
2301
   number is nearest the head of the list.  When these lists are originally
2302
   built, they are in the opposite order.  We want to traverse them in
2303
   normal line number order later (i.e. lowest to highest) so reverse the
2304
   order here.  */
2305
 
2306
static void
2307
reverse_def_dec_list (const hash_table_entry *hp)
2308
{
2309
  file_info *file_p = hp->fip;
2310
  def_dec_info *prev = NULL;
2311
  def_dec_info *current = (def_dec_info *) file_p->defs_decs;
2312
 
2313
  if (!current)
2314
    return;                     /* no list to reverse */
2315
 
2316
  prev = current;
2317
  if (! (current = (def_dec_info *) current->next_in_file))
2318
    return;                     /* can't reverse a single list element */
2319
 
2320
  prev->next_in_file = NULL;
2321
 
2322
  while (current)
2323
    {
2324
      def_dec_info *next = (def_dec_info *) current->next_in_file;
2325
 
2326
      current->next_in_file = prev;
2327
      prev = current;
2328
      current = next;
2329
    }
2330
 
2331
  file_p->defs_decs = prev;
2332
}
2333
 
2334
#ifndef UNPROTOIZE
2335
 
2336
/* Find the (only?) extern definition for a particular function name, starting
2337
   from the head of the linked list of entries for the given name.  If we
2338
   cannot find an extern definition for the given function name, issue a
2339
   warning and scrounge around for the next best thing, i.e. an extern
2340
   function declaration with a prototype attached to it.  Note that we only
2341
   allow such substitutions for extern declarations and never for static
2342
   declarations.  That's because the only reason we allow them at all is
2343
   to let un-prototyped function declarations for system-supplied library
2344
   functions get their prototypes from our own extra SYSCALLS.c.X file which
2345
   contains all of the correct prototypes for system functions.  */
2346
 
2347
static const def_dec_info *
2348
find_extern_def (const def_dec_info *head, const def_dec_info *user)
2349
{
2350
  const def_dec_info *dd_p;
2351
  const def_dec_info *extern_def_p = NULL;
2352
  int conflict_noted = 0;
2353
 
2354
  /* Don't act too stupid here.  Somebody may try to convert an entire system
2355
     in one swell fwoop (rather than one program at a time, as should be done)
2356
     and in that case, we may find that there are multiple extern definitions
2357
     of a given function name in the entire set of source files that we are
2358
     converting.  If however one of these definitions resides in exactly the
2359
     same source file as the reference we are trying to satisfy then in that
2360
     case it would be stupid for us to fail to realize that this one definition
2361
     *must* be the precise one we are looking for.
2362
 
2363
     To make sure that we don't miss an opportunity to make this "same file"
2364
     leap of faith, we do a prescan of the list of records relating to the
2365
     given function name, and we look (on this first scan) *only* for a
2366
     definition of the function which is in the same file as the reference
2367
     we are currently trying to satisfy.  */
2368
 
2369
  for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2370
    if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
2371
      return dd_p;
2372
 
2373
  /* Now, since we have not found a definition in the same file as the
2374
     reference, we scan the list again and consider all possibilities from
2375
     all files.  Here we may get conflicts with the things listed in the
2376
     SYSCALLS.c.X file, but if that happens it only means that the source
2377
     code being converted contains its own definition of a function which
2378
     could have been supplied by libc.a.  In such cases, we should avoid
2379
     issuing the normal warning, and defer to the definition given in the
2380
     user's own code.  */
2381
 
2382
  for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2383
    if (dd_p->is_func_def && !dd_p->is_static)
2384
      {
2385
        if (!extern_def_p)      /* Previous definition? */
2386
          extern_def_p = dd_p;  /* Remember the first definition found.  */
2387
        else
2388
          {
2389
            /* Ignore definition just found if it came from SYSCALLS.c.X.  */
2390
 
2391
            if (is_syscalls_file (dd_p->file))
2392
              continue;
2393
 
2394
            /* Quietly replace the definition previously found with the one
2395
               just found if the previous one was from SYSCALLS.c.X.  */
2396
 
2397
            if (is_syscalls_file (extern_def_p->file))
2398
              {
2399
                extern_def_p = dd_p;
2400
                continue;
2401
              }
2402
 
2403
            /* If we get here, then there is a conflict between two function
2404
               declarations for the same function, both of which came from the
2405
               user's own code.  */
2406
 
2407
            if (!conflict_noted)        /* first time we noticed? */
2408
              {
2409
                conflict_noted = 1;
2410
                notice ("%s: conflicting extern definitions of '%s'\n",
2411
                        pname, head->hash_entry->symbol);
2412
                if (!quiet_flag)
2413
                  {
2414
                    notice ("%s: declarations of '%s' will not be converted\n",
2415
                            pname, head->hash_entry->symbol);
2416
                    notice ("%s: conflict list for '%s' follows:\n",
2417
                            pname, head->hash_entry->symbol);
2418
                    fprintf (stderr, "%s:     %s(%d): %s\n",
2419
                             pname,
2420
                             shortpath (NULL, extern_def_p->file->hash_entry->symbol),
2421
                             extern_def_p->line, extern_def_p->ansi_decl);
2422
                  }
2423
              }
2424
            if (!quiet_flag)
2425
              fprintf (stderr, "%s:     %s(%d): %s\n",
2426
                       pname,
2427
                       shortpath (NULL, dd_p->file->hash_entry->symbol),
2428
                       dd_p->line, dd_p->ansi_decl);
2429
          }
2430
      }
2431
 
2432
  /* We want to err on the side of caution, so if we found multiple conflicting
2433
     definitions for the same function, treat this as being that same as if we
2434
     had found no definitions (i.e. return NULL).  */
2435
 
2436
  if (conflict_noted)
2437
    return NULL;
2438
 
2439
  if (!extern_def_p)
2440
    {
2441
      /* We have no definitions for this function so do the next best thing.
2442
         Search for an extern declaration already in prototype form.  */
2443
 
2444
      for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2445
        if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
2446
          {
2447
            extern_def_p = dd_p;        /* save a pointer to the definition */
2448
            if (!quiet_flag)
2449
              notice ("%s: warning: using formals list from %s(%d) for function '%s'\n",
2450
                      pname,
2451
                      shortpath (NULL, dd_p->file->hash_entry->symbol),
2452
                      dd_p->line, dd_p->hash_entry->symbol);
2453
            break;
2454
          }
2455
 
2456
      /* Gripe about unprototyped function declarations that we found no
2457
         corresponding definition (or other source of prototype information)
2458
         for.
2459
 
2460
         Gripe even if the unprototyped declaration we are worried about
2461
         exists in a file in one of the "system" include directories.  We
2462
         can gripe about these because we should have at least found a
2463
         corresponding (pseudo) definition in the SYSCALLS.c.X file.  If we
2464
         didn't, then that means that the SYSCALLS.c.X file is missing some
2465
         needed prototypes for this particular system.  That is worth telling
2466
         the user about!  */
2467
 
2468
      if (!extern_def_p)
2469
        {
2470
          const char *file = user->file->hash_entry->symbol;
2471
 
2472
          if (!quiet_flag)
2473
            if (in_system_include_dir (file))
2474
              {
2475
                /* Why copy this string into `needed' at all?
2476
                   Why not just use user->ansi_decl without copying?  */
2477
                char *needed = alloca (strlen (user->ansi_decl) + 1);
2478
                char *p;
2479
 
2480
                strcpy (needed, user->ansi_decl);
2481
                p = strstr (needed, user->hash_entry->symbol)
2482
                    + strlen (user->hash_entry->symbol) + 2;
2483
                /* Avoid having ??? in the string.  */
2484
                *p++ = '?';
2485
                *p++ = '?';
2486
                *p++ = '?';
2487
                strcpy (p, ");");
2488
 
2489
                notice ("%s: %d: '%s' used but missing from SYSCALLS\n",
2490
                        shortpath (NULL, file), user->line,
2491
                        needed+7);      /* Don't print "extern " */
2492
              }
2493
#if 0
2494
            else
2495
              notice ("%s: %d: warning: no extern definition for '%s'\n",
2496
                      shortpath (NULL, file), user->line,
2497
                      user->hash_entry->symbol);
2498
#endif
2499
        }
2500
    }
2501
  return extern_def_p;
2502
}
2503
 
2504
/* Find the (only?) static definition for a particular function name in a
2505
   given file.  Here we get the function-name and the file info indirectly
2506
   from the def_dec_info record pointer which is passed in.  */
2507
 
2508
static const def_dec_info *
2509
find_static_definition (const def_dec_info *user)
2510
{
2511
  const def_dec_info *head = user->hash_entry->ddip;
2512
  const def_dec_info *dd_p;
2513
  int num_static_defs = 0;
2514
  const def_dec_info *static_def_p = NULL;
2515
 
2516
  for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
2517
    if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
2518
      {
2519
        static_def_p = dd_p;    /* save a pointer to the definition */
2520
        num_static_defs++;
2521
      }
2522
  if (num_static_defs == 0)
2523
    {
2524
      if (!quiet_flag)
2525
        notice ("%s: warning: no static definition for '%s' in file '%s'\n",
2526
                pname, head->hash_entry->symbol,
2527
                shortpath (NULL, user->file->hash_entry->symbol));
2528
    }
2529
  else if (num_static_defs > 1)
2530
    {
2531
      notice ("%s: multiple static defs of '%s' in file '%s'\n",
2532
              pname, head->hash_entry->symbol,
2533
              shortpath (NULL, user->file->hash_entry->symbol));
2534
      return NULL;
2535
    }
2536
  return static_def_p;
2537
}
2538
 
2539
/* Find good prototype style formal argument lists for all of the function
2540
   declarations which didn't have them before now.
2541
 
2542
   To do this we consider each function name one at a time.  For each function
2543
   name, we look at the items on the linked list of def_dec_info records for
2544
   that particular name.
2545
 
2546
   Somewhere on this list we should find one (and only one) def_dec_info
2547
   record which represents the actual function definition, and this record
2548
   should have a nice formal argument list already associated with it.
2549
 
2550
   Thus, all we have to do is to connect up all of the other def_dec_info
2551
   records for this particular function name to the special one which has
2552
   the full-blown formals list.
2553
 
2554
   Of course it is a little more complicated than just that.  See below for
2555
   more details.  */
2556
 
2557
static void
2558
connect_defs_and_decs (const hash_table_entry *hp)
2559
{
2560
  const def_dec_info *dd_p;
2561
  const def_dec_info *extern_def_p = NULL;
2562
  int first_extern_reference = 1;
2563
 
2564
  /* Traverse the list of definitions and declarations for this particular
2565
     function name.  For each item on the list, if it is a function
2566
     definition (either old style or new style) then GCC has already been
2567
     kind enough to produce a prototype for us, and it is associated with
2568
     the item already, so declare the item as its own associated "definition".
2569
 
2570
     Also, for each item which is only a function declaration, but which
2571
     nonetheless has its own prototype already (obviously supplied by the user)
2572
     declare the item as its own definition.
2573
 
2574
     Note that when/if there are multiple user-supplied prototypes already
2575
     present for multiple declarations of any given function, these multiple
2576
     prototypes *should* all match exactly with one another and with the
2577
     prototype for the actual function definition.  We don't check for this
2578
     here however, since we assume that the compiler must have already done
2579
     this consistency checking when it was creating the .X files.  */
2580
 
2581
  for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2582
    if (dd_p->prototyped)
2583
      ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
2584
 
2585
  /* Traverse the list of definitions and declarations for this particular
2586
     function name.  For each item on the list, if it is an extern function
2587
     declaration and if it has no associated definition yet, go try to find
2588
     the matching extern definition for the declaration.
2589
 
2590
     When looking for the matching function definition, warn the user if we
2591
     fail to find one.
2592
 
2593
     If we find more that one function definition also issue a warning.
2594
 
2595
     Do the search for the matching definition only once per unique function
2596
     name (and only when absolutely needed) so that we can avoid putting out
2597
     redundant warning messages, and so that we will only put out warning
2598
     messages when there is actually a reference (i.e. a declaration) for
2599
     which we need to find a matching definition.  */
2600
 
2601
  for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2602
    if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
2603
      {
2604
        if (first_extern_reference)
2605
          {
2606
            extern_def_p = find_extern_def (hp->ddip, dd_p);
2607
            first_extern_reference = 0;
2608
          }
2609
        ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
2610
      }
2611
 
2612
  /* Traverse the list of definitions and declarations for this particular
2613
     function name.  For each item on the list, if it is a static function
2614
     declaration and if it has no associated definition yet, go try to find
2615
     the matching static definition for the declaration within the same file.
2616
 
2617
     When looking for the matching function definition, warn the user if we
2618
     fail to find one in the same file with the declaration, and refuse to
2619
     convert this kind of cross-file static function declaration.  After all,
2620
     this is stupid practice and should be discouraged.
2621
 
2622
     We don't have to worry about the possibility that there is more than one
2623
     matching function definition in the given file because that would have
2624
     been flagged as an error by the compiler.
2625
 
2626
     Do the search for the matching definition only once per unique
2627
     function-name/source-file pair (and only when absolutely needed) so that
2628
     we can avoid putting out redundant warning messages, and so that we will
2629
     only put out warning messages when there is actually a reference (i.e. a
2630
     declaration) for which we actually need to find a matching definition.  */
2631
 
2632
  for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2633
    if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
2634
      {
2635
        const def_dec_info *dd_p2;
2636
        const def_dec_info *static_def;
2637
 
2638
        /* We have now found a single static declaration for which we need to
2639
           find a matching definition.  We want to minimize the work (and the
2640
           number of warnings), so we will find an appropriate (matching)
2641
           static definition for this declaration, and then distribute it
2642
           (as the definition for) any and all other static declarations
2643
           for this function name which occur within the same file, and which
2644
           do not already have definitions.
2645
 
2646
           Note that a trick is used here to prevent subsequent attempts to
2647
           call find_static_definition for a given function-name & file
2648
           if the first such call returns NULL.  Essentially, we convert
2649
           these NULL return values to -1, and put the -1 into the definition
2650
           field for each other static declaration from the same file which
2651
           does not already have an associated definition.
2652
           This makes these other static declarations look like they are
2653
           actually defined already when the outer loop here revisits them
2654
           later on.  Thus, the outer loop will skip over them.  Later, we
2655
           turn the -1's back to NULL's.  */
2656
 
2657
        ((NONCONST def_dec_info *) dd_p)->definition =
2658
          (static_def = find_static_definition (dd_p))
2659
          ? static_def
2660
          : (const def_dec_info *) -1;
2661
 
2662
        for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
2663
          if (!dd_p2->is_func_def && dd_p2->is_static
2664
              && !dd_p2->definition && (dd_p2->file == dd_p->file))
2665
            ((NONCONST def_dec_info *) dd_p2)->definition = dd_p->definition;
2666
      }
2667
 
2668
  /* Convert any dummy (-1) definitions we created in the step above back to
2669
     NULL's (as they should be).  */
2670
 
2671
  for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
2672
    if (dd_p->definition == (def_dec_info *) -1)
2673
      ((NONCONST def_dec_info *) dd_p)->definition = NULL;
2674
}
2675
 
2676
#endif /* !defined (UNPROTOIZE) */
2677
 
2678
/* Give a pointer into the clean text buffer, return a number which is the
2679
   original source line number that the given pointer points into.  */
2680
 
2681
static int
2682
identify_lineno (const char *clean_p)
2683
{
2684
  int line_num = 1;
2685
  const char *scan_p;
2686
 
2687
  for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
2688
    if (*scan_p == '\n')
2689
      line_num++;
2690
  return line_num;
2691
}
2692
 
2693
/* Issue an error message and give up on doing this particular edit.  */
2694
 
2695
static void
2696
declare_source_confusing (const char *clean_p)
2697
{
2698
  if (!quiet_flag)
2699
    {
2700
      if (clean_p == 0)
2701
        notice ("%s: %d: warning: source too confusing\n",
2702
                shortpath (NULL, convert_filename), last_known_line_number);
2703
      else
2704
        notice ("%s: %d: warning: source too confusing\n",
2705
                shortpath (NULL, convert_filename),
2706
                identify_lineno (clean_p));
2707
    }
2708
  longjmp (source_confusion_recovery, 1);
2709
}
2710
 
2711
/* Check that a condition which is expected to be true in the original source
2712
   code is in fact true.  If not, issue an error message and give up on
2713
   converting this particular source file.  */
2714
 
2715
static void
2716
check_source (int cond, const char *clean_p)
2717
{
2718
  if (!cond)
2719
    declare_source_confusing (clean_p);
2720
}
2721
 
2722
/* If we think of the in-core cleaned text buffer as a memory mapped
2723
   file (with the variable last_known_line_start acting as sort of a
2724
   file pointer) then we can imagine doing "seeks" on the buffer.  The
2725
   following routine implements a kind of "seek" operation for the in-core
2726
   (cleaned) copy of the source file.  When finished, it returns a pointer to
2727
   the start of a given (numbered) line in the cleaned text buffer.
2728
 
2729
   Note that protoize only has to "seek" in the forward direction on the
2730
   in-core cleaned text file buffers, and it never needs to back up.
2731
 
2732
   This routine is made a little bit faster by remembering the line number
2733
   (and pointer value) supplied (and returned) from the previous "seek".
2734
   This prevents us from always having to start all over back at the top
2735
   of the in-core cleaned buffer again.  */
2736
 
2737
static const char *
2738
seek_to_line (int n)
2739
{
2740
  gcc_assert (n >= last_known_line_number);
2741
 
2742
  while (n > last_known_line_number)
2743
    {
2744
      while (*last_known_line_start != '\n')
2745
        check_source (++last_known_line_start < clean_text_limit, 0);
2746
      last_known_line_start++;
2747
      last_known_line_number++;
2748
    }
2749
  return last_known_line_start;
2750
}
2751
 
2752
/* Given a pointer to a character in the cleaned text buffer, return a pointer
2753
   to the next non-whitespace character which follows it.  */
2754
 
2755
static const char *
2756
forward_to_next_token_char (const char *ptr)
2757
{
2758
  for (++ptr; ISSPACE ((const unsigned char)*ptr);
2759
       check_source (++ptr < clean_text_limit, 0))
2760
    continue;
2761
  return ptr;
2762
}
2763
 
2764
/* Copy a chunk of text of length `len' and starting at `str' to the current
2765
   output buffer.  Note that all attempts to add stuff to the current output
2766
   buffer ultimately go through here.  */
2767
 
2768
static void
2769
output_bytes (const char *str, size_t len)
2770
{
2771
  if ((repl_write_ptr + 1) + len >= repl_text_limit)
2772
    {
2773
      size_t new_size = (repl_text_limit - repl_text_base) << 1;
2774
      char *new_buf = xrealloc (repl_text_base, new_size);
2775
 
2776
      repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
2777
      repl_text_base = new_buf;
2778
      repl_text_limit = new_buf + new_size;
2779
    }
2780
  memcpy (repl_write_ptr + 1, str, len);
2781
  repl_write_ptr += len;
2782
}
2783
 
2784
/* Copy all bytes (except the trailing null) of a null terminated string to
2785
   the current output buffer.  */
2786
 
2787
static void
2788
output_string (const char *str)
2789
{
2790
  output_bytes (str, strlen (str));
2791
}
2792
 
2793
/* Copy some characters from the original text buffer to the current output
2794
   buffer.
2795
 
2796
   This routine takes a pointer argument `p' which is assumed to be a pointer
2797
   into the cleaned text buffer.  The bytes which are copied are the `original'
2798
   equivalents for the set of bytes between the last value of `clean_read_ptr'
2799
   and the argument value `p'.
2800
 
2801
   The set of bytes copied however, comes *not* from the cleaned text buffer,
2802
   but rather from the direct counterparts of these bytes within the original
2803
   text buffer.
2804
 
2805
   Thus, when this function is called, some bytes from the original text
2806
   buffer (which may include original comments and preprocessing directives)
2807
   will be copied into the  output buffer.
2808
 
2809
   Note that the request implied when this routine is called includes the
2810
   byte pointed to by the argument pointer `p'.  */
2811
 
2812
static void
2813
output_up_to (const char *p)
2814
{
2815
  size_t copy_length = (size_t) (p - clean_read_ptr);
2816
  const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
2817
 
2818
  if (copy_length == 0)
2819
    return;
2820
 
2821
  output_bytes (copy_start, copy_length);
2822
  clean_read_ptr = p;
2823
}
2824
 
2825
/* Given a pointer to a def_dec_info record which represents some form of
2826
   definition of a function (perhaps a real definition, or in lieu of that
2827
   perhaps just a declaration with a full prototype) return true if this
2828
   function is one which we should avoid converting.  Return false
2829
   otherwise.  */
2830
 
2831
static int
2832
other_variable_style_function (const char *ansi_header)
2833
{
2834
#ifdef UNPROTOIZE
2835
 
2836
  /* See if we have a stdarg function, or a function which has stdarg style
2837
     parameters or a stdarg style return type.  */
2838
 
2839
  return strstr (ansi_header, "...") != 0;
2840
 
2841
#else /* !defined (UNPROTOIZE) */
2842
 
2843
  /* See if we have a varargs function, or a function which has varargs style
2844
     parameters or a varargs style return type.  */
2845
 
2846
  const char *p;
2847
  int len = strlen (varargs_style_indicator);
2848
 
2849
  for (p = ansi_header; p; )
2850
    {
2851
      const char *candidate;
2852
 
2853
      if ((candidate = strstr (p, varargs_style_indicator)) == 0)
2854
        return 0;
2855
      else
2856
        if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
2857
          return 1;
2858
        else
2859
          p = candidate + 1;
2860
    }
2861
  return 0;
2862
#endif /* !defined (UNPROTOIZE) */
2863
}
2864
 
2865
/* Do the editing operation specifically for a function "declaration".  Note
2866
   that editing for function "definitions" are handled in a separate routine
2867
   below.  */
2868
 
2869
static void
2870
edit_fn_declaration (const def_dec_info *def_dec_p,
2871
                     const char *volatile clean_text_p)
2872
{
2873
  const char *start_formals;
2874
  const char *end_formals;
2875
  const char *function_to_edit = def_dec_p->hash_entry->symbol;
2876
  size_t func_name_len = strlen (function_to_edit);
2877
  const char *end_of_fn_name;
2878
 
2879
#ifndef UNPROTOIZE
2880
 
2881
  const f_list_chain_item *this_f_list_chain_item;
2882
  const def_dec_info *definition = def_dec_p->definition;
2883
 
2884
  /* If we are protoizing, and if we found no corresponding definition for
2885
     this particular function declaration, then just leave this declaration
2886
     exactly as it is.  */
2887
 
2888
  if (!definition)
2889
    return;
2890
 
2891
  /* If we are protoizing, and if the corresponding definition that we found
2892
     for this particular function declaration defined an old style varargs
2893
     function, then we want to issue a warning and just leave this function
2894
     declaration unconverted.  */
2895
 
2896
  if (other_variable_style_function (definition->ansi_decl))
2897
    {
2898
      if (!quiet_flag)
2899
        notice ("%s: %d: warning: varargs function declaration not converted\n",
2900
                shortpath (NULL, def_dec_p->file->hash_entry->symbol),
2901
                def_dec_p->line);
2902
      return;
2903
    }
2904
 
2905
#endif /* !defined (UNPROTOIZE) */
2906
 
2907
  /* Setup here to recover from confusing source code detected during this
2908
     particular "edit".  */
2909
 
2910
  save_pointers ();
2911
  if (setjmp (source_confusion_recovery))
2912
    {
2913
      restore_pointers ();
2914
      notice ("%s: declaration of function '%s' not converted\n",
2915
              pname, function_to_edit);
2916
      return;
2917
    }
2918
 
2919
  /* We are editing a function declaration.  The line number we did a seek to
2920
     contains the comma or semicolon which follows the declaration.  Our job
2921
     now is to scan backwards looking for the function name.  This name *must*
2922
     be followed by open paren (ignoring whitespace, of course).  We need to
2923
     replace everything between that open paren and the corresponding closing
2924
     paren.  If we are protoizing, we need to insert the prototype-style
2925
     formals lists.  If we are unprotoizing, we need to just delete everything
2926
     between the pairs of opening and closing parens.  */
2927
 
2928
  /* First move up to the end of the line.  */
2929
 
2930
  while (*clean_text_p != '\n')
2931
    check_source (++clean_text_p < clean_text_limit, 0);
2932
  clean_text_p--;  /* Point to just before the newline character.  */
2933
 
2934
  /* Now we can scan backwards for the function name.  */
2935
 
2936
  do
2937
    {
2938
      for (;;)
2939
        {
2940
          /* Scan leftwards until we find some character which can be
2941
             part of an identifier.  */
2942
 
2943
          while (!is_id_char (*clean_text_p))
2944
            check_source (--clean_text_p > clean_read_ptr, 0);
2945
 
2946
          /* Scan backwards until we find a char that cannot be part of an
2947
             identifier.  */
2948
 
2949
          while (is_id_char (*clean_text_p))
2950
            check_source (--clean_text_p > clean_read_ptr, 0);
2951
 
2952
          /* Having found an "id break", see if the following id is the one
2953
             that we are looking for.  If so, then exit from this loop.  */
2954
 
2955
          if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
2956
            {
2957
              char ch = *(clean_text_p + 1 + func_name_len);
2958
 
2959
              /* Must also check to see that the name in the source text
2960
                 ends where it should (in order to prevent bogus matches
2961
                 on similar but longer identifiers.  */
2962
 
2963
              if (! is_id_char (ch))
2964
                break;                  /* exit from loop */
2965
            }
2966
        }
2967
 
2968
      /* We have now found the first perfect match for the function name in
2969
         our backward search.  This may or may not be the actual function
2970
         name at the start of the actual function declaration (i.e. we could
2971
         have easily been mislead).  We will try to avoid getting fooled too
2972
         often by looking forward for the open paren which should follow the
2973
         identifier we just found.  We ignore whitespace while hunting.  If
2974
         the next non-whitespace byte we see is *not* an open left paren,
2975
         then we must assume that we have been fooled and we start over
2976
         again accordingly.  Note that there is no guarantee, that even if
2977
         we do see the open paren, that we are in the right place.
2978
         Programmers do the strangest things sometimes!  */
2979
 
2980
      end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
2981
      start_formals = forward_to_next_token_char (end_of_fn_name);
2982
    }
2983
  while (*start_formals != '(');
2984
 
2985
  /* start_of_formals now points to the opening left paren which immediately
2986
     follows the name of the function.  */
2987
 
2988
  /* Note that there may be several formals lists which need to be modified
2989
     due to the possibility that the return type of this function is a
2990
     pointer-to-function type.  If there are several formals lists, we
2991
     convert them in left-to-right order here.  */
2992
 
2993
#ifndef UNPROTOIZE
2994
  this_f_list_chain_item = definition->f_list_chain;
2995
#endif /* !defined (UNPROTOIZE) */
2996
 
2997
  for (;;)
2998
    {
2999
      {
3000
        int depth;
3001
 
3002
        end_formals = start_formals + 1;
3003
        depth = 1;
3004
        for (; depth; check_source (++end_formals < clean_text_limit, 0))
3005
          {
3006
            switch (*end_formals)
3007
              {
3008
              case '(':
3009
                depth++;
3010
                break;
3011
              case ')':
3012
                depth--;
3013
                break;
3014
              }
3015
          }
3016
        end_formals--;
3017
      }
3018
 
3019
      /* end_formals now points to the closing right paren of the formals
3020
         list whose left paren is pointed to by start_formals.  */
3021
 
3022
      /* Now, if we are protoizing, we insert the new ANSI-style formals list
3023
         attached to the associated definition of this function.  If however
3024
         we are unprotoizing, then we simply delete any formals list which
3025
         may be present.  */
3026
 
3027
      output_up_to (start_formals);
3028
#ifndef UNPROTOIZE
3029
      if (this_f_list_chain_item)
3030
        {
3031
          output_string (this_f_list_chain_item->formals_list);
3032
          this_f_list_chain_item = this_f_list_chain_item->chain_next;
3033
        }
3034
      else
3035
        {
3036
          if (!quiet_flag)
3037
            notice ("%s: warning: too many parameter lists in declaration of '%s'\n",
3038
                    pname, def_dec_p->hash_entry->symbol);
3039
          check_source (0, end_formals);  /* leave the declaration intact */
3040
        }
3041
#endif /* !defined (UNPROTOIZE) */
3042
      clean_read_ptr = end_formals - 1;
3043
 
3044
      /* Now see if it looks like there may be another formals list associated
3045
         with the function declaration that we are converting (following the
3046
         formals list that we just converted.  */
3047
 
3048
      {
3049
        const char *another_r_paren = forward_to_next_token_char (end_formals);
3050
 
3051
        if ((*another_r_paren != ')')
3052
            || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
3053
          {
3054
#ifndef UNPROTOIZE
3055
            if (this_f_list_chain_item)
3056
              {
3057
                if (!quiet_flag)
3058
                  notice ("\n%s: warning: too few parameter lists in declaration of '%s'\n",
3059
                          pname, def_dec_p->hash_entry->symbol);
3060
                check_source (0, start_formals); /* leave the decl intact */
3061
              }
3062
#endif /* !defined (UNPROTOIZE) */
3063
            break;
3064
 
3065
          }
3066
      }
3067
 
3068
      /* There does appear to be yet another formals list, so loop around
3069
         again, and convert it also.  */
3070
    }
3071
}
3072
 
3073
/* Edit a whole group of formals lists, starting with the rightmost one
3074
   from some set of formals lists.  This routine is called once (from the
3075
   outside) for each function declaration which is converted.  It is
3076
   recursive however, and it calls itself once for each remaining formal
3077
   list that lies to the left of the one it was originally called to work
3078
   on.  Thus, a whole set gets done in right-to-left order.
3079
 
3080
   This routine returns nonzero if it thinks that it should not be trying
3081
   to convert this particular function definition (because the name of the
3082
   function doesn't match the one expected).  */
3083
 
3084
static int
3085
edit_formals_lists (const char *end_formals, unsigned int f_list_count,
3086
                    const def_dec_info *def_dec_p)
3087
{
3088
  const char *start_formals;
3089
  int depth;
3090
 
3091
  start_formals = end_formals - 1;
3092
  depth = 1;
3093
  for (; depth; check_source (--start_formals > clean_read_ptr, 0))
3094
    {
3095
      switch (*start_formals)
3096
        {
3097
        case '(':
3098
          depth--;
3099
          break;
3100
        case ')':
3101
          depth++;
3102
          break;
3103
        }
3104
    }
3105
  start_formals++;
3106
 
3107
  /* start_formals now points to the opening left paren of the formals list.  */
3108
 
3109
  f_list_count--;
3110
 
3111
  if (f_list_count)
3112
    {
3113
      const char *next_end;
3114
 
3115
      /* There should be more formal lists to the left of here.  */
3116
 
3117
      next_end = start_formals - 1;
3118
      check_source (next_end > clean_read_ptr, 0);
3119
      while (ISSPACE ((const unsigned char)*next_end))
3120
        check_source (--next_end > clean_read_ptr, 0);
3121
      check_source (*next_end == ')', next_end);
3122
      check_source (--next_end > clean_read_ptr, 0);
3123
      check_source (*next_end == ')', next_end);
3124
      if (edit_formals_lists (next_end, f_list_count, def_dec_p))
3125
        return 1;
3126
    }
3127
 
3128
  /* Check that the function name in the header we are working on is the same
3129
     as the one we would expect to find.  If not, issue a warning and return
3130
     nonzero.  */
3131
 
3132
  if (f_list_count == 0)
3133
    {
3134
      const char *expected = def_dec_p->hash_entry->symbol;
3135
      const char *func_name_start;
3136
      const char *func_name_limit;
3137
      size_t func_name_len;
3138
 
3139
      for (func_name_limit = start_formals-1;
3140
           ISSPACE ((const unsigned char)*func_name_limit); )
3141
        check_source (--func_name_limit > clean_read_ptr, 0);
3142
 
3143
      for (func_name_start = func_name_limit++;
3144
           is_id_char (*func_name_start);
3145
           func_name_start--)
3146
        check_source (func_name_start > clean_read_ptr, 0);
3147
      func_name_start++;
3148
      func_name_len = func_name_limit - func_name_start;
3149
      if (func_name_len == 0)
3150
        check_source (0, func_name_start);
3151
      if (func_name_len != strlen (expected)
3152
          || strncmp (func_name_start, expected, func_name_len))
3153
        {
3154
          notice ("%s: %d: warning: found '%s' but expected '%s'\n",
3155
                  shortpath (NULL, def_dec_p->file->hash_entry->symbol),
3156
                  identify_lineno (func_name_start),
3157
                  dupnstr (func_name_start, func_name_len),
3158
                  expected);
3159
          return 1;
3160
        }
3161
    }
3162
 
3163
  output_up_to (start_formals);
3164
 
3165
#ifdef UNPROTOIZE
3166
  if (f_list_count == 0)
3167
    output_string (def_dec_p->formal_names);
3168
#else /* !defined (UNPROTOIZE) */
3169
  {
3170
    unsigned f_list_depth;
3171
    const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
3172
 
3173
    /* At this point, the current value of f_list count says how many
3174
       links we have to follow through the f_list_chain to get to the
3175
       particular formals list that we need to output next.  */
3176
 
3177
    for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
3178
      flci_p = flci_p->chain_next;
3179
    output_string (flci_p->formals_list);
3180
  }
3181
#endif /* !defined (UNPROTOIZE) */
3182
 
3183
  clean_read_ptr = end_formals - 1;
3184
  return 0;
3185
}
3186
 
3187
/* Given a pointer to a byte in the clean text buffer which points to
3188
   the beginning of a line that contains a "follower" token for a
3189
   function definition header, do whatever is necessary to find the
3190
   right closing paren for the rightmost formals list of the function
3191
   definition header.  */
3192
 
3193
static const char *
3194
find_rightmost_formals_list (const char *clean_text_p)
3195
{
3196
  const char *end_formals;
3197
 
3198
  /* We are editing a function definition.  The line number we did a seek
3199
     to contains the first token which immediately follows the entire set of
3200
     formals lists which are part of this particular function definition
3201
     header.
3202
 
3203
     Our job now is to scan leftwards in the clean text looking for the
3204
     right-paren which is at the end of the function header's rightmost
3205
     formals list.
3206
 
3207
     If we ignore whitespace, this right paren should be the first one we
3208
     see which is (ignoring whitespace) immediately followed either by the
3209
     open curly-brace beginning the function body or by an alphabetic
3210
     character (in the case where the function definition is in old (K&R)
3211
     style and there are some declarations of formal parameters).  */
3212
 
3213
   /* It is possible that the right paren we are looking for is on the
3214
      current line (together with its following token).  Just in case that
3215
      might be true, we start out here by skipping down to the right end of
3216
      the current line before starting our scan.  */
3217
 
3218
  for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
3219
    continue;
3220
  end_formals--;
3221
 
3222
#ifdef UNPROTOIZE
3223
 
3224
  /* Now scan backwards while looking for the right end of the rightmost
3225
     formals list associated with this function definition.  */
3226
 
3227
  {
3228
    char ch;
3229
    const char *l_brace_p;
3230
 
3231
    /* Look leftward and try to find a right-paren.  */
3232
 
3233
    while (*end_formals != ')')
3234
      {
3235
        if (ISSPACE ((unsigned char)*end_formals))
3236
          while (ISSPACE ((unsigned char)*end_formals))
3237
            check_source (--end_formals > clean_read_ptr, 0);
3238
        else
3239
          check_source (--end_formals > clean_read_ptr, 0);
3240
      }
3241
 
3242
    ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3243
    /* Since we are unprotoizing an ANSI-style (prototyped) function
3244
       definition, there had better not be anything (except whitespace)
3245
       between the end of the ANSI formals list and the beginning of the
3246
       function body (i.e. the '{').  */
3247
 
3248
    check_source (ch == '{', l_brace_p);
3249
  }
3250
 
3251
#else /* !defined (UNPROTOIZE) */
3252
 
3253
  /* Now scan backwards while looking for the right end of the rightmost
3254
     formals list associated with this function definition.  */
3255
 
3256
  while (1)
3257
    {
3258
      char ch;
3259
      const char *l_brace_p;
3260
 
3261
      /* Look leftward and try to find a right-paren.  */
3262
 
3263
      while (*end_formals != ')')
3264
        {
3265
          if (ISSPACE ((const unsigned char)*end_formals))
3266
            while (ISSPACE ((const unsigned char)*end_formals))
3267
              check_source (--end_formals > clean_read_ptr, 0);
3268
          else
3269
            check_source (--end_formals > clean_read_ptr, 0);
3270
        }
3271
 
3272
      ch = *(l_brace_p = forward_to_next_token_char (end_formals));
3273
 
3274
      /* Since it is possible that we found a right paren before the starting
3275
         '{' of the body which IS NOT the one at the end of the real K&R
3276
         formals list (say for instance, we found one embedded inside one of
3277
         the old K&R formal parameter declarations) we have to check to be
3278
         sure that this is in fact the right paren that we were looking for.
3279
 
3280
         The one we were looking for *must* be followed by either a '{' or
3281
         by an alphabetic character, while others *cannot* validly be followed
3282
         by such characters.  */
3283
 
3284
      if ((ch == '{') || ISALPHA ((unsigned char) ch))
3285
        break;
3286
 
3287
      /* At this point, we have found a right paren, but we know that it is
3288
         not the one we were looking for, so backup one character and keep
3289
         looking.  */
3290
 
3291
      check_source (--end_formals > clean_read_ptr, 0);
3292
    }
3293
 
3294
#endif /* !defined (UNPROTOIZE) */
3295
 
3296
  return end_formals;
3297
}
3298
 
3299
#ifndef UNPROTOIZE
3300
 
3301
/* Insert into the output file a totally new declaration for a function
3302
   which (up until now) was being called from within the current block
3303
   without having been declared at any point such that the declaration
3304
   was visible (i.e. in scope) at the point of the call.
3305
 
3306
   We need to add in explicit declarations for all such function calls
3307
   in order to get the full benefit of prototype-based function call
3308
   parameter type checking.  */
3309
 
3310
static void
3311
add_local_decl (const def_dec_info *def_dec_p, const char *clean_text_p)
3312
{
3313
  const char *start_of_block;
3314
  const char *function_to_edit = def_dec_p->hash_entry->symbol;
3315
 
3316
  /* Don't insert new local explicit declarations unless explicitly requested
3317
     to do so.  */
3318
 
3319
  if (!local_flag)
3320
    return;
3321
 
3322
  /* Setup here to recover from confusing source code detected during this
3323
     particular "edit".  */
3324
 
3325
  save_pointers ();
3326
  if (setjmp (source_confusion_recovery))
3327
    {
3328
      restore_pointers ();
3329
      notice ("%s: local declaration for function '%s' not inserted\n",
3330
              pname, function_to_edit);
3331
      return;
3332
    }
3333
 
3334
  /* We have already done a seek to the start of the line which should
3335
     contain *the* open curly brace which begins the block in which we need
3336
     to insert an explicit function declaration (to replace the implicit one).
3337
 
3338
     Now we scan that line, starting from the left, until we find the
3339
     open curly brace we are looking for.  Note that there may actually be
3340
     multiple open curly braces on the given line, but we will be happy
3341
     with the leftmost one no matter what.  */
3342
 
3343
  start_of_block = clean_text_p;
3344
  while (*start_of_block != '{' && *start_of_block != '\n')
3345
    check_source (++start_of_block < clean_text_limit, 0);
3346
 
3347
  /* Note that the line from the original source could possibly
3348
     contain *no* open curly braces!  This happens if the line contains
3349
     a macro call which expands into a chunk of text which includes a
3350
     block (and that block's associated open and close curly braces).
3351
     In cases like this, we give up, issue a warning, and do nothing.  */
3352
 
3353
  if (*start_of_block != '{')
3354
    {
3355
      if (!quiet_flag)
3356
        notice ("\n%s: %d: warning: can't add declaration of '%s' into macro call\n",
3357
          def_dec_p->file->hash_entry->symbol, def_dec_p->line,
3358
          def_dec_p->hash_entry->symbol);
3359
      return;
3360
    }
3361
 
3362
  /* Figure out what a nice (pretty) indentation would be for the new
3363
     declaration we are adding.  In order to do this, we must scan forward
3364
     from the '{' until we find the first line which starts with some
3365
     non-whitespace characters (i.e. real "token" material).  */
3366
 
3367
  {
3368
    const char *ep = forward_to_next_token_char (start_of_block) - 1;
3369
    const char *sp;
3370
 
3371
    /* Now we have ep pointing at the rightmost byte of some existing indent
3372
       stuff.  At least that is the hope.
3373
 
3374
       We can now just scan backwards and find the left end of the existing
3375
       indentation string, and then copy it to the output buffer.  */
3376
 
3377
    for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--)
3378
      continue;
3379
 
3380
    /* Now write out the open { which began this block, and any following
3381
       trash up to and including the last byte of the existing indent that
3382
       we just found.  */
3383
 
3384
    output_up_to (ep);
3385
 
3386
    /* Now we go ahead and insert the new declaration at this point.
3387
 
3388
       If the definition of the given function is in the same file that we
3389
       are currently editing, and if its full ANSI declaration normally
3390
       would start with the keyword `extern', suppress the `extern'.  */
3391
 
3392
    {
3393
      const char *decl = def_dec_p->definition->ansi_decl;
3394
 
3395
      if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
3396
        decl += 7;
3397
      output_string (decl);
3398
    }
3399
 
3400
    /* Finally, write out a new indent string, just like the preceding one
3401
       that we found.  This will typically include a newline as the first
3402
       character of the indent string.  */
3403
 
3404
    output_bytes (sp, (size_t) (ep - sp) + 1);
3405
  }
3406
}
3407
 
3408
/* Given a pointer to a file_info record, and a pointer to the beginning
3409
   of a line (in the clean text buffer) which is assumed to contain the
3410
   first "follower" token for the first function definition header in the
3411
   given file, find a good place to insert some new global function
3412
   declarations (which will replace scattered and imprecise implicit ones)
3413
   and then insert the new explicit declaration at that point in the file.  */
3414
 
3415
static void
3416
add_global_decls (const file_info *file_p, const char *clean_text_p)
3417
{
3418
  const def_dec_info *dd_p;
3419
  const char *scan_p;
3420
 
3421
  /* Setup here to recover from confusing source code detected during this
3422
     particular "edit".  */
3423
 
3424
  save_pointers ();
3425
  if (setjmp (source_confusion_recovery))
3426
    {
3427
      restore_pointers ();
3428
      notice ("%s: global declarations for file '%s' not inserted\n",
3429
              pname, shortpath (NULL, file_p->hash_entry->symbol));
3430
      return;
3431
    }
3432
 
3433
  /* Start by finding a good location for adding the new explicit function
3434
     declarations.  To do this, we scan backwards, ignoring whitespace
3435
     and comments and other junk until we find either a semicolon, or until
3436
     we hit the beginning of the file.  */
3437
 
3438
  scan_p = find_rightmost_formals_list (clean_text_p);
3439
  for (;; --scan_p)
3440
    {
3441
      if (scan_p < clean_text_base)
3442
        break;
3443
      check_source (scan_p > clean_read_ptr, 0);
3444
      if (*scan_p == ';')
3445
        break;
3446
    }
3447
 
3448
  /* scan_p now points either to a semicolon, or to just before the start
3449
     of the whole file.  */
3450
 
3451
  /* Now scan forward for the first non-whitespace character.  In theory,
3452
     this should be the first character of the following function definition
3453
     header.  We will put in the added declarations just prior to that.  */
3454
 
3455
  scan_p++;
3456
  while (ISSPACE ((const unsigned char)*scan_p))
3457
    scan_p++;
3458
  scan_p--;
3459
 
3460
  output_up_to (scan_p);
3461
 
3462
  /* Now write out full prototypes for all of the things that had been
3463
     implicitly declared in this file (but only those for which we were
3464
     actually able to find unique matching definitions).  Avoid duplicates
3465
     by marking things that we write out as we go.  */
3466
 
3467
  {
3468
    int some_decls_added = 0;
3469
 
3470
    for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3471
      if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
3472
        {
3473
          const char *decl = dd_p->definition->ansi_decl;
3474
 
3475
          /* If the function for which we are inserting a declaration is
3476
             actually defined later in the same file, then suppress the
3477
             leading `extern' keyword (if there is one).  */
3478
 
3479
          if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
3480
            decl += 7;
3481
 
3482
          output_string ("\n");
3483
          output_string (decl);
3484
          some_decls_added = 1;
3485
          ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
3486
        }
3487
    if (some_decls_added)
3488
      output_string ("\n\n");
3489
  }
3490
 
3491
  /* Unmark all of the definitions that we just marked.  */
3492
 
3493
  for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
3494
    if (dd_p->definition)
3495
      ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
3496
}
3497
 
3498
#endif /* !defined (UNPROTOIZE) */
3499
 
3500
/* Do the editing operation specifically for a function "definition".  Note
3501
   that editing operations for function "declarations" are handled by a
3502
   separate routine above.  */
3503
 
3504
static void
3505
edit_fn_definition (const def_dec_info *def_dec_p,
3506
                    const char *volatile 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.