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