1 /* Open and close files for bison, 
   2    Copyright (C) 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 
  30 /* From basename.c.  Almost a lie, as it returns a char *. */ 
  31 const char *base_name (char const *name
); 
  35 struct obstack pre_prologue_obstack
; 
  36 struct obstack post_prologue_obstack
; 
  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.  */ 
  45 char *spec_outfile 
= NULL
;      /* for -o. */ 
  46 char *spec_file_prefix 
= NULL
;  /* for -b. */ 
  47 const 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. */ 
  51 char *parser_file_name 
= NULL
; 
  55 static char *full_base_name 
= NULL
; 
  57 /* Prefix used to generate output file names.  */ 
  58 char *short_base_name 
= NULL
; 
  60 /* Infix used to generate output file names (i.e., `.tab', or `_tab', 
  62 char *output_infix 
= NULL
; 
  64 /* C source file extension (the parser source).  */ 
  65 const char *src_extension 
= NULL
; 
  66 /* Header file extension (if option ``-d'' is specified).  */ 
  67 const char *header_extension 
= NULL
; 
  70 /*--------------------------. 
  71 | Is SUFFIX ending STRING?  | 
  72 `--------------------------*/ 
  75 strsuffix (const char *string
, const char *suffix
) 
  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
); 
  86 /*-----------------------------------------------------------------. 
  87 | Return a newly allocated string composed of the concatenation of | 
  88 | STRING1, and STRING2.                                            | 
  89 `-----------------------------------------------------------------*/ 
  92 stringappend (const char *string1
, const char *string2
) 
  94   size_t len 
= strlen (string1
) + strlen (string2
); 
  95   char *res 
= XMALLOC (char, len 
+ 1); 
  97   cp 
= stpcpy (res
, string1
); 
  98   cp 
= stpcpy (cp
, string2
); 
 102 /*-----------------------------------------------------------------. 
 103 | Try to open file NAME with mode MODE, and print an error message | 
 105 `-----------------------------------------------------------------*/ 
 108 xfopen (const char *name
, const char *mode
) 
 112   ptr 
= fopen (name
, mode
); 
 114     error (EXIT_FAILURE
, errno
, _("cannot open file `%s'"), name
); 
 119 /*-------------------------------------------------------------. 
 120 | Try to close file PTR, and print an error message if fails.  | 
 121 `-------------------------------------------------------------*/ 
 131   result 
= fclose (ptr
); 
 133     error (EXIT_FAILURE
, errno
, _("cannot close file")); 
 139 /*----------------------------------------------------------------. 
 140 | Compute BASE_NAME, SHORT_BASE_NAME and output files extensions. | 
 141 `----------------------------------------------------------------*/ 
 143 /* Replace all characters FROM by TO in the string IN. 
 144    and returns a new allocated string.  */ 
 146 tr (const char *in
, char from
, char to
) 
 151   out 
= XMALLOC (char, strlen (in
) + 1); 
 153   for (temp 
= out
; *in
; in
++, out
++) 
 162 /* Computes extensions from the grammar file extension. */ 
 164 compute_exts_from_gf (const char *ext
) 
 166   src_extension 
= tr (ext
, 'y', 'c'); 
 167   src_extension 
= tr (src_extension
, 'Y', 'C'); 
 168   header_extension 
= tr (ext
, 'y', 'h'); 
 169   header_extension 
= tr (header_extension
, 'Y', 'H'); 
 172 /* Computes extensions from the given c source file extension. */ 
 174 compute_exts_from_src (const char *ext
) 
 176   /* We use this function when the user specifies `-o' or `--output', 
 177      so the extenions must be computed unconditionally from the file name 
 178      given by this option.  */ 
 179   src_extension 
= xstrdup (ext
); 
 180   header_extension 
= tr (ext
, 'c', 'h'); 
 181   header_extension 
= tr (header_extension
, 'C', 'H'); 
 185 /* Decompose FILENAME in four parts: *BASE, *TAB, and *EXT, the fourth 
 186    part, (the directory) is ranging from FILENAME to the char before 
 187    *BASE, so we don't need an additional parameter. 
 189    *EXT points to the last period in the basename, or NULL if none. 
 191    If there is no *EXT, *TAB is NULL.  Otherwise, *TAB points to 
 192    `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB 
 193    cannot be equal to *BASE. 
 195    None are allocated, they are simply pointers to parts of FILENAME. 
 198    '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT = 
 201    'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c' 
 203    'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c' 
 205    '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c' 
 207    'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab' 
 209    'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL 
 211    'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL.  */ 
 214 filename_split (const char *filename
, 
 215                 const char **base
, const char **tab
, const char **ext
) 
 217   *base 
