#include <sys/cdefs.h>
#ifndef lint
#if 0
static char yysccsid[] = "@(#)yaccpar	1.9 (Berkeley) 02/21/93";
#else
__IDSTRING(yyrcsid, "$NetBSD: skeleton.c,v 1.14 1997/10/20 03:41:16 lukem Exp $");
#endif
#endif
#include <stdlib.h>
#define YYBYACC 1
#define YYMAJOR 1
#define YYMINOR 9
#define YYLEX yylex()
#define YYEMPTY -1
#define yyclearin (yychar=(YYEMPTY))
#define yyerrok (yyerrflag=0)
#define YYRECOVERING (yyerrflag!=0)
#define YYPREFIX "yy"
#line 2 "gram.y"
/*
 * Copyright (c) 1983, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
#if 0
static char sccsid[] = "@(#)gram.y	8.1 (Berkeley) 6/9/93";
#endif
static const char rcsid[] =
  "$FreeBSD$";
#endif /* not lint */

#include "defs.h"
#include <sys/types.h>
#include <regex.h>
#include <limits.h>

struct	cmd *cmds = NULL;
struct	cmd *last_cmd;
struct	namelist *last_n;
struct	subcmd *last_sc;

static char  *makestr __P((char *));

#line 73 "gram.y"
typedef union {
	int intval;
	char *string;
	struct subcmd *subcmd;
	struct namelist *namel;
} YYSTYPE;
#line 81 "gram.c"
#define EQUAL 1
#define LP 2
#define RP 3
#define SM 4
#define ARROW 5
#define COLON 6
#define DCOLON 7
#define NAME 8
#define STRING 9
#define INSTALL 10
#define NOTIFY 11
#define EXCEPT 12
#define PATTERN 13
#define SPECIAL 14
#define OPTION 15
#define YYERRCODE 256
short yylhs[] = {                                        -1,
    0,    0,    7,    7,    7,    7,    7,    7,    4,    4,
    5,    5,    2,    2,    3,    3,    3,    3,    3,    1,
    1,    6,    6,
};
short yylen[] = {                                         2,
    0,    2,    3,    4,    6,    4,    6,    1,    1,    3,
    0,    2,    0,    2,    4,    3,    3,    3,    4,    0,
    2,    0,    1,
};
short yydefred[] = {                                      1,
    0,    8,   11,    0,    0,    2,    0,    0,    0,    0,
    0,   10,   12,    9,    3,    0,   13,   13,    0,    0,
    0,    0,   13,   13,   20,    0,    0,    0,    0,   14,
    0,    0,    0,    0,    0,    0,   23,    0,   21,    0,
   16,   17,   18,    0,   15,   19,
};
short yydgoto[] = {                                       1,
   33,   21,   30,   37,    7,   38,    6,
};
short yysindex[] = {                                      0,
    9,    0,    0,   22,   20,    0,   32,   16,   16,   16,
   -8,    0,    0,    0,    0,   29,    0,    0,   16,    7,
   31,   31,    0,    0,    0,   16,   16,   16,   16,    0,
   31,   31,   14,   43,   45,   46,    0,   24,    0,   47,
    0,    0,    0,   48,    0,    0,
};
short yyrindex[] = {                                      0,
    0,    0,    0,   41,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    1,    2,    0,    0,    0,    0,    0,    0,   44,    0,
    5,    6,   50,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,
};
short yygindex[] = {                                      0,
    0,    8,    0,   11,    0,   23,    0,
};
#define YYTABLESIZE 265
short yytable[] = {                                      18,
    4,    6,    4,    6,    5,    7,    5,    7,    4,    6,
    3,    5,    5,    7,   24,    3,    4,    3,   15,   16,
   17,   14,    8,   14,   10,   22,   11,    9,   39,   23,
   31,   32,   44,   19,   12,   20,   34,   35,   36,   13,
   25,   26,   27,   28,   29,    9,   41,    9,   42,   43,
   45,   46,   22,   22,    0,   40,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    4,    6,    0,    0,
    5,    7,    0,    0,    2,
};
short yycheck[] = {                                       8,
    0,    0,    2,    2,    0,    0,    2,    2,    8,    8,
    2,    1,    8,    8,    8,    2,    8,    2,    8,    9,
   10,    8,    1,    8,    5,   18,    7,    6,   15,   19,
   23,   24,    9,    5,    3,    7,   26,   27,   28,    8,
   10,   11,   12,   13,   14,    5,    4,    7,    4,    4,
    4,    4,    9,    4,   -1,   33,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,  256,  256,   -1,   -1,
  256,  256,   -1,   -1,  256,
};
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
#define YYMAXTOKEN 15
#if YYDEBUG
char *yyname[] = {
"end-of-file","EQUAL","LP","RP","SM","ARROW","COLON","DCOLON","NAME","STRING",
"INSTALL","NOTIFY","EXCEPT","PATTERN","SPECIAL","OPTION",
};
char *yyrule[] = {
"$accept : file",
"file :",
"file : file command",
"command : NAME EQUAL namelist",
"command : namelist ARROW namelist cmdlist",
"command : NAME COLON namelist ARROW namelist cmdlist",
"command : namelist DCOLON NAME cmdlist",
"command : NAME COLON namelist DCOLON NAME cmdlist",
"command : error",
"namelist : NAME",
"namelist : LP names RP",
"names :",
"names : names NAME",
"cmdlist :",
"cmdlist : cmdlist cmd",
"cmd : INSTALL options opt_namelist SM",
"cmd : NOTIFY namelist SM",
"cmd : EXCEPT namelist SM",
"cmd : PATTERN namelist SM",
"cmd : SPECIAL opt_namelist STRING SM",
"options :",
"options : options OPTION",
"opt_namelist :",
"opt_namelist : namelist",
};
#endif
#ifdef YYSTACKSIZE
#undef YYMAXDEPTH
#define YYMAXDEPTH YYSTACKSIZE
#else
#ifdef YYMAXDEPTH
#define YYSTACKSIZE YYMAXDEPTH
#else
#define YYSTACKSIZE 10000
#define YYMAXDEPTH 10000
#endif
#endif
#define YYINITSTACKSIZE 200
int yydebug;
int yynerrs;
int yyerrflag;
int yychar;
short *yyssp;
YYSTYPE *yyvsp;
YYSTYPE yyval;
YYSTYPE yylval;
short *yyss;
short *yysslim;
YYSTYPE *yyvs;
int yystacksize;
#line 214 "gram.y"

