xref: /minix3/external/bsd/byacc/dist/main.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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