| /* Dependency generator utility. |
| Copyright (C) 2004 Free Software Foundation, Inc. |
| Contributed by Zack Weinberg, May 2004 |
| |
| This program is free software; you can redistribute it and/or modify it |
| under the terms of the GNU General Public License as published by the |
| Free Software Foundation; either version 2, or (at your option) any |
| later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| |
| In other words, you are welcome to use, share and improve this program. |
| You are forbidden to forbid anyone else to use, share and improve |
| what you give them. Help stamp out software-hoarding! */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "line-map.h" |
| #include "cpplib.h" |
| #include "getopt.h" |
| #include "mkdeps.h" |
| |
| /* APPLE LOCAL begin CW asm blocks -sshebs */ |
| /* Dummies needed because we use them from cpplib, yuck. */ |
| int flag_iasm_blocks; |
| int iasm_state; |
| int iasm_in_operands; |
| /* APPLE LOCAL end CW asm blocks -sshebs */ |
| |
| const char *progname; |
| const char *vpath; |
| |
| static const char *output_file; |
| static bool had_errors; |
| |
| /* Option lists, to give to cpplib before each input file. */ |
| struct cmd_line_macro |
| { |
| struct cmd_line_macro *next; |
| bool is_undef; |
| const char *macro; |
| }; |
| |
| static struct cmd_line_macro *cmd_line_macros; |
| static cpp_dir *cmd_line_searchpath; |
| |
| static void |
| add_clm (const char *macro, bool is_undef) |
| { |
| struct cmd_line_macro *clm = xmalloc (sizeof (struct cmd_line_macro)); |
| clm->next = cmd_line_macros; |
| clm->is_undef = is_undef; |
| clm->macro = macro; |
| cmd_line_macros = clm; |
| } |
| |
| static void |
| add_dir (char *name, bool sysp) |
| { |
| cpp_dir *dir = xmalloc (sizeof (cpp_dir)); |
| dir->next = cmd_line_searchpath; |
| dir->name = name; |
| dir->sysp = sysp; |
| dir->construct = 0; |
| dir->user_supplied_p = 1; |
| cmd_line_searchpath = dir; |
| } |
| |
| /* Command line processing. */ |
| |
| static void ATTRIBUTE_NORETURN |
| usage (int errcode) |
| { |
| fprintf (stderr, |
| "usage: %s [-vh] [-V vpath] [-Dname[=def]...] [-Uname] [-Idir...] [-o file] sources...\n", |
| progname); |
| exit (errcode); |
| } |
| |
| static int |
| parse_options (int argc, char **argv) |
| { |
| static const struct option longopts[] = { |
| { "--help", no_argument, 0, 'h' }, |
| { 0, 0, 0, 0 } |
| }; |
| |
| for (;;) |
| switch (getopt_long (argc, argv, "hD:U:I:J:o:V:", longopts, 0)) |
| { |
| case 'h': usage (0); |
| case 'D': add_clm (optarg, false); break; |
| case 'U': add_clm (optarg, true); break; |
| case 'I': add_dir (optarg, false); break; |
| case 'J': add_dir (optarg, true); break; |
| case 'o': |
| if (output_file) |
| { |
| fprintf (stderr, "%s: too many output files\n", progname); |
| usage (2); |
| } |
| output_file = optarg; |
| break; |
| case 'V': |
| if (vpath) |
| { |
| fprintf (stderr, "%s: too many vpaths\n", progname); |
| usage (2); |
| } |
| vpath = optarg; |
| break; |
| case '?': |
| usage (2); /* getopt has issued the error message. */ |
| |
| case -1: /* end of options */ |
| if (optind == argc) |
| { |
| fprintf (stderr, "%s: no input files\n", progname); |
| usage (2); |
| } |
| return optind; |
| |
| default: |
| abort (); |
| } |
| } |
| |
| /* Set up cpplib from command line options. */ |
| static cpp_reader * |
| reader_init (struct line_maps *line_table) |
| { |
| cpp_reader *reader; |
| cpp_options *options; |
| |
| linemap_init (line_table); |
| reader = cpp_create_reader (CLK_GNUC89, 0, line_table); |
| |
| /* Ignore warnings and errors (we don't have access to system |
| headers). Request dependency output. */ |
| options = cpp_get_options (reader); |
| options->inhibit_warnings = 1; |
| options->inhibit_errors = 1; |
| options->deps.style = DEPS_USER; |
| |
| /* Further initialization. */ |
| cpp_post_options (reader); |
| cpp_init_iconv (reader); |
| cpp_set_include_chains (reader, cmd_line_searchpath, cmd_line_searchpath, |
| false); |
| if (vpath) |
| { |
| struct deps *deps = cpp_get_deps (reader); |
| deps_add_vpath (deps, vpath); |
| } |
| |
| return reader; |
| } |
| |
| /* Process one input source file. */ |
| static void |
| process_file (const char *file) |
| { |
| struct line_maps line_table; |
| cpp_reader *reader = reader_init (&line_table); |
| |
| if (!cpp_read_main_file (reader, file)) |
| had_errors = true; |
| else |
| { |
| struct cmd_line_macro *clm; |
| |
| cpp_init_builtins (reader, true); |
| for (clm = cmd_line_macros; clm; clm = clm->next) |
| (clm->is_undef ? cpp_undef : cpp_define) (reader, clm->macro); |
| |
| cpp_scan_nooutput (reader); |
| if (cpp_finish (reader, stdout)) |
| had_errors = true; |
| } |
| cpp_destroy (reader); |
| linemap_free (&line_table); |
| } |
| |
| /* Master control. */ |
| |
| int |
| main(int argc, char **argv) |
| { |
| int first_input, i; |
| |
| progname = argv[0]; |
| xmalloc_set_program_name (progname); |
| |
| first_input = parse_options (argc, argv); |
| if (output_file) |
| if (!freopen (output_file, "w", stdout)) |
| { |
| perror (output_file); |
| return 1; |
| } |
| |
| for (i = first_input; i < argc; i++) |
| process_file (argv[i]); |
| |
| return had_errors; |
| } |