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