]> git.saurik.com Git - bison.git/blame - src/files.c
tests: syntax-check
[bison.git] / src / files.c
CommitLineData
82129ef5
PE
1/* Open and close files for Bison.
2
c932d613 3 Copyright (C) 1984, 1986, 1989, 1992, 2000-2012 Free Software
ea0a7676 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>
4c787a31 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
b5b61c61
AD
37/* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is
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
JD
53/* All computed output file names. */
54static char **file_names = NULL;
55static int file_names_count = 0;
56
6d441fc3
PE
57uniqstr grammar_file = NULL;
58uniqstr current_file = NULL;
4a120d45 59
2b81e969
AD
60/* If --output=dir/foo.c was specified,
61 DIR_PREFIX is `dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are `dir/foo'.
62
63 If --output=dir/foo.tab.c was specified, DIR_PREFIX is `dir/',
64 ALL_BUT_EXT is `dir/foo.tab', and ALL_BUT_TAB_EXT is `dir/foo'.
65
66 If --output was not specified but --file-prefix=dir/foo was specified,
67 ALL_BUT_EXT = `foo.tab' and ALL_BUT_TAB_EXT = `foo'.
68
69 If neither --output nor --file was specified but the input grammar
70 is name dir/foo.y, ALL_BUT_EXT and ALL_BUT_TAB_EXT are `foo'.
71
72 If neither --output nor --file was specified, DIR_PREFIX is the
73 empty string (meaning the current directory); otherwise it is
74 `dir/'. */
b85810ae 75
bd9d212b 76char *all_but_ext;
eb095650
PE
77static char *all_but_tab_ext;
78char *dir_prefix;
27110317 79
f0130d39 80/* C source file extension (the parser source). */
eb095650 81static char *src_extension = NULL;
f0130d39 82/* Header file extension (if option ``-d'' is specified). */
eb095650 83static char *header_extension = NULL;
54bd0db4 84\f
358c15b7
AD
85/*-----------------------------------------------------------------.
86| Return a newly allocated string composed of the concatenation of |
6d441fc3 87| STR1, and STR2. |
358c15b7 88`-----------------------------------------------------------------*/
54bd0db4 89
6d441fc3
PE
90static char *
91concat2 (char const *str1, char const *str2)
54bd0db4 92{
6d441fc3 93 size_t len = strlen (str1) + strlen (str2);
82129ef5 94 char *res = xmalloc (len + 1);
358c15b7 95 char *cp;
6d441fc3
PE
96 cp = stpcpy (res, str1);
97 cp = stpcpy (cp, str2);
358c15b7 98 return res;
54bd0db4
RS
99}
100
cfe5fbc0
AD
101/*-----------------------------------------------------------------.
102| Try to open file NAME with mode MODE, and print an error message |
103| if fails. |
104`-----------------------------------------------------------------*/
54bd0db4 105
ff61dabd 106FILE *
8963a27b 107xfopen (const char *name, const char *mode)
cfe5fbc0 108{
8963a27b 109 FILE *ptr;
cfe5fbc0 110
3ea5f0ec 111 ptr = fopen_safer (name, mode);
cfe5fbc0 112 if (!ptr)
4c787a31
AD
113 error (EXIT_FAILURE, get_errno (),
114 _("%s: cannot open"), quotearg_colon (name));
cfe5fbc0
AD
115
116 return ptr;
117}
118
119/*-------------------------------------------------------------.
120| Try to close file PTR, and print an error message if fails. |
121`-------------------------------------------------------------*/
122
e63ee1f1 123void
8963a27b 124xfclose (FILE *ptr)
cfe5fbc0 125{
cfe5fbc0 126 if (ptr == NULL)
e63ee1f1 127 return;
cfe5fbc0 128
e63ee1f1 129 if (ferror (ptr))
6487c0b3 130 error (EXIT_FAILURE, 0, _("input/output error"));
cfe5fbc0 131
e63ee1f1 132 if (fclose (ptr) != 0)
6d441fc3 133 error (EXIT_FAILURE, get_errno (), _("cannot close file"));
cfe5fbc0
AD
134}
135\f
f0130d39 136
2b81e969
AD
137/*------------------------------------------------------------------.
138| Compute ALL_BUT_EXT, ALL_BUT_TAB_EXT and output files extensions. |
139`------------------------------------------------------------------*/
234a3be3 140
d891bc49 141/* Compute extensions from the grammar file extension. */
234a3be3 142static void
f0130d39 143compute_exts_from_gf (const char *ext)
234a3be3 144{
0e021770
PE
145 if (strcmp (ext, ".y") == 0)
146 {
147 src_extension = xstrdup (language->src_extension);
148 header_extension = xstrdup (language->header_extension);
149 }
150 else
151 {
152 src_extension = xstrdup (ext);
153 header_extension = xstrdup (ext);
154 tr (src_extension, 'y', 'c');
155 tr (src_extension, 'Y', 'C');
156 tr (header_extension, 'y', 'h');
157 tr (header_extension, 'Y', 'H');
158 }
234a3be3
AD
159}
160
d891bc49 161/* Compute extensions from the given c source file extension. */
234a3be3 162static void
f0130d39 163compute_exts_from_src (const char *ext)
234a3be3 164{
4ecbf796
MA
165 /* We use this function when the user specifies `-o' or `--output',
166 so the extenions must be computed unconditionally from the file name
167 given by this option. */
f0130d39 168 src_extension = xstrdup (ext);
eb095650
PE
169 header_extension = xstrdup (ext);
170 tr (header_extension, 'c', 'h');
171 tr (header_extension, 'C', 'H');
234a3be3 172}
d8880f69 173
ae404801 174
48b16bbc
PE
175/* Decompose FILE_NAME in four parts: *BASE, *TAB, and *EXT, the fourth
176 part, (the directory) is ranging from FILE_NAME to the char before
ae404801
AD
177 *BASE, so we don't need an additional parameter.
178
179 *EXT points to the last period in the basename, or NULL if none.
180
181 If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
182 `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
183 cannot be equal to *BASE.
184
48b16bbc 185 None are allocated, they are simply pointers to parts of FILE_NAME.
ae404801
AD
186 Examples:
187
188 '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
189 '.c'
190
191 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
192
193 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
194
195 '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
196
197 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
198
199 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
200
201 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */
202
203static void
48b16bbc
PE
204file_name_split (const char *file_name,
205 const char **base, const char **tab, const char **ext)
ae404801 206{
cb48f191 207 *base = last_component (file_name);
ae404801
AD
208
209 /* Look for the extension, i.e., look for the last dot. */
d143e9c3 210 *ext = mbsrchr (*base, '.');
ae404801
AD
211 *tab = NULL;
212
82129ef5 213 /* If there is an extension, check if there is a `.tab' part right
ae404801 214 before. */
82129ef5
PE
215 if (*ext)
216 {
217 size_t baselen = *ext - *base;
218 size_t dottablen = 4;
219 if (dottablen < baselen
220 && (strncmp (*ext - dottablen, ".tab", dottablen) == 0
221 || strncmp (*ext - dottablen, "_tab", dottablen) == 0))
222 *tab = *ext - dottablen;
223 }
ae404801
AD
224}
225
226
19c50364 227static void
2b81e969 228compute_file_name_parts (void)
54bd0db4 229{
ae404801 230 const char *base, *tab, *ext;
b0ce6046 231
2b81e969
AD
232 /* Compute ALL_BUT_EXT and ALL_BUT_TAB_EXT from SPEC_OUTFILE
233 or GRAMMAR_FILE.
19c50364
AD
234
235 The precise -o name will be used for FTABLE. For other output
236 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
237 if (spec_outfile)
238 {
48b16bbc 239 file_name_split (spec_outfile, &base, &tab, &ext);
2b81e969 240 dir_prefix = xstrndup (spec_outfile, base - spec_outfile);
ae404801 241
2b81e969
AD
242 /* ALL_BUT_EXT goes up the EXT, excluding it. */
243 all_but_ext =
ae404801
AD
244 xstrndup (spec_outfile,
245 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 246
2b81e969
AD
247 /* ALL_BUT_TAB_EXT goes up to TAB, excluding it. */
248 all_but_tab_ext =
ae404801
AD
249 xstrndup (spec_outfile,
250 (strlen (spec_outfile)
251 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
252
ae404801
AD
253 if (ext)
254 compute_exts_from_src (ext);
54bd0db4 255 }
ae404801 256 else
54bd0db4 257 {
2b81e969
AD
258 file_name_split (grammar_file, &base, &tab, &ext);
259
ae404801
AD
260 if (spec_file_prefix)
261 {
02d7cce6 262 /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = `foo'. */
cae5057f
JD
263 dir_prefix =
264 xstrndup (spec_file_prefix,
265 last_component (spec_file_prefix) - spec_file_prefix);
02d7cce6 266 all_but_tab_ext = xstrdup (spec_file_prefix);
ae404801
AD
267 }
268 else if (yacc_flag)
269 {
02d7cce6 270 /* If --yacc, then the output is `y.tab.c'. */
eb095650
PE
271 dir_prefix = xstrdup ("");
272 all_but_tab_ext = xstrdup ("y");
ae404801
AD
273 }
274 else
275 {
02d7cce6 276 /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
8c165d89 277 grammar: `foo/bar.yy' => `bar'. */
eb095650 278 dir_prefix = xstrdup ("");
02d7cce6
PE
279 all_but_tab_ext =
280 xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
ae404801 281 }
9b3add5b 282
0e021770
PE
283 if (language->add_tab)
284 all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
285 else
286 all_but_ext = xstrdup (all_but_tab_ext);
ae404801 287
d891bc49 288 /* Compute the extensions from the grammar file name. */
5e5d5415 289 if (ext && !yacc_flag)
ae404801 290 compute_exts_from_gf (ext);
54bd0db4 291 }
19c50364
AD
292}
293
053658d5
PE
294
295/* Compute the output file names. Warn if we detect conflicting
296 outputs to the same file. */
342b8b6e
AD
297
298void
299compute_output_file_names (void)
300{
2b81e969 301 compute_file_name_parts ();
342b8b6e
AD
302
303 /* If not yet done. */
304 if (!src_extension)
eb095650 305 src_extension = xstrdup (".c");
342b8b6e 306 if (!header_extension)
eb095650 307 header_extension = xstrdup (".h");
fdbcd8e2 308
3f7ca628 309 parser_file_name =
eb095650
PE
310 (spec_outfile
311 ? xstrdup (spec_outfile)
312 : concat2 (all_but_ext, src_extension));
fdbcd8e2 313
053658d5
PE
314 if (defines_flag)
315 {
316 if (! spec_defines_file)
02d7cce6 317 spec_defines_file = concat2 (all_but_ext, header_extension);
053658d5 318 }
342b8b6e 319
053658d5
PE
320 if (graph_flag)
321 {
322 if (! spec_graph_file)
35fe0834 323 spec_graph_file = concat2 (all_but_tab_ext, ".dot");
47fa5747 324 output_file_name_check (&spec_graph_file);
053658d5
PE
325 }
326
41d7a5f2
PE
327 if (xml_flag)
328 {
329 if (! spec_xml_file)
330 spec_xml_file = concat2 (all_but_tab_ext, ".xml");
47fa5747 331 output_file_name_check (&spec_xml_file);
41d7a5f2
PE
332 }
333
053658d5
PE
334 if (report_flag)
335 {
1bb2bd75
JD
336 if (!spec_verbose_file)
337 spec_verbose_file = concat2 (all_but_tab_ext, OUTPUT_EXT);
47fa5747 338 output_file_name_check (&spec_verbose_file);
053658d5 339 }
342b8b6e 340
eb095650
PE
341 free (all_but_tab_ext);
342 free (src_extension);
343 free (header_extension);
344}
345
3f7ca628 346void
47fa5747 347output_file_name_check (char **file_name)
3f7ca628 348{
47fa5747
JD
349 bool conflict = false;
350 if (0 == strcmp (*file_name, grammar_file))
351 {
352 complain (_("refusing to overwrite the input file %s"),
353 quote (*file_name));
354 conflict = true;
355 }
356 else
357 {
358 int i;
359 for (i = 0; i < file_names_count; i++)
360 if (0 == strcmp (file_names[i], *file_name))
361 {
362 warn (_("conflicting outputs to file %s"),
363 quote (*file_name));
364 conflict = true;
365 }
366 }
367 if (conflict)
368 {
369 free (*file_name);
370 *file_name = strdup ("/dev/null");
371 }
372 else
373 {
374 file_names = xnrealloc (file_names, ++file_names_count,
375 sizeof *file_names);
376 file_names[file_names_count-1] = xstrdup (*file_name);
377 }
3f7ca628
JD
378}
379
eb095650
PE
380void
381output_file_names_free (void)
382{
bd9d212b 383 free (all_but_ext);
eb095650
PE
384 free (spec_verbose_file);
385 free (spec_graph_file);
41d7a5f2 386 free (spec_xml_file);
eb095650
PE
387 free (spec_defines_file);
388 free (parser_file_name);
389 free (dir_prefix);
3f7ca628
JD
390 {
391 int i;
392 for (i = 0; i < file_names_count; i++)
393 free (file_names[i]);
394 }
395 free (file_names);
342b8b6e 396}