int	yylineno = 1;
extern	FILE *fin;

int
yylex()
{
	static char yytext[INMAX];
	register int c;
	register char *cp1, *cp2;
	static char quotechars[] = "[]{}*?$";
	
again:
	switch (c = getc(fin)) {
	case EOF:  /* end of file */
		return(0);

	case '#':  /* start of comment */
		while ((c = getc(fin)) != EOF && c != '\n')
			;
		if (c == EOF)
			return(0);
	case '\n':
		yylineno++;
	case ' ':
	case '\t':  /* skip blanks */
		goto again;

	case '=':  /* EQUAL */
		return(EQUAL);

	case '(':  /* LP */
		return(LP);

	case ')':  /* RP */
		return(RP);

	case ';':  /* SM */
		return(SM);

	case '-':  /* -> */
		if ((c = getc(fin)) == '>')
			return(ARROW);
		ungetc(c, fin);
		c = '-';
		break;

	case '"':  /* STRING */
		cp1 = yytext;
		cp2 = &yytext[INMAX - 1];
		for (;;) {
			if (cp1 >= cp2) {
				yyerror("command string too long\n");
				break;
			}
			c = getc(fin);
			if (c == EOF || c == '"')
				break;
			if (c == '\\') {
				if ((c = getc(fin)) == EOF) {
					*cp1++ = '\\';
					break;
				}
			}
			if (c == '\n') {
				yylineno++;
				c = ' '; /* can't send '\n' */
			}
			*cp1++ = c;
		}
		if (c != '"')
			yyerror("missing closing '\"'\n");
		*cp1 = '\0';
		yylval.string = makestr(yytext);
		return(STRING);

	case ':':  /* : or :: */
		if ((c = getc(fin)) == ':')
			return(DCOLON);
		ungetc(c, fin);
		return(COLON);
	}
	cp1 = yytext;
	cp2 = &yytext[INMAX - 1];
	for (;;) {
		if (cp1 >= cp2) {
			yyerror("input line too long\n");
			break;
		}
		if (c == '\\') {
			if ((c = getc(fin)) != EOF) {
				if (any(c, quotechars))
					c |= QUOTE;
			} else {
				*cp1++ = '\\';
				break;
			}
		}
		*cp1++ = c;
		c = getc(fin);
		if (c == EOF || any(c, " \"'\t()=;:\n")) {
			ungetc(c, fin);
			break;
		}
	}
	*cp1 = '\0';
	if (yytext[0] == '-' && yytext[2] == '\0') {
		switch (yytext[1]) {
		case 'b':
			yylval.intval = COMPARE;
			return(OPTION);

		case 'R':
			yylval.intval = REMOVE;
			return(OPTION);

		case 'v':
			yylval.intval = VERIFY;
			return(OPTION);

		case 'w':
			yylval.intval = WHOLE;
			return(OPTION);

		case 'y':
			yylval.intval = YOUNGER;
			return(OPTION);

		case 'h':
			yylval.intval = FOLLOW;
			return(OPTION);

		case 'i':
			yylval.intval = IGNLNKS;
			return(OPTION);
		}
	}
	if (!strcmp(yytext, "install"))
		c = INSTALL;
	else if (!strcmp(yytext, "notify"))
		c = NOTIFY;
	else if (!strcmp(yytext, "except"))
		c = EXCEPT;
	else if (!strcmp(yytext, "except_pat"))
		c = PATTERN;
	else if (!strcmp(yytext, "special"))
		c = SPECIAL;
	else {
		yylval.string = makestr(yytext);
		return(NAME);
	}
	yylval.subcmd = makesubcmd(c);
	return(c);
}

