Module Name:    src
Committed By:   christos
Date:           Sat Jan  3 23:22:53 UTC 2015

Modified Files:
        src/external/bsd/byacc/bin: Makefile
        src/external/bsd/byacc/dist: closure.c config_h.in defs.h error.c
            graph.c lalr.c lr0.c main.c mkpar.c mstring.c output.c reader.c
            symtab.c verbose.c yacc.1
Removed Files:
        src/external/bsd/byacc/dist: skeleton.c
        src/external/bsd/byacc/dist/test: calc.output calc.tab.c calc.tab.h
            calc1.output calc1.tab.c calc1.tab.h calc2.output calc2.tab.c
            calc2.tab.h calc3.output calc3.tab.c calc3.tab.h code_calc.code.c
            code_calc.output code_calc.tab.c code_calc.tab.h code_error.code.c
            code_error.output code_error.tab.c code_error.tab.h error.output
            error.tab.c error.tab.h ftp.output ftp.tab.c ftp.tab.h ftp.y
            grammar.output grammar.tab.c grammar.tab.h pure_calc.output
            pure_calc.tab.c pure_calc.tab.h pure_error.output pure_error.tab.c
            pure_error.tab.h quote_calc-s.output quote_calc-s.tab.c
            quote_calc-s.tab.h quote_calc.output quote_calc.tab.c
            quote_calc.tab.h quote_calc2-s.output quote_calc2-s.tab.c
            quote_calc2-s.tab.h quote_calc2.output quote_calc2.tab.c
            quote_calc2.tab.h quote_calc3-s.output quote_calc3-s.tab.c
            quote_calc3-s.tab.h quote_calc3.output quote_calc3.tab.c
            quote_calc3.tab.h quote_calc4-s.output quote_calc4-s.tab.c
            quote_calc4-s.tab.h quote_calc4.output quote_calc4.tab.c
            quote_calc4.tab.h

Log Message:
merge conflicts.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/external/bsd/byacc/bin/Makefile
cvs rdiff -u -r1.7 -r1.8 src/external/bsd/byacc/dist/closure.c \
    src/external/bsd/byacc/dist/defs.h src/external/bsd/byacc/dist/lr0.c \
    src/external/bsd/byacc/dist/mkpar.c src/external/bsd/byacc/dist/symtab.c \
    src/external/bsd/byacc/dist/verbose.c
cvs rdiff -u -r1.4 -r1.5 src/external/bsd/byacc/dist/config_h.in \
    src/external/bsd/byacc/dist/graph.c
cvs rdiff -u -r1.8 -r1.9 src/external/bsd/byacc/dist/error.c
cvs rdiff -u -r1.5 -r1.6 src/external/bsd/byacc/dist/lalr.c \
    src/external/bsd/byacc/dist/yacc.1
cvs rdiff -u -r1.9 -r1.10 src/external/bsd/byacc/dist/main.c \
    src/external/bsd/byacc/dist/reader.c
cvs rdiff -u -r1.1.1.1 -r1.2 src/external/bsd/byacc/dist/mstring.c
cvs rdiff -u -r1.10 -r1.11 src/external/bsd/byacc/dist/output.c
cvs rdiff -u -r1.14 -r0 src/external/bsd/byacc/dist/skeleton.c
cvs rdiff -u -r1.1.1.1 -r0 src/external/bsd/byacc/dist/test/calc.output \
    src/external/bsd/byacc/dist/test/calc1.output \
    src/external/bsd/byacc/dist/test/calc2.output \
    src/external/bsd/byacc/dist/test/calc3.output \
    src/external/bsd/byacc/dist/test/code_calc.output \
    src/external/bsd/byacc/dist/test/code_error.output \
    src/external/bsd/byacc/dist/test/error.output \
    src/external/bsd/byacc/dist/test/grammar.output \
    src/external/bsd/byacc/dist/test/pure_calc.output \
    src/external/bsd/byacc/dist/test/pure_error.output \
    src/external/bsd/byacc/dist/test/quote_calc-s.output \
    src/external/bsd/byacc/dist/test/quote_calc-s.tab.c \
    src/external/bsd/byacc/dist/test/quote_calc-s.tab.h \
    src/external/bsd/byacc/dist/test/quote_calc.output \
    src/external/bsd/byacc/dist/test/quote_calc.tab.c \
    src/external/bsd/byacc/dist/test/quote_calc.tab.h \
    src/external/bsd/byacc/dist/test/quote_calc2-s.output \
    src/external/bsd/byacc/dist/test/quote_calc2-s.tab.c \
    src/external/bsd/byacc/dist/test/quote_calc2-s.tab.h \
    src/external/bsd/byacc/dist/test/quote_calc2.output \
    src/external/bsd/byacc/dist/test/quote_calc2.tab.c \
    src/external/bsd/byacc/dist/test/quote_calc2.tab.h \
    src/external/bsd/byacc/dist/test/quote_calc3-s.output \
    src/external/bsd/byacc/dist/test/quote_calc3-s.tab.c \
    src/external/bsd/byacc/dist/test/quote_calc3-s.tab.h \
    src/external/bsd/byacc/dist/test/quote_calc3.output \
    src/external/bsd/byacc/dist/test/quote_calc3.tab.c \
    src/external/bsd/byacc/dist/test/quote_calc3.tab.h \
    src/external/bsd/byacc/dist/test/quote_calc4-s.output \
    src/external/bsd/byacc/dist/test/quote_calc4-s.tab.c \
    src/external/bsd/byacc/dist/test/quote_calc4-s.tab.h \
    src/external/bsd/byacc/dist/test/quote_calc4.output \
    src/external/bsd/byacc/dist/test/quote_calc4.tab.c \
    src/external/bsd/byacc/dist/test/quote_calc4.tab.h
cvs rdiff -u -r1.1.1.5 -r0 src/external/bsd/byacc/dist/test/calc.tab.c \
    src/external/bsd/byacc/dist/test/grammar.tab.c
cvs rdiff -u -r1.1.1.3 -r0 src/external/bsd/byacc/dist/test/calc.tab.h \
    src/external/bsd/byacc/dist/test/calc1.tab.h \
    src/external/bsd/byacc/dist/test/calc2.tab.h \
    src/external/bsd/byacc/dist/test/calc3.tab.h \
    src/external/bsd/byacc/dist/test/code_calc.tab.c \
    src/external/bsd/byacc/dist/test/code_calc.tab.h \
    src/external/bsd/byacc/dist/test/code_error.tab.c \
    src/external/bsd/byacc/dist/test/code_error.tab.h \
    src/external/bsd/byacc/dist/test/grammar.tab.h \
    src/external/bsd/byacc/dist/test/pure_calc.tab.h \
    src/external/bsd/byacc/dist/test/pure_error.tab.h
cvs rdiff -u -r1.1.1.4 -r0 src/external/bsd/byacc/dist/test/calc1.tab.c \
    src/external/bsd/byacc/dist/test/calc2.tab.c \
    src/external/bsd/byacc/dist/test/calc3.tab.c \
    src/external/bsd/byacc/dist/test/code_calc.code.c \
    src/external/bsd/byacc/dist/test/code_error.code.c \
    src/external/bsd/byacc/dist/test/pure_calc.tab.c \
    src/external/bsd/byacc/dist/test/pure_error.tab.c
cvs rdiff -u -r1.5 -r0 src/external/bsd/byacc/dist/test/error.tab.c \
    src/external/bsd/byacc/dist/test/ftp.tab.c \
    src/external/bsd/byacc/dist/test/ftp.y
cvs rdiff -u -r1.3 -r0 src/external/bsd/byacc/dist/test/error.tab.h
cvs rdiff -u -r1.1.1.2 -r0 src/external/bsd/byacc/dist/test/ftp.output
cvs rdiff -u -r1.4 -r0 src/external/bsd/byacc/dist/test/ftp.tab.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/bsd/byacc/bin/Makefile
diff -u src/external/bsd/byacc/bin/Makefile:1.3 src/external/bsd/byacc/bin/Makefile:1.4
--- src/external/bsd/byacc/bin/Makefile:1.3	Sun Aug 14 09:29:26 2011
+++ src/external/bsd/byacc/bin/Makefile	Sat Jan  3 18:22:52 2015
@@ -1,10 +1,10 @@
-#	$NetBSD: Makefile,v 1.3 2011/08/14 13:29:26 christos Exp $
+#	$NetBSD: Makefile,v 1.4 2015/01/03 23:22:52 christos Exp $
 
 .include "bsd.own.mk"
 
 PROG=	yacc
 SRCS=	closure.c error.c lalr.c lr0.c main.c mkpar.c output.c reader.c \
-	skeleton.c symtab.c verbose.c warshall.c graph.c
+	symtab.c verbose.c warshall.c graph.c mstring.c btyaccpar.c
 
 CPPFLAGS+=	-DGCC_NORETURN=__dead
 

Index: src/external/bsd/byacc/dist/closure.c
diff -u src/external/bsd/byacc/dist/closure.c:1.7 src/external/bsd/byacc/dist/closure.c:1.8
--- src/external/bsd/byacc/dist/closure.c:1.7	Sat Apr  6 10:52:24 2013
+++ src/external/bsd/byacc/dist/closure.c	Sat Jan  3 18:22:52 2015
@@ -1,25 +1,32 @@
-/*	$NetBSD: closure.c,v 1.7 2013/04/06 14:52:24 christos Exp $	*/
+/*	$NetBSD: closure.c,v 1.8 2015/01/03 23:22:52 christos Exp $	*/
 
-/* Id: closure.c,v 1.9 2010/06/09 08:21:47 tom Exp  */
+/* Id: closure.c,v 1.11 2014/09/18 00:40:07 tom Exp  */
 
 #include "defs.h"
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: closure.c,v 1.7 2013/04/06 14:52:24 christos Exp $");
+__RCSID("$NetBSD: closure.c,v 1.8 2015/01/03 23:22:52 christos Exp $");
 
 Value_t *itemset;
 Value_t *itemsetend;
 unsigned *ruleset;
 
+static unsigned *first_base;
 static unsigned *first_derives;
 static unsigned *EFF;
 
+#ifdef	DEBUG
+static void print_closure(int);
+static void print_EFF(void);
+static void print_first_derives(void);
+#endif
+
 static void
 set_EFF(void)
 {
     unsigned *row;
     int symbol;
-    short *sp;
+    Value_t *sp;
     int rowsize;
     int i;
     int rule;
@@ -58,7 +65,7 @@ set_first_derives(void)
     int j;
     unsigned k;
     unsigned cword = 0;
-    short *rp;
+    Value_t *rp;
 
     int rule;
     int i;
@@ -67,7 +74,8 @@ set_first_derives(void)
 
     rulesetsize = WORDSIZE(nrules);
     varsetsize = WORDSIZE(nvars);
-    first_derives = NEW2(nvars * rulesetsize, unsigned) - ntokens * rulesetsize;
+    first_base = NEW2(nvars * rulesetsize, unsigned);
+    first_derives = first_base - ntokens * rulesetsize;
 
     set_EFF();
 
@@ -105,7 +113,7 @@ set_first_derives(void)
 }
 
 void
-closure(short *nucleus, int n)
+closure(Value_t *nucleus, int n)
 {
     unsigned ruleno;
     unsigned word;
@@ -175,22 +183,22 @@ finalize_closure(void)
 {
     FREE(itemset);
     FREE(ruleset);
-    FREE(first_derives + ntokens * WORDSIZE(nrules));
+    FREE(first_base);
 }
 
 #ifdef	DEBUG
 
-void
+static void
 print_closure(int n)
 {
-    short *isp;
+    Value_t *isp;
 
     printf("\n\nn = %d\n\n", n);
     for (isp = itemset; isp < itemsetend; isp++)
 	printf("   %d\n", *isp);
 }
 
-void
+static void
 print_EFF(void)
 {
     int i, j;
@@ -221,7 +229,7 @@ print_EFF(void)
     }
 }
 
-void
+static void
 print_first_derives(void)
 {
     int i;
Index: src/external/bsd/byacc/dist/defs.h
diff -u src/external/bsd/byacc/dist/defs.h:1.7 src/external/bsd/byacc/dist/defs.h:1.8
--- src/external/bsd/byacc/dist/defs.h:1.7	Mon Dec 30 14:08:55 2013
+++ src/external/bsd/byacc/dist/defs.h	Sat Jan  3 18:22:52 2015
@@ -1,14 +1,15 @@
-/*	$NetBSD: defs.h,v 1.7 2013/12/30 19:08:55 christos Exp $	*/
+/*	$NetBSD: defs.h,v 1.8 2015/01/03 23:22:52 christos Exp $	*/
 
 #if HAVE_NBTOOL_CONFIG_H
 #include "nbtool_config.h"
 #endif
-/* Id: defs.h,v 1.37 2012/05/26 15:23:00 tom Exp  */
+/* Id: defs.h,v 1.51 2014/10/02 22:38:13 tom Exp  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -35,14 +36,14 @@
 
 #define VERSION VSTRING(YYMAJOR, YYMINOR)
 
-/*  machine-dependent definitions			*/
-/*  the following definitions are for the Tahoe		*/
-/*  they might have to be changed for other machines	*/
+/*  machine-dependent definitions:			*/
 
 /*  MAXCHAR is the largest unsigned character value	*/
-/*  MAXSHORT is the largest value of a C short		*/
-/*  MINSHORT is the most negative value of a C short	*/
 /*  MAXTABLE is the maximum table size			*/
+/*  YYINT is the smallest C integer type that can be	*/
+/*	used to address a table of size MAXTABLE	*/
+/*  MAXYYINT is the largest value of a YYINT		*/
+/*  MINYYINT is the most negative value of a YYINT	*/
 /*  BITS_PER_WORD is the number of bits in a C unsigned	*/
 /*  WORDSIZE computes the number of words needed to	*/
 /*	store n bits					*/
@@ -50,14 +51,26 @@
 /*	from r (0-indexed)				*/
 /*  SETBIT sets the n-th bit starting from r		*/
 
-#define	MAXCHAR		255
-#define	MAXSHORT	32767
-#define MINSHORT	-32768
+#define	MAXCHAR		UCHAR_MAX
+#ifndef MAXTABLE
 #define MAXTABLE	32500
-#define BITS_PER_WORD	32
-#define	WORDSIZE(n)	(((n)+(BITS_PER_WORD-1))/BITS_PER_WORD)
-#define	BIT(r, n)	((((r)[(n)>>5])>>((n)&31))&1)
-#define	SETBIT(r, n)	((r)[(n)>>5]|=((unsigned)1<<((n)&31)))
+#endif
+#if MAXTABLE <= SHRT_MAX
+#define YYINT		short
+#define MAXYYINT	SHRT_MAX
+#define MINYYINT	SHRT_MIN
+#elif MAXTABLE <= INT_MAX
+#define YYINT		int
+#define MAXYYINT	INT_MAX
+#define MINYYINT	INT_MIN
+#else
+#error "MAXTABLE is too large for this machine architecture!"
+#endif
+
+#define BITS_PER_WORD	((int) sizeof (unsigned) * CHAR_BIT)
+#define WORDSIZE(n)	(((n)+(BITS_PER_WORD-1))/BITS_PER_WORD)
+#define BIT(r, n)	((((r)[(n)/BITS_PER_WORD])>>((n)&(BITS_PER_WORD-1)))&1)
+#define SETBIT(r, n)	((r)[(n)/BITS_PER_WORD]|=((unsigned)1<<((n)&(BITS_PER_WORD-1))))
 
 /*  character names  */
 
@@ -111,11 +124,18 @@
 #define POSIX_YACC 15
 #define TOKEN_TABLE 16
 
+#if defined(YYBTYACC)
+#define LOCATIONS 17
+#define DESTRUCTOR 18
+#endif
+
 /*  symbol classes  */
 
 #define UNKNOWN 0
 #define TERM 1
 #define NONTERM 2
+#define ACTION 3
+#define ARGUMENT 4
 
 /*  the undefined value  */
 
@@ -142,6 +162,7 @@
 #define CALLOC(k,n)	(calloc((size_t)(k),(size_t)(n)))
 #define	FREE(x)		(free((char*)(x)))
 #define MALLOC(n)	(malloc((size_t)(n)))
+#define TCMALLOC(t,n)	((t*) calloc((size_t)(n), sizeof(t)))
 #define TMALLOC(t,n)	((t*) malloc((size_t)(n) * sizeof(t)))
 #define	NEW(t)		((t*)allocate(sizeof(t)))
 #define	NEW2(n,t)	((t*)allocate(((size_t)(n)*sizeof(t))))
@@ -155,10 +176,20 @@
 /* messages */
 #define PLURAL(n) ((n) > 1 ? "s" : "")
 
+/*
+ * Features which depend indirectly on the btyacc configuration, but are not
+ * essential.
+ */
+#if defined(YYBTYACC)
+#define USE_HEADER_GUARDS 1
+#else
+#define USE_HEADER_GUARDS 0
+#endif
+
 typedef char Assoc_t;
 typedef char Class_t;
-typedef short Index_t;
-typedef short Value_t;
+typedef YYINT Index_t;
+typedef YYINT Value_t;
 
 /*  the structure of a symbol table entry  */
 
@@ -169,6 +200,12 @@ struct bucket
     struct bucket *next;
     char *name;
     char *tag;
+#if defined(YYBTYACC)
+    char **argnames;
+    char **argtags;
+    int  args;
+    char *destructor;
+#endif
     Value_t value;
     Index_t index;
     Value_t prec;
@@ -255,6 +292,11 @@ extern int outline;
 extern int exit_code;
 extern int pure_parser;
 extern int token_table;
+#if defined(YYBTYACC)
+extern int locations;
+extern int backtrack;
+extern int destructor;
+#endif
 
 extern const char *const banner[];
 extern const char *const xdecls[];
@@ -266,9 +308,7 @@ extern const char *const hdr_vars[];
 extern const char *const body_1[];
 extern const char *const body_vars[];
 extern const char *const body_2[];
-extern const char *const body_3[];
 extern const char *const trailer[];
-extern const char *const trailer_2[];
 
 extern char *code_file_name;
 extern char *input_file_name;
@@ -286,11 +326,11 @@ extern FILE *union_file;
 extern FILE *verbose_file;
 extern FILE *graph_file;
 
-extern int nitems;
-extern int nrules;
-extern int nsyms;
-extern int ntokens;
-extern int nvars;
+extern Value_t nitems;
+extern Value_t nrules;
+extern Value_t nsyms;
+extern Value_t ntokens;
+extern Value_t nvars;
 extern int ntags;
 
 extern char unionized;
@@ -303,6 +343,12 @@ extern Value_t *symbol_value;
 extern Value_t *symbol_prec;
 extern char *symbol_assoc;
 
+#if defined(YYBTYACC)
+extern Value_t *symbol_pval;
+extern char **symbol_destructor;
+extern char **symbol_type_tag;
+#endif
+
 extern Value_t *ritem;
 extern Value_t *rlhs;
 extern Value_t *rrhs;
@@ -326,6 +372,7 @@ extern reductions **reduction_table;
 extern unsigned *LA;
 extern Value_t *LAruleno;
 extern Value_t *lookaheads;
+extern Value_t *goto_base;
 extern Value_t *goto_map;
 extern Value_t *from_state;
 extern Value_t *to_state;
@@ -351,9 +398,6 @@ extern param *parse_param;
 
 /* global functions */
 
-extern bucket *lookup(const char *);
-extern bucket *make_bucket(const char *);
-
 #ifndef GCC_NORETURN
 #if defined(__dead2)
 #define GCC_NORETURN		__dead2
@@ -372,13 +416,23 @@ extern bucket *make_bucket(const char *)
 #endif
 #endif
 
+#ifndef GCC_PRINTFLIKE
+#define GCC_PRINTFLIKE(fmt,var) /*nothing*/
+#endif
+
 /* closure.c */
 extern void closure(Value_t * nucleus, int n);
 extern void finalize_closure(void);
 extern void set_first_derives(void);
 
 /* error.c */
+extern void arg_number_disagree_warning(int a_lineno, char *a_name);
+extern void arg_type_disagree_warning(int a_lineno, int i, char *a_name);
+extern void at_error(int a_lineno, char *a_line, char *a_cptr) GCC_NORETURN;
+extern void at_warning(int a_lineno, int i);
+extern void bad_formals(void) GCC_NORETURN;
 extern void default_action_warning(void);
+extern void destructor_redeclared_warning(int a_lineno, char *a_line, char *a_cptr);
 extern void dollar_error(int a_lineno, char *a_line, char *a_cptr) GCC_NORETURN;
 extern void dollar_warning(int a_lineno, int i);
 extern void fatal(const char *msg) GCC_NORETURN;
@@ -394,6 +448,7 @@ extern void reprec_warning(char *s);
 extern void restarted_warning(void);
 extern void retyped_warning(char *s);
 extern void revalued_warning(char *s);
+extern void start_requires_args(char *a_name);
 extern void syntax_error(int st_lineno, char *st_line, char *st_cptr) GCC_NORETURN;
 extern void terminal_lhs(int s_lineno) GCC_NORETURN;
 extern void terminal_start(char *s) GCC_NORETURN;
@@ -401,25 +456,26 @@ extern void tokenized_start(char *s) GCC
 extern void undefined_goal(char *s) GCC_NORETURN;
 extern void undefined_symbol_warning(char *s);
 extern void unexpected_EOF(void) GCC_NORETURN;
+extern void unknown_arg_warning(int d_lineno, const char *dlr_opt, const char *d_arg, const char *d_line, const char *d_cptr);
 extern void unknown_rhs(int i) GCC_NORETURN;
+extern void unsupported_flag_warning(const char *flag, const char *details);
 extern void unterminated_action(int a_lineno, char *a_line, char *a_cptr) GCC_NORETURN;
 extern void unterminated_comment(int c_lineno, char *c_line, char *c_cptr) GCC_NORETURN;
 extern void unterminated_string(int s_lineno, char *s_line, char *s_cptr) GCC_NORETURN;
 extern void unterminated_text(int t_lineno, char *t_line, char *t_cptr) GCC_NORETURN;
 extern void unterminated_union(int u_lineno, char *u_line, char *u_cptr) GCC_NORETURN;
+extern void untyped_arg_warning(int a_lineno, const char *dlr_opt, const char *a_name);
 extern void untyped_lhs(void) GCC_NORETURN;
 extern void untyped_rhs(int i, char *s) GCC_NORETURN;
 extern void used_reserved(char *s) GCC_NORETURN;
+extern void unterminated_arglist(int a_lineno, char *a_line, char *a_cptr) GCC_NORETURN;
+extern void wrong_number_args_warning(const char *which, const char *a_name);
+extern void wrong_type_for_arg_warning(int i, char *a_name);
 
 /* graph.c */
 extern void graph(void);
 
 /* lalr.c */
-extern void create_symbol_table(void);
-extern void free_symbol_table(void);
-extern void free_symbols(void);
-
-/* lalr.c */
 extern void lalr(void);
 
 /* lr0.c */
@@ -437,25 +493,59 @@ extern void done(int k) GCC_NORETURN;
 extern void free_parser(void);
 extern void make_parser(void);
 
+/* mstring.c */
+struct mstring
+{
+    char *base, *ptr, *end;
+};
+
+extern void msprintf(struct mstring *, const char *, ...) GCC_PRINTFLIKE(2,3);
+extern int mputchar(struct mstring *, int);
+extern struct mstring *msnew(void);
+extern char *msdone(struct mstring *);
+extern int strnscmp(const char *, const char *);
+extern unsigned int strnshash(const char *);
+
+#define mputc(m, ch)	(((m)->ptr == (m)->end) \
+			 ? mputchar(m,ch) \
+			 : (*(m)->ptr++ = (char) (ch)))
+
 /* output.c */
 extern void output(void);
 
 /* reader.c */
 extern void reader(void);
 
