]> git.saurik.com Git - bison.git/blame - src/files.c
(yylineno, yyoutname): Remove static vars, replacing
[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
f0130d39 60/* C source file extension (the parser source). */
7333d403 61const char *src_extension = NULL;
f0130d39 62/* Header file extension (if option ``-d'' is specified). */
7333d403 63const char *header_extension = NULL;
54bd0db4 64\f
f0130d39 65
19c50364
AD
66/*--------------------------.
67| Is SUFFIX ending STRING? |
68`--------------------------*/
69
9b3add5b 70int
19c50364
AD
71strsuffix (const char *string, const char *suffix)
72{
73 size_t string_len = strlen (string);
74 size_t suffix_len = strlen (suffix);
75 if (suffix_len <= string_len)
76 return !strcmp (string + string_len - suffix_len, suffix);
77 else
78 return 0;
79}
80
81
358c15b7
AD
82/*-----------------------------------------------------------------.
83| Return a newly allocated string composed of the concatenation of |
19c50364 84| STRING1, and STRING2. |
358c15b7 85`-----------------------------------------------------------------*/
54bd0db4 86
9b3add5b 87char*
19c50364 88stringappend (const char *string1, const char *string2)
54bd0db4 89{
19c50364
AD
90 size_t len = strlen (string1) + strlen (string2);
91 char *res = XMALLOC (char, len + 1);
358c15b7 92 char *cp;
19c50364
AD
93 cp = stpcpy (res, string1);
94 cp = stpcpy (cp, string2);
358c15b7 95 return res;
54bd0db4
RS
96}
97
cfe5fbc0
AD
98/*-----------------------------------------------------------------.
99| Try to open file NAME with mode MODE, and print an error message |
100| if fails. |
101`-----------------------------------------------------------------*/
54bd0db4 102
ff61dabd 103FILE *
8963a27b 104xfopen (const char *name, const char *mode)
cfe5fbc0 105{
8963a27b 106 FILE *ptr;
cfe5fbc0
AD
107
108 ptr = fopen (name, mode);
109 if (!ptr)
901ec153 110 error (EXIT_FAILURE, errno, _("cannot open file `%s'"), name);
cfe5fbc0
AD
111
112 return ptr;
113}
114
115/*-------------------------------------------------------------.
116| Try to close file PTR, and print an error message if fails. |
117`-------------------------------------------------------------*/
118
e63ee1f1 119void
8963a27b 120xfclose (FILE *ptr)
cfe5fbc0 121{
cfe5fbc0 122 if (ptr == NULL)
e63ee1f1 123 return;
cfe5fbc0 124
e63ee1f1
PE
125 if (ferror (ptr))
126 error (EXIT_FAILURE, 0, _("I/O error"));
cfe5fbc0 127
e63ee1f1
PE
128 if (fclose (ptr) != 0)
129 error (EXIT_FAILURE, errno, _("cannot close file"));
cfe5fbc0
AD
130}
131\f
f0130d39 132
234a3be3
AD
133/*----------------------------------------------------------------.
134| Compute BASE_NAME, SHORT_BASE_NAME and output files extensions. |
135`----------------------------------------------------------------*/
136
b0ce6046 137/* Replace all characters FROM by TO in the string IN.
f0130d39 138 and returns a new allocated string. */
234a3be3 139static char *
f0130d39 140tr (const char *in, char from, char to)
234a3be3
AD
141{
142 char *temp;
143 char *out;
b0ce6046 144
234a3be3
AD
145 out = XMALLOC (char, strlen (in) + 1);
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
234a3be3
AD
156/* Computes extensions from the grammar file extension. */
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
166/* Computes extensions from the given c source file extension. */
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
AD
178
179/* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth
180 part, (the directory) is ranging from FILENAME to the char before
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
189 None are allocated, they are simply pointers to parts of FILENAME.
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
208filename_split (const char *filename,
209 const char **base, const char **tab, const char **ext)
210{
211 *base = base_name (filename);
212
213 /* Look for the extension, i.e., look for the last dot. */
214 *ext = strrchr (*base, '.');
215 *tab = NULL;
216
217 /* If there is an exentension, check if there is a `.tab' part right
218 before. */
219 if (*ext
cae60122 220 && (*ext - *base) > (int) strlen (".tab")
ae404801
AD
221 && (!strncmp (*ext - strlen (".tab"), ".tab", strlen (".tab"))
222 || !strncmp (*ext - strlen ("_tab"), "_tab", strlen ("_tab"))))
223 *tab = *ext - strlen (".tab");
224}
225
226
19c50364
AD
227/* FIXME: Should use xstrndup. */
228
229static void
27110317 230compute_base_names (void)
54bd0db4 231{
ae404801 232 const char *base, *tab, *ext;
b0ce6046 233
19c50364
AD
234 /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c),
235 BASE_NAME and SHORT_BASE_NAME are `foo'.
54bd0db4 236
19c50364
AD
237 If --output=foo.tab.c was specified, BASE_NAME is `foo.tab' and
238 SHORT_BASE_NAME is `foo'.
239
240 The precise -o name will be used for FTABLE. For other output
241 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
242 if (spec_outfile)
243 {
ae404801
AD
244 filename_split (spec_outfile, &base, &tab, &ext);
245
246 /* The full base name goes up the EXT, excluding it. */
247 full_base_name =
248 xstrndup (spec_outfile,
249 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 250
ae404801
AD
251 /* The short base name goes up to TAB, excluding it. */
252 short_base_name =
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 }
19c50364 260
ae404801
AD
261 /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab'
262 and SHORT_BASE_NAME = `foo'.
19c50364
AD
263
264 Construct names from it. */
ae404801 265 else
54bd0db4 266 {
ae404801
AD
267 if (spec_file_prefix)
268 {
269 /* If --file-prefix=foo was specified, SHORT_BASE_NAME =
270 `foo'. */
271 short_base_name = xstrdup (spec_file_prefix);
272 }
273 else if (yacc_flag)
274 {
275 /* If --yacc, then the output is `y.tab.c'. */
276 short_base_name = xstrdup ("y");
277 }
278 else
279 {
280 /* Otherwise, the short base name is computed from the input
8c165d89 281 grammar: `foo/bar.yy' => `bar'. */
ae404801
AD
282 filename_split (infile, &base, &tab, &ext);
283 short_base_name =
8c165d89
AD
284 xstrndup (base,
285 (strlen (base) - (ext ? strlen (ext) : 0)));
ae404801 286 }
9b3add5b 287
ae404801
AD
288 full_base_name = XMALLOC (char,
289 strlen (short_base_name)
290 + strlen (EXT_TAB) + 1);
291 stpcpy (stpcpy (full_base_name, short_base_name), EXT_TAB);
292
293 /* Computes the extensions from the grammar file name. */
294 filename_split (infile, &base, &tab, &ext);
5e5d5415 295 if (ext && !yacc_flag)
ae404801 296 compute_exts_from_gf (ext);
54bd0db4 297 }
19c50364
AD
298}
299
342b8b6e
AD
300/*-------------------------------------------------------.
301| Close the open files, compute the output files names. |
302`-------------------------------------------------------*/
303
304void
305compute_output_file_names (void)
306{
307 compute_base_names ();
308
309 /* If not yet done. */
310 if (!src_extension)
311 src_extension = ".c";
312 if (!header_extension)
313 header_extension = ".h";
fdbcd8e2 314
fc6edc45
MA
315 parser_file_name =
316 spec_outfile ? spec_outfile : stringappend (full_base_name, src_extension);
fdbcd8e2 317
342b8b6e
AD
318 /* It the defines filename if not given, we create it. */
319 if (!spec_defines_file)
ae404801 320 spec_defines_file = stringappend (full_base_name, header_extension);
342b8b6e
AD
321
322 /* It the graph filename if not given, we create it. */
323 if (!spec_graph_file)
324 spec_graph_file = stringappend (short_base_name, ".vcg");
325
326 spec_verbose_file = stringappend (short_base_name, EXT_OUTPUT);
342b8b6e 327}