int
any(c, str)
	register int c;
	register char *str;
{
	while (*str)
		if (c == *str++)
			return(1);
	return(0);
}

/*
 * Insert or append ARROW command to list of hosts to be updated.
 */
void
insert(label, files, hosts, subcmds)
	char *label;
	struct namelist *files, *hosts;
	struct subcmd *subcmds;
{
	register struct cmd *c, *prev, *nc;
	register struct namelist *h, *next_h;

	files = expand(files, E_VARS|E_SHELL);
	hosts = expand(hosts, E_ALL);
	for (h = hosts; h != NULL; next_h = h->n_next, free(h), h = next_h) {
		/*
		 * Search command list for an update to the same host.
		 */
		for (prev = NULL, c = cmds; c!=NULL; prev = c, c = c->c_next) {
			if (strcmp(c->c_name, h->n_name) == 0) {
				do {
					prev = c;
					c = c->c_next;
				} while (c != NULL &&
					strcmp(c->c_name, h->n_name) == 0);
				break;
			}
		}
		/*
		 * Insert new command to update host.
		 */
		nc = ALLOC(cmd);
		if (nc == NULL)
			fatal("ran out of memory\n");
		nc->c_type = ARROW;
		nc->c_name = h->n_name;
		nc->c_label = label;
		nc->c_files = files;
		nc->c_cmds = subcmds;
		nc->c_next = c;
		if (prev == NULL)
			cmds = nc;
		else
			prev->c_next = nc;
		/* update last_cmd if appending nc to cmds */
		if (c == NULL)
			last_cmd = nc;
	}
}

/*
 * Append DCOLON command to the end of the command list since these are always
 * executed in the order they appear in the distfile.
 */
void
append(label, files, stamp, subcmds)
	char *label;
	struct namelist *files;
	char *stamp;
	struct subcmd *subcmds;
{
	register struct cmd *c;