-/* skeleton.c */
+/* skeleton.c (generated by skel2c) */
 extern void write_section(FILE * fp, const char *const section[]);
 
+/* symtab.c */
+extern bucket *make_bucket(const char *);
+extern bucket *lookup(const char *);
+extern void create_symbol_table(void);
+extern void free_symbol_table(void);
+extern void free_symbols(void);
+
 /* verbose.c */
 extern void verbose(void);
 
 /* warshall.c */
 extern void reflexive_transitive_closure(unsigned *R, int n);
 
+#ifdef DEBUG
+    /* closure.c */
+extern void print_closure(int n);
+extern void print_EFF(void);
+extern void print_first_derives(void);
+    /* lr0.c */
+extern void print_derives(void);
+#endif
+
 #ifdef NO_LEAKS
 extern void lr0_leaks(void);
 extern void lalr_leaks(void);
 extern void mkpar_leaks(void);
 extern void output_leaks(void);
+extern void mstring_leaks(void);
 extern void reader_leaks(void);
 #endif
Index: src/external/bsd/byacc/dist/lr0.c
diff -u src/external/bsd/byacc/dist/lr0.c:1.7 src/external/bsd/byacc/dist/lr0.c:1.8
--- src/external/bsd/byacc/dist/lr0.c:1.7	Sat Apr  6 10:52:24 2013
+++ src/external/bsd/byacc/dist/lr0.c	Sat Jan  3 18:22:52 2015
@@ -1,10 +1,11 @@
-/*	$NetBSD: lr0.c,v 1.7 2013/04/06 14:52:24 christos Exp $	*/
-/* Id: lr0.c,v 1.13 2012/05/26 00:40:47 tom Exp  */
+/*	$NetBSD: lr0.c,v 1.8 2015/01/03 23:22:52 christos Exp $	*/
+
+/* Id: lr0.c,v 1.17 2014/11/28 15:46:42 tom Exp  */
 
 #include "defs.h"
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: lr0.c,v 1.7 2013/04/06 14:52:24 christos Exp $");
+__RCSID("$NetBSD: lr0.c,v 1.8 2015/01/03 23:22:52 christos Exp $");
 
 static core *new_state(int symbol);
 static Value_t get_state(int symbol);
@@ -32,7 +33,9 @@ static shifts *last_shift;
 static reductions *last_reduction;
 
 static int nshifts;
-static short *shift_symbol;
+static Value_t *shift_symbol;
+
+static Value_t *rules;
 
 static Value_t *redset;
 static Value_t *shiftset;
@@ -44,16 +47,16 @@ static Value_t *kernel_items;
 static void
 allocate_itemsets(void)
 {
-    short *itemp;
-    short *item_end;
+    Value_t *itemp;
+    Value_t *item_end;
     int symbol;
     int i;
     int count;
     int max;
-    short *symbol_count;
+    Value_t *symbol_count;
 
     count = 0;
-    symbol_count = NEW2(nsyms, short);
+    symbol_count = NEW2(nsyms, Value_t);
 
     item_end = ritem + nitems;
     for (itemp = ritem; itemp < item_end; itemp++)
@@ -66,8 +69,8 @@ allocate_itemsets(void)
 	}
     }
 
-    kernel_base = NEW2(nsyms, short *);
-    kernel_items = NEW2(count, short);
+    kernel_base = NEW2(nsyms, Value_t *);
+    kernel_items = NEW2(count, Value_t);
 
     count = 0;
     max = 0;
@@ -80,15 +83,15 @@ allocate_itemsets(void)
     }
 
     shift_symbol = symbol_count;
-    kernel_end = NEW2(nsyms, short *);
+    kernel_end = NEW2(nsyms, Value_t *);
 }
 
 static void
 allocate_storage(void)
 {
     allocate_itemsets();
-    shiftset = NEW2(nsyms, short);
-    redset = NEW2(nrules + 1, short);
+    shiftset = NEW2(nsyms, Value_t);
+    redset = NEW2(nrules + 1, Value_t);
     state_set = NEW2(nitems, core *);
 }
 
@@ -137,7 +140,7 @@ static void
 generate_states(void)
 {
     allocate_storage();
-    itemset = NEW2(nitems, short);
+    itemset = NEW2(nitems, Value_t);
     ruleset = NEW2(WORDSIZE(nrules), unsigned);
     set_first_derives();
     initialize_states();
@@ -162,9 +165,9 @@ static Value_t
 get_state(int symbol)
 {
     int key;
-    short *isp1;
-    short *isp2;
-    short *iend;
+    Value_t *isp1;
+    Value_t *isp2;
+    Value_t *iend;
     core *sp;
     int found;
     int n;
@@ -224,14 +227,14 @@ static void
 initialize_states(void)
 {
     unsigned i;
-    short *start_derives;
+    Value_t *start_derives;
     core *p;
 
     start_derives = derives[start_symbol];
     for (i = 0; start_derives[i] >= 0; ++i)
 	continue;
 
-    p = (core *)MALLOC(sizeof(core) + i * sizeof(short));
+    p = (core *)MALLOC(sizeof(core) + i * sizeof(Value_t));
     NO_SPACE(p);
 
     p->next = 0;
@@ -252,8 +255,8 @@ new_itemsets(void)
 {
     Value_t i;
     int shiftcount;
-    short *isp;
-    short *ksp;
+    Value_t *isp;
+    Value_t *ksp;
     Value_t symbol;
 
     for (i = 0; i < nsyms; i++)
@@ -287,22 +290,22 @@ new_state(int symbol)
 {
     unsigned n;
     core *p;
-    short *isp1;
-    short *isp2;
-    short *iend;
+    Value_t *isp1;
+    Value_t *isp2;
+    Value_t *iend;
 
 #ifdef	TRACE
     fprintf(stderr, "Entering new_state(%d)\n", symbol);
 #endif
 
-    if (nstates >= MAXSHORT)
+    if (nstates >= MAXYYINT)
 	fatal("too many states");
 
     isp1 = kernel_base[symbol];
     iend = kernel_end[symbol];
     n = (unsigned)(iend - isp1);
 
-    p = (core *)allocate((sizeof(core) + (n - 1) * sizeof(short)));
+    p = (core *)allocate((sizeof(core) + (n - 1) * sizeof(Value_t)));
     p->accessing_symbol = (Value_t) symbol;
     p->number = (Value_t) nstates;
     p->nitems = (Value_t) n;
@@ -320,7 +323,7 @@ new_state(int symbol)
 }
 
 /* show_cores is used for debugging */
-
+#ifdef DEBUG
 void
 show_cores(void)
 {
@@ -397,17 +400,18 @@ show_shifts(void)
 	    printf("\t%d\n", p->shift[i]);
     }
 }
+#endif
 
 static void
 save_shifts(void)
 {
     shifts *p;
-    short *sp1;
-    short *sp2;
-    short *send;
+    Value_t *sp1;
+    Value_t *sp2;
+    Value_t *send;
 
     p = (shifts *)allocate((sizeof(shifts) +
-			      (unsigned)(nshifts - 1) * sizeof(short)));
+			      (unsigned)(nshifts - 1) * sizeof(Value_t)));
 
     p->number = this_state->number;
     p->nshifts = (Value_t) nshifts;
@@ -434,13 +438,13 @@ save_shifts(void)
 static void
 save_reductions(void)
 {
-    short *isp;
-    short *rp1;
-    short *rp2;
+    Value_t *isp;
+    Value_t *rp1;
+    Value_t *rp2;
     int item;
     Value_t count;
     reductions *p;
-    short *rend;
+    Value_t *rend;
 
     count = 0;
     for (isp = itemset; isp < itemsetend; isp++)
@@ -456,7 +460,7 @@ save_reductions(void)
     {
 	p = (reductions *)allocate((sizeof(reductions) +
 				      (unsigned)(count - 1) *
-				    sizeof(short)));
+				    sizeof(Value_t)));
 
 	p->number = this_state->number;
 	p->nreds = count;
@@ -486,10 +490,9 @@ set_derives(void)
 {
     Value_t i, k;
     int lhs;
-    short *rules;
 
-    derives = NEW2(nsyms, short *);
-    rules = NEW2(nvars + nrules, short);
+    derives = NEW2(nsyms, Value_t *);
+    rules = NEW2(nvars + nrules, Value_t);
 
     k = 0;
     for (lhs = start_symbol; lhs < nsyms; lhs++)
@@ -517,7 +520,7 @@ void
 print_derives(void)
 {
     int i;
-    short *sp;
+    Value_t *sp;
 
     printf("\nDERIVES\n\n");
 
@@ -596,8 +599,12 @@ lr0(void)
 void
 lr0_leaks(void)
 {
-    DO_FREE(derives[start_symbol]);
-    DO_FREE(derives);
+    if (derives)
+    {
+	DO_FREE(derives[start_symbol]);
+	DO_FREE(derives);
+	DO_FREE(rules);
+    }
     DO_FREE(nullable);
 }
 #endif
Index: src/external/bsd/byacc/dist/mkpar.c
diff -u src/external/bsd/byacc/dist/mkpar.c:1.7 src/external/bsd/byacc/dist/mkpar.c:1.8
--- src/external/bsd/byacc/dist/mkpar.c:1.7	Sat Apr  6 10:52:24 2013
+++ src/external/bsd/byacc/dist/mkpar.c	Sat Jan  3 18:22:52 2015
@@ -1,11 +1,22 @@
-/*	$NetBSD: mkpar.c,v 1.7 2013/04/06 14:52:24 christos Exp $	*/
+/*	$NetBSD: mkpar.c,v 1.8 2015/01/03 23:22:52 christos Exp $	*/
 
-/* Id: mkpar.c,v 1.12 2012/05/26 00:42:18 tom Exp  */
+/* Id: mkpar.c,v 1.14 2014/04/01 23:05:37 tom Exp  */
 
 #include "defs.h"
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: mkpar.c,v 1.7 2013/04/06 14:52:24 christos Exp $");
+__RCSID("$NetBSD: mkpar.c,v 1.8 2015/01/03 23:22:52 christos Exp $");
+
+#define NotSuppressed(p)	((p)->suppressed == 0)
+
+#if defined(YYBTYACC)
+#define MaySuppress(p)		((backtrack ? ((p)->suppressed <= 1) : (p)->suppressed == 0))
+    /* suppress the preferred action => enable backtracking */
+#define StartBacktrack(p)	if (backtrack && (p) != NULL && NotSuppressed(p)) (p)->suppressed = 1
+#else
+#define MaySuppress(p)		((p)->suppressed == 0)
+#define StartBacktrack(p)	/*nothing */
+#endif
 
 static action *add_reduce(action *actions, int ruleno, int symbol);
 static action *add_reductions(int stateno, action *actions);
@@ -195,7 +206,7 @@ unused_rules(void)
     {
 	for (p = parser[i]; p; p = p->next)
 	{
-	    if (p->action_code == REDUCE && p->suppressed == 0)
+	    if ((p->action_code == REDUCE) && MaySuppress(p))
 		rules_used[p->number] = 1;
 	}
     }
@@ -230,17 +241,23 @@ remove_conflicts(void)
 	SRcount = 0;
 	RRcount = 0;
 	symbol = -1;
+#if defined(YYBTYACC)
+	pref = NULL;
+#endif
 	for (p = parser[i]; p; p = p->next)
 	{
 	    if (p->symbol != symbol)
 	    {
+		/* the first parse action for each symbol is the preferred action */
 		pref = p;
 		symbol = p->symbol;
 	    }
+	    /* following conditions handle multiple, i.e., conflicting, parse actions */
 	    else if (i == final_state && symbol == 0)
 	    {
 		SRcount++;
 		p->suppressed = 1;
+		StartBacktrack(pref);
 	    }
 	    else if (pref != 0 && pref->action_code == SHIFT)
 	    {
@@ -274,12 +291,14 @@ remove_conflicts(void)
 		{
 		    SRcount++;
 		    p->suppressed = 1;
+		    StartBacktrack(pref);
 		}
 	    }
 	    else
 	    {
 		RRcount++;
 		p->suppressed = 1;
+		StartBacktrack(pref);
 	    }
 	}
 	SRtotal += SRcount;
@@ -334,9 +353,9 @@ sole_reduction(int stateno)
     ruleno = 0;
     for (p = parser[stateno]; p; p = p->next)
     {
-	if (p->action_code == SHIFT && p->suppressed == 0)
+	if (p->action_code == SHIFT && MaySuppress(p))
 	    return (0);
-	else if (p->action_code == REDUCE && p->suppressed == 0)
+	else if ((p->action_code == REDUCE) && MaySuppress(p))
 	{
 	    if (ruleno > 0 && p->number != ruleno)
 		return (0);
Index: src/external/bsd/byacc/dist/symtab.c
diff -u src/external/bsd/byacc/dist/symtab.c:1.7 src/external/bsd/byacc/dist/symtab.c:1.8
--- src/external/bsd/byacc/dist/symtab.c:1.7	Sat Apr  6 10:52:24 2013
+++ src/external/bsd/byacc/dist/symtab.c	Sat Jan  3 18:22:52 2015
@@ -1,11 +1,11 @@
-/*	$NetBSD: symtab.c,v 1.7 2013/04/06 14:52:24 christos Exp $	*/
+/*	$NetBSD: symtab.c,v 1.8 2015/01/03 23:22:52 christos Exp $	*/
 
-/* Id: symtab.c,v 1.10 2012/05/26 15:16:12 tom Exp  */
+/* Id: symtab.c,v 1.11 2014/03/26 00:17:09 Tom.Shields Exp  */
 
 #include "defs.h"
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: symtab.c,v 1.7 2013/04/06 14:52:24 christos Exp $");
+__RCSID("$NetBSD: symtab.c,v 1.8 2015/01/03 23:22:52 christos Exp $");
 
 /* TABLE_SIZE is the number of entries in the symbol table. */
 /* TABLE_SIZE must be a power of two.			    */
@@ -53,6 +53,12 @@ make_bucket(const char *name)
     bp->prec = 0;
     bp->class = UNKNOWN;
     bp->assoc = TOKEN;
+#if defined(YYBTYACC)
+    bp->args = -1;
+    bp->argnames = 0;
+    bp->argtags = 0;
+    bp->destructor = 0;
+#endif
     strcpy(bp->name, name);
 
     return (bp);
Index: src/external/bsd/byacc/dist/verbose.c
diff -u src/external/bsd/byacc/dist/verbose.c:1.7 src/external/bsd/byacc/dist/verbose.c:1.8
--- src/external/bsd/byacc/dist/verbose.c:1.7	Sat Apr  6 10:52:24 2013
+++ src/external/bsd/byacc/dist/verbose.c	Sat Jan  3 18:22:52 2015
@@ -1,11 +1,11 @@
-/*	$NetBSD: verbose.c,v 1.7 2013/04/06 14:52:24 christos Exp $	*/
+/*	$NetBSD: verbose.c,v 1.8 2015/01/03 23:22:52 christos Exp $	*/
 
-/* Id: verbose.c,v 1.10 2012/05/26 00:45:17 tom Exp  */
+/* Id: verbose.c,v 1.11 2014/04/01 23:15:59 Tom.Shields Exp  */
 
 #include "defs.h"
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: verbose.c,v 1.7 2013/04/06 14:52:24 christos Exp $");
+__RCSID("$NetBSD: verbose.c,v 1.8 2015/01/03 23:22:52 christos Exp $");
 
 static void log_conflicts(void);
 static void log_unused(void);
@@ -18,7 +18,7 @@ static void print_shifts(action *p);
 static void print_state(int state);
 static void print_reductions(action *p, int defred2);
 
-static short *null_rules;
+static Value_t *null_rules;
 
 void
 verbose(void)
@@ -28,7 +28,7 @@ verbose(void)
     if (!vflag)
 	return;
 
-    null_rules = TMALLOC(short, nrules);
+    null_rules = TMALLOC(Value_t, nrules);
     NO_SPACE(null_rules);
 
     fprintf(verbose_file, "\f\n");
@@ -44,13 +44,33 @@ verbose(void)
     fprintf(verbose_file, "\n\n%d terminals, %d nonterminals\n", ntokens,
 	    nvars);
     fprintf(verbose_file, "%d grammar rules, %d states\n", nrules - 2, nstates);
+#if defined(YYBTYACC)
+    {				/* print out the grammar symbol # and parser internal symbol # for each
+				   symbol as an aide to writing the implementation for YYDESTRUCT_CALL()
+				   and YYSTYPE_TOSTRING() */
+	int maxtok = 0;
+
+	fputs("\ngrammar parser grammar\n", verbose_file);
+	fputs("symbol# value# symbol\n", verbose_file);
+	for (i = 0; i < ntokens; ++i)
+	{
+	    fprintf(verbose_file, " %5d  %5d  %s\n",
+		    i, symbol_value[i], symbol_name[i]);
+	    if (symbol_value[i] > maxtok)
+		maxtok = symbol_value[i];
+	}
+	for (i = ntokens; i < nsyms; ++i)
+	    fprintf(verbose_file, " %5d  %5d  %s\n",
+		    i, (maxtok + 1) + symbol_value[i] + 1, symbol_name[i]);
+    }
+#endif
 }
 
 static void
 log_unused(void)
 {
     int i;
-    short *p;
+    Value_t *p;
 
     fprintf(verbose_file, "\n\nRules never reduced:\n");
     for (i = 3; i < nrules; ++i)
@@ -160,8 +180,8 @@ print_core(int state)
     int k;
     int rule;
     core *statep;
-    short *sp;
-    short *sp1;
+    Value_t *sp;
+    Value_t *sp1;
 
     statep = state_table[state];
     k = statep->nitems;
@@ -278,6 +298,11 @@ print_shifts(action *p)
 	    if (p->action_code == SHIFT && p->suppressed == 0)
 		fprintf(verbose_file, "\t%s  shift %d\n",
 			symbol_name[p->symbol], p->number);
+#if defined(YYBTYACC)
+	    if (backtrack && p->action_code == SHIFT && p->suppressed == 1)
+		fprintf(verbose_file, "\t%s  [trial] shift %d\n",
+			symbol_name[p->symbol], p->number);
+#endif
 	}
     }
 }
@@ -310,6 +335,11 @@ print_reductions(action *p, int defred2)
 		if (p->suppressed == 0)
 		    fprintf(verbose_file, "\t%s  reduce %d\n",
 			    symbol_name[p->symbol], k);
+#if defined(YYBTYACC)
+		if (backtrack && p->suppressed == 1)
+		    fprintf(verbose_file, "\t%s  [trial] reduce %d\n",
+			    symbol_name[p->symbol], k);
+#endif
 	    }
 	}
 
@@ -323,7 +353,7 @@ print_gotos(int stateno)
 {
     int i, k;
     int as;
-    short *to_state2;
+    Value_t *to_state2;
     shifts *sp;
 
     putc('\n', verbose_file);

Index: src/external/bsd/byacc/dist/config_h.in
diff -u src/external/bsd/byacc/dist/config_h.in:1.4 src/external/bsd/byacc/dist/config_h.in:1.5
--- src/external/bsd/byacc/dist/config_h.in:1.4	Sat Apr  6 10:52:24 2013
+++ src/external/bsd/byacc/dist/config_h.in	Sat Jan  3 18:22:52 2015
@@ -30,6 +30,12 @@
 /* Define to 1 if mkstemp() is available and working. */
 #undef HAVE_MKSTEMP
 
+/* Define to 1 if vsnprintf() is available and working. */
+#undef HAVE_VSNPRINTF
+
+/* Define to maximum table size (default: 32500) */
+#undef MAXTABLE
+
 /* Define to 1 if filesystem supports mixed-case filenames. */
 #undef MIXEDCASE_FILENAMES
 
@@ -48,5 +54,8 @@
 /* "Define to 1 if you want to use valgrind for testing." */
 #undef USE_VALGRIND
 
+/* Define to 1 to enable backtracking extension */
+#undef YYBTYACC
+
 /* Define to 1 if you want to perform memory-leak testing. */
 #undef YY_NO_LEAKS
Index: src/external/bsd/byacc/dist/graph.c
diff -u src/external/bsd/byacc/dist/graph.c:1.4 src/external/bsd/byacc/dist/graph.c:1.5
--- src/external/bsd/byacc/dist/graph.c:1.4	Sat Dec 25 18:43:30 2010
+++ src/external/bsd/byacc/dist/graph.c	Sat Jan  3 18:22:52 2015
@@ -1,10 +1,10 @@
-/*	$NetBSD: graph.c,v 1.4 2010/12/25 23:43:30 christos Exp $	*/
-/* Id: graph.c,v 1.7 2009/10/27 09:25:20 tom Exp */
+/*	$NetBSD: graph.c,v 1.5 2015/01/03 23:22:52 christos Exp $	*/
 
 #include "defs.h"
+/* Id: graph.c,v 1.8 2014/02/19 00:46:57 Tom.Shields Exp  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: graph.c,v 1.4 2010/12/25 23:43:30 christos Exp $");
+__RCSID("$NetBSD: graph.c,v 1.5 2015/01/03 23:22:52 christos Exp $");
 
 static void graph_state(int stateno);
 static void graph_LA(int ruleno);
@@ -55,10 +55,10 @@ graph(void)
 static void
 graph_state(int stateno)
 {
-    short *isp;
+    Value_t *isp;
     int rule;
-    short *sp;
-    short *sp1;
+    Value_t *sp;
+    Value_t *sp1;
 
     larno = (unsigned)lookaheads[stateno];
     fprintf(graph_file, "\n\tq%d [label=\"%d:\\l", stateno, stateno);

Index: src/external/bsd/byacc/dist/error.c
diff -u src/external/bsd/byacc/dist/error.c:1.8 src/external/bsd/byacc/dist/error.c:1.9
--- src/external/bsd/byacc/dist/error.c:1.8	Sat Apr  6 10:52:24 2013
+++ src/external/bsd/byacc/dist/error.c	Sat Jan  3 18:22:52 2015
@@ -1,10 +1,10 @@
-/*	$NetBSD: error.c,v 1.8 2013/04/06 14:52:24 christos Exp $	*/
+/*	$NetBSD: error.c,v 1.9 2015/01/03 23:22:52 christos Exp $	*/
 
 #include "defs.h"
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: error.c,v 1.8 2013/04/06 14:52:24 christos Exp $");
-/* Id: error.c,v 1.9 2011/09/05 23:27:43 tom Exp  */
+__RCSID("$NetBSD: error.c,v 1.9 2015/01/03 23:22:52 christos Exp $");
+/* Id: error.c,v 1.11 2014/04/07 22:22:49 tom Exp  */
 
 /* routines for printing error messages  */
 
@@ -46,9 +46,9 @@ unexpected_EOF(void)
 }
 
 static void
-print_pos(char *st_line, char *st_cptr)
+print_pos(const char *st_line, const char *st_cptr)
 {
-    char *s;
+    const char *s;
 
     if (st_line == 0)
 	return;
@@ -290,3 +290,117 @@ undefined_symbol_warning(char *s)
 {
     fprintf(stderr, "%s: w - the symbol %s is undefined\n", myname, s);
 }
+
+#if ! defined(YYBTYACC)
+void
+unsupported_flag_warning(const char *flag, const char *details)
+{
+    fprintf(stderr, "%s: w - %s flag unsupported, %s\n",
+	    myname, flag, details);
+}
+#endif
+
+#if defined(YYBTYACC)
+void
+at_warning(int a_lineno, int i)
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", @%d references beyond the \
+end of the current rule\n", myname, a_lineno, input_file_name, i);
+}
+
+void
+at_error(int a_lineno, char *a_line, char *a_cptr)
+{
+    fprintf(stderr,
+	    "%s: e - line %d of \"%s\", illegal @$ or @N reference\n",
+	    myname, a_lineno, input_file_name);
+    print_pos(a_line, a_cptr);
+    done(1);
+}
+
+void
+unterminated_arglist(int a_lineno, char *a_line, char *a_cptr)
+{
+    fprintf(stderr,
+	    "%s: e - line %d of \"%s\", unterminated argument list\n",
+	    myname, a_lineno, input_file_name);
+    print_pos(a_line, a_cptr);
+    done(1);
+}
+
+void
+arg_number_disagree_warning(int a_lineno, char *a_name)
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", number of arguments of %s "
+	    "doesn't agree with previous declaration\n",
+	    myname, a_lineno, input_file_name, a_name);
+}
+
+void
+bad_formals(void)
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", bad formal argument list\n",
+	    myname, lineno, input_file_name);
+    print_pos(line, cptr);
+    done(1);
+}
+
+void
+arg_type_disagree_warning(int a_lineno, int i, char *a_name)
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", type of argument %d "
+	    "to %s doesn't agree with previous declaration\n",
+	    myname, a_lineno, input_file_name, i, a_name);
+}
+
+void
+unknown_arg_warning(int d_lineno, const char *dlr_opt, const char *d_arg, const char
+		    *d_line, const char *d_cptr)
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", unknown argument %s%s\n",
+	    myname, d_lineno, input_file_name, dlr_opt, d_arg);
+    print_pos(d_line, d_cptr);
+}
+
+void
+untyped_arg_warning(int a_lineno, const char *dlr_opt, const char *a_name)
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", untyped argument %s%s\n",
+	    myname, a_lineno, input_file_name, dlr_opt, a_name);
+}
+
+void
+wrong_number_args_warning(const char *which, const char *a_name)
+{
+    fprintf(stderr,
+	    "%s: w - line %d of \"%s\", wrong number of %sarguments for %s\n",
+	    myname, lineno, input_file_name, which, a_name);
+    print_pos(line, cptr);
+}
+
+void
+wrong_type_for_arg_warning(int i, char *a_name)
+{
+    fprintf(stderr,
+	    "%s: w - line %d of \"%s\", wrong type for default argument %d to %s\n",
+	    myname, lineno, input_file_name, i, a_name);
+    print_pos(line, cptr);
+}
+
+void
+start_requires_args(char *a_name)
+{
+    fprintf(stderr,
+	    "%s: w - line %d of \"%s\", start symbol %s requires arguments\n",
+	    myname, 0, input_file_name, a_name);
+
+}
+
+void
+destructor_redeclared_warning(int a_lineno, char *a_line, char *a_cptr)
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", destructor redeclared\n",
+	    myname, a_lineno, input_file_name);
+    print_pos(a_line, a_cptr);
+}
+#endif

