1 /* Open and close files for Bison. 
   3    Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002, 2003 
   4    Free Software Foundation, Inc. 
   6    This file is part of Bison, the GNU Compiler Compiler. 
   8    Bison is free software; you can redistribute it and/or modify it 
   9    under the terms of the GNU General Public License as published by 
  10    the Free Software Foundation; either version 2, or (at your option) 
  13    Bison is distributed in the hope that it will be useful, but 
  14    WITHOUT ANY WARRANTY; without even the implied warranty of 
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  16    General Public License for more details. 
  18    You should have received a copy of the GNU General Public License 
  19    along with Bison; see the file COPYING.  If not, write to the Free 
  20    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
  27 #include <get-errno.h> 
  35 /* From basename.c.  Almost a lie, as it returns a char *. */ 
  36 const char *base_name (char const *name
); 
  40 struct obstack pre_prologue_obstack
; 
  41 struct obstack post_prologue_obstack
; 
  43 /* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is 
  44    tempting, but don't do that: for the time being our handling of the 
  45    %directive vs --option leaves precedence to the options by deciding 
  46    that if a %directive sets a variable which is really set (i.e., not 
  47    NULL), then the %directive is ignored.  As a result, %name-prefix, 
  48    for instance, will not be honored.  */ 
  50 char *spec_outfile 
= NULL
;      /* for -o. */ 
  51 char *spec_file_prefix 
= NULL
;  /* for -b. */ 
  52 const char *spec_name_prefix 
= NULL
;    /* for -p. */ 
  53 char *spec_verbose_file 
= NULL
;   /* for --verbose. */ 
  54 char *spec_graph_file 
= NULL
;   /* for -g. */ 
  55 char *spec_defines_file 
= NULL
; /* for --defines. */ 
  56 char *parser_file_name 
= NULL
; 
  58 uniqstr grammar_file 
= NULL
; 
  59 uniqstr current_file 
= NULL
; 
  61 static char *full_base_name 
= NULL
; 
  63 /* Prefix used to generate output file names.  */ 
  64 char *short_base_name 
= NULL
; 
  66 /* C source file extension (the parser source).  */ 
  67 const char *src_extension 
= NULL
; 
  68 /* Header file extension (if option ``-d'' is specified).  */ 
  69 const char *header_extension 
= NULL
; 
  71 /*-----------------------------------------------------------------. 
  72 | Return a newly allocated string composed of the concatenation of | 
  74 `-----------------------------------------------------------------*/ 
  77 concat2 (char const *str1
, char const *str2
) 
  79   size_t len 
= strlen (str1
) + strlen (str2
); 
  80   char *res 
= xmalloc (len 
+ 1); 
  82   cp 
= stpcpy (res
, str1
); 
  83   cp 
= stpcpy (cp
, str2
); 
  87 /*-----------------------------------------------------------------. 
  88 | Try to open file NAME with mode MODE, and print an error message | 
  90 `-----------------------------------------------------------------*/ 
  93 xfopen (const char *name
, const char *mode
) 
  97   ptr 
= fopen (name
, mode
); 
  99     error (EXIT_FAILURE
, get_errno (), _("cannot open file `%s'"), name
); 
 104 /*-------------------------------------------------------------. 
 105 | Try to close file PTR, and print an error message if fails.  | 
 106 `-------------------------------------------------------------*/ 
 115     error (EXIT_FAILURE
, 0, _("I/O error")); 
 117   if (fclose (ptr
) != 0) 
 118     error (EXIT_FAILURE
, get_errno (), _("cannot close file")); 
 122 /*---------------------------------------------------------------------. 
 123 | Compute FULL_BASE_NAME, SHORT_BASE_NAME and output files extensions. | 
 124 `---------------------------------------------------------------------*/ 
 126 /* Replace all characters FROM by TO in the string IN. 
 127    and returns a new allocated string.  */ 
 129 tr (const char *in
, char from
, char to
) 
 132   char *out 
= xmalloc (strlen (in
) + 1); 
 134   for (temp 
= out
; *in
; in
++, out
++) 
 143 /* Compute extensions from the grammar file extension.  */ 
 145 compute_exts_from_gf (const char *ext
) 
 147   src_extension 
= tr (ext
, 'y', 'c'); 
 148   src_extension 
= tr (src_extension
, 'Y', 'C'); 
 149   header_extension 
= tr (ext
, 'y', 'h'); 
 150   header_extension 
= tr (header_extension
, 'Y', 'H'); 
 153 /* Compute extensions from the given c source file extension.  */ 
 155 compute_exts_from_src (const char *ext
) 
 157   /* We use this function when the user specifies `-o' or `--output', 
 158      so the extenions must be computed unconditionally from the file name 
 159      given by this option.  */ 
 160   src_extension 
= xstrdup (ext
); 
 161   header_extension 
= tr (ext
, 'c', 'h'); 
 162   header_extension 