	c = ALLOC(cmd);
	if (c == NULL)
		fatal("ran out of memory\n");
	c->c_type = DCOLON;
	c->c_name = stamp;
	c->c_label = label;
	c->c_files = expand(files, E_ALL);
	c->c_cmds = subcmds;
	c->c_next = NULL;
	if (cmds == NULL)
		cmds = last_cmd = c;
	else {
		last_cmd->c_next = c;
		last_cmd = c;
	}
}

/*
 * Error printing routine in parser.
 */
void
yyerror(s)
	char *s;
{
	++nerrs;
	fflush(stdout);
	fprintf(stderr, "rdist: line %d: %s\n", yylineno, s);
}

/*
 * Return a copy of the string.
 */
static char *
makestr(str)
	char *str;
{
	register char *cp, *s;

	str = cp = malloc(strlen(s = str) + 1);
	if (cp == NULL)
		fatal("ran out of memory\n");
	while ((*cp++ = *s++))
		;
	return(str);
}

/*
 * Allocate a namelist structure.
 */
struct namelist *
makenl(name)
	char *name;
{
	register struct namelist *nl;

	nl = ALLOC(namelist);
	if (nl == NULL)
		fatal("ran out of memory\n");
	nl->n_name = name;
	nl->n_next = NULL;
	return(nl);
}

/*
 * Make a sub command for lists of variables, commands, etc.
 */
struct subcmd *
makesubcmd(type)
	int type;
{
	register struct subcmd *sc;

	sc = ALLOC(subcmd);
	if (sc == NULL)
		fatal("ran out of memory\n");
	sc->sc_type = type;
	sc->sc_args = NULL;
	sc->sc_next = NULL;
	sc->sc_name = NULL;
	return(sc);
}
#line 566 "gram.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
int yyparse __P((void));
static int yygrowstack __P((void));
static int yygrowstack()
{
    int newsize, i;
    short *newss;
    YYSTYPE *newvs;

    if ((newsize = yystacksize) == 0)
        newsize = YYINITSTACKSIZE;
    else if (newsize >= YYMAXDEPTH)
        return -1;
    else if ((newsize *= 2) > YYMAXDEPTH)
        newsize = YYMAXDEPTH;
    i = yyssp - yyss;
    if ((newss = (short *)realloc(yyss, newsize * sizeof *newss)) == NULL)
        return -1;
    yyss = newss;
    yyssp = newss + i;
    if ((newvs = (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs)) == NULL)
        return -1;
    yyvs = newvs;
    yyvsp = newvs + i;
    yystacksize = newsize;
    yysslim = yyss + newsize - 1;
    return 0;
}

