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