]> git.saurik.com Git - bison.git/blobdiff - src/files.c
Regen.
[bison.git] / src / files.c
index 5e81ebe8ae136cdfc7bd6af5192904b17b2ed04d..2e817b1ed18e247d5834989c6185e079b275403c 100644 (file)
@@ -1,5 +1,5 @@
 /* Open and close files for bison,
 /* Open and close files for bison,
-   Copyright 1984, 1986, 1989, 1992, 2000 Free Software Foundation, Inc.
+   Copyright 1984, 1986, 1989, 1992, 2000, 2001 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
 
 #include "system.h"
 
 
 #include "system.h"
-
-#if defined (VMS) & !defined (__VMS_POSIX)
-# ifndef BISON_SIMPLE
-#  define BISON_SIMPLE "GNU_BISON:[000000]BISON.SIMPLE"
-# endif
-# ifndef BISON_HAIRY
-#  define BISON_HARIRY "GNU_BISON:[000000]BISON.HAIRY"
-# endif
-#endif
-
-#if defined (_MSC_VER)
-# ifndef BISON_SIMPLE
-#  define BISON_SIMPLE "c:/usr/local/lib/bison.simple"
-# endif
-# ifndef BISON_HAIRY
-#  define BISON_HAIRY "c:/usr/local/lib/bison.hairy"
-# endif
-#endif
-
 #include "getargs.h"
 #include "files.h"
 #include "getargs.h"
 #include "files.h"
-#include "xalloc.h"
 #include "gram.h"
 #include "gram.h"
+#include "error.h"
 #include "complain.h"
 
 FILE *finput = NULL;
 #include "complain.h"
 
 FILE *finput = NULL;
-FILE *foutput = NULL;
-FILE *fguard = NULL;
-FILE *fparser = NULL;
 
 struct obstack action_obstack;
 struct obstack attrs_obstack;
 
 struct obstack action_obstack;
 struct obstack attrs_obstack;
-struct obstack table_obstack;
-struct obstack defines_obstack;
-
-/* File name specified with -o for the output file, or 0 if no -o.  */
-char *spec_outfile;
+struct obstack output_obstack;
+
+/* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is
+   tempting, but don't do that: for the time being our handling of the
+   %directive vs --option leaves precedence to the options by deciding
+   that if a %directive sets a variable which is really set (i.e., not
+   NULL), then the %directive is ignored.  As a result, %name-prefix,
+   for instance, will not be honored.  */
+
+char *spec_outfile = NULL;     /* for -o. */
+char *spec_file_prefix = NULL; /* for -b. */
+const char *spec_name_prefix = NULL;   /* for -p. */
+char *spec_verbose_file = NULL;   /* for --verbose. */
+char *spec_graph_file = NULL;   /* for -g. */
+char *spec_defines_file = NULL; /* for --defines. */
+char *parser_file_name = NULL;
+
+char *infile = NULL;
+char *attrsfile = NULL;
+
+static char *base_name = NULL;
+char *short_base_name = NULL;
+
+/* C source file extension (the parser source).  */
+const char *src_extension = NULL;
+/* Header file extension (if option ``-d'' is specified).  */
+const char *header_extension = NULL;
+
+/* Should we insert '.tab' in yacc-compatible parsers?  */
+int tab_extension = 0;
+\f
 
 
-char *infile;
-char *attrsfile;
+/*--------------------------.
+| Is SUFFIX ending STRING?  |
+`--------------------------*/
 
 
-static char *outfile;
-static char *defsfile;
-static char *tabfile;
-static char *guardfile;
-static char *actfile;
+int
+strsuffix (const char *string, const char *suffix)
+{
+  size_t string_len = strlen (string);
+  size_t suffix_len = strlen (suffix);
+  if (suffix_len <= string_len)
+    return !strcmp (string + string_len - suffix_len, suffix);
+  else
+    return 0;
+}
 
 
-extern char *getenv ();
 
 
-extern char *program_name;
-\f
+/*-----------------------------------------------------------------.
+| Return a newly allocated string composed of the concatenation of |
+| STRING1, and STRING2.                                            |
+`-----------------------------------------------------------------*/
 
 
-static char *
-stringappend (const char *string1, int end1, const char *string2)
+char*
+stringappend (const char *string1, const char *string2)
 {
 {
-  register char *ostring;
-  register char *cp;
-  register const char *cp1;
-  register int i;
+  size_t len = strlen (string1) + strlen (string2);
+  char *res = XMALLOC (char, len + 1);
+  char *cp;
+  cp = stpcpy (res, string1);
+  cp = stpcpy (cp, string2);
+  return res;
+}
+
 
 
-  cp1 = string2;
-  i = 0;
-  while (*cp1++)
-    i++;
+/*-----------------------------------------------------------------.
+| Computes the macro name used to avoid double inclusion in the    |
+| header of the parser and store it in header_macro_name.  Be sure |
+| to produce valid CPP names (don't start with digit, remain       |
+| alphanumerical + underscore).                                    |
+`-----------------------------------------------------------------*/
 
 
-  ostring = XCALLOC (char, i + end1 + 1);
+char *
+compute_header_macro (void)
+{
+  const char *prefix = "BISON_";
+  char *macro_name, *cp;
 
 
-  cp = ostring;
-  cp1 = string1;
-  for (i = 0; i < end1; i++)
-    *cp++ = *cp1++;
+  if (spec_defines_file)
+    {
+      macro_name = XMALLOC (char,
+                           strlen (prefix) +
+                           strlen (spec_defines_file) + 1);
+      cp = stpcpy (macro_name, prefix);
+      cp = stpcpy (cp, spec_defines_file);
+    }
+  else
+    {
+      macro_name = XMALLOC (char,
+                           strlen (prefix) +
+                           strlen (base_name) +
+                           strlen (header_extension) + 1);
+      cp = stpcpy (macro_name, prefix);
+      cp = stpcpy (cp, base_name);
+      cp = stpcpy (cp, header_extension);
+    }
 
 
-  cp1 = string2;
-  while ((*cp++ = *cp1++))
-    ;
+  for (cp = macro_name; *cp; ++cp)
+    if (islower (*cp))
+      *cp = toupper (*cp);
+    else if (!isalnum (*cp))
+      *cp = '_';
 
 
-  return ostring;
+  return macro_name;
 }
 
 }
 