#define YYABORT goto yyabort
#define YYREJECT goto yyabort
#define YYACCEPT goto yyaccept
#define YYERROR goto yyerrlab
int
yyparse()
{
    int yym, yyn, yystate;
#if YYDEBUG
    char *yys;

    if ((yys = getenv("YYDEBUG")) != NULL)
    {
        yyn = *yys;
        if (yyn >= '0' && yyn <= '9')
            yydebug = yyn - '0';
    }
#endif

    yynerrs = 0;
    yyerrflag = 0;
    yychar = (-1);

    if (yyss == NULL && yygrowstack()) goto yyoverflow;
    yyssp = yyss;
    yyvsp = yyvs;
    *yyssp = yystate = 0;

yyloop:
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
    if (yychar < 0)
    {
        if ((yychar = yylex()) < 0) yychar = 0;
#if YYDEBUG
        if (yydebug)
        {
            yys = 0;
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
            if (!yys) yys = "illegal-symbol";
            printf("%sdebug: state %d, reading %d (%s)\n",
                    YYPREFIX, yystate, yychar, yys);
        }
#endif
    }
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
    {
#if YYDEBUG
        if (yydebug)
            printf("%sdebug: state %d, shifting to state %d\n",
                    YYPREFIX, yystate, yytable[yyn]);
#endif
        if (yyssp >= yysslim && yygrowstack())
        {
            goto yyoverflow;
        }
        *++yyssp = yystate = yytable[yyn];
        *++yyvsp = yylval;
        yychar = (-1);
        if (yyerrflag > 0)  --yyerrflag;
        goto yyloop;
    }
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
    {
        yyn = yytable[yyn];
        goto yyreduce;
    }
    if (yyerrflag) goto yyinrecovery;
    goto yynewerror;
yynewerror:
    yyerror("syntax error");
    goto yyerrlab;
yyerrlab:
    ++yynerrs;
yyinrecovery:
    if (yyerrflag < 3)
    {
        yyerrflag = 3;
        for (;;)
        {
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
            {
#if YYDEBUG
                if (yydebug)
                    printf("%sdebug: state %d, error recovery shifting\
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
#endif
                if (yyssp >= yysslim && yygrowstack())
                {
                    goto yyoverflow;
                }
                *++yyssp = yystate = yytable[yyn];
                *++yyvsp = yylval;
                goto yyloop;
            }
            else
            {
#if YYDEBUG
                if (yydebug)
                    printf("%sdebug: error recovery discarding state %d\n",
                            YYPREFIX, *yyssp);
#endif
                if (yyssp <= yyss) goto yyabort;
                --yyssp;
                --yyvsp;
            }
        }
    }
    else
    {
        if (yychar == 0) goto yyabort;
#if YYDEBUG
        if (yydebug)
        {
            yys = 0;
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
            if (!yys) yys = "illegal-symbol";
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
                    YYPREFIX, yystate, yychar, yys);
        }
#endif
        yychar = (-1);
        goto yyloop;
    }
yyreduce:
#if YYDEBUG
    if (yydebug)
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
                YYPREFIX, yystate, yyn, yyrule[yyn]);
