1169695Skan/* Dependency generator utility.
2169695Skan   Copyright (C) 2004 Free Software Foundation, Inc.
3169695Skan   Contributed by Zack Weinberg, May 2004
4169695Skan
5169695SkanThis program is free software; you can redistribute it and/or modify it
6169695Skanunder the terms of the GNU General Public License as published by the
7169695SkanFree Software Foundation; either version 2, or (at your option) any
8169695Skanlater version.
9169695Skan
10169695SkanThis program is distributed in the hope that it will be useful,
11169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of
12169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13169695SkanGNU General Public License for more details.
14169695Skan
15169695SkanYou should have received a copy of the GNU General Public License
16169695Skanalong with this program; if not, write to the Free Software
17169695SkanFoundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18169695Skan
19169695Skan In other words, you are welcome to use, share and improve this program.
20169695Skan You are forbidden to forbid anyone else to use, share and improve
21169695Skan what you give them.   Help stamp out software-hoarding!  */
22169695Skan
23169695Skan#include "config.h"
24169695Skan#include "system.h"
25169695Skan#include "line-map.h"
26169695Skan#include "cpplib.h"
27169695Skan#include "getopt.h"
28169695Skan#include "mkdeps.h"
29169695Skan
30169695Skanconst char *progname;
31169695Skanconst char *vpath;
32169695Skan
33169695Skanstatic const char *output_file;
34169695Skanstatic bool had_errors;
35169695Skan
36169695Skan/* Option lists, to give to cpplib before each input file.  */
37169695Skanstruct cmd_line_macro
38169695Skan{
39169695Skan  struct cmd_line_macro *next;
40169695Skan  bool is_undef;
41169695Skan  const char *macro;
42169695Skan};
43169695Skan
44169695Skanstatic struct cmd_line_macro *cmd_line_macros;
45169695Skanstatic cpp_dir *cmd_line_searchpath;
46169695Skan
47169695Skanstatic void
48169695Skanadd_clm (const char *macro, bool is_undef)
49169695Skan{
50169695Skan  struct cmd_line_macro *clm = XNEW (struct cmd_line_macro);
51169695Skan  clm->next = cmd_line_macros;
52169695Skan  clm->is_undef = is_undef;
53169695Skan  clm->macro = macro;
54169695Skan  cmd_line_macros = clm;
55169695Skan}
56169695Skan
57169695Skanstatic void
58169695Skanadd_dir (char *name, bool sysp)
59169695Skan{
60169695Skan  cpp_dir *dir = XNEW (cpp_dir);
61169695Skan  dir->next = cmd_line_searchpath;
62169695Skan  dir->name = name;
63169695Skan  dir->sysp = sysp;
64169695Skan  dir->construct = 0;
65169695Skan  dir->user_supplied_p = 1;
66169695Skan  cmd_line_searchpath = dir;
67169695Skan}
68169695Skan
69169695Skan/* Command line processing.  */
70169695Skan
71169695Skanstatic void ATTRIBUTE_NORETURN
72169695Skanusage (int errcode)
73169695Skan{
74169695Skan  fprintf (stderr,
75169695Skan"usage: %s [-vh] [-V vpath] [-Dname[=def]...] [-Uname] [-Idir...] [-o file] sources...\n",
76169695Skan	   progname);
77169695Skan  exit (errcode);
78169695Skan}
79169695Skan
80169695Skanstatic int
81169695Skanparse_options (int argc, char **argv)
82169695Skan{
83169695Skan  static const struct option longopts[] = {
84169695Skan    { "--help", no_argument, 0, 'h' },
85169695Skan    { 0, 0, 0, 0 }
86169695Skan  };
87169695Skan
88169695Skan  for (;;)
89169695Skan    switch (getopt_long (argc, argv, "hD:U:I:J:o:V:", longopts, 0))
90169695Skan      {
91169695Skan      case 'h': usage (0);
92169695Skan      case 'D': add_clm (optarg, false); break;
93169695Skan      case 'U': add_clm (optarg, true);  break;
94169695Skan      case 'I': add_dir (optarg, false); break;
95169695Skan      case 'J': add_dir (optarg, true);  break;
96169695Skan      case 'o':
97169695Skan	if (output_file)
98169695Skan	  {
99169695Skan	    fprintf (stderr, "%s: too many output files\n", progname);
100169695Skan	    usage (2);
101169695Skan	  }
102169695Skan	output_file = optarg;
103169695Skan	break;
104169695Skan      case 'V':
105169695Skan	if (vpath)
106169695Skan	  {
107169695Skan	    fprintf (stderr, "%s: too many vpaths\n", progname);
108169695Skan	    usage (2);
109169695Skan	  }
110169695Skan	vpath = optarg;
111169695Skan	break;
112169695Skan      case '?':
113169695Skan	usage (2);  /* getopt has issued the error message.  */
114169695Skan
115169695Skan      case -1: /* end of options */
116169695Skan	if (optind == argc)
117169695Skan	  {
118169695Skan	    fprintf (stderr, "%s: no input files\n", progname);
119169695Skan	    usage (2);
120169695Skan	  }
121169695Skan	return optind;
122169695Skan
123169695Skan      default:
124169695Skan	abort ();
125169695Skan      }
126169695Skan}
127169695Skan
128169695Skan/* Set up cpplib from command line options.  */
129169695Skanstatic cpp_reader *
130169695Skanreader_init (struct line_maps *line_table)
131169695Skan{
132169695Skan  cpp_reader *reader;
133169695Skan  cpp_options *options;
134169695Skan
135169695Skan  linemap_init (line_table);
136169695Skan  reader = cpp_create_reader (CLK_GNUC89, 0, line_table);
137169695Skan
138169695Skan  /* Ignore warnings and errors (we don't have access to system
139169695Skan     headers).  Request dependency output.  */
140169695Skan  options = cpp_get_options (reader);
141169695Skan  options->inhibit_warnings = 1;
142169695Skan  options->inhibit_errors = 1;
143169695Skan  options->deps.style = DEPS_USER;
144169695Skan
145169695Skan  /* Further initialization.  */
146169695Skan  cpp_post_options (reader);
147169695Skan  cpp_init_iconv (reader);
148169695Skan  cpp_set_include_chains (reader, cmd_line_searchpath, cmd_line_searchpath,
149169695Skan			  false);
150169695Skan  if (vpath)
151169695Skan    {
152169695Skan      struct deps *deps = cpp_get_deps (reader);
153169695Skan      deps_add_vpath (deps, vpath);
154169695Skan    }
155169695Skan
156169695Skan  return reader;
157169695Skan}
158169695Skan
159169695Skan/* Process one input source file.  */
160169695Skanstatic void
161169695Skanprocess_file (const char *file)
162169695Skan{
163169695Skan  struct line_maps line_table;
164169695Skan  cpp_reader *reader = reader_init (&line_table);
165169695Skan
166169695Skan  if (!cpp_read_main_file (reader, file))
167169695Skan    had_errors = true;
168169695Skan  else
169169695Skan    {
170169695Skan      struct cmd_line_macro *clm;
171169695Skan
172169695Skan      cpp_init_builtins (reader, true);
173169695Skan      for (clm = cmd_line_macros; clm; clm = clm->next)
174169695Skan	(clm->is_undef ? cpp_undef : cpp_define) (reader, clm->macro);
175169695Skan
176169695Skan      cpp_scan_nooutput (reader);
177169695Skan      if (cpp_finish (reader, stdout))
178169695Skan	had_errors = true;
179169695Skan    }
180169695Skan  cpp_destroy (reader);
181169695Skan  linemap_free (&line_table);
182169695Skan}
183169695Skan
184169695Skan/* Master control.  */
185169695Skan
186169695Skanint
187169695Skanmain(int argc, char **argv)
188169695Skan{
189169695Skan  int first_input, i;
190169695Skan
191169695Skan  progname = argv[0];
192169695Skan  xmalloc_set_program_name (progname);
193169695Skan
194169695Skan  first_input = parse_options (argc, argv);
195169695Skan  if (output_file)
196169695Skan    if (!freopen (output_file, "w", stdout))
197169695Skan      {
198169695Skan	perror (output_file);
199169695Skan	return 1;
200169695Skan      }
201169695Skan
202169695Skan  for (i = first_input; i < argc; i++)
203169695Skan    process_file (argv[i]);
204169695Skan
205169695Skan  return had_errors;
206169695Skan}
207