= tr (header_extension
, 'C', 'H'); 
 166 /* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth 
 167    part, (the directory) is ranging from FILENAME to the char before 
 168    *BASE, so we don't need an additional parameter. 
 170    *EXT points to the last period in the basename, or NULL if none. 
 172    If there is no *EXT, *TAB is NULL.  Otherwise, *TAB points to 
 173    `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB 
 174    cannot be equal to *BASE. 
 176    None are allocated, they are simply pointers to parts of FILENAME. 
 179    '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT = 
 182    'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c' 
 184    'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c' 
 186    '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c' 
 188    'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab' 
 190    'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL 
 192    'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL.  */ 
 195 filename_split (const char *filename
, 
 196                 const char **base
, const char **tab
, const char **ext
) 
 198   *base 
= base_name (filename
); 
 200   /* Look for the extension, i.e., look for the last dot. */ 
 201   *ext 
= strrchr (*base
, '.'); 
 204   /* If there is an extension, check if there is a `.tab' part right 
 208       size_t baselen 
= *ext 
- *base
; 
 209       size_t dottablen 
= 4; 
 210       if (dottablen 
< baselen
 
 211           && (strncmp (*ext 
- dottablen
, ".tab", dottablen
) == 0 
 212               || strncmp (*ext 
- dottablen
, "_tab", dottablen
) == 0)) 
 213         *tab 
= *ext 
- dottablen
; 
 218 /* FIXME: Should use xstrndup. */ 
 221 compute_base_names (void) 
 223   const char *base
, *tab
, *ext
; 
 225   /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c), 
 226      FULL_BASE_NAME and SHORT_BASE_NAME are `foo'. 
 228      If --output=foo.tab.c was specified, FULL_BASE_NAME is `foo.tab' 
 229      and SHORT_BASE_NAME is `foo'. 
 231      The precise -o name will be used for FTABLE.  For other output 
 232      files, remove the ".c" or ".tab.c" suffix.  */ 
 235       filename_split (spec_outfile
, &base
, &tab
, &ext
); 
 237       /* The full base name goes up the EXT, excluding it. */ 
 239         xstrndup (spec_outfile
, 
 240                   (strlen (spec_outfile
) - (ext 
? strlen (ext
) : 0))); 
 242       /* The short base name goes up to TAB, excluding it.  */ 
 244         xstrndup (spec_outfile
, 
 245                   (strlen (spec_outfile
) 
 246                    - (tab 
? strlen (tab
) : (ext 
? strlen (ext
) : 0)))); 
 249         compute_exts_from_src (ext
); 
 252   /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab' 
 253      and SHORT_BASE_NAME = `foo'. 
 255      Construct names from it.  */ 
 258       if (spec_file_prefix
) 
 260           /* If --file-prefix=foo was specified, SHORT_BASE_NAME = 
 262           short_base_name 
= xstrdup (spec_file_prefix
); 
 266           /* If --yacc, then the output is `y.tab.c'. */ 
 267           short_base_name 
= xstrdup ("y"); 
 271           /* Otherwise, the short base name is computed from the input 
 272              grammar: `foo/bar.yy' => `bar'.  */ 
 273           filename_split (grammar_file
, &base
, &tab
, &ext
); 
 276                       (strlen (base
) - (ext 
? strlen (ext
) : 0))); 
 279       full_base_name 
= xmalloc (strlen (short_base_name
) 
 280                                 + strlen (TAB_EXT
) + 1); 
 281       stpcpy (stpcpy (full_base_name
, short_base_name
), TAB_EXT
); 
 283       /* Compute the extensions from the grammar file name.  */ 
 284       filename_split (grammar_file
, &base
, &tab
, &ext
); 
 285       if (ext 
&& !yacc_flag
) 
 286         compute_exts_from_gf (ext
); 
 291 /* Compute the output file names.  Warn if we detect conflicting 
 292    outputs to the same file.  */ 
 295 compute_output_file_names (void) 
 302   compute_base_names (); 
 304   /* If not yet done. */ 
 306     src_extension 
= ".c"; 
 307   if (!header_extension
) 
 308     header_extension 
= ".h"; 
 310   name
[names
++] = parser_file_name 
= 
 311     spec_outfile 
? spec_outfile 
: concat2 (full_base_name
, src_extension
); 
 315       if (! spec_defines_file
) 
 316         spec_defines_file 
= concat2 (full_base_name
, header_extension
); 
 317       name
[names
++] = spec_defines_file
; 
 322       if (! spec_graph_file
) 
 323         spec_graph_file 
= concat2 (short_base_name
, ".vcg"); 
 324       name
[names
++] = spec_graph_file
; 
 329       spec_verbose_file 
= concat2 (short_base_name
, OUTPUT_EXT
); 
 330       name
[names
++] = spec_verbose_file
; 
 333   for (j 
= 0; j 
< names
; j
++) 
 334     for (i 
= 0; i 
< j
; i
++) 
 335       if (strcmp (name
[i
], name
[j
]) == 0) 
 336         warn (_("conflicting outputs to file %s"), quote (name
[i
]));