#endif
    yym = yylen[yyn];
    yyval = yyvsp[1-yym];
    switch (yyn)
    {
case 3:
#line 91 "gram.y"
 {
			(void) lookup(yyvsp[-2].string, INSERT, yyvsp[0].namel);
		}
break;
case 4:
#line 94 "gram.y"
 {
			insert(NULL, yyvsp[-3].namel, yyvsp[-1].namel, yyvsp[0].subcmd);
		}
break;
case 5:
#line 97 "gram.y"
 {
			insert(yyvsp[-5].string, yyvsp[-3].namel, yyvsp[-1].namel, yyvsp[0].subcmd);
		}
break;
case 6:
#line 100 "gram.y"
 {
			append(NULL, yyvsp[-3].namel, yyvsp[-1].string, yyvsp[0].subcmd);
		}
break;
case 7:
#line 103 "gram.y"
 {
			append(yyvsp[-5].string, yyvsp[-3].namel, yyvsp[-1].string, yyvsp[0].subcmd);
		}
break;
case 9:
#line 109 "gram.y"
 {
			yyval.namel = makenl(yyvsp[0].string);
		}
break;
case 10:
#line 112 "gram.y"
 {
			yyval.namel = yyvsp[-1].namel;
		}
break;
case 11:
#line 117 "gram.y"
{
			yyval.namel = last_n = NULL;
		}
break;
case 12:
#line 120 "gram.y"
 {
			if (last_n == NULL)
				yyval.namel = last_n = makenl(yyvsp[0].string);
			else {
				last_n->n_next = makenl(yyvsp[0].string);
				last_n = last_n->n_next;
				yyval.namel = yyvsp[-1].namel;
			}
		}
break;
case 13:
#line 131 "gram.y"
{
			yyval.subcmd = last_sc = NULL;
		}
break;
case 14:
#line 134 "gram.y"
 {
			if (last_sc == NULL)
				yyval.subcmd = last_sc = yyvsp[0].subcmd;
			else {
				last_sc->sc_next = yyvsp[0].subcmd;
				last_sc = yyvsp[0].subcmd;
				yyval.subcmd = yyvsp[-1].subcmd;
			}
		}
break;
case 15:
#line 145 "gram.y"
 {
			register struct namelist *nl;

			yyvsp[-3].subcmd->sc_options = yyvsp[-2].intval | options;
			if (yyvsp[-1].namel != NULL) {
				nl = expand(yyvsp[-1].namel, E_VARS);
				if (nl) {
					if (nl->n_next != NULL)
					    yyerror("only one name allowed\n");
					yyvsp[-3].subcmd->sc_name = nl->n_name;
					free(nl);
				} else
					yyvsp[-3].subcmd->sc_name = NULL;
			}
			yyval.subcmd = yyvsp[-3].subcmd;
		}
break;
case 16:
#line 161 "gram.y"
 {
			if (yyvsp[-1].namel != NULL)
				yyvsp[-2].subcmd->sc_args = expand(yyvsp[-1].namel, E_VARS);
			yyval.subcmd = yyvsp[-2].subcmd;
		}
break;
case 17:
#line 166 "gram.y"
 {
			if (yyvsp[-1].namel != NULL)
				yyvsp[-2].subcmd->sc_args = expand(yyvsp[-1].namel, E_ALL);
			yyval.subcmd = yyvsp[-2].subcmd;
		}
break;
case 18:
#line 171 "gram.y"
 {
			struct namelist *nl;
			regex_t rx;
			int val;
			char errbuf[_POSIX2_LINE_MAX];

			for (nl = yyvsp[-1].namel; nl != NULL; nl = nl->n_next) {
				if ((val = regcomp(&rx, nl->n_name, 
						  REG_EXTENDED))) {
					regerror(val, &rx, errbuf, 
						 sizeof errbuf);
					yyerror(errbuf);
				}
				regfree(&rx);
			}
			yyvsp[-2].subcmd->sc_args = expand(yyvsp[-1].namel, E_VARS);
			yyval.subcmd = yyvsp[-2].subcmd;
		}
break;
case 19:
#line 189 "gram.y"
 {
			if (yyvsp[-2].namel != NULL)
				yyvsp[-3].subcmd->sc_args = expand(yyvsp[-2].namel, E_ALL);
			yyvsp[-3].subcmd->sc_name = yyvsp[-1].string;
			yyval.subcmd = yyvsp[-3].subcmd;
		}
break;
case 20:
#line 197 "gram.y"
 {
			yyval.intval = 0;
		}
break;
case 21:
#line 200 "gram.y"
 {
			yyval.intval |= yyvsp[0].intval;
		}
break;
case 22:
#line 205 "gram.y"
 {
			yyval.namel = NULL;
		}
break;
case 23:
#line 208 "gram.y"
 {
			yyval.namel = yyvsp[0].namel;
		}
break;
#line 899 "gram.c"
    }
    yyssp -= yym;
    yystate = *yyssp;
    yyvsp -= yym;
    yym = yylhs[yyn];
    if (yystate == 0 && yym == 0)
    {
#if YYDEBUG
        if (yydebug)
            printf("%sdebug: after reduction, shifting from state 0 to\
 state %d\n", YYPREFIX, YYFINAL);
#endif
        yystate = YYFINAL;
        *++yyssp = YYFINAL;
        *++yyvsp = yyval;
        if (yychar < 0)
        {
            if ((yychar = yylex()) < 0) yychar = 0;
#if YYDEBUG
            if (yydebug)
            {
                yys = 0;
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
                if (!yys) yys = "illegal-symbol";
                printf("%sdebug: state %d, reading %d (%s)\n",
                        YYPREFIX, YYFINAL, yychar, yys);
            }
#endif
        }
        if (yychar == 0) goto yyaccept;
        goto yyloop;
    }
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
        yystate = yytable[yyn];
    else
        yystate = yydgoto[yym];
#if YYDEBUG
    if (yydebug)
        printf("%sdebug: after reduction, shifting from state %d \
to state %d\n", YYPREFIX, *yyssp, yystate);
#endif
    if (yyssp >= yysslim && yygrowstack())
    {
        goto yyoverflow;
    }
    *++yyssp = yystate;
    *++yyvsp = yyval;
    goto yyloop;
yyoverflow:
    yyerror("yacc stack overflow");
yyabort:
    return (1);
yyaccept:
    return (0);
}


syntax highlighted by Code2HTML, v. 0.9.1