]> git.saurik.com Git - bison.git/blame - src/files.c
* src/lalr.c (state_lookahead_tokens_count): For code readability,
[bison.git] / src / files.c
CommitLineData
82129ef5
PE
1/* Open and close files for Bison.
2
cb48f191 3 Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002, 2003, 2004,
279cabb6 4 2005, 2006, 2007 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
b5b61c61
AD
38/* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is
39 tempting, but don't do that: for the time being our handling of the
40 %directive vs --option leaves precedence to the options by deciding
41 that if a %directive sets a variable which is really set (i.e., not
42 NULL), then the %directive is ignored. As a result, %name-prefix,
43 for instance, will not be honored. */
44
2b81e969
AD
45char const *spec_outfile = NULL; /* for -o. */
46char const *spec_file_prefix = NULL; /* for -b. */
47char const *spec_name_prefix = NULL; /* for -p. */
eb095650
PE
48char *spec_verbose_file = NULL; /* for --verbose. */
49char *spec_graph_file = NULL; /* for -g. */
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)
6d441fc3 113 error (EXIT_FAILURE, get_errno (), _("cannot open file `%s'"), name);
cfe5fbc0
AD
114
115 return ptr;
116}
117
118/*-------------------------------------------------------------.
119| Try to close file PTR, and print an error message if fails. |
120`-------------------------------------------------------------*/
121
e63ee1f1 122void
8963a27b 123xfclose (FILE *ptr)
cfe5fbc0 124{
cfe5fbc0 125 if (ptr == NULL)
e63ee1f1 126 return;
cfe5fbc0 127
e63ee1f1
PE
128 if (ferror (ptr))
129 error (EXIT_FAILURE, 0, _("I/O error"));
cfe5fbc0 130
e63ee1f1 131 if (fclose (ptr) != 0)
6d441fc3 132 error (EXIT_FAILURE, get_errno (), _("cannot close file"));
cfe5fbc0
AD
133}
134\f
f0130d39 135
2b81e969
AD
136/*------------------------------------------------------------------.
137| Compute ALL_BUT_EXT, ALL_BUT_TAB_EXT and output files extensions. |
138`------------------------------------------------------------------*/
234a3be3 139
eb095650 140/* In the string S, replace all characters FROM by TO. */
4502eadc 141static void
eb095650 142tr (char *s, char from, char to)
234a3be3 143{
eb095650
PE
144 for (; *s; s++)
145 if (*s == from)
146 *s = to;
234a3be3
AD
147}
148
d891bc49 149/* Compute extensions from the grammar file extension. */
234a3be3 150static void
f0130d39 151compute_exts_from_gf (const char *ext)
234a3be3 152{
0e021770
PE
153 if (strcmp (ext, ".y") == 0)
154 {
155 src_extension = xstrdup (language->src_extension);
156 header_extension = xstrdup (language->header_extension);
157 }
158 else
159 {
160 src_extension = xstrdup (ext);
161 header_extension = xstrdup (ext);
162 tr (src_extension, 'y', 'c');
163 tr (src_extension, 'Y', 'C');
164 tr (header_extension, 'y', 'h');
165 tr (header_extension, 'Y', 'H');
166 }
234a3be3
AD
167}
168
d891bc49 169/* Compute extensions from the given c source file extension. */
234a3be3 170static void
f0130d39 171compute_exts_from_src (const char *ext)
234a3be3 172{
4ecbf796
MA
173 /* We use this function when the user specifies `-o' or `--output',
174 so the extenions must be computed unconditionally from the file name
175 given by this option. */
f0130d39 176 src_extension = xstrdup (ext);
eb095650
PE
177 header_extension = xstrdup (ext);
178 tr (header_extension, 'c', 'h');
179 tr (header_extension, 'C', 'H');
234a3be3 180}
d8880f69 181
ae404801 182
48b16bbc
PE
183/* Decompose FILE_NAME in four parts: *BASE, *TAB, and *EXT, the fourth
184 part, (the directory) is ranging from FILE_NAME to the char before
ae404801
AD
185 *BASE, so we don't need an additional parameter.
186
187 *EXT points to the last period in the basename, or NULL if none.
188
189 If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
190 `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
191 cannot be equal to *BASE.
192
48b16bbc 193 None are allocated, they are simply pointers to parts of FILE_NAME.
ae404801
AD
194 Examples:
195
196 '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
197 '.c'
198
199 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
200
201 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
202
203 '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
204
205 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
206
207 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
208
209 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */
210
211static void
48b16bbc
PE
212file_name_split (const char *file_name,
213 const char **base, const char **tab, const char **ext)
ae404801 214{
cb48f191 215 *base = last_component (file_name);
ae404801
AD
216
217 /* Look for the extension, i.e., look for the last dot. */
218 *ext = strrchr (*base, '.');
219 *tab = NULL;
220
82129ef5 221 /* If there is an extension, check if there is a `.tab' part right
ae404801 222 before. */
82129ef5
PE
223 if (*ext)
224 {
225 size_t baselen = *ext - *base;
226 size_t dottablen = 4;
227 if (dottablen < baselen
228 && (strncmp (*ext - dottablen, ".tab", dottablen) == 0
229 || strncmp (*ext - dottablen, "_tab", dottablen) == 0))
230 *tab = *ext - dottablen;
231 }
ae404801
AD
232}
233
234
19c50364 235static void
2b81e969 236compute_file_name_parts (void)
54bd0db4 237{
ae404801 238 const char *base, *tab, *ext;
b0ce6046 239
2b81e969
AD
240 /* Compute ALL_BUT_EXT and ALL_BUT_TAB_EXT from SPEC_OUTFILE
241 or GRAMMAR_FILE.
19c50364
AD
242
243 The precise -o name will be used for FTABLE. For other output
244 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
245 if (spec_outfile)
246 {
48b16bbc 247 file_name_split (spec_outfile, &base, &tab, &ext);
2b81e969 248 dir_prefix = xstrndup (spec_outfile, base - spec_outfile);
ae404801 249
2b81e969
AD
250 /* ALL_BUT_EXT goes up the EXT, excluding it. */
251 all_but_ext =
ae404801
AD
252 xstrndup (spec_outfile,
253 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 254
2b81e969
AD
255 /* ALL_BUT_TAB_EXT goes up to TAB, excluding it. */
256 all_but_tab_ext =
ae404801
AD
257 xstrndup (spec_outfile,
258 (strlen (spec_outfile)
259 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
260
ae404801
AD
261 if (ext)
262 compute_exts_from_src (ext);
54bd0db4 263 }
ae404801 264 else
54bd0db4 265 {
2b81e969
AD
266 file_name_split (grammar_file, &base, &tab, &ext);
267
ae404801
AD
268 if (spec_file_prefix)
269 {
02d7cce6
PE
270 /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = `foo'. */
271 dir_prefix = xstrndup (grammar_file, base - grammar_file);
272 all_but_tab_ext = xstrdup (spec_file_prefix);
ae404801
AD
273 }
274 else if (yacc_flag)
275 {
02d7cce6 276 /* If --yacc, then the output is `y.tab.c'. */
eb095650
PE
277 dir_prefix = xstrdup ("");
278 all_but_tab_ext = xstrdup ("y");
ae404801
AD
279 }
280 else
281 {
02d7cce6 282 /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
8c165d89 283 grammar: `foo/bar.yy' => `bar'. */
eb095650 284 dir_prefix = xstrdup ("");
02d7cce6
PE
285 all_but_tab_ext =
286 xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
ae404801 287 }
9b3add5b 288
0e021770
PE
289 if (language->add_tab)
290 all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
291 else
292 all_but_ext = xstrdup (all_but_tab_ext);
ae404801 293
d891bc49 294 /* Compute the extensions from the grammar file name. */
5e5d5415 295 if (ext && !yacc_flag)
ae404801 296 compute_exts_from_gf (ext);
54bd0db4 297 }
19c50364
AD
298}
299
053658d5
PE
300
301/* Compute the output file names. Warn if we detect conflicting
302 outputs to the same file. */
342b8b6e
AD
303
304void
305compute_output_file_names (void)
306{
2b81e969 307 compute_file_name_parts ();
342b8b6e
AD
308
309 /* If not yet done. */
310 if (!src_extension)
eb095650 311 src_extension = xstrdup (".c");
342b8b6e 312 if (!header_extension)
eb095650 313 header_extension = xstrdup (".h");
fdbcd8e2 314
3f7ca628 315 parser_file_name =
eb095650
PE
316 (spec_outfile
317 ? xstrdup (spec_outfile)
318 : concat2 (all_but_ext, src_extension));
fdbcd8e2 319
053658d5
PE
320 if (defines_flag)
321 {
322 if (! spec_defines_file)
02d7cce6 323 spec_defines_file = concat2 (all_but_ext, header_extension);
053658d5 324 }
342b8b6e 325
053658d5
PE
326 if (graph_flag)
327 {
328 if (! spec_graph_file)
35fe0834 329 spec_graph_file = concat2 (all_but_tab_ext, ".dot");
3f7ca628 330 output_file_name_check (spec_graph_file);
053658d5
PE
331 }
332
333 if (report_flag)
334 {
2b81e969 335 spec_verbose_file = concat2 (all_but_tab_ext, OUTPUT_EXT);
3f7ca628 336 output_file_name_check (spec_verbose_file);
053658d5 337 }
342b8b6e 338
eb095650
PE
339 free (all_but_tab_ext);
340 free (src_extension);
341 free (header_extension);
342}
343
3f7ca628
JD
344void
345output_file_name_check (char const *file_name)
346{
347 {
348 int i;
349 for (i = 0; i < file_names_count; i++)
350 if (0 == strcmp (file_names[i], file_name))
351 warn (_("conflicting outputs to file %s"), quote (file_name));
352 }
353 file_names = xnrealloc (file_names, ++file_names_count, sizeof *file_names);
354 file_names[file_names_count-1] = xstrdup (file_name);
355}
356
eb095650
PE
357void
358output_file_names_free (void)
359{
bd9d212b 360 free (all_but_ext);
eb095650
PE
361 free (spec_verbose_file);
362 free (spec_graph_file);
363 free (spec_defines_file);
364 free (parser_file_name);
365 free (dir_prefix);
3f7ca628
JD
366 {
367 int i;
368 for (i = 0; i < file_names_count; i++)
369 free (file_names[i]);
370 }
371 free (file_names);
342b8b6e 372}