* data/bison.simple (YYCOPY): Fix [] quoting problem in the non-GCC case.
[bison.git] / src / files.c
CommitLineData
54bd0db4 1/* Open and close files for bison,
b85810ae
AD
2 Copyright 1984, 1986, 1989, 1992, 2000, 2001, 2002
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
8c7ebe49 35struct obstack action_obstack;
ff4423cc 36struct obstack output_obstack;
0dd1580a
RA
37struct obstack pre_prologue_obstack;
38struct obstack post_prologue_obstack;
8c7ebe49 39
b5b61c61
AD
40/* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is
41 tempting, but don't do that: for the time being our handling of the
42 %directive vs --option leaves precedence to the options by deciding
43 that if a %directive sets a variable which is really set (i.e., not
44 NULL), then the %directive is ignored. As a result, %name-prefix,
45 for instance, will not be honored. */
46
b0ce6046 47char *spec_outfile = NULL; /* for -o. */
f0130d39 48char *spec_file_prefix = NULL; /* for -b. */
b5b61c61 49const char *spec_name_prefix = NULL; /* for -p. */
342b8b6e
AD
50char *spec_verbose_file = NULL; /* for --verbose. */
51char *spec_graph_file = NULL; /* for -g. */
52char *spec_defines_file = NULL; /* for --defines. */
ea52d706 53char *parser_file_name = NULL;
54bd0db4 54
b0ce6046
AD
55char *infile = NULL;
56char *attrsfile = NULL;
4a120d45 57
ae404801 58static char *full_base_name = NULL;
b85810ae
AD
59
60/* Prefix used to generate output file names. */
9b3add5b 61char *short_base_name = NULL;
27110317 62
b85810ae
AD
63/* Infix used to generate output file names (i.e., `.tab', or `_tab',
64 or `'). */
65char *output_infix = NULL;
66
f0130d39 67/* C source file extension (the parser source). */
7333d403 68const char *src_extension = NULL;
f0130d39 69/* Header file extension (if option ``-d'' is specified). */
7333d403 70const char *header_extension = NULL;
54bd0db4 71\f
f0130d39 72
19c50364
AD
73/*--------------------------.
74| Is SUFFIX ending STRING? |
75`--------------------------*/
76
9b3add5b 77int
19c50364
AD
78strsuffix (const char *string, const char *suffix)
79{
80 size_t string_len = strlen (string);
81 size_t suffix_len = strlen (suffix);
82 if (suffix_len <= string_len)
83 return !strcmp (string + string_len - suffix_len, suffix);
84 else
85 return 0;
86}
87
88
358c15b7
AD
89/*-----------------------------------------------------------------.
90| Return a newly allocated string composed of the concatenation of |
19c50364 91| STRING1, and STRING2. |
358c15b7 92`-----------------------------------------------------------------*/
54bd0db4 93
9b3add5b 94char*
19c50364 95stringappend (const char *string1, const char *string2)
54bd0db4 96{
19c50364
AD
97 size_t len = strlen (string1) + strlen (string2);
98 char *res = XMALLOC (char, len + 1);
358c15b7 99 char *cp;
19c50364
AD
100 cp = stpcpy (res, string1);
101 cp = stpcpy (cp, string2);
358c15b7 102 return res;
54bd0db4
RS
103}
104
0b8afb77 105
270a173c
AD
106/*-----------------------------------------------------------------.
107| Computes the macro name used to avoid double inclusion in the |
108| header of the parser and store it in header_macro_name. Be sure |
109| to produce valid CPP names (don't start with digit, remain |
110| alphanumerical + underscore). |
111`-----------------------------------------------------------------*/
0b8afb77 112
93ede233 113char *
0b8afb77
AD
114compute_header_macro (void)
115{
270a173c 116 const char *prefix = "BISON_";
342b8b6e 117 char *macro_name, *cp;
0b8afb77 118
342b8b6e 119 if (spec_defines_file)
270a173c
AD
120 {
121 macro_name = XMALLOC (char,
122 strlen (prefix) +
123 strlen (spec_defines_file) + 1);
124 cp = stpcpy (macro_name, prefix);
125 cp = stpcpy (cp, spec_defines_file);
126 }
342b8b6e
AD
127 else
128 {
129 macro_name = XMALLOC (char,
270a173c 130 strlen (prefix) +
ae404801 131 strlen (full_base_name) +
342b8b6e 132 strlen (header_extension) + 1);
270a173c 133 cp = stpcpy (macro_name, prefix);
ae404801 134 cp = stpcpy (cp, full_base_name);
270a173c 135 cp = stpcpy (cp, header_extension);
342b8b6e
AD
136 }
137
138 for (cp = macro_name; *cp; ++cp)
139 if (islower (*cp))
140 *cp = toupper (*cp);
141 else if (!isalnum (*cp))
142 *cp = '_';
0b8afb77 143
0b8afb77
AD
144 return macro_name;
145}
146
147
cfe5fbc0
AD
148/*-----------------------------------------------------------------.
149| Try to open file NAME with mode MODE, and print an error message |
150| if fails. |
151`-----------------------------------------------------------------*/
54bd0db4 152
ff61dabd 153FILE *
8963a27b 154xfopen (const char *name, const char *mode)
cfe5fbc0 155{
8963a27b 156 FILE *ptr;
cfe5fbc0
AD
157
158 ptr = fopen (name, mode);
159 if (!ptr)
160 error (2, errno, _("cannot open file `%s'"), name);
161
162 return ptr;
163}
164
165/*-------------------------------------------------------------.
166| Try to close file PTR, and print an error message if fails. |
167`-------------------------------------------------------------*/
168
ff61dabd 169int
8963a27b 170xfclose (FILE *ptr)
cfe5fbc0
AD
171{
172 int result;
173
174 if (ptr == NULL)
175 return 0;
176
177 result = fclose (ptr);
178 if (result == EOF)
179 error (2, errno, _("cannot close file"));
180
181 return result;
182}
d8880f69 183
d8880f69 184
ff61dabd
AD
185/*------------------------------------------------------------------.
186| Return the path to the skeleton which locaction might be given in |
b0ce6046 187| ENVVAR, otherwise return SKELETON_NAME. |
ff61dabd
AD
188`------------------------------------------------------------------*/
189
190const char *
b0ce6046 191skeleton_find (const char *envvar, const char *skeleton_name)
9311529b
AD
192{
193 const char *res = getenv (envvar);
194
342b8b6e 195#if defined (MSDOS) || defined (_WIN32)
bec30531 196 const char *cp = getenv ("INIT");
342b8b6e 197 if (!res)
9311529b 198 {
342b8b6e 199 /* Skeleton file name without path */
5e147124 200 const char *skel_name = strrchr (skeleton_name, '/');
342b8b6e 201 if (!skel_name)
5e147124 202 skel_name = strrchr (skeleton_name, '\\');
342b8b6e
AD
203 if (!skel_name)
204 skel_name = skeleton_name;
205 else
206 ++skel_name;
207
208 /* File doesn't exist in current directory; try in INIT directory. */
342b8b6e
AD
209 if (cp)
210 {
211 res = XMALLOC (char, strlen (cp) + strlen (skel_name) + 2);
212 sprintf (res, "%s%c%s", cp, '\\', skel_name);
213 }
214 else if (access (skel_name, 4) == 0) /* Look in current dir. */
215 res = skel_name;
216 else
217 {
218 /* Look in program locations dir. */
219 extern char *program_name;
220 cp = strrchr(program_name, '\\');
221 if (!cp)
222 return skeleton_name;
223 else
224 ++cp;
225 res = XMALLOC (char, cp - program_name + strlen (skel_name) + 1);
226 strncpy (res, program_name, cp - program_name);
227 strcpy (res + (cp - program_name), skel_name);
228 }
9311529b 229 }
342b8b6e 230#endif /* defined (MSDOS) || defined (_WIN32) */
9311529b 231 if (!res)
b0ce6046 232 res = skeleton_name;
9311529b
AD
233
234 return res;
235}
cfe5fbc0 236\f
f0130d39 237
234a3be3
AD
238/*----------------------------------------------------------------.
239| Compute BASE_NAME, SHORT_BASE_NAME and output files extensions. |
240`----------------------------------------------------------------*/
241
b0ce6046 242/* Replace all characters FROM by TO in the string IN.
f0130d39 243 and returns a new allocated string. */
234a3be3 244static char *
f0130d39 245tr (const char *in, char from, char to)
234a3be3
AD
246{
247 char *temp;
248 char *out;
b0ce6046 249
234a3be3
AD
250 out = XMALLOC (char, strlen (in) + 1);
251
252 for (temp = out; *in; in++, out++)
253 if (*in == from)
254 *out = to;
255 else
256 *out = *in;
257 *out = 0;
258 return (temp);
259}
260
234a3be3
AD
261/* Computes extensions from the grammar file extension. */
262static void
f0130d39 263compute_exts_from_gf (const char *ext)
234a3be3 264{
342b8b6e
AD
265 src_extension = tr (ext, 'y', 'c');
266 src_extension = tr (src_extension, 'Y', 'C');
267 header_extension = tr (ext, 'y', 'h');
268 header_extension = tr (header_extension, 'Y', 'H');
234a3be3
AD
269}
270
271/* Computes extensions from the given c source file extension. */
272static void
f0130d39 273compute_exts_from_src (const char *ext)
234a3be3 274{
4ecbf796
MA
275 /* We use this function when the user specifies `-o' or `--output',
276 so the extenions must be computed unconditionally from the file name
277 given by this option. */
f0130d39
AD
278 src_extension = xstrdup (ext);
279 header_extension = tr (ext, 'c', 'h');
280 header_extension = tr (header_extension, 'C', 'H');
234a3be3 281}
d8880f69 282
ae404801
AD
283
284/* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth
285 part, (the directory) is ranging from FILENAME to the char before
286 *BASE, so we don't need an additional parameter.
287
288 *EXT points to the last period in the basename, or NULL if none.
289
290 If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
291 `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
292 cannot be equal to *BASE.
293
294 None are allocated, they are simply pointers to parts of FILENAME.
295 Examples:
296
297 '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
298 '.c'
299
300 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
301
302 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
303
304 '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
305
306 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
307
308 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
309
310 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */
311
312static void
313filename_split (const char *filename,
314 const char **base, const char **tab, const char **ext)
315{
316 *base = base_name (filename);
317
318 /* Look for the extension, i.e., look for the last dot. */
319 *ext = strrchr (*base, '.');
320 *tab = NULL;
321
322 /* If there is an exentension, check if there is a `.tab' part right
323 before. */
324 if (*ext
cae60122 325 && (*ext - *base) > (int) strlen (".tab")
ae404801
AD
326 && (!strncmp (*ext - strlen (".tab"), ".tab", strlen (".tab"))
327 || !strncmp (*ext - strlen ("_tab"), "_tab", strlen ("_tab"))))
328 *tab = *ext - strlen (".tab");
329}
330
331
19c50364
AD
332/* FIXME: Should use xstrndup. */
333
334static void
27110317 335compute_base_names (void)
54bd0db4 336{
ae404801 337 const char *base, *tab, *ext;
b0ce6046 338
19c50364
AD
339 /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c),
340 BASE_NAME and SHORT_BASE_NAME are `foo'.
54bd0db4 341
19c50364
AD
342 If --output=foo.tab.c was specified, BASE_NAME is `foo.tab' and
343 SHORT_BASE_NAME is `foo'.
344
345 The precise -o name will be used for FTABLE. For other output
346 files, remove the ".c" or ".tab.c" suffix. */
54bd0db4
RS
347 if (spec_outfile)
348 {
ae404801
AD
349 filename_split (spec_outfile, &base, &tab, &ext);
350
351 /* The full base name goes up the EXT, excluding it. */
352 full_base_name =
353 xstrndup (spec_outfile,
354 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
b85810ae 355
ae404801
AD
356 /* The short base name goes up to TAB, excluding it. */
357 short_base_name =
358 xstrndup (spec_outfile,
359 (strlen (spec_outfile)
360 - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
361
b85810ae
AD
362 if (tab)
363 output_infix = xstrndup (tab,
364 (strlen (tab) - (ext ? strlen (ext) : 0)));
ae404801
AD
365
366 if (ext)
367 compute_exts_from_src (ext);
54bd0db4 368 }
19c50364 369
ae404801
AD
370 /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab'
371 and SHORT_BASE_NAME = `foo'.
19c50364
AD
372
373 Construct names from it. */
ae404801 374 else
54bd0db4 375 {
ae404801
AD
376 if (spec_file_prefix)
377 {
378 /* If --file-prefix=foo was specified, SHORT_BASE_NAME =
379 `foo'. */
380 short_base_name = xstrdup (spec_file_prefix);
381 }
382 else if (yacc_flag)
383 {
384 /* If --yacc, then the output is `y.tab.c'. */
385 short_base_name = xstrdup ("y");
386 }
387 else
388 {
389 /* Otherwise, the short base name is computed from the input
390 grammar: `foo.yy' => `foo'. */
391 filename_split (infile, &base, &tab, &ext);
392 short_base_name =
393 xstrndup (infile,
394 (strlen (infile) - (ext ? strlen (ext) : 0)));
395 }
9b3add5b 396
ae404801 397 /* In these cases, always append `.tab'. */
b85810ae
AD
398 output_infix = xstrdup (EXT_TAB);
399
ae404801
AD
400 full_base_name = XMALLOC (char,
401 strlen (short_base_name)
402 + strlen (EXT_TAB) + 1);
403 stpcpy (stpcpy (full_base_name, short_base_name), EXT_TAB);
404
405 /* Computes the extensions from the grammar file name. */
406 filename_split (infile, &base, &tab, &ext);
5e5d5415 407 if (ext && !yacc_flag)
ae404801 408 compute_exts_from_gf (ext);
54bd0db4 409 }
19c50364
AD
410}
411
342b8b6e
AD
412/*-------------------------------------------------------.
413| Close the open files, compute the output files names. |
414`-------------------------------------------------------*/
415
416void
417compute_output_file_names (void)
418{
419 compute_base_names ();
420
421 /* If not yet done. */
422 if (!src_extension)
423 src_extension = ".c";
424 if (!header_extension)
425 header_extension = ".h";
5e5d5415 426
fc6edc45
MA
427 parser_file_name =
428 spec_outfile ? spec_outfile : stringappend (full_base_name, src_extension);
429
342b8b6e
AD
430 /* It the defines filename if not given, we create it. */
431 if (!spec_defines_file)
ae404801 432 spec_defines_file = stringappend (full_base_name, header_extension);
342b8b6e
AD
433
434 /* It the graph filename if not given, we create it. */
435 if (!spec_graph_file)
436 spec_graph_file = stringappend (short_base_name, ".vcg");
437
438 spec_verbose_file = stringappend (short_base_name, EXT_OUTPUT);
439
440 attrsfile = stringappend (short_base_name, EXT_STYPE_H);
342b8b6e 441}