#include "config.h"
#include "system.h"
#include "cpplib.h"
#include "intl.h"
struct printer
{
FILE *outf;
const struct line_map *map;
const cpp_token *prev;
const cpp_token *source;
unsigned int line;
unsigned char printed;
};
int main PARAMS ((int, char **));
static void general_init PARAMS ((const char *));
static void do_preprocessing PARAMS ((int, char **));
static void setup_callbacks PARAMS ((void));
static void scan_translation_unit PARAMS ((cpp_reader *));
static void check_multiline_token PARAMS ((const cpp_string *));
static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *));
static void print_line PARAMS ((const struct line_map *, unsigned int,
const char *));
static void maybe_print_line PARAMS ((const struct line_map *, unsigned int));
static void cb_line_change PARAMS ((cpp_reader *, const cpp_token *, int));
static void cb_define PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
static void cb_undef PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
static void cb_include PARAMS ((cpp_reader *, unsigned int,
const unsigned char *, const cpp_token *));
static void cb_ident PARAMS ((cpp_reader *, unsigned int,
const cpp_string *));
static void cb_file_change PARAMS ((cpp_reader *, const struct line_map *));
static void cb_def_pragma PARAMS ((cpp_reader *, unsigned int));
int compiling_objc = 0;
const char *progname;
static cpp_reader *pfile;
static cpp_options *options;
static struct printer print;
int
main (argc, argv)
int argc;
char **argv;
{
general_init (argv[0]);
pfile = cpp_create_reader (CLK_GNUC89);
options = cpp_get_options (pfile);
do_preprocessing (argc, argv);
if (cpp_destroy (pfile))
return FATAL_EXIT_CODE;
return SUCCESS_EXIT_CODE;
}
static void
general_init (argv0)
const char *argv0;
{
progname = argv0 + strlen (argv0);
while (progname != argv0 && ! IS_DIR_SEPARATOR (progname[-1]))
--progname;
xmalloc_set_program_name (progname);
hex_init ();
gcc_init_libintl ();
}
static void
do_preprocessing (argc, argv)
int argc;
char **argv;
{
int argi = 1;
argi += cpp_handle_options (pfile, argc - argi , argv + argi);
if (CPP_FATAL_ERRORS (pfile))
return;
if (argi < argc)
{
cpp_fatal (pfile, "invalid option %s", argv[argi]);
return;
}
cpp_post_options (pfile);
if (CPP_FATAL_ERRORS (pfile))
return;
if (options->help_only)
return;
print.line = (unsigned int) -1;
print.printed = 0;
print.prev = 0;
print.map = 0;
if (options->out_fname[0] == '\0')
print.outf = stdout;
else
{
print.outf = fopen (options->out_fname, "w");
if (print.outf == NULL)
{
cpp_notice_from_errno (pfile, options->out_fname);
return;
}
}
setup_callbacks ();
if (cpp_read_main_file (pfile, options->in_fname, NULL))
{
cpp_finish_options (pfile);
if (options->no_output)
cpp_scan_nooutput (pfile);
else
scan_translation_unit (pfile);
if (options->dump_macros == dump_only)
cpp_forall_identifiers (pfile, dump_macro, NULL);
cpp_finish (pfile);
}
if (print.printed)
putc ('\n', print.outf);
if (ferror (print.outf) || fclose (print.outf))
cpp_notice_from_errno (pfile, options->out_fname);
}
static void
setup_callbacks ()
{
cpp_callbacks *cb = cpp_get_callbacks (pfile);
if (! options->no_output)
{
cb->line_change = cb_line_change;
if (options->lang != CLK_ASM)
{
cb->ident = cb_ident;
cb->def_pragma = cb_def_pragma;
}
if (! options->no_line_commands)
cb->file_change = cb_file_change;
}
if (options->dump_includes)
cb->include = cb_include;
if (options->dump_macros == dump_names
|| options->dump_macros == dump_definitions)
{
cb->define = cb_define;
cb->undef = cb_undef;
}
}
static void
scan_translation_unit (pfile)
cpp_reader *pfile;
{
bool avoid_paste = false;
print.source = NULL;
for (;;)
{
const cpp_token *token = cpp_get_token (pfile);
if (token->type == CPP_PADDING)
{
avoid_paste = true;
if (print.source == NULL
|| (!(print.source->flags & PREV_WHITE)
&& token->val.source == NULL))
print.source = token->val.source;
continue;
}
if (token->type == CPP_EOF)
break;
if (avoid_paste)
{
if (print.source == NULL)
print.source = token;
if (print.source->flags & PREV_WHITE
|| (print.prev && cpp_avoid_paste (pfile, print.prev, token))
|| (print.prev == NULL && token->type == CPP_HASH))
putc (' ', print.outf);
}
else if (token->flags & PREV_WHITE)
putc (' ', print.outf);
avoid_paste = false;
print.source = NULL;
print.prev = token;
cpp_output_token (token, print.outf);
if (token->type == CPP_STRING || token->type == CPP_WSTRING
|| token->type == CPP_COMMENT)
check_multiline_token (&token->val.str);
}
}
static void
check_multiline_token (str)
const cpp_string *str;
{
unsigned int i;
for (i = 0; i < str->len; i++)
if (str->text[i] == '\n')
print.line++;
}
static void
maybe_print_line (map, line)
const struct line_map *map;
unsigned int line;
{
if (print.printed)
{
putc ('\n', print.outf);
print.line++;
print.printed = 0;
}
if (line >= print.line && line < print.line + 8)
{
while (line > print.line)
{
putc ('\n', print.outf);
print.line++;
}
}
else
print_line (map, line, "");
}
static void
print_line (map, line, special_flags)
const struct line_map *map;
unsigned int line;
const char *special_flags;
{
if (print.printed)
putc ('\n', print.outf);
print.printed = 0;
print.line = line;
if (! options->no_line_commands)
{
size_t to_file_len = strlen (map->to_file);
unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
unsigned char *p;
p = cpp_quote_string (to_file_quoted,
(unsigned char *)map->to_file, to_file_len);
*p = '\0';
fprintf (print.outf, "# %u \"%s\"%s",
SOURCE_LINE (map, print.line), to_file_quoted, special_flags);
if (map->sysp == 2)
fputs (" 3 4", print.outf);
else if (map->sysp == 1)
fputs (" 3", print.outf);
putc ('\n', print.outf);
}
}
static void
cb_line_change (pfile, token, parsing_args)
cpp_reader *pfile ATTRIBUTE_UNUSED;
const cpp_token *token;
int parsing_args;
{
if (token->type == CPP_EOF || parsing_args)
return;
maybe_print_line (print.map, token->line);
print.printed = 1;
print.prev = 0;
print.source = 0;
if (token->col > 2)
{
unsigned int spaces = token->col - 2;
while (spaces--)
putc (' ', print.outf);
}
}
static void
cb_ident (pfile, line, str)
cpp_reader *pfile ATTRIBUTE_UNUSED;
unsigned int line;
const cpp_string * str;
{
maybe_print_line (print.map, line);
fprintf (print.outf, "#ident \"%s\"\n", str->text);
print.line++;
}
static void
cb_define (pfile, line, node)
cpp_reader *pfile;
unsigned int line;
cpp_hashnode *node;
{
maybe_print_line (print.map, line);
fputs ("#define ", print.outf);
if (options->dump_macros == dump_definitions)
fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
else
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
print.line++;
}
static void
cb_undef (pfile, line, node)
cpp_reader *pfile ATTRIBUTE_UNUSED;
unsigned int line;
cpp_hashnode *node;
{
maybe_print_line (print.map, line);
fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
print.line++;
}
static void
cb_include (pfile, line, dir, header)
cpp_reader *pfile;
unsigned int line;
const unsigned char *dir;
const cpp_token *header;
{
maybe_print_line (print.map, line);
fprintf (print.outf, "#%s %s\n", dir, cpp_token_as_text (pfile, header));
print.line++;
}
static void
cb_file_change (pfile, map)
cpp_reader *pfile ATTRIBUTE_UNUSED;
const struct line_map *map;
{
const char *flags = "";
if (print.map == NULL)
{
if (!options->preprocessed)
print_line (map, map->from_line, flags);
}
else
{
if (map->reason == LC_ENTER)
maybe_print_line (map - 1, map->from_line - 1);
if (map->reason == LC_ENTER)
flags = " 1";
else if (map->reason == LC_LEAVE)
flags = " 2";
print_line (map, map->from_line, flags);
}
print.map = map;
}
static void
cb_def_pragma (pfile, line)
cpp_reader *pfile;
unsigned int line;
{
maybe_print_line (print.map, line);
fputs ("#pragma ", print.outf);
cpp_output_line (pfile, print.outf);
print.line++;
}
static int
dump_macro (pfile, node, v)
cpp_reader *pfile;
cpp_hashnode *node;
void *v ATTRIBUTE_UNUSED;
{
if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
{
fputs ("#define ", print.outf);
fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
putc ('\n', print.outf);
print.line++;
}
return 1;
}
int c_language = -1;
void warning PARAMS ((char *));
void warning (char *msgid) { printf ("%s\n", msgid); }
int flag_cpp_precomp = 0;