]> git.saurik.com Git - bison.git/blame - src/files.c
Avoid gcc -Wundef warnings reported by Gerald Pfeifer in
[bison.git] / src / files.c
CommitLineData
82129ef5
PE
1/* Open and close files for Bison.
2
d891bc49 3 Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002, 2003
b85810ae 4 Free Software Foundation, Inc.
54bd0db4 5
ceed8467 6 This file is part of Bison, the GNU Compiler Compiler.
54bd0db4 7
ceed8467
AD
8 Bison is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
54bd0db4 12
ceed8467
AD
13 Bison is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
54bd0db4 17
ceed8467
AD
18 You should have received a copy of the GNU General Public License
19 along with Bison; see the file COPYING. If not, write to the Free
20 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
54bd0db4
RS
22
23
9eceb6c6 24#include "system.h"
6d441fc3
PE
25
26#include <error.h>
27#include <get-errno.h>
053658d5 28#include <quote.h>
6d441fc3
PE
29
30#include "complain.h"
54bd0db4 31#include "files.h"
6d441fc3 32#include "getargs.h"
54bd0db4
RS
33#include "gram.h"
34
ae404801 35/* From basename.c. Almost a lie, as it returns a char *. */
d33cb3ae 36const char *base_name (char const *name);
ae404801 37
54bd0db4 38FILE *finput = NULL;
54bd0db4 39
0dd1580a
RA
40struct obstack pre_prologue_obstack;
41struct obstack post_prologue_obstack;
8c7ebe49 42
b5b61c61
AD
43/* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is
44 tempting, but don't do that: for the time being our handling of the
45 %directive vs --option leaves precedence to the options by deciding
46 that if a %directive sets a variable which is really set (i.e., not
47 NULL), then the %directive is ignored. As a result, %name-prefix,
48 for instance, will not be honored. */
49
b0ce6046 50char *spec_outfile = NULL; /* for -o. */
f0130d39 51char *spec_file_prefix = NULL; /* for -b. */
b5b61c61 52const char *spec_name_prefix = NULL; /* for -p. */
342b8b6e
AD
53char *spec_verbose_file = NULL; /* for --verbose. */
54char *spec_graph_file = NULL; /* for -g. */
55char *spec_defines_file = NULL; /* for --defines. */
ea52d706 56char *parser_file_name = NULL;
54bd0db4 57
6d441fc3
PE
58uniqstr grammar_file = NULL;
59uniqstr current_file = NULL;
4a120d45 60
ae404801 61static char *full_base_name = NULL;
b85810ae
AD
62
63/* Prefix used to generate output file names. */
9b3add5b 64char *short_base_name = NULL;
27110317 65
f0130d39 66/* C source file extension (the parser source). */
7333d403 67const char *src_extension = NULL;
f0130d39 68/* Header file extension (if option ``-d'' is specified). */
7333d403 69const char *header_extension = NULL;
54bd0db4 70\f
358c15b7
AD
71/*-----------------------------------------------------------------.
72| Return a newly allocated string composed of the concatenation of |
6d441fc3 73| STR1, and STR2. |
358c15b7 74`-----------------------------------------------------------------*/
54bd0db4 75
6d441fc3
PE
76static char *
77concat2 (char const *str1, char const *str2)
54bd0db4 78{
6d441fc3 79 size_t len = strlen (str1) + strlen (str2);
82129ef5 80 char *res = xmalloc (len + 1);
358c15b7 81 char *cp;
6d441fc3
PE
82 cp = stpcpy (res, str1);
83 cp = stpcpy (cp, str2);
358c15b7 84 return res;
54bd0db4
RS
85}
86
cfe5fbc0
AD
87/*-----------------------------------------------------------------.
88| Try to open file NAME with mode MODE, and print an error message |
89| if fails. |
90`-----------------------------------------------------------------*/
54bd0db4 91
ff61dabd 92FILE *
8963a27b 93xfopen (const char *name, const char *mode)
cfe5fbc0 94{
8963a27b 95 FILE *ptr;
cfe5fbc0
AD
96
97 ptr = fopen (name, mode);
98 if (!ptr)
6d441fc3 99 error (EXIT_FAILURE, get_errno (), _("cannot open file `%s'"), name);
cfe5fbc0
AD
100
101 return ptr;
102}
103
104/*-------------------------------------------------------------.
105| Try to close file PTR, and print an error message if fails. |
106`-------------------------------------------------------------*/
107
e63ee1f1 108void
8963a27b 109xfclose (FILE *ptr)
cfe5fbc0 110{
cfe5fbc0 111 if (ptr == NULL)
e63ee1f1 112 return;
cfe5fbc0 113
e63ee1f1
PE
114 if (ferror (ptr))
115 error (EXIT_FAILURE, 0, _("I/O error"));
cfe5fbc0 116
e63ee1f1 117 if (fclose (ptr) != 0)
6d441fc3 118 error (EXIT_FAILURE, get_errno (), _("cannot close file"));
cfe5fbc0
AD
119}
120\f
f0130d39 121
053658d5
PE
122/*---------------------------------------------------------------------.
123| Compute FULL_BASE_NAME, SHORT_BASE_NAME and output files extensions. |
124`---------------------------------------------------------------------*/
234a3be3 125
b0ce6046 126/* Replace all characters FROM by TO in the string IN.
f0130d39 127 and returns a new allocated string. */
234a3be3 128static char *
f0130d39 129tr (const char *in, char from, char to)
234a3be3
AD
130{
131 char *temp;
82129ef5 132 char *out = xmalloc (strlen (in) + 1);
234a3be3
AD
133
134 for (temp = out; *in; in++, out++)
135 if (*in == from)
136 *out = to;
137 else
138 *out = *in;
139 *out = 0;
140 return (temp);
141}
142
d891bc49 143/* Compute extensions from the grammar file extension. */
234a3be3 144static void
f0130d39 145compute_exts_from_gf (const char *ext)
234a3be3 146{
342b8b6e
AD
147 src_extension = tr (ext, 'y', 'c');
148 src_extension = tr (src_extension, 'Y', 'C');
149 header_extension = tr (ext, 'y', 'h');
150 header_extension = tr (header_extension, 'Y', 'H');
234a3be3
AD
151}
152
d891bc49 153/* Compute extensions from the given c source file extension. */
234a3be3 154static void
f0130d39 155compute_exts_from_src (const char *ext)
234a3be3 156{
4ecbf796
MA
157 /* We use this function when the user specifies `-o' or `--output',
158 so the extenions must be computed unconditionally from the file name
159 given by this option. */
f0130d39
AD
160 src_extension = xstrdup (ext);
161 header_extension = tr (ext, 'c', 'h');
162 header_extension = tr (header_extension, 'C', 'H');
234a3be3 163}
d8880f69 164
ae404801
AD
165
166/* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth
167 part, (the directory) is ranging from FILENAME to the char before
168 *BASE, so we don't need an additional parameter.
169
170 *EXT points to the last period in the basename, or NULL if none.
171
172 If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
173 `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
174 cannot be equal to *BASE.
175
176 None are allocated, they are simply pointers to parts of FILENAME.
177 Examples:
178
179 '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
180 '.c'
181
182 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
183
184 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
185
186 '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
187
188 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
189
190 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
191
192 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */
193
194static void
195filename_split (const char *filename,
196 const char **base, const char **tab, const char **ext)
197{
198 *base = base_name (filename);
199
200 /* Look for the extension, i.e., look for the last dot. */
201 *ext = strrchr (*base, '.');
202 *tab = NULL;
203
82129ef5 204 /* If there is an extension, check if there is a `.tab' part right
ae404801 205 before. */
82129ef5
PE
206 if (*ext)
207 {
208 size_t baselen = *ext - *base;
209 size_t dottablen = 4;
210 if (dottablen < baselen
211 && (strncmp (*ext - dottablen, ".tab", dottablen) == 0
212 || strncmp (*ext - dottablen, "_tab", dottablen) == 0))
213 *tab = *ext - dottablen;
214 }
ae404801
AD
215}
216
217
19c50364
AD
218/* FIXME: Should use xstrndup. */
219
220static void
27110317 221compute_base_names (void)
54bd0db4 222{
ae404801 223 const char *base, *tab, *ext;
b0ce6046 224
19c50364 225 /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c),
053658d5 226 FULL_BASE_NAME and SHORT_BASE_NAME are `foo'.
54bd0db4 227
053658d5
PE
228 If --output=foo.tab.c was specified, FULL_BASE_NAME is `foo.tab'
229 and SHORT_BASE_NAME is `foo'.
19c50364
AD
230
231 The precise -o name will be used for FTABLE. For other output
232 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
233 if (spec_outfile)
234 {
ae404801
AD
235 filename_split (spec_outfile, &base, &tab, &ext);
236
237 /* The full base name goes up the EXT, excluding it. */
238 full_base_name =
239 xstrndup (spec_outfile,
240 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 241
ae404801
AD
242 /* The short base name goes up to TAB, excluding it. */
243 short_base_name =
244 xstrndup (spec_outfile,
245 (strlen (spec_outfile)
246 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
247
ae404801
AD
248 if (ext)
249 compute_exts_from_src (ext);
54bd0db4 250 }
19c50364 251
ae404801
AD
252 /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab'
253 and SHORT_BASE_NAME = `foo'.
19c50364
AD
254
255 Construct names from it. */
ae404801 256 else
54bd0db4 257 {
ae404801
AD
258 if (spec_file_prefix)
259 {
260 /* If --file-prefix=foo was specified, SHORT_BASE_NAME =
261 `foo'. */
262 short_base_name = xstrdup (spec_file_prefix);
263 }
264 else if (yacc_flag)
265 {
266 /* If --yacc, then the output is `y.tab.c'. */
267 short_base_name = xstrdup ("y");
268 }
269 else
270 {
271 /* Otherwise, the short base name is computed from the input
8c165d89 272 grammar: `foo/bar.yy' => `bar'. */
95612cfa 273 filename_split (grammar_file, &base, &tab, &ext);
ae404801 274 short_base_name =
8c165d89
AD
275 xstrndup (base,
276 (strlen (base) - (ext ? strlen (ext) : 0)));
ae404801 277 }
9b3add5b 278
82129ef5 279 full_base_name = xmalloc (strlen (short_base_name)
6d441fc3
PE
280 + strlen (TAB_EXT) + 1);
281 stpcpy (stpcpy (full_base_name, short_base_name), TAB_EXT);
ae404801 282
d891bc49 283 /* Compute the extensions from the grammar file name. */
95612cfa 284 filename_split (grammar_file, &base, &tab, &ext);
5e5d5415 285 if (ext && !yacc_flag)
ae404801 286 compute_exts_from_gf (ext);
54bd0db4 287 }
19c50364
AD
288}
289
053658d5
PE
290
291/* Compute the output file names. Warn if we detect conflicting
292 outputs to the same file. */
342b8b6e
AD
293
294void
295compute_output_file_names (void)
296{
053658d5
PE
297 char const *name[4];
298 int i;
299 int j;
300 int names = 0;
301
342b8b6e
AD
302 compute_base_names ();
303
304 /* If not yet done. */
305 if (!src_extension)
306 src_extension = ".c";
307 if (!header_extension)
308 header_extension = ".h";
fdbcd8e2 309
053658d5 310 name[names++] = parser_file_name =
6d441fc3 311 spec_outfile ? spec_outfile : concat2 (full_base_name, src_extension);
fdbcd8e2 312
053658d5
PE
313 if (defines_flag)
314 {
315 if (! spec_defines_file)
316 spec_defines_file = concat2 (full_base_name, header_extension);
317 name[names++] = spec_defines_file;
318 }
342b8b6e 319
053658d5
PE
320 if (graph_flag)
321 {
322 if (! spec_graph_file)
323 spec_graph_file = concat2 (short_base_name, ".vcg");
324 name[names++] = spec_graph_file;
325 }
326
327 if (report_flag)
328 {
329 spec_verbose_file = concat2 (short_base_name, OUTPUT_EXT);
330 name[names++] = spec_verbose_file;
331 }
342b8b6e 332
053658d5
PE
333 for (j = 0; j < names; j++)
334 for (i = 0; i < j; i++)
335 if (strcmp (name[i], name[j]) == 0)
336 warn (_("conflicting outputs to file %s"), quote (name[i]));
342b8b6e 337}