#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "intl.h"
#include "cppdefault.h"
#include <setjmp.h>
#include <signal.h>
#if ! defined( SIGCHLD ) && defined( SIGCLD )
# define SIGCHLD SIGCLD
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "version.h"
#include "getopt.h"
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
#define IS_SAME_PATH_CHAR(a,b) (TOUPPER (a) == TOUPPER (b))
#else
#define IS_SAME_PATH_CHAR(a,b) ((a) == (b))
#endif
#define IS_SAME_PATH(a,b) (FILENAME_CMP (a, b) == 0)
#ifdef __MSDOS__
#define AUX_INFO_SUFFIX "X"
#else
#define AUX_INFO_SUFFIX ".X"
#endif
#ifdef __MSDOS__
#define SAVE_SUFFIX "sav"
#else
#define SAVE_SUFFIX ".save"
#endif
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
#define CPLUS_FILE_SUFFIX "cc"
#else
#define CPLUS_FILE_SUFFIX "C"
#endif
static void usage (void) ATTRIBUTE_NORETURN;
static void aux_info_corrupted (void) ATTRIBUTE_NORETURN;
static void declare_source_confusing (const char *) ATTRIBUTE_NORETURN;
static const char *shortpath (const char *, const char *);
static void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
static char *savestring (const char *, unsigned int);
static char *dupnstr (const char *, size_t);
static int safe_read (int, void *, int);
static void safe_write (int, void *, int, const char *);
static void save_pointers (void);
static void restore_pointers (void);
static int is_id_char (int);
static int in_system_include_dir (const char *);
static int directory_specified_p (const char *);
static int file_excluded_p (const char *);
static char *unexpand_if_needed (const char *);
static char *abspath (const char *, const char *);
static void check_aux_info (int);
static const char *find_corresponding_lparen (const char *);
static int referenced_file_is_newer (const char *, time_t);
static void save_def_or_dec (const char *, int);
static void munge_compile_params (const char *);
static int gen_aux_info_file (const char *);
static void process_aux_info_file (const char *, int, int);
static int identify_lineno (const char *);
static void check_source (int, const char *);
static const char *seek_to_line (int);
static const char *forward_to_next_token_char (const char *);
static void output_bytes (const char *, size_t);
static void output_string (const char *);
static void output_up_to (const char *);
static int other_variable_style_function (const char *);
static const char *find_rightmost_formals_list (const char *);
static void do_cleaning (char *, const char *);
static const char *careful_find_l_paren (const char *);
static void do_processing (void);
#define NONCONST
#ifndef UNPROTOIZE
#ifndef STANDARD_EXEC_PREFIX
#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
#endif
static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX;
static const char * const target_machine = DEFAULT_TARGET_MACHINE;
static const char * const target_version = DEFAULT_TARGET_VERSION;
#endif
static const char * const aux_info_suffix = AUX_INFO_SUFFIX;
static const char * const save_suffix = SAVE_SUFFIX;
#ifndef UNPROTOIZE
static const char * const cplus_suffix = CPLUS_FILE_SUFFIX;
static const char syscalls_filename[] = "SYSCALLS.c";
static const char * default_syscalls_dir;
static char * syscalls_absolute_filename;
#endif
struct unexpansion_struct {
const char *const expanded;
const char *const contracted;
};
typedef struct unexpansion_struct unexpansion;
static const unexpansion unexpansions[] = {
{ "struct _iobuf", "FILE" },
{ 0, 0 }
};
#define HASH_TABLE_SIZE (1 << 9)
static const int hash_mask = (HASH_TABLE_SIZE - 1);
struct string_list
{
const char *name;
struct string_list *next;
};
static struct string_list *string_list_cons (const char *,
struct string_list *);
struct string_list *directory_list;
struct string_list *exclude_list;
#ifdef UNPROTOIZE
static const char * const other_var_style = "stdarg";
#else
static const char * const other_var_style = "varargs";
static const char *varargs_style_indicator = "va_alist";
#endif
typedef struct hash_table_entry_struct hash_table_entry;
typedef struct def_dec_info_struct def_dec_info;
typedef struct file_info_struct file_info;
typedef struct f_list_chain_item_struct f_list_chain_item;
#ifndef UNPROTOIZE
static int is_syscalls_file (const file_info *);
static void rename_c_file (const hash_table_entry *);
static const def_dec_info *find_extern_def (const def_dec_info *,
const def_dec_info *);
static const def_dec_info *find_static_definition (const def_dec_info *);
static void connect_defs_and_decs (const hash_table_entry *);
static void add_local_decl (const def_dec_info *, const char *);
static void add_global_decls (const file_info *, const char *);
#endif
static int needs_to_be_converted (const file_info *);
static void visit_each_hash_node (const hash_table_entry *,
void (*)(const hash_table_entry *));
static hash_table_entry *add_symbol (hash_table_entry *, const char *);
static hash_table_entry *lookup (hash_table_entry *, const char *);
static void free_def_dec (def_dec_info *);
static file_info *find_file (const char *, int);
static void reverse_def_dec_list (const hash_table_entry *);
static void edit_fn_declaration (const def_dec_info *, const char *);
static int edit_formals_lists (const char *, unsigned int,
const def_dec_info *);
static void edit_fn_definition (const def_dec_info *, const char *);
static void scan_for_missed_items (const file_info *);
static void edit_file (const hash_table_entry *);
struct hash_table_entry_struct {
hash_table_entry * hash_next;
const char * symbol;
union {
const def_dec_info * _ddip;
file_info * _fip;
} _info;
};
#define ddip _info._ddip
#define fip _info._fip
typedef hash_table_entry hash_table[HASH_TABLE_SIZE];
struct file_info_struct {
const hash_table_entry * hash_entry;
const def_dec_info * defs_decs;
time_t mtime;
};
struct f_list_chain_item_struct {
const f_list_chain_item * chain_next;
const char * formals_list;
};
struct def_dec_info_struct {
const def_dec_info * next_in_file;
file_info * file;
int line;
const char * ansi_decl;
hash_table_entry * hash_entry;
unsigned int is_func_def;
const def_dec_info * next_for_func;
unsigned int f_list_count;
char prototyped;
#ifndef UNPROTOIZE
const f_list_chain_item * f_list_chain;
const def_dec_info * definition;
char is_static;
char is_implicit;
char written;
#else
const char * formal_names;
const char * formal_decls;
#endif
};
static const char *pname;
static int errors = 0;
static const char *compiler_file_name = "gcc";
int version_flag = 0;
int quiet_flag = 0;
int nochange_flag = 0;
int nosave_flag = 0;
int keep_flag = 0;
static const char ** compile_params = 0;
#ifdef UNPROTOIZE
static const char *indent_string = " ";
#else
int local_flag = 0;
int global_flag = 0;
int cplusplus_flag = 0;
static const char *nondefault_syscalls_dir = 0;
#endif
static int input_file_name_index = 0;
static int aux_info_file_name_index = 0;
static int n_base_source_files = 0;
static const char **base_source_filenames;
static int current_aux_info_lineno;
static const char *convert_filename;
static const char *invocation_filename;
static const char *orig_text_base;
static const char *orig_text_limit;
static const char *clean_text_base;
static const char *clean_text_limit;
static const char * clean_read_ptr;
static char *repl_text_base;
static char *repl_text_limit;
static char * repl_write_ptr;
static const char *last_known_line_start;
static int last_known_line_number;
static hash_table filename_primary;
static hash_table function_name_primary;
static jmp_buf source_confusion_recovery;
static char *cwd_buffer;
static const char * saved_clean_read_ptr;
static char * saved_repl_write_ptr;
static void
notice (const char *cmsgid, ...)
{
va_list ap;
va_start (ap, cmsgid);
vfprintf (stderr, _(cmsgid), ap);
va_end (ap);
}
static char *
savestring (const char *input, unsigned int size)
{
char *output = xmalloc (size + 1);
strcpy (output, input);
return output;
}
static char *
dupnstr (const char *s, size_t n)
{
char *ret_val = xmalloc (n + 1);
strncpy (ret_val, s, n);
ret_val[n] = '\0';
return ret_val;
}
static int
safe_read (int desc, void *ptr, int len)
{
int left = len;
while (left > 0) {
int nchars = read (desc, ptr, left);
if (nchars < 0)
{
#ifdef EINTR
if (errno == EINTR)
continue;
#endif
return nchars;
}
if (nchars == 0)
break;
ptr = (char *) ptr + nchars;
left -= nchars;
}
return len - left;
}
static void
safe_write (int desc, void *ptr, int len, const char *out_fname)
{
while (len > 0) {
int written = write (desc, ptr, len);
if (written < 0)
{
int errno_val = errno;
#ifdef EINTR
if (errno_val == EINTR)
continue;
#endif
notice ("%s: error writing file '%s': %s\n",
pname, shortpath (NULL, out_fname), xstrerror (errno_val));
return;
}
ptr = (char *) ptr + written;
len -= written;
}
}
static void
save_pointers (void)
{
saved_clean_read_ptr = clean_read_ptr;
saved_repl_write_ptr = repl_write_ptr;
}
static void
restore_pointers (void)
{
clean_read_ptr = saved_clean_read_ptr;
repl_write_ptr = saved_repl_write_ptr;
}
static int
is_id_char (int ch)
{
return (ISIDNUM (ch) || (ch == '$'));
}
static void
usage (void)
{
#ifdef UNPROTOIZE
notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
pname, pname);
#else
notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
pname, pname);
#endif
exit (FATAL_EXIT_CODE);
}
static int
in_system_include_dir (const char *path)
{
const struct default_include *p;
gcc_assert (IS_ABSOLUTE_PATH (path));
for (p = cpp_include_defaults; p->fname; p++)
if (!strncmp (path, p->fname, strlen (p->fname))
&& IS_DIR_SEPARATOR (path[strlen (p->fname)]))
return 1;
return 0;
}
#if 0
static int
file_could_be_converted (const char *path)
{
char *const dir_name = alloca (strlen (path) + 1);
if (access (path, R_OK))
return 0;
{
char *dir_last_slash;
strcpy (dir_name, path);
dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
#ifdef DIR_SEPARATOR_2
{
char *slash;
slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
DIR_SEPARATOR_2);
if (slash)
dir_last_slash = slash;
}
#endif
gcc_assert (dir_last_slash);
*dir_last_slash = '\0';
}
if (access (path, W_OK))
return 0;
return 1;
}
static int
file_normally_convertible (const char *path)
{
char *const dir_name = alloca (strlen (path) + 1);
if (in_system_include_dir (path))
return 0;
{
char *dir_last_slash;
strcpy (dir_name, path);
dir_last_slash = strrchr (dir_name, DIR_SEPARATOR);
#ifdef DIR_SEPARATOR_2
{
char *slash;
slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
DIR_SEPARATOR_2);
if (slash)
dir_last_slash = slash;
}
#endif
gcc_assert (dir_last_slash);
*dir_last_slash = '\0';
}
if (access (path, R_OK))
{
if (!quiet_flag)
notice ("%s: warning: no read access for file '%s'\n",
pname, shortpath (NULL, path));
return 0;
}
if (access (path, W_OK))
{
if (!quiet_flag)
notice ("%s: warning: no write access for file '%s'\n",
pname, shortpath (NULL, path));
return 0;
}
if (access (dir_name, W_OK))
{
if (!quiet_flag)
notice ("%s: warning: no write access for dir containing '%s'\n",
pname, shortpath (NULL, path));
return 0;
}
return 1;
}
#endif
#ifndef UNPROTOIZE
static int
is_syscalls_file (const file_info *fi_p)
{
char const *f = fi_p->hash_entry->symbol;
size_t fl = strlen (f), sysl = sizeof (syscalls_filename) - 1;
return sysl <= fl && strcmp (f + fl - sysl, syscalls_filename) == 0;
}
#endif
static int
needs_to_be_converted (const file_info *file_p)
{
const def_dec_info *ddp;
#ifndef UNPROTOIZE
if (is_syscalls_file (file_p))
return 0;
#endif
for (ddp = file_p->defs_decs; ddp; ddp = ddp->next_in_file)
if (
#ifndef UNPROTOIZE
!ddp->prototyped
&& (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
#else
ddp->prototyped
#endif
)
return -1;
return 0;
}
static int
directory_specified_p (const char *name)
{
struct string_list *p;
for (p = directory_list; p; p = p->next)
if (!strncmp (name, p->name, strlen (p->name))
&& IS_DIR_SEPARATOR (name[strlen (p->name)]))
{
const char *q = name + strlen (p->name) + 1;
while (*q++)
if (IS_DIR_SEPARATOR (*(q-1)))
goto lose;
return 1;
lose: ;
}
return 0;
}
static int
file_excluded_p (const char *name)
{
struct string_list *p;
int len = strlen (name);
for (p = exclude_list; p; p = p->next)
if (!strcmp (name + len - strlen (p->name), p->name)
&& IS_DIR_SEPARATOR (name[len - strlen (p->name) - 1]))
return 1;
return 0;
}
static struct string_list *
string_list_cons (const char *string, struct string_list *rest)
{
struct string_list *temp = xmalloc (sizeof (struct string_list));
temp->next = rest;
temp->name = string;
return temp;
}
static void
visit_each_hash_node (const hash_table_entry *hash_tab_p,
void (*func) (const hash_table_entry *))
{
const hash_table_entry *primary;
for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
if (primary->symbol)
{
hash_table_entry *second;
(*func)(primary);
for (second = primary->hash_next; second; second = second->hash_next)
(*func) (second);
}
}
static hash_table_entry *
add_symbol (hash_table_entry *p, const char *s)
{
p->hash_next = NULL;
p->symbol = xstrdup (s);
p->ddip = NULL;
p->fip = NULL;
return p;
}
static hash_table_entry *
lookup (hash_table_entry *hash_tab_p, const char *search_symbol)
{
int hash_value = 0;
const char *search_symbol_char_p = search_symbol;
hash_table_entry *p;
while (*search_symbol_char_p)
hash_value += *search_symbol_char_p++;
hash_value &= hash_mask;
p = &hash_tab_p[hash_value];
if (! p->symbol)
return add_symbol (p, search_symbol);
if (!strcmp (p->symbol, search_symbol))
return p;
while (p->hash_next)
{
p = p->hash_next;
if (!strcmp (p->symbol, search_symbol))
return p;
}
p->hash_next = xmalloc (sizeof (hash_table_entry));
p = p->hash_next;
return add_symbol (p, search_symbol);
}
static void
free_def_dec (def_dec_info *p)
{
free ((NONCONST void *) p->ansi_decl);
#ifndef UNPROTOIZE
{
const f_list_chain_item * curr;
const f_list_chain_item * next;
for (curr = p->f_list_chain; curr; curr = next)
{
next = curr->chain_next;
free ((NONCONST void *) curr);
}
}
#endif
free (p);
}
static char *
unexpand_if_needed (const char *aux_info_line)
{
static char *line_buf = 0;
static int line_buf_size = 0;
const unexpansion *unexp_p;
int got_unexpanded = 0;
const char *s;
char *copy_p = line_buf;
if (line_buf == 0)
{
line_buf_size = 1024;
line_buf = xmalloc (line_buf_size);
}
copy_p = line_buf;
for (s = aux_info_line; *s != '\n'; )
{
for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
{
const char *in_p = unexp_p->expanded;
size_t len = strlen (in_p);
if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
{
int size = strlen (unexp_p->contracted);
got_unexpanded = 1;
if (copy_p + size - line_buf >= line_buf_size)
{
int offset = copy_p - line_buf;
line_buf_size *= 2;
line_buf_size += size;
line_buf = xrealloc (line_buf, line_buf_size);
copy_p = line_buf + offset;
}
strcpy (copy_p, unexp_p->contracted);
copy_p += size;
s += len;
goto continue_outer;
}
}
if (copy_p - line_buf == line_buf_size)
{
int offset = copy_p - line_buf;
line_buf_size *= 2;
line_buf = xrealloc (line_buf, line_buf_size);
copy_p = line_buf + offset;
}
*copy_p++ = *s++;
continue_outer: ;
}
if (copy_p + 2 - line_buf >= line_buf_size)
{
int offset = copy_p - line_buf;
line_buf_size *= 2;
line_buf = xrealloc (line_buf, line_buf_size);
copy_p = line_buf + offset;
}
*copy_p++ = '\n';
*copy_p = '\0';
return (got_unexpanded ? savestring (line_buf, copy_p - line_buf) : 0);
}
static char *
abspath (const char *cwd, const char *rel_filename)
{
const char *const cwd2 = (cwd) ? cwd : cwd_buffer;
char *const abs_buffer = alloca (strlen (cwd2) + strlen (rel_filename) + 2);
char *endp = abs_buffer;
char *outp, *inp;
{
const char *src_p;
if (! IS_ABSOLUTE_PATH (rel_filename))
{
src_p = cwd2;
while ((*endp++ = *src_p++))
continue;
*(endp-1) = DIR_SEPARATOR;
}
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
else if (IS_DIR_SEPARATOR (rel_filename[0]))
{
*endp++ = cwd2[0];
*endp++ = cwd2[1];
}
#endif
src_p = rel_filename;
while ((*endp++ = *src_p++))
continue;
}
outp = inp = abs_buffer;
*outp++ = *inp++;
#if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
if (IS_DIR_SEPARATOR (inp[0]))
*outp++ = *inp++;
#endif
for (;;)
{
if (!inp[0])
break;
else if (IS_DIR_SEPARATOR (inp[0]) && IS_DIR_SEPARATOR (outp[-1]))
{
inp++;
continue;
}
else if (inp[0] == '.' && IS_DIR_SEPARATOR (outp[-1]))
{
if (!inp[1])
break;
else if (IS_DIR_SEPARATOR (inp[1]))
{
inp += 2;
continue;
}
else if ((inp[1] == '.') && (inp[2] == 0
|| IS_DIR_SEPARATOR (inp[2])))
{
inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2;
outp -= 2;
while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*outp))
outp--;
if (outp < abs_buffer)
{
notice ("%s: invalid file name: %s\n",
pname, rel_filename);
exit (FATAL_EXIT_CODE);
}
*++outp = '\0';
continue;
}
}
*outp++ = *inp++;
}
*outp = '\0';
if (IS_DIR_SEPARATOR (outp[-1]))
*--outp = '\0';
return savestring (abs_buffer, outp - abs_buffer);
}
static const char *
shortpath (const char *cwd, const char *filename)
{
char *rel_buffer;
char *rel_buf_p;
char *cwd_p = cwd_buffer;
char *path_p;
int unmatched_slash_count = 0;
size_t filename_len = strlen (filename);
path_p = abspath (cwd, filename);
rel_buf_p = rel_buffer = xmalloc (filename_len);
while (*cwd_p && IS_SAME_PATH_CHAR (*cwd_p, *path_p))
{
cwd_p++;
path_p++;
}
if (!*cwd_p && (!*path_p || IS_DIR_SEPARATOR (*path_p)))
{
if (!*path_p)
return ".";
else
return ++path_p;
}
else
{
if (*path_p)
{
--cwd_p;
--path_p;
while (! IS_DIR_SEPARATOR (*cwd_p))
{
--cwd_p;
--path_p;
}
cwd_p++;
path_p++;
unmatched_slash_count++;
}
while (*cwd_p++)
if (IS_DIR_SEPARATOR (*(cwd_p-1)))
unmatched_slash_count++;
if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
return filename;
while (unmatched_slash_count--)
{
if (rel_buffer + filename_len <= rel_buf_p + 3)
return filename;
*rel_buf_p++ = '.';
*rel_buf_p++ = '.';
*rel_buf_p++ = DIR_SEPARATOR;
}
do
{
if (rel_buffer + filename_len <= rel_buf_p)
return filename;
}
while ((*rel_buf_p++ = *path_p++));
--rel_buf_p;
if (IS_DIR_SEPARATOR (*(rel_buf_p-1)))
*--rel_buf_p = '\0';
return rel_buffer;
}
}
static file_info *
find_file (const char *filename, int do_not_stat)
{
hash_table_entry *hash_entry_p;
hash_entry_p = lookup (filename_primary, filename);
if (hash_entry_p->fip)
return hash_entry_p->fip;
else
{
struct stat stat_buf;
file_info *file_p = xmalloc (sizeof (file_info));
if (do_not_stat)
stat_buf.st_mtime = (time_t) 0;
else
{
if (stat (filename, &stat_buf) == -1)
{
int errno_val = errno;
notice ("%s: %s: can't get status: %s\n",
pname, shortpath (NULL, filename),
xstrerror (errno_val));
stat_buf.st_mtime = (time_t) -1;
}
}
hash_entry_p->fip = file_p;
file_p->hash_entry = hash_entry_p;
file_p->defs_decs = NULL;
file_p->mtime = stat_buf.st_mtime;
return file_p;
}
}
static void
aux_info_corrupted (void)
{
notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
pname, current_aux_info_lineno);
exit (FATAL_EXIT_CODE);
}
static void
check_aux_info (int cond)
{
if (! cond)
aux_info_corrupted ();
}
static const char *
find_corresponding_lparen (const char *p)
{
const char *q;
int paren_depth;
for (paren_depth = 1, q = p-1; paren_depth; q--)
{
switch (*q)
{
case ')':
paren_depth++;
break;
case '(':
paren_depth--;
break;
}
}
return ++q;
}
static int
referenced_file_is_newer (const char *l, time_t aux_info_mtime)
{
const char *p;
file_info *fi_p;
char *filename;
check_aux_info (l[0] == '/');
check_aux_info (l[1] == '*');
check_aux_info (l[2] == ' ');
{
const char *filename_start = p = l + 3;
while (*p != ':'
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
|| (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
#endif
)
p++;
filename = alloca ((size_t) (p - filename_start) + 1);
strncpy (filename, filename_start, (size_t) (p - filename_start));
filename[p-filename_start] = '\0';
}
fi_p = find_file (abspath (invocation_filename, filename), 0);
return (fi_p->mtime > aux_info_mtime);
}
static void
save_def_or_dec (const char *l, int is_syscalls)
{
const char *p;
const char *semicolon_p;
def_dec_info *def_dec_p = xmalloc (sizeof (def_dec_info));
#ifndef UNPROTOIZE
def_dec_p->written = 0;
#endif
check_aux_info (l[0] == '/');
check_aux_info (l[1] == '*');
check_aux_info (l[2] == ' ');
{
const char *filename_start = p = l + 3;
char *filename;
while (*p != ':'
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
|| (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
#endif
)
p++;
filename = alloca ((size_t) (p - filename_start) + 1);
strncpy (filename, filename_start, (size_t) (p - filename_start));
filename[p-filename_start] = '\0';
def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
}
{
const char *line_number_start = ++p;
char line_number[10];
while (*p != ':'
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
|| (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
#endif
)
p++;
strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
line_number[p-line_number_start] = '\0';
def_dec_p->line = atoi (line_number);
}
p++;
check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
def_dec_p->prototyped = (*p == 'N');
#ifndef UNPROTOIZE
def_dec_p->is_implicit = (*p == 'I');
#endif
p++;
check_aux_info ((*p == 'C') || (*p == 'F'));
def_dec_p->is_func_def = ((*p++ == 'F') || is_syscalls);
#ifndef UNPROTOIZE
def_dec_p->definition = 0;
#endif
check_aux_info (*p++ == ' ');
check_aux_info (*p++ == '*');
check_aux_info (*p++ == '/');
check_aux_info (*p++ == ' ');
#ifdef UNPROTOIZE
check_aux_info ((!strncmp (p, "static", 6)) || (!strncmp (p, "extern", 6)));
#else
if (!strncmp (p, "static", 6))
def_dec_p->is_static = -1;
else if (!strncmp (p, "extern", 6))
def_dec_p->is_static = 0;
else
check_aux_info (0);
#endif
{
const char *ansi_start = p;
p += 6;
while (*++p != ';')
continue;
semicolon_p = p;
def_dec_p->ansi_decl
= dupnstr (ansi_start, (size_t) ((semicolon_p+1) - ansi_start));
p--;
#ifndef UNPROTOIZE
def_dec_p->f_list_chain = NULL;
#endif
while (p != ansi_start && (p[-1] == ' ' || p[-1] == '\t')) p--;
if (*p != ')')
{
free_def_dec (def_dec_p);
return;
}
}
def_dec_p->f_list_count = 0;
for (;;)
{
const char *left_paren_p = find_corresponding_lparen (p);
#ifndef UNPROTOIZE
{
f_list_chain_item *cip = xmalloc (sizeof (f_list_chain_item));
cip->formals_list
= dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
cip->chain_next = def_dec_p->f_list_chain;
def_dec_p->f_list_chain = cip;
}
#endif
def_dec_p->f_list_count++;
p = left_paren_p - 2;
if (*p != ')')
break;
else
check_aux_info (*--p == ')');
}
{
const char *past_fn = p + 1;
check_aux_info (*past_fn == ' ');
while (is_id_char (*p))
p--;
p++;
{
char *fn_string = alloca (past_fn - p + 1);
strncpy (fn_string, p, (size_t) (past_fn - p));
fn_string[past_fn-p] = '\0';
def_dec_p->hash_entry = lookup (function_name_primary, fn_string);
}
}
{
const def_dec_info *other;
for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
{
if (def_dec_p->line == other->line && def_dec_p->file == other->file)
{
if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
{
notice ("%s:%d: declaration of function '%s' takes different forms\n",
def_dec_p->file->hash_entry->symbol,
def_dec_p->line,
def_dec_p->hash_entry->symbol);
exit (FATAL_EXIT_CODE);
}
free_def_dec (def_dec_p);
return;
}
}
}
#ifdef UNPROTOIZE
def_dec_p->formal_names = NULL;
def_dec_p->formal_decls = NULL;
if (def_dec_p->is_func_def)
{
p = semicolon_p;
check_aux_info (*++p == ' ');
check_aux_info (*++p == '/');
check_aux_info (*++p == '*');
check_aux_info (*++p == ' ');
check_aux_info (*++p == '(');
{
const char *kr_names_start = ++p;
while (*p++ != ')')
continue;
p--;
def_dec_p->formal_names
= dupnstr (kr_names_start, (size_t) (p - kr_names_start));
}
check_aux_info (*++p == ' ');
p++;
if (*p == '*')
{
check_aux_info (*++p == '/');
def_dec_p->formal_decls = "";
}
else
{
const char *kr_decls_start = p;
while (p[0] != '*' || p[1] != '/')
p++;
p--;
check_aux_info (*p == ' ');
def_dec_p->formal_decls
= dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
}
if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
def_dec_p->prototyped = 1;
}
if (!def_dec_p->prototyped)
{
free_def_dec (def_dec_p);
return;
}
#endif
def_dec_p->next_for_func = def_dec_p->hash_entry->ddip;
def_dec_p->hash_entry->ddip = def_dec_p;
if (!def_dec_p->file->defs_decs)
{
def_dec_p->file->defs_decs = def_dec_p;
def_dec_p->next_in_file = NULL;
}
else
{
int line = def_dec_p->line;
const def_dec_info *prev = NULL;
const def_dec_info *curr = def_dec_p->file->defs_decs;
const def_dec_info *next = curr->next_in_file;
while (next && (line < curr->line))
{
prev = curr;
curr = next;
next = next->next_in_file;
}
if (line >= curr->line)
{
def_dec_p->next_in_file = curr;
if (prev)
((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
else
def_dec_p->file->defs_decs = def_dec_p;
}
else
{
((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
def_dec_p->next_in_file = next;
}
}
}
static void
munge_compile_params (const char *params_list)
{
const char **temp_params
= alloca ((strlen (params_list) + 8) * sizeof (char *));
int param_count = 0;
const char *param;
struct stat st;
temp_params[param_count++] = compiler_file_name;
for (;;)
{
while (ISSPACE ((const unsigned char)*params_list))
params_list++;
if (!*params_list)
break;
param = params_list;
while (*params_list && !ISSPACE ((const unsigned char)*params_list))
params_list++;
if (param[0] != '-')
temp_params[param_count++]
= dupnstr (param, (size_t) (params_list - param));
else
{
switch (param[1])
{
case 'g':
case 'O':
case 'S':
case 'c':
break;
case 'o':
while (ISSPACE ((const unsigned char)*params_list))
params_list++;
while (*params_list
&& !ISSPACE ((const unsigned char)*params_list))
params_list++;
break;
default:
temp_params[param_count++]
= dupnstr (param, (size_t) (params_list - param));
}
}
if (!*params_list)
break;
}
temp_params[param_count++] = "-aux-info";
aux_info_file_name_index = param_count;
temp_params[param_count++] = NULL;
temp_params[param_count++] = "-S";
temp_params[param_count++] = "-o";
if ((stat (HOST_BIT_BUCKET, &st) == 0)
&& (!S_ISDIR (st.st_mode))
&& (access (HOST_BIT_BUCKET, W_OK) == 0))
temp_params[param_count++] = HOST_BIT_BUCKET;
else
temp_params[param_count++] = "/dev/null";
input_file_name_index = param_count;
temp_params[param_count++] = NULL;
temp_params[param_count++] = NULL;
compile_params = xmalloc (sizeof (char *) * (param_count+1));
memcpy (compile_params, temp_params, sizeof (char *) * param_count);
}
static int
gen_aux_info_file (const char *base_filename)
{
if (!input_file_name_index)
munge_compile_params ("");
compile_params[input_file_name_index] = shortpath (NULL, base_filename);
compile_params[aux_info_file_name_index] =
concat (compile_params[input_file_name_index], aux_info_suffix, NULL);
if (!quiet_flag)
notice ("%s: compiling '%s'\n",
pname, compile_params[input_file_name_index]);
{
char *errmsg_fmt, *errmsg_arg;
int wait_status, pid;
pid = pexecute (compile_params[0], (char * const *) compile_params,
pname, NULL, &errmsg_fmt, &errmsg_arg,
PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
if (pid == -1)
{
int errno_val = errno;
fprintf (stderr, "%s: ", pname);
fprintf (stderr, errmsg_fmt, errmsg_arg);
fprintf (stderr, ": %s\n", xstrerror (errno_val));
return 0;
}
pid = pwait (pid, &wait_status, 0);
if (pid == -1)
{
notice ("%s: wait: %s\n", pname, xstrerror (errno));
return 0;
}
if (WIFSIGNALED (wait_status))
{
notice ("%s: subprocess got fatal signal %d\n",
pname, WTERMSIG (wait_status));
return 0;
}
if (WIFEXITED (wait_status))
{
if (WEXITSTATUS (wait_status) != 0)
{
notice ("%s: %s exited with status %d\n",
pname, compile_params[0], WEXITSTATUS (wait_status));
return 0;
}
return 1;
}
gcc_unreachable ();
}
}
static void
process_aux_info_file (const char *base_source_filename, int keep_it,
int is_syscalls)
{
size_t base_len = strlen (base_source_filename);
char * aux_info_filename = alloca (base_len + strlen (aux_info_suffix) + 1);
char *aux_info_base;
char *aux_info_limit;
char *aux_info_relocated_name;
const char *aux_info_second_line;
time_t aux_info_mtime;
size_t aux_info_size;
int must_create;
strcpy (aux_info_filename, base_source_filename);
strcat (aux_info_filename, aux_info_suffix);
must_create = 0;
start_over: ;
if (access (aux_info_filename, R_OK) == -1)
{
if (errno == ENOENT)
{
if (is_syscalls)
{
notice ("%s: warning: missing SYSCALLS file '%s'\n",
pname, aux_info_filename);
return;
}
must_create = 1;
}
else
{
int errno_val = errno;
notice ("%s: can't read aux info file '%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
errors++;
return;
}
}
#if 0
else
{
struct stat s1, s2;
stat (aux_info_file_name, &s1);
stat (base_source_file_name, &s2);
if (s2.st_mtime > s1.st_mtime)
must_create = 1;
}
#endif
if (must_create)
{
if (!gen_aux_info_file (base_source_filename))
{
errors++;
return;
}
if (access (aux_info_filename, R_OK) == -1)
{
int errno_val = errno;
notice ("%s: can't read aux info file '%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
errors++;
return;
}
}
{
struct stat stat_buf;
if (stat (aux_info_filename, &stat_buf) == -1)
{
int errno_val = errno;
notice ("%s: can't get status of aux info file '%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
errors++;
return;
}
if ((aux_info_size = stat_buf.st_size) == 0)
return;
aux_info_mtime = stat_buf.st_mtime;
if (!is_syscalls)
{
if (stat (base_source_filename, &stat_buf) == -1)
{
int errno_val = errno;
notice ("%s: can't get status of aux info file '%s': %s\n",
pname, shortpath (NULL, base_source_filename),
xstrerror (errno_val));
errors++;
return;
}
if (stat_buf.st_mtime > aux_info_mtime)
{
must_create = 1;
goto start_over;
}
}
}
{
int aux_info_file;
int fd_flags;
fd_flags = O_RDONLY;
#ifdef O_BINARY
fd_flags |= O_BINARY;
#endif
if ((aux_info_file = open (aux_info_filename, fd_flags, 0444 )) == -1)
{
int errno_val = errno;
notice ("%s: can't open aux info file '%s' for reading: %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
return;
}
aux_info_base = xmalloc (aux_info_size + 1);
aux_info_limit = aux_info_base + aux_info_size;
*aux_info_limit = '\0';
if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
(int) aux_info_size)
{
int errno_val = errno;
notice ("%s: error reading aux info file '%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
free (aux_info_base);
close (aux_info_file);
return;
}
if (close (aux_info_file))
{
int errno_val = errno;
notice ("%s: error closing aux info file '%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
free (aux_info_base);
close (aux_info_file);
return;
}
}
if (must_create && !keep_it)
if (unlink (aux_info_filename) == -1)
{
int errno_val = errno;
notice ("%s: can't delete aux info file '%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
}
{
char *p = aux_info_base;
while (*p != ':'
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
|| (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
#endif
)
p++;
p++;
while (*p == ' ')
p++;
invocation_filename = p;
while (*p != ' ')
p++;
*p++ = DIR_SEPARATOR;
*p++ = '\0';
while (*p++ != '\n')
continue;
aux_info_second_line = p;
aux_info_relocated_name = 0;
if (! IS_ABSOLUTE_PATH (invocation_filename))
{
char *dir_end;
aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename));
strcpy (aux_info_relocated_name, base_source_filename);
dir_end = strrchr (aux_info_relocated_name, DIR_SEPARATOR);
#ifdef DIR_SEPARATOR_2
{
char *slash;
slash = strrchr (dir_end ? dir_end : aux_info_relocated_name,
DIR_SEPARATOR_2);
if (slash)
dir_end = slash;
}
#endif
if (dir_end)
dir_end++;
else
dir_end = aux_info_relocated_name;
strcpy (dir_end, invocation_filename);
invocation_filename = aux_info_relocated_name;
}
}
{
const char *aux_info_p;
if (!is_syscalls)
{
current_aux_info_lineno = 2;
for (aux_info_p = aux_info_second_line; *aux_info_p; )
{
if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
{
free (aux_info_base);
free (aux_info_relocated_name);
if (keep_it && unlink (aux_info_filename) == -1)
{
int errno_val = errno;
notice ("%s: can't delete file '%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
return;
}
must_create = 1;
goto start_over;
}
while (*aux_info_p != '\n')
aux_info_p++;
aux_info_p++;
current_aux_info_lineno++;
}
}
current_aux_info_lineno = 2;
for (aux_info_p = aux_info_second_line; *aux_info_p;)
{
char *unexpanded_line = unexpand_if_needed (aux_info_p);
if (unexpanded_line)
{
save_def_or_dec (unexpanded_line, is_syscalls);
free (unexpanded_line);
}
else
save_def_or_dec (aux_info_p, is_syscalls);
while (*aux_info_p != '\n')
aux_info_p++;
aux_info_p++;
current_aux_info_lineno++;
}
}
free (aux_info_base);
free (aux_info_relocated_name);
}
#ifndef UNPROTOIZE
static void
rename_c_file (const hash_table_entry *hp)
{
const char *filename = hp->symbol;
int last_char_index = strlen (filename) - 1;
char *const new_filename = alloca (strlen (filename)
+ strlen (cplus_suffix) + 1);
if (filename[last_char_index] != 'c' || filename[last_char_index-1] != '.'
|| IS_SAME_PATH (syscalls_absolute_filename, filename))
return;
strcpy (new_filename, filename);
strcpy (&new_filename[last_char_index], cplus_suffix);
if (rename (filename, new_filename) == -1)
{
int errno_val = errno;
notice ("%s: warning: can't rename file '%s' to '%s': %s\n",
pname, shortpath (NULL, filename),
shortpath (NULL, new_filename), xstrerror (errno_val));
errors++;
return;
}
}
#endif
static void
reverse_def_dec_list (const hash_table_entry *hp)
{
file_info *file_p = hp->fip;
def_dec_info *prev = NULL;
def_dec_info *current = (def_dec_info *) file_p->defs_decs;
if (!current)
return;
prev = current;
if (! (current = (def_dec_info *) current->next_in_file))
return;
prev->next_in_file = NULL;
while (current)
{
def_dec_info *next = (def_dec_info *) current->next_in_file;
current->next_in_file = prev;
prev = current;
current = next;
}
file_p->defs_decs = prev;
}
#ifndef UNPROTOIZE
static const def_dec_info *
find_extern_def (const def_dec_info *head, const def_dec_info *user)
{
const def_dec_info *dd_p;
const def_dec_info *extern_def_p = NULL;
int conflict_noted = 0;
for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
if (dd_p->is_func_def && !dd_p->is_static && dd_p->file == user->file)
return dd_p;
for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
if (dd_p->is_func_def && !dd_p->is_static)
{
if (!extern_def_p)
extern_def_p = dd_p;
else
{
if (is_syscalls_file (dd_p->file))
continue;
if (is_syscalls_file (extern_def_p->file))
{
extern_def_p = dd_p;
continue;
}
if (!conflict_noted)
{
conflict_noted = 1;
notice ("%s: conflicting extern definitions of '%s'\n",
pname, head->hash_entry->symbol);
if (!quiet_flag)
{
notice ("%s: declarations of '%s' will not be converted\n",
pname, head->hash_entry->symbol);
notice ("%s: conflict list for '%s' follows:\n",
pname, head->hash_entry->symbol);
fprintf (stderr, "%s: %s(%d): %s\n",
pname,
shortpath (NULL, extern_def_p->file->hash_entry->symbol),
extern_def_p->line, extern_def_p->ansi_decl);
}
}
if (!quiet_flag)
fprintf (stderr, "%s: %s(%d): %s\n",
pname,
shortpath (NULL, dd_p->file->hash_entry->symbol),
dd_p->line, dd_p->ansi_decl);
}
}
if (conflict_noted)
return NULL;
if (!extern_def_p)
{
for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
{
extern_def_p = dd_p;
if (!quiet_flag)
notice ("%s: warning: using formals list from %s(%d) for function '%s'\n",
pname,
shortpath (NULL, dd_p->file->hash_entry->symbol),
dd_p->line, dd_p->hash_entry->symbol);
break;
}
if (!extern_def_p)
{
const char *file = user->file->hash_entry->symbol;
if (!quiet_flag)
if (in_system_include_dir (file))
{
char *needed = alloca (strlen (user->ansi_decl) + 1);
char *p;
strcpy (needed, user->ansi_decl);
p = strstr (needed, user->hash_entry->symbol)
+ strlen (user->hash_entry->symbol) + 2;
*p++ = '?';
*p++ = '?';
*p++ = '?';
strcpy (p, ");");
notice ("%s: %d: '%s' used but missing from SYSCALLS\n",
shortpath (NULL, file), user->line,
needed+7);
}
#if 0
else
notice ("%s: %d: warning: no extern definition for '%s'\n",
shortpath (NULL, file), user->line,
user->hash_entry->symbol);
#endif
}
}
return extern_def_p;
}
static const def_dec_info *
find_static_definition (const def_dec_info *user)
{
const def_dec_info *head = user->hash_entry->ddip;
const def_dec_info *dd_p;
int num_static_defs = 0;
const def_dec_info *static_def_p = NULL;
for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
{
static_def_p = dd_p;
num_static_defs++;
}
if (num_static_defs == 0)
{
if (!quiet_flag)
notice ("%s: warning: no static definition for '%s' in file '%s'\n",
pname, head->hash_entry->symbol,
shortpath (NULL, user->file->hash_entry->symbol));
}
else if (num_static_defs > 1)
{
notice ("%s: multiple static defs of '%s' in file '%s'\n",
pname, head->hash_entry->symbol,
shortpath (NULL, user->file->hash_entry->symbol));
return NULL;
}
return static_def_p;
}
static void
connect_defs_and_decs (const hash_table_entry *hp)
{
const def_dec_info *dd_p;
const def_dec_info *extern_def_p = NULL;
int first_extern_reference = 1;
for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
if (dd_p->prototyped)
((NONCONST def_dec_info *) dd_p)->definition = dd_p;
for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
{
if (first_extern_reference)
{
extern_def_p = find_extern_def (hp->ddip, dd_p);
first_extern_reference = 0;
}
((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
}
for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
{
const def_dec_info *dd_p2;
const def_dec_info *static_def;
((NONCONST def_dec_info *) dd_p)->definition =
(static_def = find_static_definition (dd_p))
? static_def
: (const def_dec_info *) -1;
for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
if (!dd_p2->is_func_def && dd_p2->is_static
&& !dd_p2->definition && (dd_p2->file == dd_p->file))
((NONCONST def_dec_info *) dd_p2)->definition = dd_p->definition;
}
for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
if (dd_p->definition == (def_dec_info *) -1)
((NONCONST def_dec_info *) dd_p)->definition = NULL;
}
#endif
static int
identify_lineno (const char *clean_p)
{
int line_num = 1;
const char *scan_p;
for (scan_p = clean_text_base; scan_p <= clean_p; scan_p++)
if (*scan_p == '\n')
line_num++;
return line_num;
}
static void
declare_source_confusing (const char *clean_p)
{
if (!quiet_flag)
{
if (clean_p == 0)
notice ("%s: %d: warning: source too confusing\n",
shortpath (NULL, convert_filename), last_known_line_number);
else
notice ("%s: %d: warning: source too confusing\n",
shortpath (NULL, convert_filename),
identify_lineno (clean_p));
}
longjmp (source_confusion_recovery, 1);
}
static void
check_source (int cond, const char *clean_p)
{
if (!cond)
declare_source_confusing (clean_p);
}
static const char *
seek_to_line (int n)
{
gcc_assert (n >= last_known_line_number);
while (n > last_known_line_number)
{
while (*last_known_line_start != '\n')
check_source (++last_known_line_start < clean_text_limit, 0);
last_known_line_start++;
last_known_line_number++;
}
return last_known_line_start;
}
static const char *
forward_to_next_token_char (const char *ptr)
{
for (++ptr; ISSPACE ((const unsigned char)*ptr);
check_source (++ptr < clean_text_limit, 0))
continue;
return ptr;
}
static void
output_bytes (const char *str, size_t len)
{
if ((repl_write_ptr + 1) + len >= repl_text_limit)
{
size_t new_size = (repl_text_limit - repl_text_base) << 1;
char *new_buf = xrealloc (repl_text_base, new_size);
repl_write_ptr = new_buf + (repl_write_ptr - repl_text_base);
repl_text_base = new_buf;
repl_text_limit = new_buf + new_size;
}
memcpy (repl_write_ptr + 1, str, len);
repl_write_ptr += len;
}
static void
output_string (const char *str)
{
output_bytes (str, strlen (str));
}
static void
output_up_to (const char *p)
{
size_t copy_length = (size_t) (p - clean_read_ptr);
const char *copy_start = orig_text_base+(clean_read_ptr-clean_text_base)+1;
if (copy_length == 0)
return;
output_bytes (copy_start, copy_length);
clean_read_ptr = p;
}
static int
other_variable_style_function (const char *ansi_header)
{
#ifdef UNPROTOIZE
return strstr (ansi_header, "...") != 0;
#else
const char *p;
int len = strlen (varargs_style_indicator);
for (p = ansi_header; p; )
{
const char *candidate;
if ((candidate = strstr (p, varargs_style_indicator)) == 0)
return 0;
else
if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
return 1;
else
p = candidate + 1;
}
return 0;
#endif
}
static void
edit_fn_declaration (const def_dec_info *def_dec_p,
const char *volatile clean_text_p)
{
const char *start_formals;
const char *end_formals;
const char *function_to_edit = def_dec_p->hash_entry->symbol;
size_t func_name_len = strlen (function_to_edit);
const char *end_of_fn_name;
#ifndef UNPROTOIZE
const f_list_chain_item *this_f_list_chain_item;
const def_dec_info *definition = def_dec_p->definition;
if (!definition)
return;
if (other_variable_style_function (definition->ansi_decl))
{
if (!quiet_flag)
notice ("%s: %d: warning: varargs function declaration not converted\n",
shortpath (NULL, def_dec_p->file->hash_entry->symbol),
def_dec_p->line);
return;
}
#endif
save_pointers ();
if (setjmp (source_confusion_recovery))
{
restore_pointers ();
notice ("%s: declaration of function '%s' not converted\n",
pname, function_to_edit);
return;
}
while (*clean_text_p != '\n')
check_source (++clean_text_p < clean_text_limit, 0);
clean_text_p--;
do
{
for (;;)
{
while (!is_id_char (*clean_text_p))
check_source (--clean_text_p > clean_read_ptr, 0);
while (is_id_char (*clean_text_p))
check_source (--clean_text_p > clean_read_ptr, 0);
if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
{
char ch = *(clean_text_p + 1 + func_name_len);
if (! is_id_char (ch))
break;
}
}
end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
start_formals = forward_to_next_token_char (end_of_fn_name);
}
while (*start_formals != '(');
#ifndef UNPROTOIZE
this_f_list_chain_item = definition->f_list_chain;
#endif
for (;;)
{
{
int depth;
end_formals = start_formals + 1;
depth = 1;
for (; depth; check_source (++end_formals < clean_text_limit, 0))
{
switch (*end_formals)
{
case '(':
depth++;
break;
case ')':
depth--;
break;
}
}
end_formals--;
}
output_up_to (start_formals);
#ifndef UNPROTOIZE
if (this_f_list_chain_item)
{
output_string (this_f_list_chain_item->formals_list);
this_f_list_chain_item = this_f_list_chain_item->chain_next;
}
else
{
if (!quiet_flag)
notice ("%s: warning: too many parameter lists in declaration of '%s'\n",
pname, def_dec_p->hash_entry->symbol);
check_source (0, end_formals);
}
#endif
clean_read_ptr = end_formals - 1;
{
const char *another_r_paren = forward_to_next_token_char (end_formals);
if ((*another_r_paren != ')')
|| (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
{
#ifndef UNPROTOIZE
if (this_f_list_chain_item)
{
if (!quiet_flag)
notice ("\n%s: warning: too few parameter lists in declaration of '%s'\n",
pname, def_dec_p->hash_entry->symbol);
check_source (0, start_formals);
}
#endif
break;
}
}
}
}
static int
edit_formals_lists (const char *end_formals, unsigned int f_list_count,
const def_dec_info *def_dec_p)
{
const char *start_formals;
int depth;
start_formals = end_formals - 1;
depth = 1;
for (; depth; check_source (--start_formals > clean_read_ptr, 0))
{
switch (*start_formals)
{
case '(':
depth--;
break;
case ')':
depth++;
break;
}
}
start_formals++;
f_list_count--;
if (f_list_count)
{
const char *next_end;
next_end = start_formals - 1;
check_source (next_end > clean_read_ptr, 0);
while (ISSPACE ((const unsigned char)*next_end))
check_source (--next_end > clean_read_ptr, 0);
check_source (*next_end == ')', next_end);
check_source (--next_end > clean_read_ptr, 0);
check_source (*next_end == ')', next_end);
if (edit_formals_lists (next_end, f_list_count, def_dec_p))
return 1;
}
if (f_list_count == 0)
{
const char *expected = def_dec_p->hash_entry->symbol;
const char *func_name_start;
const char *func_name_limit;
size_t func_name_len;
for (func_name_limit = start_formals-1;
ISSPACE ((const unsigned char)*func_name_limit); )
check_source (--func_name_limit > clean_read_ptr, 0);
for (func_name_start = func_name_limit++;
is_id_char (*func_name_start);
func_name_start--)
check_source (func_name_start > clean_read_ptr, 0);
func_name_start++;
func_name_len = func_name_limit - func_name_start;
if (func_name_len == 0)
check_source (0, func_name_start);
if (func_name_len != strlen (expected)
|| strncmp (func_name_start, expected, func_name_len))
{
notice ("%s: %d: warning: found '%s' but expected '%s'\n",
shortpath (NULL, def_dec_p->file->hash_entry->symbol),
identify_lineno (func_name_start),
dupnstr (func_name_start, func_name_len),
expected);
return 1;
}
}
output_up_to (start_formals);
#ifdef UNPROTOIZE
if (f_list_count == 0)
output_string (def_dec_p->formal_names);
#else
{
unsigned f_list_depth;
const f_list_chain_item *flci_p = def_dec_p->f_list_chain;
for (f_list_depth = 0; f_list_depth < f_list_count; f_list_depth++)
flci_p = flci_p->chain_next;
output_string (flci_p->formals_list);
}
#endif
clean_read_ptr = end_formals - 1;
return 0;
}
static const char *
find_rightmost_formals_list (const char *clean_text_p)
{
const char *end_formals;
for (end_formals = clean_text_p; *end_formals != '\n'; end_formals++)
continue;
end_formals--;
#ifdef UNPROTOIZE
{
char ch;
const char *l_brace_p;
while (*end_formals != ')')
{
if (ISSPACE ((unsigned char)*end_formals))
while (ISSPACE ((unsigned char)*end_formals))
check_source (--end_formals > clean_read_ptr, 0);
else
check_source (--end_formals > clean_read_ptr, 0);
}
ch = *(l_brace_p = forward_to_next_token_char (end_formals));
check_source (ch == '{', l_brace_p);
}
#else
while (1)
{
char ch;
const char *l_brace_p;
while (*end_formals != ')')
{
if (ISSPACE ((const unsigned char)*end_formals))
while (ISSPACE ((const unsigned char)*end_formals))
check_source (--end_formals > clean_read_ptr, 0);
else
check_source (--end_formals > clean_read_ptr, 0);
}
ch = *(l_brace_p = forward_to_next_token_char (end_formals));
if ((ch == '{') || ISALPHA ((unsigned char) ch))
break;
check_source (--end_formals > clean_read_ptr, 0);
}
#endif
return end_formals;
}
#ifndef UNPROTOIZE
static void
add_local_decl (const def_dec_info *def_dec_p, const char *clean_text_p)
{
const char *start_of_block;
const char *function_to_edit = def_dec_p->hash_entry->symbol;
if (!local_flag)
return;
save_pointers ();
if (setjmp (source_confusion_recovery))
{
restore_pointers ();
notice ("%s: local declaration for function '%s' not inserted\n",
pname, function_to_edit);
return;
}
start_of_block = clean_text_p;
while (*start_of_block != '{' && *start_of_block != '\n')
check_source (++start_of_block < clean_text_limit, 0);
if (*start_of_block != '{')
{
if (!quiet_flag)
notice ("\n%s: %d: warning: can't add declaration of '%s' into macro call\n",
def_dec_p->file->hash_entry->symbol, def_dec_p->line,
def_dec_p->hash_entry->symbol);
return;
}
{
const char *ep = forward_to_next_token_char (start_of_block) - 1;
const char *sp;
for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--)
continue;
output_up_to (ep);
{
const char *decl = def_dec_p->definition->ansi_decl;
if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
decl += 7;
output_string (decl);
}
output_bytes (sp, (size_t) (ep - sp) + 1);
}
}
static void
add_global_decls (const file_info *file_p, const char *clean_text_p)
{
const def_dec_info *dd_p;
const char *scan_p;
save_pointers ();
if (setjmp (source_confusion_recovery))
{
restore_pointers ();
notice ("%s: global declarations for file '%s' not inserted\n",
pname, shortpath (NULL, file_p->hash_entry->symbol));
return;
}
scan_p = find_rightmost_formals_list (clean_text_p);
for (;; --scan_p)
{
if (scan_p < clean_text_base)
break;
check_source (scan_p > clean_read_ptr, 0);
if (*scan_p == ';')
break;
}
scan_p++;
while (ISSPACE ((const unsigned char)*scan_p))
scan_p++;
scan_p--;
output_up_to (scan_p);
{
int some_decls_added = 0;
for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
{
const char *decl = dd_p->definition->ansi_decl;
if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
decl += 7;
output_string ("\n");
output_string (decl);
some_decls_added = 1;
((NONCONST def_dec_info *) dd_p->definition)->written = 1;
}
if (some_decls_added)
output_string ("\n\n");
}
for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
if (dd_p->definition)
((NONCONST def_dec_info *) dd_p->definition)->written = 0;
}
#endif
static void
edit_fn_definition (const def_dec_info *def_dec_p,
const char *volatile clean_text_p)
{
const char *end_formals;
const char *function_to_edit = def_dec_p->hash_entry->symbol;
save_pointers ();
if (setjmp (source_confusion_recovery))
{
restore_pointers ();
notice ("%s: definition of function '%s' not converted\n",
pname, function_to_edit);
return;
}
end_formals = find_rightmost_formals_list (clean_text_p);
if (other_variable_style_function (def_dec_p->ansi_decl))
{
if (!quiet_flag)
notice ("%s: %d: warning: definition of %s not converted\n",
shortpath (NULL, def_dec_p->file->hash_entry->symbol),
identify_lineno (end_formals),
other_var_style);
output_up_to (end_formals);
return;
}
if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
{
restore_pointers ();
notice ("%s: definition of function '%s' not converted\n",
pname, function_to_edit);
return;
}
output_up_to (end_formals);
#ifdef UNPROTOIZE
{
const char *decl_p;
const char *semicolon_p;
const char *limit_p;
const char *scan_p;
int had_newlines = 0;
decl_p = def_dec_p->formal_decls;
limit_p = decl_p + strlen (decl_p);
for (;decl_p < limit_p; decl_p = semicolon_p + 2)
{
for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
continue;
output_string ("\n");
output_string (indent_string);
output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
}
for (scan_p = end_formals+1; *scan_p != '{'; )
{
if (*scan_p == '\n')
{
had_newlines = 1;
break;
}
check_source (++scan_p < clean_text_limit, 0);
}
if (!had_newlines)
output_string ("\n");
}
#else
{
const char *end_formals_orig;
const char *start_body;
const char *start_body_orig;
const char *scan;
const char *scan_orig;
int have_flotsam = 0;
int have_newlines = 0;
for (start_body = end_formals + 1; *start_body != '{';)
check_source (++start_body < clean_text_limit, 0);
end_formals_orig = orig_text_base + (end_formals - clean_text_base);
start_body_orig = orig_text_base + (start_body - clean_text_base);
scan = end_formals + 1;
scan_orig = end_formals_orig + 1;
for (; scan < start_body; scan++, scan_orig++)
{
if (*scan == *scan_orig)
{
have_newlines |= (*scan_orig == '\n');
if (!ISSPACE ((const unsigned char)*scan_orig))
*((NONCONST char *) scan_orig) = ' ';
}
else
have_flotsam = 1;
}
if (have_flotsam)
output_bytes (end_formals_orig + 1,
(size_t) (start_body_orig - end_formals_orig) - 1);
else
if (have_newlines)
output_string ("\n");
else
output_string (" ");
clean_read_ptr = start_body - 1;
}
#endif
}
static void
do_cleaning (char *new_clean_text_base, const char *new_clean_text_limit)
{
char *scan_p;
int non_whitespace_since_newline = 0;
for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
{
switch (*scan_p)
{
case '/':
if (scan_p[1] != '*')
goto regular;
non_whitespace_since_newline = 1;
scan_p[0] = ' ';
scan_p[1] = ' ';
scan_p += 2;
while (scan_p[1] != '/' || scan_p[0] != '*')
{
if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
++scan_p;
gcc_assert (scan_p < new_clean_text_limit);
}
*scan_p++ = ' ';
*scan_p = ' ';
break;
case '#':
if (non_whitespace_since_newline)
goto regular;
*scan_p = ' ';
while (scan_p[1] != '\n' || scan_p[0] == '\\')
{
if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
++scan_p;
gcc_assert (scan_p < new_clean_text_limit);
}
*scan_p++ = ' ';
break;
case '\'':
non_whitespace_since_newline = 1;
while (scan_p[1] != '\'' || scan_p[0] == '\\')
{
if (scan_p[0] == '\\'
&& !ISSPACE ((const unsigned char) scan_p[1]))
scan_p[1] = ' ';
if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
++scan_p;
gcc_assert (scan_p < new_clean_text_limit);
}
*scan_p++ = ' ';
break;
case '"':
non_whitespace_since_newline = 1;
while (scan_p[1] != '"' || scan_p[0] == '\\')
{
if (scan_p[0] == '\\'
&& !ISSPACE ((const unsigned char) scan_p[1]))
scan_p[1] = ' ';
if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
++scan_p;
gcc_assert (scan_p < new_clean_text_limit);
}
if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
scan_p++;
break;
case '\\':
if (scan_p[1] != '\n')
goto regular;
*scan_p = ' ';
break;
case '\n':
non_whitespace_since_newline = 0;
break;
case ' ':
case '\v':
case '\t':
case '\r':
case '\f':
case '\b':
break;
default:
regular:
non_whitespace_since_newline = 1;
break;
}
}
}
static const char *
careful_find_l_paren (const char *p)
{
const char *q;
int paren_depth;
for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
{
switch (*q)
{
case ')':
paren_depth++;
break;
case '(':
paren_depth--;
break;
}
}
return ++q;
}
static void
scan_for_missed_items (const file_info *file_p)
{
static const char *scan_p;
const char *limit = clean_text_limit - 3;
static const char *backup_limit;
backup_limit = clean_text_base - 1;
for (scan_p = clean_text_base; scan_p < limit; scan_p++)
{
if (*scan_p == ')')
{
static const char *last_r_paren;
const char *ahead_p;
last_r_paren = scan_p;
for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
check_source (++ahead_p < limit, limit);
scan_p = ahead_p - 1;
if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
{
const char *last_l_paren;
const int lineno = identify_lineno (ahead_p);
if (setjmp (source_confusion_recovery))
continue;
do
{
last_l_paren = careful_find_l_paren (last_r_paren);
for (last_r_paren = last_l_paren-1;
ISSPACE ((const unsigned char)*last_r_paren); )
check_source (--last_r_paren >= backup_limit, backup_limit);
}
while (*last_r_paren == ')');
if (is_id_char (*last_r_paren))
{
const char *id_limit = last_r_paren + 1;
const char *id_start;
size_t id_length;
const def_dec_info *dd_p;
for (id_start = id_limit-1; is_id_char (*id_start); )
check_source (--id_start >= backup_limit, backup_limit);
id_start++;
backup_limit = id_start;
if ((id_length = (size_t) (id_limit - id_start)) == 0)
goto not_missed;
{
char *func_name = alloca (id_length + 1);
static const char * const stmt_keywords[]
= { "if", "else", "do", "while", "for", "switch", "case", "return", 0 };
const char * const *stmt_keyword;
strncpy (func_name, id_start, id_length);
func_name[id_length] = '\0';
for (stmt_keyword = stmt_keywords; *stmt_keyword; stmt_keyword++)
if (!strcmp (func_name, *stmt_keyword))
goto not_missed;
#if 0
notice ("%s: found definition of '%s' at %s(%d)\n",
pname,
func_name,
shortpath (NULL, file_p->hash_entry->symbol),
identify_lineno (id_start));
#endif
for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
if (dd_p->is_func_def && dd_p->line == lineno)
goto not_missed;
notice ("%s: %d: warning: '%s' excluded by preprocessing\n",
shortpath (NULL, file_p->hash_entry->symbol),
identify_lineno (id_start), func_name);
notice ("%s: function definition not converted\n",
pname);
}
not_missed: ;
}
}
}
}
}
static void
edit_file (const hash_table_entry *hp)
{
struct stat stat_buf;
const file_info *file_p = hp->fip;
char *new_orig_text_base;
char *new_orig_text_limit;
char *new_clean_text_base;
char *new_clean_text_limit;
size_t orig_size;
size_t repl_size;
int first_definition_in_file;
if (!needs_to_be_converted (file_p))
return;
convert_filename = file_p->hash_entry->symbol;
if (!directory_specified_p (convert_filename)
|| file_excluded_p (convert_filename))
{
if (!quiet_flag
#ifdef UNPROTOIZE
&& !in_system_include_dir (convert_filename)
#endif
)
notice ("%s: '%s' not converted\n",
pname, shortpath (NULL, convert_filename));
return;
}
if (nochange_flag)
notice ("%s: would convert file '%s'\n",
pname, shortpath (NULL, convert_filename));
else
notice ("%s: converting file '%s'\n",
pname, shortpath (NULL, convert_filename));
fflush (stderr);
if (stat (convert_filename, &stat_buf) == -1)
{
int errno_val = errno;
notice ("%s: can't get status for file '%s': %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
return;
}
orig_size = stat_buf.st_size;
orig_text_base = new_orig_text_base = xmalloc (orig_size + 2);
orig_text_limit = new_orig_text_limit = new_orig_text_base + orig_size;
clean_text_base = new_clean_text_base = xmalloc (orig_size + 2);
clean_text_limit = new_clean_text_limit = new_clean_text_base + orig_size;
clean_read_ptr = clean_text_base - 1;
repl_size = orig_size + (orig_size >> 2) + 4096;
repl_text_base = xmalloc (repl_size + 2);
repl_text_limit = repl_text_base + repl_size - 1;
repl_write_ptr = repl_text_base - 1;
{
int input_file;
int fd_flags;
fd_flags = O_RDONLY;
#ifdef O_BINARY
fd_flags |= O_BINARY;
#endif
if ((input_file = open (convert_filename, fd_flags, 0444)) == -1)
{
int errno_val = errno;
notice ("%s: can't open file '%s' for reading: %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
return;
}
if (safe_read (input_file, new_orig_text_base, orig_size) !=
(int) orig_size)
{
int errno_val = errno;
close (input_file);
notice ("\n%s: error reading input file '%s': %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
return;
}
close (input_file);
}
if (orig_size == 0 || orig_text_limit[-1] != '\n')
{
*new_orig_text_limit++ = '\n';
orig_text_limit++;
}
memcpy (new_clean_text_base, orig_text_base,
(size_t) (orig_text_limit - orig_text_base));
do_cleaning (new_clean_text_base, new_clean_text_limit);
#if 0
{
int clean_file;
size_t clean_size = orig_text_limit - orig_text_base;
char *const clean_filename = alloca (strlen (convert_filename) + 6 + 1);
strcpy (clean_filename, convert_filename);
strcat (clean_filename, ".clean");
if ((clean_file = creat (clean_filename, 0666)) == -1)
{
int errno_val = errno;
notice ("%s: can't create/open clean file '%s': %s\n",
pname, shortpath (NULL, clean_filename),
xstrerror (errno_val));
return;
}
safe_write (clean_file, new_clean_text_base, clean_size, clean_filename);
close (clean_file);
}
#endif
scan_for_missed_items (file_p);
last_known_line_number = 1;
last_known_line_start = clean_text_base;
{
const def_dec_info *def_dec_p;
first_definition_in_file = 1;
def_dec_p = file_p->defs_decs;
for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
{
const char *clean_text_p = seek_to_line (def_dec_p->line);
#ifndef UNPROTOIZE
if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
{
add_global_decls (def_dec_p->file, clean_text_p);
first_definition_in_file = 0;
}
if (def_dec_p->prototyped
|| (!def_dec_p->is_func_def && !def_dec_p->definition))
continue;
#endif
if (def_dec_p->is_func_def)
edit_fn_definition (def_dec_p, clean_text_p);
else
#ifndef UNPROTOIZE
if (def_dec_p->is_implicit)
add_local_decl (def_dec_p, clean_text_p);
else
#endif
edit_fn_declaration (def_dec_p, clean_text_p);
}
}
output_up_to (clean_text_limit - 1);
if (nochange_flag)
{
free (new_orig_text_base);
free (new_clean_text_base);
free (repl_text_base);
return;
}
if (!nosave_flag)
{
char *new_filename
= xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
strcpy (new_filename, convert_filename);
#ifdef __MSDOS__
new_filename[(strlen (convert_filename) - 1] = '\0';
#endif
strcat (new_filename, save_suffix);
if (access (new_filename, F_OK) == 0)
{
if (!quiet_flag)
notice ("%s: warning: file '%s' already saved in '%s'\n",
pname,
shortpath (NULL, convert_filename),
shortpath (NULL, new_filename));
}
else if (rename (convert_filename, new_filename) == -1)
{
int errno_val = errno;
notice ("%s: can't link file '%s' to '%s': %s\n",
pname,
shortpath (NULL, convert_filename),
shortpath (NULL, new_filename),
xstrerror (errno_val));
return;
}
}
if (unlink (convert_filename) == -1)
{
int errno_val = errno;
if (errno_val != ENOENT)
{
notice ("%s: can't delete file '%s': %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
return;
}
}
{
int output_file;
if ((output_file = creat (convert_filename, 0666)) == -1)
{
int errno_val = errno;
notice ("%s: can't create/open output file '%s': %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
return;
}
#ifdef O_BINARY
setmode (output_file, O_BINARY);
#endif
{
unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
safe_write (output_file, repl_text_base, out_size, convert_filename);
}
close (output_file);
}
free (new_orig_text_base);
free (new_clean_text_base);
free (repl_text_base);
if (chmod (convert_filename, stat_buf.st_mode) == -1)
{
int errno_val = errno;
notice ("%s: can't change mode of file '%s': %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
}
}
static void
do_processing (void)
{
const char * const *base_pp;
const char * const * const end_pps
= &base_source_filenames[n_base_source_files];
#ifndef UNPROTOIZE
int syscalls_len;
#endif
for (base_pp = base_source_filenames; base_pp < end_pps; base_pp++)
process_aux_info_file (*base_pp, keep_flag, 0);
#ifndef UNPROTOIZE
if (nondefault_syscalls_dir)
{
syscalls_absolute_filename
= xmalloc (strlen (nondefault_syscalls_dir) + 1
+ sizeof (syscalls_filename));
strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
}
else
{
GET_ENVIRONMENT (default_syscalls_dir, "GCC_EXEC_PREFIX");
if (!default_syscalls_dir)
{
default_syscalls_dir = standard_exec_prefix;
}
syscalls_absolute_filename
= xmalloc (strlen (default_syscalls_dir) + 0
+ strlen (target_machine) + 1
+ strlen (target_version) + 1
+ sizeof (syscalls_filename));
strcpy (syscalls_absolute_filename, default_syscalls_dir);
strcat (syscalls_absolute_filename, target_machine);
strcat (syscalls_absolute_filename, "/");
strcat (syscalls_absolute_filename, target_version);
strcat (syscalls_absolute_filename, "/");
}
syscalls_len = strlen (syscalls_absolute_filename);
if (! IS_DIR_SEPARATOR (*(syscalls_absolute_filename + syscalls_len - 1)))
{
*(syscalls_absolute_filename + syscalls_len++) = DIR_SEPARATOR;
*(syscalls_absolute_filename + syscalls_len) = '\0';
}
strcat (syscalls_absolute_filename, syscalls_filename);
process_aux_info_file (syscalls_absolute_filename, 1, 1);
#endif
visit_each_hash_node (filename_primary, reverse_def_dec_list);
#ifndef UNPROTOIZE
visit_each_hash_node (function_name_primary, connect_defs_and_decs);
#endif
visit_each_hash_node (filename_primary, edit_file);
#ifndef UNPROTOIZE
if (cplusplus_flag && !nochange_flag)
visit_each_hash_node (filename_primary, rename_c_file);
#endif
}
static const struct option longopts[] =
{
{"version", 0, 0, 'V'},
{"file_name", 0, 0, 'p'},
{"quiet", 0, 0, 'q'},
{"silent", 0, 0, 'q'},
{"force", 0, 0, 'f'},
{"keep", 0, 0, 'k'},
{"nosave", 0, 0, 'N'},
{"nochange", 0, 0, 'n'},
{"compiler-options", 1, 0, 'c'},
{"exclude", 1, 0, 'x'},
{"directory", 1, 0, 'd'},
#ifdef UNPROTOIZE
{"indent", 1, 0, 'i'},
#else
{"local", 0, 0, 'l'},
{"global", 0, 0, 'g'},
{"c++", 0, 0, 'C'},
{"syscalls-dir", 1, 0, 'B'},
#endif
{0, 0, 0, 0}
};
extern int main (int, char **const);
int
main (int argc, char **const argv)
{
int longind;
int c;
const char *params = "";
pname = strrchr (argv[0], DIR_SEPARATOR);
#ifdef DIR_SEPARATOR_2
{
char *slash;
slash = strrchr (pname ? pname : argv[0], DIR_SEPARATOR_2);
if (slash)
pname = slash;
}
#endif
pname = pname ? pname+1 : argv[0];
#ifdef SIGCHLD
signal (SIGCHLD, SIG_DFL);
#endif
unlock_std_streams ();
gcc_init_libintl ();
cwd_buffer = getpwd ();
if (!cwd_buffer)
{
notice ("%s: cannot get working directory: %s\n",
pname, xstrerror(errno));
return (FATAL_EXIT_CODE);
}
directory_list = string_list_cons (cwd_buffer, NULL);
while ((c = getopt_long (argc, argv,
#ifdef UNPROTOIZE
"c:d:i:knNp:qvVx:",
#else
"B:c:Cd:gklnNp:qvVx:",
#endif
longopts, &longind)) != EOF)
{
if (c == 0)
c = longopts[longind].val;
switch (c)
{
case 'p':
compiler_file_name = optarg;
break;
case 'd':
directory_list
= string_list_cons (abspath (NULL, optarg), directory_list);
break;
case 'x':
exclude_list = string_list_cons (optarg, exclude_list);
break;
case 'v':
case 'V':
version_flag = 1;
break;
case 'q':
quiet_flag = 1;
break;
#if 0
case 'f':
force_flag = 1;
break;
#endif
case 'n':
nochange_flag = 1;
keep_flag = 1;
break;
case 'N':
nosave_flag = 1;
break;
case 'k':
keep_flag = 1;
break;
case 'c':
params = optarg;
break;
#ifdef UNPROTOIZE
case 'i':
indent_string = optarg;
break;
#else
case 'l':
local_flag = 1;
break;
case 'g':
global_flag = 1;
break;
case 'C':
cplusplus_flag = 1;
break;
case 'B':
nondefault_syscalls_dir = optarg;
break;
#endif
default:
usage ();
}
}
munge_compile_params (params);
n_base_source_files = argc - optind;
base_source_filenames
= xmalloc ((n_base_source_files + 1) * sizeof (char *));
n_base_source_files = 0;
for (; optind < argc; optind++)
{
const char *path = abspath (NULL, argv[optind]);
int len = strlen (path);
if (path[len-1] == 'c' && path[len-2] == '.')
base_source_filenames[n_base_source_files++] = path;
else
{
notice ("%s: input file names must have .c suffixes: %s\n",
pname, shortpath (NULL, path));
errors++;
}
}
#ifndef UNPROTOIZE
{
const char *cp;
for (cp = varargs_style_indicator; ISIDNUM (*cp); cp++)
continue;
if (*cp != 0)
varargs_style_indicator = savestring (varargs_style_indicator,
cp - varargs_style_indicator);
}
#endif
if (errors)
usage ();
else
{
if (version_flag)
fprintf (stderr, "%s: %s\n", pname, version_string);
do_processing ();
}
return (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
}