Index: src/external/bsd/byacc/dist/lalr.c
diff -u src/external/bsd/byacc/dist/lalr.c:1.5 src/external/bsd/byacc/dist/lalr.c:1.6
--- src/external/bsd/byacc/dist/lalr.c:1.5	Sat Sep 10 17:29:04 2011
+++ src/external/bsd/byacc/dist/lalr.c	Sat Jan  3 18:22:52 2015
@@ -1,10 +1,10 @@
-/*	$NetBSD: lalr.c,v 1.5 2011/09/10 21:29:04 christos Exp $	*/
-/* Id: lalr.c,v 1.9 2009/10/27 09:49:27 tom Exp */
+/*	$NetBSD: lalr.c,v 1.6 2015/01/03 23:22:52 christos Exp $	*/
 
 #include "defs.h"
+/* Id: lalr.c,v 1.11 2014/09/18 00:26:39 tom Exp  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: lalr.c,v 1.5 2011/09/10 21:29:04 christos Exp $");
+__RCSID("$NetBSD: lalr.c,v 1.6 2015/01/03 23:22:52 christos Exp $");
 
 typedef struct shorts
 {
@@ -38,6 +38,7 @@ Value_t *accessing_symbol;
 core **state_table;
 shifts **shift_table;
 reductions **reduction_table;
+Value_t *goto_base;
 Value_t *goto_map;
 Value_t *from_state;
 Value_t *to_state;
@@ -183,12 +184,16 @@ set_goto_map(void)
     int i;
     int symbol;
     int k;
+    Value_t *temp_base;
     Value_t *temp_map;
     Value_t state2;
     Value_t state1;
 
-    goto_map = NEW2(nvars + 1, Value_t) - ntokens;
-    temp_map = NEW2(nvars + 1, Value_t) - ntokens;
+    goto_base = NEW2(nvars + 1, Value_t);
+    temp_base = NEW2(nvars + 1, Value_t);
+
+    goto_map = goto_base - ntokens;
+    temp_map = temp_base - ntokens;
 
     ngotos = 0;
     for (sp = first_shift; sp; sp = sp->next)
@@ -200,7 +205,7 @@ set_goto_map(void)
 	    if (ISTOKEN(symbol))
 		break;
 
-	    if (ngotos == MAXSHORT)
+	    if (ngotos == MAXYYINT)
 		fatal("too many gotos");
 
 	    ngotos++;
@@ -241,7 +246,7 @@ set_goto_map(void)
 	}
     }
 
-    FREE(temp_map + ntokens);
+    FREE(temp_base);
 }
 
 /*  Map_goto maps a state/symbol pair into its numeric representation.	*/
Index: src/external/bsd/byacc/dist/yacc.1
diff -u src/external/bsd/byacc/dist/yacc.1:1.5 src/external/bsd/byacc/dist/yacc.1:1.6
--- src/external/bsd/byacc/dist/yacc.1:1.5	Sat Apr  6 10:52:24 2013
+++ src/external/bsd/byacc/dist/yacc.1	Sat Jan  3 18:22:52 2015
@@ -1,6 +1,6 @@
-.\"	$NetBSD: yacc.1,v 1.5 2013/04/06 14:52:24 christos Exp $
+.\"	$NetBSD: yacc.1,v 1.6 2015/01/03 23:22:52 christos Exp $
 .\"
-.\" Id: yacc.1,v 1.18 2012/01/15 18:12:28 tom Exp 
+.\" Id: yacc.1,v 1.24 2014/10/06 00:03:48 tom Exp 
 .\"
 .\" .TH YACC 1 "July\ 15,\ 1990"
 .\" .UC 6
@@ -10,20 +10,29 @@
 .sp
 .in +4
 ..