+
 /*-----------------------------------------------------------------.
 | Try to open file NAME with mode MODE, and print an error message |
 | if fails.                                                        |
 `-----------------------------------------------------------------*/
 
 /*-----------------------------------------------------------------.
 | Try to open file NAME with mode MODE, and print an error message |
 | if fails.                                                        |
 `-----------------------------------------------------------------*/
 
-static FILE *
+FILE *
 xfopen (const char *name, const char *mode)
 {
   FILE *ptr;
 xfopen (const char *name, const char *mode)
 {
   FILE *ptr;
@@ -120,7 +158,7 @@ xfopen (const char *name, const char *mode)
 | Try to close file PTR, and print an error message if fails.  |
 `-------------------------------------------------------------*/
 
 | Try to close file PTR, and print an error message if fails.  |
 `-------------------------------------------------------------*/
 
-static int
+int
 xfclose (FILE *ptr)
 {
   int result;
 xfclose (FILE *ptr)
 {
   int result;
@@ -135,230 +173,275 @@ xfclose (FILE *ptr)
   return result;
 }
 
   return result;
 }
 
-/*--------------------------------------------------.
-| Save the content of the obstack OBS in FILENAME.  |
-`--------------------------------------------------*/
-
-static void
-obstack_save (struct obstack *obs, const char *filename)
-{
-  FILE *out = xfopen (filename, "w");
-  size_t size = obstack_object_size (obs);
-  fwrite (obstack_finish (obs), 1, size, out);
-  xfclose (out);
-}
 
 
+/*------------------------------------------------------------------.
+| Return the path to the skeleton which locaction might be given in |
+| ENVVAR, otherwise return SKELETON_NAME.                           |
+`------------------------------------------------------------------*/
 
 
-static const char *
-skeleton_find (const char *envvar, const char *skeleton)
+const char *
+skeleton_find (const char *envvar, const char *skeleton_name)
 {
   const char *res = getenv (envvar);
 
 {
   const char *res = getenv (envvar);
 
-#ifdef MSDOS
-  const char *cp;
-
-  /* File doesn't exist in current directory; try in INIT directory.  */
-  if (!res && (cp = getenv ("INIT")))
+#if defined (MSDOS) || defined (_WIN32)
+  if (!res)
     {
     {
-      res = XMALLOC (char, strlen (cp) + strlen (skeleton) + 2);
-      sprintf (res, "%s%c%s", cp, '/', skeleton);
+      /* Skeleton file name without path */
+      const char *skel_name = strrchr (skeleton_name, '/');
+      if (!skel_name)
+        skel_name = strrchr (skeleton_name, '\\');
+      if (!skel_name)
+        skel_name = skeleton_name;
+      else
+        ++skel_name;
+
+      /* File doesn't exist in current directory; try in INIT directory.  */
+      const char *cp = getenv ("INIT");
+      if (cp)
+       {
+         res = XMALLOC (char, strlen (cp) + strlen (skel_name) + 2);
+         sprintf (res, "%s%c%s", cp, '\\', skel_name);
+       }
+      else if (access (skel_name, 4) == 0) /* Look in current dir. */
+        res = skel_name;
+      else
+       {
+         /* Look in program locations dir. */
+         extern char *program_name;
+         cp = strrchr(program_name, '\\');
+         if (!cp)
+           return skeleton_name;
+         else
+           ++cp;
+         res = XMALLOC (char, cp - program_name + strlen (skel_name) + 1);
+         strncpy (res, program_name, cp - program_name);
+         strcpy (res + (cp - program_name), skel_name);
+       }
     }
     }
-#endif /* !MSDOS */
-
+#endif /* defined (MSDOS) || defined (_WIN32) */
   if (!res)
   if (!res)
-    res = skeleton;
+    res = skeleton_name;
 
   return res;
 }
 
   return res;
 }
-
 \f
 \f
-/*-----------------------------------------------------------------.
-| Open the input file.  Look for the skeletons.  Find the names of |
-| the output files.  Prepare the obstacks.                         |
-`-----------------------------------------------------------------*/
 
 
-void
-open_files (void)
+/*----------------------------------------------------------------.
+| Compute BASE_NAME, SHORT_BASE_NAME and output files extensions. |
+`----------------------------------------------------------------*/
+
+/* Replace all characters FROM by TO in the string IN.
+   and returns a new allocated string.  */
+static char *
+tr (const char *in, char from, char to)
 {
 {
-  char *name_base;
-#ifdef MSDOS
-  register char *cp;
-#endif
-  int base_length;
-  int short_base_length;
-
-#if defined (VMS) & !defined (__VMS_POSIX)
-  const char *tmp_base = "sys$scratch:b_";
-#else
-  const char *tmp_base = "/tmp/b.";
-#endif
-  int tmp_len;
+  char *temp;
+  char *out;
+
+  out = XMALLOC (char, strlen (in) + 1);
+
+  for (temp = out; *in; in++, out++)
+    if (*in == from)
+      *out = to;
+    else
+      *out = *in;
+  *out = 0;
+  return (temp);
+}
 
 
-#ifdef MSDOS
-  tmp_base = getenv ("TMP");
-  if (tmp_base == 0)
-    tmp_base = "";
-  strlwr (infile);
-#endif /* MSDOS */
+/* Gets the extension index in FILENAME. Returns 0 if fails to
+   find an extension.  */
+static int
+get_extension_index (const char *filename)
+{
+  int len;
 
 
-#if (defined(_WIN32) && !defined(__CYGWIN32__))
-  tmp_base = getenv ("TEMP");  /* Windows95 defines this ... */
-  if (tmp_base == 0)
-    tmp_base = getenv ("Temp");        /* ... while NT prefers this */
-  if (tmp_base == 0)
-    tmp_base = "";
-  strlwr (infile);
-#endif /* _WIN32 && !__CYGWIN32__ */
+  len = strlen (filename);
 
 
-#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__EMX__))
-  {
-    char *tmp_ptr = getenv ("TMPDIR");
+  if (filename[len-- - 1] == '.')
+    return (0);
 
 
-    if (tmp_ptr != 0)
-      tmp_base = stringappend (tmp_ptr, strlen (tmp_ptr), "/b.");
-  }
-#endif /* unix || __unix || __unix__ */
+  while ((len > 0) && (filename[len - 1] != '.'))
+    if (filename[len - 1] == '/')
+      return (0);
+    else
+      len--;
 
 
-  tmp_len = strlen (tmp_base);
+  return (len - 1);
+}
+
+/* Computes extensions from the grammar file extension. */
+static void
+compute_exts_from_gf (const char *ext)
+{
+  src_extension = tr (ext, 'y', 'c');
+  src_extension = tr (src_extension, 'Y', 'C');
+  header_extension = tr (ext, 'y', 'h');
+  header_extension = tr (header_extension, 'Y', 'H');
+}
+
+/* Computes extensions from the given c source file extension. */
+static void
+compute_exts_from_src (const char *ext)
+{
+  /* We use this function when the user specifies `-o' or `--output',
+     so the extenions must be computed unconditionally from the file name
+     given by this option.  */
+  src_extension = xstrdup (ext);
+  header_extension = tr (ext, 'c', 'h');
+  header_extension = tr (header_extension, 'C', 'H');
+}
+
+/* FIXME: Should use xstrndup. */
+
+static void
+compute_base_names (void)
+{
+  size_t base_length;
+  size_t short_base_length;
+  size_t ext_index;
+
+  /* If --output=foo.c was specified (SPEC_OUTFILE == foo.c),
+     BASE_NAME and SHORT_BASE_NAME are `foo'.
+
+     If --output=foo.tab.c was specified, BASE_NAME is `foo.tab' and
+     SHORT_BASE_NAME is `foo'.
 
 
+     The precise -o name will be used for FTABLE.  For other output
+     files, remove the ".c" or ".tab.c" suffix.  */
   if (spec_outfile)
     {
   if (spec_outfile)
     {
-      /* -o was specified.  The precise -o name will be used for FTABLE.
-         For other output files, remove the ".c" or ".tab.c" suffix.  */
-      name_base = spec_outfile;
 #ifdef MSDOS
 #ifdef MSDOS
-      strlwr (name_base);
+      strlwr (spec_outfile);
 #endif /* MSDOS */
       /* BASE_LENGTH includes ".tab" but not ".c".  */
 #endif /* MSDOS */
       /* BASE_LENGTH includes ".tab" but not ".c".  */
-      base_length = strlen (name_base);
-      if (!strcmp (name_base + base_length - 2, ".c"))
-       base_length -= 2;
+      base_length = strlen (spec_outfile);
+
+      ext_index = get_extension_index (spec_outfile);
+      /* If the initial segment of extension contains 'c' or a 'C', I assume
+         that it is a C or C++ source file.  */
+      if (ext_index)
+       ext_index =
+         (strspn (spec_outfile + ext_index + 1, "cC")) ? ext_index : 0;
+      if (ext_index)
+       {
+         base_length -= strlen (spec_outfile + ext_index);
+         compute_exts_from_src (spec_outfile + ext_index);
+       }
+
+      base_name = strndup (spec_outfile, base_length);
       /* SHORT_BASE_LENGTH includes neither ".tab" nor ".c".  */
       short_base_length = base_length;
       /* SHORT_BASE_LENGTH includes neither ".tab" nor ".c".  */
       short_base_length = base_length;
-      if (!strncmp (name_base + short_base_length - 4, ".tab", 4))
-       short_base_length -= 4;
-      else if (!strncmp (name_base + short_base_length - 4, "_tab", 4))
+      if (strsuffix (base_name, ".tab") || strsuffix (base_name, "_tab"))
        short_base_length -= 4;
        short_base_length -= 4;
+      short_base_name = strndup (spec_outfile, short_base_length);
+
+      /* FIXME: This is a quick and dirty way for me to find out if we
+        should .tab or not, using the computations above.  */
+      if (strcmp (base_name, short_base_name))
+       tab_extension = 1;
+
+      return;
     }
     }
-  else if (spec_file_prefix)
+
+  /* If --file-prefix=foo was specified, BASE_NAME and SHORT_BASE_NAME
+     are `foo'.
+
+     Construct names from it.  */
+  if (spec_file_prefix)
     {
     {
-      /* -b was specified.  Construct names from it.  */
-      /* SHORT_BASE_LENGTH includes neither ".tab" nor ".c".  */
-      short_base_length = strlen (spec_file_prefix);
-      /* Count room for `.tab'.  */
-      base_length = short_base_length + 4;
-      name_base = XMALLOC (char, base_length + 1);
-      /* Append `.tab'.  */
-      strcpy (name_base, spec_file_prefix);
-      strcat (name_base, EXT_TAB);
 #ifdef MSDOS
 #ifdef MSDOS
-      strlwr (name_base);
+      strlwr (spec_file_prefix);
 #endif /* MSDOS */
 #endif /* MSDOS */
+      short_base_name = xstrdup (spec_file_prefix);
+      base_name = XMALLOC (char,
+                          strlen (short_base_name) + strlen (EXT_TAB) + 1);
+      stpcpy (stpcpy (base_name, short_base_name), EXT_TAB);
+
+      /* Computes the extensions from the garmmar file name.  */
+      ext_index = get_extension_index (infile);
+      /* If the initial segment of extension contains a 'y' or a 'Y', I assume
+         that it is a yacc or bison grammar file.  */
+      if (ext_index)
+       ext_index = (strspn (infile + ext_index + 1, "yY")) ? ext_index : 0;
+      if (ext_index)
+       compute_exts_from_gf (infile + ext_index);
+
+      /* It seems that when only a prefix is given, '.tab' should always be
+        used.  */
+      tab_extension = 1;
+
+      return;
     }
     }
-  else
-    {
-      /* -o was not specified; compute output file name from input
-         or use y.tab.c, etc., if -y was specified.  */
-
-      static char FIXED_NAME_BASE[] = "y.y";
 
 
-      name_base = yacc_flag ? FIXED_NAME_BASE : infile;
+  /* If neither -o nor --file-prefix were specified, and the input
+     file is foo.y, BASE_NAME is `foo.tab', and SHORT_BASE_NAME is
+     `foo'.
 
 
-      /* BASE_LENGTH gets length of NAME_BASE, sans ".y" suffix if any.  */
-
-      base_length = strlen (name_base);
-      if (!strcmp (name_base + base_length - 2, ".y"))
-       base_length -= 2;
-      short_base_length = base_length;
+     If --yacc is used, do as if the input file was `y.y'.  */
+  {
+    const char *name_base = yacc_flag ? "y.y" : infile;
 
 
-      name_base = stringappend (name_base, short_base_length, EXT_TAB);
-      base_length = short_base_length + 4;
-    }
+    /* BASE_LENGTH gets length of BASE_NAME, sans ".y" suffix if any.  */
 
 
-  finput = xfopen (infile, "r");
+    base_length = strlen (name_base);
 
 
-  if (!no_parser_flag)
-    fparser = xfopen (skeleton_find ("BISON_SIMPLE", BISON_SIMPLE), "r");
+    ext_index = get_extension_index (name_base);
+    /* If the initial segment of extension contains a 'y' or a 'Y', I assume
+       that it is a yacc or bison grammar file.  */
+    if (ext_index)
+      ext_index = (strspn (name_base + ext_index + 1, "yY")) ? ext_index : 0;
+    if (ext_index)
+      {
+       base_length -= strlen (name_base + ext_index);
+       compute_exts_from_gf (name_base + ext_index);
+      }
 
 
-  if (verbose_flag)
-    {
-      /* We used to use just .out if spec_name_prefix (-p) was used,
-         but that conflicts with Posix.  */
-      outfile = stringappend (name_base, short_base_length, EXT_OUTPUT);
-      foutput = xfopen (outfile, "w");
-    }
+    short_base_length = base_length;
+    short_base_name = strndup (name_base, short_base_length);
 
 
-  if (no_parser_flag)
-    {
-      /* use permanent name for actions file */
-      actfile = stringappend (name_base, short_base_length, ".act");
-    }
+    base_name = XMALLOC (char,
+                        strlen (short_base_name) + strlen (EXT_TAB) + 1);
+    stpcpy (stpcpy (base_name, short_base_name), EXT_TAB);
 
 
-  if (defines_flag)
-    {
-      defsfile = stringappend (name_base, base_length, ".h");
-    }
+    /* By default, Bison should insert '.tab' were needed.  */
+    tab_extension = 1;
 
 
-  /* These are opened by `done' or `open_extra_files', if at all */
-  if (spec_outfile)
-    tabfile = spec_outfile;
-  else
-    tabfile = stringappend (name_base, base_length, ".c");
-
-  attrsfile = stringappend (name_base, short_base_length, EXT_STYPE_H);
-  guardfile = stringappend (name_base, short_base_length, EXT_GUARD_C);
-
-  /* Initialize the obstacks. */
-  obstack_init (&action_obstack);
-  obstack_init (&attrs_obstack);
-  obstack_init (&table_obstack);
-  obstack_init (&defines_obstack);
+    return;
+  }
 }
 
 }
 
-
-
-/*--------------------------------------------------------------------.
-| Open the output files needed only for the semantic parser.  This    |
-| is done when %semantic_parser is seen in the declarations section.  |
-`--------------------------------------------------------------------*/
+/*-------------------------------------------------------.
+| Close the open files, compute the output files names.  |
+`-------------------------------------------------------*/
 
 void
 
 void
-open_extra_files (void)
+compute_output_file_names (void)
 {
 {
-  xfclose (fparser);
+  compute_base_names ();
 
 
-  if (!no_parser_flag)
-    fparser = xfopen (skeleton_find ("BISON_HAIRY", BISON_HAIRY), "r");
-  fguard = xfopen (guardfile, "w");
-}
+  parser_file_name =
+    spec_outfile ? spec_outfile : stringappend (base_name, src_extension);
 
 
+  /* If not yet done. */
+  if (!src_extension)
+    src_extension = ".c";
+  if (!header_extension)
+    header_extension = ".h";
 
 
-/*-----------------------------------------------------.
-| Close the open files, produce all the output files.  |
-`-----------------------------------------------------*/
+  /* It the defines filename if not given, we create it.  */
+  if (!spec_defines_file)
+    spec_defines_file = stringappend (base_name, header_extension);
 
 
-void
-output_files (void)
-{
-  xfclose (fguard);
-  xfclose (finput);
-  xfclose (fparser);
-  xfclose (foutput);
-
-  /* Output the main file.  */
-  obstack_save (&table_obstack, tabfile);
-
-  /* Output the header file if wanted. */
-  if (defines_flag)
-    obstack_save (&defines_obstack, defsfile);
-
-  /* If we output only the table, dump the actions in ACTFILE.
-     */
-  if (no_parser_flag)
-    obstack_save (&action_obstack, actfile);
-
-  /* If we produced a semantic parser ATTRS_OBSTACK must be dumped
-     into its own file, ATTTRSFILE.  */
-  if (semantic_parser)
-    obstack_save (&attrs_obstack, attrsfile);
+  /* It the graph filename if not given, we create it.  */
+  if (!spec_graph_file)
+    spec_graph_file = stringappend (short_base_name, ".vcg");
+
+  spec_verbose_file = stringappend (short_base_name, EXT_OUTPUT);
+
+  attrsfile = stringappend (short_base_name, EXT_STYPE_H);
+#ifndef MSDOS
+  attrsfile = stringappend (attrsfile, header_extension);
+#endif /* MSDOS */
 }
 }