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