]>
git.saurik.com Git - bison.git/blob - src/files.c
13eecf8e98729b8b2cf20b86fad3f05148b2f8f9
   1 /* Open and close files for Bison. 
   3    Copyright (C) 1984, 1986, 1989, 1992, 2000-2012 Free Software 
   6    This file is part of Bison, the GNU Compiler Compiler. 
   8    This program is free software: you can redistribute it and/or modify 
   9    it under the terms of the GNU General Public License as published by 
  10    the Free Software Foundation, either version 3 of the License, or 
  11    (at your option) any later version. 
  13    This program is distributed in the hope that it will be useful, 
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of 
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  16    GNU General Public License for more details. 
  18    You should have received a copy of the GNU General Public License 
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ 
  26 #include <get-errno.h> 
  28 #include <stdio-safer.h> 
  36 /* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is 
  37    tempting, but don't do that: for the time being our handling of the 
  38    %directive vs --option leaves precedence to the options by deciding 
  39    that if a %directive sets a variable which is really set (i.e., not 
  40    NULL), then the %directive is ignored.  As a result, %name-prefix, 
  41    for instance, will not be honored.  */ 
  43 char const *spec_outfile 
= NULL
;       /* for -o. */ 
  44 char const *spec_file_prefix 
= NULL
;   /* for -b. */ 
  45 char const *spec_name_prefix 
= NULL
;   /* for -p. */ 
  46 char *spec_verbose_file 
= NULL
;  /* for --verbose. */ 
  47 char *spec_graph_file 
= NULL
;    /* for -g. */ 
  48 char *spec_xml_file 
= NULL
;      /* for -x. */ 
  49 char *spec_defines_file 
= NULL
;  /* for --defines. */ 
  50 char *parser_file_name
; 
  52 /* All computed output file names.  */ 
  53 static char **file_names 
= NULL
; 
  54 static int file_names_count 
= 0; 
  56 uniqstr grammar_file 
= NULL
; 
  57 uniqstr current_file 
= NULL
; 
  59 /* If --output=dir/foo.c was specified, 
  60    DIR_PREFIX is `dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are `dir/foo'. 
  62    If --output=dir/foo.tab.c was specified, DIR_PREFIX is `dir/', 
  63    ALL_BUT_EXT is `dir/foo.tab', and ALL_BUT_TAB_EXT is `dir/foo'. 
  65    If --output was not specified but --file-prefix=dir/foo was specified, 
  66    ALL_BUT_EXT = `foo.tab' and ALL_BUT_TAB_EXT = `foo'. 
  68    If neither --output nor --file was specified but the input grammar 
  69    is name dir/foo.y, ALL_BUT_EXT and ALL_BUT_TAB_EXT are `foo'. 
  71    If neither --output nor --file was specified, DIR_PREFIX is the 
  72    empty string (meaning the current directory); otherwise it is 
  76 static char *all_but_tab_ext
; 
  79 /* C source file extension (the parser source).  */ 
  80 static char *src_extension 
= NULL
; 
  81 /* Header file extension (if option ``-d'' is specified).  */ 
  82 static char *header_extension 
= NULL
; 
  84 /*-----------------------------------------------------------------. 
  85 | Return a newly allocated string composed of the concatenation of | 
  87 `-----------------------------------------------------------------*/ 
  90 concat2 (char const *str1
, char const *str2
) 
  92   size_t len 
= strlen (str1
) + strlen (str2
); 
  93   char *res 
= xmalloc (len 
+ 1); 
  95   cp 
= stpcpy (res
, str1
); 
  96   cp 
= stpcpy (cp
, str2
); 
 100 /*-----------------------------------------------------------------. 
 101 | Try to open file NAME with mode MODE, and print an error message | 
 103 `-----------------------------------------------------------------*/ 
 106 xfopen (const char *name
, const char *mode
) 
 110   ptr 
