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