]> git.saurik.com Git - bison.git/blame - src/files.c
(EXTRA_DIST): Avoid +=, a GNU make extension.
[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}
d8880f69 137
d8880f69 138
ff61dabd
AD
139/*------------------------------------------------------------------.
140| Return the path to the skeleton which locaction might be given in |
b0ce6046 141| ENVVAR, otherwise return SKELETON_NAME. |
ff61dabd
AD
142`------------------------------------------------------------------*/
143
144const char *
b0ce6046 145skeleton_find (const char *envvar, const char *skeleton_name)
9311529b
AD
146{
147 const char *res = getenv (envvar);
148
342b8b6e 149#if defined (MSDOS) || defined (_WIN32)
bec30531 150 const char *cp = getenv ("INIT");
342b8b6e 151 if (!res)
9311529b 152 {
342b8b6e 153 /* Skeleton file name without path */
5e147124 154 const char *skel_name = strrchr (skeleton_name, '/');
342b8b6e 155 if (!skel_name)
5e147124 156 skel_name = strrchr (skeleton_name, '\\');
342b8b6e
AD
157 if (!skel_name)
158 skel_name = skeleton_name;
159 else
160 ++skel_name;
161
162 /* File doesn't exist in current directory; try in INIT directory. */
342b8b6e
AD
163 if (cp)
164 {
165 res = XMALLOC (char, strlen (cp) + strlen (skel_name) + 2);
166 sprintf (res, "%s%c%s", cp, '\\', skel_name);
167 }
168 else if (access (skel_name, 4) == 0) /* Look in current dir. */
169 res = skel_name;
170 else
171 {
172 /* Look in program locations dir. */
173 extern char *program_name;
174 cp = strrchr(program_name, '\\');
175 if (!cp)
176 return skeleton_name;
177 else
178 ++cp;
179 res = XMALLOC (char, cp - program_name + strlen (skel_name) + 1);
180 strncpy (res, program_name, cp - program_name);
181 strcpy (res + (cp - program_name), skel_name);
182 }
9311529b 183 }
342b8b6e 184#endif /* defined (MSDOS) || defined (_WIN32) */
9311529b 185 if (!res)
b0ce6046 186 res = skeleton_name;
9311529b
AD
187
188 return res;
189}
cfe5fbc0 190\f
f0130d39 191
234a3be3
AD
192/*----------------------------------------------------------------.
193| Compute BASE_NAME, SHORT_BASE_NAME and output files extensions. |
194`----------------------------------------------------------------*/
195
b0ce6046 196/* Replace all characters FROM by TO in the string IN.
f0130d39 197 and returns a new allocated string. */
234a3be3 198static char *
f0130d39 199tr (const char *in, char from, char to)
234a3be3
AD
200{
201 char *temp;
202 char *out;
b0ce6046 203
234a3be3
AD
204 out = XMALLOC (char, strlen (in) + 1);
205
206 for (temp = out; *in; in++, out++)
207 if (*in == from)
208 *out = to;
209 else
210 *out = *in;
211 *out = 0;
212 return (temp);
213}
214
234a3be3
AD
215/* Computes extensions from the grammar file extension. */
216static void
f0130d39 217compute_exts_from_gf (const char *ext)
234a3be3 218{
342b8b6e
AD
219 src_extension = tr (ext, 'y', 'c');
220 src_extension = tr (src_extension, 'Y', 'C');
221 header_extension = tr (ext, 'y', 'h');
222 header_extension = tr (header_extension, 'Y', 'H');
234a3be3
AD
223}
224
225/* Computes extensions from the given c source file extension. */
226static void
f0130d39 227compute_exts_from_src (const char *ext)
234a3be3 228{
4ecbf796
MA
229 /* We use this function when the user specifies `-o' or `--output',
230 so the extenions must be computed unconditionally from the file name
231 given by this option. */
f0130d39
AD
232 src_extension = xstrdup (ext);
233 header_extension = tr (ext, 'c', 'h');
234 header_extension = tr (header_extension, 'C', 'H');
234a3be3 235}
d8880f69 236
ae404801
AD
237
238/* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth
239 part, (the directory) is ranging from FILENAME to the char before
240 *BASE, so we don't need an additional parameter.
241
242 *EXT points to the last period in the basename, or NULL if none.
243
244 If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
245 `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
246 cannot be equal to *BASE.
247
248 None are allocated, they are simply pointers to parts of FILENAME.
249 Examples:
250
251 '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
252 '.c'
253
254 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
255
256 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
257
258 '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
259
260 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
261
262 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
263
264 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */
265
266static void
267filename_split (const char *filename,
268 const char **base, const char **tab, const char **ext)
269{
270 *base = base_name (filename);
271
272 /* Look for the extension, i.e., look for the last dot. */
273 *ext = strrchr (*base, '.');
274 *tab = NULL;
275
276 /* If there is an exentension, check if there is a `.tab' part right
277 before. */
278 if (*ext
cae60122 279 && (*ext - *base) > (int) strlen (".tab")
ae404801
AD
280 && (!strncmp (*ext - strlen (".tab"), ".tab", strlen (".tab"))
281 || !strncmp (*ext - strlen ("_tab"), "_tab", strlen ("_tab"))))
282 *tab = *ext - strlen (".tab");
283}
284
285
19c50364
AD
286/* FIXME: Should use xstrndup. */
287
288static void
27110317 289compute_base_names (void)
54bd0db4 290{
ae404801 291 const char *base, *tab, *ext;
b0ce6046 292
19c50364
AD
293 /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c),
294 BASE_NAME and SHORT_BASE_NAME are `foo'.
54bd0db4 295
19c50364
AD
296 If --output=foo.tab.c was specified, BASE_NAME is `foo.tab' and
297 SHORT_BASE_NAME is `foo'.
298
299 The precise -o name will be used for FTABLE. For other output
300 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
301 if (spec_outfile)
302 {
ae404801
AD
303 filename_split (spec_outfile, &base, &tab, &ext);
304
305 /* The full base name goes up the EXT, excluding it. */
306 full_base_name =
307 xstrndup (spec_outfile,
308 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 309
ae404801
AD
310 /* The short base name goes up to TAB, excluding it. */
311 short_base_name =
312 xstrndup (spec_outfile,
313 (strlen (spec_outfile)
314 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
315
b85810ae
AD
316 if (tab)
317 output_infix = xstrndup (tab,
318 (strlen (tab) - (ext ? strlen (ext) : 0)));
ae404801
AD
319
320 if (ext)
321 compute_exts_from_src (ext);
54bd0db4 322 }
19c50364 323
ae404801
AD
324 /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab'
325 and SHORT_BASE_NAME = `foo'.
19c50364
AD
326
327 Construct names from it. */
ae404801 328 else
54bd0db4 329 {
ae404801
AD
330 if (spec_file_prefix)
331 {
332 /* If --file-prefix=foo was specified, SHORT_BASE_NAME =
333 `foo'. */
334 short_base_name = xstrdup (spec_file_prefix);
335 }
336 else if (yacc_flag)
337 {
338 /* If --yacc, then the output is `y.tab.c'. */
339 short_base_name = xstrdup ("y");
340 }
341 else
342 {
343 /* Otherwise, the short base name is computed from the input
8c165d89 344 grammar: `foo/bar.yy' => `bar'. */
ae404801
AD
345 filename_split (infile, &base, &tab, &ext);
346 short_base_name =
8c165d89
AD
347 xstrndup (base,
348 (strlen (base) - (ext ? strlen (ext) : 0)));
ae404801 349 }
9b3add5b 350
ae404801 351 /* In these cases, always append `.tab'. */
b85810ae
AD
352 output_infix = xstrdup (EXT_TAB);
353
ae404801
AD
354 full_base_name = XMALLOC (char,
355 strlen (short_base_name)
356 + strlen (EXT_TAB) + 1);
357 stpcpy (stpcpy (full_base_name, short_base_name), EXT_TAB);
358
359 /* Computes the extensions from the grammar file name. */
360 filename_split (infile, &base, &tab, &ext);
5e5d5415 361 if (ext && !yacc_flag)
ae404801 362 compute_exts_from_gf (ext);
54bd0db4 363 }
19c50364
AD
364}
365
342b8b6e
AD
366/*-------------------------------------------------------.
367| Close the open files, compute the output files names. |
368`-------------------------------------------------------*/
369
370void
371compute_output_file_names (void)
372{
373 compute_base_names ();
374
375 /* If not yet done. */
376 if (!src_extension)
377 src_extension = ".c";
378 if (!header_extension)
379 header_extension = ".h";
fdbcd8e2 380
fc6edc45
MA
381 parser_file_name =
382 spec_outfile ? spec_outfile : stringappend (full_base_name, src_extension);
fdbcd8e2 383
342b8b6e
AD
384 /* It the defines filename if not given, we create it. */
385 if (!spec_defines_file)
ae404801 386 spec_defines_file = stringappend (full_base_name, header_extension);
342b8b6e
AD
387
388 /* It the graph filename if not given, we create it. */
389 if (!spec_graph_file)
390 spec_graph_file = stringappend (short_base_name, ".vcg");
391
392 spec_verbose_file = stringappend (short_base_name, EXT_OUTPUT);
342b8b6e 393}