]> git.saurik.com Git - bison.git/blame - src/files.c
Add lib/subpipe.c.
[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
AD
30/* From basename.c. Almost a lie, as it returns a char *. */
31const char *base_name PARAMS ((char const *name));
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)
114 error (2, errno, _("cannot open file `%s'"), name);
115
116 return ptr;
117}
118
119/*-------------------------------------------------------------.
120| Try to close file PTR, and print an error message if fails. |
121`-------------------------------------------------------------*/
122
ff61dabd 123int
8963a27b 124xfclose (FILE *ptr)
cfe5fbc0
AD
125{
126 int result;
127
128 if (ptr == NULL)
129 return 0;
130
131 result = fclose (ptr);
132 if (result == EOF)
133 error (2, errno, _("cannot close file"));
134
135 return result;
136}
137\f
f0130d39 138
234a3be3
AD
139/*----------------------------------------------------------------.
140| Compute BASE_NAME, SHORT_BASE_NAME and output files extensions. |
141`----------------------------------------------------------------*/
142
b0ce6046 143/* Replace all characters FROM by TO in the string IN.
f0130d39 144 and returns a new allocated string. */
234a3be3 145static char *
f0130d39 146tr (const char *in, char from, char to)
234a3be3
AD
147{
148 char *temp;
149 char *out;
b0ce6046 150
234a3be3
AD
151 out = XMALLOC (char, strlen (in) + 1);
152
153 for (temp = out; *in; in++, out++)
154 if (*in == from)
155 *out = to;
156 else
157 *out = *in;
158 *out = 0;
159 return (temp);
160}
161
234a3be3
AD
162/* Computes extensions from the grammar file extension. */
163static void
f0130d39 164compute_exts_from_gf (const char *ext)
234a3be3 165{
342b8b6e
AD
166 src_extension = tr (ext, 'y', 'c');
167 src_extension = tr (src_extension, 'Y', 'C');
168 header_extension = tr (ext, 'y', 'h');
169 header_extension = tr (header_extension, 'Y', 'H');
234a3be3
AD
170}
171
172/* Computes extensions from the given c source file extension. */
173static void
f0130d39 174compute_exts_from_src (const char *ext)
234a3be3 175{
4ecbf796
MA
176 /* We use this function when the user specifies `-o' or `--output',
177 so the extenions must be computed unconditionally from the file name
178 given by this option. */
f0130d39
AD
179 src_extension = xstrdup (ext);
180 header_extension = tr (ext, 'c', 'h');
181 header_extension = tr (header_extension, 'C', 'H');
234a3be3 182}
d8880f69 183
ae404801
AD
184
185/* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth
186 part, (the directory) is ranging from FILENAME to the char before
187 *BASE, so we don't need an additional parameter.
188
189 *EXT points to the last period in the basename, or NULL if none.
190
191 If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
192 `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
193 cannot be equal to *BASE.
194
195 None are allocated, they are simply pointers to parts of FILENAME.
196 Examples:
197
198 '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
199 '.c'
200
201 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
202
203 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
204
205 '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
206
207 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
208
209 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
210
211 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */
212
213static void
214filename_split (const char *filename,
215 const char **base, const char **tab, const char **ext)
216{
217 *base = base_name (filename);
218
219 /* Look for the extension, i.e., look for the last dot. */
220 *ext = strrchr (*base, '.');
221 *tab = NULL;
222
223 /* If there is an exentension, check if there is a `.tab' part right
224 before. */
225 if (*ext
cae60122 226 && (*ext - *base) > (int) strlen (".tab")
ae404801
AD
227 && (!strncmp (*ext - strlen (".tab"), ".tab", strlen (".tab"))
228 || !strncmp (*ext - strlen ("_tab"), "_tab", strlen ("_tab"))))
229 *tab = *ext - strlen (".tab");
230}
231
232
19c50364
AD
233/* FIXME: Should use xstrndup. */
234
235static void
27110317 236compute_base_names (void)
54bd0db4 237{
ae404801 238 const char *base, *tab, *ext;
b0ce6046 239
19c50364
AD
240 /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c),
241 BASE_NAME and SHORT_BASE_NAME are `foo'.
54bd0db4 242
19c50364
AD
243 If --output=foo.tab.c was specified, BASE_NAME is `foo.tab' and
244 SHORT_BASE_NAME is `foo'.
245
246 The precise -o name will be used for FTABLE. For other output
247 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
248 if (spec_outfile)
249 {
ae404801
AD
250 filename_split (spec_outfile, &base, &tab, &ext);
251
252 /* The full base name goes up the EXT, excluding it. */
253 full_base_name =
254 xstrndup (spec_outfile,
255 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 256
ae404801
AD
257 /* The short base name goes up to TAB, excluding it. */
258 short_base_name =
259 xstrndup (spec_outfile,
260 (strlen (spec_outfile)
261 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
262
b85810ae
AD
263 if (tab)
264 output_infix = xstrndup (tab,
265 (strlen (tab) - (ext ? strlen (ext) : 0)));
ae404801
AD
266
267 if (ext)
268 compute_exts_from_src (ext);
54bd0db4 269 }
19c50364 270
ae404801
AD
271 /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab'
272 and SHORT_BASE_NAME = `foo'.
19c50364
AD
273
274 Construct names from it. */
ae404801 275 else
54bd0db4 276 {
ae404801
AD
277 if (spec_file_prefix)
278 {
279 /* If --file-prefix=foo was specified, SHORT_BASE_NAME =
280 `foo'. */
281 short_base_name = xstrdup (spec_file_prefix);
282 }
283 else if (yacc_flag)
284 {
285 /* If --yacc, then the output is `y.tab.c'. */
286 short_base_name = xstrdup ("y");
287 }
288 else
289 {
290 /* Otherwise, the short base name is computed from the input
8c165d89 291 grammar: `foo/bar.yy' => `bar'. */
ae404801
AD
292 filename_split (infile, &base, &tab, &ext);
293 short_base_name =
8c165d89
AD
294 xstrndup (base,
295 (strlen (base) - (ext ? strlen (ext) : 0)));
ae404801 296 }
9b3add5b 297
ae404801 298 /* In these cases, always append `.tab'. */
b85810ae
AD
299 output_infix = xstrdup (EXT_TAB);
300
ae404801
AD
301 full_base_name = XMALLOC (char,
302 strlen (short_base_name)
303 + strlen (EXT_TAB) + 1);
304 stpcpy (stpcpy (full_base_name, short_base_name), EXT_TAB);
305
306 /* Computes the extensions from the grammar file name. */
307 filename_split (infile, &base, &tab, &ext);
5e5d5415 308 if (ext && !yacc_flag)
ae404801 309 compute_exts_from_gf (ext);
54bd0db4 310 }
19c50364
AD
311}
312
342b8b6e
AD
313/*-------------------------------------------------------.
314| Close the open files, compute the output files names. |
315`-------------------------------------------------------*/
316
317void
318compute_output_file_names (void)
319{
320 compute_base_names ();
321
322 /* If not yet done. */
323 if (!src_extension)
324 src_extension = ".c";
325 if (!header_extension)
326 header_extension = ".h";
fdbcd8e2 327
fc6edc45
MA
328 parser_file_name =
329 spec_outfile ? spec_outfile : stringappend (full_base_name, src_extension);
fdbcd8e2 330
342b8b6e
AD
331 /* It the defines filename if not given, we create it. */
332 if (!spec_defines_file)
ae404801 333 spec_defines_file = stringappend (full_base_name, header_extension);
342b8b6e
AD
334
335 /* It the graph filename if not given, we create it. */
336 if (!spec_graph_file)
337 spec_graph_file = stringappend (short_base_name, ".vcg");
338
339 spec_verbose_file = stringappend (short_base_name, EXT_OUTPUT);
342b8b6e 340}