]> git.saurik.com Git - bison.git/blame - src/files.c
* src/files.c: Include "stdio-safer.h"; this fixes a typo in
[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). */
7333d403 69const char *src_extension = NULL;
f0130d39 70/* Header file extension (if option ``-d'' is specified). */
7333d403 71const char *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
AD
167
168/* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth
169 part, (the directory) is ranging from FILENAME to the char before
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
178 None are allocated, they are simply pointers to parts of FILENAME.
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
197filename_split (const char *filename,
198 const char **base, const char **tab, const char **ext)
199{
200 *base = base_name (filename);
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
AD
220/* FIXME: Should use xstrndup. */
221
222static void
27110317 223compute_base_names (void)
54bd0db4 224{
ae404801 225 const char *base, *tab, *ext;
b0ce6046 226
19c50364 227 /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c),
053658d5 228 FULL_BASE_NAME and SHORT_BASE_NAME are `foo'.
54bd0db4 229
053658d5
PE
230 If --output=foo.tab.c was specified, FULL_BASE_NAME is `foo.tab'
231 and SHORT_BASE_NAME is `foo'.
19c50364
AD
232
233 The precise -o name will be used for FTABLE. For other output
234 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
235 if (spec_outfile)
236 {
ae404801
AD
237 filename_split (spec_outfile, &base, &tab, &ext);
238
239 /* The full base name goes up the EXT, excluding it. */
240 full_base_name =
241 xstrndup (spec_outfile,
242 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 243
ae404801
AD
244 /* The short base name goes up to TAB, excluding it. */
245 short_base_name =
246 xstrndup (spec_outfile,
247 (strlen (spec_outfile)
248 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
249
ae404801
AD
250 if (ext)
251 compute_exts_from_src (ext);
54bd0db4 252 }
19c50364 253
ae404801
AD
254 /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab'
255 and SHORT_BASE_NAME = `foo'.
19c50364
AD
256
257 Construct names from it. */
ae404801 258 else
54bd0db4 259 {
ae404801
AD
260 if (spec_file_prefix)
261 {
262 /* If --file-prefix=foo was specified, SHORT_BASE_NAME =
263 `foo'. */
264 short_base_name = xstrdup (spec_file_prefix);
265 }
266 else if (yacc_flag)
267 {
268 /* If --yacc, then the output is `y.tab.c'. */
269 short_base_name = xstrdup ("y");
270 }
271 else
272 {
273 /* Otherwise, the short base name is computed from the input
8c165d89 274 grammar: `foo/bar.yy' => `bar'. */
95612cfa 275 filename_split (grammar_file, &base, &tab, &ext);
ae404801 276 short_base_name =
8c165d89
AD
277 xstrndup (base,
278 (strlen (base) - (ext ? strlen (ext) : 0)));
ae404801 279 }
9b3add5b 280
82129ef5 281 full_base_name = xmalloc (strlen (short_base_name)
6d441fc3
PE
282 + strlen (TAB_EXT) + 1);
283 stpcpy (stpcpy (full_base_name, short_base_name), TAB_EXT);
ae404801 284
d891bc49 285 /* Compute the extensions from the grammar file name. */
95612cfa 286 filename_split (grammar_file, &base, &tab, &ext);
5e5d5415 287 if (ext && !yacc_flag)
ae404801 288 compute_exts_from_gf (ext);
54bd0db4 289 }
19c50364
AD
290}
291
053658d5
PE
292
293/* Compute the output file names. Warn if we detect conflicting
294 outputs to the same file. */
342b8b6e
AD
295
296void
297compute_output_file_names (void)
298{
053658d5
PE
299 char const *name[4];
300 int i;
301 int j;
302 int names = 0;
303
342b8b6e
AD
304 compute_base_names ();
305
306 /* If not yet done. */
307 if (!src_extension)
308 src_extension = ".c";
309 if (!header_extension)
310 header_extension = ".h";
fdbcd8e2 311
053658d5 312 name[names++] = parser_file_name =
6d441fc3 313 spec_outfile ? spec_outfile : concat2 (full_base_name, src_extension);
fdbcd8e2 314
053658d5
PE
315 if (defines_flag)
316 {
317 if (! spec_defines_file)
318 spec_defines_file = concat2 (full_base_name, header_extension);
319 name[names++] = spec_defines_file;
320 }
342b8b6e 321
053658d5
PE
322 if (graph_flag)
323 {
324 if (! spec_graph_file)
325 spec_graph_file = concat2 (short_base_name, ".vcg");
326 name[names++] = spec_graph_file;
327 }
328
329 if (report_flag)
330 {
331 spec_verbose_file = concat2 (short_base_name, OUTPUT_EXT);
332 name[names++] = spec_verbose_file;
333 }
342b8b6e 334
053658d5
PE
335 for (j = 0; j < names; j++)
336 for (i = 0; i < j; i++)
337 if (strcmp (name[i], name[j]) == 0)
338 warn (_("conflicting outputs to file %s"), quote (name[i]));
342b8b6e 339}