-/* $Id: main.c,v 1.30 2010/11/24 15:13:39 tom Exp $ */
+/* $Id: main.c,v 1.39 2012/05/26 00:50:20 tom Exp $ */
#include <signal.h>
#include <unistd.h> /* for _exit() */
#include "defs.h"
+#if defined(HAVE_ATEXIT)
+# ifdef HAVE_MKSTEMP
+# define USE_MKSTEMP 1
+# elif defined(HAVE_FCNTL_H)
+# define USE_MKSTEMP 1
+# include <fcntl.h> /* for open(), O_EXCL, etc. */
+# else
+# define USE_MKSTEMP 0
+# endif
+#else
+# define USE_MKSTEMP 0
+#endif
+
+#if USE_MKSTEMP
+#include <sys/types.h>
+#include <sys/stat.h>
+
+typedef struct _my_tmpfiles
+{
+ struct _my_tmpfiles *next;
+ char *name;
+}
+MY_TMPFILES;
+
+static MY_TMPFILES *my_tmpfiles;
+#endif /* USE_MKSTEMP */
+
char dflag;
char gflag;
+char iflag;
char lflag;
static char oflag;
char rflag;
+char sflag;
char tflag;
char vflag;
char *code_file_name;
char *input_file_name = empty_string;
-static char *defines_file_name;
+char *defines_file_name;
+char *externs_file_name;
+
static char *graph_file_name;
static char *output_file_name;
static char *verbose_file_name;
/* with rules until the parser is written */
FILE *code_file; /* y.code.c (used when the -r option is specified) */
FILE *defines_file; /* y.tab.h */
+FILE *externs_file; /* y.tab.i */
FILE *input_file; /* the input file */
FILE *output_file; /* y.tab.c */
FILE *text_file; /* a temp file, used to save text until all */
if (dflag)
DO_FREE(defines_file_name);
+ if (iflag)
+ DO_FREE(externs_file_name);
+
if (oflag)
DO_FREE(output_file_name);
,"Options:"
," -b file_prefix set filename prefix (default \"y.\")"
," -d write definitions (y.tab.h)"
+ ," -i write interface (y.tab.i)"
," -g write a graphical description"
," -l suppress #line directives"
," -o output_file (default \"y.tab.c\")"
," -p symbol_prefix set symbol prefix (default \"yy\")"
," -P create a reentrant parser, e.g., \"%pure-parser\""
," -r produce separate code and table files (y.code.c)"
+ ," -s suppress #define's for quoted names in %token lines"
," -t add debugging support"
," -v write description (y.output)"
," -V show version information and exit"
gflag = 1;
break;
+ case 'i':
+ iflag = 1;
+ break;
+
case 'l':
lflag = 1;
break;
rflag = 1;
break;
+ case 's':
+ sflag = 1;
+ break;
+
case 't':
tflag = 1;
break;
input_file_name = argv[i];
}
-char *
+void *
allocate(size_t n)
{
- char *p;
+ void *p;
p = NULL;
if (n)
}
#define CREATE_FILE_NAME(dest, suffix) \
- dest = MALLOC(len + strlen(suffix) + 1); \
+ dest = TMALLOC(char, len + strlen(suffix) + 1); \
NO_SPACE(dest); \
strcpy(dest, file_prefix); \
strcpy(dest + len, suffix)
{
size_t len;
const char *defines_suffix;
+ const char *externs_suffix;
char *prefix;
prefix = NULL;
defines_suffix = DEFINES_SUFFIX;
+ externs_suffix = EXTERNS_SUFFIX;
/* compute the file_prefix from the user provided output_file_name */
if (output_file_name != 0)
{
if (!(prefix = strstr(output_file_name, ".tab.c"))
&& (prefix = strstr(output_file_name, ".c")))
+ {
defines_suffix = ".h";
+ externs_suffix = ".i";
+ }
}
if (prefix != NULL)
{
len = (size_t) (prefix - output_file_name);
- file_prefix = (char *)MALLOC(len + 1);
+ file_prefix = TMALLOC(char, len + 1);
NO_SPACE(file_prefix);
strncpy(file_prefix, output_file_name, len)[len] = 0;
}
CREATE_FILE_NAME(defines_file_name, defines_suffix);
}
+ if (iflag)
+ {
+ CREATE_FILE_NAME(externs_file_name, externs_suffix);
+ }
+
if (vflag)
{
CREATE_FILE_NAME(verbose_file_name, VERBOSE_SUFFIX);
}
}
+#if USE_MKSTEMP
+static void
+close_tmpfiles(void)
+{
+ while (my_tmpfiles != 0)
+ {
+ MY_TMPFILES *next = my_tmpfiles->next;
+
+ chmod(my_tmpfiles->name, 0644);
+ unlink(my_tmpfiles->name);
+
+ free(my_tmpfiles->name);
+ free(my_tmpfiles);
+
+ my_tmpfiles = next;
+ }
+}
+
+#ifndef HAVE_MKSTEMP
+static int
+my_mkstemp(char *temp)
+{
+ int fd;
+ char *dname;
+ char *fname;
+ char *name;
+
+ /*
+ * Split-up to use tempnam, rather than tmpnam; the latter (like
+ * mkstemp) is unusable on Windows.
+ */
+ if ((fname = strrchr(temp, '/')) != 0)
+ {
+ dname = strdup(temp);
+ dname[++fname - temp] = '\0';
+ }
+ else
+ {
+ dname = 0;
+ fname = temp;
+ }
+ if ((name = tempnam(dname, fname)) != 0)
+ {
+ fd = open(name, O_CREAT | O_EXCL | O_RDWR);
+ strcpy(temp, name);
+ }
+ else
+ {
+ fd = -1;
+ }
+
+ if (dname != 0)
+ free(dname);
+
+ return fd;
+}
+#define mkstemp(s) my_mkstemp(s)
+#endif
+
+#endif
+
+/*
+ * tmpfile() should be adequate, except that it may require special privileges
+ * to use, e.g., MinGW and Windows 7 where it tries to use the root directory.
+ */
+static FILE *
+open_tmpfile(const char *label)
+{
+ FILE *result;
+#if USE_MKSTEMP
+ int fd;
+ const char *tmpdir;
+ char *name;
+ const char *mark;
+
+ if ((tmpdir = getenv("TMPDIR")) == 0 || access(tmpdir, W_OK) != 0)
+ {
+#ifdef P_tmpdir
+ tmpdir = P_tmpdir;
+#else
+ tmpdir = "/tmp";
+#endif
+ if (access(tmpdir, W_OK) != 0)
+ tmpdir = ".";
+ }
+
+ name = malloc(strlen(tmpdir) + 10 + strlen(label));
+
+ result = 0;
+ if (name != 0)
+ {
+ if ((mark = strrchr(label, '_')) == 0)
+ mark = label + strlen(label);
+
+ sprintf(name, "%s/%.*sXXXXXX", tmpdir, (int)(mark - label), label);
+ fd = mkstemp(name);
+ if (fd >= 0)
+ {
+ result = fdopen(fd, "w+");
+ if (result != 0)
+ {
+ MY_TMPFILES *item;
+
+ if (my_tmpfiles == 0)
+ {
+ atexit(close_tmpfiles);
+ }
+
+ item = NEW(MY_TMPFILES);
+ NO_SPACE(item);
+
+ item->name = name;
+ NO_SPACE(item->name);
+
+ item->next = my_tmpfiles;
+ my_tmpfiles = item;
+ }
+ }
+ }
+#else
+ result = tmpfile();
+#endif
+
+ if (result == 0)
+ open_error(label);
+ return result;
+}
+
static void
open_files(void)
{
open_error(input_file_name);
}
- action_file = tmpfile();
- if (action_file == 0)
- open_error("action_file");
-
- text_file = tmpfile();
- if (text_file == 0)
- open_error("text_file");
+ action_file = open_tmpfile("action_file");
+ text_file = open_tmpfile("text_file");
if (vflag)
{
defines_file = fopen(defines_file_name, "w");
if (defines_file == 0)
open_error(defines_file_name);
- union_file = tmpfile();
- if (union_file == 0)
- open_error("union_file");
+ union_file = open_tmpfile("union_file");
+ }
+
+ if (iflag)
+ {
+ externs_file = fopen(externs_file_name, "w");
+ if (externs_file == 0)
+ open_error(externs_file_name);
}
output_file = fopen(output_file_name, "w");