]>
git.saurik.com Git - bison.git/blob - src/files.c
1 /* Open and close files for bison,
2 Copyright 1984, 1986, 1989, 1992, 2000, 2001, 2002
3 Free Software Foundation, Inc.
5 This file is part of Bison, the GNU Compiler Compiler.
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)
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.
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
31 /* From basename.c. Almost a lie, as it returns a char *. */
32 const char *base_name
PARAMS ((char const *name
));
33 /* From xstrndup.c. */
34 char *xstrndup
PARAMS ((const char *s
, size_t n
));
38 struct obstack action_obstack
;
39 struct obstack attrs_obstack
;
40 struct obstack table_obstack
;
41 struct obstack defines_obstack
;
42 struct obstack guard_obstack
;
43 struct obstack output_obstack
;
45 char *spec_outfile
= NULL
; /* for -o. */
46 char *spec_file_prefix
= NULL
; /* for -b. */
47 char *spec_name_prefix
= NULL
; /* for -p. */
48 char *spec_verbose_file
= NULL
; /* for --verbose. */
49 char *spec_graph_file
= NULL
; /* for -g. */
50 char *spec_defines_file
= NULL
; /* for --defines. */
53 char *attrsfile
= NULL
;
55 static char *full_base_name
= NULL
;
56 static char *short_base_name
= NULL
;
58 /* C source file extension (the parser source). */
59 const char *src_extension
= NULL
;
60 /* Header file extension (if option ``-d'' is specified). */
61 const char *header_extension
= NULL
;
64 /*--------------------------.
65 | Is SUFFIX ending STRING? |
66 `--------------------------*/
69 strsuffix (const char *string
, const char *suffix
)
71 size_t string_len
= strlen (string
);
72 size_t suffix_len
= strlen (suffix
);
73 if (suffix_len
<= string_len
)
74 return !strcmp (string
+ string_len
- suffix_len
, suffix
);
80 /*-----------------------------------------------------------------.
81 | Return a newly allocated string composed of the concatenation of |
82 | STRING1, and STRING2. |
83 `-----------------------------------------------------------------*/
86 stringappend (const char *string1
, const char *string2
)
88 size_t len
= strlen (string1
) + strlen (string2
);
89 char *res
= XMALLOC (char, len
+ 1);
91 cp
= stpcpy (res
, string1
);
92 cp
= stpcpy (cp
, string2
);
97 /*-----------------------------------------------------------------.
98 | Computes the macro name used to avoid double inclusion in the |
99 | header of the parser and store it in header_macro_name. Be sure |
100 | to produce valid CPP names (don't start with digit, remain |
101 | alphanumerical + underscore). |
102 `-----------------------------------------------------------------*/
105 compute_header_macro (void)
107 const char *prefix
= "BISON_";
108 char *macro_name
, *cp
;
110 if (spec_defines_file
)
112 macro_name
= XMALLOC (char,
114 strlen (spec_defines_file
) + 1);
115 cp
= stpcpy (macro_name
, prefix
);
116 cp
= stpcpy (cp
, spec_defines_file
);
120 macro_name
= XMALLOC (char,
122 strlen (full_base_name
) +
123 strlen (header_extension
) + 1);
124 cp
= stpcpy (macro_name
, prefix
);
125 cp
= stpcpy (cp
, full_base_name
);
126 cp
= stpcpy (cp
, header_extension
);
129 for (cp
= macro_name
; *cp
; ++cp
)
132 else if (!isalnum (*cp
))
139 /*-----------------------------------------------------------------.
140 | Try to open file NAME with mode MODE, and print an error message |
142 `-----------------------------------------------------------------*/
145 xfopen (const char *name
, const char *mode
)
149 ptr
= fopen (name
, mode
);
151 error (2, errno
, _("cannot open file `%s'"), name
);
156 /*-------------------------------------------------------------.
157 | Try to close file PTR, and print an error message if fails. |
158 `-------------------------------------------------------------*/
168 result
= fclose (ptr
);
170 error (2, errno
, _("cannot close file"));
175 /*--------------------------------------------------.
176 | Save the content of the obstack OBS in FILENAME. |
177 `--------------------------------------------------*/
180 obstack_save (struct obstack
*obs
, const char *filename
)
182 FILE *out
= xfopen (filename
, "w");
183 size_t size
= obstack_object_size (obs
);
184 fwrite (obstack_finish (obs
), 1, size
, out
);
188 /*---------------------------------------------------------------------.
189 | Output double inclusion protection macros and saves defines_obstack |
190 `---------------------------------------------------------------------*/
193 defines_obstack_save (const char *filename
)
195 FILE *out
= xfopen (filename
, "w");
196 size_t size
= obstack_object_size (&defines_obstack
);
197 char *macro_name
= compute_header_macro ();
199 fprintf (out
, "#ifndef %s\n", macro_name
);
200 fprintf (out
, "# define %s\n\n", macro_name
);
201 fwrite (obstack_finish (&defines_obstack
), 1, size
, out
);
202 fprintf (out
, "\n#endif /* not %s */\n", macro_name
);
208 /*------------------------------------------------------------------.
209 | Return the path to the skeleton which locaction might be given in |
210 | ENVVAR, otherwise return SKELETON_NAME. |
211 `------------------------------------------------------------------*/
214 skeleton_find (const char *envvar
, const char *skeleton_name
)
216 const char *res
= getenv (envvar
);
218 #if (defined (MSDOS) && !defined(__DJGPP__)) || defined (_WIN32)
219 const char *cp
= getenv ("INIT");
222 /* Skeleton file name without path */
223 const char *skel_name
= strrchr (skeleton_name
, '/');
225 skel_name
= strrchr (skeleton_name
, '\\');
227 skel_name
= skeleton_name
;
231 /* File doesn't exist in current directory; try in INIT directory. */
234 res
= XMALLOC (char, strlen (cp
) + strlen (skel_name
) + 2);
235 sprintf (res
, "%s%c%s", cp
, '\\', skel_name
);
237 else if (access (skel_name
, 4) == 0) /* Look in current dir. */
241 /* Look in program locations dir. */
242 extern char *program_name
;
243 cp
= strrchr(program_name
, '\\');
245 return skeleton_name
;
248 res
= XMALLOC (char, cp
- program_name
+ strlen (skel_name
) + 1);
249 strncpy (res
, program_name
, cp
- program_name
);
250 strcpy (res
+ (cp
- program_name
), skel_name
);
253 #endif /* (defined (MSDOS) && !defined (__DJGPP__)) || defined (_WIN32) */
261 /*----------------------------------------------------------------.
262 | Compute BASE_NAME, SHORT_BASE_NAME and output files extensions. |
263 `----------------------------------------------------------------*/
265 /* Replace all characters FROM by TO in the string IN.
266 and returns a new allocated string. */
268 tr (const char *in
, char from
, char to
)
273 out
= XMALLOC (char, strlen (in
) + 1);
275 for (temp
= out
; *in
; in
++, out
++)
284 /* Computes extensions from the grammar file extension. */
286 compute_exts_from_gf (const char *ext
)
288 src_extension
= tr (ext
, 'y', 'c');
289 src_extension
= tr (src_extension
, 'Y', 'C');
290 header_extension
= tr (ext
, 'y', 'h');
291 header_extension
= tr (header_extension
, 'Y', 'H');
294 /* Computes extensions from the given c source file extension. */
296 compute_exts_from_src (const char *ext
)
298 /* We use this function when the user specifies `-o' or `--output',
299 so the extenions must be computed unconditionally from the file name
300 given by this option. */
301 src_extension
= xstrdup (ext
);
302 header_extension
= tr (ext
, 'c', 'h');
303 header_extension
= tr (header_extension
, 'C', 'H');
307 /* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth
308 part, (the directory) is ranging from FILENAME to the char before
309 *BASE, so we don't need an additional parameter.
311 *EXT points to the last period in the basename, or NULL if none.
313 If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
314 `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
315 cannot be equal to *BASE.
317 None are allocated, they are simply pointers to parts of FILENAME.
320 '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT =
323 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c'
325 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c'
327 '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c'
329 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab'
331 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL
333 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */
336 filename_split (const char *filename
,
337 const char **base
, const char **tab
, const char **ext
)
339 *base
= base_name (filename
);
341 /* Look for the extension, i.e., look for the last dot. */
342 *ext
= strrchr (*base
, '.');
345 /* If there is an exentension, check if there is a `.tab' part right
348 && (*ext
- *base
) > (int) strlen (".tab")
349 && (!strncmp (*ext
- strlen (".tab"), ".tab", strlen (".tab"))
350 || !strncmp (*ext
- strlen ("_tab"), "_tab", strlen ("_tab"))))
351 *tab
= *ext
- strlen (".tab");
355 /* FIXME: Should use xstrndup. */
358 compute_base_names (void)
360 const char *base
, *tab
, *ext
;
362 /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c),
363 BASE_NAME and SHORT_BASE_NAME are `foo'.
365 If --output=foo.tab.c was specified, BASE_NAME is `foo.tab' and
366 SHORT_BASE_NAME is `foo'.
368 The precise -o name will be used for FTABLE. For other output
369 files, remove the ".c" or ".tab.c" suffix. */
372 filename_split (spec_outfile
, &base
, &tab
, &ext
);
374 /* The full base name goes up the EXT, excluding it. */
376 xstrndup (spec_outfile
,
377 (strlen (spec_outfile
) - (ext
? strlen (ext
) : 0)));
378 /* The short base name goes up to TAB, excluding it. */
380 xstrndup (spec_outfile
,
381 (strlen (spec_outfile
)
382 - (tab
? strlen (tab
) : (ext
? strlen (ext
) : 0))));
385 compute_exts_from_src (ext
);
388 /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab'
389 and SHORT_BASE_NAME = `foo'.
391 Construct names from it. */
394 if (spec_file_prefix
)
396 /* If --file-prefix=foo was specified, SHORT_BASE_NAME =
398 short_base_name
= xstrdup (spec_file_prefix
);
402 /* If --yacc, then the output is `y.tab.c'. */
403 short_base_name
= xstrdup ("y");
407 /* Otherwise, the short base name is computed from the input
408 grammar: `foo.yy' => `foo'. */
409 filename_split (infile
, &base
, &tab
, &ext
);
412 (strlen (infile
) - (ext
? strlen (ext
) : 0)));
415 /* In these cases, always append `.tab'. */
416 full_base_name
= XMALLOC (char,
417 strlen (short_base_name
)
418 + strlen (EXT_TAB
) + 1);
419 stpcpy (stpcpy (full_base_name
, short_base_name
), EXT_TAB
);
421 /* Computes the extensions from the grammar file name. */
422 filename_split (infile
, &base
, &tab
, &ext
);
424 if (ext
&& !yacc_flag
)
425 compute_exts_from_gf (ext
);
430 /*-------------------------------------------------------.
431 | Close the open files, compute the output files names. |
432 `-------------------------------------------------------*/
435 compute_output_file_names (void)
437 compute_base_names ();
439 /* If not yet done. */
441 src_extension
= ".c";
442 if (!header_extension
)
443 header_extension
= ".h";
445 /* It the defines filename if not given, we create it. */
446 if (!spec_defines_file
)
447 spec_defines_file
= stringappend (full_base_name
, header_extension
);
451 /* This is really Q&D, but I don't want to spend time on issues
452 which will be different with 1.50. */
453 const char *parser_filename
= NULL
;
455 parser_filename
= spec_outfile
;
457 parser_filename
= stringappend (full_base_name
, src_extension
);
458 if (!strcmp (spec_defines_file
, parser_filename
))
459 fatal ("header and parser would both be named %s",
460 quote (parser_filename
));
463 /* It the graph filename if not given, we create it. */
464 if (!spec_graph_file
)
465 spec_graph_file
= stringappend (short_base_name
, ".vcg");
467 spec_verbose_file
= stringappend (short_base_name
, EXT_OUTPUT
);
469 attrsfile
= stringappend (short_base_name
, EXT_STYPE_H
);
470 attrsfile
= stringappend (attrsfile
, EXT_TYPE (header_extension
));
474 /*-----------------------------------------------------------------.
475 | Open the input file. Look for the skeletons. Find the names of |
476 | the output files. Prepare the obstacks. |
477 `-----------------------------------------------------------------*/
482 finput
= xfopen (infile
, "r");
484 /* Initialize the obstacks. */
485 obstack_init (&action_obstack
);
486 obstack_init (&attrs_obstack
);
487 obstack_init (&table_obstack
);
488 obstack_init (&defines_obstack
);
489 obstack_init (&guard_obstack
);
490 obstack_init (&output_obstack
);
495 /*-----------------------.
496 | Close the open file.. |
497 `-----------------------*/
505 /*---------------------------.
506 | Produce the output files. |
507 `---------------------------*/
512 /* Output the main file. */
514 obstack_save (&table_obstack
, spec_outfile
);
516 obstack_save (&table_obstack
,
517 stringappend (full_base_name
, src_extension
));
518 obstack_free (&table_obstack
, NULL
);
520 /* Output the header file if wanted. */
522 defines_obstack_save (spec_defines_file
);
523 obstack_free (&defines_obstack
, NULL
);
525 /* If we output only the table, dump the actions in ACTFILE. */
527 obstack_save (&action_obstack
, stringappend (short_base_name
, ".act"));
528 obstack_free (&action_obstack
, NULL
);
530 /* If we produced a semantic parser ATTRS_OBSTACK must be dumped
531 into its own file, ATTTRSFILE. */
536 obstack_save (&attrs_obstack
, attrsfile
);
537 obstack_free (&attrs_obstack
, NULL
);
538 temp_name
= stringappend (short_base_name
, EXT_GUARD_C
);
539 temp_name
= stringappend (temp_name
, EXT_TYPE (src_extension
));
540 obstack_save (&guard_obstack
, temp_name
);
541 obstack_free (&guard_obstack
, NULL
);