]> git.saurik.com Git - bison.git/blame - src/files.c
avoid direct strncmp calls.
[bison.git] / src / files.c
CommitLineData
82129ef5
PE
1/* Open and close files for Bison.
2
34136e65 3 Copyright (C) 1984, 1986, 1989, 1992, 2000-2012 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
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)
4a9cd8f2
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))
108df813 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{
f518dbaf 145 if (STREQ (ext, ".y"))
0e021770
PE
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 204file_name_split (const char *file_name,
e9690142 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. */
ba60c395 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;
4663cb4d 218 size_t dottablen = sizeof (TAB_EXT) - 1;
82129ef5 219 if (dottablen < baselen
4663cb4d 220 && STRPREFIX_LIT (TAB_EXT, *ext - dottablen))
e9690142 221 *tab = *ext - dottablen;
82129ef5 222 }
ae404801
AD
223}
224
225
19c50364 226static void
2b81e969 227compute_file_name_parts (void)
54bd0db4 228{
ae404801 229 const char *base, *tab, *ext;
b0ce6046 230
2b81e969
AD
231 /* Compute ALL_BUT_EXT and ALL_BUT_TAB_EXT from SPEC_OUTFILE
232 or GRAMMAR_FILE.
19c50364
AD
233
234 The precise -o name will be used for FTABLE. For other output
235 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
236 if (spec_outfile)
237 {
48b16bbc 238 file_name_split (spec_outfile, &base, &tab, &ext);
2b81e969 239 dir_prefix = xstrndup (spec_outfile, base - spec_outfile);
ae404801 240
2b81e969
AD
241 /* ALL_BUT_EXT goes up the EXT, excluding it. */
242 all_but_ext =
e9690142
JD
243 xstrndup (spec_outfile,
244 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 245
2b81e969
AD
246 /* ALL_BUT_TAB_EXT goes up to TAB, excluding it. */
247 all_but_tab_ext =
e9690142
JD
248 xstrndup (spec_outfile,
249 (strlen (spec_outfile)
250 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
ae404801 251
ae404801 252 if (ext)
e9690142 253 compute_exts_from_src (ext);
54bd0db4 254 }
ae404801 255 else
54bd0db4 256 {
2b81e969
AD
257 file_name_split (grammar_file, &base, &tab, &ext);
258
ae404801 259 if (spec_file_prefix)
e9690142
JD
260 {
261 /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = `foo'. */
262 dir_prefix =
cae5057f
JD
263 xstrndup (spec_file_prefix,
264 last_component (spec_file_prefix) - spec_file_prefix);
e9690142
JD
265 all_but_tab_ext = xstrdup (spec_file_prefix);
266 }
ae404801 267 else if (yacc_flag)
e9690142
JD
268 {
269 /* If --yacc, then the output is `y.tab.c'. */
270 dir_prefix = xstrdup ("");
271 all_but_tab_ext = xstrdup ("y");
272 }
ae404801 273 else
e9690142
JD
274 {
275 /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
276 grammar: `foo/bar.yy' => `bar'. */
277 dir_prefix = xstrdup ("");
278 all_but_tab_ext =
279 xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
280 }
9b3add5b 281
0e021770
PE
282 if (language->add_tab)
283 all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
284 else
285 all_but_ext = xstrdup (all_but_tab_ext);
ae404801 286
d891bc49 287 /* Compute the extensions from the grammar file name. */
5e5d5415 288 if (ext && !yacc_flag)
e9690142 289 compute_exts_from_gf (ext);
54bd0db4 290 }
19c50364
AD
291}
292
053658d5
PE
293
294/* Compute the output file names. Warn if we detect conflicting
295 outputs to the same file. */
342b8b6e
AD
296
297void
298compute_output_file_names (void)
299{
2b81e969 300 compute_file_name_parts ();
342b8b6e
AD
301
302 /* If not yet done. */
303 if (!src_extension)
eb095650 304 src_extension = xstrdup (".c");
342b8b6e 305 if (!header_extension)
eb095650 306 header_extension = xstrdup (".h");
fdbcd8e2 307
3f7ca628 308 parser_file_name =
eb095650
PE
309 (spec_outfile
310 ? xstrdup (spec_outfile)
311 : concat2 (all_but_ext, src_extension));
fdbcd8e2 312
053658d5
PE
313 if (defines_flag)
314 {
315 if (! spec_defines_file)
e9690142 316 spec_defines_file = concat2 (all_but_ext, header_extension);
053658d5 317 }
342b8b6e 318
053658d5
PE
319 if (graph_flag)
320 {
321 if (! spec_graph_file)
e9690142 322 spec_graph_file = concat2 (all_but_tab_ext, ".dot");
f39ab286 323 output_file_name_check (&spec_graph_file);
053658d5
PE
324 }
325
41d7a5f2
PE
326 if (xml_flag)
327 {
328 if (! spec_xml_file)
e9690142 329 spec_xml_file = concat2 (all_but_tab_ext, ".xml");
f39ab286 330 output_file_name_check (&spec_xml_file);
41d7a5f2
PE
331 }
332
053658d5
PE
333 if (report_flag)
334 {
1bb2bd75
JD
335 if (!spec_verbose_file)
336 spec_verbose_file = concat2 (all_but_tab_ext, OUTPUT_EXT);
f39ab286 337 output_file_name_check (&spec_verbose_file);
053658d5 338 }
342b8b6e 339
eb095650
PE
340 free (all_but_tab_ext);
341 free (src_extension);
342 free (header_extension);
343}
344
3f7ca628 345void
f39ab286 346output_file_name_check (char **file_name)
3f7ca628 347{
f39ab286 348 bool conflict = false;
f518dbaf 349 if (STREQ (*file_name, grammar_file))
f39ab286
JD
350 {
351 complain (_("refusing to overwrite the input file %s"),
352 quote (*file_name));
353 conflict = true;
354 }
355 else
356 {
357 int i;
358 for (i = 0; i < file_names_count; i++)
f518dbaf 359 if (STREQ (file_names[i], *file_name))
f39ab286
JD
360 {
361 warn (_("conflicting outputs to file %s"),
362 quote (*file_name));
363 conflict = true;
364 }
365 }
366 if (conflict)
367 {
368 free (*file_name);
369 *file_name = strdup ("/dev/null");
370 }
371 else
372 {
373 file_names = xnrealloc (file_names, ++file_names_count,
374 sizeof *file_names);
375 file_names[file_names_count-1] = xstrdup (*file_name);
376 }
3f7ca628
JD
377}
378
eb095650
PE
379void
380output_file_names_free (void)
381{
bd9d212b 382 free (all_but_ext);
eb095650
PE
383 free (spec_verbose_file);
384 free (spec_graph_file);
41d7a5f2 385 free (spec_xml_file);
eb095650
PE
386 free (spec_defines_file);
387 free (parser_file_name);
388 free (dir_prefix);
3f7ca628
JD
389 {
390 int i;
391 for (i = 0; i < file_names_count; i++)
392 free (file_names[i]);
393 }
394 free (file_names);
342b8b6e 395}