= fopen_safer (name
, mode
); 
 112     error (EXIT_FAILURE
, get_errno (), _("cannot open file `%s'"), name
); 
 117 /*-------------------------------------------------------------. 
 118 | Try to close file PTR, and print an error message if fails.  | 
 119 `-------------------------------------------------------------*/ 
 128     error (EXIT_FAILURE
, 0, _("I/O error")); 
 130   if (fclose (ptr
) != 0) 
 131     error (EXIT_FAILURE
, get_errno (), _("cannot close file")); 
 135 /*------------------------------------------------------------------. 
 136 | Compute ALL_BUT_EXT, ALL_BUT_TAB_EXT and output files extensions. | 
 137 `------------------------------------------------------------------*/ 
 139 /* Compute extensions from the grammar file extension.  */ 
 141 compute_exts_from_gf (const char *ext
) 
 143   if (strcmp (ext
, ".y") == 0) 
 145       src_extension 
= xstrdup (language
->src_extension
); 
 146       header_extension 
= xstrdup (language
->header_extension
); 
 150       src_extension 
= xstrdup (ext
); 
 151       header_extension 
= xstrdup (ext
); 
 152       tr (src_extension
, 'y', 'c'); 
 153       tr (src_extension
, 'Y', 'C'); 
 154       tr (header_extension
, 'y', 'h'); 
 155       tr (header_extension
, 'Y', 'H'); 
 159 /* Compute extensions from the given c source file extension.  */ 
 161 compute_exts_from_src (const char *ext
) 
 163   /* We use this function when the user specifies `-o' or `--output', 
 164      so the extenions must be computed unconditionally from the file name 
 165      given by this option.  */ 
 166   src_extension 
= xstrdup (ext
); 
 167   header_extension 
= xstrdup (ext
); 
 168   tr (header_extension
, 'c', 'h'); 
 169   tr (header_extension
, 'C', 'H'); 
 173 /* Decompose FILE_NAME in four parts: *BASE, *TAB, and *EXT, the fourth 
 174    part, (the directory) is ranging from FILE_NAME to the char before 
 175    *BASE, so we don't need an additional parameter. 
 177    *EXT points to the last period in the basename, or NULL if none. 
 179    If there is no *EXT, *TAB is NULL.  Otherwise, *TAB points to 
 180    `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB 
 181    cannot be equal to *BASE. 
 183    None are allocated, they are simply pointers to parts of FILE_NAME. 
 186    '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT = 
 189    'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c' 
 191    'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c' 
 193    '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c' 
 195    'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab' 
 197    'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL 
 199    'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL.  */ 
 202 file_name_split (const char *file_name
, 
 203                  const char **base
, const char **tab
, const char **ext
) 
 205   *base 
= last_component (file_name
); 
 207   /* Look for the extension, i.e., look for the last dot. */ 
 208   *ext 
= mbsrchr (*base
, '.'); 
 211   /* If there is an extension, check if there is a `.tab' part right 
 215       size_t baselen 
= *ext 
- *base
; 
 216       size_t dottablen 
= 4; 
 217       if (dottablen 
< baselen
 
 218           && (strncmp (*ext 
- dottablen
, ".tab", dottablen
) == 0 
 219               || strncmp (*ext 
- dottablen
, "_tab", dottablen
) == 0)) 
 220         *tab 
= *ext 
- dottablen
; 
 226 compute_file_name_parts (void) 
 228   const char *base
, *tab
, *ext
; 
 230   /* Compute ALL_BUT_EXT and ALL_BUT_TAB_EXT from SPEC_OUTFILE 
 233      The precise -o name will be used for FTABLE.  For other output 
 234      files, remove the ".c" or ".tab.c" suffix.  */ 
 237       file_name_split (spec_outfile
, &base
, &tab
, &ext
); 
 238       dir_prefix 
