]> git.saurik.com Git - bison.git/blame - src/files.c
output: do not generate source files when late errors are caught
[bison.git] / src / files.c
CommitLineData
82129ef5
PE
1/* Open and close files for Bison.
2
7d6bad19 3 Copyright (C) 1984, 1986, 1989, 1992, 2000-2013 Free Software
575619af 4 Foundation, Inc.
54bd0db4 5
ceed8467 6 This file is part of Bison, the GNU Compiler Compiler.
54bd0db4 7
f16b0819
PE
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
54bd0db4 12
f16b0819
PE
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
54bd0db4 17
ceed8467 18 You should have received a copy of the GNU General Public License
f16b0819 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
54bd0db4 20
2cec9080 21#include <config.h>
9eceb6c6 22#include "system.h"
6d441fc3
PE
23
24#include <error.h>
cb48f191 25#include <dirname.h>
6d441fc3 26#include <get-errno.h>
053658d5 27#include <quote.h>
4a9cd8f2 28#include <quotearg.h>
cb48f191 29#include <stdio-safer.h>
1f65350a 30#include <xstrndup.h>
6d441fc3
PE
31
32#include "complain.h"
54bd0db4 33#include "files.h"
6d441fc3 34#include "getargs.h"
54bd0db4
RS
35#include "gram.h"
36
45eebca4 37/* Initializing some values below (such SPEC_NAME_PREFIX to 'yy') is
b5b61c61
AD
38 tempting, but don't do that: for the time being our handling of the
39 %directive vs --option leaves precedence to the options by deciding
40 that if a %directive sets a variable which is really set (i.e., not
41 NULL), then the %directive is ignored. As a result, %name-prefix,
42 for instance, will not be honored. */
43
2b81e969
AD
44char const *spec_outfile = NULL; /* for -o. */
45char const *spec_file_prefix = NULL; /* for -b. */
46char const *spec_name_prefix = NULL; /* for -p. */
eb095650
PE
47char *spec_verbose_file = NULL; /* for --verbose. */
48char *spec_graph_file = NULL; /* for -g. */
41d7a5f2 49char *spec_xml_file = NULL; /* for -x. */
eb095650
PE
50char *spec_defines_file = NULL; /* for --defines. */
51char *parser_file_name;
54bd0db4 52
3f7ca628 53/* All computed output file names. */
ea99d6e6
AD
54typedef struct generated_file
55{
56 /** File name. */
57 char *name;
58 /** Whether is a generated source file (e.g., *.c, *.java...), as
59 opposed to the report file (e.g., *.output). When late errors
60 are detected, generated source files are removed. */
61 bool is_source;
62} generated_file;
63static generated_file *generated_files = NULL;
64static int generated_files_size = 0;
3f7ca628 65
6d441fc3
PE
66uniqstr grammar_file = NULL;
67uniqstr current_file = NULL;
4a120d45 68
2b81e969 69/* If --output=dir/foo.c was specified,
45eebca4 70 DIR_PREFIX is 'dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'dir/foo'.
2b81e969 71
45eebca4
AD
72 If --output=dir/foo.tab.c was specified, DIR_PREFIX is 'dir/',
73 ALL_BUT_EXT is 'dir/foo.tab', and ALL_BUT_TAB_EXT is 'dir/foo'.
2b81e969
AD
74
75 If --output was not specified but --file-prefix=dir/foo was specified,
45eebca4 76 ALL_BUT_EXT = 'foo.tab' and ALL_BUT_TAB_EXT = 'foo'.
2b81e969
AD
77
78 If neither --output nor --file was specified but the input grammar
45eebca4 79 is name dir/foo.y, ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'foo'.
2b81e969
AD
80
81 If neither --output nor --file was specified, DIR_PREFIX is the
82 empty string (meaning the current directory); otherwise it is
45eebca4 83 'dir/'. */
b85810ae 84
bd9d212b 85char *all_but_ext;
eb095650
PE
86static char *all_but_tab_ext;
87char *dir_prefix;
27110317 88
f0130d39 89/* C source file extension (the parser source). */
eb095650 90static char *src_extension = NULL;
45eebca4 91/* Header file extension (if option '`-d'' is specified). */
eb095650 92static char *header_extension = NULL;
54bd0db4 93\f
358c15b7
AD
94/*-----------------------------------------------------------------.
95| Return a newly allocated string composed of the concatenation of |
6d441fc3 96| STR1, and STR2. |
358c15b7 97`-----------------------------------------------------------------*/
54bd0db4 98
6d441fc3
PE
99static char *
100concat2 (char const *str1, char const *str2)
54bd0db4 101{
6d441fc3 102 size_t len = strlen (str1) + strlen (str2);
82129ef5 103 char *res = xmalloc (len + 1);
358c15b7 104 char *cp;
6d441fc3
PE
105 cp = stpcpy (res, str1);
106 cp = stpcpy (cp, str2);
358c15b7 107 return res;
54bd0db4
RS
108}
109
cfe5fbc0
AD
110/*-----------------------------------------------------------------.
111| Try to open file NAME with mode MODE, and print an error message |
112| if fails. |
113`-----------------------------------------------------------------*/
54bd0db4 114
ff61dabd 115FILE *
8963a27b 116xfopen (const char *name, const char *mode)
cfe5fbc0 117{
8963a27b 118 FILE *ptr;
cfe5fbc0 119
3ea5f0ec 120 ptr = fopen_safer (name, mode);
cfe5fbc0 121 if (!ptr)
4a9cd8f2
AD
122 error (EXIT_FAILURE, get_errno (),
123 _("%s: cannot open"), quotearg_colon (name));
cfe5fbc0
AD
124
125 return ptr;
126}
127
128/*-------------------------------------------------------------.
129| Try to close file PTR, and print an error message if fails. |
130`-------------------------------------------------------------*/
131
e63ee1f1 132void
8963a27b 133xfclose (FILE *ptr)
cfe5fbc0 134{
cfe5fbc0 135 if (ptr == NULL)
e63ee1f1 136 return;
cfe5fbc0 137
e63ee1f1 138 if (ferror (ptr))
108df813 139 error (EXIT_FAILURE, 0, _("input/output error"));
cfe5fbc0 140
e63ee1f1 141 if (fclose (ptr) != 0)
6d441fc3 142 error (EXIT_FAILURE, get_errno (), _("cannot close file"));
cfe5fbc0
AD
143}
144\f
f0130d39 145
22539284
AD
146FILE *
147xfdopen (int fd, char const *mode)
148{
149 FILE *res = fdopen (fd, mode);
150 if (! res)
9fd33c2b 151 error (EXIT_FAILURE, get_errno (),
c5ae8e85
AD
152 /* On a separate line to please the "unmarked_diagnostics"
153 syntax-check. */
9fd33c2b 154 "fdopen");
22539284
AD
155 return res;
156}
157
2b81e969
AD
158/*------------------------------------------------------------------.
159| Compute ALL_BUT_EXT, ALL_BUT_TAB_EXT and output files extensions. |
160`------------------------------------------------------------------*/
234a3be3 161
d891bc49 162/* Compute extensions from the grammar file extension. */
234a3be3 163static void
f0130d39 164compute_exts_from_gf (const char *ext)
234a3be3 165{
f518dbaf 166 if (STREQ (ext, ".y"))
0e021770
PE
167 {
168 src_extension = xstrdup (language->src_extension);
169 header_extension = xstrdup (language->header_extension);
170 }
171 else
172 {
173 src_extension = xstrdup (ext);
174 header_extension = xstrdup (ext);
175 tr (src_extension, 'y', 'c');
176 tr (src_extension, 'Y', 'C');
177 tr (header_extension, 'y', 'h');
178 tr (header_extension, 'Y', 'H');
179 }
234a3be3
AD
180}
181
d891bc49 182/* Compute extensions from the given c source file extension. */
234a3be3 183static void
f0130d39 184compute_exts_from_src (const char *ext)
234a3be3 185{
4ecbf796
MA
186 /* We use this function when the user specifies `-o' or `--output',
187 so the extenions must be computed unconditionally from the file name
188 given by this option. */
f0130d39 189 src_extension = xstrdup (ext);
eb095650
PE
190 header_extension = xstrdup (ext);
191 tr (header_extension, 'c', 'h');
192 tr (header_extension, 'C', 'H');
234a3be3 193}
d8880f69 194
ae404801 195
48b16bbc
PE
196/* Decompose FILE_NAME in four parts: *BASE, *TAB, and *EXT, the fourth
197 part, (the directory) is ranging from FILE_NAME to the char before
ae404801
AD
198 *BASE, so we don't need an additional parameter.
199
200 *EXT points to the last period in the basename, or NULL if none.
201
202 If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
45eebca4 203 '.tab' or '_tab' if present right before *EXT, or is NULL. *TAB
ae404801
AD
204 cannot be equal to *BASE.
205
48b16bbc 206 None are allocated, they are simply pointers to parts of FILE_NAME.
ae404801
AD
207 Examples:
208
209 '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
210 '.c'
211
212 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
213
214 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
215
216 '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
217
218 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
219
220 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
221
222 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */
223
224static void
48b16bbc 225file_name_split (const char *file_name,
e9690142 226 const char **base, const char **tab, const char **ext)
ae404801 227{
cb48f191 228 *base = last_component (file_name);
ae404801
AD
229
230 /* Look for the extension, i.e., look for the last dot. */
84526bf3 231 *ext = strrchr (*base, '.');
ae404801
AD
232 *tab = NULL;
233
45eebca4 234 /* If there is an extension, check if there is a '.tab' part right
ae404801 235 before. */
82129ef5
PE
236 if (*ext)
237 {
238 size_t baselen = *ext - *base;
4663cb4d 239 size_t dottablen = sizeof (TAB_EXT) - 1;
82129ef5 240 if (dottablen < baselen
4663cb4d 241 && STRPREFIX_LIT (TAB_EXT, *ext - dottablen))
e9690142 242 *tab = *ext - dottablen;
82129ef5 243 }
ae404801
AD
244}
245
246
19c50364 247static void
2b81e969 248compute_file_name_parts (void)
54bd0db4 249{
ae404801 250 const char *base, *tab, *ext;
b0ce6046 251
2b81e969
AD
252 /* Compute ALL_BUT_EXT and ALL_BUT_TAB_EXT from SPEC_OUTFILE
253 or GRAMMAR_FILE.
19c50364
AD
254
255 The precise -o name will be used for FTABLE. For other output
256 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
257 if (spec_outfile)
258 {
48b16bbc 259 file_name_split (spec_outfile, &base, &tab, &ext);
2b81e969 260 dir_prefix = xstrndup (spec_outfile, base - spec_outfile);
ae404801 261
2b81e969
AD
262 /* ALL_BUT_EXT goes up the EXT, excluding it. */
263 all_but_ext =
e9690142
JD
264 xstrndup (spec_outfile,
265 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 266
2b81e969
AD
267 /* ALL_BUT_TAB_EXT goes up to TAB, excluding it. */
268 all_but_tab_ext =
e9690142
JD
269 xstrndup (spec_outfile,
270 (strlen (spec_outfile)
271 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
ae404801 272
ae404801 273 if (ext)
e9690142 274 compute_exts_from_src (ext);
54bd0db4 275 }
ae404801 276 else
54bd0db4 277 {
2b81e969
AD
278 file_name_split (grammar_file, &base, &tab, &ext);
279
ae404801 280 if (spec_file_prefix)
e9690142 281 {
45eebca4 282 /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = 'foo'. */
e9690142 283 dir_prefix =
cae5057f
JD
284 xstrndup (spec_file_prefix,
285 last_component (spec_file_prefix) - spec_file_prefix);
e9690142
JD
286 all_but_tab_ext = xstrdup (spec_file_prefix);
287 }
ae404801 288 else if (yacc_flag)
e9690142 289 {
45eebca4 290 /* If --yacc, then the output is 'y.tab.c'. */
e9690142
JD
291 dir_prefix = xstrdup ("");
292 all_but_tab_ext = xstrdup ("y");
293 }
ae404801 294 else
e9690142
JD
295 {
296 /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
45eebca4 297 grammar: 'foo/bar.yy' => 'bar'. */
e9690142
JD
298 dir_prefix = xstrdup ("");
299 all_but_tab_ext =
300 xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
301 }
9b3add5b 302
0e021770
PE
303 if (language->add_tab)
304 all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
305 else
306 all_but_ext = xstrdup (all_but_tab_ext);
ae404801 307
d891bc49 308 /* Compute the extensions from the grammar file name. */
5e5d5415 309 if (ext && !yacc_flag)
e9690142 310 compute_exts_from_gf (ext);
54bd0db4 311 }
19c50364
AD
312}
313
053658d5
PE
314
315/* Compute the output file names. Warn if we detect conflicting
316 outputs to the same file. */
342b8b6e
AD
317
318void
319compute_output_file_names (void)
320{
2b81e969 321 compute_file_name_parts ();
342b8b6e
AD
322
323 /* If not yet done. */
324 if (!src_extension)
eb095650 325 src_extension = xstrdup (".c");
342b8b6e 326 if (!header_extension)
eb095650 327 header_extension = xstrdup (".h");
fdbcd8e2 328
3f7ca628 329 parser_file_name =
eb095650
PE
330 (spec_outfile
331 ? xstrdup (spec_outfile)
332 : concat2 (all_but_ext, src_extension));
fdbcd8e2 333
053658d5
PE
334 if (defines_flag)
335 {
336 if (! spec_defines_file)
e9690142 337 spec_defines_file = concat2 (all_but_ext, header_extension);
053658d5 338 }
342b8b6e 339
053658d5
PE
340 if (graph_flag)
341 {
342 if (! spec_graph_file)
e9690142 343 spec_graph_file = concat2 (all_but_tab_ext, ".dot");
ea99d6e6 344 output_file_name_check (&spec_graph_file, false);
053658d5
PE
345 }
346
41d7a5f2
PE
347 if (xml_flag)
348 {
349 if (! spec_xml_file)
e9690142 350 spec_xml_file = concat2 (all_but_tab_ext, ".xml");
ea99d6e6 351 output_file_name_check (&spec_xml_file, false);
41d7a5f2
PE
352 }
353
053658d5
PE
354 if (report_flag)
355 {
1bb2bd75
JD
356 if (!spec_verbose_file)
357 spec_verbose_file = concat2 (all_but_tab_ext, OUTPUT_EXT);
ea99d6e6 358 output_file_name_check (&spec_verbose_file, false);
053658d5 359 }
342b8b6e 360
eb095650
PE
361 free (all_but_tab_ext);
362 free (src_extension);
363 free (header_extension);
364}
365
3f7ca628 366void
ea99d6e6 367output_file_name_check (char **file_name, bool source)
3f7ca628 368{
f39ab286 369 bool conflict = false;
f518dbaf 370 if (STREQ (*file_name, grammar_file))
f39ab286 371 {
bb8e56ff 372 complain (NULL, complaint, _("refusing to overwrite the input file %s"),
f39ab286
JD
373 quote (*file_name));
374 conflict = true;
375 }
376 else
377 {
378 int i;
ea99d6e6
AD
379 for (i = 0; i < generated_files_size; i++)
380 if (STREQ (generated_files[i].name, *file_name))
f39ab286 381 {
bb8e56ff 382 complain (NULL, Wother, _("conflicting outputs to file %s"),
ea99d6e6 383 quote (generated_files[i].name));
f39ab286
JD
384 conflict = true;
385 }
386 }
387 if (conflict)
388 {
389 free (*file_name);
390 *file_name = strdup ("/dev/null");
391 }
392 else
393 {
ea99d6e6
AD
394 generated_files = xnrealloc (generated_files, ++generated_files_size,
395 sizeof *generated_files);
396 generated_files[generated_files_size-1].name = xstrdup (*file_name);
397 generated_files[generated_files_size-1].is_source = source;
f39ab286 398 }
3f7ca628
JD
399}
400
46198327
AD
401void
402unlink_generated_sources (void)
403{
404 int i;
405 for (i = 0; i < generated_files_size; i++)
406 if (generated_files[i].is_source)
407 /* Ignore errors. The file might not even exist. */
408 unlink (generated_files[i].name);
409}
410
eb095650
PE
411void
412output_file_names_free (void)
413{
bd9d212b 414 free (all_but_ext);
eb095650
PE
415 free (spec_verbose_file);
416 free (spec_graph_file);
41d7a5f2 417 free (spec_xml_file);
eb095650
PE
418 free (spec_defines_file);
419 free (parser_file_name);
420 free (dir_prefix);
3f7ca628
JD
421 {
422 int i;
ea99d6e6
AD
423 for (i = 0; i < generated_files_size; i++)
424 free (generated_files[i].name);
3f7ca628 425 }
ea99d6e6 426 free (generated_files);
342b8b6e 427}