00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "intl.h"
00027 #include "cppdefault.h"
00028
00029 #include <setjmp.h>
00030 #include <signal.h>
00031 #if ! defined( SIGCHLD ) && defined( SIGCLD )
00032 # define SIGCHLD SIGCLD
00033 #endif
00034 #ifdef HAVE_UNISTD_H
00035 #include <unistd.h>
00036 #endif
00037 #undef abort
00038 #include "version.h"
00039
00040
00041 #include "getopt.h"
00042
00043
00044 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00045 #define IS_SAME_PATH_CHAR(a,b) (TOUPPER (a) == TOUPPER (b))
00046 #else
00047 #define IS_SAME_PATH_CHAR(a,b) ((a) == (b))
00048 #endif
00049
00050
00051 #define IS_SAME_PATH(a,b) (FILENAME_CMP (a, b) == 0)
00052
00053
00054 #ifdef __MSDOS__
00055 #define AUX_INFO_SUFFIX "X"
00056 #else
00057 #define AUX_INFO_SUFFIX ".X"
00058 #endif
00059
00060
00061 #ifdef __MSDOS__
00062 #define SAVE_SUFFIX "sav"
00063 #else
00064 #define SAVE_SUFFIX ".save"
00065 #endif
00066
00067
00068 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00069 #define CPLUS_FILE_SUFFIX "cc"
00070 #else
00071 #define CPLUS_FILE_SUFFIX "C"
00072 #endif
00073
00074 static void usage (void) ATTRIBUTE_NORETURN;
00075 static void aux_info_corrupted (void) ATTRIBUTE_NORETURN;
00076 static void declare_source_confusing (const char *) ATTRIBUTE_NORETURN;
00077 static const char *shortpath (const char *, const char *);
00078 static void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
00079 static char *savestring (const char *, unsigned int);
00080 static char *dupnstr (const char *, size_t);
00081 static int safe_read (int, void *, int);
00082 static void safe_write (int, void *, int, const char *);
00083 static void save_pointers (void);
00084 static void restore_pointers (void);
00085 static int is_id_char (int);
00086 static int in_system_include_dir (const char *);
00087 static int directory_specified_p (const char *);
00088 static int file_excluded_p (const char *);
00089 static char *unexpand_if_needed (const char *);
00090 static char *abspath (const char *, const char *);
00091 static void check_aux_info (int);
00092 static const char *find_corresponding_lparen (const char *);
00093 static int referenced_file_is_newer (const char *, time_t);
00094 static void save_def_or_dec (const char *, int);
00095 static void munge_compile_params (const char *);
00096 static int gen_aux_info_file (const char *);
00097 static void process_aux_info_file (const char *, int, int);
00098 static int identify_lineno (const char *);
00099 static void check_source (int, const char *);
00100 static const char *seek_to_line (int);
00101 static const char *forward_to_next_token_char (const char *);
00102 static void output_bytes (const char *, size_t);
00103 static void output_string (const char *);
00104 static void output_up_to (const char *);
00105 static int other_variable_style_function (const char *);
00106 static const char *find_rightmost_formals_list (const char *);
00107 static void do_cleaning (char *, const char *);
00108 static const char *careful_find_l_paren (const char *);
00109 static void do_processing (void);
00110
00111
00112 #define NONCONST
00113
00114
00115
00116 #ifndef UNPROTOIZE
00117
00118 #ifndef STANDARD_EXEC_PREFIX
00119 #define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
00120 #endif
00121
00122 static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX;
00123 static const char * const target_machine = DEFAULT_TARGET_MACHINE;
00124 static const char * const target_version = DEFAULT_TARGET_VERSION;
00125
00126 #endif
00127
00128
00129
00130 static const char * const aux_info_suffix = AUX_INFO_SUFFIX;
00131
00132
00133
00134 static const char * const save_suffix = SAVE_SUFFIX;
00135
00136 #ifndef UNPROTOIZE
00137
00138
00139
00140 static const char * const cplus_suffix = CPLUS_FILE_SUFFIX;
00141
00142
00143
00144
00145
00146 static const char syscalls_filename[] = "SYSCALLS.c";
00147
00148
00149
00150 static const char * default_syscalls_dir;
00151
00152
00153
00154
00155 static char * syscalls_absolute_filename;
00156
00157 #endif
00158
00159
00160
00161 struct unexpansion_struct {
00162 const char *const expanded;
00163 const char *const contracted;
00164 };
00165 typedef struct unexpansion_struct unexpansion;
00166
00167
00168
00169
00170
00171
00172
00173
00174 static const unexpansion unexpansions[] = {
00175 { "struct _iobuf", "FILE" },
00176 { 0, 0 }
00177 };
00178
00179
00180
00181
00182
00183 #define HASH_TABLE_SIZE (1 << 9)
00184
00185
00186
00187 static const int hash_mask = (HASH_TABLE_SIZE - 1);
00188
00189
00190
00191 struct string_list
00192 {
00193 const char *name;
00194 struct string_list *next;
00195 };
00196
00197 static struct string_list *string_list_cons (const char *,
00198 struct string_list *);
00199
00200
00201
00202 struct string_list *directory_list;
00203
00204
00205
00206
00207
00208 struct string_list *exclude_list;
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 #ifdef UNPROTOIZE
00220 static const char * const other_var_style = "stdarg";
00221 #else
00222 static const char * const other_var_style = "varargs";
00223 static const char *varargs_style_indicator = "va_alist";
00224 #endif
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 typedef struct hash_table_entry_struct hash_table_entry;
00235
00236
00237
00238 typedef struct def_dec_info_struct def_dec_info;
00239 typedef struct file_info_struct file_info;
00240 typedef struct f_list_chain_item_struct f_list_chain_item;
00241
00242 #ifndef UNPROTOIZE
00243 static int is_syscalls_file (const file_info *);
00244 static void rename_c_file (const hash_table_entry *);
00245 static const def_dec_info *find_extern_def (const def_dec_info *,
00246 const def_dec_info *);
00247 static const def_dec_info *find_static_definition (const def_dec_info *);
00248 static void connect_defs_and_decs (const hash_table_entry *);
00249 static void add_local_decl (const def_dec_info *, const char *);
00250 static void add_global_decls (const file_info *, const char *);
00251 #endif
00252 static int needs_to_be_converted (const file_info *);
00253 static void visit_each_hash_node (const hash_table_entry *,
00254 void (*)(const hash_table_entry *));
00255 static hash_table_entry *add_symbol (hash_table_entry *, const char *);
00256 static hash_table_entry *lookup (hash_table_entry *, const char *);
00257 static void free_def_dec (def_dec_info *);
00258 static file_info *find_file (const char *, int);
00259 static void reverse_def_dec_list (const hash_table_entry *);
00260 static void edit_fn_declaration (const def_dec_info *, const char *);
00261 static int edit_formals_lists (const char *, unsigned int,
00262 const def_dec_info *);
00263 static void edit_fn_definition (const def_dec_info *, const char *);
00264 static void scan_for_missed_items (const file_info *);
00265 static void edit_file (const hash_table_entry *);
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 struct hash_table_entry_struct {
00280 hash_table_entry * hash_next;
00281 const char * symbol;
00282 union {
00283 const def_dec_info * _ddip;
00284 file_info * _fip;
00285 } _info;
00286 };
00287 #define ddip _info._ddip
00288 #define fip _info._fip
00289
00290
00291
00292 typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
00293
00294
00295
00296
00297 struct file_info_struct {
00298 const hash_table_entry * hash_entry;
00299 const def_dec_info * defs_decs;
00300 time_t mtime;
00301 };
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 struct f_list_chain_item_struct {
00321 const f_list_chain_item * chain_next;
00322 const char * formals_list;
00323 };
00324
00325
00326
00327
00328
00329
00330
00331
00332 struct def_dec_info_struct {
00333 const def_dec_info * next_in_file;
00334 file_info * file;
00335 int line;
00336 const char * ansi_decl;
00337 hash_table_entry * hash_entry;
00338 unsigned int is_func_def;
00339 const def_dec_info * next_for_func;
00340 unsigned int f_list_count;
00341 char prototyped;
00342 #ifndef UNPROTOIZE
00343 const f_list_chain_item * f_list_chain;
00344 const def_dec_info * definition;
00345 char is_static;
00346 char is_implicit;
00347 char written;
00348 #else
00349 const char * formal_names;
00350 const char * formal_decls;
00351 #endif
00352 };
00353
00354
00355
00356
00357 static const char *pname;
00358
00359
00360
00361
00362 static int errors = 0;
00363
00364
00365
00366
00367
00368
00369
00370 static const char *compiler_file_name = "gcc";
00371
00372 static int version_flag = 0;
00373 static int quiet_flag = 0;
00374 static int nochange_flag = 0;
00375
00376 static int nosave_flag = 0;
00377 static int keep_flag = 0;
00378 static const char ** compile_params = 0;
00379 #ifdef UNPROTOIZE
00380 static const char *indent_string = " ";
00381
00382 #else
00383 static int local_flag = 0;
00384 static int global_flag = 0;
00385 static int cplusplus_flag = 0;
00386 static const char *nondefault_syscalls_dir = 0;
00387
00388 #endif
00389
00390
00391
00392
00393
00394 static int input_file_name_index = 0;
00395
00396
00397
00398 static int aux_info_file_name_index = 0;
00399
00400
00401
00402 static int n_base_source_files = 0;
00403
00404
00405
00406
00407 static const char **base_source_filenames;
00408
00409
00410
00411
00412
00413 static int current_aux_info_lineno;
00414
00415
00416
00417 static const char *convert_filename;
00418
00419
00420
00421
00422
00423 static const char *invocation_filename;
00424
00425
00426
00427
00428 static const char *orig_text_base;
00429
00430
00431
00432
00433 static const char *orig_text_limit;
00434
00435
00436
00437
00438 static const char *clean_text_base;
00439
00440
00441
00442
00443 static const char *clean_text_limit;
00444
00445
00446
00447
00448 static const char * clean_read_ptr;
00449
00450
00451
00452
00453 static char *repl_text_base;
00454
00455
00456
00457
00458 static char *repl_text_limit;
00459
00460
00461
00462
00463
00464 static char * repl_write_ptr;
00465
00466
00467
00468
00469
00470 static const char *last_known_line_start;
00471
00472
00473
00474
00475
00476 static int last_known_line_number;
00477
00478
00479
00480 static hash_table filename_primary;
00481
00482
00483
00484 static hash_table function_name_primary;
00485
00486
00487
00488
00489 static jmp_buf source_confusion_recovery;
00490
00491
00492
00493 static char *cwd_buffer;
00494
00495
00496
00497
00498 static const char * saved_clean_read_ptr;
00499
00500
00501
00502
00503 static char * saved_repl_write_ptr;
00504
00505
00506 static void
00507 notice (const char *cmsgid, ...)
00508 {
00509 va_list ap;
00510
00511 va_start (ap, cmsgid);
00512 vfprintf (stderr, _(cmsgid), ap);
00513 va_end (ap);
00514 }
00515
00516
00517
00518
00519 static char *
00520 savestring (const char *input, unsigned int size)
00521 {
00522 char *output = xmalloc (size + 1);
00523 strcpy (output, input);
00524 return output;
00525 }
00526
00527
00528
00529
00530
00531 static char *
00532 dupnstr (const char *s, size_t n)
00533 {
00534 char *ret_val = xmalloc (n + 1);
00535
00536 strncpy (ret_val, s, n);
00537 ret_val[n] = '\0';
00538 return ret_val;
00539 }
00540
00541
00542
00543
00544 static int
00545 safe_read (int desc, void *ptr, int len)
00546 {
00547 int left = len;
00548 while (left > 0) {
00549 int nchars = read (desc, ptr, left);
00550 if (nchars < 0)
00551 {
00552 #ifdef EINTR
00553 if (errno == EINTR)
00554 continue;
00555 #endif
00556 return nchars;
00557 }
00558 if (nchars == 0)
00559 break;
00560
00561 ptr = (char *) ptr + nchars;
00562 left -= nchars;
00563 }
00564 return len - left;
00565 }
00566
00567
00568
00569
00570 static void
00571 safe_write (int desc, void *ptr, int len, const char *out_fname)
00572 {
00573 while (len > 0) {
00574 int written = write (desc, ptr, len);
00575 if (written < 0)
00576 {
00577 int errno_val = errno;
00578 #ifdef EINTR
00579 if (errno_val == EINTR)
00580 continue;
00581 #endif
00582 notice ("%s: error writing file '%s': %s\n",
00583 pname, shortpath (NULL, out_fname), xstrerror (errno_val));
00584 return;
00585 }
00586
00587 ptr = (char *) ptr + written;
00588 len -= written;
00589 }
00590 }
00591
00592
00593
00594 static void
00595 save_pointers (void)
00596 {
00597 saved_clean_read_ptr = clean_read_ptr;
00598 saved_repl_write_ptr = repl_write_ptr;
00599 }
00600
00601
00602
00603
00604 static void
00605 restore_pointers (void)
00606 {
00607 clean_read_ptr = saved_clean_read_ptr;
00608 repl_write_ptr = saved_repl_write_ptr;
00609 }
00610
00611
00612
00613 static int
00614 is_id_char (int ch)
00615 {
00616 return (ISIDNUM (ch) || (ch == '$'));
00617 }
00618
00619
00620
00621
00622 static void
00623 usage (void)
00624 {
00625 #ifdef UNPROTOIZE
00626 notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
00627 pname, pname);
00628 #else
00629 notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
00630 pname, pname);
00631 #endif
00632 exit (FATAL_EXIT_CODE);
00633 }
00634
00635
00636
00637
00638
00639 static int
00640 in_system_include_dir (const char *path)
00641 {
00642 const struct default_include *p;
00643
00644 if (! IS_ABSOLUTE_PATH (path))
00645 abort ();
00646
00647 for (p = cpp_include_defaults; p->fname; p++)
00648 if (!strncmp (path, p->fname, strlen (p->fname))
00649 && IS_DIR_SEPARATOR (path[strlen (p->fname)]))
00650 return 1;
00651 return 0;
00652 }
00653
00654 #if 0
00655
00656
00657
00658
00659 static int
00660 file_could_be_converted (const char *path)
00661 {
00662 char *const dir_name = alloca (strlen (path) + 1);
00663
00664 if (access (path, R_OK))
00665 return 0;
00666
00667 {
00668 char *dir_last_slash;
00669
00670 strcpy (dir_name, path);
00671 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
00672 #ifdef DIR_SEPARATOR_2
00673 {
00674 char *slash;
00675
00676 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
00677 DIR_SEPARATOR_2);
00678 if (slash)
00679 dir_last_slash = slash;
00680 }
00681 #endif
00682 if (dir_last_slash)
00683 *dir_last_slash = '\0';
00684 else
00685 abort ();
00686 }
00687
00688 if (access (path, W_OK))
00689 return 0;
00690
00691 return 1;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 static int
00704 file_normally_convertible (const char *path)
00705 {
00706 char *const dir_name = alloca (strlen (path) + 1);
00707
00708 if (in_system_include_dir (path))
00709 return 0;
00710
00711 {
00712 char *dir_last_slash;
00713
00714 strcpy (dir_name, path);
00715 dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
00716 #ifdef DIR_SEPARATOR_2
00717 {
00718 char *slash;
00719
00720 slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
00721 DIR_SEPARATOR_2);
00722 if (slash)
00723 dir_last_slash = slash;
00724 }
00725 #endif
00726 if (dir_last_slash)
00727 *dir_last_slash = '\0';
00728 else
00729 abort ();
00730 }
00731
00732 if (access (path, R_OK))
00733 {
00734 if (!quiet_flag)
00735 notice ("%s: warning: no read access for file '%s'\n",
00736 pname, shortpath (NULL, path));
00737 return 0;
00738 }
00739
00740 if (access (path, W_OK))
00741 {
00742 if (!quiet_flag)
00743 notice ("%s: warning: no write access for file '%s'\n",
00744 pname, shortpath (NULL, path));
00745 return 0;
00746 }
00747
00748 if (access (dir_name, W_OK))
00749 {
00750 if (!quiet_flag)
00751 notice ("%s: warning: no write access for dir containing '%s'\n",
00752 pname, shortpath (NULL, path));
00753 return 0;
00754 }
00755
00756 return 1;
00757 }
00758 #endif
00759
00760 #ifndef UNPROTOIZE
00761
00762
00763
00764
00765 static int
00766 is_syscalls_file (const file_info *fi_p)
00767 {
00768 char const *f = fi_p->hash_entry->symbol;
00769 size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
00770 return sysl <= fl && strcmp (f + fl - sysl, syscalls_filename) == 0;
00771 }
00772
00773 #endif
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784 static int
00785 needs_to_be_converted (const file_info *file_p)
00786 {
00787 const def_dec_info *ddp;
00788
00789 #ifndef UNPROTOIZE
00790
00791 if (is_syscalls_file (file_p))
00792 return 0;
00793
00794 #endif
00795
00796 for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
00797
00798 if (
00799
00800 #ifndef UNPROTOIZE
00801
00802
00803 !ddp->prototyped
00804
00805 && (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
00806
00807 #else
00808
00809
00810 ddp->prototyped
00811
00812 #endif
00813 )
00814
00815 return -1;
00816 return 0;
00817 }
00818
00819
00820
00821
00822 static int
00823 directory_specified_p (const char *name)
00824 {
00825 struct string_list *p;
00826
00827 for (p = directory_list; p; p = p->next)
00828 if (!strncmp (name, p->name, strlen (p->name))
00829 && IS_DIR_SEPARATOR (name[strlen (p->name)]))
00830 {
00831 const char *q = name + strlen (p->name) + 1;
00832
00833
00834
00835 while (*q++)
00836 if (IS_DIR_SEPARATOR (*(q-1)))
00837 goto lose;
00838 return 1;
00839
00840 lose: ;
00841 }
00842
00843 return 0;
00844 }
00845
00846
00847
00848 static int
00849 file_excluded_p (const char *name)
00850 {
00851 struct string_list *p;
00852 int len = strlen (name);
00853
00854 for (p = exclude_list; p; p = p->next)
00855 if (!strcmp (name + len - strlen (p->name), p->name)
00856 && IS_DIR_SEPARATOR (name[len - strlen (p->name) - 1]))
00857 return 1;
00858
00859 return 0;
00860 }
00861
00862
00863
00864
00865 static struct string_list *
00866 string_list_cons (const char *string, struct string_list *rest)
00867 {
00868 struct string_list *temp = xmalloc (sizeof (struct string_list));
00869
00870 temp->next = rest;
00871 temp->name = string;
00872 return temp;
00873 }
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884 static void
00885 visit_each_hash_node (const hash_table_entry *hash_tab_p,
00886 void (*func) (const hash_table_entry *))
00887 {
00888 const hash_table_entry *primary;
00889
00890 for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
00891 if (primary->symbol)
00892 {
00893 hash_table_entry *second;
00894
00895 (*func)(primary);
00896 for (second = primary->hash_next; second; second = second->hash_next)
00897 (*func) (second);
00898 }
00899 }
00900
00901
00902
00903
00904
00905
00906 static hash_table_entry *
00907 add_symbol (hash_table_entry *p, const char *s)
00908 {
00909 p->hash_next = NULL;
00910 p->symbol = xstrdup (s);
00911 p->ddip = NULL;
00912 p->fip = NULL;
00913 return p;
00914 }
00915
00916
00917
00918
00919
00920
00921 static hash_table_entry *
00922 lookup (hash_table_entry *hash_tab_p, const char *search_symbol)
00923 {
00924 int hash_value = 0;
00925 const char *search_symbol_char_p = search_symbol;
00926 hash_table_entry *p;
00927
00928 while (*search_symbol_char_p)
00929 hash_value += *search_symbol_char_p++;
00930 hash_value &= hash_mask;
00931 p = &hash_tab_p[hash_value];
00932 if (! p->symbol)
00933 return add_symbol (p, search_symbol);
00934 if (!strcmp (p->symbol, search_symbol))
00935 return p;
00936 while (p->hash_next)
00937 {
00938 p = p->hash_next;
00939 if (!strcmp (p->symbol, search_symbol))
00940 return p;
00941 }
00942 p->hash_next = xmalloc (sizeof (hash_table_entry));
00943 p = p->hash_next;
00944 return add_symbol (p, search_symbol);
00945 }
00946
00947
00948
00949
00950
00951
00952 static void
00953 free_def_dec (def_dec_info *p)
00954 {
00955 free ((NONCONST void *) p->ansi_decl);
00956
00957 #ifndef UNPROTOIZE
00958 {
00959 const f_list_chain_item * curr;
00960 const f_list_chain_item * next;
00961
00962 for (curr = p->f_list_chain; curr; curr = next)
00963 {
00964 next = curr->chain_next;
00965 free ((NONCONST void *) curr);
00966 }
00967 }
00968 #endif
00969
00970 free (p);
00971 }
00972
00973
00974
00975
00976
00977
00978 static char *
00979 unexpand_if_needed (const char *aux_info_line)
00980 {
00981 static char *line_buf = 0;
00982 static int line_buf_size = 0;
00983 const unexpansion *unexp_p;
00984 int got_unexpanded = 0;
00985 const char *s;
00986 char *copy_p = line_buf;
00987
00988 if (line_buf == 0)
00989 {
00990 line_buf_size = 1024;
00991 line_buf = xmalloc (line_buf_size);
00992 }
00993
00994 copy_p = line_buf;
00995
00996
00997
00998 for (s = aux_info_line; *s != '\n'; )
00999 {
01000 for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
01001 {
01002 const char *in_p = unexp_p->expanded;
01003 size_t len = strlen (in_p);
01004
01005 if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
01006 {
01007 int size = strlen (unexp_p->contracted);
01008 got_unexpanded = 1;
01009 if (copy_p + size - line_buf >= line_buf_size)
01010 {
01011 int offset = copy_p - line_buf;
01012 line_buf_size *= 2;
01013 line_buf_size += size;
01014 line_buf = xrealloc (line_buf, line_buf_size);
01015 copy_p = line_buf + offset;
01016 }
01017 strcpy (copy_p, unexp_p->contracted);
01018 copy_p += size;
01019
01020
01021
01022
01023 s += len;
01024 goto continue_outer;
01025 }
01026 }
01027 if (copy_p - line_buf == line_buf_size)
01028 {
01029 int offset = copy_p - line_buf;
01030 line_buf_size *= 2;
01031 line_buf = xrealloc (line_buf, line_buf_size);
01032 copy_p = line_buf + offset;
01033 }
01034 *copy_p++ = *s++;
01035 continue_outer: ;
01036 }
01037 if (copy_p + 2 - line_buf >= line_buf_size)
01038 {
01039 int offset = copy_p - line_buf;
01040 line_buf_size *= 2;
01041 line_buf = xrealloc (line_buf, line_buf_size);
01042 copy_p = line_buf + offset;
01043 }
01044 *copy_p++ = '\n';
01045 *copy_p = '\0';
01046
01047 return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
01048 }
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 static char *
01061 abspath (const char *cwd, const char *rel_filename)
01062 {
01063
01064 const char *const cwd2 = (cwd) ? cwd : cwd_buffer;
01065 char *const abs_buffer = alloca (strlen (cwd2) + strlen (rel_filename) + 2);
01066 char *endp = abs_buffer;
01067 char *outp, *inp;
01068
01069
01070
01071
01072 {
01073 const char *src_p;
01074
01075 if (! IS_ABSOLUTE_PATH (rel_filename))
01076 {
01077 src_p = cwd2;
01078 while ((*endp++ = *src_p++))
01079 continue;
01080 *(endp-1) = DIR_SEPARATOR;
01081 }
01082 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
01083 else if (IS_DIR_SEPARATOR (rel_filename[0]))
01084 {
01085
01086
01087
01088
01089 *endp++ = cwd2[0];
01090 *endp++ = cwd2[1];
01091 }
01092 #endif
01093 src_p = rel_filename;
01094 while ((*endp++ = *src_p++))
01095 continue;
01096 }
01097
01098
01099
01100
01101 outp = inp = abs_buffer;
01102 *outp++ = *inp++;
01103 #if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
01104 if (IS_DIR_SEPARATOR (inp[0]))
01105 *outp++ = *inp++;
01106 #endif
01107 for (;;)
01108 {
01109 if (!inp[0])
01110 break;
01111 else if (IS_DIR_SEPARATOR (inp[0]) && IS_DIR_SEPARATOR (outp[-1]))
01112 {
01113 inp++;
01114 continue;
01115 }
01116 else if (inp[0] == '.' && IS_DIR_SEPARATOR (outp[-1]))
01117 {
01118 if (!inp[1])
01119 break;
01120 else if (IS_DIR_SEPARATOR (inp[1]))
01121 {
01122 inp += 2;
01123 continue;
01124 }
01125 else if ((inp[1] == '.') && (inp[2] == 0
01126 || IS_DIR_SEPARATOR (inp[2])))
01127 {
01128 inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2;
01129 outp -= 2;
01130 while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*outp))
01131 outp--;
01132 if (outp < abs_buffer)
01133 {
01134
01135
01136
01137
01138 notice ("%s: invalid file name: %s\n",
01139 pname, rel_filename);
01140 exit (FATAL_EXIT_CODE);
01141 }
01142 *++outp = '\0';
01143 continue;
01144 }
01145 }
01146 *outp++ = *inp++;
01147 }
01148
01149
01150
01151
01152 *outp = '\0';
01153 if (IS_DIR_SEPARATOR (outp[-1]))
01154 *--outp = '\0';
01155
01156
01157
01158
01159 return savestring (abs_buffer, outp - abs_buffer);
01160 }
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 static const char *
01177 shortpath (const char *cwd, const char *filename)
01178 {
01179 char *rel_buffer;
01180 char *rel_buf_p;
01181 char *cwd_p = cwd_buffer;
01182 char *path_p;
01183 int unmatched_slash_count = 0;
01184 size_t filename_len = strlen (filename);
01185
01186 path_p = abspath (cwd, filename);
01187 rel_buf_p = rel_buffer = xmalloc (filename_len);
01188
01189 while (*cwd_p && IS_SAME_PATH_CHAR (*cwd_p, *path_p))
01190 {
01191 cwd_p++;
01192 path_p++;
01193 }
01194 if (!*cwd_p && (!*path_p || IS_DIR_SEPARATOR (*path_p)))
01195 {
01196
01197 if (!*path_p)
01198 return ".";
01199 else
01200 return ++path_p;
01201 }
01202 else
01203 {
01204 if (*path_p)
01205 {
01206 --cwd_p;
01207 --path_p;
01208 while (! IS_DIR_SEPARATOR (*cwd_p))
01209 {
01210 --cwd_p;
01211 --path_p;
01212 }
01213 cwd_p++;
01214 path_p++;
01215 unmatched_slash_count++;
01216 }
01217
01218
01219 while (*cwd_p++)
01220 if (IS_DIR_SEPARATOR (*(cwd_p-1)))
01221 unmatched_slash_count++;
01222
01223
01224
01225 if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
01226 return filename;
01227
01228
01229 while (unmatched_slash_count--)
01230 {
01231
01232
01233 if (rel_buffer + filename_len <= rel_buf_p + 3)
01234 return filename;
01235 *rel_buf_p++ = '.';
01236 *rel_buf_p++ = '.';
01237 *rel_buf_p++ = DIR_SEPARATOR;
01238 }
01239
01240
01241 do
01242 {
01243 if (rel_buffer + filename_len <= rel_buf_p)
01244 return filename;
01245 }
01246 while ((*rel_buf_p++ = *path_p++));
01247
01248 --rel_buf_p;
01249 if (IS_DIR_SEPARATOR (*(rel_buf_p-1)))
01250 *--rel_buf_p = '\0';
01251 return rel_buffer;
01252 }
01253 }
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263 static file_info *
01264 find_file (const char *filename, int do_not_stat)
01265 {
01266 hash_table_entry *hash_entry_p;
01267
01268 hash_entry_p = lookup (filename_primary, filename);
01269 if (hash_entry_p->fip)
01270 return hash_entry_p->fip;
01271 else
01272 {
01273 struct stat stat_buf;
01274 file_info *file_p = xmalloc (sizeof (file_info));
01275
01276
01277
01278
01279 if (do_not_stat)
01280 stat_buf.st_mtime = (time_t) 0;
01281 else
01282 {
01283 if (stat (filename, &stat_buf) == -1)
01284 {
01285 int errno_val = errno;
01286 notice ("%s: %s: can't get status: %s\n",
01287 pname, shortpath (NULL, filename),
01288 xstrerror (errno_val));
01289 stat_buf.st_mtime = (time_t) -1;
01290 }
01291 }
01292
01293 hash_entry_p->fip = file_p;
01294 file_p->hash_entry = hash_entry_p;
01295 file_p->defs_decs = NULL;
01296 file_p->mtime = stat_buf.st_mtime;
01297 return file_p;
01298 }
01299 }
01300
01301
01302
01303
01304 static void
01305 aux_info_corrupted (void)
01306 {
01307 notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
01308 pname, current_aux_info_lineno);
01309 exit (FATAL_EXIT_CODE);
01310 }
01311
01312
01313
01314
01315 static void
01316 check_aux_info (int cond)
01317 {
01318 if (! cond)
01319 aux_info_corrupted ();
01320 }
01321
01322
01323
01324
01325
01326 static const char *
01327 find_corresponding_lparen (const char *p)
01328 {
01329 const char *q;
01330 int paren_depth;
01331
01332 for (paren_depth = 1, q = p-1; paren_depth; q--)
01333 {
01334 switch (*q)
01335 {
01336 case ')':
01337 paren_depth++;
01338 break;
01339 case '(':
01340 paren_depth--;
01341 break;
01342 }
01343 }
01344 return ++q;
01345 }
01346
01347
01348
01349
01350
01351
01352 static int
01353 referenced_file_is_newer (const char *l, time_t aux_info_mtime)
01354 {
01355 const char *p;
01356 file_info *fi_p;
01357 char *filename;
01358
01359 check_aux_info (l[0] == '/');
01360 check_aux_info (l[1] == '*');
01361 check_aux_info (l[2] == ' ');
01362
01363 {
01364 const char *filename_start = p = l + 3;
01365
01366 while (*p != ':'
01367 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
01368 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
01369 #endif
01370 )
01371 p++;
01372 filename = alloca ((size_t) (p - filename_start) + 1);
01373 strncpy (filename, filename_start, (size_t) (p - filename_start));
01374 filename[p-filename_start] = '\0';
01375 }
01376
01377
01378
01379
01380
01381
01382 fi_p = find_file (abspath (invocation_filename, filename), 0);
01383
01384 return (fi_p->mtime > aux_info_mtime);
01385 }
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402 static void
01403 save_def_or_dec (const char *l, int is_syscalls)
01404 {
01405 const char *p;
01406 const char *semicolon_p;
01407 def_dec_info *def_dec_p = xmalloc (sizeof (def_dec_info));
01408
01409 #ifndef UNPROTOIZE
01410 def_dec_p->written = 0;
01411 #endif
01412
01413
01414
01415
01416
01417
01418 check_aux_info (l[0] == '/');
01419 check_aux_info (l[1] == '*');
01420 check_aux_info (l[2] == ' ');
01421
01422 {
01423 const char *filename_start = p = l + 3;
01424 char *filename;
01425
01426 while (*p != ':'
01427 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
01428 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
01429 #endif
01430 )
01431 p++;
01432 filename = alloca ((size_t) (p - filename_start) + 1);
01433 strncpy (filename, filename_start, (size_t) (p - filename_start));
01434 filename[p-filename_start] = '\0';
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450 def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
01451 }
01452
01453 {
01454 const char *line_number_start = ++p;
01455 char line_number[10];
01456
01457 while (*p != ':'
01458 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
01459 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
01460 #endif
01461 )
01462 p++;
01463 strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
01464 line_number[p-line_number_start] = '\0';
01465 def_dec_p->line = atoi (line_number);
01466 }
01467
01468
01469
01470
01471 p++;
01472 check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
01473
01474
01475
01476 def_dec_p->prototyped = (*p == 'N');
01477
01478 #ifndef UNPROTOIZE
01479
01480
01481
01482 def_dec_p->is_implicit = (*p == 'I');
01483
01484 #endif
01485
01486 p++;
01487
01488 check_aux_info ((*p == 'C') || (*p == 'F'));
01489
01490
01491
01492
01493
01494 def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
01495
01496 #ifndef UNPROTOIZE
01497 def_dec_p->definition = 0;
01498 #endif
01499
01500 check_aux_info (*p++ == ' ');
01501 check_aux_info (*p++ == '*');
01502 check_aux_info (*p++ == '/');
01503 check_aux_info (*p++ == ' ');
01504
01505 #ifdef UNPROTOIZE
01506 check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
01507 #else
01508 if (!strncmp (p, "static", 6))
01509 def_dec_p->is_static = -1;
01510 else if (!strncmp (p, "extern", 6))
01511 def_dec_p->is_static = 0;
01512 else
01513 check_aux_info (0);
01514 #endif
01515
01516 {
01517 const char *ansi_start = p;
01518
01519 p += 6;
01520
01521
01522
01523
01524
01525 while (*++p != ';')
01526 continue;
01527
01528 semicolon_p = p;
01529
01530
01531
01532
01533 def_dec_p->ansi_decl
01534 = dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
01535
01536
01537
01538 p--;
01539
01540 #ifndef UNPROTOIZE
01541 def_dec_p->f_list_chain = NULL;
01542 #endif
01543
01544 while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
01545 if (*p != ')')
01546 {
01547 free_def_dec (def_dec_p);
01548 return;
01549 }
01550 }
01551
01552
01553
01554
01555 def_dec_p->f_list_count = 0;
01556
01557 for (;;)
01558 {
01559 const char *left_paren_p = find_corresponding_lparen (p);
01560 #ifndef UNPROTOIZE
01561 {
01562 f_list_chain_item *cip = xmalloc (sizeof (f_list_chain_item));
01563
01564 cip->formals_list
01565 = dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
01566
01567
01568
01569 cip->chain_next = def_dec_p->f_list_chain;
01570 def_dec_p->f_list_chain = cip;
01571 }
01572 #endif
01573 def_dec_p->f_list_count++;
01574
01575 p = left_paren_p - 2;
01576
01577
01578
01579
01580
01581
01582
01583 if (*p != ')')
01584 break;
01585 else
01586 check_aux_info (*--p == ')');
01587 }
01588
01589
01590 {
01591 const char *past_fn = p + 1;
01592
01593 check_aux_info (*past_fn == ' ');
01594
01595
01596
01597 while (is_id_char (*p))
01598 p--;
01599 p++;
01600
01601
01602
01603 {
01604 char *fn_string = alloca (past_fn - p + 1);
01605
01606 strncpy (fn_string, p, (size_t) (past_fn - p));
01607 fn_string[past_fn-p] = '\0';
01608 def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
01609 }
01610 }
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627 {
01628 const def_dec_info *other;
01629
01630 for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
01631 {
01632 if (def_dec_p->line == other->line && def_dec_p->file == other->file)
01633 {
01634 if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
01635 {
01636 notice ("%s:%d: declaration of function '%s' takes different forms\n",
01637 def_dec_p->file->hash_entry->symbol,
01638 def_dec_p->line,
01639 def_dec_p->hash_entry->symbol);
01640 exit (FATAL_EXIT_CODE);
01641 }
01642 free_def_dec (def_dec_p);
01643 return;
01644 }
01645 }
01646 }
01647
01648 #ifdef UNPROTOIZE
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663 def_dec_p->formal_names = NULL;
01664 def_dec_p->formal_decls = NULL;
01665
01666 if (def_dec_p->is_func_def)
01667 {
01668 p = semicolon_p;
01669 check_aux_info (*++p == ' ');
01670 check_aux_info (*++p == '/');
01671 check_aux_info (*++p == '*');
01672 check_aux_info (*++p == ' ');
01673 check_aux_info (*++p == '(');
01674
01675 {
01676 const char *kr_names_start = ++p;
01677
01678 while (*p++ != ')')
01679 continue;
01680 p--;
01681
01682
01683
01684 def_dec_p->formal_names
01685 = dupnstr (kr_names_start, (size_t) (p - kr_names_start));
01686 }
01687
01688 check_aux_info (*++p == ' ');
01689 p++;
01690
01691
01692
01693
01694
01695
01696
01697
01698 if (*p == '*')
01699 {
01700 check_aux_info (*++p == '/');
01701 def_dec_p->formal_decls = "";
01702 }
01703 else
01704 {
01705 const char *kr_decls_start = p;
01706
01707 while (p[0] != '*' || p[1] != '/')
01708 p++;
01709 p--;
01710
01711 check_aux_info (*p == ' ');
01712
01713 def_dec_p->formal_decls
01714 = dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
01715 }
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726 if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
01727 def_dec_p->prototyped = 1;
01728 }
01729
01730
01731
01732
01733 if (!def_dec_p->prototyped)
01734 {
01735 free_def_dec (def_dec_p);
01736 return;
01737 }
01738
01739 #endif
01740
01741
01742
01743
01744 def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
01745 def_dec_p->hash_entry->ddip = def_dec_p;
01746
01747
01748
01749
01750
01751
01752 if (!def_dec_p->file->defs_decs)
01753 {
01754 def_dec_p->file->defs_decs = def_dec_p;
01755 def_dec_p->next_in_file = NULL;
01756 }
01757 else
01758 {
01759 int line = def_dec_p->line;
01760 const def_dec_info *prev = NULL;
01761 const def_dec_info *curr = def_dec_p->file->defs_decs;
01762 const def_dec_info *next = curr->next_in_file;
01763
01764 while (next && (line < curr->line))
01765 {
01766 prev = curr;
01767 curr = next;
01768 next = next->next_in_file;
01769 }
01770 if (line >= curr->line)
01771 {
01772 def_dec_p->next_in_file = curr;
01773 if (prev)
01774 ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
01775 else
01776 def_dec_p->file->defs_decs = def_dec_p;
01777 }
01778 else
01779 {
01780 ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
01781
01782 def_dec_p->next_in_file = next;
01783 }
01784 }
01785 }
01786
01787
01788
01789
01790
01791
01792
01793
01794 static void
01795 munge_compile_params (const char *params_list)
01796 {
01797
01798
01799 const char **temp_params
01800 = alloca ((strlen (params_list) + 8) * sizeof (char *));
01801 int param_count = 0;
01802 const char *param;
01803 struct stat st;
01804
01805 temp_params[param_count++] = compiler_file_name;
01806 for (;;)
01807 {
01808 while (ISSPACE ((const unsigned char)*params_list))
01809 params_list++;
01810 if (!*params_list)
01811 break;
01812 param = params_list;
01813 while (*params_list && !ISSPACE ((const unsigned char)*params_list))
01814 params_list++;
01815 if (param[0] != '-')
01816 temp_params[param_count++]
01817 = dupnstr (param, (size_t) (params_list - param));
01818 else
01819 {
01820 switch (param[1])
01821 {
01822 case 'g':
01823 case 'O':
01824 case 'S':
01825 case 'c':
01826 break;
01827 case 'o':
01828 while (ISSPACE ((const unsigned char)*params_list))
01829 params_list++;
01830 while (*params_list
01831 && !ISSPACE ((const unsigned char)*params_list))
01832 params_list++;
01833 break;
01834 default:
01835 temp_params[param_count++]
01836 = dupnstr (param, (size_t) (params_list - param));
01837 }
01838 }
01839 if (!*params_list)
01840 break;
01841 }
01842 temp_params[param_count++] = "-aux-info";
01843
01844
01845 aux_info_file_name_index = param_count;
01846 temp_params[param_count++] = NULL;
01847
01848 temp_params[param_count++] = "-S";
01849 temp_params[param_count++] = "-o";
01850
01851 if ((stat (HOST_BIT_BUCKET, &st) == 0)
01852 && (!S_ISDIR (st.st_mode))
01853 && (access (HOST_BIT_BUCKET, W_OK) == 0))
01854 temp_params[param_count++] = HOST_BIT_BUCKET;
01855 else
01856
01857
01858
01859 temp_params[param_count++] = "/dev/null";
01860
01861
01862 input_file_name_index = param_count;
01863 temp_params[param_count++] = NULL;
01864
01865 temp_params[param_count++] = NULL;
01866
01867
01868
01869 compile_params = xmalloc (sizeof (char *) * (param_count+1));
01870 memcpy (compile_params, temp_params, sizeof (char *) * param_count);
01871 }
01872
01873
01874
01875
01876
01877
01878 static int
01879 gen_aux_info_file (const char *base_filename)
01880 {
01881 if (!input_file_name_index)
01882 munge_compile_params ("");
01883
01884
01885 compile_params[input_file_name_index] = shortpath (NULL, base_filename);
01886
01887 compile_params[aux_info_file_name_index] =
01888 concat (compile_params[input_file_name_index], aux_info_suffix, NULL);
01889
01890 if (!quiet_flag)
01891 notice ("%s: compiling '%s'\n",
01892 pname, compile_params[input_file_name_index]);
01893
01894 {
01895 char *errmsg_fmt, *errmsg_arg;
01896 int wait_status, pid;
01897
01898 pid = pexecute (compile_params[0], (char * const *) compile_params,
01899 pname, NULL, &errmsg_fmt, &errmsg_arg,
01900 PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
01901
01902 if (pid == -1)
01903 {
01904 int errno_val = errno;
01905 fprintf (stderr, "%s: ", pname);
01906 fprintf (stderr, errmsg_fmt, errmsg_arg);
01907 fprintf (stderr, ": %s\n", xstrerror (errno_val));
01908 return 0;
01909 }
01910
01911 pid = pwait (pid, &wait_status, 0);
01912 if (pid == -1)
01913 {
01914 notice ("%s: wait: %s\n", pname, xstrerror (errno));
01915 return 0;
01916 }
01917 if (WIFSIGNALED (wait_status))
01918 {
01919 notice ("%s: subprocess got fatal signal %d\n",
01920 pname, WTERMSIG (wait_status));
01921 return 0;
01922 }
01923 if (WIFEXITED (wait_status))
01924 {
01925 if (WEXITSTATUS (wait_status) != 0)
01926 {
01927 notice ("%s: %s exited with status %d\n",
01928 pname, compile_params[0], WEXITSTATUS (wait_status));
01929 return 0;
01930 }
01931 return 1;
01932 }
01933 abort ();
01934 }
01935 }
01936
01937
01938
01939
01940 static void
01941 process_aux_info_file (const char *base_source_filename, int keep_it,
01942 int is_syscalls)
01943 {
01944 size_t base_len = strlen (base_source_filename);
01945 char * aux_info_filename = alloca (base_len + strlen (aux_info_suffix) + 1);
01946 char *aux_info_base;
01947 char *aux_info_limit;
01948 char *aux_info_relocated_name;
01949 const char *aux_info_second_line;
01950 time_t aux_info_mtime;
01951 size_t aux_info_size;
01952 int must_create;
01953
01954
01955
01956 strcpy (aux_info_filename, base_source_filename);
01957 strcat (aux_info_filename, aux_info_suffix);
01958
01959
01960
01961
01962
01963
01964
01965 must_create = 0;
01966
01967
01968 start_over: ;
01969
01970 if (access (aux_info_filename, R_OK) == -1)
01971 {
01972 if (errno == ENOENT)
01973 {
01974 if (is_syscalls)
01975 {
01976 notice ("%s: warning: missing SYSCALLS file '%s'\n",
01977 pname, aux_info_filename);
01978 return;
01979 }
01980 must_create = 1;
01981 }
01982 else
01983 {
01984 int errno_val = errno;
01985 notice ("%s: can't read aux info file '%s': %s\n",
01986 pname, shortpath (NULL, aux_info_filename),
01987 xstrerror (errno_val));
01988 errors++;
01989 return;
01990 }
01991 }
01992 #if 0
01993 else
01994 {
01995 struct stat s1, s2;
01996 stat (aux_info_file_name, &s1);
01997 stat (base_source_file_name, &s2);
01998 if (s2.st_mtime > s1.st_mtime)
01999 must_create = 1;
02000 }
02001 #endif
02002
02003
02004 if (must_create)
02005 {
02006 if (!gen_aux_info_file (base_source_filename))
02007 {
02008 errors++;
02009 return;
02010 }
02011 if (access (aux_info_filename, R_OK) == -1)
02012 {
02013 int errno_val = errno;
02014 notice ("%s: can't read aux info file '%s': %s\n",
02015 pname, shortpath (NULL, aux_info_filename),
02016 xstrerror (errno_val));
02017 errors++;
02018 return;
02019 }
02020 }
02021
02022 {
02023 struct stat stat_buf;
02024
02025
02026
02027 if (stat (aux_info_filename, &stat_buf) == -1)
02028 {
02029 int errno_val = errno;
02030 notice ("%s: can't get status of aux info file '%s': %s\n",
02031 pname, shortpath (NULL, aux_info_filename),
02032 xstrerror (errno_val));
02033 errors++;
02034 return;
02035 }
02036
02037
02038
02039
02040 if ((aux_info_size = stat_buf.st_size) == 0)
02041 return;
02042
02043
02044
02045
02046
02047 aux_info_mtime = stat_buf.st_mtime;
02048
02049 if (!is_syscalls)
02050 {
02051
02052
02053
02054
02055 if (stat (base_source_filename, &stat_buf) == -1)
02056 {
02057 int errno_val = errno;
02058 notice ("%s: can't get status of aux info file '%s': %s\n",
02059 pname, shortpath (NULL, base_source_filename),
02060 xstrerror (errno_val));
02061 errors++;
02062 return;
02063 }
02064 if (stat_buf.st_mtime > aux_info_mtime)
02065 {
02066 must_create = 1;
02067 goto start_over;
02068 }
02069 }
02070 }
02071
02072 {
02073 int aux_info_file;
02074 int fd_flags;
02075
02076
02077
02078 fd_flags = O_RDONLY;
02079 #ifdef O_BINARY
02080
02081 fd_flags |= O_BINARY;
02082 #endif
02083 if ((aux_info_file = open (aux_info_filename, fd_flags, 0444 )) == -1)
02084 {
02085 int errno_val = errno;
02086 notice ("%s: can't open aux info file '%s' for reading: %s\n",
02087 pname, shortpath (NULL, aux_info_filename),
02088 xstrerror (errno_val));
02089 return;
02090 }
02091
02092
02093
02094 aux_info_base = xmalloc (aux_info_size + 1);
02095 aux_info_limit = aux_info_base + aux_info_size;
02096 *aux_info_limit = '\0';
02097
02098
02099
02100 if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
02101 (int) aux_info_size)
02102 {
02103 int errno_val = errno;
02104 notice ("%s: error reading aux info file '%s': %s\n",
02105 pname, shortpath (NULL, aux_info_filename),
02106 xstrerror (errno_val));
02107 free (aux_info_base);
02108 close (aux_info_file);
02109 return;
02110 }
02111
02112
02113
02114 if (close (aux_info_file))
02115 {
02116 int errno_val = errno;
02117 notice ("%s: error closing aux info file '%s': %s\n",
02118 pname, shortpath (NULL, aux_info_filename),
02119 xstrerror (errno_val));
02120 free (aux_info_base);
02121 close (aux_info_file);
02122 return;
02123 }
02124 }
02125
02126
02127
02128
02129 if (must_create && !keep_it)
02130 if (unlink (aux_info_filename) == -1)
02131 {
02132 int errno_val = errno;
02133 notice ("%s: can't delete aux info file '%s': %s\n",
02134 pname, shortpath (NULL, aux_info_filename),
02135 xstrerror (errno_val));
02136 }
02137
02138
02139
02140
02141
02142
02143
02144
02145 {
02146 char *p = aux_info_base;
02147
02148 while (*p != ':'
02149 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
02150 || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
02151 #endif
02152 )
02153 p++;
02154 p++;
02155 while (*p == ' ')
02156 p++;
02157 invocation_filename = p;
02158 while (*p != ' ')
02159 p++;
02160 *p++ = DIR_SEPARATOR;
02161 *p++ = '\0';
02162 while (*p++ != '\n')
02163 continue;
02164 aux_info_second_line = p;
02165 aux_info_relocated_name = 0;
02166 if (! IS_ABSOLUTE_PATH (invocation_filename))
02167 {
02168
02169
02170 char *dir_end;
02171 aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
02172 strcpy (aux_info_relocated_name, base_source_filename);
02173 dir_end = strrchr (aux_info_relocated_name, DIR_SEPARATOR);
02174 #ifdef DIR_SEPARATOR_2
02175 {
02176 char *slash;
02177
02178 slash = strrchr (dir_end ? dir_end : aux_info_relocated_name,
02179 DIR_SEPARATOR_2);
02180 if (slash)
02181 dir_end = slash;
02182 }
02183 #endif
02184 if (dir_end)
02185 dir_end++;
02186 else
02187 dir_end = aux_info_relocated_name;
02188 strcpy (dir_end, invocation_filename);
02189 invocation_filename = aux_info_relocated_name;
02190 }
02191 }
02192
02193
02194 {
02195 const char *aux_info_p;
02196
02197
02198
02199
02200
02201
02202 if (!is_syscalls)
02203 {
02204 current_aux_info_lineno = 2;
02205
02206 for (aux_info_p = aux_info_second_line; *aux_info_p; )
02207 {
02208 if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
02209 {
02210 free (aux_info_base);
02211 free (aux_info_relocated_name);
02212 if (keep_it && unlink (aux_info_filename) == -1)
02213 {
02214 int errno_val = errno;
02215 notice ("%s: can't delete file '%s': %s\n",
02216 pname, shortpath (NULL, aux_info_filename),
02217 xstrerror (errno_val));
02218 return;
02219 }
02220 must_create = 1;
02221 goto start_over;
02222 }
02223
02224
02225
02226 while (*aux_info_p != '\n')
02227 aux_info_p++;
02228 aux_info_p++;
02229 current_aux_info_lineno++;
02230 }
02231 }
02232
02233
02234
02235
02236 current_aux_info_lineno = 2;
02237
02238 for (aux_info_p = aux_info_second_line; *aux_info_p;)
02239 {
02240 char *unexpanded_line = unexpand_if_needed (aux_info_p);
02241
02242 if (unexpanded_line)
02243 {
02244 save_def_or_dec (unexpanded_line, is_syscalls);
02245 free (unexpanded_line);
02246 }
02247 else
02248 save_def_or_dec (aux_info_p, is_syscalls);
02249
02250
02251
02252 while (*aux_info_p != '\n')
02253 aux_info_p++;
02254 aux_info_p++;
02255 current_aux_info_lineno++;
02256 }
02257 }
02258
02259 free (aux_info_base);
02260 free (aux_info_relocated_name);
02261 }
02262
02263 #ifndef UNPROTOIZE
02264
02265
02266
02267
02268
02269 static void
02270 rename_c_file (const hash_table_entry *hp)
02271 {
02272 const char *filename = hp->symbol;
02273 int last_char_index = strlen (filename) - 1;
02274 char *const new_filename = alloca (strlen (filename)
02275 + strlen (cplus_suffix) + 1);
02276
02277
02278
02279
02280
02281
02282
02283 if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.'
02284 || IS_SAME_PATH (syscalls_absolute_filename, filename))
02285 return;
02286
02287 strcpy (new_filename, filename);
02288 strcpy (&new_filename[last_char_index], cplus_suffix);
02289
02290 if (rename (filename, new_filename) == -1)
02291 {
02292 int errno_val = errno;
02293 notice ("%s: warning: can't rename file '%s' to '%s': %s\n",
02294 pname, shortpath (NULL, filename),
02295 shortpath (NULL, new_filename), xstrerror (errno_val));
02296 errors++;
02297 return;
02298 }
02299 }
02300
02301 #endif
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311 static void
02312 reverse_def_dec_list (const hash_table_entry *hp)
02313 {
02314 file_info *file_p = hp->fip;
02315 def_dec_info *prev = NULL;
02316 def_dec_info *current = (def_dec_info *) file_p->defs_decs;
02317
02318 if (!current)
02319 return;
02320
02321 prev = current;
02322 if (! (current = (def_dec_info *) current->next_in_file))
02323 return;
02324
02325 prev->next_in_file = NULL;
02326
02327 while (current)
02328 {
02329 def_dec_info *next = (def_dec_info *) current->next_in_file;
02330
02331 current->next_in_file = prev;
02332 prev = current;
02333 current = next;
02334 }
02335
02336 file_p->defs_decs = prev;
02337 }
02338
02339 #ifndef UNPROTOIZE
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352 static const def_dec_info *
02353 find_extern_def (const def_dec_info *head, const def_dec_info *user)
02354 {
02355 const def_dec_info *dd_p;
02356 const def_dec_info *extern_def_p = NULL;
02357 int conflict_noted = 0;
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
02375 if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
02376 return dd_p;
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
02388 if (dd_p->is_func_def && !dd_p->is_static)
02389 {
02390 if (!extern_def_p)
02391 extern_def_p = dd_p;
02392 else
02393 {
02394
02395
02396 if (is_syscalls_file (dd_p->file))
02397 continue;
02398
02399
02400
02401
02402 if (is_syscalls_file (extern_def_p->file))
02403 {
02404 extern_def_p = dd_p;
02405 continue;
02406 }
02407
02408
02409
02410
02411
02412 if (!conflict_noted)
02413 {
02414 conflict_noted = 1;
02415 notice ("%s: conflicting extern definitions of '%s'\n",
02416 pname, head->hash_entry->symbol);
02417 if (!quiet_flag)
02418 {
02419 notice ("%s: declarations of '%s' will not be converted\n",
02420 pname, head->hash_entry->symbol);
02421 notice ("%s: conflict list for '%s' follows:\n",
02422 pname, head->hash_entry->symbol);
02423 fprintf (stderr, "%s: %s(%d): %s\n",
02424 pname,
02425 shortpath (NULL, extern_def_p->file->hash_entry->symbol),
02426 extern_def_p->line, extern_def_p->ansi_decl);
02427 }
02428 }
02429 if (!quiet_flag)
02430 fprintf (stderr, "%s: %s(%d): %s\n",
02431 pname,
02432 shortpath (NULL, dd_p->file->hash_entry->symbol),
02433 dd_p->line, dd_p->ansi_decl);
02434 }
02435 }
02436
02437
02438
02439
02440
02441 if (conflict_noted)
02442 return NULL;
02443
02444 if (!extern_def_p)
02445 {
02446
02447
02448
02449 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
02450 if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
02451 {
02452 extern_def_p = dd_p;
02453 if (!quiet_flag)
02454 notice ("%s: warning: using formals list from %s(%d) for function '%s'\n",
02455 pname,
02456 shortpath (NULL, dd_p->file->hash_entry->symbol),
02457 dd_p->line, dd_p->hash_entry->symbol);
02458 break;
02459 }
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473 if (!extern_def_p)
02474 {
02475 const char *file = user->file->hash_entry->symbol;
02476
02477 if (!quiet_flag)
02478 if (in_system_include_dir (file))
02479 {
02480
02481
02482 char *needed = alloca (strlen (user->ansi_decl) + 1);
02483 char *p;
02484
02485 strcpy (needed, user->ansi_decl);
02486 p = strstr (needed, user->hash_entry->symbol)
02487 + strlen (user->hash_entry->symbol) + 2;
02488
02489 *p++ = '?';
02490 *p++ = '?';
02491 *p++ = '?';
02492 strcpy (p, ");");
02493
02494 notice ("%s: %d: '%s' used but missing from SYSCALLS\n",
02495 shortpath (NULL, file), user->line,
02496 needed+7);
02497 }
02498 #if 0
02499 else
02500 notice ("%s: %d: warning: no extern definition for '%s'\n",
02501 shortpath (NULL, file), user->line,
02502 user->hash_entry->symbol);
02503 #endif
02504 }
02505 }
02506 return extern_def_p;
02507 }
02508
02509
02510
02511
02512
02513 static const def_dec_info *
02514 find_static_definition (const def_dec_info *user)
02515 {
02516 const def_dec_info *head = user->hash_entry->ddip;
02517 const def_dec_info *dd_p;
02518 int num_static_defs = 0;
02519 const def_dec_info *static_def_p = NULL;
02520
02521 for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
02522 if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
02523 {
02524 static_def_p = dd_p;
02525 num_static_defs++;
02526 }
02527 if (num_static_defs == 0)
02528 {
02529 if (!quiet_flag)
02530 notice ("%s: warning: no static definition for '%s' in file '%s'\n",
02531 pname, head->hash_entry->symbol,
02532 shortpath (NULL, user->file->hash_entry->symbol));
02533 }
02534 else if (num_static_defs > 1)
02535 {
02536 notice ("%s: multiple static defs of '%s' in file '%s'\n",
02537 pname, head->hash_entry->symbol,
02538 shortpath (NULL, user->file->hash_entry->symbol));
02539 return NULL;
02540 }
02541 return static_def_p;
02542 }
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562 static void
02563 connect_defs_and_decs (const hash_table_entry *hp)
02564 {
02565 const def_dec_info *dd_p;
02566 const def_dec_info *extern_def_p = NULL;
02567 int first_extern_reference = 1;
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
02587 if (dd_p->prototyped)
02588 ((NONCONST def_dec_info *) dd_p)->definition = dd_p;
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
02607 if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
02608 {
02609 if (first_extern_reference)
02610 {
02611 extern_def_p = find_extern_def (hp->ddip, dd_p);
02612 first_extern_reference = 0;
02613 }
02614 ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
02615 }
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
02638 if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
02639 {
02640 const def_dec_info *dd_p2;
02641 const def_dec_info *static_def;
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662 ((NONCONST def_dec_info *) dd_p)->definition =
02663 (static_def = find_static_definition (dd_p))
02664 ? static_def
02665 : (const def_dec_info *) -1;
02666
02667 for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
02668 if (!dd_p2->is_func_def && dd_p2->is_static
02669 && !dd_p2->definition && (dd_p2->file == dd_p->file))
02670 ((NONCONST def_dec_info *) dd_p2)->definition = dd_p->definition;
02671 }
02672
02673
02674
02675
02676 for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
02677 if (dd_p->definition == (def_dec_info *) -1)
02678 ((NONCONST def_dec_info *) dd_p)->definition = NULL;
02679 }
02680
02681 #endif
02682
02683
02684
02685
02686 static int
02687 identify_lineno (const char *clean_p)
02688 {
02689 int line_num = 1;
02690 const char *scan_p;
02691
02692 for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
02693 if (*scan_p == '\n')
02694 line_num++;
02695 return line_num;
02696 }
02697
02698
02699
02700 static void
02701 declare_source_confusing (const char *clean_p)
02702 {
02703 if (!quiet_flag)
02704 {
02705 if (clean_p == 0)
02706 notice ("%s: %d: warning: source too confusing\n",
02707 shortpath (NULL, convert_filename), last_known_line_number);
02708 else
02709 notice ("%s: %d: warning: source too confusing\n",
02710 shortpath (NULL, convert_filename),
02711 identify_lineno (clean_p));
02712 }
02713 longjmp (source_confusion_recovery, 1);
02714 }
02715
02716
02717
02718
02719
02720 static void
02721 check_source (int cond, const char *clean_p)
02722 {
02723 if (!cond)
02724 declare_source_confusing (clean_p);
02725 }
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742 static const char *
02743 seek_to_line (int n)
02744 {
02745 if (n < last_known_line_number)
02746 abort ();
02747
02748 while (n > last_known_line_number)
02749 {
02750 while (*last_known_line_start != '\n')
02751 check_source (++last_known_line_start < clean_text_limit, 0);
02752 last_known_line_start++;
02753 last_known_line_number++;
02754 }
02755 return last_known_line_start;
02756 }
02757
02758
02759
02760
02761 static const char *
02762 forward_to_next_token_char (const char *ptr)
02763 {
02764 for (++ptr; ISSPACE ((const unsigned char)*ptr);
02765 check_source (++ptr < clean_text_limit, 0))
02766 continue;
02767 return ptr;
02768 }
02769
02770
02771
02772
02773
02774 static void
02775 output_bytes (const char *str, size_t len)
02776 {
02777 if ((repl_write_ptr + 1) + len >= repl_text_limit)
02778 {
02779 size_t new_size = (repl_text_limit - repl_text_base) << 1;
02780 char *new_buf = xrealloc (repl_text_base, new_size);
02781
02782 repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
02783 repl_text_base = new_buf;
02784 repl_text_limit = new_buf + new_size;
02785 }
02786 memcpy (repl_write_ptr + 1, str, len);
02787 repl_write_ptr += len;
02788 }
02789
02790
02791
02792
02793 static void
02794 output_string (const char *str)
02795 {
02796 output_bytes (str, strlen (str));
02797 }
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818 static void
02819 output_up_to (const char *p)
02820 {
02821 size_t copy_length = (size_t) (p - clean_read_ptr);
02822 const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
02823
02824 if (copy_length == 0)
02825 return;
02826
02827 output_bytes (copy_start, copy_length);
02828 clean_read_ptr = p;
02829 }
02830
02831
02832
02833
02834
02835
02836
02837 static int
02838 other_variable_style_function (const char *ansi_header)
02839 {
02840 #ifdef UNPROTOIZE
02841
02842
02843
02844
02845 return strstr (ansi_header, "...") != 0;
02846
02847 #else
02848
02849
02850
02851
02852 const char *p;
02853 int len = strlen (varargs_style_indicator);
02854
02855 for (p = ansi_header; p; )
02856 {
02857 const char *candidate;
02858
02859 if ((candidate = strstr (p, varargs_style_indicator)) == 0)
02860 return 0;
02861 else
02862 if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
02863 return 1;
02864 else
02865 p = candidate + 1;
02866 }
02867 return 0;
02868 #endif
02869 }
02870
02871
02872
02873
02874
02875 static void
02876 edit_fn_declaration (const def_dec_info *def_dec_p,
02877 const char *volatile clean_text_p)
02878 {
02879 const char *start_formals;
02880 const char *end_formals;
02881 const char *function_to_edit = def_dec_p->hash_entry->symbol;
02882 size_t func_name_len = strlen (function_to_edit);
02883 const char *end_of_fn_name;
02884
02885 #ifndef UNPROTOIZE
02886
02887 const f_list_chain_item *this_f_list_chain_item;
02888 const def_dec_info *definition = def_dec_p->definition;
02889
02890
02891
02892
02893
02894 if (!definition)
02895 return;
02896
02897
02898
02899
02900
02901
02902 if (other_variable_style_function (definition->ansi_decl))
02903 {
02904 if (!quiet_flag)
02905 notice ("%s: %d: warning: varargs function declaration not converted\n",
02906 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
02907 def_dec_p->line);
02908 return;
02909 }
02910
02911 #endif
02912
02913
02914
02915
02916 save_pointers ();
02917 if (setjmp (source_confusion_recovery))
02918 {
02919 restore_pointers ();
02920 notice ("%s: declaration of function '%s' not converted\n",
02921 pname, function_to_edit);
02922 return;
02923 }
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936 while (*clean_text_p != '\n')
02937 check_source (++clean_text_p < clean_text_limit, 0);
02938 clean_text_p--;
02939
02940
02941
02942 do
02943 {
02944 for (;;)
02945 {
02946
02947
02948
02949 while (!is_id_char (*clean_text_p))
02950 check_source (--clean_text_p > clean_read_ptr, 0);
02951
02952
02953
02954
02955 while (is_id_char (*clean_text_p))
02956 check_source (--clean_text_p > clean_read_ptr, 0);
02957
02958
02959
02960
02961 if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
02962 {
02963 char ch = *(clean_text_p + 1 + func_name_len);
02964
02965
02966
02967
02968
02969 if (! is_id_char (ch))
02970 break;
02971 }
02972 }
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986 end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
02987 start_formals = forward_to_next_token_char (end_of_fn_name);
02988 }
02989 while (*start_formals != '(');
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999 #ifndef UNPROTOIZE
03000 this_f_list_chain_item = definition->f_list_chain;
03001 #endif
03002
03003 for (;;)
03004 {
03005 {
03006 int depth;
03007
03008 end_formals = start_formals + 1;
03009 depth = 1;
03010 for (; depth; check_source (++end_formals < clean_text_limit, 0))
03011 {
03012 switch (*end_formals)
03013 {
03014 case '(':
03015 depth++;
03016 break;
03017 case ')':
03018 depth--;
03019 break;
03020 }
03021 }
03022 end_formals--;
03023 }
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033 output_up_to (start_formals);
03034 #ifndef UNPROTOIZE
03035 if (this_f_list_chain_item)
03036 {
03037 output_string (this_f_list_chain_item->formals_list);
03038 this_f_list_chain_item = this_f_list_chain_item->chain_next;
03039 }
03040 else
03041 {
03042 if (!quiet_flag)
03043 notice ("%s: warning: too many parameter lists in declaration of '%s'\n",
03044 pname, def_dec_p->hash_entry->symbol);
03045 check_source (0, end_formals);
03046 }
03047 #endif
03048 clean_read_ptr = end_formals - 1;
03049
03050
03051
03052
03053
03054 {
03055 const char *another_r_paren = forward_to_next_token_char (end_formals);
03056
03057 if ((*another_r_paren != ')')
03058 || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
03059 {
03060 #ifndef UNPROTOIZE
03061 if (this_f_list_chain_item)
03062 {
03063 if (!quiet_flag)
03064 notice ("\n%s: warning: too few parameter lists in declaration of '%s'\n",
03065 pname, def_dec_p->hash_entry->symbol);
03066 check_source (0, start_formals);
03067 }
03068 #endif
03069 break;
03070
03071 }
03072 }
03073
03074
03075
03076 }
03077 }
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090 static int
03091 edit_formals_lists (const char *end_formals, unsigned int f_list_count,
03092 const def_dec_info *def_dec_p)
03093 {
03094 const char *start_formals;
03095 int depth;
03096
03097 start_formals = end_formals - 1;
03098 depth = 1;
03099 for (; depth; check_source (--start_formals > clean_read_ptr, 0))
03100 {
03101 switch (*start_formals)
03102 {
03103 case '(':
03104 depth--;
03105 break;
03106 case ')':
03107 depth++;
03108 break;
03109 }
03110 }
03111 start_formals++;
03112
03113
03114
03115 f_list_count--;
03116
03117 if (f_list_count)
03118 {
03119 const char *next_end;
03120
03121
03122
03123 next_end = start_formals - 1;
03124 check_source (next_end > clean_read_ptr, 0);
03125 while (ISSPACE ((const unsigned char)*next_end))
03126 check_source (--next_end > clean_read_ptr, 0);
03127 check_source (*next_end == ')', next_end);
03128 check_source (--next_end > clean_read_ptr, 0);
03129 check_source (*next_end == ')', next_end);
03130 if (edit_formals_lists (next_end, f_list_count, def_dec_p))
03131 return 1;
03132 }
03133
03134
03135
03136
03137
03138 if (f_list_count == 0)
03139 {
03140 const char *expected = def_dec_p->hash_entry->symbol;
03141 const char *func_name_start;
03142 const char *func_name_limit;
03143 size_t func_name_len;
03144
03145 for (func_name_limit = start_formals-1;
03146 ISSPACE ((const unsigned char)*func_name_limit); )
03147 check_source (--func_name_limit > clean_read_ptr, 0);
03148
03149 for (func_name_start = func_name_limit++;
03150 is_id_char (*func_name_start);
03151 func_name_start--)
03152 check_source (func_name_start > clean_read_ptr, 0);
03153 func_name_start++;
03154 func_name_len = func_name_limit - func_name_start;
03155 if (func_name_len == 0)
03156 check_source (0, func_name_start);
03157 if (func_name_len != strlen (expected)
03158 || strncmp (func_name_start, expected, func_name_len))
03159 {
03160 notice ("%s: %d: warning: found '%s' but expected '%s'\n",
03161 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
03162 identify_lineno (func_name_start),
03163 dupnstr (func_name_start, func_name_len),
03164 expected);
03165 return 1;
03166 }
03167 }
03168
03169 output_up_to (start_formals);
03170
03171 #ifdef UNPROTOIZE
03172 if (f_list_count == 0)
03173 output_string (def_dec_p->formal_names);
03174 #else
03175 {
03176 unsigned f_list_depth;
03177 const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
03178
03179
03180
03181
03182
03183 for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
03184 flci_p = flci_p->chain_next;
03185 output_string (flci_p->formals_list);
03186 }
03187 #endif
03188
03189 clean_read_ptr = end_formals - 1;
03190 return 0;
03191 }
03192
03193
03194
03195
03196
03197
03198
03199 static const char *
03200 find_rightmost_formals_list (const char *clean_text_p)
03201 {
03202 const char *end_formals;
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224 for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
03225 continue;
03226 end_formals--;
03227
03228 #ifdef UNPROTOIZE
03229
03230
03231
03232
03233 {
03234 char ch;
03235 const char *l_brace_p;
03236
03237
03238
03239 while (*end_formals != ')')
03240 {
03241 if (ISSPACE ((unsigned char)*end_formals))
03242 while (ISSPACE ((unsigned char)*end_formals))
03243 check_source (--end_formals > clean_read_ptr, 0);
03244 else
03245 check_source (--end_formals > clean_read_ptr, 0);
03246 }
03247
03248 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
03249
03250
03251
03252
03253
03254 check_source (ch == '{', l_brace_p);
03255 }
03256
03257 #else
03258
03259
03260
03261
03262 while (1)
03263 {
03264 char ch;
03265 const char *l_brace_p;
03266
03267
03268
03269 while (*end_formals != ')')
03270 {
03271 if (ISSPACE ((const unsigned char)*end_formals))
03272 while (ISSPACE ((const unsigned char)*end_formals))
03273 check_source (--end_formals > clean_read_ptr, 0);
03274 else
03275 check_source (--end_formals > clean_read_ptr, 0);
03276 }
03277
03278 ch = *(l_brace_p = forward_to_next_token_char (end_formals));
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290 if ((ch == '{') || ISALPHA ((unsigned char) ch))
03291 break;
03292
03293
03294
03295
03296
03297 check_source (--end_formals > clean_read_ptr, 0);
03298 }
03299
03300 #endif
03301
03302 return end_formals;
03303 }
03304
03305 #ifndef UNPROTOIZE
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316 static void
03317 add_local_decl (const def_dec_info *def_dec_p, const char *clean_text_p)
03318 {
03319 const char *start_of_block;
03320 const char *function_to_edit = def_dec_p->hash_entry->symbol;
03321
03322
03323
03324
03325 if (!local_flag)
03326 return;
03327
03328
03329
03330
03331 save_pointers ();
03332 if (setjmp (source_confusion_recovery))
03333 {
03334 restore_pointers ();
03335 notice ("%s: local declaration for function '%s' not inserted\n",
03336 pname, function_to_edit);
03337 return;
03338 }
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349 start_of_block = clean_text_p;
03350 while (*start_of_block != '{' && *start_of_block != '\n')
03351 check_source (++start_of_block < clean_text_limit, 0);
03352
03353
03354
03355
03356
03357
03358
03359 if (*start_of_block != '{')
03360 {
03361 if (!quiet_flag)
03362 notice ("\n%s: %d: warning: can't add declaration of '%s' into macro call\n",
03363 def_dec_p->file->hash_entry->symbol, def_dec_p->line,
03364 def_dec_p->hash_entry->symbol);
03365 return;
03366 }
03367
03368
03369
03370
03371
03372
03373 {
03374 const char *ep = forward_to_next_token_char (start_of_block) - 1;
03375 const char *sp;
03376
03377
03378
03379
03380
03381
03382
03383 for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--)
03384 continue;
03385
03386
03387
03388
03389
03390 output_up_to (ep);
03391
03392
03393
03394
03395
03396
03397
03398 {
03399 const char *decl = def_dec_p->definition->ansi_decl;
03400
03401 if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
03402 decl += 7;
03403 output_string (decl);
03404 }
03405
03406
03407
03408
03409
03410 output_bytes (sp, (size_t) (ep - sp) + 1);
03411 }
03412 }
03413
03414
03415
03416
03417
03418
03419
03420
03421 static void
03422 add_global_decls (const file_info *file_p, const char *clean_text_p)
03423 {
03424 const def_dec_info *dd_p;
03425 const char *scan_p;
03426
03427
03428
03429
03430 save_pointers ();
03431 if (setjmp (source_confusion_recovery))
03432 {
03433 restore_pointers ();
03434 notice ("%s: global declarations for file '%s' not inserted\n",
03435 pname, shortpath (NULL, file_p->hash_entry->symbol));
03436 return;
03437 }
03438
03439
03440
03441
03442
03443
03444 scan_p = find_rightmost_formals_list (clean_text_p);
03445 for (;; --scan_p)
03446 {
03447 if (scan_p < clean_text_base)
03448 break;
03449 check_source (scan_p > clean_read_ptr, 0);
03450 if (*scan_p == ';')
03451 break;
03452 }
03453
03454
03455
03456
03457
03458
03459
03460
03461 scan_p++;
03462 while (ISSPACE ((const unsigned char)*scan_p))
03463 scan_p++;
03464 scan_p--;
03465
03466 output_up_to (scan_p);
03467
03468
03469
03470
03471
03472
03473 {
03474 int some_decls_added = 0;
03475
03476 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
03477 if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
03478 {
03479 const char *decl = dd_p->definition->ansi_decl;
03480
03481
03482
03483
03484
03485 if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
03486 decl += 7;
03487
03488 output_string ("\n");
03489 output_string (decl);
03490 some_decls_added = 1;
03491 ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
03492 }
03493 if (some_decls_added)
03494 output_string ("\n\n");
03495 }
03496
03497
03498
03499 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
03500 if (dd_p->definition)
03501 ((NONCONST def_dec_info *) dd_p->definition)->written = 0;
03502 }
03503
03504 #endif
03505
03506
03507
03508
03509
03510 static void
03511 edit_fn_definition (const def_dec_info *def_dec_p, const char *clean_text_p)
03512 {
03513 const char *end_formals;
03514 const char *function_to_edit = def_dec_p->hash_entry->symbol;
03515
03516
03517
03518
03519 save_pointers ();
03520 if (setjmp (source_confusion_recovery))
03521 {
03522 restore_pointers ();
03523 notice ("%s: definition of function '%s' not converted\n",
03524 pname, function_to_edit);
03525 return;
03526 }
03527
03528 end_formals = find_rightmost_formals_list (clean_text_p);
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539 if (other_variable_style_function (def_dec_p->ansi_decl))
03540 {
03541 if (!quiet_flag)
03542 notice ("%s: %d: warning: definition of %s not converted\n",
03543 shortpath (NULL, def_dec_p->file->hash_entry->symbol),
03544 identify_lineno (end_formals),
03545 other_var_style);
03546 output_up_to (end_formals);
03547 return;
03548 }
03549
03550 if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
03551 {
03552 restore_pointers ();
03553 notice ("%s: definition of function '%s' not converted\n",
03554 pname, function_to_edit);
03555 return;
03556 }
03557
03558
03559
03560
03561 output_up_to (end_formals);
03562
03563 #ifdef UNPROTOIZE
03564 {
03565 const char *decl_p;
03566 const char *semicolon_p;
03567 const char *limit_p;
03568 const char *scan_p;
03569 int had_newlines = 0;
03570
03571
03572
03573 decl_p = def_dec_p->formal_decls;
03574 limit_p = decl_p + strlen (decl_p);
03575 for (;decl_p < limit_p; decl_p = semicolon_p + 2)
03576 {
03577 for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
03578 continue;
03579 output_string ("\n");
03580 output_string (indent_string);
03581 output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
03582 }
03583
03584
03585
03586
03587 for (scan_p = end_formals+1; *scan_p != '{'; )
03588 {
03589 if (*scan_p == '\n')
03590 {
03591 had_newlines = 1;
03592 break;
03593 }
03594 check_source (++scan_p < clean_text_limit, 0);
03595 }
03596 if (!had_newlines)
03597 output_string ("\n");
03598 }
03599 #else
03600
03601
03602
03603
03604
03605
03606
03607 {
03608 const char *end_formals_orig;
03609 const char *start_body;
03610 const char *start_body_orig;
03611 const char *scan;
03612 const char *scan_orig;
03613 int have_flotsam = 0;
03614 int have_newlines = 0;
03615
03616 for (start_body = end_formals + 1; *start_body != '{';)
03617 check_source (++start_body < clean_text_limit, 0);
03618
03619 end_formals_orig = orig_text_base + (end_formals - clean_text_base);
03620 start_body_orig = orig_text_base + (start_body - clean_text_base);
03621 scan = end_formals + 1;
03622 scan_orig = end_formals_orig + 1;
03623 for (; scan < start_body; scan++, scan_orig++)
03624 {
03625 if (*scan == *scan_orig)
03626 {
03627 have_newlines |= (*scan_orig == '\n');
03628
03629 if (!ISSPACE ((const unsigned char)*scan_orig))
03630 *((NONCONST char *) scan_orig) = ' ';
03631 }
03632 else
03633 have_flotsam = 1;
03634 }
03635 if (have_flotsam)
03636 output_bytes (end_formals_orig + 1,
03637 (size_t) (start_body_orig - end_formals_orig) - 1);
03638 else
03639 if (have_newlines)
03640 output_string ("\n");
03641 else
03642 output_string (" ");
03643 clean_read_ptr = start_body - 1;
03644 }
03645 #endif
03646 }
03647
03648
03649
03650
03651
03652 static void
03653 do_cleaning (char *new_clean_text_base, const char *new_clean_text_limit)
03654 {
03655 char *scan_p;
03656 int non_whitespace_since_newline = 0;
03657
03658 for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
03659 {
03660 switch (*scan_p)
03661 {
03662 case '/':
03663 if (scan_p[1] != '*')
03664 goto regular;
03665 non_whitespace_since_newline = 1;
03666 scan_p[0] = ' ';
03667 scan_p[1] = ' ';
03668 scan_p += 2;
03669 while (scan_p[1] != '/' || scan_p[0] != '*')
03670 {
03671 if (!ISSPACE ((const unsigned char)*scan_p))
03672 *scan_p = ' ';
03673 if (++scan_p >= new_clean_text_limit)
03674 abort ();
03675 }
03676 *scan_p++ = ' ';
03677 *scan_p = ' ';
03678 break;
03679
03680 case '#':
03681 if (non_whitespace_since_newline)
03682 goto regular;
03683 *scan_p = ' ';
03684 while (scan_p[1] != '\n' || scan_p[0] == '\\')
03685 {
03686 if (!ISSPACE ((const unsigned char)*scan_p))
03687 *scan_p = ' ';
03688 if (++scan_p >= new_clean_text_limit)
03689 abort ();
03690 }
03691 *scan_p++ = ' ';
03692 break;
03693
03694 case '\'':
03695 non_whitespace_since_newline = 1;
03696 while (scan_p[1] != '\'' || scan_p[0] == '\\')
03697 {
03698 if (scan_p[0] == '\\'
03699 && !ISSPACE ((const unsigned char) scan_p[1]))
03700 scan_p[1] = ' ';
03701 if (!ISSPACE ((const unsigned char)*scan_p))
03702 *scan_p = ' ';
03703 if (++scan_p >= new_clean_text_limit)
03704 abort ();
03705 }
03706 *scan_p++ = ' ';
03707 break;
03708
03709 case '"':
03710 non_whitespace_since_newline = 1;
03711 while (scan_p[1] != '"' || scan_p[0] == '\\')
03712 {
03713 if (scan_p[0] == '\\'
03714 && !ISSPACE ((const unsigned char) scan_p[1]))
03715 scan_p[1] = ' ';
03716 if (!ISSPACE ((const unsigned char)*scan_p))
03717 *scan_p = ' ';
03718 if (++scan_p >= new_clean_text_limit)
03719 abort ();
03720 }
03721 if (!ISSPACE ((const unsigned char)*scan_p))
03722 *scan_p = ' ';
03723 scan_p++;
03724 break;
03725
03726 case '\\':
03727 if (scan_p[1] != '\n')
03728 goto regular;
03729 *scan_p = ' ';
03730 break;
03731
03732 case '\n':
03733 non_whitespace_since_newline = 0;
03734 break;
03735
03736 case ' ':
03737 case '\v':
03738 case '\t':
03739 case '\r':
03740 case '\f':
03741 case '\b':
03742 break;
03743
03744 default:
03745 regular:
03746 non_whitespace_since_newline = 1;
03747 break;
03748 }
03749 }
03750 }
03751
03752
03753
03754
03755
03756 static const char *
03757 careful_find_l_paren (const char *p)
03758 {
03759 const char *q;
03760 int paren_depth;
03761
03762 for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
03763 {
03764 switch (*q)
03765 {
03766 case ')':
03767 paren_depth++;
03768 break;
03769 case '(':
03770 paren_depth--;
03771 break;
03772 }
03773 }
03774 return ++q;
03775 }
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794 static void
03795 scan_for_missed_items (const file_info *file_p)
03796 {
03797 static const char *scan_p;
03798 const char *limit = clean_text_limit - 3;
03799 static const char *backup_limit;
03800
03801 backup_limit = clean_text_base - 1;
03802
03803 for (scan_p = clean_text_base; scan_p < limit; scan_p++)
03804 {
03805 if (*scan_p == ')')
03806 {
03807 static const char *last_r_paren;
03808 const char *ahead_p;
03809
03810 last_r_paren = scan_p;
03811
03812 for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
03813 check_source (++ahead_p < limit, limit);
03814
03815 scan_p = ahead_p - 1;
03816
03817 if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
03818 {
03819 const char *last_l_paren;
03820 const int lineno = identify_lineno (ahead_p);
03821
03822 if (setjmp (source_confusion_recovery))
03823 continue;
03824
03825
03826
03827
03828 do
03829 {
03830 last_l_paren = careful_find_l_paren (last_r_paren);
03831 for (last_r_paren = last_l_paren-1;
03832 ISSPACE ((const unsigned char)*last_r_paren); )
03833 check_source (--last_r_paren >= backup_limit, backup_limit);
03834 }
03835 while (*last_r_paren == ')');
03836
03837 if (is_id_char (*last_r_paren))
03838 {
03839 const char *id_limit = last_r_paren + 1;
03840 const char *id_start;
03841 size_t id_length;
03842 const def_dec_info *dd_p;
03843
03844 for (id_start = id_limit-1; is_id_char (*id_start); )
03845 check_source (--id_start >= backup_limit, backup_limit);
03846 id_start++;
03847 backup_limit = id_start;
03848 if ((id_length = (size_t) (id_limit - id_start)) == 0)
03849 goto not_missed;
03850
03851 {
03852 char *func_name = alloca (id_length + 1);
03853 static const char * const stmt_keywords[]
03854 = { "if", "else", "do", "while", "for", "switch", "case", "return", 0 };
03855 const char * const *stmt_keyword;
03856
03857 strncpy (func_name, id_start, id_length);
03858 func_name[id_length] = '\0';
03859
03860
03861
03862
03863 for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
03864 if (!strcmp (func_name, *stmt_keyword))
03865 goto not_missed;
03866
03867 #if 0
03868 notice ("%s: found definition of '%s' at %s(%d)\n",
03869 pname,
03870 func_name,
03871 shortpath (NULL, file_p->hash_entry->symbol),
03872 identify_lineno (id_start));
03873 #endif
03874
03875
03876
03877 for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
03878 if (dd_p->is_func_def && dd_p->line == lineno)
03879 goto not_missed;
03880
03881
03882
03883
03884 notice ("%s: %d: warning: '%s' excluded by preprocessing\n",
03885 shortpath (NULL, file_p->hash_entry->symbol),
03886 identify_lineno (id_start), func_name);
03887 notice ("%s: function definition not converted\n",
03888 pname);
03889 }
03890 not_missed: ;
03891 }
03892 }
03893 }
03894 }
03895 }
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909 static void
03910 edit_file (const hash_table_entry *hp)
03911 {
03912 struct stat stat_buf;
03913 const file_info *file_p = hp->fip;
03914 char *new_orig_text_base;
03915 char *new_orig_text_limit;
03916 char *new_clean_text_base;
03917 char *new_clean_text_limit;
03918 size_t orig_size;
03919 size_t repl_size;
03920 int first_definition_in_file;
03921
03922
03923
03924
03925 if (!needs_to_be_converted (file_p))
03926 return;
03927
03928 convert_filename = file_p->hash_entry->symbol;
03929
03930
03931
03932
03933 if (!directory_specified_p (convert_filename)
03934 || file_excluded_p (convert_filename))
03935 {
03936 if (!quiet_flag
03937 #ifdef UNPROTOIZE
03938
03939
03940
03941
03942 && !in_system_include_dir (convert_filename)
03943 #endif
03944 )
03945 notice ("%s: '%s' not converted\n",
03946 pname, shortpath (NULL, convert_filename));
03947 return;
03948 }
03949
03950
03951
03952 if (nochange_flag)
03953 notice ("%s: would convert file '%s'\n",
03954 pname, shortpath (NULL, convert_filename));
03955 else
03956 notice ("%s: converting file '%s'\n",
03957 pname, shortpath (NULL, convert_filename));
03958 fflush (stderr);
03959
03960
03961
03962
03963 if (stat (convert_filename, &stat_buf) == -1)
03964 {
03965 int errno_val = errno;
03966 notice ("%s: can't get status for file '%s': %s\n",
03967 pname, shortpath (NULL, convert_filename),
03968 xstrerror (errno_val));
03969 return;
03970 }
03971 orig_size = stat_buf.st_size;
03972
03973
03974
03975 orig_text_base = new_orig_text_base = xmalloc (orig_size + 2);
03976 orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
03977
03978
03979
03980 clean_text_base = new_clean_text_base = xmalloc (orig_size + 2);
03981 clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
03982 clean_read_ptr = clean_text_base - 1;
03983
03984
03985
03986
03987
03988
03989 repl_size = orig_size + (orig_size >> 2) + 4096;
03990 repl_text_base = xmalloc (repl_size + 2);
03991 repl_text_limit = repl_text_base + repl_size - 1;
03992 repl_write_ptr = repl_text_base - 1;
03993
03994 {
03995 int input_file;
03996 int fd_flags;
03997
03998
03999
04000 fd_flags = O_RDONLY;
04001 #ifdef O_BINARY
04002
04003 fd_flags |= O_BINARY;
04004 #endif
04005 if ((input_file = open (convert_filename, fd_flags, 0444)) == -1)
04006 {
04007 int errno_val = errno;
04008 notice ("%s: can't open file '%s' for reading: %s\n",
04009 pname, shortpath (NULL, convert_filename),
04010 xstrerror (errno_val));
04011 return;
04012 }
04013
04014
04015
04016
04017
04018 if (safe_read (input_file, new_orig_text_base, orig_size) !=
04019 (int) orig_size)
04020 {
04021 int errno_val = errno;
04022 close (input_file);
04023 notice ("\n%s: error reading input file '%s': %s\n",
04024 pname, shortpath (NULL, convert_filename),
04025 xstrerror (errno_val));
04026 return;
04027 }
04028
04029 close (input_file);
04030 }
04031
04032 if (orig_size == 0 || orig_text_limit[-1] != '\n')
04033 {
04034 *new_orig_text_limit++ = '\n';
04035 orig_text_limit++;
04036 }
04037
04038
04039
04040 memcpy (new_clean_text_base, orig_text_base,
04041 (size_t) (orig_text_limit - orig_text_base));
04042 do_cleaning (new_clean_text_base, new_clean_text_limit);
04043
04044 #if 0
04045 {
04046 int clean_file;
04047 size_t clean_size = orig_text_limit - orig_text_base;
04048 char *const clean_filename = alloca (strlen (convert_filename) + 6 + 1);
04049
04050
04051
04052 strcpy (clean_filename, convert_filename);
04053 strcat (clean_filename, ".clean");
04054 if ((clean_file = creat (clean_filename, 0666)) == -1)
04055 {
04056 int errno_val = errno;
04057 notice ("%s: can't create/open clean file '%s': %s\n",
04058 pname, shortpath (NULL, clean_filename),
04059 xstrerror (errno_val));
04060 return;
04061 }
04062
04063
04064
04065 safe_write (clean_file, new_clean_text_base, clean_size, clean_filename);
04066
04067 close (clean_file);
04068 }
04069 #endif
04070
04071
04072
04073
04074
04075
04076 scan_for_missed_items (file_p);
04077
04078
04079
04080 last_known_line_number = 1;
04081 last_known_line_start = clean_text_base;
04082
04083
04084
04085 {
04086 const def_dec_info *def_dec_p;
04087
04088 first_definition_in_file = 1;
04089 def_dec_p = file_p->defs_decs;
04090 for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
04091 {
04092 const char *clean_text_p = seek_to_line (def_dec_p->line);
04093
04094
04095
04096
04097
04098 #ifndef UNPROTOIZE
04099
04100 if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
04101 {
04102 add_global_decls (def_dec_p->file, clean_text_p);
04103 first_definition_in_file = 0;
04104 }
04105
04106
04107
04108
04109
04110 if (def_dec_p->prototyped
04111 || (!def_dec_p->is_func_def && !def_dec_p->definition))
04112 continue;
04113
04114 #endif
04115
04116 if (def_dec_p->is_func_def)
04117 edit_fn_definition (def_dec_p, clean_text_p);
04118 else
04119 #ifndef UNPROTOIZE
04120 if (def_dec_p->is_implicit)
04121 add_local_decl (def_dec_p, clean_text_p);
04122 else
04123 #endif
04124 edit_fn_declaration (def_dec_p, clean_text_p);
04125 }
04126 }
04127
04128
04129
04130 output_up_to (clean_text_limit - 1);
04131
04132
04133
04134 if (nochange_flag)
04135 {
04136 free (new_orig_text_base);
04137 free (new_clean_text_base);
04138 free (repl_text_base);
04139 return;
04140 }
04141
04142
04143
04144
04145 if (!nosave_flag)
04146 {
04147 char *new_filename
04148 = xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
04149
04150 strcpy (new_filename, convert_filename);
04151 #ifdef __MSDOS__
04152
04153
04154 new_filename[(strlen (convert_filename) - 1] = '\0';
04155 #endif
04156 strcat (new_filename, save_suffix);
04157
04158
04159 if (access (new_filename, F_OK) == 0)
04160 {
04161 if (!quiet_flag)
04162 notice ("%s: warning: file '%s' already saved in '%s'\n",
04163 pname,
04164 shortpath (NULL, convert_filename),
04165 shortpath (NULL, new_filename));
04166 }
04167 else if (rename (convert_filename, new_filename) == -1)
04168 {
04169 int errno_val = errno;
04170 notice ("%s: can't link file '%s' to '%s': %s\n",
04171 pname,
04172 shortpath (NULL, convert_filename),
04173 shortpath (NULL, new_filename),
04174 xstrerror (errno_val));
04175 return;
04176 }
04177 }
04178
04179 if (unlink (convert_filename) == -1)
04180 {
04181 int errno_val = errno;
04182
04183 if (errno_val != ENOENT)
04184 {
04185 notice ("%s: can't delete file '%s': %s\n",
04186 pname, shortpath (NULL, convert_filename),
04187 xstrerror (errno_val));
04188 return;
04189 }
04190 }
04191
04192 {
04193 int output_file;
04194
04195
04196
04197 if ((output_file = creat (convert_filename, 0666)) == -1)
04198 {
04199 int errno_val = errno;
04200 notice ("%s: can't create/open output file '%s': %s\n",
04201 pname, shortpath (NULL, convert_filename),
04202 xstrerror (errno_val));
04203 return;
04204 }
04205 #ifdef O_BINARY
04206
04207 setmode (output_file, O_BINARY);
04208 #endif
04209
04210
04211
04212 {
04213 unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
04214
04215 safe_write (output_file, repl_text_base, out_size, convert_filename);
04216 }
04217
04218 close (output_file);
04219 }
04220
04221
04222
04223 free (new_orig_text_base);
04224 free (new_clean_text_base);
04225 free (repl_text_base);
04226
04227
04228
04229
04230 if (chmod (convert_filename, stat_buf.st_mode) == -1)
04231 {
04232 int errno_val = errno;
04233 notice ("%s: can't change mode of file '%s': %s\n",
04234 pname, shortpath (NULL, convert_filename),
04235 xstrerror (errno_val));
04236 }
04237
04238
04239
04240
04241
04242 }
04243
04244
04245
04246
04247
04248 static void
04249 do_processing (void)
04250 {
04251 const char * const *base_pp;
04252 const char * const * const end_pps
04253 = &base_source_filenames[n_base_source_files];
04254
04255 #ifndef UNPROTOIZE
04256 int syscalls_len;
04257 #endif
04258
04259
04260
04261
04262
04263
04264 for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
04265 process_aux_info_file (*base_pp, keep_flag, 0);
04266
04267 #ifndef UNPROTOIZE
04268
04269
04270
04271
04272 if (nondefault_syscalls_dir)
04273 {
04274 syscalls_absolute_filename
04275 = xmalloc (strlen (nondefault_syscalls_dir) + 1
04276 + sizeof (syscalls_filename));
04277 strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
04278 }
04279 else
04280 {
04281 GET_ENVIRONMENT (default_syscalls_dir, "GCC_EXEC_PREFIX");
04282 if (!default_syscalls_dir)
04283 {
04284 default_syscalls_dir = standard_exec_prefix;
04285 }
04286 syscalls_absolute_filename
04287 = xmalloc (strlen (default_syscalls_dir) + 0
04288 + strlen (target_machine) + 1
04289 + strlen (target_version) + 1
04290 + sizeof (syscalls_filename));
04291 strcpy (syscalls_absolute_filename, default_syscalls_dir);
04292 strcat (syscalls_absolute_filename, target_machine);
04293 strcat (syscalls_absolute_filename, "/");
04294 strcat (syscalls_absolute_filename, target_version);
04295 strcat (syscalls_absolute_filename, "/");
04296 }
04297
04298 syscalls_len = strlen (syscalls_absolute_filename);
04299 if (! IS_DIR_SEPARATOR (*(syscalls_absolute_filename + syscalls_len - 1)))
04300 {
04301 *(syscalls_absolute_filename + syscalls_len++) = DIR_SEPARATOR;
04302 *(syscalls_absolute_filename + syscalls_len) = '\0';
04303 }
04304 strcat (syscalls_absolute_filename, syscalls_filename);
04305
04306
04307
04308
04309 process_aux_info_file (syscalls_absolute_filename, 1, 1);
04310
04311 #endif
04312
04313
04314
04315
04316
04317
04318
04319
04320 visit_each_hash_node (filename_primary, reverse_def_dec_list);
04321
04322 #ifndef UNPROTOIZE
04323
04324
04325
04326
04327
04328
04329
04330
04331 visit_each_hash_node (function_name_primary, connect_defs_and_decs);
04332
04333 #endif
04334
04335
04336
04337 visit_each_hash_node (filename_primary, edit_file);
04338
04339 #ifndef UNPROTOIZE
04340
04341
04342
04343
04344 if (cplusplus_flag && !nochange_flag)
04345 visit_each_hash_node (filename_primary, rename_c_file);
04346
04347 #endif
04348 }
04349
04350 static const struct option longopts[] =
04351 {
04352 {"version", 0, 0, 'V'},
04353 {"file_name", 0, 0, 'p'},
04354 {"quiet", 0, 0, 'q'},
04355 {"silent", 0, 0, 'q'},
04356 {"force", 0, 0, 'f'},
04357 {"keep", 0, 0, 'k'},
04358 {"nosave", 0, 0, 'N'},
04359 {"nochange", 0, 0, 'n'},
04360 {"compiler-options", 1, 0, 'c'},
04361 {"exclude", 1, 0, 'x'},
04362 {"directory", 1, 0, 'd'},
04363 #ifdef UNPROTOIZE
04364 {"indent", 1, 0, 'i'},
04365 #else
04366 {"local", 0, 0, 'l'},
04367 {"global", 0, 0, 'g'},
04368 {"c++", 0, 0, 'C'},
04369 {"syscalls-dir", 1, 0, 'B'},
04370 #endif
04371 {0, 0, 0, 0}
04372 };
04373
04374 extern int main (int, char **const);
04375
04376 int
04377 main (int argc, char **const argv)
04378 {
04379 int longind;
04380 int c;
04381 const char *params = "";
04382
04383 pname = strrchr (argv[0], DIR_SEPARATOR);
04384 #ifdef DIR_SEPARATOR_2
04385 {
04386 char *slash;
04387
04388 slash = strrchr (pname ? pname : argv[0], DIR_SEPARATOR_2);
04389 if (slash)
04390 pname = slash;
04391 }
04392 #endif
04393 pname = pname ? pname+1 : argv[0];
04394
04395 #ifdef SIGCHLD
04396
04397
04398 signal (SIGCHLD, SIG_DFL);
04399 #endif
04400
04401
04402 unlock_std_streams ();
04403
04404 gcc_init_libintl ();
04405
04406 cwd_buffer = getpwd ();
04407 if (!cwd_buffer)
04408 {
04409 notice ("%s: cannot get working directory: %s\n",
04410 pname, xstrerror(errno));
04411 return (FATAL_EXIT_CODE);
04412 }
04413
04414
04415 directory_list = string_list_cons (cwd_buffer, NULL);
04416
04417 while ((c = getopt_long (argc, argv,
04418 #ifdef UNPROTOIZE
04419 "c:d:i:knNp:qvVx:",
04420 #else
04421 "B:c:Cd:gklnNp:qvVx:",
04422 #endif
04423 longopts, &longind)) != EOF)
04424 {
04425 if (c == 0)
04426 c = longopts[longind].val;
04427 switch (c)
04428 {
04429 case 'p':
04430 compiler_file_name = optarg;
04431 break;
04432 case 'd':
04433 directory_list
04434 = string_list_cons (abspath (NULL, optarg), directory_list);
04435 break;
04436 case 'x':
04437 exclude_list = string_list_cons (optarg, exclude_list);
04438 break;
04439
04440 case 'v':
04441 case 'V':
04442 version_flag = 1;
04443 break;
04444 case 'q':
04445 quiet_flag = 1;
04446 break;
04447 #if 0
04448 case 'f':
04449 force_flag = 1;
04450 break;
04451 #endif
04452 case 'n':
04453 nochange_flag = 1;
04454 keep_flag = 1;
04455 break;
04456 case 'N':
04457 nosave_flag = 1;
04458 break;
04459 case 'k':
04460 keep_flag = 1;
04461 break;
04462 case 'c':
04463 params = optarg;
04464 break;
04465 #ifdef UNPROTOIZE
04466 case 'i':
04467 indent_string = optarg;
04468 break;
04469 #else
04470 case 'l':
04471 local_flag = 1;
04472 break;
04473 case 'g':
04474 global_flag = 1;
04475 break;
04476 case 'C':
04477 cplusplus_flag = 1;
04478 break;
04479 case 'B':
04480 nondefault_syscalls_dir = optarg;
04481 break;
04482 #endif
04483 default:
04484 usage ();
04485 }
04486 }
04487
04488
04489 munge_compile_params (params);
04490
04491 n_base_source_files = argc - optind;
04492
04493
04494
04495 base_source_filenames
04496 = xmalloc ((n_base_source_files + 1) * sizeof (char *));
04497 n_base_source_files = 0;
04498 for (; optind < argc; optind++)
04499 {
04500 const char *path = abspath (NULL, argv[optind]);
04501 int len = strlen (path);
04502
04503 if (path[len-1] == 'c' && path[len-2] == '.')
04504 base_source_filenames[n_base_source_files++] = path;
04505 else
04506 {
04507 notice ("%s: input file names must have .c suffixes: %s\n",
04508 pname, shortpath (NULL, path));
04509 errors++;
04510 }
04511 }
04512
04513 #ifndef UNPROTOIZE
04514
04515
04516
04517 {
04518 const char *cp;
04519
04520 for (cp = varargs_style_indicator; ISIDNUM (*cp); cp++)
04521 continue;
04522 if (*cp != 0)
04523 varargs_style_indicator = savestring (varargs_style_indicator,
04524 cp - varargs_style_indicator);
04525 }
04526 #endif
04527
04528 if (errors)
04529 usage ();
04530 else
04531 {
04532 if (version_flag)
04533 fprintf (stderr, "%s: %s\n", pname, version_string);
04534 do_processing ();
04535 }
04536
04537 return (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
04538 }