= xstrndup (spec_outfile
, base 
- spec_outfile
); 
 240       /* ALL_BUT_EXT goes up the EXT, excluding it. */ 
 242         xstrndup (spec_outfile
, 
 243                   (strlen (spec_outfile
) - (ext 
? strlen (ext
) : 0))); 
 245       /* ALL_BUT_TAB_EXT goes up to TAB, excluding it.  */ 
 247         xstrndup (spec_outfile
, 
 248                   (strlen (spec_outfile
) 
 249                    - (tab 
? strlen (tab
) : (ext 
? strlen (ext
) : 0)))); 
 252         compute_exts_from_src (ext
); 
 256       file_name_split (grammar_file
, &base
, &tab
, &ext
); 
 258       if (spec_file_prefix
) 
 260           /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = `foo'.  */ 
 262             xstrndup (spec_file_prefix
, 
 263                       last_component (spec_file_prefix
) - spec_file_prefix
); 
 264           all_but_tab_ext 
= xstrdup (spec_file_prefix
); 
 268           /* If --yacc, then the output is `y.tab.c'.  */ 
 269           dir_prefix 
= xstrdup (""); 
 270           all_but_tab_ext 
= xstrdup ("y"); 
 274           /* Otherwise, ALL_BUT_TAB_EXT is computed from the input 
 275              grammar: `foo/bar.yy' => `bar'.  */ 
 276           dir_prefix 
= xstrdup (""); 
 278             xstrndup (base
, (strlen (base
) - (ext 
? strlen (ext
) : 0))); 
 281       if (language
->add_tab
) 
 282         all_but_ext 
= concat2 (all_but_tab_ext
, TAB_EXT
); 
 284         all_but_ext 
= xstrdup (all_but_tab_ext
); 
 286       /* Compute the extensions from the grammar file name.  */ 
 287       if (ext 
&& !yacc_flag
) 
 288         compute_exts_from_gf (ext
); 
 293 /* Compute the output file names.  Warn if we detect conflicting 
 294    outputs to the same file.  */ 
 297 compute_output_file_names (void) 
 299   compute_file_name_parts (); 
 301   /* If not yet done. */ 
 303     src_extension 
= xstrdup (".c"); 
 304   if (!header_extension
) 
 305     header_extension 
= xstrdup (".h"); 
 309      ? xstrdup (spec_outfile
) 
 310      : concat2 (all_but_ext
, src_extension
)); 
 314       if (! spec_defines_file
) 
 315         spec_defines_file 
= concat2 (all_but_ext
, header_extension
); 
 320       if (! spec_graph_file
) 
 321         spec_graph_file 
= concat2 (all_but_tab_ext
, ".dot"); 
 322       output_file_name_check (&spec_graph_file
); 
 328         spec_xml_file 
= concat2 (all_but_tab_ext
, ".xml"); 
 329       output_file_name_check (&spec_xml_file
); 
 334       if (!spec_verbose_file
) 
 335         spec_verbose_file 
= concat2 (all_but_tab_ext
, OUTPUT_EXT
); 
 336       output_file_name_check (&spec_verbose_file
); 
 339   free (all_but_tab_ext
); 
 340   free (src_extension
); 
 341   free (header_extension
); 
 345 output_file_name_check (char **file_name
) 
 347   bool conflict 
= false; 
 348   if (0 == strcmp (*file_name
, grammar_file
)) 
 350       complain (_("refusing to overwrite the input file %s"), 
 357       for (i 
= 0; i 
< file_names_count
; i
++) 
 358         if (0 == strcmp (file_names
[i
], *file_name
)) 
 360             warn (_("conflicting outputs to file %s"), 
 368       *file_name 
= strdup ("/dev/null"); 
 372       file_names 
= xnrealloc (file_names
, ++file_names_count
, 
 374       file_names
[file_names_count
-1] = xstrdup (*file_name
); 
 379 output_file_names_free (void) 
 382   free (spec_verbose_file
); 
 383   free (spec_graph_file
); 
 384   free (spec_xml_file
); 
 385   free (spec_defines_file
); 
 386   free (parser_file_name
); 
 390     for (i 
= 0; i 
< file_names_count
; i
++) 
 391       free (file_names
[i
]);