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