1*0a6a1f1dSLionel Sambuc /* $NetBSD: main.c,v 1.11 2015/01/04 01:34:20 christos Exp $ */
24a17663cSThomas Veerman
34a17663cSThomas Veerman #include "defs.h"
44a17663cSThomas Veerman
54a17663cSThomas Veerman #include <sys/cdefs.h>
6*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: main.c,v 1.11 2015/01/04 01:34:20 christos Exp $");
7*0a6a1f1dSLionel Sambuc /* Id: main.c,v 1.54 2014/10/06 22:40:07 tom Exp */
84a17663cSThomas Veerman
94a17663cSThomas Veerman #include <signal.h>
10*0a6a1f1dSLionel Sambuc #ifndef _WIN32
114a17663cSThomas Veerman #include <unistd.h> /* for _exit() */
12*0a6a1f1dSLionel Sambuc #else
13*0a6a1f1dSLionel Sambuc #include <stdlib.h> /* for _exit() */
14*0a6a1f1dSLionel Sambuc #endif
154a17663cSThomas Veerman
164a17663cSThomas Veerman
174a17663cSThomas Veerman #ifdef HAVE_MKSTEMP
184a17663cSThomas Veerman # define USE_MKSTEMP 1
194a17663cSThomas Veerman #elif defined(HAVE_FCNTL_H)
204a17663cSThomas Veerman # define USE_MKSTEMP 1
214a17663cSThomas Veerman # include <fcntl.h> /* for open(), O_EXCL, etc. */
224a17663cSThomas Veerman #else
234a17663cSThomas Veerman # define USE_MKSTEMP 0
244a17663cSThomas Veerman #endif
254a17663cSThomas Veerman
264a17663cSThomas Veerman #if USE_MKSTEMP
274a17663cSThomas Veerman #include <sys/types.h>
284a17663cSThomas Veerman #include <sys/stat.h>
294a17663cSThomas Veerman
304a17663cSThomas Veerman typedef struct _my_tmpfiles
314a17663cSThomas Veerman {
324a17663cSThomas Veerman struct _my_tmpfiles *next;
334a17663cSThomas Veerman char *name;
344a17663cSThomas Veerman }
354a17663cSThomas Veerman MY_TMPFILES;
364a17663cSThomas Veerman
374a17663cSThomas Veerman static MY_TMPFILES *my_tmpfiles;
384a17663cSThomas Veerman #endif /* USE_MKSTEMP */
394a17663cSThomas Veerman
404a17663cSThomas Veerman char dflag;
414a17663cSThomas Veerman char gflag;
424a17663cSThomas Veerman char iflag;
434a17663cSThomas Veerman char lflag;
444a17663cSThomas Veerman static char oflag;
454a17663cSThomas Veerman char rflag;
4684d9c625SLionel Sambuc char sflag;
474a17663cSThomas Veerman char tflag;
484a17663cSThomas Veerman char vflag;
494a17663cSThomas Veerman
504a17663cSThomas Veerman const char *symbol_prefix;
514a17663cSThomas Veerman const char *myname = "yacc";
524a17663cSThomas Veerman
534a17663cSThomas Veerman int lineno;
544a17663cSThomas Veerman int outline;
554a17663cSThomas Veerman
564a17663cSThomas Veerman static char empty_string[] = "";
574a17663cSThomas Veerman static char default_file_prefix[] = "y";
584a17663cSThomas Veerman static int explicit_file_name;
594a17663cSThomas Veerman
604a17663cSThomas Veerman static char *file_prefix = default_file_prefix;
614a17663cSThomas Veerman
624a17663cSThomas Veerman char *code_file_name;
634a17663cSThomas Veerman char *input_file_name = empty_string;
644a17663cSThomas Veerman char *defines_file_name;
654a17663cSThomas Veerman char *externs_file_name;
664a17663cSThomas Veerman
674a17663cSThomas Veerman static char *graph_file_name;
684a17663cSThomas Veerman static char *output_file_name;
694a17663cSThomas Veerman static char *verbose_file_name;
704a17663cSThomas Veerman
714a17663cSThomas Veerman FILE *action_file; /* a temp file, used to save actions associated */
724a17663cSThomas Veerman /* with rules until the parser is written */
734a17663cSThomas Veerman FILE *code_file; /* y.code.c (used when the -r option is specified) */
744a17663cSThomas Veerman FILE *defines_file; /* y.tab.h */
754a17663cSThomas Veerman FILE *externs_file; /* y.tab.i */
764a17663cSThomas Veerman FILE *input_file; /* the input file */
774a17663cSThomas Veerman FILE *output_file; /* y.tab.c */
784a17663cSThomas Veerman FILE *text_file; /* a temp file, used to save text until all */
794a17663cSThomas Veerman /* symbols have been defined */
804a17663cSThomas Veerman FILE *union_file; /* a temp file, used to save the union */
814a17663cSThomas Veerman /* definition until all symbol have been */
824a17663cSThomas Veerman /* defined */
834a17663cSThomas Veerman FILE *verbose_file; /* y.output */
844a17663cSThomas Veerman FILE *graph_file; /* y.dot */
854a17663cSThomas Veerman
86*0a6a1f1dSLionel Sambuc Value_t nitems;
87*0a6a1f1dSLionel Sambuc Value_t nrules;
88*0a6a1f1dSLionel Sambuc Value_t nsyms;
89*0a6a1f1dSLionel Sambuc Value_t ntokens;
90*0a6a1f1dSLionel Sambuc Value_t nvars;
914a17663cSThomas Veerman
924a17663cSThomas Veerman Value_t start_symbol;
934a17663cSThomas Veerman char **symbol_name;
944a17663cSThomas Veerman char **symbol_pname;
954a17663cSThomas Veerman Value_t *symbol_value;
96*0a6a1f1dSLionel Sambuc Value_t *symbol_prec;
974a17663cSThomas Veerman char *symbol_assoc;
984a17663cSThomas Veerman
994a17663cSThomas Veerman int pure_parser;
100*0a6a1f1dSLionel Sambuc int token_table;
101*0a6a1f1dSLionel Sambuc int error_verbose;
102*0a6a1f1dSLionel Sambuc
103*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
104*0a6a1f1dSLionel Sambuc Value_t *symbol_pval;
105*0a6a1f1dSLionel Sambuc char **symbol_destructor;
106*0a6a1f1dSLionel Sambuc char **symbol_type_tag;
107*0a6a1f1dSLionel Sambuc int locations = 0; /* default to no position processing */
108*0a6a1f1dSLionel Sambuc int backtrack = 0; /* default is no backtracking */
109*0a6a1f1dSLionel Sambuc char *initial_action = NULL;
110*0a6a1f1dSLionel Sambuc #endif
111*0a6a1f1dSLionel Sambuc
1124a17663cSThomas Veerman int exit_code;
1134a17663cSThomas Veerman
1144a17663cSThomas Veerman Value_t *ritem;
1154a17663cSThomas Veerman Value_t *rlhs;
1164a17663cSThomas Veerman Value_t *rrhs;
1174a17663cSThomas Veerman Value_t *rprec;
1184a17663cSThomas Veerman Assoc_t *rassoc;
1194a17663cSThomas Veerman Value_t **derives;
1204a17663cSThomas Veerman char *nullable;
1214a17663cSThomas Veerman
1224a17663cSThomas Veerman /*
1234a17663cSThomas Veerman * Since fclose() is called via the signal handler, it might die. Don't loop
1244a17663cSThomas Veerman * if there is a problem closing a file.
1254a17663cSThomas Veerman */
1264a17663cSThomas Veerman #define DO_CLOSE(fp) \
1274a17663cSThomas Veerman if (fp != 0) { \
1284a17663cSThomas Veerman FILE *use = fp; \
1294a17663cSThomas Veerman fp = 0; \
1304a17663cSThomas Veerman fclose(use); \
1314a17663cSThomas Veerman }
1324a17663cSThomas Veerman
1334a17663cSThomas Veerman static int got_intr = 0;
1344a17663cSThomas Veerman
1354a17663cSThomas Veerman void
done(int k)1364a17663cSThomas Veerman done(int k)
1374a17663cSThomas Veerman {
1384a17663cSThomas Veerman DO_CLOSE(input_file);
1394a17663cSThomas Veerman DO_CLOSE(output_file);
140*0a6a1f1dSLionel Sambuc if (iflag)
141*0a6a1f1dSLionel Sambuc DO_CLOSE(externs_file);
142*0a6a1f1dSLionel Sambuc if (rflag)
143*0a6a1f1dSLionel Sambuc DO_CLOSE(code_file);
1444a17663cSThomas Veerman
1454a17663cSThomas Veerman DO_CLOSE(action_file);
1464a17663cSThomas Veerman DO_CLOSE(defines_file);
1474a17663cSThomas Veerman DO_CLOSE(graph_file);
1484a17663cSThomas Veerman DO_CLOSE(text_file);
1494a17663cSThomas Veerman DO_CLOSE(union_file);
1504a17663cSThomas Veerman DO_CLOSE(verbose_file);
1514a17663cSThomas Veerman
1524a17663cSThomas Veerman if (got_intr)
1534a17663cSThomas Veerman _exit(EXIT_FAILURE);
1544a17663cSThomas Veerman
1554a17663cSThomas Veerman #ifdef NO_LEAKS
1564a17663cSThomas Veerman if (rflag)
1574a17663cSThomas Veerman DO_FREE(code_file_name);
1584a17663cSThomas Veerman
1594a17663cSThomas Veerman if (dflag)
1604a17663cSThomas Veerman DO_FREE(defines_file_name);
1614a17663cSThomas Veerman
1624a17663cSThomas Veerman if (iflag)
1634a17663cSThomas Veerman DO_FREE(externs_file_name);
1644a17663cSThomas Veerman
1654a17663cSThomas Veerman if (oflag)
1664a17663cSThomas Veerman DO_FREE(output_file_name);
1674a17663cSThomas Veerman
1684a17663cSThomas Veerman if (vflag)
1694a17663cSThomas Veerman DO_FREE(verbose_file_name);
1704a17663cSThomas Veerman
1714a17663cSThomas Veerman if (gflag)
1724a17663cSThomas Veerman DO_FREE(graph_file_name);
1734a17663cSThomas Veerman
1744a17663cSThomas Veerman lr0_leaks();
1754a17663cSThomas Veerman lalr_leaks();
1764a17663cSThomas Veerman mkpar_leaks();
177*0a6a1f1dSLionel Sambuc mstring_leaks();
1784a17663cSThomas Veerman output_leaks();
1794a17663cSThomas Veerman reader_leaks();
1804a17663cSThomas Veerman #endif
1814a17663cSThomas Veerman
1824a17663cSThomas Veerman exit(k);
1834a17663cSThomas Veerman }
1844a17663cSThomas Veerman
1854a17663cSThomas Veerman static void
onintr(int sig GCC_UNUSED)1864a17663cSThomas Veerman onintr(int sig GCC_UNUSED)
1874a17663cSThomas Veerman {
1884a17663cSThomas Veerman got_intr = 1;
1894a17663cSThomas Veerman done(EXIT_FAILURE);
1904a17663cSThomas Veerman }
1914a17663cSThomas Veerman
1924a17663cSThomas Veerman static void
set_signals(void)1934a17663cSThomas Veerman set_signals(void)
1944a17663cSThomas Veerman {
1954a17663cSThomas Veerman #ifdef SIGINT
1964a17663cSThomas Veerman if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1974a17663cSThomas Veerman signal(SIGINT, onintr);
1984a17663cSThomas Veerman #endif
1994a17663cSThomas Veerman #ifdef SIGTERM
2004a17663cSThomas Veerman if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
2014a17663cSThomas Veerman signal(SIGTERM, onintr);
2024a17663cSThomas Veerman #endif
2034a17663cSThomas Veerman #ifdef SIGHUP
2044a17663cSThomas Veerman if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
2054a17663cSThomas Veerman signal(SIGHUP, onintr);
2064a17663cSThomas Veerman #endif
2074a17663cSThomas Veerman }
2084a17663cSThomas Veerman
2094a17663cSThomas Veerman static void
usage(void)2104a17663cSThomas Veerman usage(void)
2114a17663cSThomas Veerman {
2124a17663cSThomas Veerman static const char *msg[] =
2134a17663cSThomas Veerman {
2144a17663cSThomas Veerman ""
2154a17663cSThomas Veerman ,"Options:"
2164a17663cSThomas Veerman ," -b file_prefix set filename prefix (default \"y.\")"
217*0a6a1f1dSLionel Sambuc ," -B create a backtracking parser"
218*0a6a1f1dSLionel Sambuc ," -d write definitions (" DEFINES_SUFFIX ")"
2194a17663cSThomas Veerman ," -i write interface (y.tab.i)"
2204a17663cSThomas Veerman ," -g write a graphical description"
2214a17663cSThomas Veerman ," -l suppress #line directives"
222*0a6a1f1dSLionel Sambuc ," -L enable position processing, e.g., \"%locations\""
223*0a6a1f1dSLionel Sambuc ," -o output_file (default \"" OUTPUT_SUFFIX "\")"
2244a17663cSThomas Veerman ," -p symbol_prefix set symbol prefix (default \"yy\")"
2254a17663cSThomas Veerman ," -P create a reentrant parser, e.g., \"%pure-parser\""
2264a17663cSThomas Veerman ," -r produce separate code and table files (y.code.c)"
22784d9c625SLionel Sambuc ," -s suppress #define's for quoted names in %token lines"
2284a17663cSThomas Veerman ," -t add debugging support"
2294a17663cSThomas Veerman ," -v write description (y.output)"
2304a17663cSThomas Veerman ," -V show version information and exit"
2314a17663cSThomas Veerman };
2324a17663cSThomas Veerman unsigned n;
2334a17663cSThomas Veerman
2344a17663cSThomas Veerman fflush(stdout);
2354a17663cSThomas Veerman fprintf(stderr, "Usage: %s [options] filename\n", myname);
2364a17663cSThomas Veerman for (n = 0; n < sizeof(msg) / sizeof(msg[0]); ++n)
2374a17663cSThomas Veerman fprintf(stderr, "%s\n", msg[n]);
2384a17663cSThomas Veerman
2394a17663cSThomas Veerman exit(1);
2404a17663cSThomas Veerman }
2414a17663cSThomas Veerman
2424a17663cSThomas Veerman static void
setflag(int ch)2434a17663cSThomas Veerman setflag(int ch)
2444a17663cSThomas Veerman {
2454a17663cSThomas Veerman switch (ch)
2464a17663cSThomas Veerman {
247*0a6a1f1dSLionel Sambuc case 'B':
248*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
249*0a6a1f1dSLionel Sambuc backtrack = 1;
250*0a6a1f1dSLionel Sambuc #else
251*0a6a1f1dSLionel Sambuc unsupported_flag_warning("-B", "reconfigure with --enable-btyacc");
252*0a6a1f1dSLionel Sambuc #endif
253*0a6a1f1dSLionel Sambuc break;
254*0a6a1f1dSLionel Sambuc
2554a17663cSThomas Veerman case 'd':
2564a17663cSThomas Veerman dflag = 1;
2574a17663cSThomas Veerman break;
2584a17663cSThomas Veerman
2594a17663cSThomas Veerman case 'g':
2604a17663cSThomas Veerman gflag = 1;
2614a17663cSThomas Veerman break;
2624a17663cSThomas Veerman
2634a17663cSThomas Veerman case 'i':
2644a17663cSThomas Veerman iflag = 1;
2654a17663cSThomas Veerman break;
2664a17663cSThomas Veerman
2674a17663cSThomas Veerman case 'l':
2684a17663cSThomas Veerman lflag = 1;
2694a17663cSThomas Veerman break;
2704a17663cSThomas Veerman
271*0a6a1f1dSLionel Sambuc case 'L':
272*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
273*0a6a1f1dSLionel Sambuc locations = 1;
274*0a6a1f1dSLionel Sambuc #else
275*0a6a1f1dSLionel Sambuc unsupported_flag_warning("-B", "reconfigure with --enable-btyacc");
276*0a6a1f1dSLionel Sambuc #endif
277*0a6a1f1dSLionel Sambuc break;
278*0a6a1f1dSLionel Sambuc
2794a17663cSThomas Veerman case 'P':
2804a17663cSThomas Veerman pure_parser = 1;
2814a17663cSThomas Veerman break;
2824a17663cSThomas Veerman
2834a17663cSThomas Veerman case 'r':
2844a17663cSThomas Veerman rflag = 1;
2854a17663cSThomas Veerman break;
2864a17663cSThomas Veerman
28784d9c625SLionel Sambuc case 's':
28884d9c625SLionel Sambuc sflag = 1;
28984d9c625SLionel Sambuc break;
29084d9c625SLionel Sambuc
2914a17663cSThomas Veerman case 't':
2924a17663cSThomas Veerman tflag = 1;
2934a17663cSThomas Veerman break;
2944a17663cSThomas Veerman
2954a17663cSThomas Veerman case 'v':
2964a17663cSThomas Veerman vflag = 1;
2974a17663cSThomas Veerman break;
2984a17663cSThomas Veerman
2994a17663cSThomas Veerman case 'V':
3004a17663cSThomas Veerman printf("%s - %s\n", myname, VERSION);
3014a17663cSThomas Veerman exit(EXIT_SUCCESS);
3024a17663cSThomas Veerman
3034a17663cSThomas Veerman case 'y':
3044a17663cSThomas Veerman /* noop for bison compatibility. byacc is already designed to be posix
3054a17663cSThomas Veerman * yacc compatible. */
3064a17663cSThomas Veerman break;
3074a17663cSThomas Veerman
3084a17663cSThomas Veerman default:
3094a17663cSThomas Veerman usage();
3104a17663cSThomas Veerman }
3114a17663cSThomas Veerman }
3124a17663cSThomas Veerman
3134a17663cSThomas Veerman static void
getargs(int argc,char * argv[])3144a17663cSThomas Veerman getargs(int argc, char *argv[])
3154a17663cSThomas Veerman {
3164a17663cSThomas Veerman int i;
3174a17663cSThomas Veerman char *s;
3184a17663cSThomas Veerman int ch;
3194a17663cSThomas Veerman
3204a17663cSThomas Veerman if (argc > 0)
3214a17663cSThomas Veerman myname = argv[0];
3224a17663cSThomas Veerman
3234a17663cSThomas Veerman for (i = 1; i < argc; ++i)
3244a17663cSThomas Veerman {
3254a17663cSThomas Veerman s = argv[i];
3264a17663cSThomas Veerman if (*s != '-')
3274a17663cSThomas Veerman break;
3284a17663cSThomas Veerman switch (ch = *++s)
3294a17663cSThomas Veerman {
3304a17663cSThomas Veerman case '\0':
3314a17663cSThomas Veerman input_file = stdin;
3324a17663cSThomas Veerman if (i + 1 < argc)
3334a17663cSThomas Veerman usage();
3344a17663cSThomas Veerman return;
3354a17663cSThomas Veerman
3364a17663cSThomas Veerman case '-':
3374a17663cSThomas Veerman ++i;
3384a17663cSThomas Veerman goto no_more_options;
3394a17663cSThomas Veerman
3404a17663cSThomas Veerman case 'b':
3414a17663cSThomas Veerman if (*++s)
3424a17663cSThomas Veerman file_prefix = s;
3434a17663cSThomas Veerman else if (++i < argc)
3444a17663cSThomas Veerman file_prefix = argv[i];
3454a17663cSThomas Veerman else
3464a17663cSThomas Veerman usage();
3474a17663cSThomas Veerman continue;
3484a17663cSThomas Veerman
3494a17663cSThomas Veerman case 'o':
3504a17663cSThomas Veerman if (*++s)
3514a17663cSThomas Veerman output_file_name = s;
3524a17663cSThomas Veerman else if (++i < argc)
3534a17663cSThomas Veerman output_file_name = argv[i];
3544a17663cSThomas Veerman else
3554a17663cSThomas Veerman usage();
3564a17663cSThomas Veerman explicit_file_name = 1;
3574a17663cSThomas Veerman continue;
3584a17663cSThomas Veerman
3594a17663cSThomas Veerman case 'p':
3604a17663cSThomas Veerman if (*++s)
3614a17663cSThomas Veerman symbol_prefix = s;
3624a17663cSThomas Veerman else if (++i < argc)
3634a17663cSThomas Veerman symbol_prefix = argv[i];
3644a17663cSThomas Veerman else
3654a17663cSThomas Veerman usage();
3664a17663cSThomas Veerman continue;
3674a17663cSThomas Veerman
3684a17663cSThomas Veerman default:
3694a17663cSThomas Veerman setflag(ch);
3704a17663cSThomas Veerman break;
3714a17663cSThomas Veerman }
3724a17663cSThomas Veerman
3734a17663cSThomas Veerman for (;;)
3744a17663cSThomas Veerman {
3754a17663cSThomas Veerman switch (ch = *++s)
3764a17663cSThomas Veerman {
3774a17663cSThomas Veerman case '\0':
3784a17663cSThomas Veerman goto end_of_option;
3794a17663cSThomas Veerman
3804a17663cSThomas Veerman default:
3814a17663cSThomas Veerman setflag(ch);
3824a17663cSThomas Veerman break;
3834a17663cSThomas Veerman }
3844a17663cSThomas Veerman }
3854a17663cSThomas Veerman end_of_option:;
3864a17663cSThomas Veerman }
3874a17663cSThomas Veerman
3884a17663cSThomas Veerman no_more_options:;
3894a17663cSThomas Veerman if (i + 1 != argc)
3904a17663cSThomas Veerman usage();
3914a17663cSThomas Veerman input_file_name = argv[i];
3924a17663cSThomas Veerman }
3934a17663cSThomas Veerman
3944a17663cSThomas Veerman void *
allocate(size_t n)3954a17663cSThomas Veerman allocate(size_t n)
3964a17663cSThomas Veerman {
3974a17663cSThomas Veerman void *p;
3984a17663cSThomas Veerman
3994a17663cSThomas Veerman p = NULL;
4004a17663cSThomas Veerman if (n)
4014a17663cSThomas Veerman {
4024a17663cSThomas Veerman p = CALLOC(1, n);
4034a17663cSThomas Veerman NO_SPACE(p);
4044a17663cSThomas Veerman }
4054a17663cSThomas Veerman return (p);
4064a17663cSThomas Veerman }
4074a17663cSThomas Veerman
4084a17663cSThomas Veerman #define CREATE_FILE_NAME(dest, suffix) \
409*0a6a1f1dSLionel Sambuc dest = alloc_file_name(len, suffix)
410*0a6a1f1dSLionel Sambuc
411*0a6a1f1dSLionel Sambuc static char *
alloc_file_name(size_t len,const char * suffix)412*0a6a1f1dSLionel Sambuc alloc_file_name(size_t len, const char *suffix)
413*0a6a1f1dSLionel Sambuc {
414*0a6a1f1dSLionel Sambuc char *result = TMALLOC(char, len + strlen(suffix) + 1);
415*0a6a1f1dSLionel Sambuc if (result == 0)
416*0a6a1f1dSLionel Sambuc no_space();
417*0a6a1f1dSLionel Sambuc strcpy(result, file_prefix);
418*0a6a1f1dSLionel Sambuc strcpy(result + len, suffix);
419*0a6a1f1dSLionel Sambuc return result;
420*0a6a1f1dSLionel Sambuc }
4214a17663cSThomas Veerman
4224a17663cSThomas Veerman static void
create_file_names(void)4234a17663cSThomas Veerman create_file_names(void)
4244a17663cSThomas Veerman {
4254a17663cSThomas Veerman size_t len;
4264a17663cSThomas Veerman const char *defines_suffix;
4274a17663cSThomas Veerman const char *externs_suffix;
4284a17663cSThomas Veerman char *prefix;
4294a17663cSThomas Veerman
4304a17663cSThomas Veerman prefix = NULL;
4314a17663cSThomas Veerman defines_suffix = DEFINES_SUFFIX;
4324a17663cSThomas Veerman externs_suffix = EXTERNS_SUFFIX;
4334a17663cSThomas Veerman
4344a17663cSThomas Veerman /* compute the file_prefix from the user provided output_file_name */
4354a17663cSThomas Veerman if (output_file_name != 0)
4364a17663cSThomas Veerman {
437*0a6a1f1dSLionel Sambuc if (!(prefix = strstr(output_file_name, OUTPUT_SUFFIX))
4384a17663cSThomas Veerman && (prefix = strstr(output_file_name, ".c")))
4394a17663cSThomas Veerman {
4404a17663cSThomas Veerman defines_suffix = ".h";
4414a17663cSThomas Veerman externs_suffix = ".i";
4424a17663cSThomas Veerman }
4434a17663cSThomas Veerman }
4444a17663cSThomas Veerman
4454a17663cSThomas Veerman if (prefix != NULL)
4464a17663cSThomas Veerman {
4474a17663cSThomas Veerman len = (size_t) (prefix - output_file_name);
44884d9c625SLionel Sambuc file_prefix = TMALLOC(char, len + 1);
4494a17663cSThomas Veerman NO_SPACE(file_prefix);
4504a17663cSThomas Veerman strncpy(file_prefix, output_file_name, len)[len] = 0;
4514a17663cSThomas Veerman }
4524a17663cSThomas Veerman else
4534a17663cSThomas Veerman len = strlen(file_prefix);
4544a17663cSThomas Veerman
4554a17663cSThomas Veerman /* if "-o filename" was not given */
4564a17663cSThomas Veerman if (output_file_name == 0)
4574a17663cSThomas Veerman {
4584a17663cSThomas Veerman oflag = 1;
4594a17663cSThomas Veerman CREATE_FILE_NAME(output_file_name, OUTPUT_SUFFIX);
4604a17663cSThomas Veerman }
4614a17663cSThomas Veerman
4624a17663cSThomas Veerman if (rflag)
4634a17663cSThomas Veerman {
4644a17663cSThomas Veerman CREATE_FILE_NAME(code_file_name, CODE_SUFFIX);
4654a17663cSThomas Veerman }
4664a17663cSThomas Veerman else
4674a17663cSThomas Veerman code_file_name = output_file_name;
4684a17663cSThomas Veerman
4694a17663cSThomas Veerman if (dflag)
4704a17663cSThomas Veerman {
4714a17663cSThomas Veerman if (explicit_file_name)
4724a17663cSThomas Veerman {
4734a17663cSThomas Veerman char *suffix;
4744a17663cSThomas Veerman defines_file_name = strdup(output_file_name);
4754a17663cSThomas Veerman if (defines_file_name == 0)
4764a17663cSThomas Veerman no_space();
4774a17663cSThomas Veerman /* does the output_file_name have a known suffix */
4784a17663cSThomas Veerman suffix = strrchr(output_file_name, '.');
4794a17663cSThomas Veerman if (suffix != 0 &&
4804a17663cSThomas Veerman (!strcmp(suffix, ".c") || /* good, old-fashioned C */
4814a17663cSThomas Veerman !strcmp(suffix, ".C") || /* C++, or C on Windows */
4824a17663cSThomas Veerman !strcmp(suffix, ".cc") || /* C++ */
4834a17663cSThomas Veerman !strcmp(suffix, ".cxx") || /* C++ */
4844a17663cSThomas Veerman !strcmp(suffix, ".cpp"))) /* C++ (Windows) */
4854a17663cSThomas Veerman {
4864a17663cSThomas Veerman strncpy(defines_file_name, output_file_name,
4874a17663cSThomas Veerman suffix - output_file_name + 1);
4884a17663cSThomas Veerman defines_file_name[suffix - output_file_name + 1] = 'h';
4894a17663cSThomas Veerman defines_file_name[suffix - output_file_name + 2] = 0;
4904a17663cSThomas Veerman } else {
4914a17663cSThomas Veerman fprintf(stderr,"%s: suffix of output file name %s"
4924a17663cSThomas Veerman " not recognized, no -d file generated.\n",
4934a17663cSThomas Veerman myname, output_file_name);
4944a17663cSThomas Veerman dflag = 0;
4954a17663cSThomas Veerman free(defines_file_name);
4964a17663cSThomas Veerman defines_file_name = 0;
4974a17663cSThomas Veerman }
4984a17663cSThomas Veerman } else {
4994a17663cSThomas Veerman CREATE_FILE_NAME(defines_file_name, defines_suffix);
5004a17663cSThomas Veerman }
5014a17663cSThomas Veerman }
5024a17663cSThomas Veerman
5034a17663cSThomas Veerman if (iflag)
5044a17663cSThomas Veerman {
5054a17663cSThomas Veerman CREATE_FILE_NAME(externs_file_name, externs_suffix);
5064a17663cSThomas Veerman }
5074a17663cSThomas Veerman
5084a17663cSThomas Veerman if (vflag)
5094a17663cSThomas Veerman {
5104a17663cSThomas Veerman CREATE_FILE_NAME(verbose_file_name, VERBOSE_SUFFIX);
5114a17663cSThomas Veerman }
5124a17663cSThomas Veerman
5134a17663cSThomas Veerman if (gflag)
5144a17663cSThomas Veerman {
5154a17663cSThomas Veerman CREATE_FILE_NAME(graph_file_name, GRAPH_SUFFIX);
5164a17663cSThomas Veerman }
5174a17663cSThomas Veerman
5184a17663cSThomas Veerman if (prefix != NULL)
5194a17663cSThomas Veerman {
5204a17663cSThomas Veerman FREE(file_prefix);
5214a17663cSThomas Veerman }
5224a17663cSThomas Veerman }
5234a17663cSThomas Veerman
5244a17663cSThomas Veerman #if USE_MKSTEMP
5254a17663cSThomas Veerman static void
close_tmpfiles(void)5264a17663cSThomas Veerman close_tmpfiles(void)
5274a17663cSThomas Veerman {
5284a17663cSThomas Veerman while (my_tmpfiles != 0)
5294a17663cSThomas Veerman {
5304a17663cSThomas Veerman MY_TMPFILES *next = my_tmpfiles->next;
5314a17663cSThomas Veerman
532*0a6a1f1dSLionel Sambuc (void)chmod(my_tmpfiles->name, 0644);
533*0a6a1f1dSLionel Sambuc (void)unlink(my_tmpfiles->name);
5344a17663cSThomas Veerman
5354a17663cSThomas Veerman free(my_tmpfiles->name);
5364a17663cSThomas Veerman free(my_tmpfiles);
5374a17663cSThomas Veerman
5384a17663cSThomas Veerman my_tmpfiles = next;
5394a17663cSThomas Veerman }
5404a17663cSThomas Veerman }
5414a17663cSThomas Veerman
5424a17663cSThomas Veerman #ifndef HAVE_MKSTEMP
5434a17663cSThomas Veerman static int
my_mkstemp(char * temp)5444a17663cSThomas Veerman my_mkstemp(char *temp)
5454a17663cSThomas Veerman {
5464a17663cSThomas Veerman int fd;
5474a17663cSThomas Veerman char *dname;
5484a17663cSThomas Veerman char *fname;
5494a17663cSThomas Veerman char *name;
5504a17663cSThomas Veerman
5514a17663cSThomas Veerman /*
5524a17663cSThomas Veerman * Split-up to use tempnam, rather than tmpnam; the latter (like
5534a17663cSThomas Veerman * mkstemp) is unusable on Windows.
5544a17663cSThomas Veerman */
5554a17663cSThomas Veerman if ((fname = strrchr(temp, '/')) != 0)
5564a17663cSThomas Veerman {
5574a17663cSThomas Veerman dname = strdup(temp);
5584a17663cSThomas Veerman dname[++fname - temp] = '\0';
5594a17663cSThomas Veerman }
5604a17663cSThomas Veerman else
5614a17663cSThomas Veerman {
5624a17663cSThomas Veerman dname = 0;
5634a17663cSThomas Veerman fname = temp;
5644a17663cSThomas Veerman }
5654a17663cSThomas Veerman if ((name = tempnam(dname, fname)) != 0)
5664a17663cSThomas Veerman {
5674a17663cSThomas Veerman fd = open(name, O_CREAT | O_EXCL | O_RDWR);
5684a17663cSThomas Veerman strcpy(temp, name);
5694a17663cSThomas Veerman }
5704a17663cSThomas Veerman else
5714a17663cSThomas Veerman {
5724a17663cSThomas Veerman fd = -1;
5734a17663cSThomas Veerman }
5744a17663cSThomas Veerman
5754a17663cSThomas Veerman if (dname != 0)
5764a17663cSThomas Veerman free(dname);
5774a17663cSThomas Veerman
5784a17663cSThomas Veerman return fd;
5794a17663cSThomas Veerman }
5804a17663cSThomas Veerman #define mkstemp(s) my_mkstemp(s)
5814a17663cSThomas Veerman #endif
5824a17663cSThomas Veerman
5834a17663cSThomas Veerman #endif
5844a17663cSThomas Veerman
5854a17663cSThomas Veerman /*
5864a17663cSThomas Veerman * tmpfile() should be adequate, except that it may require special privileges
5874a17663cSThomas Veerman * to use, e.g., MinGW and Windows 7 where it tries to use the root directory.
5884a17663cSThomas Veerman */
5894a17663cSThomas Veerman static FILE *
open_tmpfile(const char * label)5904a17663cSThomas Veerman open_tmpfile(const char *label)
5914a17663cSThomas Veerman {
5924a17663cSThomas Veerman FILE *result;
5934a17663cSThomas Veerman #if USE_MKSTEMP
5944a17663cSThomas Veerman int fd;
5954a17663cSThomas Veerman const char *tmpdir;
5964a17663cSThomas Veerman char *name;
5974a17663cSThomas Veerman const char *mark;
5984a17663cSThomas Veerman
5994a17663cSThomas Veerman if ((tmpdir = getenv("TMPDIR")) == 0 || access(tmpdir, W_OK) != 0)
6004a17663cSThomas Veerman {
6014a17663cSThomas Veerman #ifdef P_tmpdir
6024a17663cSThomas Veerman tmpdir = P_tmpdir;
6034a17663cSThomas Veerman #else
6044a17663cSThomas Veerman tmpdir = "/tmp";
6054a17663cSThomas Veerman #endif
6064a17663cSThomas Veerman if (access(tmpdir, W_OK) != 0)
6074a17663cSThomas Veerman tmpdir = ".";
6084a17663cSThomas Veerman }
6094a17663cSThomas Veerman
6104a17663cSThomas Veerman name = malloc(strlen(tmpdir) + 10 + strlen(label));
6114a17663cSThomas Veerman
6124a17663cSThomas Veerman result = 0;
6134a17663cSThomas Veerman if (name != 0)
6144a17663cSThomas Veerman {
615*0a6a1f1dSLionel Sambuc mode_t save_umask = umask(0177);
616*0a6a1f1dSLionel Sambuc
6174a17663cSThomas Veerman if ((mark = strrchr(label, '_')) == 0)
6184a17663cSThomas Veerman mark = label + strlen(label);
6194a17663cSThomas Veerman
6204a17663cSThomas Veerman sprintf(name, "%s/%.*sXXXXXX", tmpdir, (int)(mark - label), label);
6214a17663cSThomas Veerman fd = mkstemp(name);
6224a17663cSThomas Veerman if (fd >= 0)
6234a17663cSThomas Veerman {
6244a17663cSThomas Veerman result = fdopen(fd, "w+");
6254a17663cSThomas Veerman if (result != 0)
6264a17663cSThomas Veerman {
6274a17663cSThomas Veerman MY_TMPFILES *item;
6284a17663cSThomas Veerman
6294a17663cSThomas Veerman if (my_tmpfiles == 0)
6304a17663cSThomas Veerman {
6314a17663cSThomas Veerman atexit(close_tmpfiles);
6324a17663cSThomas Veerman }
6334a17663cSThomas Veerman
6344a17663cSThomas Veerman item = NEW(MY_TMPFILES);
6354a17663cSThomas Veerman NO_SPACE(item);
6364a17663cSThomas Veerman
6374a17663cSThomas Veerman item->name = name;
6384a17663cSThomas Veerman NO_SPACE(item->name);
6394a17663cSThomas Veerman
6404a17663cSThomas Veerman item->next = my_tmpfiles;
6414a17663cSThomas Veerman my_tmpfiles = item;
6424a17663cSThomas Veerman }
6434a17663cSThomas Veerman }
644*0a6a1f1dSLionel Sambuc (void)umask(save_umask);
6454a17663cSThomas Veerman }
6464a17663cSThomas Veerman #else
6474a17663cSThomas Veerman result = tmpfile();
6484a17663cSThomas Veerman #endif
6494a17663cSThomas Veerman
6504a17663cSThomas Veerman if (result == 0)
6514a17663cSThomas Veerman open_error(label);
6524a17663cSThomas Veerman return result;
6534a17663cSThomas Veerman }
6544a17663cSThomas Veerman
6554a17663cSThomas Veerman static void
open_files(void)6564a17663cSThomas Veerman open_files(void)
6574a17663cSThomas Veerman {
6584a17663cSThomas Veerman create_file_names();
6594a17663cSThomas Veerman
6604a17663cSThomas Veerman if (input_file == 0)
6614a17663cSThomas Veerman {
6624a17663cSThomas Veerman input_file = fopen(input_file_name, "r");
6634a17663cSThomas Veerman if (input_file == 0)
6644a17663cSThomas Veerman open_error(input_file_name);
6654a17663cSThomas Veerman }
6664a17663cSThomas Veerman
6674a17663cSThomas Veerman action_file = open_tmpfile("action_file");
6684a17663cSThomas Veerman text_file = open_tmpfile("text_file");
6694a17663cSThomas Veerman
6704a17663cSThomas Veerman if (vflag)
6714a17663cSThomas Veerman {
6724a17663cSThomas Veerman verbose_file = fopen(verbose_file_name, "w");
6734a17663cSThomas Veerman if (verbose_file == 0)
6744a17663cSThomas Veerman open_error(verbose_file_name);
6754a17663cSThomas Veerman }
6764a17663cSThomas Veerman
6774a17663cSThomas Veerman if (gflag)
6784a17663cSThomas Veerman {
6794a17663cSThomas Veerman graph_file = fopen(graph_file_name, "w");
6804a17663cSThomas Veerman if (graph_file == 0)
6814a17663cSThomas Veerman open_error(graph_file_name);
6824a17663cSThomas Veerman fprintf(graph_file, "digraph %s {\n", file_prefix);
6834a17663cSThomas Veerman fprintf(graph_file, "\tedge [fontsize=10];\n");
6844a17663cSThomas Veerman fprintf(graph_file, "\tnode [shape=box,fontsize=10];\n");
6854a17663cSThomas Veerman fprintf(graph_file, "\torientation=landscape;\n");
6864a17663cSThomas Veerman fprintf(graph_file, "\trankdir=LR;\n");
6874a17663cSThomas Veerman fprintf(graph_file, "\t/*\n");
6884a17663cSThomas Veerman fprintf(graph_file, "\tmargin=0.2;\n");
6894a17663cSThomas Veerman fprintf(graph_file, "\tpage=\"8.27,11.69\"; // for A4 printing\n");
6904a17663cSThomas Veerman fprintf(graph_file, "\tratio=auto;\n");
6914a17663cSThomas Veerman fprintf(graph_file, "\t*/\n");
6924a17663cSThomas Veerman }
6934a17663cSThomas Veerman
6944a17663cSThomas Veerman if (dflag)
6954a17663cSThomas Veerman {
6964a17663cSThomas Veerman defines_file = fopen(defines_file_name, "w");
6974a17663cSThomas Veerman if (defines_file == 0)
6984a17663cSThomas Veerman open_error(defines_file_name);
6994a17663cSThomas Veerman union_file = open_tmpfile("union_file");
7004a17663cSThomas Veerman }
7014a17663cSThomas Veerman
7024a17663cSThomas Veerman if (iflag)
7034a17663cSThomas Veerman {
7044a17663cSThomas Veerman externs_file = fopen(externs_file_name, "w");
7054a17663cSThomas Veerman if (externs_file == 0)
7064a17663cSThomas Veerman open_error(externs_file_name);
7074a17663cSThomas Veerman }
7084a17663cSThomas Veerman
7094a17663cSThomas Veerman output_file = fopen(output_file_name, "w");
7104a17663cSThomas Veerman if (output_file == 0)
7114a17663cSThomas Veerman open_error(output_file_name);
7124a17663cSThomas Veerman
7134a17663cSThomas Veerman if (rflag)
7144a17663cSThomas Veerman {
7154a17663cSThomas Veerman code_file = fopen(code_file_name, "w");
7164a17663cSThomas Veerman if (code_file == 0)
7174a17663cSThomas Veerman open_error(code_file_name);
7184a17663cSThomas Veerman }
7194a17663cSThomas Veerman else
7204a17663cSThomas Veerman code_file = output_file;
7214a17663cSThomas Veerman }
7224a17663cSThomas Veerman
7234a17663cSThomas Veerman int
main(int argc,char * argv[])7244a17663cSThomas Veerman main(int argc, char *argv[])
7254a17663cSThomas Veerman {
7264a17663cSThomas Veerman SRexpect = -1;
7274a17663cSThomas Veerman RRexpect = -1;
7284a17663cSThomas Veerman exit_code = EXIT_SUCCESS;
7294a17663cSThomas Veerman
7304a17663cSThomas Veerman set_signals();
7314a17663cSThomas Veerman getargs(argc, argv);
7324a17663cSThomas Veerman open_files();
7334a17663cSThomas Veerman reader();
7344a17663cSThomas Veerman lr0();
7354a17663cSThomas Veerman lalr();
7364a17663cSThomas Veerman make_parser();
7374a17663cSThomas Veerman graph();
7384a17663cSThomas Veerman finalize_closure();
7394a17663cSThomas Veerman verbose();
7404a17663cSThomas Veerman output();
7414a17663cSThomas Veerman done(exit_code);
7424a17663cSThomas Veerman /*NOTREACHED */
7434a17663cSThomas Veerman }
744