]> git.saurik.com Git - bison.git/blame - src/files.c
Regen.
[bison.git] / src / files.c
CommitLineData
54bd0db4 1/* Open and close files for bison,
592e8d4d 2 Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002
b85810ae 3 Free Software Foundation, Inc.
54bd0db4 4
ceed8467 5 This file is part of Bison, the GNU Compiler Compiler.
54bd0db4 6
ceed8467
AD
7 Bison is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
54bd0db4 11
ceed8467
AD
12 Bison is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
54bd0db4 16
ceed8467
AD
17 You should have received a copy of the GNU General Public License
18 along with Bison; see the file COPYING. If not, write to the Free
19 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
54bd0db4
RS
21
22
9eceb6c6 23#include "system.h"
ceed8467 24#include "getargs.h"
54bd0db4 25#include "files.h"
54bd0db4 26#include "gram.h"
26cfe0be 27#include "error.h"
a0f6b076 28#include "complain.h"
54bd0db4 29
ae404801 30/* From basename.c. Almost a lie, as it returns a char *. */
d33cb3ae 31const char *base_name (char const *name);
ae404801 32
54bd0db4 33FILE *finput = NULL;
54bd0db4 34
0dd1580a
RA
35struct obstack pre_prologue_obstack;
36struct obstack post_prologue_obstack;
8c7ebe49 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
b0ce6046 45char *spec_outfile = NULL; /* for -o. */
f0130d39 46char *spec_file_prefix = NULL; /* for -b. */
b5b61c61 47const char *spec_name_prefix = NULL; /* for -p. */
342b8b6e
AD
48char *spec_verbose_file = NULL; /* for --verbose. */
49char *spec_graph_file = NULL; /* for -g. */
50char *spec_defines_file = NULL; /* for --defines. */
ea52d706 51char *parser_file_name = NULL;
54bd0db4 52
b0ce6046 53char *infile = NULL;
4a120d45 54
ae404801 55static char *full_base_name = NULL;
b85810ae
AD
56
57/* Prefix used to generate output file names. */
9b3add5b 58char *short_base_name = NULL;
27110317 59
b85810ae
AD
60/* Infix used to generate output file names (i.e., `.tab', or `_tab',
61 or `'). */
62char *output_infix = NULL;
63
f0130d39 64/* C source file extension (the parser source). */
7333d403 65const char *src_extension = NULL;
f0130d39 66/* Header file extension (if option ``-d'' is specified). */
7333d403 67const char *header_extension = NULL;
54bd0db4 68\f
f0130d39 69
19c50364
AD
70/*--------------------------.
71| Is SUFFIX ending STRING? |
72`--------------------------*/
73
9b3add5b 74int
19c50364
AD
75strsuffix (const char *string, const char *suffix)
76{
77 size_t string_len = strlen (string);
78 size_t suffix_len = strlen (suffix);
79 if (suffix_len <= string_len)
80 return !strcmp (string + string_len - suffix_len, suffix);
81 else
82 return 0;
83}
84
85
358c15b7
AD
86/*-----------------------------------------------------------------.
87| Return a newly allocated string composed of the concatenation of |
19c50364 88| STRING1, and STRING2. |
358c15b7 89`-----------------------------------------------------------------*/
54bd0db4 90
9b3add5b 91char*
19c50364 92stringappend (const char *string1, const char *string2)
54bd0db4 93{
19c50364
AD
94 size_t len = strlen (string1) + strlen (string2);
95 char *res = XMALLOC (char, len + 1);
358c15b7 96 char *cp;
19c50364
AD
97 cp = stpcpy (res, string1);
98 cp = stpcpy (cp, string2);
358c15b7 99 return res;
54bd0db4
RS
100}
101
cfe5fbc0
AD
102/*-----------------------------------------------------------------.
103| Try to open file NAME with mode MODE, and print an error message |
104| if fails. |
105`-----------------------------------------------------------------*/
54bd0db4 106
ff61dabd 107FILE *
8963a27b 108xfopen (const char *name, const char *mode)
cfe5fbc0 109{
8963a27b 110 FILE *ptr;
cfe5fbc0
AD
111
112 ptr = fopen (name, mode);
113 if (!ptr)
901ec153 114 error (EXIT_FAILURE, errno, _("cannot open file `%s'"), name);
cfe5fbc0
AD
115
116 return ptr;
117}
118
119/*-------------------------------------------------------------.
120| Try to close file PTR, and print an error message if fails. |
121`-------------------------------------------------------------*/
122
e63ee1f1 123void
8963a27b 124xfclose (FILE *ptr)
cfe5fbc0 125{
cfe5fbc0 126 if (ptr == NULL)
e63ee1f1 127 return;
cfe5fbc0 128
e63ee1f1
PE
129 if (ferror (ptr))
130 error (EXIT_FAILURE, 0, _("I/O error"));
cfe5fbc0 131
e63ee1f1
PE
132 if (fclose (ptr) != 0)
133 error (EXIT_FAILURE, errno, _("cannot close file"));
cfe5fbc0
AD
134}
135\f
f0130d39 136
234a3be3
AD
137/*----------------------------------------------------------------.
138| Compute BASE_NAME, SHORT_BASE_NAME and output files extensions. |
139`----------------------------------------------------------------*/
140
b0ce6046 141/* Replace all characters FROM by TO in the string IN.
f0130d39 142 and returns a new allocated string. */
234a3be3 143static char *
f0130d39 144tr (const char *in, char from, char to)
234a3be3
AD
145{
146 char *temp;
147 char *out;
b0ce6046 148
234a3be3
AD
149 out = XMALLOC (char, strlen (in) + 1);
150
151 for (temp = out; *in; in++, out++)
152 if (*in == from)
153 *out = to;
154 else
155 *out = *in;
156 *out = 0;
157 return (temp);
158}
159
234a3be3
AD
160/* Computes extensions from the grammar file extension. */
161static void
f0130d39 162compute_exts_from_gf (const char *ext)
234a3be3 163{
342b8b6e
AD
164 src_extension = tr (ext, 'y', 'c');
165 src_extension = tr (src_extension, 'Y', 'C');
166 header_extension = tr (ext, 'y', 'h');
167 header_extension = tr (header_extension, 'Y', 'H');
234a3be3
AD
168}
169
170/* Computes extensions from the given c source file extension. */
171static void
f0130d39 172compute_exts_from_src (const char *ext)
234a3be3 173{
4ecbf796
MA
174 /* We use this function when the user specifies `-o' or `--output',
175 so the extenions must be computed unconditionally from the file name
176 given by this option. */
f0130d39
AD
177 src_extension = xstrdup (ext);
178 header_extension = tr (ext, 'c', 'h');
179 header_extension = tr (header_extension, 'C', 'H');
234a3be3 180}
d8880f69 181
ae404801
AD
182
183/* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth
184 part, (the directory) is ranging from FILENAME to the char before
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
193 None are allocated, they are simply pointers to parts of FILENAME.
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
212filename_split (const char *filename,
213 const char **base, const char **tab, const char **ext)
214{
215 *base = base_name (filename);
216
217 /* Look for the extension, i.e., look for the last dot. */
218 *ext = strrchr (*base, '.');
219 *tab = NULL;
220
221 /* If there is an exentension, check if there is a `.tab' part right
222 before. */
223 if (*ext
cae60122 224 && (*ext - *base) > (int) strlen (".tab")
ae404801
AD
225 && (!strncmp (*ext - strlen (".tab"), ".tab", strlen (".tab"))
226 || !strncmp (*ext - strlen ("_tab"), "_tab", strlen ("_tab"))))
227 *tab = *ext - strlen (".tab");
228}
229
230
19c50364
AD
231/* FIXME: Should use xstrndup. */
232
233static void
27110317 234compute_base_names (void)
54bd0db4 235{
ae404801 236 const char *base, *tab, *ext;
b0ce6046 237
19c50364
AD
238 /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c),
239 BASE_NAME and SHORT_BASE_NAME are `foo'.
54bd0db4 240
19c50364
AD
241 If --output=foo.tab.c was specified, BASE_NAME is `foo.tab' and
242 SHORT_BASE_NAME is `foo'.
243
244 The precise -o name will be used for FTABLE. For other output
245 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
246 if (spec_outfile)
247 {
ae404801
AD
248 filename_split (spec_outfile, &base, &tab, &ext);
249
250 /* The full base name goes up the EXT, excluding it. */
251 full_base_name =
252 xstrndup (spec_outfile,
253 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 254
ae404801
AD
255 /* The short base name goes up to TAB, excluding it. */
256 short_base_name =
257 xstrndup (spec_outfile,
258 (strlen (spec_outfile)
259 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
260
b85810ae
AD
261 if (tab)
262 output_infix = xstrndup (tab,
263 (strlen (tab) - (ext ? strlen (ext) : 0)));
ae404801
AD
264
265 if (ext)
266 compute_exts_from_src (ext);
54bd0db4 267 }
19c50364 268
ae404801
AD
269 /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab'
270 and SHORT_BASE_NAME = `foo'.
19c50364
AD
271
272 Construct names from it. */
ae404801 273 else
54bd0db4 274 {
ae404801
AD
275 if (spec_file_prefix)
276 {
277 /* If --file-prefix=foo was specified, SHORT_BASE_NAME =
278 `foo'. */
279 short_base_name = xstrdup (spec_file_prefix);
280 }
281 else if (yacc_flag)
282 {
283 /* If --yacc, then the output is `y.tab.c'. */
284 short_base_name = xstrdup ("y");
285 }
286 else
287 {
288 /* Otherwise, the short base name is computed from the input
8c165d89 289 grammar: `foo/bar.yy' => `bar'. */
ae404801
AD
290 filename_split (infile, &base, &tab, &ext);
291 short_base_name =
8c165d89
AD
292 xstrndup (base,
293 (strlen (base) - (ext ? strlen (ext) : 0)));
ae404801 294 }
9b3add5b 295
ae404801 296 /* In these cases, always append `.tab'. */
b85810ae
AD
297 output_infix = xstrdup (EXT_TAB);
298
ae404801
AD
299 full_base_name = XMALLOC (char,
300 strlen (short_base_name)
301 + strlen (EXT_TAB) + 1);
302 stpcpy (stpcpy (full_base_name, short_base_name), EXT_TAB);
303
304 /* Computes the extensions from the grammar file name. */
305 filename_split (infile, &base, &tab, &ext);
5e5d5415 306 if (ext && !yacc_flag)
ae404801 307 compute_exts_from_gf (ext);
54bd0db4 308 }
19c50364
AD
309}
310
342b8b6e
AD
311/*-------------------------------------------------------.
312| Close the open files, compute the output files names. |
313`-------------------------------------------------------*/
314
315void
316compute_output_file_names (void)
317{
318 compute_base_names ();
319
320 /* If not yet done. */
321 if (!src_extension)
322 src_extension = ".c";
323 if (!header_extension)
324 header_extension = ".h";
fdbcd8e2 325
fc6edc45
MA
326 parser_file_name =
327 spec_outfile ? spec_outfile : stringappend (full_base_name, src_extension);
fdbcd8e2 328
342b8b6e
AD
329 /* It the defines filename if not given, we create it. */
330 if (!spec_defines_file)
ae404801 331 spec_defines_file = stringappend (full_base_name, header_extension);
342b8b6e
AD
332
333 /* It the graph filename if not given, we create it. */
334 if (!spec_graph_file)
335 spec_graph_file = stringappend (short_base_name, ".vcg");
336
337 spec_verbose_file = stringappend (short_base_name, EXT_OUTPUT);
342b8b6e 338}