]> git.saurik.com Git - bison.git/blame - src/files.c
* data/glr.c (yyGLRStateSet): Rename yylookaheadStatuses to
[bison.git] / src / files.c
CommitLineData
82129ef5
PE
1/* Open and close files for Bison.
2
3ea5f0ec 3 Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002, 2003, 2004, 2005
b85810ae 4 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>
27#include <get-errno.h>
053658d5 28#include <quote.h>
1f65350a 29#include <xstrndup.h>
6d441fc3
PE
30
31#include "complain.h"
2b81e969 32#include "dirname.h"
54bd0db4 33#include "files.h"
6d441fc3 34#include "getargs.h"
54bd0db4 35#include "gram.h"
f2a97c62 36#include "stdio-safer.h"
54bd0db4 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. */
51char const *spec_verbose_file = NULL; /* for --verbose. */
52char const *spec_graph_file = NULL; /* for -g. */
53char const *spec_defines_file = NULL; /* for --defines. */
54char const *parser_file_name;
54bd0db4 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
2b81e969
AD
75static char const *all_but_ext;
76static char const *all_but_tab_ext;
77char const *dir_prefix;
27110317 78
f0130d39 79/* C source file extension (the parser source). */
04098407 80static char const *src_extension = NULL;
f0130d39 81/* Header file extension (if option ``-d'' is specified). */
04098407 82static char const *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
b0ce6046 139/* Replace all characters FROM by TO in the string IN.
f0130d39 140 and returns a new allocated string. */
234a3be3 141static char *
f0130d39 142tr (const char *in, char from, char to)
234a3be3
AD
143{
144 char *temp;
82129ef5 145 char *out = xmalloc (strlen (in) + 1);
234a3be3
AD
146
147 for (temp = out; *in; in++, out++)
148 if (*in == from)
149 *out = to;
150 else
151 *out = *in;
152 *out = 0;
153 return (temp);
154}
155
d891bc49 156/* Compute extensions from the grammar file extension. */
234a3be3 157static void
f0130d39 158compute_exts_from_gf (const char *ext)
234a3be3 159{
342b8b6e
AD
160 src_extension = tr (ext, 'y', 'c');
161 src_extension = tr (src_extension, 'Y', 'C');
162 header_extension = tr (ext, 'y', 'h');
163 header_extension = tr (header_extension, 'Y', 'H');
234a3be3
AD
164}
165
d891bc49 166/* Compute extensions from the given c source file extension. */
234a3be3 167static void
f0130d39 168compute_exts_from_src (const char *ext)
234a3be3 169{
4ecbf796
MA
170 /* We use this function when the user specifies `-o' or `--output',
171 so the extenions must be computed unconditionally from the file name
172 given by this option. */
f0130d39
AD
173 src_extension = xstrdup (ext);
174 header_extension = tr (ext, 'c', 'h');
175 header_extension = tr (header_extension, 'C', 'H');
234a3be3 176}
d8880f69 177
ae404801 178
48b16bbc
PE
179/* Decompose FILE_NAME in four parts: *BASE, *TAB, and *EXT, the fourth
180 part, (the directory) is ranging from FILE_NAME to the char before
ae404801
AD
181 *BASE, so we don't need an additional parameter.
182
183 *EXT points to the last period in the basename, or NULL if none.
184
185 If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
186 `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
187 cannot be equal to *BASE.
188
48b16bbc 189 None are allocated, they are simply pointers to parts of FILE_NAME.
ae404801
AD
190 Examples:
191
192 '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
193 '.c'
194
195 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
196
197 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
198
199 '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
200
201 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
202
203 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
204
205 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */
206
207static void
48b16bbc
PE
208file_name_split (const char *file_name,
209 const char **base, const char **tab, const char **ext)
ae404801 210{
48b16bbc 211 *base = base_name (file_name);
ae404801
AD
212
213 /* Look for the extension, i.e., look for the last dot. */
214 *ext = strrchr (*base, '.');
215 *tab = NULL;
216
82129ef5 217 /* If there is an extension, check if there is a `.tab' part right
ae404801 218 before. */
82129ef5
PE
219 if (*ext)
220 {
221 size_t baselen = *ext - *base;
222 size_t dottablen = 4;
223 if (dottablen < baselen
224 && (strncmp (*ext - dottablen, ".tab", dottablen) == 0
225 || strncmp (*ext - dottablen, "_tab", dottablen) == 0))
226 *tab = *ext - dottablen;
227 }
ae404801
AD
228}
229
230
19c50364 231static void
2b81e969 232compute_file_name_parts (void)
54bd0db4 233{
ae404801 234 const char *base, *tab, *ext;
b0ce6046 235
2b81e969
AD
236 /* Compute ALL_BUT_EXT and ALL_BUT_TAB_EXT from SPEC_OUTFILE
237 or GRAMMAR_FILE.
19c50364
AD
238
239 The precise -o name will be used for FTABLE. For other output
240 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
241 if (spec_outfile)
242 {
48b16bbc 243 file_name_split (spec_outfile, &base, &tab, &ext);
2b81e969 244 dir_prefix = xstrndup (spec_outfile, base - spec_outfile);
ae404801 245
2b81e969
AD
246 /* ALL_BUT_EXT goes up the EXT, excluding it. */
247 all_but_ext =
ae404801
AD
248 xstrndup (spec_outfile,
249 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 250
2b81e969
AD
251 /* ALL_BUT_TAB_EXT goes up to TAB, excluding it. */
252 all_but_tab_ext =
ae404801
AD
253 xstrndup (spec_outfile,
254 (strlen (spec_outfile)
255 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
256
ae404801
AD
257 if (ext)
258 compute_exts_from_src (ext);
54bd0db4 259 }
ae404801 260 else
54bd0db4 261 {
2b81e969
AD
262 file_name_split (grammar_file, &base, &tab, &ext);
263
ae404801
AD
264 if (spec_file_prefix)
265 {
2b81e969 266 /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT =
ae404801 267 `foo'. */
2b81e969
AD
268 dir_prefix = xstrndup (grammar_file, base - grammar_file);
269 all_but_tab_ext = xstrdup (spec_file_prefix);
ae404801
AD
270 }
271 else if (yacc_flag)
272 {
273 /* If --yacc, then the output is `y.tab.c'. */
2b81e969
AD
274 dir_prefix = "";
275 all_but_tab_ext = "y";
ae404801
AD
276 }
277 else
278 {
2b81e969 279 /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
8c165d89 280 grammar: `foo/bar.yy' => `bar'. */
2b81e969
AD
281 dir_prefix = "";
282 all_but_tab_ext =
8c165d89
AD
283 xstrndup (base,
284 (strlen (base) - (ext ? strlen (ext) : 0)));
ae404801 285 }
9b3add5b 286
2b81e969 287 all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
ae404801 288
d891bc49 289 /* Compute the extensions from the grammar file name. */
5e5d5415 290 if (ext && !yacc_flag)
ae404801 291 compute_exts_from_gf (ext);
54bd0db4 292 }
19c50364
AD
293}
294
053658d5
PE
295
296/* Compute the output file names. Warn if we detect conflicting
297 outputs to the same file. */
342b8b6e
AD
298
299void
300compute_output_file_names (void)
301{
053658d5
PE
302 char const *name[4];
303 int i;
304 int j;
305 int names = 0;
306
2b81e969 307 compute_file_name_parts ();
342b8b6e
AD
308
309 /* If not yet done. */
310 if (!src_extension)
311 src_extension = ".c";
312 if (!header_extension)
313 header_extension = ".h";
fdbcd8e2 314
053658d5 315 name[names++] = parser_file_name =
2b81e969 316 spec_outfile ? spec_outfile : concat2 (all_but_ext, src_extension);
fdbcd8e2 317
053658d5
PE
318 if (defines_flag)
319 {
320 if (! spec_defines_file)
2b81e969 321 spec_defines_file = concat2 (all_but_ext, header_extension);
053658d5
PE
322 name[names++] = spec_defines_file;
323 }
342b8b6e 324
053658d5
PE
325 if (graph_flag)
326 {
327 if (! spec_graph_file)
2b81e969 328 spec_graph_file = concat2 (all_but_tab_ext, ".vcg");
053658d5
PE
329 name[names++] = spec_graph_file;
330 }
331
332 if (report_flag)
333 {
2b81e969 334 spec_verbose_file = concat2 (all_but_tab_ext, OUTPUT_EXT);
053658d5
PE
335 name[names++] = spec_verbose_file;
336 }
342b8b6e 337
053658d5
PE
338 for (j = 0; j < names; j++)
339 for (i = 0; i < j; i++)
340 if (strcmp (name[i], name[j]) == 0)
341 warn (_("conflicting outputs to file %s"), quote (name[i]));
342b8b6e 342}