+ ptr = fopen (name, mode);
+ if (!ptr)
+ error (2, errno, _("cannot open file `%s'"), name);
+
+ return ptr;
+}
+
+/*-------------------------------------------------------------.
+| Try to close file PTR, and print an error message if fails. |
+`-------------------------------------------------------------*/
+
+int
+xfclose (FILE *ptr)
+{
+ int result;
+
+ if (ptr == NULL)
+ return 0;
+
+ result = fclose (ptr);
+ if (result == EOF)
+ error (2, errno, _("cannot close file"));
+
+ 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);
+}
+
+/*---------------------------------------------------------------------.
+| Output double inclusion protection macros and saves defines_obstack |
+`---------------------------------------------------------------------*/
+
+static void
+defines_obstack_save (const char *filename)
+{
+ FILE *out = xfopen (filename, "w");
+ size_t size = obstack_object_size (&defines_obstack);
+ char *macro_name = compute_header_macro ();
+
+ fprintf (out, "#ifndef %s\n", macro_name);
+ fprintf (out, "# define %s\n\n", macro_name);
+ fwrite (obstack_finish (&defines_obstack), 1, size, out);
+ fprintf (out, "\n#endif /* not %s */\n", macro_name);
+
+ free (macro_name);
+ xfclose (out);
+}
+
+/*------------------------------------------------------------------.
+| Return the path to the skeleton which locaction might be given in |
+| ENVVAR, otherwise return SKELETON_NAME. |
+`------------------------------------------------------------------*/
+
+const char *
+skeleton_find (const char *envvar, const char *skeleton_name)
+{
+ const char *res = getenv (envvar);
+
+#if defined (MSDOS) || defined (_WIN32)
+ if (!res)
+ {
+ /* 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 /* defined (MSDOS) || defined (_WIN32) */
+ if (!res)
+ res = skeleton_name;
+
+ return res;
+}
+\f
+
+/*----------------------------------------------------------------.
+| 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 *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);
+}
+
+/* Gets the extension index in FILENAME. Returns 0 if fails to
+ find an extension. */
+static int
+get_extension_index (const char *filename)
+{
+ int len;
+
+ len = strlen (filename);
+
+ if (filename[len-- - 1] == '.')
+ return (0);
+
+ while ((len > 0) && (filename[len - 1] != '.'))
+ if (filename[len - 1] == '/')
+ return (0);
+ else
+ len--;
+
+ 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');
+}