-.de EE
+.de XE
 .in -4
 .fi
 ..
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds AQ \(aq
+.el       .ds AQ '
+.ie \n(.g .ds `` \(lq
+.el       .ds `` ``
+.ie \n(.g .ds '' \(rq
+.el       .ds '' ''
 .\" Bulleted paragraph
 .de bP
 .IP \(bu 4
 ..
-.TH YACC 1 "September 7, 2011" "Berkeley Yacc" "User Commands"
+.TH YACC 1 "October 5, 2014" "Berkeley Yacc" "User Commands"
 .SH NAME
 Yacc \- an LALR(1) parser generator
 .SH SYNOPSIS
-.B yacc [ -dgilrtv ] [ \-b
+.B yacc [ -BdgilLPrtvVy ] [ \-b
 .I file_prefix
+.B ] [ \-o
+.I output_file
 .B ] [ \-p
 .I symbol_prefix
 .B ]
@@ -50,6 +59,9 @@ the string denoted by
 The default prefix is the character
 .IR y.
 .TP
+.B \-B
+create a backtracking parser (compile-type configuration for \fBbtyacc\fP).
+.TP
 .B \-d
 The \fB-d\fR option causes the header file
 .BR y.tab.h
@@ -91,11 +103,14 @@ If the \fB-l\fR option is specified,
 will not insert the \fI#line\fP directives.
 \&\fI#line\fP directives specified by the user will be retained.
 .TP
+.B \-L
+enable position processing, e.g., \*(``%locations\*('' (compile-type configuration for \fBbtyacc\fP).
+.TP
 \fB\-o \fP\fIoutput_file\fR
 specify the filename for the parser file.
 If this option is not given, the output filename is
 the file prefix concatenated with the file suffix, e.g., \fBy.tab.c\fP.
-This overrides the \fB-p\fP option.
+This overrides the \fB-b\fP option.
 .TP
 \fB\-p \fP\fIsymbol_prefix\fR
 The
@@ -107,30 +122,31 @@ The default prefix is the string
 .BR yy.
 .TP
 .B \-P
-create a reentrant parser, e.g., "%pure-parser".
+create a reentrant parser, e.g., \*(``%pure-parser\*(''.
 .TP
 .B \-r
 The
 .B \-r
 option causes
 .B yacc
-to produce separate files for code and tables.  The code file
-is named
+to produce separate files for code and tables.
+The code file is named
 .IR y.code.c,
 and the tables file is named
 .IR y.tab.c.
-The prefix "\fIy.\fP" can be overridden using the \fB\-b\fP option.
+The prefix \*(``\fIy.\fP\*('' can be overridden using the \fB\-b\fP option.
 .TP
 .B \-s
-suppress "\fB#define\fP" statements generated for string literals in
-a "\fB%token\fP" statement, to more closely match original \fByacc\fP behavior.
+suppress \*(``\fB#define\fP\*('' statements generated for string literals in
+a \*(``\fB%token\fP\*('' statement,
+to more closely match original \fByacc\fP behavior.
 .IP
 Normally when \fByacc\fP sees a line such as
 .ES
 %token OP_ADD "ADD"
-.EE
+.XE
 .IP
-it notices that the quoted "ADD" is a valid C identifier,
+it notices that the quoted \*(``ADD\*('' is a valid C identifier,
 and generates a #define not only for OP_ADD,
 but for ADD as well,
 e.g.,
@@ -138,12 +154,13 @@ e.g.,
 #define OP_ADD 257
 .br
 #define ADD 258
-.EE
+.XE
 .IP
-The original \fByacc\fP does not generate the second "\fB#define\fP".
-The \fB\-s\fP option suppresses this "\fB#define\fP".
+The original \fByacc\fP does not generate the second \*(``\fB#define\fP\*(''.
+The \fB\-s\fP option suppresses this \*(``\fB#define\fP\*(''.
 .IP
-POSIX (IEEE 1003.1 2004) documents only names and numbers for "\fB%token\fP",
+POSIX (IEEE 1003.1 2004) documents only names and numbers
+for \*(``\fB%token\fP\*('',
 though original \fByacc\fP and bison also accept string literals.
 .TP
 .B \-t
@@ -168,11 +185,56 @@ print the version number to the standard
 which bison supports for ostensible POSIX compatibility.
 .SH EXTENSIONS
 .B yacc
-provides some extensions for compatibility with bison and other implementations
-of yacc:
+provides some extensions for
+compatibility with bison and other implementations of yacc.
+The \fB%destructor\fP and \fB%locations\fP features are available
+only if \fByacc\fP has been configured and compiled to support the
+back-tracking (\fBbtyacc\fP) functionality.
+The remaining features are always available:
+.TP
+\fB %destructor\fP { \fIcode\fP } \fIsymbol+\fP
+defines code that is invoked when a symbol is automatically
+discarded during error recovery.
+This code can be used to
+reclaim dynamically allocated memory associated with the corresponding
+semantic value for cases where user actions cannot manage the memory
+explicitly.
+.IP
+On encountering a parse error, the generated parser
+discards symbols on the stack and input tokens until it reaches a state
+that will allow parsing to continue.
+This error recovery approach results in a memory leak
+if the \fBYYSTYPE\fP value is, or contains,
+pointers to dynamically allocated memory.
+.IP
+The bracketed \fIcode\fP is invoked whenever the parser discards one of
+the symbols. Within \fIcode\fP, \*(``\fB$$\fP\*('' or
+\*(``\fB$<tag>$\fP\*('' designates the semantic value associated with the
+discarded symbol, and  \*(``\fB@$\fP\*('' designates its location (see
+\fB%locations\fP directive).
+.IP
+A per-symbol destructor is defined by listing a grammar symbol
+in \fIsymbol+\fP.  A per-type destructor is defined  by listing
+a semantic type tag (e.g., \*(``<some_tag>\*('') in \fIsymbol+\fP; in this
+case, the parser will invoke \fIcode\fP whenever it discards any grammar
+symbol that has that semantic type tag, unless that symbol has its own
+per-symbol destructor.
+.IP
+Two categories of default destructor are supported that are
+invoked when discarding any grammar symbol that has no per-symbol and no
+per-type destructor:
+.RS
+.bP
+the code for \*(``\fB<*>\fP\*('' is used
+for grammar symbols that have an explicitly declared semantic type tag
+(via \*(``\fB%type\fP\*('');
+.bP
+the code for \*(``\fB<>\fP\*('' is used
+for grammar symbols that have no declared semantic type tag.
+.RE
 .TP
 \fB %expect\fP \fInumber\fP
-tell \fByacc\fP the expected number of shift/reduce conflicts.
+tells \fByacc\fP the expected number of shift/reduce conflicts.
 That makes it only report the number if it differs.
 .TP
 \fB %expect-rr\fP \fInumber\fP
@@ -180,6 +242,42 @@ tell \fByacc\fP the expected number of r
 That makes it only report the number if it differs.
 This is (unlike bison) allowable in LALR parsers.
 .TP
+\fB %locations\fP
+tells \fByacc\fP to enable  management of position information associated
+with each token, provided by the lexer in the global variable \fByylloc\fP,
+similar to management of semantic value information provided in \fByylval\fP.
+.IP
+As for semantic values, locations can be referenced within actions using
+\fB@$\fP to refer to the location of the left hand side symbol, and \fB@N\fP
+(\fBN\fP an integer) to refer to the location of one of the right hand side
+symbols. Also as for semantic values, when a rule is matched, a default
+action is used the compute the location represented by \fB@$\fP as the
+beginning of the first symbol and the end of the last symbol in the right
+hand side of the rule. This default computation can be overridden by
+explicit assignment to \fB@$\fP in a rule action.
+.IP
+The type of \fByylloc\fP is \fBYYLTYPE\fP, which is defined by default as:
+.ES
+typedef struct YYLTYPE {
+    int first_line;
+    int first_column;
+    int last_line;
+    int last_column;
+} YYLTYPE;
+.XE
+.IP
+\fBYYLTYPE\fP can be redefined by the user
+(\fBYYLTYPE_IS_DEFINED\fP must be defined, to inhibit the default)
+in the declarations section of the specification file.
+As in bison, the macro \fBYYLLOC_DEFAULT\fP is invoked
+each time a rule is matched to calculate a position for the left hand side of
+the rule, before the associated action is executed; this macro can be
+redefined by the user.
+.IP
+This directive adds a \fBYYLTYPE\fP parameter to \fByyerror()\fP.
+If the \fB%pure-parser\fP directive is present,
+a \fBYYLTYPE\fP parameter is added to \fByylex()\fP calls.
+.TP
 \fB %lex-param\fP { \fIargument-declaration\fP }
 By default, the lexer accepts no parameters, e.g., \fByylex()\fP.
 Use this directive to add parameter declarations for your customized lexer.
@@ -192,6 +290,13 @@ Use this directive to add parameter decl
 Most variables (other than \fByydebug\fP and \fByynerrs\fP) are
 allocated on the stack within \fByyparse\fP, making the parser reasonably
 reentrant.
+.TP
+\fB %token-table\fP
+Make the parser's names for tokens available in the \fByytname\fP array.
+However,
+.B yacc
+does not predefine \*(``$end\*('', \*(``$error\*(''
+or \*(``$undefined\*('' in this array.
 .SH PORTABILITY
 According to Robert Corbett,
 .ES
@@ -200,17 +305,17 @@ as compatible as possible with AT&T Yacc
 specification that conforms to the AT&T Yacc documentation.  Specifications
 that take advantage of undocumented features of AT&T Yacc will probably be
 rejected.
-.EE
+.XE
 .PP
 The rationale in
 .ES
 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/yacc.html
-.EE
+.XE
 .PP
 documents some features of AT&T yacc which are no longer required for POSIX
 compliance.
 .PP
-That said, you may be interested in reusing grammary files with some
+That said, you may be interested in reusing grammar files with some
 other implementation which is not strictly compatible with AT&T yacc.
 For instance, there is bison.
 Here are a few differences:
@@ -222,20 +327,37 @@ of an action (as in the original grammar
 		= {
 			statcmd();
 		}
-.EE
+.XE
 .bP
 \fBYacc\fP and bison emit code in different order, and in particular bison
 makes forward reference to common functions such as yylex, yyparse and
 yyerror without providing prototypes.
 .bP
-Bison's support for "%expect" is broken in more than one release.
+Bison's support for \*(``%expect\*('' is broken in more than one release.
 For best results using bison, delete that directive.
 .bP
 Bison has no equivalent for some of \fByacc\fP's commmand-line options,
 relying on directives embedded in the grammar file.
 .bP
-Bison's "\fB\-y\fP" option does not affect bison's lack of support for
+Bison's \*(``\fB\-y\fP\*('' option does not affect bison's lack of support for
 features of AT&T yacc which were deemed obsolescent.
+.bP
+\fBYacc\fP accepts multiple parameters with \fB%lex-param\fP and \fB%parse-param\fP
+in two forms
+.ES
+{type1 name1} {type2 name2} ...
+{type1 name1,  type2 name2 ...}
+.XE
+.IP
+Bison accepts the latter (though undocumented), but depending on the
+release may generate bad code.
+.bP
+Like bison, \fByacc\fP will add parameters specified via \fB%parse-param\fP
+to \fByyparse\fP, \fByyerror\fP and (if configured for back-tracking)
+to the destructor declared using \fB%destructor\fP.
+Bison puts the additional parameters \fIfirst\fP for
+\fByyparse\fP and \fByyerror\fP but \fIlast\fP for destructors.
+\fBYacc\fP matches this behavior.
 .
 .SH DIAGNOSTICS
 If there are rules that are never reduced, the number of such rules is

Index: src/external/bsd/byacc/dist/main.c
diff -u src/external/bsd/byacc/dist/main.c:1.9 src/external/bsd/byacc/dist/main.c:1.10
--- src/external/bsd/byacc/dist/main.c:1.9	Mon Dec 30 14:08:55 2013
+++ src/external/bsd/byacc/dist/main.c	Sat Jan  3 18:22:52 2015
@@ -1,13 +1,17 @@
-/*	$NetBSD: main.c,v 1.9 2013/12/30 19:08:55 christos Exp $	*/
+/*	$NetBSD: main.c,v 1.10 2015/01/03 23:22:52 christos Exp $	*/
 
 #include "defs.h"
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: main.c,v 1.9 2013/12/30 19:08:55 christos Exp $");
-/* Id: main.c,v 1.40 2012/09/29 13:11:00 Adrian.Bunk Exp  */
+__RCSID("$NetBSD: main.c,v 1.10 2015/01/03 23:22:52 christos Exp $");
+/* Id: main.c,v 1.54 2014/10/06 22:40:07 tom Exp  */
 
 #include <signal.h>
+#ifndef _WIN32
 #include <unistd.h>		/* for _exit() */
+#else
+#include <stdlib.h>		/* for _exit() */
+#endif
 
 
 #ifdef HAVE_MKSTEMP
@@ -79,21 +83,30 @@ FILE *union_file;	/*  a temp file, used 
 FILE *verbose_file;	/*  y.output                                        */
 FILE *graph_file;	/*  y.dot                                           */
 
-int nitems;
-int nrules;
-int nsyms;
-int ntokens;
-int nvars;
+Value_t nitems;
+Value_t nrules;
+Value_t nsyms;
+Value_t ntokens;
+Value_t nvars;
 
 Value_t start_symbol;
 char **symbol_name;
 char **symbol_pname;
 Value_t *symbol_value;
-short *symbol_prec;
+Value_t *symbol_prec;
 char *symbol_assoc;
 
 int pure_parser;
 int token_table;
+
+#if defined(YYBTYACC)
+Value_t *symbol_pval;
+char **symbol_destructor;
+char **symbol_type_tag;
+int locations = 0;	/* default to no position processing */
+int backtrack = 0;	/* default is no backtracking */
+#endif
+
 int exit_code;
 
 Value_t *ritem;
@@ -122,6 +135,10 @@ done(int k)
 {
     DO_CLOSE(input_file);
     DO_CLOSE(output_file);
+    if (iflag)
+	DO_CLOSE(externs_file);
+    if (rflag)
+	DO_CLOSE(code_file);
 
     DO_CLOSE(action_file);
     DO_CLOSE(defines_file);
@@ -155,13 +172,11 @@ done(int k)
     lr0_leaks();
     lalr_leaks();
     mkpar_leaks();
+    mstring_leaks();
     output_leaks();
     reader_leaks();
 #endif
 
-    if (rflag)
-	DO_CLOSE(code_file);
-
     exit(k);
 }
 
@@ -197,11 +212,13 @@ usage(void)
 	""
 	,"Options:"
 	,"  -b file_prefix        set filename prefix (default \"y.\")"
-	,"  -d                    write definitions (y.tab.h)"
+	,"  -B                    create a backtracking parser"
+	,"  -d                    write definitions (" DEFINES_SUFFIX ")"
 	,"  -i                    write interface (y.tab.i)"
 	,"  -g                    write a graphical description"
 	,"  -l                    suppress #line directives"
-	,"  -o output_file        (default \"y.tab.c\")"
+	,"  -L                    enable position processing, e.g., \"%locations\""
+	,"  -o output_file        (default \"" OUTPUT_SUFFIX "\")"
 	,"  -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)"
@@ -225,6 +242,14 @@ setflag(int ch)
 {
     switch (ch)
     {
+    case 'B':
+#if defined(YYBTYACC)
+	backtrack = 1;
+#else
+	unsupported_flag_warning("-B", "reconfigure with --enable-btyacc");
+#endif
+	break;
+
     case 'd':
 	dflag = 1;
 	break;
@@ -241,6 +266,14 @@ setflag(int ch)
 	lflag = 1;
 	break;
 
+    case 'L':
+#if defined(YYBTYACC)
+	locations = 1;
+#else
+	unsupported_flag_warning("-B", "reconfigure with --enable-btyacc");
+#endif
+	break;
+
     case 'P':
 	pure_parser = 1;
 	break;
@@ -371,10 +404,18 @@ allocate(size_t n)
 }
 
 #define CREATE_FILE_NAME(dest, suffix) \
-	dest = TMALLOC(char, len + strlen(suffix) + 1); \
-	NO_SPACE(dest); \
-	strcpy(dest, file_prefix); \
-	strcpy(dest + len, suffix)
+	dest = alloc_file_name(len, suffix)
+
+static char *
+alloc_file_name(size_t len, const char *suffix)
+{
+    char *result = TMALLOC(char, len + strlen(suffix) + 1);
+    if (result == 0)
+	no_space();
+    strcpy(result, file_prefix);
+    strcpy(result + len, suffix);
+    return result;
+}
 
 static void
 create_file_names(void)
@@ -391,7 +432,7 @@ create_file_names(void)
     /* compute the file_prefix from the user provided output_file_name */
     if (output_file_name != 0)
     {
-	if (!(prefix = strstr(output_file_name, ".tab.c"))
+	if (!(prefix = strstr(output_file_name, OUTPUT_SUFFIX))
 	    && (prefix = strstr(output_file_name, ".c")))
 	{
 	    defines_suffix = ".h";
@@ -486,8 +527,8 @@ close_tmpfiles(void)
     {
 	MY_TMPFILES *next = my_tmpfiles->next;
 
-	chmod(my_tmpfiles->name, 0644);
-	unlink(my_tmpfiles->name);
+	(void)chmod(my_tmpfiles->name, 0644);
+	(void)unlink(my_tmpfiles->name);
 
 	free(my_tmpfiles->name);
 	free(my_tmpfiles);
@@ -569,6 +610,8 @@ open_tmpfile(const char *label)
     result = 0;
     if (name != 0)
     {
+	mode_t save_umask = umask(0177);
+
 	if ((mark = strrchr(label, '_')) == 0)
 	    mark = label + strlen(label);
 
@@ -596,6 +639,7 @@ open_tmpfile(const char *label)
 		my_tmpfiles = item;
 	    }
 	}
+	(void)umask(save_umask);
     }
 #else
     result = tmpfile();
Index: src/external/bsd/byacc/dist/reader.c
diff -u src/external/bsd/byacc/dist/reader.c:1.9 src/external/bsd/byacc/dist/reader.c:1.10
--- src/external/bsd/byacc/dist/reader.c:1.9	Mon Dec 30 14:08:55 2013
+++ src/external/bsd/byacc/dist/reader.c	Sat Jan  3 18:22:52 2015
@@ -1,11 +1,11 @@
-/*	$NetBSD: reader.c,v 1.9 2013/12/30 19:08:55 christos Exp $	*/
+/*	$NetBSD: reader.c,v 1.10 2015/01/03 23:22:52 christos Exp $	*/
 
-/* Id: reader.c,v 1.36 2012/05/26 16:05:41 tom Exp  */
+/* Id: reader.c,v 1.58 2014/10/06 22:15:08 tom Exp  */
 
 #include "defs.h"
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: reader.c,v 1.9 2013/12/30 19:08:55 christos Exp $");
+__RCSID("$NetBSD: reader.c,v 1.10 2015/01/03 23:22:52 christos Exp $");
 
 /*  The line size must be a positive integer.  One hundred was chosen	*/
 /*  because few lines in Yacc input grammars exceed 100 characters.	*/
@@ -14,16 +14,28 @@ __RCSID("$NetBSD: reader.c,v 1.9 2013/12
 
 #define LINESIZE 100
 
-#define L_CURL '{'
-#define R_CURL '}'
+#define L_CURL  '{'
+#define R_CURL  '}'
+#define L_PAREN '('
+#define R_PAREN ')'
+#define L_BRAC  '['
+#define R_BRAC  ']'
+
+/* the maximum number of arguments (inherited attributes) to a non-terminal */
+/* this is a hard limit, but seems more than adequate */
+#define MAXARGS	20
 
 static void start_rule(bucket *bp, int s_lineno);
+#if defined(YYBTYACC)
+static void copy_destructor(void);
+static char *process_destructor_XX(char *code, char *tag);
+#endif
 
 static char *cache;
 static int cinc, cache_size;
 
 int ntags;
-static int tagmax;
+static int tagmax, havetags;
 static char **tag_table;
 
 static char saw_eof;
@@ -50,6 +62,38 @@ char line_format[] = "#line %d \"%s\"\n"
 param *lex_param;
 param *parse_param;
 
+#if defined(YYBTYACC)
+int destructor = 0;	/* =1 if at least one %destructor */
+
+static bucket *default_destructor[3] =
+{0, 0, 0};
+
+#define UNTYPED_DEFAULT 0
+#define TYPED_DEFAULT   1
+#define TYPE_SPECIFIED  2
+
+static bucket *
+lookup_type_destructor(char *tag)
+{
+    const char fmt[] = "%.*s destructor";
+    char name[1024] = "\0";
+    bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
+
+    while ((bp = *bpp) != NULL)
+    {
+	if (bp->tag == tag)
+	    return (bp);
+	bpp = &bp->link;
+    }
+
+    sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
+    *bpp = bp = make_bucket(name);
+    bp->tag = tag;
+
+    return (bp);
+}
+#endif /* defined(YYBTYACC) */
+
 static void
 cachec(int c)
 {
@@ -96,13 +140,10 @@ get_line(void)
     ++lineno;
     for (;;)
     {
-	line[i] = (char)c;
+	line[i++] = (char)c;
 	if (c == '\n')
-	{
-	    cptr = line;
-	    return;
-	}
-	if (++i >= linesize)
+	    break;
+	if ((i + 3) >= linesize)
 	{
 	    linesize += LINESIZE;
 	    line = TREALLOC(char, line, linesize);
@@ -111,12 +152,14 @@ get_line(void)
 	c = getc(f);
 	if (c == EOF)
 	{
-	    line[i] = '\n';
+	    line[i++] = '\n';
 	    saw_eof = 1;
-	    cptr = line;
-	    return;
+	    break;
 	}
     }
+    line[i] = '\0';
+    cptr = line;
+    return;
 }
 
 static char *
@@ -170,7 +213,7 @@ skip_comment(void)
 }
 
 static int
-nextc(void)
+next_inline(void)
 {
     char *s;
 
@@ -186,27 +229,6 @@ nextc(void)
     {
 	switch (*s)
 	{
-	case '\n':
-	    get_line();
-	    if (line == 0)
-		return (EOF);
-	    s = cptr;
-	    break;
-
-	case ' ':
-	case '\t':
-	case '\f':
-	case '\r':
-	case '\v':
-	case ',':
-	case ';':
-	    ++s;
-	    break;
-
-	case '\\':
-	    cptr = s;
-	    return ('%');
-
 	case '/':
 	    if (s[1] == '*')
 	    {
@@ -232,34 +254,79 @@ nextc(void)
     }
 }
 
-/*
- * Compare keyword to cached token, treating '_' and '-' the same.  Some
- * grammars rely upon this misfeature.
- */
 static int
-matchec(const char *name)
+nextc(void)
 {
-    const char *p = cache;
-    const char *q = name;
-    int code = 0;	/* assume mismatch */
+    int ch;
+    int finish = 0;
 
-    while (*p != '\0' && *q != '\0')
+    do
     {
-	char a = *p++;
-	char b = *q++;
-	if (a == '_')
-	    a = '-';
-	if (b == '_')
-	    b = '-';
-	if (a != b)
-	    break;
-	if (*p == '\0' && *q == '\0')
+	switch (ch = next_inline())
 	{
-	    code = 1;
+	case '\n':
+	    get_line();
+	    break;
+	case ' ':
+	case '\t':
+	case '\f':
+	case '\r':
+	case '\v':
+	case ',':
+	case ';':
+	    ++cptr;
+	    break;
+	case '\\':
+	    ch = '%';
+	    /* FALLTHRU */
+	default:
+	    finish = 1;
 	    break;
 	}
     }
-    return code;
+    while (!finish);
+
+    return ch;
+}
+/* *INDENT-OFF* */
+static struct keyword
+{
+    char name[13];
+    int token;
+}
+keywords[] = {
+    { "binary",      NONASSOC },
+#if defined(YYBTYACC)
+    { "destructor",  DESTRUCTOR },
+#endif
+    { "expect",      EXPECT },
+    { "expect-rr",   EXPECT_RR },
+    { "ident",       IDENT }, 
+    { "left",        LEFT },
+    { "lex-param",   LEX_PARAM },
+#if defined(YYBTYACC)
+    { "locations",   LOCATIONS },
+#endif
+    { "nonassoc",    NONASSOC },
+    { "parse-param", PARSE_PARAM },
+    { "pure-parser", PURE_PARSER },
+    { "right",       RIGHT }, 
+    { "start",       START },
+    { "term",        TOKEN }, 
+    { "token",       TOKEN }, 
+    { "token-table", TOKEN_TABLE }, 
+    { "type",        TYPE },
+    { "union",       UNION },
+    { "yacc",        POSIX_YACC },
+};
+/* *INDENT-ON* */
+
+static int
+compare_keys(const void *a, const void *b)
+{
+    const struct keyword *p = (const struct keyword *)a;
+    const struct keyword *q = (const struct keyword *)b;
+    return strcmp(p->name, q->name);
 }
 
 static int
@@ -267,6 +334,7 @@ keyword(void)
 {
     int c;
     char *t_cptr = cptr;
+    struct keyword *key;
 
     c = *++cptr;
     if (isalpha(c))
@@ -282,12 +350,16 @@ keyword(void)
 	    }
 	    else if (isdigit(c)
 		     || c == '-'
-		     || c == '_'
 		     || c == '.'
 		     || c == '$')
 	    {
 		cachec(c);
 	    }
+	    else if (c == '_')
+	    {
+		/* treat keywords spelled with '_' as if it were '-' */
+		cachec('-');
+	    }
 	    else
 	    {
 		break;
@@ -296,36 +368,10 @@ keyword(void)
 	}
 	cachec(NUL);
 
-	if (matchec("token") || matchec("term"))
-	    return (TOKEN);
-	if (matchec("type"))
-	    return (TYPE);
-	if (matchec("left"))
-	    return (LEFT);
-	if (matchec("right"))
-	    return (RIGHT);
-	if (matchec("nonassoc") || matchec("binary"))
-	    return (NONASSOC);
-	if (matchec("start"))
-	    return (START);
-	if (matchec("union"))
-	    return (UNION);
-	if (matchec("ident"))
-	    return (IDENT);
-	if (matchec("expect"))
-	    return (EXPECT);
-	if (matchec("expect-rr"))
-	    return (EXPECT_RR);
-	if (matchec("pure-parser"))
-	    return (PURE_PARSER);
-	if (matchec("parse-param"))
-	    return (PARSE_PARAM);
-	if (matchec("lex-param"))
-	    return (LEX_PARAM);
-	if (matchec("token-table"))
-	    return (TOKEN_TABLE);
-	if (matchec("yacc"))
-	    return (POSIX_YACC);
+	if ((key = bsearch(cache, keywords,
+			   sizeof(keywords) / sizeof(*key),
+			   sizeof(*key), compare_keys)))
+	    return key->token;
     }
     else
     {
@@ -344,7 +390,6 @@ keyword(void)
 	    return (NONASSOC);
     }
     syntax_error(lineno, line, t_cptr);
-    /*NOTREACHED */
 }
 
 
@@ -379,11 +424,93 @@ copy_ident(void)
     }
 }
 
+static char *
+copy_string(int quote)
+{
+    struct mstring *temp = msnew();
+    int c;
+    int s_lineno = lineno;
+    char *s_line = dup_line();
+    char *s_cptr = s_line + (cptr - line - 1);
+
+    for (;;)
+    {
+	c = *cptr++;
+	mputc(temp, c);
+	if (c == quote)
+	{
+	    FREE(s_line);
+	    return msdone(temp);
+	}
+	if (c == '\n')
+	    unterminated_string(s_lineno, s_line, s_cptr);
+	if (c == '\\')
+	{
+	    c = *cptr++;
+	    mputc(temp, c);
+	    if (c == '\n')
+	    {
+		get_line();
+		if (line == 0)
+		    unterminated_string(s_lineno, s_line, s_cptr);
+	    }
+	}
+    }
+}
+
+static char *
+copy_comment(void)
+{
+    struct mstring *temp = msnew();
+    int c;
+
+    c = *cptr;
+    if (c == '/')
+    {
+	mputc(temp, '*');
+	while ((c = *++cptr) != '\n')
+	{
+	    mputc(temp, c);
+	    if (c == '*' && cptr[1] == '/')
+		mputc(temp, ' ');
+	}
+	mputc(temp, '*');
+	mputc(temp, '/');
+    }
+    else if (c == '*')
+    {
+	int c_lineno = lineno;
+	char *c_line = dup_line();
+	char *c_cptr = c_line + (cptr - line - 1);
+
+	mputc(temp, c);
+	++cptr;
+	for (;;)
+	{
+	    c = *cptr++;
+	    mputc(temp, c);
+	    if (c == '*' && *cptr == '/')
+	    {
+		mputc(temp, '/');
+		++cptr;
+		FREE(c_line);
+		return msdone(temp);
+	    }
+	    if (c == '\n')
+	    {
+		get_line();
+		if (line == 0)
+		    unterminated_comment(c_lineno, c_line, c_cptr);
+	    }
+	}
+    }
+    return msdone(temp);
+}
+
 static void
 copy_text(void)
 {
     int c;
-    int quote;
     FILE *f = text_file;
     int need_newline = 0;
     int t_lineno = lineno;
@@ -404,7 +531,6 @@ copy_text(void)
     switch (c)
     {
     case '\n':
-      next_line:
 	putc('\n', f);
 	need_newline = 0;
 	get_line();
@@ -414,82 +540,21 @@ copy_text(void)
 
     case '\'':
     case '"':
+	putc(c, f);
 	{
-	    int s_lineno = lineno;
-	    char *s_line = dup_line();
-	    char *s_cptr = s_line + (cptr - line - 1);
-
-	    quote = c;
-	    putc(c, f);
-	    for (;;)
-	    {
-		c = *cptr++;
-		putc(c, f);
-		if (c == quote)
-		{
-		    need_newline = 1;
-		    FREE(s_line);
-		    goto loop;
-		}
-		if (c == '\n')
-		    unterminated_string(s_lineno, s_line, s_cptr);
-		if (c == '\\')
-		{
-		    c = *cptr++;
-		    putc(c, f);
-		    if (c == '\n')
-		    {
-			get_line();
-			if (line == 0)
-			    unterminated_string(s_lineno, s_line, s_cptr);
-		    }
-		}
-	    }
+	    char *s = copy_string(c);
+	    fputs(s, f);
+	    free(s);
 	}
+	need_newline = 1;
+	goto loop;
 
     case '/':
 	putc(c, f);
-	need_newline = 1;
-	c = *cptr;
-	if (c == '/')
-	{
-	    putc('*', f);
-	    while ((c = *++cptr) != '\n')
-	    {
-		if (c == '*' && cptr[1] == '/')
-		    fprintf(f, "* ");
-		else
-		    putc(c, f);
-	    }
-	    fprintf(f, "*/");
-	    goto next_line;
-	}
-	if (c == '*')
 	{
-	    int c_lineno = lineno;
-	    char *c_line = dup_line();
-	    char *c_cptr = c_line + (cptr - line - 1);
-
-	    putc('*', f);
-	    ++cptr;
-	    for (;;)
-	    {
-		c = *cptr++;
-		putc(c, f);
-		if (c == '*' && *cptr == '/')
-		{
-		    putc('/', f);
-		    ++cptr;
-		    FREE(c_line);
-		    goto loop;
-		}
-		if (c == '\n')
-		{
-		    get_line();
-		    if (line == 0)
-			unterminated_comment(c_lineno, c_line, c_cptr);
-		}
-	    }
+	    char *s = copy_comment();
+	    fputs(s, f);
+	    free(s);
 	}
 	need_newline = 1;
 	goto loop;
@@ -533,7 +598,6 @@ static void
 copy_union(void)
 {
     int c;
-    int quote;
     int depth;
     int u_lineno = lineno;
     char *u_line = dup_line();
@@ -561,7 +625,6 @@ copy_union(void)
     switch (c)
     {
     case '\n':
-      next_line:
 	get_line();
 	if (line == 0)
 	    unterminated_union(u_lineno, u_line, u_cptr);
@@ -584,81 +647,17 @@ copy_union(void)
     case '\'':
     case '"':
 	{
-	    int s_lineno = lineno;
-	    char *s_line = dup_line();
-	    char *s_cptr = s_line + (cptr - line - 1);
-
-	    quote = c;
-	    for (;;)
-	    {
-		c = *cptr++;
-		putc_both(c);
-		if (c == quote)
-		{
-		    FREE(s_line);
-		    goto loop;
-		}
-		if (c == '\n')
-		    unterminated_string(s_lineno, s_line, s_cptr);
-		if (c == '\\')
-		{
-		    c = *cptr++;
-		    putc_both(c);
-		    if (c == '\n')
-		    {
-			get_line();
-			if (line == 0)
-			    unterminated_string(s_lineno, s_line, s_cptr);
-		    }
-		}
-	    }
+	    char *s = copy_string(c);
+	    puts_both(s);
+	    free(s);
 	}
+	goto loop;
 
     case '/':
-	c = *cptr;
-	if (c == '/')
-	{
-	    putc_both('*');
-	    while ((c = *++cptr) != '\n')
-	    {
-		if (c == '*' && cptr[1] == '/')
-		{
-		    puts_both("* ");
-		}
-		else
-		{
-		    putc_both(c);
-		}
-	    }
-	    puts_both("*/\n");
-	    goto next_line;
-	}
-	if (c == '*')
 	{
-	    int c_lineno = lineno;
-	    char *c_line = dup_line();
-	    char *c_cptr = c_line + (cptr - line - 1);
-
-	    putc_both('*');
-	    ++cptr;
-	    for (;;)
-	    {
-		c = *cptr++;
-		putc_both(c);
-		if (c == '*' && *cptr == '/')
-		{
-		    putc_both('/');
-		    ++cptr;
-		    FREE(c_line);
-		    goto loop;
-		}
-		if (c == '\n')
-		{
-		    get_line();
-		    if (line == 0)
-			unterminated_comment(c_lineno, c_line, c_cptr);
-		}
-	    }
+	    char *s = copy_comment();
+	    puts_both(s);
+	    free(s);
 	}
 	goto loop;
 
@@ -667,92 +666,109 @@ copy_union(void)
     }
 }
 
+static char *
+after_blanks(char *s)
+{
+    while (*s != '\0' && isspace(UCH(*s)))
+	++s;
+    return s;
+}
+
 /*
- * Keep a linked list of parameters
+ * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
+ * single space.  Return index to last character in the buffer.
  */
-static void
-copy_param(int k)
+static int
+trim_blanks(char *buffer)
 {
-    char *buf;
-    int c;
-    param *head, *p;
-    int i;
-    int name, type2;
-
-    c = nextc();
-    if (c == EOF)
-	unexpected_EOF();
-    if (c != '{')
-	goto out;
-    cptr++;
+    if (*buffer != '\0')
+    {
+	char *d = buffer;
+	char *s = after_blanks(d);
 
-    c = nextc();
-    if (c == EOF)
-	unexpected_EOF();
-    if (c == '}')
-	goto out;
+	while ((*d++ = *s++) != '\0')
+	{
+	    ;
+	}
 
-    buf = TMALLOC(char, linesize);
-    NO_SPACE(buf);
+	--d;
+	while ((--d != buffer) && isspace(UCH(*d)))
+	    *d = '\0';
 
-    for (i = 0; (c = *cptr++) != '}'; i++)
-    {
-	if (c == '\0')
-	    missing_brace();
-	if (c == EOF)
-	    unexpected_EOF();
-	buf[i] = (char)c;
+	for (s = d = buffer; (*d++ = *s++) != '\0';)
+	{
+	    if (isspace(UCH(*s)))
+	    {
+		*s = ' ';
+		while (isspace(UCH(*s)))
+		{
+		    *s++ = ' ';
+		}
+		--s;
+	    }
+	}
     }
 
-    if (i == 0)
-	goto out;
-
-    buf[i--] = '\0';
-    while (i >= 0 && isspace(UCH(buf[i])))
-	buf[i--] = '\0';
+    return (int)strlen(buffer) - 1;
+}
 
-    if (buf[i] == ']')
+/*
+ * Scan forward in the current line-buffer looking for a right-curly bracket.
+ *
+ * Parameters begin with a left-curly bracket, and continue until there are no
+ * more interesting characters after the last right-curly bracket on the
+ * current line.  Bison documents parameters as separated like this:
+ *	{type param1} {type2 param2}
+ * but also accepts commas (although some versions of bison mishandle this)
+ *	{type param1,  type2 param2}
+ */
+static int
+more_curly(void)
+{
+    char *save = cptr;
+    int result = 0;
+    int finish = 0;
+    do
     {
-	int level = 1;
-	while (i >= 0 && level > 0 && buf[i] != '[')
+	switch (next_inline())
 	{
-	    if (buf[i] == ']')
-		++level;
-	    else if (buf[i] == '[')
-		--level;
-	    i--;
+	case 0:
+	case '\n':
+	    finish = 1;
+	    break;
+	case R_CURL:
+	    finish = 1;
+	    result = 1;
+	    break;
 	}
-	if (i <= 0)
-	    unexpected_EOF();
-	type2 = i--;
-    }
-    else
-    {
-	type2 = i + 1;
+	++cptr;
     }
+    while (!finish);
+    cptr = save;
+    return result;
+}
 
-    while (i >= 0 && (isalnum(UCH(buf[i])) ||
-		      UCH(buf[i]) == '_'))
-	i--;
-
-    if (!isspace(UCH(buf[i])) && buf[i] != '*')
-	goto out;
-
-    name = i + 1;
+static void
+save_param(int k, char *buffer, int name, int type2)
+{
+    param *head, *p;
 
     p = TMALLOC(param, 1);
     NO_SPACE(p);
 
-    p->type2 = strdup(buf + type2);
+    p->type2 = strdup(buffer + type2);
     NO_SPACE(p->type2);
+    buffer[type2] = '\0';
+    (void)trim_blanks(p->type2);
 
-    buf[type2] = '\0';
-
-    p->name = strdup(buf + name);
+    p->name = strdup(buffer + name);
     NO_SPACE(p->name);
+    buffer[name] = '\0';
+    (void)trim_blanks(p->name);
 
-    buf[name] = '\0';
-    p->type = buf;
+    p->type = strdup(buffer);
+    NO_SPACE(p->type);
+    (void)trim_blanks(p->type);
 
     if (k == LEX_PARAM)
 	head = lex_param;
@@ -773,9 +789,169 @@ copy_param(int k)
 	    parse_param = p;
     }
     p->next = NULL;
+}
+
+/*
+ * Keep a linked list of parameters.  This may be multi-line, if the trailing
+ * right-curly bracket is absent.
+ */
+static void
+copy_param(int k)
+{
+    int c;
+    int name, type2;
+    int curly = 0;
+    char *buf = 0;
+    int i = -1;
+    size_t buf_size = 0;
+    int st_lineno = lineno;
+    char *comma;
+
+    do
+    {
+	int state = curly;
+	c = next_inline();
+	switch (c)
+	{
+	case EOF:
+	    unexpected_EOF();
+	    break;
+	case L_CURL:
+	    if (curly == 1)
+	    {
+		goto oops;
+	    }
+	    curly = 1;
+	    st_lineno = lineno;
+	    break;
+	case R_CURL:
+	    if (curly != 1)
+	    {
+		goto oops;
+	    }
+	    curly = 2;
+	    break;
+	case '\n':
+	    if (curly == 0)
+	    {
+		goto oops;
+	    }
+	    break;
+	case '%':
+	    if ((curly == 1) && (cptr == line))
+	    {
+		lineno = st_lineno;
+		missing_brace();
+	    }
+	    /* FALLTHRU */
+	case '"':
+	case '\'':
+	    goto oops;
+	default:
+	    if (curly == 0 && !isspace(UCH(c)))
+	    {
+		goto oops;
+	    }
+	    break;
+	}
+	if (buf == 0)
+	{
+	    buf_size = (size_t) linesize;
+	    buf = TMALLOC(char, buf_size);
+	}
+	else if (c == '\n')
+	{
+	    get_line();
+	    if (line == 0)
+		unexpected_EOF();
+	    --cptr;
+	    buf_size += (size_t) linesize;
+	    buf = TREALLOC(char, buf, buf_size);
+	}
+	NO_SPACE(buf);
+	if (curly)
+	{
+	    if ((state == 2) && (c == L_CURL))
+	    {
+		buf[++i] = ',';
+	    }
+	    else if ((state == 2) && isspace(UCH(c)))
+	    {
+		;
+	    }
+	    else if ((c != L_CURL) && (c != R_CURL))
+	    {
+		buf[++i] = (char)c;
+	    }
+	}
+	cptr++;
+    }
+    while (curly < 2 || more_curly());
+
+    if (i == 0)
+    {
+	if (curly == 1)
+	{
+	    lineno = st_lineno;
+	    missing_brace();
+	}
+	goto oops;
+    }
+
+    buf[++i] = '\0';
+    i = trim_blanks(buf);
+
+    comma = buf - 1;
+    do
+    {
+	char *parms = (comma + 1);
+	comma = strchr(parms, ',');
+	if (comma != 0)
+	    *comma = '\0';
+
+	(void)trim_blanks(parms);
+	i = (int)strlen(parms) - 1;
+	if (i < 0)
+	{
+	    goto oops;
+	}
+
+	if (parms[i] == ']')
+	{
+	    int level = 1;
+	    while (i >= 0 && level > 0 && parms[i] != '[')
+	    {
+		if (parms[i] == ']')
+		    ++level;
+		else if (parms[i] == '[')
+		    --level;
+		i--;
+	    }
+	    if (i <= 0)
+		unexpected_EOF();
+	    type2 = i--;
+	}
+	else
+	{
+	    type2 = i + 1;
+	}
+
+	while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
+	    i--;
+
+	if (!isspace(UCH(parms[i])) && parms[i] != '*')
+	    goto oops;
+
+	name = i + 1;
+
+	save_param(k, parms, name, type2);
+    }
+    while (comma != 0);
+    FREE(buf);
     return;
 
-  out:
+  oops:
+    FREE(buf);
     syntax_error(lineno, line, cptr);
 }
 
@@ -1021,11 +1197,41 @@ get_number(void)
 }
 
 static char *
-get_tag(void)
+cache_tag(char *tag, size_t len)
 {
-    int c;
     int i;
     char *s;
+
+    for (i = 0; i < ntags; ++i)
+    {
+	if (strncmp(tag, tag_table[i], len) == 0 &&
+	    tag_table[i][len] == NUL)
+	    return (tag_table[i]);
+    }
+
+    if (ntags >= tagmax)
+    {
+	tagmax += 16;
+	tag_table =
+	    (tag_table
+	     ? TREALLOC(char *, tag_table, tagmax)
+	     : TMALLOC(char *, tagmax));
+	NO_SPACE(tag_table);
+    }
+
+    s = TMALLOC(char, len + 1);
+    NO_SPACE(s);
+
+    strncpy(s, tag, len);
+    s[len] = 0;
+    tag_table[ntags++] = s;
+    return s;
+}
+
+static char *
+get_tag(void)
+{
+    int c;
     int t_lineno = lineno;
     char *t_line = dup_line();
     char *t_cptr = t_line + (cptr - line);
@@ -1053,34 +1259,22 @@ get_tag(void)
 	illegal_tag(t_lineno, t_line, t_cptr);
     ++cptr;
 
-    for (i = 0; i < ntags; ++i)
-    {
-	if (strcmp(cache, tag_table[i]) == 0)
-	{
-	    FREE(t_line);
-	    return (tag_table[i]);
-	}
-    }
-
-    if (ntags >= tagmax)
-    {
-	tagmax += 16;
-	tag_table =
-	    (tag_table
-	     ? TREALLOC(char *, tag_table, tagmax)
-	     : TMALLOC(char *, tagmax));
-	NO_SPACE(tag_table);
-    }
+    FREE(t_line);
+    havetags = 1;
+    return cache_tag(cache, (size_t) cinc);
+}
 
-    s = TMALLOC(char, cinc);
-    NO_SPACE(s);
+#if defined(YYBTYACC)
+static char *
+scan_id(void)
+{
+    char *b = cptr;
 
-    strcpy(s, cache);
-    tag_table[ntags] = s;
-    ++ntags;
-    FREE(t_line);
-    return (s);
+    while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
+	cptr++;
+    return cache_tag(b, (size_t) (cptr - b));
 }
+#endif
 
 static void
 declare_tokens(int assoc)
@@ -1198,33 +1392,88 @@ declare_expect(int assoc)
     }
 }
 
+#if defined(YYBTYACC)
+static void
+declare_argtypes(bucket *bp)
+{
+    char *tags[MAXARGS];
+    int args = 0, c;
+
+    if (bp->args >= 0)
+	retyped_warning(bp->name);
+    cptr++;			/* skip open paren */
+    for (;;)
+    {
+	c = nextc();
+	if (c == EOF)
+	    unexpected_EOF();
+	if (c != '<')
+	    syntax_error(lineno, line, cptr);
+	tags[args++] = get_tag();
+	c = nextc();
+	if (c == R_PAREN)
+	    break;
+	if (c == EOF)
+	    unexpected_EOF();
+    }
+    cptr++;			/* skip close paren */
+    bp->args = args;
+    bp->argnames = TMALLOC(char *, args);
+    NO_SPACE(bp->argnames);
+    bp->argtags = CALLOC(sizeof(char *), args + 1);
+    NO_SPACE(bp->argtags);
+    while (--args >= 0)
+    {
+	bp->argtags[args] = tags[args];
+	bp->argnames[args] = NULL;
+    }
+}
+#endif
+
 static void
 declare_types(void)
 {
     int c;
     bucket *bp;
-    char *tag;
+    char *tag = NULL;
 
     c = nextc();
     if (c == EOF)
 	unexpected_EOF();
-    if (c != '<')
-	syntax_error(lineno, line, cptr);
-    tag = get_tag();
+    if (c == '<')
+	tag = get_tag();
 
     for (;;)
     {
 	c = nextc();
+	if (c == EOF)
+	    unexpected_EOF();
 	if (isalpha(c) || c == '_' || c == '.' || c == '$')
+	{
 	    bp = get_name();
+#if defined(YYBTYACC)
+	    if (nextc() == L_PAREN)
+		declare_argtypes(bp);
+	    else
+		bp->args = 0;
+#endif
+	}
 	else if (c == '\'' || c == '"')
+	{
 	    bp = get_literal();
+#if defined(YYBTYACC)
+	    bp->args = 0;
+#endif
+	}
 	else
 	    return;
 
-	if (bp->tag && tag != bp->tag)
-	    retyped_warning(bp->name);
-	bp->tag = tag;
+	if (tag)
+	{
+	    if (bp->tag && tag != bp->tag)
+		retyped_warning(bp->name);
+	    bp->tag = tag;
+	}
     }
 }
 
@@ -1313,6 +1562,17 @@ read_declarations(void)
 	    token_table = 1;
 	    break;
 
+#if defined(YYBTYACC)
+	case LOCATIONS:
+	    locations = 1;
+	    break;
+
+	case DESTRUCTOR:
+	    destructor = 1;
+	    copy_destructor();
+	    break;
+#endif
+
 	case POSIX_YACC:
 	    /* noop for bison compatibility. byacc is already designed to be posix
 	     * yacc compatible. */
@@ -1383,68 +1643,412 @@ expand_rules(void)
     NO_SPACE(rassoc);
 }
 
-static void
-advance_to_start(void)
+/* set immediately prior to where copy_args() could be called, and incremented by
+   the various routines that will rescan the argument list as appropriate */
+static int rescan_lineno;
+#if defined(YYBTYACC)
+
+static char *
+copy_args(int *alen)
 {
-    int c;
-    bucket *bp;
-    char *s_cptr;
-    int s_lineno;
+    struct mstring *s = msnew();
+    int depth = 0, len = 1;
+    char c, quote = 0;
+    int a_lineno = lineno;
+    char *a_line = dup_line();
+    char *a_cptr = a_line + (cptr - line - 1);
 
-    for (;;)
+    while ((c = *cptr++) != R_PAREN || depth || quote)
     {
-	c = nextc();
-	if (c != '%')
-	    break;
-	s_cptr = cptr;
-	switch (keyword())
+	if (c == ',' && !quote && !depth)
 	{
-	case MARK:
-	    no_grammar();
-
-	case TEXT:
-	    copy_text();
-	    break;
-
-	case START:
-	    declare_start();
-	    break;
-
-	default:
-	    syntax_error(lineno, line, s_cptr);
+	    len++;
+	    mputc(s, 0);
+	    continue;
+	}
+	mputc(s, c);
+	if (c == '\n')
+	{
+	    get_line();
+	    if (!line)
+	    {
+		if (quote)
+		    unterminated_string(a_lineno, a_line, a_cptr);
+		else
+		    unterminated_arglist(a_lineno, a_line, a_cptr);
+	    }
+	}
+	else if (quote)
+	{
+	    if (c == quote)
+		quote = 0;
+	    else if (c == '\\')
+	    {
+		if (*cptr != '\n')
+		    mputc(s, *cptr++);
+	    }
+	}
+	else
+	{
+	    if (c == L_PAREN)
+		depth++;
+	    else if (c == R_PAREN)
+		depth--;
+	    else if (c == '\"' || c == '\'')
+		quote = c;
 	}
     }
+    if (alen)
+	*alen = len;
+    FREE(a_line);
+    return msdone(s);
+}
 
-    c = nextc();
-    if (!isalpha(c) && c != '_' && c != '.' && c != '_')
-	syntax_error(lineno, line, cptr);
-    bp = get_name();
-    if (goal == 0)
+static char *
+parse_id(char *p, char **save)
+{
+    char *b;
+
+    while (isspace(*p))
+	if (*p++ == '\n')
+	    rescan_lineno++;
+    if (!isalpha(*p) && *p != '_')
+	return NULL;
+    b = p;
+    while (isalnum(*p) || *p == '_' || *p == '$')
+	p++;
+    if (save)
     {
-	if (bp->class == TERM)
-	    terminal_start(bp->name);
-	goal = bp;
+	*save = cache_tag(b, (size_t) (p - b));
     }
+    return p;
+}
 
-    s_lineno = lineno;
-    c = nextc();
-    if (c == EOF)
-	unexpected_EOF();
-    if (c != ':')
-	syntax_error(lineno, line, cptr);
-    start_rule(bp, s_lineno);
-    ++cptr;
+static char *
+parse_int(char *p, int *save)
+{
+    int neg = 0, val = 0;
+
+    while (isspace(*p))
+	if (*p++ == '\n')
+	    rescan_lineno++;
+    if (*p == '-')
+    {
+	neg = 1;
+	p++;
+    }
+    if (!isdigit(*p))
+	return NULL;
+    while (isdigit(*p))
+	val = val * 10 + *p++ - '0';
+    if (neg)
+	val = -val;
+    if (save)
+	*save = val;
+    return p;
 }
 
 static void
-start_rule(bucket *bp, int s_lineno)
+parse_arginfo(bucket *a, char *args, int argslen)
 {
-    if (bp->class == TERM)
-	terminal_lhs(s_lineno);
-    bp->class = NONTERM;
-    if (nrules >= maxrules)
-	expand_rules();
-    plhs[nrules] = bp;
+    char *p = args, *tmp;
+    int i, redec = 0;
+
+    if (a->args > 0)
+    {
+	if (a->args != argslen)
+	    arg_number_disagree_warning(rescan_lineno, a->name);
+	redec = 1;
+    }
+    else
+    {
+	if ((a->args = argslen) == 0)
+	    return;
+	a->argnames = TMALLOC(char *, argslen);
+	NO_SPACE(a->argnames);
+	a->argtags = TMALLOC(char *, argslen);
+	NO_SPACE(a->argtags);
+    }
+    if (!args)
+	return;
+    for (i = 0; i < argslen; i++)
+    {
+	while (isspace(*p))
+	    if (*p++ == '\n')
+		rescan_lineno++;
+	if (*p++ != '$')
+	    bad_formals();
+	while (isspace(*p))
+	    if (*p++ == '\n')
+		rescan_lineno++;
+	if (*p == '<')
+	{
+	    havetags = 1;
+	    if (!(p = parse_id(p + 1, &tmp)))
+		bad_formals();
+	    while (isspace(*p))
+		if (*p++ == '\n')
+		    rescan_lineno++;
+	    if (*p++ != '>')
+		bad_formals();
+	    if (redec)
+	    {
+		if (a->argtags[i] != tmp)
+		    arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
+	    }
+	    else
+		a->argtags[i] = tmp;
+	}
+	else if (!redec)
+	    a->argtags[i] = NULL;
+	if (!(p = parse_id(p, &a->argnames[i])))
+	    bad_formals();
+	while (isspace(*p))
+	    if (*p++ == '\n')
+		rescan_lineno++;
+	if (*p++)
+	    bad_formals();
+    }
+    free(args);
+}
+
+static char *
+compile_arg(char **theptr, char *yyvaltag)
+{
+    char *p = *theptr;
+    struct mstring *c = msnew();
+    int i, j, n;
+    Value_t *offsets = NULL, maxoffset;
+    bucket **rhs;
+
+    maxoffset = 0;
+    n = 0;
+    for (i = nitems - 1; pitem[i]; --i)
+    {
+	n++;
+	if (pitem[i]->class != ARGUMENT)
+	    maxoffset++;
+    }
+    if (maxoffset > 0)
+    {
+	offsets = TMALLOC(Value_t, maxoffset + 1);
+	NO_SPACE(offsets);
+
+	for (j = 0, i++; i < nitems; i++)
+	    if (pitem[i]->class != ARGUMENT)
+		offsets[++j] = (Value_t) (i - nitems + 1);
+    }
+    rhs = pitem + nitems - 1;
+
+    if (yyvaltag)
+	msprintf(c, "yyval.%s = ", yyvaltag);
+    else
+	msprintf(c, "yyval = ");
+    while (*p)
+    {
+	if (*p == '$')
+	{
+	    char *tag = NULL;
+	    if (*++p == '<')
+		if (!(p = parse_id(++p, &tag)) || *p++ != '>')
+		    illegal_tag(rescan_lineno, NULL, NULL);
+	    if (isdigit(*p) || *p == '-')
+	    {
+		int val;
+		if (!(p = parse_int(p, &val)))
+		    dollar_error(rescan_lineno, NULL, NULL);
+		if (val <= 0)
+		    i = val - n;
+		else if (val > maxoffset)
+		{
+		    dollar_warning(rescan_lineno, val);
+		    i = val - maxoffset;
+		}
+		else if (maxoffset > 0)
+		{
+		    i = offsets[val];
+		    if (!tag && !(tag = rhs[i]->tag) && havetags)
+			untyped_rhs(val, rhs[i]->name);
+		}
+		msprintf(c, "yystack.l_mark[%d]", i);
+		if (tag)
+		    msprintf(c, ".%s", tag);
+		else if (havetags)
+		    unknown_rhs(val);
+	    }
+	    else if (isalpha(*p) || *p == '_')
+	    {
+		char *arg;
+		if (!(p = parse_id(p, &arg)))
+		    dollar_error(rescan_lineno, NULL, NULL);
+		for (i = plhs[nrules]->args - 1; i >= 0; i--)
+		    if (arg == plhs[nrules]->argnames[i])
+			break;
+		if (i < 0)
+		    unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
+		else if (!tag)
+		    tag = plhs[nrules]->argtags[i];
+		msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
+			 - n);
+		if (tag)
+		    msprintf(c, ".%s", tag);
+		else if (havetags)
+		    untyped_arg_warning(rescan_lineno, "$", arg);
+	    }
+	    else
+		dollar_error(rescan_lineno, NULL, NULL);
+	}
+	else if (*p == '@')
+	{
+	    at_error(rescan_lineno, NULL, NULL);
+	}
+	else
+	{
+	    if (*p == '\n')
+		rescan_lineno++;
+	    mputc(c, *p++);
+	}
+    }
+    *theptr = p;
+    if (maxoffset > 0)
+	FREE(offsets);
+    return msdone(c);
+}
+
+#define ARG_CACHE_SIZE	1024
+static struct arg_cache
+{
+    struct arg_cache *next;
+    char *code;
+    int rule;
+}
+ *arg_cache[ARG_CACHE_SIZE];
+
+static int
+lookup_arg_cache(char *code)
+{
+    struct arg_cache *entry;
+
+    entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
+    while (entry)
+    {
+	if (!strnscmp(entry->code, code))
+	    return entry->rule;
+	entry = entry->next;
+    }
+    return -1;
+}
+
+static void
+insert_arg_cache(char *code, int rule)
+{
+    struct arg_cache *entry = NEW(struct arg_cache);
+    int i;
+
+    NO_SPACE(entry);
+    i = strnshash(code) % ARG_CACHE_SIZE;
+    entry->code = code;
+    entry->rule = rule;
+    entry->next = arg_cache[i];
+    arg_cache[i] = entry;
+}
+
+static void
+clean_arg_cache(void)
+{
+    struct arg_cache *e, *t;
+    int i;
+
+    for (i = 0; i < ARG_CACHE_SIZE; i++)
+    {
+	for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
+	    free(e->code);
+	arg_cache[i] = NULL;
+    }
+}
+#endif
+
+static void
+advance_to_start(void)
+{
+    int c;
+    bucket *bp;
+    char *s_cptr;
+    int s_lineno;
+#if defined(YYBTYACC)
+    char *args = NULL;
+    int argslen = 0;
+#endif
+
+    for (;;)
+    {
+	c = nextc();
+	if (c != '%')
+	    break;
+	s_cptr = cptr;
+	switch (keyword())
+	{
+	case MARK:
+	    no_grammar();
+
+	case TEXT:
+	    copy_text();
+	    break;
+
+	case START:
+	    declare_start();
+	    break;
+
+	default:
+	    syntax_error(lineno, line, s_cptr);
+	}
+    }
+
+    c = nextc();
+    if (!isalpha(c) && c != '_' && c != '.' && c != '_')
+	syntax_error(lineno, line, cptr);
+    bp = get_name();
+    if (goal == 0)
+    {
+	if (bp->class == TERM)
+	    terminal_start(bp->name);
+	goal = bp;
+    }
+
+    s_lineno = lineno;
+    c = nextc();
+    if (c == EOF)
+	unexpected_EOF();
+    rescan_lineno = lineno;	/* line# for possible inherited args rescan */
+#if defined(YYBTYACC)
+    if (c == L_PAREN)
+    {
+	++cptr;
+	args = copy_args(&argslen);
+	NO_SPACE(args);
+	c = nextc();
+    }
+#endif
+    if (c != ':')
+	syntax_error(lineno, line, cptr);
+    start_rule(bp, s_lineno);
+#if defined(YYBTYACC)
+    parse_arginfo(bp, args, argslen);
+#endif
+    ++cptr;
+}
+
+static void
+start_rule(bucket *bp, int s_lineno)
+{
+    if (bp->class == TERM)
+	terminal_lhs(s_lineno);
+    bp->class = NONTERM;
+    if (!bp->index)
+	bp->index = nrules;
+    if (nrules >= maxrules)
+	expand_rules();
+    plhs[nrules] = bp;
     rprec[nrules] = UNDEFINED;
     rassoc[nrules] = TOKEN;
 }
@@ -1488,9 +2092,13 @@ insert_empty_rule(void)
     last_symbol->next = bp;
     last_symbol = bp;
     bp->tag = plhs[nrules]->tag;
-    bp->class = NONTERM;
+    bp->class = ACTION;
+#if defined(YYBTYACC)
+    bp->args = 0;
+#endif
 
-    if ((nitems += 2) > maxitems)
+    nitems = (Value_t) (nitems + 2);
+    if (nitems > maxitems)
 	expand_items();
     bpp = pitem + nitems - 1;
     *bpp-- = bp;
@@ -1507,12 +2115,49 @@ insert_empty_rule(void)
     rassoc[nrules - 1] = TOKEN;
 }
 
+#if defined(YYBTYACC)
+static char *
+insert_arg_rule(char *arg, char *tag)
+{
+    int line_number = rescan_lineno;
+    char *code = compile_arg(&arg, tag);
+    int rule = lookup_arg_cache(code);
+    FILE *f = action_file;
+
+    if (rule < 0)
+    {
+	rule = nrules;
+	insert_arg_cache(code, rule);
+	fprintf(f, "case %d:\n", rule - 2);
+	if (!lflag)
+	    fprintf(f, line_format, line_number, input_file_name);
+	fprintf(f, "%s;\n", code);
+	fprintf(f, "break;\n");
+	insert_empty_rule();
+	plhs[rule]->tag = tag;
+	plhs[rule]->class = ARGUMENT;
+    }
+    else
+    {
+	if (++nitems > maxitems)
+	    expand_items();
+	pitem[nitems - 1] = plhs[rule];
+	free(code);
+    }
+    return arg + 1;
+}
+#endif
+
 static void
 add_symbol(void)
 {
     int c;
     bucket *bp;
     int s_lineno = lineno;
+#if defined(YYBTYACC)
+    char *args = NULL;
+    int argslen = 0;
+#endif
 
     c = *cptr;
     if (c == '\'' || c == '"')
@@ -1521,64 +2166,451 @@ add_symbol(void)
 	bp = get_name();
 
     c = nextc();
+    rescan_lineno = lineno;	/* line# for possible inherited args rescan */
+#if defined(YYBTYACC)
+    if (c == L_PAREN)
+    {
+	++cptr;
+	args = copy_args(&argslen);
+	NO_SPACE(args);
+	c = nextc();
+    }
+#endif
     if (c == ':')
     {
 	end_rule();
 	start_rule(bp, s_lineno);
+#if defined(YYBTYACC)
+	parse_arginfo(bp, args, argslen);
+#endif
 	++cptr;
 	return;
-    }
+    }
+
+    if (last_was_action)
+	insert_empty_rule();
+    last_was_action = 0;
+
+#if defined(YYBTYACC)
+    if (bp->args < 0)
+	bp->args = argslen;
+    if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
+    {
+	int i;
+	if (plhs[nrules]->args != bp->args)
+	    wrong_number_args_warning("default ", bp->name);
+	for (i = bp->args - 1; i >= 0; i--)
+	    if (plhs[nrules]->argtags[i] != bp->argtags[i])
+		wrong_type_for_arg_warning(i + 1, bp->name);
+    }
+    else if (bp->args != argslen)
+	wrong_number_args_warning("", bp->name);
+    if (bp->args > 0 && argslen > 0)
+    {
+	char *ap;
+	int i;
+	for (ap = args, i = 0; i < argslen; i++)
+	    ap = insert_arg_rule(ap, bp->argtags[i]);
+	free(args);
+    }
+#endif /* defined(YYBTYACC) */
+
+    if (++nitems > maxitems)
+	expand_items();
+    pitem[nitems - 1] = bp;
+}
+
+static void
+copy_action(void)
+{
+    int c;
+    int i, j, n;
+    int depth;
+#if defined(YYBTYACC)
+    int trialaction = 0;
+    int haveyyval = 0;
+#endif
+    char *tag;
+    FILE *f = action_file;
+    int a_lineno = lineno;
+    char *a_line = dup_line();
+    char *a_cptr = a_line + (cptr - line);
+    Value_t *offsets = NULL, maxoffset;
+    bucket **rhs;
+
+    if (last_was_action)
+	insert_empty_rule();
+    last_was_action = 1;
+
+    fprintf(f, "case %d:\n", nrules - 2);
+#if defined(YYBTYACC)
+    if (backtrack)
+    {
+	if (*cptr != L_BRAC)
+	    fprintf(f, "  if (!yytrial)\n");
+	else
+	    trialaction = 1;
+    }
+#endif
+    if (!lflag)
+	fprintf(f, line_format, lineno, input_file_name);
+    if (*cptr == '=')
+	++cptr;
+
+    /* avoid putting curly-braces in first column, to ease editing */
+    if (*after_blanks(cptr) == L_CURL)
+    {
+	putc('\t', f);
+	cptr = after_blanks(cptr);
+    }
+
+    maxoffset = 0;
+    n = 0;
+    for (i = nitems - 1; pitem[i]; --i)
+    {
+	++n;
+	if (pitem[i]->class != ARGUMENT)
+	    maxoffset++;
+    }
+    if (maxoffset > 0)
+    {
+	offsets = TMALLOC(Value_t, maxoffset + 1);
+	NO_SPACE(offsets);
+
+	for (j = 0, i++; i < nitems; i++)
+	{
+	    if (pitem[i]->class != ARGUMENT)
+	    {
+		offsets[++j] = (Value_t) (i - nitems + 1);
+	    }
+	}
+    }
+    rhs = pitem + nitems - 1;
+
+    depth = 0;
+  loop:
+    c = *cptr;
+    if (c == '$')
+    {
+	if (cptr[1] == '<')
+	{
+	    int d_lineno = lineno;
+	    char *d_line = dup_line();
+	    char *d_cptr = d_line + (cptr - line);
+
+	    ++cptr;
+	    tag = get_tag();
+	    c = *cptr;
+	    if (c == '$')
+	    {
+		fprintf(f, "yyval.%s", tag);
+		++cptr;
+		FREE(d_line);
+		goto loop;
+	    }
+	    else if (isdigit(c))
+	    {
+		i = get_number();
+		if (i == 0)
+		    fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
+		else if (i > maxoffset)
+		{
+		    dollar_warning(d_lineno, i);
+		    fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
+		}
+		else if (offsets)
+		    fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
+		FREE(d_line);
+		goto loop;
+	    }
+	    else if (c == '-' && isdigit(UCH(cptr[1])))
+	    {
+		++cptr;
+		i = -get_number() - n;
+		fprintf(f, "yystack.l_mark[%d].%s", i, tag);
+		FREE(d_line);
+		goto loop;
+	    }
+#if defined(YYBTYACC)
+	    else if (isalpha(c) || c == '_')
+	    {
+		char *arg = scan_id();
+		for (i = plhs[nrules]->args - 1; i >= 0; i--)
+		    if (arg == plhs[nrules]->argnames[i])
+			break;
+		if (i < 0)
+		    unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
+		fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
+			1 - n, tag);
+		FREE(d_line);
+		goto loop;
+	    }
+#endif
+	    else
+		dollar_error(d_lineno, d_line, d_cptr);
+	}
+	else if (cptr[1] == '$')
+	{
+	    if (havetags)
+	    {
+		tag = plhs[nrules]->tag;
+		if (tag == 0)
+		    untyped_lhs();
+		fprintf(f, "yyval.%s", tag);
+	    }
+	    else
+		fprintf(f, "yyval");
+	    cptr += 2;
+#if defined(YYBTYACC)
+	    haveyyval = 1;
+#endif
+	    goto loop;
+	}
+	else if (isdigit(UCH(cptr[1])))
+	{
+	    ++cptr;
+	    i = get_number();
+	    if (havetags && offsets)
+	    {
+		if (i <= 0 || i > maxoffset)
+		    unknown_rhs(i);
+		tag = rhs[offsets[i]]->tag;
+		if (tag == 0)
+		    untyped_rhs(i, rhs[offsets[i]]->name);
+		fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
+	    }
+	    else
+	    {
+		if (i == 0)
+		    fprintf(f, "yystack.l_mark[%d]", -n);
+		else if (i > maxoffset)
+		{
+		    dollar_warning(lineno, i);
+		    fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
+		}
+		else if (offsets)
+		    fprintf(f, "yystack.l_mark[%d]", offsets[i]);
+	    }
+	    goto loop;
+	}
+	else if (cptr[1] == '-')
+	{
+	    cptr += 2;
+	    i = get_number();
+	    if (havetags)
+		unknown_rhs(-i);
+	    fprintf(f, "yystack.l_mark[%d]", -i - n);
+	    goto loop;
+	}
+#if defined(YYBTYACC)
+	else if (isalpha(cptr[1]) || cptr[1] == '_')
+	{
+	    char *arg;
+	    ++cptr;
+	    arg = scan_id();
+	    for (i = plhs[nrules]->args - 1; i >= 0; i--)
+		if (arg == plhs[nrules]->argnames[i])
+		    break;
+	    if (i < 0)
+		unknown_arg_warning(lineno, "$", arg, line, cptr);
+	    tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
+	    fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
+	    if (tag)
+		fprintf(f, ".%s", tag);
+	    else if (havetags)
+		untyped_arg_warning(lineno, "$", arg);
+	    goto loop;
+	}
+#endif
+    }
+#if defined(YYBTYACC)
+    if (c == '@')
+    {
+	if (!locations)
+	{
+	    int l_lineno = lineno;
+	    char *l_line = dup_line();
+	    char *l_cptr = l_line + (cptr - line);
+	    syntax_error(l_lineno, l_line, l_cptr);
+	}
+	if (cptr[1] == '$')
+	{
+	    fprintf(f, "yyloc");
+	    cptr += 2;
+	    goto loop;
+	}
+	else if (isdigit(UCH(cptr[1])))
+	{
+	    ++cptr;
+	    i = get_number();
+	    if (i == 0)
+		fprintf(f, "yystack.p_mark[%d]", -n);
+	    else if (i > maxoffset)
+	    {
+		at_warning(lineno, i);
+		fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
+	    }
+	    else if (offsets)
+		fprintf(f, "yystack.p_mark[%d]", offsets[i]);
+	    goto loop;
+	}
+    }
+#endif
+    if (isalpha(c) || c == '_' || c == '$')
+    {
+	do
+	{
+	    putc(c, f);
+	    c = *++cptr;
+	}
+	while (isalnum(c) || c == '_' || c == '$');
+	goto loop;
+    }
+    ++cptr;
+#if defined(YYBTYACC)
+    if (backtrack)
+    {
+	if (trialaction && c == L_BRAC && depth == 0)
+	{
+	    ++depth;
+	    putc(L_CURL, f);
+	    goto loop;
+	}
+	if (trialaction && c == R_BRAC && depth == 1)
+	{
+	    --depth;
+	    putc(R_CURL, f);
+	    c = nextc();
+	    if (c == L_BRAC && !haveyyval)
+	    {
+		goto loop;
+	    }
+	    if (c == L_CURL && !haveyyval)
+	    {
+		fprintf(f, "  if (!yytrial)\n");
+		if (!lflag)
+		    fprintf(f, line_format, lineno, input_file_name);
+		trialaction = 0;
+		goto loop;
+	    }
+	    fprintf(f, "\nbreak;\n");
+	    FREE(a_line);
+	    if (maxoffset > 0)
+		FREE(offsets);
+	    return;
+	}
+    }
+#endif
+    putc(c, f);
+    switch (c)
+    {
+    case '\n':
+	get_line();
+	if (line)
+	    goto loop;
+	unterminated_action(a_lineno, a_line, a_cptr);
+
+    case ';':
+	if (depth > 0)
+	    goto loop;
+	fprintf(f, "\nbreak;\n");
+	free(a_line);
+	if (maxoffset > 0)
+	    FREE(offsets);
+	return;
+
+#if defined(YYBTYACC)
+    case L_BRAC:
+	if (backtrack)
+	    ++depth;
+	goto loop;
+
+    case R_BRAC:
+	if (backtrack)
+	    --depth;
+	goto loop;
+#endif
+
+    case L_CURL:
+	++depth;
+	goto loop;
+
+    case R_CURL:
+	if (--depth > 0)
+	    goto loop;
+#if defined(YYBTYACC)
+	if (backtrack)
+	{
+	    c = nextc();
+	    if (c == L_BRAC && !haveyyval)
+	    {
+		trialaction = 1;
+		goto loop;
+	    }
+	    if (c == L_CURL && !haveyyval)
+	    {
+		fprintf(f, "  if (!yytrial)\n");
+		if (!lflag)
+		    fprintf(f, line_format, lineno, input_file_name);
+		goto loop;
+	    }
+	}
+#endif
+	fprintf(f, "\nbreak;\n");
+	free(a_line);
+	if (maxoffset > 0)
+	    FREE(offsets);
+	return;
 
-    if (last_was_action)
-	insert_empty_rule();
-    last_was_action = 0;
+    case '\'':
+    case '"':
+	{
+	    char *s = copy_string(c);
+	    fputs(s, f);
+	    free(s);
+	}
+	goto loop;
 
-    if (++nitems > maxitems)
-	expand_items();
-    pitem[nitems - 1] = bp;
-}
+    case '/':
+	{
+	    char *s = copy_comment();
+	    fputs(s, f);
+	    free(s);
+	}
+	goto loop;
 
-static char *
-after_blanks(char *s)
-{
-    while (*s != '\0' && isspace(UCH(*s)))
-	++s;
-    return s;
+    default:
+	goto loop;
+    }
 }
 
+#if defined(YYBTYACC)
 static void
-copy_action(void)
+copy_destructor(void)
 {
     int c;
-    int i, n;
     int depth;
-    int quote;
     char *tag;
-    FILE *f = action_file;
-    int a_lineno = lineno;
-    char *a_line = dup_line();
-    char *a_cptr = a_line + (cptr - line);
-
-    if (last_was_action)
-	insert_empty_rule();
-    last_was_action = 1;
+    bucket *bp;
+    struct mstring *destructor_text = msnew();
+    char *code_text;
+    int a_lineno;
+    char *a_line;
+    char *a_cptr;
 
-    fprintf(f, "case %d:\n", nrules - 2);
     if (!lflag)
-	fprintf(f, line_format, lineno, input_file_name);
-    if (*cptr == '=')
-	++cptr;
+	msprintf(destructor_text, line_format, lineno, input_file_name);
 
-    /* avoid putting curly-braces in first column, to ease editing */
-    if (*after_blanks(cptr) == L_CURL)
-    {
-	putc('\t', f);
-	cptr = after_blanks(cptr);
-    }
+    cptr = after_blanks(cptr);
+    if (*cptr == L_CURL)
+	/* avoid putting curly-braces in first column, to ease editing */
+	mputc(destructor_text, '\t');
+    else
+	syntax_error(lineno, line, cptr);
 
-    n = 0;
-    for (i = nitems - 1; pitem[i]; --i)
-	++n;
+    a_lineno = lineno;
+    a_line = dup_line();
+    a_cptr = a_line + (cptr - line);
 
     depth = 0;
   loop:
@@ -1596,25 +2628,8 @@ copy_action(void)
 	    c = *cptr;
 	    if (c == '$')
 	    {
-		fprintf(f, "yyval.%s", tag);
-		++cptr;
-		FREE(d_line);
-		goto loop;
-	    }
-	    else if (isdigit(c))
-	    {
-		i = get_number();
-		if (i > n)
-		    dollar_warning(d_lineno, i);
-		fprintf(f, "yystack.l_mark[%d].%s", i - n, tag);
-		FREE(d_line);
-		goto loop;
-	    }
-	    else if (c == '-' && isdigit(UCH(cptr[1])))
-	    {
+		msprintf(destructor_text, "(*val).%s", tag);
 		++cptr;
-		i = -get_number() - n;
-		fprintf(f, "yystack.l_mark[%d].%s", i, tag);
 		FREE(d_line);
 		goto loop;
 	    }
@@ -1623,77 +2638,45 @@ copy_action(void)
 	}
 	else if (cptr[1] == '$')
 	{
-	    if (ntags)
-	    {
-		tag = plhs[nrules]->tag;
-		if (tag == 0)
-		    untyped_lhs();
-		fprintf(f, "yyval.%s", tag);
-	    }
-	    else
-		fprintf(f, "yyval");
+	    /* process '$$' later; replacement is context dependent */
+	    msprintf(destructor_text, "$$");
 	    cptr += 2;
 	    goto loop;
 	}
-	else if (isdigit(UCH(cptr[1])))
-	{
-	    ++cptr;
-	    i = get_number();
-	    if (ntags)
-	    {
-		if (i <= 0 || i > n)
-		    unknown_rhs(i);
-		tag = pitem[nitems + i - n - 1]->tag;
-		if (tag == 0)
-		    untyped_rhs(i, pitem[nitems + i - n - 1]->name);
-		fprintf(f, "yystack.l_mark[%d].%s", i - n, tag);
-	    }
-	    else
-	    {
-		if (i > n)
-		    dollar_warning(lineno, i);
-		fprintf(f, "yystack.l_mark[%d]", i - n);
-	    }
-	    goto loop;
-	}
-	else if (cptr[1] == '-')
+    }
+    if (c == '@' && cptr[1] == '$')
+    {
+	if (!locations)
 	{
-	    cptr += 2;
-	    i = get_number();
-	    if (ntags)
-		unknown_rhs(-i);
-	    fprintf(f, "yystack.l_mark[%d]", -i - n);
-	    goto loop;
+	    int l_lineno = lineno;
+	    char *l_line = dup_line();
+	    char *l_cptr = l_line + (cptr - line);
+	    syntax_error(l_lineno, l_line, l_cptr);
 	}
+	msprintf(destructor_text, "(*loc)");
+	cptr += 2;
+	goto loop;
     }
     if (isalpha(c) || c == '_' || c == '$')
     {
 	do
 	{
-	    putc(c, f);
+	    mputc(destructor_text, c);
 	    c = *++cptr;
 	}
 	while (isalnum(c) || c == '_' || c == '$');
 	goto loop;
     }
-    putc(c, f);
     ++cptr;
+    mputc(destructor_text, c);
     switch (c)
     {
     case '\n':
-      next_line:
 	get_line();
 	if (line)
 	    goto loop;
 	unterminated_action(a_lineno, a_line, a_cptr);
 
-    case ';':
-	if (depth > 0)
-	    goto loop;
-	fprintf(f, "\nbreak;\n");
-	free(a_line);
-	return;
-
     case L_CURL:
 	++depth;
 	goto loop;
@@ -1701,83 +2684,180 @@ copy_action(void)
     case R_CURL:
 	if (--depth > 0)
 	    goto loop;
-	fprintf(f, "\nbreak;\n");
-	free(a_line);
-	return;
+	goto process_symbols;
 
     case '\'':
     case '"':
 	{
-	    int s_lineno = lineno;
-	    char *s_line = dup_line();
-	    char *s_cptr = s_line + (cptr - line - 1);
+	    char *s = copy_string(c);
+	    msprintf(destructor_text, "%s", s);
+	    free(s);
+	}
+	goto loop;
 
-	    quote = c;
-	    for (;;)
-	    {
-		c = *cptr++;
-		putc(c, f);
-		if (c == quote)
+    case '/':
+	{
+	    char *s = copy_comment();
+	    msprintf(destructor_text, "%s", s);
+	    free(s);
+	}
+	goto loop;
+
+    default:
+	goto loop;
+    }
+  process_symbols:
+    code_text = msdone(destructor_text);
+    for (;;)
+    {
+	c = nextc();
+	if (c == EOF)
+	    unexpected_EOF();
+	if (c == '<')
+	{
+	    if (cptr[1] == '>')
+	    {			/* "no semantic type" default destructor */
+		cptr += 2;
+		if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
 		{
-		    FREE(s_line);
-		    goto loop;
+		    static char untyped_default[] = "<>";
+		    bp = make_bucket("untyped default");
+		    bp->tag = untyped_default;
+		    default_destructor[UNTYPED_DEFAULT] = bp;
 		}
-		if (c == '\n')
-		    unterminated_string(s_lineno, s_line, s_cptr);
-		if (c == '\\')
+		if (bp->destructor != NULL)
+		    destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+		else
+		    /* replace "$$" with "(*val)" in destructor code */
+		    bp->destructor = process_destructor_XX(code_text, NULL);
+	    }
+	    else if (cptr[1] == '*' && cptr[2] == '>')
+	    {			/* "no per-symbol or per-type" default destructor */
+		cptr += 3;
+		if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
 		{
-		    c = *cptr++;
-		    putc(c, f);
-		    if (c == '\n')
-		    {
-			get_line();
-			if (line == 0)
-			    unterminated_string(s_lineno, s_line, s_cptr);
-		    }
+		    static char typed_default[] = "<*>";
+		    bp = make_bucket("typed default");
+		    bp->tag = typed_default;
+		    default_destructor[TYPED_DEFAULT] = bp;
+		}
+		if (bp->destructor != NULL)
+		    destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+		else
+		{
+		    /* postpone re-processing destructor $$s until end of grammar spec */
+		    bp->destructor = TMALLOC(char, strlen(code_text) + 1);
+		    NO_SPACE(bp->destructor);
+		    strcpy(bp->destructor, code_text);
 		}
 	    }
+	    else
+	    {			/* "semantic type" default destructor */
+		tag = get_tag();
+		bp = lookup_type_destructor(tag);
+		if (bp->destructor != NULL)
+		    destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+		else
+		    /* replace "$$" with "(*val).tag" in destructor code */
+		    bp->destructor = process_destructor_XX(code_text, tag);
+	    }
 	}
+	else if (isalpha(c) || c == '_' || c == '.' || c == '$')
+	{			/* "symbol" destructor */
+	    bp = get_name();
+	    if (bp->destructor != NULL)
+		destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+	    else
+	    {
+		/* postpone re-processing destructor $$s until end of grammar spec */
+		bp->destructor = TMALLOC(char, strlen(code_text) + 1);
+		NO_SPACE(bp->destructor);
+		strcpy(bp->destructor, code_text);
+	    }
+	}
+	else
+	    break;
+    }
+    free(a_line);
+    free(code_text);
+}
 
-    case '/':
-	c = *cptr;
-	if (c == '/')
+static char *
+process_destructor_XX(char *code, char *tag)
+{
+    int c;
+    int quote;
+    int depth;
+    struct mstring *new_code = msnew();
+    char *codeptr = code;
+
+    depth = 0;
+  loop:			/* step thru code */
+    c = *codeptr;
+    if (c == '$' && codeptr[1] == '$')
+    {
+	codeptr += 2;
+	if (tag == NULL)
+	    msprintf(new_code, "(*val)");
+	else
+	    msprintf(new_code, "(*val).%s", tag);
+	goto loop;
+    }
+    if (isalpha(c) || c == '_' || c == '$')
+    {
+	do
+	{
+	    mputc(new_code, c);
+	    c = *++codeptr;
+	}
+	while (isalnum(c) || c == '_' || c == '$');
+	goto loop;
+    }
+    ++codeptr;
+    mputc(new_code, c);
+    switch (c)
+    {
+    case L_CURL:
+	++depth;
+	goto loop;
+
+    case R_CURL:
+	if (--depth > 0)
+	    goto loop;
+	return msdone(new_code);
+
+    case '\'':
+    case '"':
+	quote = c;
+	for (;;)
 	{
-	    putc('*', f);
-	    while ((c = *++cptr) != '\n')
+	    c = *codeptr++;
+	    mputc(new_code, c);
+	    if (c == quote)
+		goto loop;
+	    if (c == '\\')
 	    {
-		if (c == '*' && cptr[1] == '/')
-		    fprintf(f, "* ");
-		else
-		    putc(c, f);
+		c = *codeptr++;
+		mputc(new_code, c);
 	    }
-	    fprintf(f, "*/\n");
-	    goto next_line;
 	}
+
+    case '/':
+	c = *codeptr;
 	if (c == '*')
 	{
-	    int c_lineno = lineno;
-	    char *c_line = dup_line();
-	    char *c_cptr = c_line + (cptr - line - 1);
-
-	    putc('*', f);
-	    ++cptr;
+	    mputc(new_code, c);
+	    ++codeptr;
 	    for (;;)
 	    {
-		c = *cptr++;
-		putc(c, f);
-		if (c == '*' && *cptr == '/')
+		c = *codeptr++;
+		mputc(new_code, c);
+		if (c == '*' && *codeptr == '/')
 		{
-		    putc('/', f);
-		    ++cptr;
-		    FREE(c_line);
+		    mputc(new_code, '/');
+		    ++codeptr;
 		    goto loop;
 		}
-		if (c == '\n')
-		{
-		    get_line();
-		    if (line == 0)
-			unterminated_comment(c_lineno, c_line, c_cptr);
-		}
 	    }
 	}
 	goto loop;
@@ -1786,6 +2866,7 @@ copy_action(void)
 	goto loop;
     }
 }
+#endif /* defined(YYBTYACC) */
 
 static int
 mark_symbol(void)
@@ -1819,7 +2900,6 @@ mark_symbol(void)
     else
     {
 	syntax_error(lineno, line, cptr);
-	/*NOTREACHED */
     }
 
     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
@@ -1850,7 +2930,11 @@ read_grammar(void)
 	    || c == '\''
 	    || c == '"')
 	    add_symbol();
+#if defined(YYBTYACC)
+	else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
+#else
 	else if (c == L_CURL || c == '=')
+#endif
 	    copy_action();
 	else if (c == '|')
 	{
@@ -1867,6 +2951,10 @@ read_grammar(void)
 	    syntax_error(lineno, line, cptr);
     }
     end_rule();
+#if defined(YYBTYACC)
+    if (goal->args > 0)
+	start_requires_args(goal->name);
+#endif
 }
 
 static void
@@ -1970,6 +3058,9 @@ pack_symbols(void)
     bucket *bp;
     bucket **v;
     Value_t i, j, k, n;
+#if defined(YYBTYACC)
+    Value_t max_tok_pval;
+#endif
 
     nsyms = 2;
     ntokens = 1;
@@ -1980,7 +3071,7 @@ pack_symbols(void)
 	    ++ntokens;
     }
     start_symbol = (Value_t) ntokens;
-    nvars = nsyms - ntokens;
+    nvars = (Value_t) (nsyms - ntokens);
 
     symbol_name = TMALLOC(char *, nsyms);
     NO_SPACE(symbol_name);
@@ -1988,12 +3079,26 @@ pack_symbols(void)
     symbol_value = TMALLOC(Value_t, nsyms);
     NO_SPACE(symbol_value);
 
-    symbol_prec = TMALLOC(short, nsyms);
+    symbol_prec = TMALLOC(Value_t, nsyms);
     NO_SPACE(symbol_prec);
 
     symbol_assoc = TMALLOC(char, nsyms);
     NO_SPACE(symbol_assoc);
 
+#if defined(YYBTYACC)
+    symbol_pval = TMALLOC(Value_t, nsyms);
+    NO_SPACE(symbol_pval);
+
+    if (destructor)
+    {
+	symbol_destructor = CALLOC(sizeof(char *), nsyms);
+	NO_SPACE(symbol_destructor);
+
+	symbol_type_tag = CALLOC(sizeof(char *), nsyms);
+	NO_SPACE(symbol_type_tag);
+    }
+#endif
+
     v = TMALLOC(bucket *, nsyms);
     NO_SPACE(v);
 
@@ -2072,17 +3177,34 @@ pack_symbols(void)
     symbol_value[0] = 0;
     symbol_prec[0] = 0;
     symbol_assoc[0] = TOKEN;
+#if defined(YYBTYACC)
+    symbol_pval[0] = 0;
+    max_tok_pval = 0;
+#endif
     for (i = 1; i < ntokens; ++i)
     {
 	symbol_name[i] = v[i]->name;
 	symbol_value[i] = v[i]->value;
 	symbol_prec[i] = v[i]->prec;
 	symbol_assoc[i] = v[i]->assoc;
+#if defined(YYBTYACC)
+	symbol_pval[i] = v[i]->value;
+	if (symbol_pval[i] > max_tok_pval)
+	    max_tok_pval = symbol_pval[i];
+	if (destructor)
+	{
+	    symbol_destructor[i] = v[i]->destructor;
+	    symbol_type_tag[i] = v[i]->tag;
+	}
+#endif
     }
     symbol_name[start_symbol] = name_pool;
     symbol_value[start_symbol] = -1;
     symbol_prec[start_symbol] = 0;
     symbol_assoc[start_symbol] = TOKEN;
+#if defined(YYBTYACC)
+    symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
+#endif
     for (++i; i < nsyms; ++i)
     {
 	k = v[i]->index;
@@ -2090,6 +3212,14 @@ pack_symbols(void)
 	symbol_value[k] = v[i]->value;
 	symbol_prec[k] = v[i]->prec;
 	symbol_assoc[k] = v[i]->assoc;
+#if defined(YYBTYACC)
+	symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
+	if (destructor)
+	{
+	    symbol_destructor[k] = v[i]->destructor;
+	    symbol_type_tag[k] = v[i]->tag;
+	}
+#endif
     }
 
     if (gflag)
@@ -2141,6 +3271,21 @@ pack_grammar(void)
     j = 4;
     for (i = 3; i < nrules; ++i)
     {
+#if defined(YYBTYACC)
+	if (plhs[i]->args > 0)
+	{
+	    if (plhs[i]->argnames)
+	    {
+		FREE(plhs[i]->argnames);
+		plhs[i]->argnames = NULL;
+	    }
+	    if (plhs[i]->argtags)
+	    {
+		FREE(plhs[i]->argtags);
+		plhs[i]->argtags = NULL;
+	    }
+	}
+#endif /* defined(YYBTYACC) */
 	rlhs[i] = plhs[i]->index;
 	rrhs[i] = j;
 	assoc = TOKEN;
@@ -2167,6 +3312,9 @@ pack_grammar(void)
 
     FREE(plhs);
     FREE(pitem);
+#if defined(YYBTYACC)
+    clean_arg_cache();
+#endif
 }
 
 static void
@@ -2208,6 +3356,85 @@ print_grammar(void)
     }
 }
 
+#if defined(YYBTYACC)
+static void
+finalize_destructors(void)
+{
+    int i;
+    bucket *bp;
+    char *tag;
+
+    for (i = 2; i < nsyms; ++i)
+    {
+	tag = symbol_type_tag[i];
+	if (symbol_destructor[i] == NULL)
+	{
+	    if (tag == NULL)
+	    {			/* use <> destructor, if there is one */
+		if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
+		{
+		    symbol_destructor[i] = TMALLOC(char,
+						   strlen(bp->destructor) + 1);
+		    NO_SPACE(symbol_destructor[i]);
+		    strcpy(symbol_destructor[i], bp->destructor);
+		}
+	    }
+	    else
+	    {			/* use type destructor for this tag, if there is one */
+		bp = lookup_type_destructor(tag);
+		if (bp->destructor != NULL)
+		{
+		    symbol_destructor[i] = TMALLOC(char,
+						   strlen(bp->destructor) + 1);
+		    NO_SPACE(symbol_destructor[i]);
+		    strcpy(symbol_destructor[i], bp->destructor);
+		}
+		else
+		{		/* use <*> destructor, if there is one */
+		    if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
+			/* replace "$$" with "(*val).tag" in destructor code */
+			symbol_destructor[i]
+			    = process_destructor_XX(bp->destructor, tag);
+		}
+	    }
+	}
+	else
+	{			/* replace "$$" with "(*val)[.tag]" in destructor code */
+	    symbol_destructor[i]
+		= process_destructor_XX(symbol_destructor[i], tag);
+	}
+    }
+    /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
+    DO_FREE(symbol_type_tag);	/* no longer needed */
+    if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
+    {
+	FREE(bp->name);
+	/* 'bp->tag' is a static value, don't free */
+	FREE(bp->destructor);
+	FREE(bp);
+    }
+    if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
+    {
+	FREE(bp->name);
+	/* 'bp->tag' is a static value, don't free */
+	FREE(bp->destructor);
+	FREE(bp);
+    }
+    if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
+    {
+	bucket *p;
+	for (; bp; bp = p)
+	{
+	    p = bp->link;
+	    FREE(bp->name);
+	    /* 'bp->tag' freed by 'free_tags()' */
+	    FREE(bp->destructor);
+	    FREE(bp);
+	}
+    }
+}
+#endif /* defined(YYBTYACC) */
+
 void
 reader(void)
 {
@@ -2216,13 +3443,17 @@ reader(void)
     read_declarations();
     read_grammar();
     free_symbol_table();
-    free_tags();
     pack_names();
     check_symbols();
     pack_symbols();
     pack_grammar();
     free_symbols();
     print_grammar();
+#if defined(YYBTYACC)
+    if (destructor)
+	finalize_destructors();
+#endif
+    free_tags();
 }
 
 #ifdef NO_LEAKS
@@ -2259,5 +3490,10 @@ reader_leaks(void)
     DO_FREE(symbol_prec);
     DO_FREE(symbol_assoc);
     DO_FREE(symbol_value);
+#if defined(YYBTYACC)
+    DO_FREE(symbol_pval);
+    DO_FREE(symbol_destructor);
+    DO_FREE(symbol_type_tag);
+#endif
 }
 #endif

Index: src/external/bsd/byacc/dist/mstring.c
diff -u src/external/bsd/byacc/dist/mstring.c:1.1.1.1 src/external/bsd/byacc/dist/mstring.c:1.2
--- src/external/bsd/byacc/dist/mstring.c:1.1.1.1	Sat Jan  3 17:58:23 2015
+++ src/external/bsd/byacc/dist/mstring.c	Sat Jan  3 18:22:52 2015
@@ -1,6 +1,12 @@
-/*	$NetBSD: mstring.c,v 1.1.1.1 2015/01/03 22:58:23 christos Exp $	*/
+/*	$NetBSD: mstring.c,v 1.2 2015/01/03 23:22:52 christos Exp $	*/
 
 /* Id: mstring.c,v 1.6 2014/04/22 23:36:31 tom Exp  */
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: mstring.c,v 1.2 2015/01/03 23:22:52 christos Exp $");
 
 #include <stdlib.h>
 #include <stdio.h>

Index: src/external/bsd/byacc/dist/output.c
diff -u src/external/bsd/byacc/dist/output.c:1.10 src/external/bsd/byacc/dist/output.c:1.11
--- src/external/bsd/byacc/dist/output.c:1.10	Mon Dec 30 14:08:55 2013
+++ src/external/bsd/byacc/dist/output.c	Sat Jan  3 18:22:52 2015
@@ -1,19 +1,29 @@
-/*	$NetBSD: output.c,v 1.10 2013/12/30 19:08:55 christos Exp $	*/
+/*	$NetBSD: output.c,v 1.11 2015/01/03 23:22:52 christos Exp $	*/
 
-/* Id: output.c,v 1.45 2013/03/05 00:29:17 tom Exp  */
+/* Id: output.c,v 1.74 2014/10/05 23:21:09 tom Exp  */
 
 #include "defs.h"
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: output.c,v 1.10 2013/12/30 19:08:55 christos Exp $");
+__RCSID("$NetBSD: output.c,v 1.11 2015/01/03 23:22:52 christos Exp $");
 
 #define StaticOrR	(rflag ? "" : "static ")
 #define CountLine(fp)   (!rflag || ((fp) == code_file))
 
+#if defined(YYBTYACC)
+#define PER_STATE 3
+#else
+#define PER_STATE 2
+#endif
+
 static int nvectors;
 static int nentries;
 static Value_t **froms;
 static Value_t **tos;
+#if defined(YYBTYACC)
+static Value_t *conflicts = NULL;
+static Value_t nconflicts = 0;
+#endif
 static Value_t *tally;
 static Value_t *width;
 static Value_t *state_count;
@@ -24,7 +34,7 @@ static int maxtable;
 static Value_t *table;
 static Value_t *check;
 static int lowzero;
-static int high;
+static long high;
 
 static void
 putc_code(FILE * fp, int c)
@@ -49,12 +59,49 @@ puts_code(FILE * fp, const char *s)
 }
 
 static void
+puts_param_types(FILE * fp, param * list, int more)
+{
+    param *p;
+
+    if (list != 0)
+    {
+	for (p = list; p; p = p->next)
+	{
+	    size_t len_type = strlen(p->type);
+	    fprintf(fp, "%s%s%s%s%s", p->type,
+		    (((len_type != 0) && (p->type[len_type - 1] == '*'))
+		     ? ""
+		     : " "),
+		    p->name, p->type2,
+		    ((more || p->next) ? ", " : ""));
+	}
+    }
+    else
+    {
+	if (!more)
+	    fprintf(fp, "void");
+    }
+}
+
+static void
+puts_param_names(FILE * fp, param * list, int more)
+{
+    param *p;
+
+    for (p = list; p; p = p->next)
+    {
+	fprintf(fp, "%s%s", p->name,
+		((more || p->next) ? ", " : ""));
+    }
+}
+
+static void
 write_code_lineno(FILE * fp)
 {
     if (!lflag && (fp == code_file))
     {
 	++outline;
-	fprintf(fp, line_format, outline, code_file_name);
+	fprintf(fp, line_format, outline + 1, code_file_name);
     }
 }
 
@@ -110,6 +157,9 @@ output_prefix(FILE * fp)
 	define_prefixed(fp, "yylhs");
 	define_prefixed(fp, "yylen");
 	define_prefixed(fp, "yydefred");
+#if defined(YYBTYACC)
+	define_prefixed(fp, "yystos");
+#endif
 	define_prefixed(fp, "yydgoto");
 	define_prefixed(fp, "yysindex");
 	define_prefixed(fp, "yyrindex");
@@ -118,6 +168,22 @@ output_prefix(FILE * fp)
 	define_prefixed(fp, "yycheck");
 	define_prefixed(fp, "yytname");
 	define_prefixed(fp, "yyrule");
+#if defined(YYBTYACC)
+	if (locations)
+	{
+	    define_prefixed(fp, "yyloc");
+	    define_prefixed(fp, "yylloc");
+	}
+	putc_code(fp, '\n');
+	putl_code(fp, "#if YYBTYACC\n");
+
+	define_prefixed(fp, "yycindex");
+	define_prefixed(fp, "yyctable");
+
+	putc_code(fp, '\n');
+	putl_code(fp, "#endif /* YYBTYACC */\n");
+	putc_code(fp, '\n');
+#endif
     }
     if (CountLine(fp))
 	++outline;
@@ -153,7 +219,7 @@ start_int_table(const char *name, int va
     if (need < 6)
 	need = 6;
     fprintf(output_file,
-	    "%sconst short %s%s[] = {%*d,",
+	    "%sconst YYINT %s%s[] = {%*d,",
 	    StaticOrR, symbol_prefix, name, need, value);
 }
 
@@ -161,8 +227,8 @@ static void
 start_str_table(const char *name)
 {
     fprintf(output_file,
-	    "%sconst char *%s%s[] = {",
-	    StaticOrR, "yy", name);
+	    "%sconst char *const %s%s[] = {",
+	    StaticOrR, symbol_prefix, name);
     output_newline();
 }
 
@@ -174,11 +240,22 @@ end_table(void)
 }
 
 static void
+output_YYINT_typedef(FILE * fp)
+{
+    /* generate the type used to index the various parser tables */
+    if (CountLine(fp))
+	++outline;
+    fprintf(fp, "typedef %s YYINT;\n", CONCAT1("", YYINT));
+}
+
+static void
 output_rule_data(void)
 {
     int i;
     int j;
 
+    output_YYINT_typedef(output_file);
+
     start_int_table("lhs", symbol_value[start_symbol]);
 
     j = 10;
@@ -238,27 +315,123 @@ output_yydefred(void)
     end_table();
 }
 
+#if defined(YYBTYACC)
+static void
+output_accessing_symbols(void)
+{
+    int i, j;
+    int *translate;
+
+    if (nstates != 0)
+    {
+	translate = TMALLOC(int, nstates);
+	NO_SPACE(translate);
+
+	for (i = 0; i < nstates; ++i)
+	{
+	    int gsymb = accessing_symbol[i];
+
+	    translate[i] = symbol_pval[gsymb];
+	}
+
+	/* yystos[] may be unused, depending on compile-time defines */
+	start_int_table("stos", translate[0]);
+
+	j = 10;
+	for (i = 1; i < nstates; ++i)
+	{
+	    if (j < 10)
+		++j;
+	    else
+	    {
+		output_newline();
+		j = 1;
+	    }
+
+	    output_int(translate[i]);
+	}
+
+	end_table();
+	FREE(translate);
+    }
+}
+
+static Value_t
+find_conflict_base(int cbase)
+{
+    int i, j;
+
+    for (i = 0; i < cbase; i++)
+    {
+	for (j = 0; j + cbase < nconflicts; j++)
+	{
+	    if (conflicts[i + j] != conflicts[cbase + j])
+		break;
+	}
+	if (j + cbase >= nconflicts)
+	    break;
+    }
+    return (Value_t) i;
+}
+#endif
+
 static void
 token_actions(void)
 {
     int i, j;
     Value_t shiftcount, reducecount;
+#if defined(YYBTYACC)
+    Value_t conflictcount = 0;
+    Value_t csym = -1;
+    Value_t cbase = 0;
+#endif
     int max, min;
     Value_t *actionrow, *r, *s;
     action *p;
 
-    actionrow = NEW2(2 * ntokens, Value_t);
+    actionrow = NEW2(PER_STATE * ntokens, Value_t);
     for (i = 0; i < nstates; ++i)
     {
 	if (parser[i])
 	{
-	    for (j = 0; j < 2 * ntokens; ++j)
+	    for (j = 0; j < PER_STATE * ntokens; ++j)
 		actionrow[j] = 0;
 
 	    shiftcount = 0;
 	    reducecount = 0;
+#if defined(YYBTYACC)
+	    if (backtrack)
+	    {
+		conflictcount = 0;
+		csym = -1;
+		cbase = nconflicts;
+	    }
+#endif
 	    for (p = parser[i]; p; p = p->next)
 	    {
+#if defined(YYBTYACC)
+		if (backtrack)
+		{
+		    if (csym != -1 && csym != p->symbol)
+		    {
+			conflictcount++;
+			conflicts[nconflicts++] = -1;
+			j = find_conflict_base(cbase);
+			actionrow[csym + 2 * ntokens] = (Value_t) (j + 1);
+			if (j == cbase)
+			{
+			    cbase = nconflicts;
+			}
+			else
+			{
+			    if (conflicts[cbase] == -1)
+				cbase++;
+			    nconflicts = cbase;
+			}
+			csym = -1;
+		    }
+		}
+#endif
 		if (p->suppressed == 0)
 		{
 		    if (p->action_code == SHIFT)
@@ -272,17 +445,65 @@ token_actions(void)
 			actionrow[p->symbol + ntokens] = p->number;
 		    }
 		}
+#if defined(YYBTYACC)
+		else if (backtrack && p->suppressed == 1)
+		{
+		    csym = p->symbol;
+		    if (p->action_code == SHIFT)
+		    {
+			conflicts[nconflicts++] = p->number;
+		    }
+		    else if (p->action_code == REDUCE && p->number != defred[i])
+		    {
+			if (cbase == nconflicts)
+			{
+			    if (cbase)
+				cbase--;
+			    else
+				conflicts[nconflicts++] = -1;
+			}
+			conflicts[nconflicts++] = (Value_t) (p->number - 2);
+		    }
+		}
+#endif
 	    }
+#if defined(YYBTYACC)
+	    if (backtrack && csym != -1)
+	    {
+		conflictcount++;
+		conflicts[nconflicts++] = -1;
+		j = find_conflict_base(cbase);
+		actionrow[csym + 2 * ntokens] = (Value_t) (j + 1);
+		if (j == cbase)
+		{
+		    cbase = nconflicts;
+		}
+		else
+		{
+		    if (conflicts[cbase] == -1)
+			cbase++;
+		    nconflicts = cbase;
+		}
+	    }
+#endif
 
 	    tally[i] = shiftcount;
 	    tally[nstates + i] = reducecount;
+#if defined(YYBTYACC)
+	    if (backtrack)
+		tally[2 * nstates + i] = conflictcount;
+#endif
 	    width[i] = 0;
 	    width[nstates + i] = 0;
+#if defined(YYBTYACC)
+	    if (backtrack)
+		width[2 * nstates + i] = 0;
+#endif
 	    if (shiftcount > 0)
 	    {
 		froms[i] = r = NEW2(shiftcount, Value_t);
 		tos[i] = s = NEW2(shiftcount, Value_t);
-		min = MAXSHORT;
+		min = MAXYYINT;
 		max = 0;
 		for (j = 0; j < ntokens; ++j)
 		{
@@ -302,7 +523,7 @@ token_actions(void)
 	    {
 		froms[nstates + i] = r = NEW2(reducecount, Value_t);
 		tos[nstates + i] = s = NEW2(reducecount, Value_t);
-		min = MAXSHORT;
+		min = MAXYYINT;
 		max = 0;
 		for (j = 0; j < ntokens; ++j)
 		{
@@ -318,6 +539,28 @@ token_actions(void)
 		}
 		width[nstates + i] = (Value_t) (max - min + 1);
 	    }
+#if defined(YYBTYACC)
+	    if (backtrack && conflictcount > 0)
+	    {
+		froms[2 * nstates + i] = r = NEW2(conflictcount, Value_t);
+		tos[2 * nstates + i] = s = NEW2(conflictcount, Value_t);
+		min = MAXYYINT;
+		max = 0;
+		for (j = 0; j < ntokens; ++j)
+		{
+		    if (actionrow[2 * ntokens + j])
+		    {
+			if (min > symbol_value[j])
+			    min = symbol_value[j];
+			if (max < symbol_value[j])
+			    max = symbol_value[j];
+			*r++ = symbol_value[j];
+			*s++ = (Value_t) (actionrow[2 * ntokens + j] - 1);
+		    }
+		}
+		width[2 * nstates + i] = (Value_t) (max - min + 1);
+	    }
+#endif
 	}
     }
     FREE(actionrow);
@@ -382,7 +625,7 @@ save_column(int symbol, int default_stat
     if (count == 0)
 	return;
 
-    symno = symbol_value[symbol] + 2 * nstates;
+    symno = symbol_value[symbol] + PER_STATE * nstates;
 
     froms[symno] = sp1 = sp = NEW2(count, Value_t);
     tos[symno] = sp2 = NEW2(count, Value_t);
@@ -481,6 +724,11 @@ sort_actions(void)
 /*  Matching_vector is poorly designed.  The test could easily be made	*/
 /*  faster.  Also, it depends on the vectors being in a specific	*/
 /*  order.								*/
+#if defined(YYBTYACC)
+/*									*/
+/*  Not really any point in checking for matching conflicts -- it is    */
+/*  extremely unlikely to occur, and conflicts are (hopefully) rare.    */
+#endif
 
 static int
 matching_vector(int vector)
@@ -644,9 +892,11 @@ pack_table(void)
 	    FREE(tos[i]);
     }
 
-    FREE(froms);
-    FREE(tos);
-    FREE(pos);
+    DO_FREE(froms);
+    DO_FREE(tos);
+    DO_FREE(tally);
+    DO_FREE(width);
+    DO_FREE(pos);
 }
 
 static void
@@ -690,10 +940,32 @@ output_base(void)
 
     end_table();
 
-    start_int_table("gindex", base[2 * nstates]);
+#if defined(YYBTYACC)
+    output_line("#if YYBTYACC");
+    start_int_table("cindex", base[2 * nstates]);
+
+    j = 10;
+    for (i = 2 * nstates + 1; i < 3 * nstates; i++)
+    {
+	if (j >= 10)
+	{
+	    output_newline();
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	output_int(base[i]);
+    }
+
+    end_table();
+    output_line("#endif");
+#endif
+
+    start_int_table("gindex", base[PER_STATE * nstates]);
 
     j = 10;
-    for (i = 2 * nstates + 1; i < nvectors - 1; i++)
+    for (i = PER_STATE * nstates + 1; i < nvectors - 1; i++)
     {
 	if (j >= 10)
 	{
@@ -716,8 +988,15 @@ output_table(void)
     int i;
     int j;
 
+    if (high >= MAXYYINT)
+    {
+	fprintf(stderr, "YYTABLESIZE: %ld\n", high);
+	fprintf(stderr, "Table is longer than %d elements.\n", MAXYYINT);
+	done(1);
+    }
+
     ++outline;
-    fprintf(code_file, "#define YYTABLESIZE %d\n", high);
+    fprintf(code_file, "#define YYTABLESIZE %ld\n", high);
     start_int_table("table", table[0]);
 
     j = 10;
@@ -764,16 +1043,57 @@ output_check(void)
     FREE(check);
 }
 
+#if defined(YYBTYACC)
+static void
+output_ctable(void)
+{
+    int i;
+    int j;
+    int limit = (conflicts != 0) ? nconflicts : 0;
+
+    if (limit < high)
+	limit = (int)high;
+
+    output_line("#if YYBTYACC");
+    start_int_table("ctable", conflicts ? conflicts[0] : -1);
+
+    j = 10;
+    for (i = 1; i < limit; i++)
+    {
+	if (j >= 10)
+	{
+	    output_newline();
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	output_int((conflicts != 0 && i < nconflicts) ? conflicts[i] : -1);
+    }
+
+    if (conflicts)
+	FREE(conflicts);
+
+    end_table();
+    output_line("#endif");
+}
+#endif
+
 static void
 output_actions(void)
 {
-    nvectors = 2 * nstates + nvars;
+    nvectors = PER_STATE * nstates + nvars;
 
     froms = NEW2(nvectors, Value_t *);
     tos = NEW2(nvectors, Value_t *);
     tally = NEW2(nvectors, Value_t);
     width = NEW2(nvectors, Value_t);
 
+#if defined(YYBTYACC)
+    if (backtrack && (SRtotal + RRtotal) != 0)
+	conflicts = NEW2(4 * (SRtotal + RRtotal), Value_t);
+#endif
+
     token_actions();
     FREE(lookaheads);
     FREE(LA);
@@ -781,7 +1101,7 @@ output_actions(void)
     FREE(accessing_symbol);
 
     goto_actions();
-    FREE(goto_map + ntokens);
+    FREE(goto_base);
     FREE(from_state);
     FREE(to_state);
 
@@ -790,6 +1110,9 @@ output_actions(void)
     output_base();
     output_table();
     output_check();
+#if defined(YYBTYACC)
+    output_ctable();
+#endif
 }
 
 static int
@@ -823,6 +1146,24 @@ is_C_identifier(char *name)
     return (1);
 }
 
+#if USE_HEADER_GUARDS
+static void
+start_defines_file(void)
+{
+    fprintf(defines_file, "#ifndef _%s_defines_h_\n", symbol_prefix);
+    fprintf(defines_file, "#define _%s_defines_h_\n\n", symbol_prefix);
+}
+
+static void
+end_defines_file(void)
+{
+    fprintf(defines_file, "\n#endif /* _%s_defines_h_ */\n", symbol_prefix);
+}
+#else
+#define start_defines_file()	/* nothing */
+#define end_defines_file()	/* nothing */
+#endif
+
 static void
 output_defines(FILE * fp)
 {
@@ -870,7 +1211,7 @@ output_defines(FILE * fp)
 	    {
 		rewind(union_file);
 		while ((c = getc(union_file)) != EOF)
-		    putc(c, fp);
+		    putc_code(fp, c);
 	    }
 	    fprintf(fp, "extern YYSTYPE %slval;\n", symbol_prefix);
 	}
@@ -900,7 +1241,7 @@ output_stored_text(FILE * fp)
 static void
 output_debug(void)
 {
-    int i, j, k, max;
+    int i, j, k, max, maxtok;
     const char **symnam;
     const char *s;
 
@@ -919,30 +1260,65 @@ output_debug(void)
 	fprintf(output_file, "#endif\n");
     }
 
-    max = 0;
-    for (i = 2; i < ntokens; ++i)
-	if (symbol_value[i] > max)
-	    max = symbol_value[i];
+    maxtok = 0;
+    for (i = 0; i < ntokens; ++i)
+	if (symbol_value[i] > maxtok)
+	    maxtok = symbol_value[i];
+
+    /* symbol_value[$accept] = -1         */
+    /* symbol_value[<goal>]  = 0          */
+    /* remaining non-terminals start at 1 */
+    max = maxtok;
+    for (i = ntokens; i < nsyms; ++i)
+	if (((maxtok + 1) + (symbol_value[i] + 1)) > max)
+	    max = (maxtok + 1) + (symbol_value[i] + 1);
+
+    ++outline;
+    fprintf(code_file, "#define YYMAXTOKEN %d\n", maxtok);
+
+    ++outline;
+    fprintf(code_file, "#define YYUNDFTOKEN %d\n", max + 1);
 
     ++outline;
-    fprintf(code_file, "#define YYMAXTOKEN %d\n", max);
     fprintf(code_file, "#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? "
-	"(YYMAXTOKEN + 1) : (a))\n");
+	    "YYUNDFTOKEN : (a))\n");
 
     symnam = TMALLOC(const char *, max + 2);
     NO_SPACE(symnam);
 
-    /* Note that it is  not necessary to initialize the element         */
+    /* Note that it is not necessary to initialize the element          */
     /* symnam[max].                                                     */
+#if defined(YYBTYACC)
+    for (i = 0; i < max; ++i)
+	symnam[i] = 0;
+    for (i = nsyms - 1; i >= 0; --i)
+	symnam[symbol_pval[i]] = symbol_name[i];
+    symnam[max + 1] = "illegal-symbol";
+#else
     for (i = 0; i <= max; ++i)
 	symnam[i] = 0;
     for (i = ntokens - 1; i >= 2; --i)
 	symnam[symbol_value[i]] = symbol_name[i];
     symnam[0] = "end-of-file";
-    symnam[max + 1] = "illegal-token";
+    symnam[max + 1] = "illegal-symbol";
+#endif
 
-    if (!token_table)
+    /*
+     * bison's yytname[] array is roughly the same as byacc's yyname[] array.
+     * The difference is that byacc does not predefine "$undefined".
+     *
+     * If the grammar declares "%token-table", define symbol "yytname" so
+     * an application such as ntpd can build.
+     */
+    if (token_table)
+    {
+	output_line("#undef yytname");
+	output_line("#define yytname yyname");
+    }
+    else
+    {
 	output_line("#if YYDEBUG");
+    }
 
     start_str_table("tname");
     j = 80;
@@ -1123,13 +1499,34 @@ output_debug(void)
     output_line("#endif");
 }
 
+#if defined(YYBTYACC)
+static void
+output_backtracking_parser(FILE * fp)
+{
+    putl_code(fp, "#undef YYBTYACC\n");
+#if defined(YYBTYACC)
+    if (backtrack)
+    {
+	putl_code(fp, "#define YYBTYACC 1\n");
+	putl_code(fp,
+		  "#define YYDEBUGSTR (yytrial ? YYPREFIX \"debug(trial)\" : YYPREFIX \"debug\")\n");
+    }
+    else
+#endif
+    {
+	putl_code(fp, "#define YYBTYACC 0\n");
+	putl_code(fp, "#define YYDEBUGSTR YYPREFIX \"debug\"\n");
+    }
+}
+#endif
+
 static void
 output_pure_parser(FILE * fp)
 {
     putc_code(fp, '\n');
 
     if (fp == code_file)
-	outline += 1;
+	++outline;
     fprintf(fp, "#define YYPURE %d\n", pure_parser);
     putc_code(fp, '\n');
 }
@@ -1140,12 +1537,35 @@ output_stype(FILE * fp)
     if (!unionized && ntags == 0)
     {
 	putc_code(fp, '\n');
-	putl_code(fp, "#ifndef YYSTYPE\n");
+	putl_code(fp, "#if "
+		  "! defined(YYSTYPE) && "
+		  "! defined(YYSTYPE_IS_DECLARED)\n");
+	putl_code(fp, "/* Default: YYSTYPE is the semantic value type. */\n");
 	putl_code(fp, "typedef int YYSTYPE;\n");
+	putl_code(fp, "# define YYSTYPE_IS_DECLARED 1\n");
 	putl_code(fp, "#endif\n");
     }
 }
 
+#if defined(YYBTYACC)
+static void
+output_ltype(FILE * fp)
+{
+    putc_code(fp, '\n');
+    putl_code(fp, "#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED\n");
+    putl_code(fp, "/* Default: YYLTYPE is the text position type. */\n");
+    putl_code(fp, "typedef struct YYLTYPE\n");
+    putl_code(fp, "{\n");
+    putl_code(fp, "    int first_line;\n");
+    putl_code(fp, "    int first_column;\n");
+    putl_code(fp, "    int last_line;\n");
+    putl_code(fp, "    int last_column;\n");
+    putl_code(fp, "} YYLTYPE;\n");
+    putl_code(fp, "#define YYLTYPE_IS_DECLARED 1\n");
+    putl_code(fp, "#endif\n");
+}
+#endif
+
 static void
 output_trailing_text(void)
 {
@@ -1219,7 +1639,7 @@ output_semantic_actions(void)
 static void
 output_parse_decl(FILE * fp)
 {
-    putl_code(fp, "\n");
+    putc_code(fp, '\n');
     putl_code(fp, "/* compatibility with bison */\n");
     putl_code(fp, "#ifdef YYPARSE_PARAM\n");
     putl_code(fp, "/* compatibility with FreeBSD */\n");
@@ -1232,15 +1652,7 @@ output_parse_decl(FILE * fp)
     putl_code(fp, "#else\n");
 
     puts_code(fp, "# define YYPARSE_DECL() yyparse(");
-    if (!parse_param)
-	puts_code(fp, "void");
-    else
-    {
-	param *p;
-	for (p = parse_param; p; p = p->next)
-	    fprintf(fp, "%s %s%s%s", p->type, p->name, p->type2,
-		    p->next ? ", " : "");
-    }
+    puts_param_types(fp, parse_param, 0);
     putl_code(fp, ")\n");
 
     putl_code(fp, "#endif\n");
@@ -1249,19 +1661,47 @@ output_parse_decl(FILE * fp)
 static void
 output_lex_decl(FILE * fp)
 {
-    putl_code(fp, "\n");
+    putc_code(fp, '\n');
     putl_code(fp, "/* Parameters sent to lex. */\n");
     putl_code(fp, "#ifdef YYLEX_PARAM\n");
     if (pure_parser)
     {
 	putl_code(fp, "# ifdef YYLEX_PARAM_TYPE\n");
-	putl_code(fp, "#  define YYLEX_DECL() yylex(YYSTYPE *yylval,"
-		  " YYLEX_PARAM_TYPE YYLEX_PARAM)\n");
+#if defined(YYBTYACC)
+	if (locations)
+	{
+	    putl_code(fp, "#  define YYLEX_DECL() yylex(YYSTYPE *yylval,"
+		      " YYLTYPE *yylloc,"
+		      " YYLEX_PARAM_TYPE YYLEX_PARAM)\n");
+	}
+	else
+#endif
+	{
+	    putl_code(fp, "#  define YYLEX_DECL() yylex(YYSTYPE *yylval,"
+		      " YYLEX_PARAM_TYPE YYLEX_PARAM)\n");
+	}
 	putl_code(fp, "# else\n");
-	putl_code(fp, "#  define YYLEX_DECL() yylex(YYSTYPE *yylval,"
-		  " void * YYLEX_PARAM)\n");
+#if defined(YYBTYACC)
+	if (locations)
+	{
+	    putl_code(fp, "#  define YYLEX_DECL() yylex(YYSTYPE *yylval,"
+		      " YYLTYPE *yylloc,"
+		      " void * YYLEX_PARAM)\n");
+	}
+	else
+#endif
+	{
+	    putl_code(fp, "#  define YYLEX_DECL() yylex(YYSTYPE *yylval,"
+		      " void * YYLEX_PARAM)\n");
+	}
 	putl_code(fp, "# endif\n");
-	putl_code(fp, "# define YYLEX yylex(&yylval, YYLEX_PARAM)\n");
+#if defined(YYBTYACC)
+	if (locations)
+	    putl_code(fp,
+		      "# define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)\n");
+	else
+#endif
+	    putl_code(fp, "# define YYLEX yylex(&yylval, YYLEX_PARAM)\n");
     }
     else
     {
@@ -1271,35 +1711,49 @@ output_lex_decl(FILE * fp)
     putl_code(fp, "#else\n");
     if (pure_parser && lex_param)
     {
-	param *p;
-	puts_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval, ");
-	for (p = lex_param; p; p = p->next)
-	    fprintf(fp, "%s %s%s%s", p->type, p->name, p->type2,
-		    p->next ? ", " : "");
+#if defined(YYBTYACC)
+	if (locations)
+	    puts_code(fp,
+		      "# define YYLEX_DECL() yylex(YYSTYPE *yylval, YYLTYPE *yylloc, ");
+	else
+#endif
+	    puts_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval, ");
+	puts_param_types(fp, lex_param, 0);
 	putl_code(fp, ")\n");
 
-	puts_code(fp, "# define YYLEX yylex(&yylval, ");
-	for (p = lex_param; p; p = p->next)
-	    fprintf(fp, "%s%s", p->name, p->next ? ", " : "");
+#if defined(YYBTYACC)
+	if (locations)
+	    puts_code(fp, "# define YYLEX yylex(&yylval, &yylloc, ");
+	else
+#endif
+	    puts_code(fp, "# define YYLEX yylex(&yylval, ");
+	puts_param_names(fp, lex_param, 0);
 	putl_code(fp, ")\n");
     }
     else if (pure_parser)
     {
-	putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval)\n");
-	putl_code(fp, "# define YYLEX yylex(&yylval)\n");
+#if defined(YYBTYACC)
+	if (locations)
+	{
+	    putl_code(fp,
+		      "# define YYLEX_DECL() yylex(YYSTYPE *yylval, YYLTYPE *yylloc)\n");
+	    putl_code(fp, "# define YYLEX yylex(&yylval, &yylloc)\n");
+	}
+	else
+#endif
+	{
+	    putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval)\n");
+	    putl_code(fp, "# define YYLEX yylex(&yylval)\n");
+	}
     }
     else if (lex_param)
     {
-	param *p;
 	puts_code(fp, "# define YYLEX_DECL() yylex(");
-	for (p = lex_param; p; p = p->next)
-	    fprintf(fp, "%s %s%s%s", p->type, p->name, p->type2,
-		    p->next ? ", " : "");
+	puts_param_types(fp, lex_param, 0);
 	putl_code(fp, ")\n");
 
 	puts_code(fp, "# define YYLEX yylex(");
-	for (p = lex_param; p; p = p->next)
-	    fprintf(fp, "%s%s", p->name, p->next ? ", " : "");
+	puts_param_names(fp, lex_param, 0);
 	putl_code(fp, ")\n");
     }
     else
@@ -1313,38 +1767,114 @@ output_lex_decl(FILE * fp)
 static void
 output_error_decl(FILE * fp)
 {
-    putl_code(fp, "\n");
+    putc_code(fp, '\n');
     putl_code(fp, "/* Parameters sent to yyerror. */\n");
+    putl_code(fp, "#ifndef YYERROR_DECL\n");
+    puts_code(fp, "#define YYERROR_DECL() yyerror(");
+#if defined(YYBTYACC)
+    if (locations)
+	puts_code(fp, "YYLTYPE loc, ");
+#endif
+    puts_param_types(fp, parse_param, 1);
+    putl_code(fp, "const char *s)\n");
+    putl_code(fp, "#endif\n");
+
+    putl_code(fp, "#ifndef YYERROR_CALL\n");
+
+    puts_code(fp, "#define YYERROR_CALL(msg) yyerror(");
+#if defined(YYBTYACC)
+    if (locations)
+	puts_code(fp, "yylloc, ");
+#endif
+    puts_param_names(fp, parse_param, 1);
+    putl_code(fp, "msg)\n");
+
+    putl_code(fp, "#endif\n");
+}
+
+#if defined(YYBTYACC)
+static void
+output_yydestruct_decl(FILE * fp)
+{
+    putc_code(fp, '\n');
+    putl_code(fp, "#ifndef YYDESTRUCT_DECL\n");
+
+    puts_code(fp,
+	      "#define YYDESTRUCT_DECL() "
+	      "yydestruct(const char *msg, int psymb, YYSTYPE *val");
+#if defined(YYBTYACC)
+    if (locations)
+	puts_code(fp, ", YYLTYPE *loc");
+#endif
     if (parse_param)
     {
-	param *p;
-
-	putl_code(fp, "#ifndef YYERROR_DECL\n");
-	fprintf(fp, "#define YYERROR_DECL() yyerror(");
-	for (p = parse_param; p; p = p->next)
-	    fprintf(fp, "%s %s%s, ", p->type, p->name, p->type2);
-	putl_code(fp, "const char *s)\n");
-	putl_code(fp, "#endif\n");
+	puts_code(fp, ", ");
+	puts_param_types(fp, parse_param, 0);
+    }
+    putl_code(fp, ")\n");
 
-	putl_code(fp, "#ifndef YYERROR_CALL\n");
-	puts_code(fp, "#define YYERROR_CALL(msg) yyerror(");
+    putl_code(fp, "#endif\n");
 
-	for (p = parse_param; p; p = p->next)
-	    fprintf(fp, "%s, ", p->name);
+    putl_code(fp, "#ifndef YYDESTRUCT_CALL\n");
 
-	putl_code(fp, "msg)\n");
-	putl_code(fp, "#endif\n");
+    puts_code(fp, "#define YYDESTRUCT_CALL(msg, psymb, val");
+#if defined(YYBTYACC)
+    if (locations)
+	puts_code(fp, ", loc");
+#endif
+    puts_code(fp, ") yydestruct(msg, psymb, val");
+#if defined(YYBTYACC)
+    if (locations)
+	puts_code(fp, ", loc");
+#endif
+    if (parse_param)
+    {
+	puts_code(fp, ", ");
+	puts_param_names(fp, parse_param, 0);
     }
-    else
+    putl_code(fp, ")\n");
+
+    putl_code(fp, "#endif\n");
+}
+
+static void
+output_yydestruct_impl(void)
+{
+    int i;
+    char *s, *destructor_code;
+
+    putc_code(code_file, '\n');
+    putl_code(code_file, "/* Release memory associated with symbol. */\n");
+    putl_code(code_file, "#if ! defined YYDESTRUCT_IS_DECLARED\n");
+    putl_code(code_file, "static void\n");
+    putl_code(code_file, "YYDESTRUCT_DECL()\n");
+    putl_code(code_file, "{\n");
+    putl_code(code_file, "    switch (psymb)\n");
+    putl_code(code_file, "    {\n");
+    for (i = 2; i < nsyms; ++i)
     {
-	putl_code(fp, "#ifndef YYERROR_DECL\n");
-	putl_code(fp, "#define YYERROR_DECL() yyerror(const char *s)\n");
-	putl_code(fp, "#endif\n");
-	putl_code(fp, "#ifndef YYERROR_CALL\n");
-	putl_code(fp, "#define YYERROR_CALL(msg) yyerror(msg)\n");
-	putl_code(fp, "#endif\n");
+	if ((destructor_code = symbol_destructor[i]) != NULL)
+	{
+	    ++outline;
+	    fprintf(code_file, "\tcase %d:\n", symbol_pval[i]);
+	    /* comprehend the number of lines in the destructor code */
+	    for (s = destructor_code; (s = strchr(s, '\n')) != NULL; s++)
+		++outline;
+	    puts_code(code_file, destructor_code);
+	    putc_code(code_file, '\n');
+	    putl_code(code_file, "\tbreak;\n");
+	    write_code_lineno(code_file);
+	    FREE(destructor_code);
+	}
     }
+    putl_code(code_file, "    }\n");
+    putl_code(code_file, "}\n");
+    putl_code(code_file, "#define YYDESTRUCT_IS_DECLARED 1\n");
+    putl_code(code_file, "#endif\n");
+
+    DO_FREE(symbol_destructor);
 }
+#endif
 
 static void
 free_itemsets(void)
@@ -1386,41 +1916,20 @@ free_reductions(void)
 }
 
 static void
-output_yyerror_call(const char *msg)
-{
-    FILE *fp = code_file;
-
-    puts_code(fp, "    yyerror(");
-    if (parse_param)
-    {
-	param *p;
-	for (p = parse_param; p; p = p->next)
-	    fprintf(fp, "%s, ", p->name);
-    }
-    puts_code(fp, "\"");
-    puts_code(fp, msg);
-    putl_code(fp, "\");\n");
-}
-
-static void
 output_externs(FILE * fp, const char *const section[])
 {
-    int c;
     int i;
     const char *s;
 
     for (i = 0; (s = section[i]) != 0; ++i)
     {
-	if (*s && *s != '#')
+	/* prefix non-blank lines that don't start with
+	   C pre-processor directives with 'extern ' */
+	if (*s && (*s != '#'))
 	    fputs("extern\t", fp);
-	while ((c = *s) != 0)
-	{
-	    putc(c, fp);
-	    ++s;
-	}
 	if (fp == code_file)
 	    ++outline;
-	putc('\n', fp);
+	fprintf(fp, "%s\n", s);
     }
 }
 
@@ -1433,8 +1942,15 @@ output(void)
     free_shifts();
     free_reductions();
 
+#if defined(YYBTYACC)
+    output_backtracking_parser(output_file);
+    if (rflag)
+	output_backtracking_parser(code_file);
+#endif
+
     if (iflag)
     {
+	write_code_lineno(code_file);
 	++outline;
 	fprintf(code_file, "#include \"%s\"\n", externs_file_name);
 	fp = externs_file;
@@ -1442,14 +1958,25 @@ output(void)
     else
 	fp = code_file;
 
-    output_prefix(iflag ? externs_file : output_file);
+    output_prefix(fp);
     output_pure_parser(fp);
     output_stored_text(fp);
     output_stype(fp);
+#if defined(YYBTYACC)
+    if (locations)
+	output_ltype(fp);
+#endif
     output_parse_decl(fp);
     output_lex_decl(fp);
     output_error_decl(fp);
-    write_section(fp, xdecls);
+#if defined(YYBTYACC)
+    if (destructor)
+	output_yydestruct_decl(fp);
+#endif
+    if (iflag || !rflag)
+    {
+	write_section(fp, xdecls);
+    }
 
     if (iflag)
     {
@@ -1475,17 +2002,24 @@ output(void)
     }
 
     if (dflag)
+    {
+	start_defines_file();
 	output_defines(defines_file);
+	end_defines_file();
+    }
 
     output_rule_data();
     output_yydefred();
+#if defined(YYBTYACC)
+    output_accessing_symbols();
+#endif
     output_actions();
     free_parser();
     output_debug();
     if (rflag)
     {
-	output_prefix(code_file);
 	write_section(code_file, xdecls);
+	output_YYINT_typedef(code_file);
 	write_section(code_file, tables);
     }
     write_section(code_file, global_vars);
@@ -1499,18 +2033,18 @@ output(void)
 	write_section(code_file, hdr_vars);
     }
     output_trailing_text();
+#if defined(YYBTYACC)
+    if (destructor)
+	output_yydestruct_impl();
+#endif
     write_section(code_file, body_1);
     if (pure_parser)
     {
 	write_section(code_file, body_vars);
     }
     write_section(code_file, body_2);
-    output_yyerror_call("syntax error");
-    write_section(code_file, body_3);
     output_semantic_actions();
     write_section(code_file, trailer);
-    output_yyerror_call("yacc stack overflow");
-    write_section(code_file, trailer_2);
 }
 
 #ifdef NO_LEAKS

Reply via email to