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