= base_name (filename
); 
 219   /* Look for the extension, i.e., look for the last dot. */ 
 220   *ext 
= strrchr (*base
, '.'); 
 223   /* If there is an exentension, check if there is a `.tab' part right 
 226       && (*ext 
- *base
) > (int) strlen (".tab") 
 227       && (!strncmp (*ext 
- strlen (".tab"), ".tab", strlen (".tab")) 
 228           || !strncmp (*ext 
- strlen ("_tab"), "_tab", strlen ("_tab")))) 
 229     *tab 
= *ext 
- strlen (".tab"); 
 233 /* FIXME: Should use xstrndup. */ 
 236 compute_base_names (void) 
 238   const char *base
, *tab
, *ext
; 
 240   /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c), 
 241      BASE_NAME and SHORT_BASE_NAME are `foo'. 
 243      If --output=foo.tab.c was specified, BASE_NAME is `foo.tab' and 
 244      SHORT_BASE_NAME is `foo'. 
 246      The precise -o name will be used for FTABLE.  For other output 
 247      files, remove the ".c" or ".tab.c" suffix.  */ 
 250       filename_split (spec_outfile
, &base
, &tab
, &ext
); 
 252       /* The full base name goes up the EXT, excluding it. */ 
 254         xstrndup (spec_outfile
, 
 255                   (strlen (spec_outfile
) - (ext 
? strlen (ext
) : 0))); 
 257       /* The short base name goes up to TAB, excluding it.  */ 
 259         xstrndup (spec_outfile
, 
 260                   (strlen (spec_outfile
) 
 261                    - (tab 
? strlen (tab
) : (ext 
? strlen (ext
) : 0)))); 
 264         output_infix 
= xstrndup (tab
, 
 265                                  (strlen (tab
) - (ext 
? strlen (ext
) : 0))); 
 268         compute_exts_from_src (ext
); 
 271   /* If --file-prefix=foo was specified, FULL_BASE_NAME = `foo.tab' 
 272      and SHORT_BASE_NAME = `foo'. 
 274      Construct names from it.  */ 
 277       if (spec_file_prefix
) 
 279           /* If --file-prefix=foo was specified, SHORT_BASE_NAME = 
 281           short_base_name 
= xstrdup (spec_file_prefix
); 
 285           /* If --yacc, then the output is `y.tab.c'. */ 
 286           short_base_name 
= xstrdup ("y"); 
 290           /* Otherwise, the short base name is computed from the input 
 291              grammar: `foo/bar.yy' => `bar'.  */ 
 292           filename_split (infile
, &base
, &tab
, &ext
); 
 295                       (strlen (base
) - (ext 
? strlen (ext
) : 0))); 
 298       /* In these cases, always append `.tab'. */ 
 299       output_infix 
= xstrdup (EXT_TAB
); 
 301       full_base_name 
= XMALLOC (char, 
 302                                 strlen (short_base_name
) 
 303                                 + strlen (EXT_TAB
) + 1); 
 304       stpcpy (stpcpy (full_base_name
, short_base_name
), EXT_TAB
); 
 306       /* Computes the extensions from the grammar file name.  */ 
 307       filename_split (infile
, &base
, &tab
, &ext
); 
 308       if (ext 
&& !yacc_flag
) 
 309         compute_exts_from_gf (ext
); 
 313 /*-------------------------------------------------------. 
 314 | Close the open files, compute the output files names.  | 
 315 `-------------------------------------------------------*/ 
 318 compute_output_file_names (void) 
 320   compute_base_names (); 
 322   /* If not yet done. */ 
 324     src_extension 
= ".c"; 
 325   if (!header_extension
) 
 326     header_extension 
= ".h"; 
 329     spec_outfile 
? spec_outfile 
: stringappend (full_base_name
, src_extension
); 
 331   /* It the defines filename if not given, we create it.  */ 
 332   if (!spec_defines_file
) 
 333     spec_defines_file 
= stringappend (full_base_name
, header_extension
); 
 335   /* It the graph filename if not given, we create it.  */ 
 336   if (!spec_graph_file
) 
 337     spec_graph_file 
= stringappend (short_base_name
, ".vcg"); 
 339   spec_verbose_file 
= stringappend (short_base_name
, EXT_OUTPUT
);