#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 "config.y"
/*
 * $Id: config.y,v 2.0.1.5 1996/06/26 18:39:38 alexis Exp alexis $
 *
 * UPS Daemon
 * The Wild Wind Communications, 1995, 1996
 *
 * See file LICENSE for the distribution terms of this software.
 */

#include "upsd.h"
#include "apc.h"

#include <ctype.h>

static FILE *config;
static char *input;
static char *pathname;
static char *token;
static int lineno;

struct keyword {
	char *keyword;
	int len;
	int token;
};

#line 30 "config.y"
typedef union {
	char	*string;
	double	number;
	struct	ups_reg *ups_reg;
	struct	ups_trig *ups_trig;
	struct	event *event;
	struct	action *action;
	struct	when *when;
} YYSTYPE;
#line 57 "config.c"
#define STRING 257
#define NUMBER 258
#define ERROR 259
#define AFTER 260
#define BLOCK 261
#define DELAY 262
#define DEVICE 263
#define DROP 264
#define EQUAL 265
#define EVERY 266
#define EXEC 267
#define FOR 268
#define LESS 269
#define LOG 270
#define MORE 271
#define NOT 272
#define ON 273
#define POLL 274
#define PROTO 275
#define QUEUE 276
#define RAISE 277
#define READ 278
#define SIZE 279
#define SLEEP 280
#define SPEED 281
#define THAN 282
#define TIMEOUT 283
#define TO 284
#define TUNE 285
#define UPS 286
#define WRITE 287
#define LEMERG 288
#define LALERT 289
#define LCRIT 290
#define LERR 291
#define LWARNING 292
#define LNOTICE 293
#define LINFO 294
#define LDEBUG 295
#define NOP 296
#define YYERRCODE 256
short yylhs[] = {                                        -1,
    0,   13,   14,   14,   15,   15,   15,   15,   15,   15,
   15,   15,    9,    9,    8,    8,    8,    8,    1,    1,
    1,    1,   16,   16,   16,   17,   17,   17,   18,   18,
   18,   19,   19,   19,   12,    2,    2,    4,    4,    3,
    3,    7,    7,    6,    6,    6,    6,    6,    6,    6,
    6,    6,    6,   11,   10,    5,    5,    5,    5,    5,
    5,    5,    5,    5,
};
short yylen[] = {                                         2,
    2,   10,    1,    2,    0,    2,    2,    6,    4,    6,
    6,    4,    1,    2,    6,    8,    8,    4,    1,    1,
    1,    1,    1,    2,    1,    1,    2,    1,    1,    2,
    2,    2,    3,    2,    3,    0,    2,    0,    2,    0,
    2,    1,    2,    2,    2,    2,    2,    3,    3,    3,
    2,    1,    1,    1,    1,    1,    1,    1,    1,    1,
    1,    1,    1,    0,
};
short yydefred[] = {                                      0,
    0,    0,    0,    0,    0,    0,    0,   13,    0,    0,
    0,   37,    0,    0,    0,    0,    0,   14,    0,    0,
    0,    0,    0,    0,    0,   25,   28,    0,    0,    0,
   19,   20,   21,   22,   39,    0,   35,    0,    0,    0,
    0,    0,    0,    0,   52,   42,    0,   53,    0,    0,
   30,   27,   24,    0,   31,   34,    0,    0,   41,   55,
   44,   45,   56,   57,   58,   59,   60,   61,   62,   63,
    0,   54,   47,   46,   51,    0,   18,   43,    0,    0,
   33,    0,    0,   50,   48,   49,    0,   15,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    3,
   17,   16,    6,    0,    0,    7,    0,    2,    4,    0,
    0,    0,   12,    0,    0,    0,    0,    0,    8,   11,
   10,
};
short yydgoto[] = {                                       2,
   30,    7,   37,   17,   71,   46,   47,   48,    9,   14,
   15,   10,    3,   99,  100,   31,   32,   33,   34,
};
short yysindex[] = {                                   -265,
 -227,    0, -249,   -2, -222, -215, -209,    0, -249,  -79,
 -212,    0,    0, -200,  -28, -192, -186,    0, -205,   40,
  -40, -199, -198, -196, -178,    0,    0,   27,   28, -208,
    0,    0,    0,    0,    0, -166,    0, -164, -163, -276,
 -162, -164, -161, -162,    0,    0, -123,    0, -177, -205,
    0,    0,    0, -188,    0,    0, -200, -200,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
 -158,    0,    0,    0,    0, -194,    0,    0, -157, -121,
    0,  -22,  -20,    0,    0,    0,  -19,    0, -205, -205,
 -220,  -90,  -88, -155,   60,   61, -151,   63, -118,    0,
    0,    0,    0, -170, -173,    0, -150,    0,    0, -146,
 -145,   69,    0,   70, -253, -143, -141, -140,    0,    0,
    0,
};
short yyrindex[] = {                                      0,
    0,    0, -101,    0,    0,    0, -120,    0,    1,    0,
    0,    0,  -33, -101,    0,    0,   -3,    0, -101,    0,
    0, -187, -184, -181,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0, -138,
    0,    0,    0,    0,    0,    0, -101,    0,    0, -101,
    0,    0,    0, -179,    0,    0, -101, -101,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0, -101,
    0,    0,    0,    0,    0,    0,    0,    0, -101, -101,
    2, -101, -101,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,  -85,    0,    0,    0,    0,    0,    0,
    0,
};
short yygindex[] = {                                      0,
    0,    0,    0,    0,    0,  -41,  -42,   22,    0,    3,
  -21,   -4,    0,    0,   23,    0,    0,    0,    0,
};
#define YYTABLESIZE 269
short yytable[] = {                                      54,
    1,   77,   38,   88,   29,   78,  108,   80,  117,   21,
    5,   63,   64,   65,   66,   67,   68,   69,   70,   73,
    1,   36,   76,    6,    8,  118,   54,   54,   54,    4,
   18,   27,   28,   26,  101,   12,  102,   11,   78,    9,
   61,   13,   94,   19,   74,   20,   92,   93,   57,   58,
   78,   78,   82,   83,    5,   95,   16,   96,   38,    5,
   97,   39,   85,   86,   40,   35,   98,    6,   41,   29,
   29,   42,   26,   26,   43,   23,   23,   32,   32,   44,
   49,   36,   50,   52,   51,   53,   54,   55,   56,   55,
   45,   59,   60,   62,   72,   81,   75,   79,   84,   87,
   89,  103,   90,   91,  104,  105,  106,  107,  110,  111,
  112,  113,  114,  115,  119,  116,  120,  121,   64,   40,
    0,  109,    0,   36,    0,    0,    5,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    5,    0,    5,    0,
   38,    0,   38,   39,   94,   39,   40,   38,   40,    6,
   41,    6,   41,   42,    0,   42,   43,   95,   43,   96,
    0,   44,   97,   44,   36,    0,   36,    0,   98,    5,
    0,    5,   45,   38,   45,   38,   39,    9,   39,   40,
    0,   40,    6,   41,    6,   41,   42,    0,   42,   43,
    9,   43,    9,    0,   44,    9,   44,    0,    0,    0,
    0,    9,    0,    0,    0,   45,    0,   45,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,   55,    0,    0,    0,
    0,   54,   55,    0,   55,   54,   22,   54,   54,    0,
   23,    0,   24,   25,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,   36,    0,   36,
};
short yycheck[] = {                                      33,
    0,  125,  123,  125,   33,   47,  125,   50,  262,   14,
  260,  288,  289,  290,  291,  292,  293,  294,  295,   41,
  286,  123,   44,  273,    3,  279,   60,   61,   62,  257,
    9,   60,   61,   62,  125,  258,  125,   40,   80,  125,
   38,  257,  263,  123,   42,  258,   89,   90,  257,  258,
   92,   93,   57,   58,  260,  276,  266,  278,  264,  260,
  281,  267,  257,  258,  270,  258,  287,  273,  274,  257,
  258,  277,  257,  258,  280,  257,  258,  257,  258,  285,
   41,  268,  123,  282,  284,  282,  265,   61,   61,  123,
  296,  258,  257,  257,  257,  284,  258,  275,  257,  257,
  123,  257,  123,  123,   45,   45,  258,   45,  279,  283,
  261,  258,  258,   45,  258,   46,  258,  258,  257,  123,
   -1,   99,   -1,  123,   -1,   -1,  125,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,  260,   -1,  260,   -1,
  264,   -1,  264,  267,  263,  267,  270,  268,  270,  273,
  274,  273,  274,  277,   -1,  277,  280,  276,  280,  278,
   -1,  285,  281,  285,  266,   -1,  268,   -1,  287,  260,
   -1,  260,  296,  264,  296,  264,  267,  263,  267,  270,
   -1,  270,  273,  274,  273,  274,  277,   -1,  277,  280,
  276,  280,  278,   -1,  285,  281,  285,   -1,   -1,   -1,
   -1,  287,   -1,   -1,   -1,  296,   -1,  296,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,  260,   -1,   -1,   -1,
   -1,  265,  266,   -1,  268,  269,  265,  271,  272,   -1,
  269,   -1,  271,  272,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,  266,   -1,  268,
};
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
#define YYMAXTOKEN 296
#if YYDEBUG
char *yyname[] = {
"end-of-file",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,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,"STRING","NUMBER","ERROR","AFTER","BLOCK","DELAY","DEVICE","DROP",
"EQUAL","EVERY","EXEC","FOR","LESS","LOG","MORE","NOT","ON","POLL","PROTO",
"QUEUE","RAISE","READ","SIZE","SLEEP","SPEED","THAN","TIMEOUT","TO","TUNE",
"UPS","WRITE","LEMERG","LALERT","LCRIT","LERR","LWARNING","LNOTICE","LINFO",
"LDEBUG","NOP",
};
char *yyrule[] = {
"$accept : config",
"config : ups events",
"ups : UPS STRING '(' NUMBER ')' PROTO STRING '{' port_settings '}'",
"port_settings : port_setting",
"port_settings : port_settings port_setting",
"port_setting :",
"port_setting : DEVICE STRING",
"port_setting : SPEED NUMBER",
"port_setting : READ '-' TIMEOUT NUMBER '.' NUMBER",
"port_setting : READ '-' TIMEOUT NUMBER",
"port_setting : WRITE '-' BLOCK '-' SIZE NUMBER",
"port_setting : WRITE '-' BLOCK '-' DELAY NUMBER",
"port_setting : QUEUE '-' SIZE NUMBER",
"events : event",
"events : events event",
"event : ON trigger when '{' actions '}'",
"event : ON register condition NUMBER when '{' actions '}'",
"event : ON register condition STRING when '{' actions '}'",
"event : when '{' actions '}'",
"condition : morethan",
"condition : lessthan",
"condition : equalto",
"condition : nequalto",
"morethan : MORE",
"morethan : MORE THAN",
"morethan : '>'",
"lessthan : LESS",
"lessthan : LESS THAN",
"lessthan : '<'",
"equalto : EQUAL",
"equalto : EQUAL TO",
"equalto : '=' '='",
"nequalto : NOT EQUAL",
"nequalto : NOT EQUAL TO",
"nequalto : '!' '='",
"when : after every for",
"after :",
"after : AFTER NUMBER",
"every :",
"every : EVERY NUMBER",
"for :",
"for : FOR NUMBER",
"actions : action",
"actions : actions action",
"action : DROP trigger",
"action : EXEC STRING",
"action : RAISE trigger",
"action : POLL register",
"action : TUNE register STRING",
"action : TUNE register NUMBER",
"action : LOG priority STRING",
"action : SLEEP NUMBER",
"action : NOP",
"action : event",
"register : STRING",
"trigger : STRING",
"priority : LEMERG",
"priority : LALERT",
"priority : LCRIT",
"priority : LERR",
"priority : LWARNING",
"priority : LNOTICE",
"priority : LINFO",
"priority : LDEBUG",
"priority :",
};
#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 374 "config.y"

static struct keyword keywords[] = {
	{"after", 5, AFTER},
	{"alert", 5, LALERT},
	{"block", 5, BLOCK},
	{"crit", 4, LCRIT},
	{"debug", 5, LDEBUG},
	{"delay", 5, DELAY},
	{"device", 6, DEVICE},
	{"drop", 4, DROP},
	{"emerg", 5, LEMERG},
	{"equal", 5, EQUAL},
	{"err", 3, LERR},
	{"every", 5, EVERY},
	{"exec", 4, EXEC},
	{"for", 3, FOR},
	{"info", 4, LINFO},
	{"less", 4, LESS},
	{"log", 3, LOG},
	{"more", 4, MORE},
	{"nop", 3, NOP},
	{"notice", 6, LNOTICE},
	{"not", 3, NOT},
	{"on", 2, ON},
	{"poll", 4, POLL},
	{"proto", 5, PROTO},
	{"queue", 5, QUEUE},
	{"raise", 5, RAISE},
	{"read", 4, READ},
	{"size", 4, SIZE},
	{"sleep", 5, SLEEP},
	{"speed", 5, SPEED},
	{"than", 4, THAN},
	{"timeout", 7, TIMEOUT},
	{"to", 2, TO},
	{"tune", 4, TUNE},
	{"ups", 3, UPS},
	{"warning", 7, LWARNING},
	{"write", 5, WRITE},
	{NULL, 0, 0}
};

/*
 * This is the actual lexical parser.
 */
int
yylex(void)
{
	char *t;
	struct keyword *k;

	for(;;) {
		if((token == NULL) || (*token == '\0')) {
			lineno++;
			if((token = fgets(input, MAXINPUTLEN, config)) == NULL) {
				return 0;
			}
			if((t = index(token, '\n')) != NULL) {
				*t = '\0';	/* Chop the line. */
			}
		}
		while(isspace(*token)) {	/* Skip spaces. */
			token++;
		}

		if(*token == '#' || *token == '\n' || *token == '\0') {
			token = NULL;
			continue;		/* Keep reading the file. */
		}

		if(*token == '"') {		/* Is it a string? */
			token++;
			if((t = index(token, '"')) == NULL) {
				/* An unterminated string is treated as */
				/* a single double quote character. */
				return *(token-1);
			}
			*t++ = '\0';
			if((yylval.string = xstrdup(token)) == NULL) {
				return ERROR;
			}
			token = t;
			return STRING;
		}

		if(isdigit(*token)) {		/* Is it a number? */
			yylval.number = strtod(token, &t);
			token = t;
			return NUMBER;
		}

		for(k = keywords; k->keyword; k++) {
			if(!strncasecmp(token, k->keyword, k->len)) {
				token += k->len;
				return k->token;
			}
		}

		/* Let's return a character. */
		t = token++;
		return *t;
	}
}

/*
 * Error reporting routine.
 */
void
yyerror(string)
	char *string;
{
	syslog(LOG_ERR, "parse error: %s in file %s, line %d",
	    string, pathname, lineno);
}

/*
 * Main function.
 */
int
configure(config_pathname)
	char *config_pathname;
{
	extern int yyparse();

	lineno = 0;
	pathname = config_pathname;
	token = NULL;

	if((input = xalloc(MAXINPUTLEN)) == NULL) {
		return -1;
	}

	if((config = fopen(pathname, "r")) == NULL) {
		syslog(LOG_ERR, "configure: cannot open %s: %m", pathname);
		return -1;
	};

	if(yyparse()) {
		syslog(LOG_ERR, "configure: cannot parse configuration file %s",
		    pathname);
		return -1;
	};

	fclose(config);
	xfree(input);

	return 0;
}

/*
 * Allocates space for a new event and fills it according to the
 * arguments. Returns the pointer onto this newly allocated area
 * or NULL if failed.
 */
struct event *
newevent(trigger, value, condition, when, actions)
	struct ups_trig *trigger;
	struct ups_val *value;
	int condition;
	struct when *when;
	struct action *actions;
{
	register struct event *ep;
	if((ep = (struct event*) xalloc(sizeof(struct event))) == NULL) {
		return NULL;
	}
	bzero(ep, sizeof(struct event));
	if(trigger != NULL) {
		ep->trigger = trigger->id;
	} else {
		ep->trigger = 0;
	}
	if(value == NULL && condition != 0) {
		return NULL;		/* Already reported in newval(). */
	}
	ep->v = value;
	ep->condition = condition;
	ep->when = when;
	ep->acts = actions;

	return ep;
}

/*
 * Allocates space for a new action and fills it according to the
 * arguments. Returns the pointer onto this newly allocated area
 * or NULL if failed.
 */
struct action *
newaction(type, action)
	int type;
	void *action;
{
	register struct action *ap;
	if((ap = (struct action*)xalloc(sizeof(struct action))) == NULL) {
		return NULL;
	}
	bzero(ap, sizeof(struct action));
	ap->type = type;
	ap->action = action;

	return ap;
}

/*
 * Allocates space for a new value and fills it according to the
 * arguments. Returns the pointer onto the new value or NULL if
 * failed.
 */
struct ups_val *
newval(reg, value, type)
	struct ups_reg *reg;
	void *value;
	int type;
{
	register struct ups_val *vp;

	if(type != reg->type) {
		yyerror("incorrect value type for this register");
		return NULL;
	}

	if((vp = xalloc(sizeof(struct ups_val))) == NULL) {
		return NULL;
	}

	bzero(vp, sizeof(struct ups_val));
	vp->id = reg->id;
	if(value == NULL) {
		return vp;
	}
	switch((reg->type & T_TYPE)) {
	case T_BINARY:
		bcopy(value, (void *)&vp->val, sizeof(void *));
		break;
	case T_NUMBER:
		bcopy(value, (void *)&vp->val, sizeof(double));
		break;
	}
	return vp;
}

/*
 * Checks if the value is legal for this UPS. Zero is returned
 * if legal, non-zero otherwise. -1 is returned upon error.
 */
int
illval(val, reg)
	struct ups_val *val;
	struct ups_reg *reg;
{
	register struct ups_val *v;

	if(reg->id != val->id) {
		syslog(LOG_ERR, "illval: illegal register supplied for the value");
		return -1;
	}
	for(v = upsp->model->values; v->id != 0; v++) {
		if(v->id == reg->id) {
			switch(reg->type & T_TYPE) {
			case T_NUMBER:
				if(val->val.number == v->val.number) {
					return 0;
				}
				break;
			case T_BINARY:
				if(v->val.binary == NULL) {
					return 0;
				} else if(!bcmp(val->val.binary, v->val.binary, reg->size - reg->prec)) {
					return 0;
				}
				break;
			default:
				syslog(LOG_ERR, "illval: incorrect type of legal value");
				return -1;
			}
		}
	}
	return 1;
}
#line 622 "config.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 1:
#line 65 "config.y"
{
			upsp->eventv = yyvsp[0].event;
		}
break;
case 2:
#line 73 "config.y"
{
			register struct ups_model **mp;
			register struct ups_reg *rp;
			register struct ups_val *vp;

			for(mp = upslist; *mp != NULL; mp++) {
				if(!strcmp((*mp)->type, yyvsp[-8].string) && ((*mp)->voltage == (int)yyvsp[-6].number)
				    && !strcmp((*mp)->protocol, yyvsp[-3].string)) {
					break;
				}
			}
			if(*mp == NULL) {
				yyerror("uknown ups specification");
				YYERROR;
			}
			upsp->model = *mp;
			xfree(yyvsp[-8].string);
			xfree(yyvsp[-3].string);

			if((zero_trig = TRIGGERID(0)) == NULL) {
				yyerror("cannot find the terminating trigger");
				YYERROR;
			}

			/* Fill up upsp->state. */
			if((upsp->state = xalloc((upsp->model->nregs) * sizeof(struct ups_val))) == NULL) {
				YYERROR;
			}
			bzero(upsp->state, sizeof(struct ups_val) * upsp->model->nregs);
			for(rp = upsp->model->registers, vp = upsp->state; rp->id; rp++, vp++) {
				vp->id = rp->id;
				if((rp->type & T_TYPE) == T_BINARY) {
					if((vp->val.binary = xalloc(rp->size)) == NULL) {
						YYERROR;
					}
				}
			}
		}
break;
case 6:
#line 121 "config.y"
{
			if((upsp->port.device = yyvsp[0].string) == NULL) {
				YYERROR;
			}
		}
break;
case 7:
#line 126 "config.y"
{
			upsp->port.ntty.c_ispeed = upsp->port.ntty.c_ospeed
				= (speed_t) yyvsp[0].number;
		}
break;
case 8:
#line 130 "config.y"
{
			upsp->port.timeout.tv_sec = (long) yyvsp[-2].number;
			upsp->port.timeout.tv_usec = (long) yyvsp[0].number;
		}
break;
case 9:
#line 134 "config.y"
{
			upsp->port.timeout.tv_sec = (long) yyvsp[0].number;
			upsp->port.timeout.tv_usec = 0;
		}
break;
case 10:
#line 138 "config.y"
{
			upsp->port.writeblksz = (int) yyvsp[0].number;
		}
break;
case 11:
#line 141 "config.y"
{
			upsp->port.writedelay.tv_sec = 0;
			upsp->port.writedelay.tv_usec = (long) yyvsp[0].number;
		}
break;
case 12:
#line 145 "config.y"
{
			upsp->port.queue.size = (int) yyvsp[0].number;
		}
break;
case 13:
#line 152 "config.y"
{
			yyval.event = yyvsp[0].event;
			yyvsp[0].event->next = NULL;
		}
break;
case 14:
#line 156 "config.y"
{
			register struct event *ep;
			for(ep = yyvsp[-1].event; ep->next != NULL; ep = ep->next);
			ep->next = yyvsp[0].event;
			yyvsp[0].event->next = NULL;
			yyval.event = yyvsp[-1].event;
		}
break;
case 15:
#line 166 "config.y"
{
			if((yyval.event = newevent(yyvsp[-4].ups_trig, NULL, 0, yyvsp[-3].when, yyvsp[-1].action)) == NULL) {
				YYERROR;
			}
		}
break;
case 16:
#line 171 "config.y"
{
			if((yyval.event = newevent(NULL, newval(yyvsp[-6].ups_reg, &(yyvsp[-4].number), T_NUMBER),
			    (int) yyvsp[-5].number, yyvsp[-3].when, yyvsp[-1].action)) == NULL) {
				YYERROR;
			}
		}
break;
case 17:
#line 177 "config.y"
{
			if((yyval.event = newevent(NULL, newval(yyvsp[-6].ups_reg, &(yyvsp[-4].string), T_BINARY),
			    ((int) yyvsp[-5].number | C_STRING), yyvsp[-3].when, yyvsp[-1].action)) == NULL) {
				YYERROR;
			}
		}
break;
case 18:
#line 183 "config.y"
{
			if((yyval.event = newevent(NULL, NULL, 0, yyvsp[-3].when, yyvsp[-1].action)) == NULL) {
				YYERROR;
			}
		}
break;
case 19:
#line 191 "config.y"
{ yyval.number = C_MORE; }
break;
case 20:
#line 192 "config.y"
{ yyval.number = C_LESS; }
break;
case 21:
#line 193 "config.y"
{ yyval.number = C_EQUAL; }
break;
case 22:
#line 194 "config.y"
{ yyval.number = C_NEQUAL; }
break;
case 35:
#line 222 "config.y"
{
			if((yyval.when = xalloc(sizeof(struct when))) == NULL) {
				YYERROR;
			}
			yyval.when->act_after = (time_t) yyvsp[-2].number;
			yyval.when->act_every = (time_t) yyvsp[-1].number;
			yyval.when->act_for = (time_t) yyvsp[0].number;
		}
break;
case 36:
#line 233 "config.y"
{ yyval.number = 0; }
break;
case 37:
#line 234 "config.y"
{ yyval.number = yyvsp[0].number; }
break;
case 38:
#line 238 "config.y"
{ yyval.number = 0; }
break;
case 39:
#line 239 "config.y"
{ yyval.number = yyvsp[0].number; }
break;
case 40:
#line 243 "config.y"
{ yyval.number = 0; }
break;
case 41:
#line 244 "config.y"
{ yyval.number = yyvsp[0].number; }
break;
case 42:
#line 249 "config.y"
{
			yyval.action = yyvsp[0].action;
			yyvsp[0].action->next = NULL;
		}
break;
case 43:
#line 253 "config.y"
{
			register struct action *ap;
			for(ap = yyvsp[-1].action; ap->next != NULL; ap = ap->next);
			ap->next = yyvsp[0].action;
			yyvsp[0].action->next = NULL;
			yyval.action = yyvsp[-1].action;
		}
break;
case 44:
#line 263 "config.y"
{
			if((yyval.action = newaction(A_DROP, yyvsp[0].ups_trig)) == NULL) {
				YYERROR;
			}
		}
break;
case 45:
#line 268 "config.y"
{
			if((yyval.action = newaction(A_EXEC, yyvsp[0].string)) == NULL) {
				YYERROR;
			}
		}
break;
case 46:
#line 273 "config.y"
{
			if((yyval.action = newaction(A_RAISE, yyvsp[0].ups_trig)) == NULL) {
				YYERROR;
			}
		}
break;
case 47:
#line 278 "config.y"
{
			if((yyval.action = newaction(A_POLL, VALUEID(yyvsp[0].ups_reg->id))) == NULL) {
				YYERROR;
			}
		}
break;
case 48:
#line 283 "config.y"
{
			register struct ups_val *val;
			if((val = newval(yyvsp[-1].ups_reg, &(yyvsp[0].string), T_BINARY)) == NULL) {
				YYERROR;
			}
			if(illval(val, yyvsp[-1].ups_reg)) {
				yyerror("illegal value for this ups model");
				YYERROR;
			}
			if((yyval.action = newaction(A_TUNE, val)) == NULL) {
				YYERROR;
			}
		}
break;
case 49:
#line 296 "config.y"
{
			register struct ups_val *val;
			if((val = newval(yyvsp[-1].ups_reg, &(yyvsp[0].number), T_NUMBER)) == NULL) {
				YYERROR;
			}
			if(illval(val, yyvsp[-1].ups_reg)) {
				yyerror("illegal value for this ups model");
				YYERROR;
			}
			if((yyval.action = newaction(A_TUNE, val)) == NULL) {
				YYERROR;
			}
		}
break;
case 50:
#line 309 "config.y"
{
			register struct message *m;
			if((m = xalloc(sizeof(struct message))) == NULL) {
				YYERROR;
			}
			m->priority = (int) yyvsp[-1].number;
			m->message = yyvsp[0].string;
			if((yyval.action = newaction(A_LOG, m)) == NULL) {
				YYERROR;
			}
		}
break;
case 51:
#line 320 "config.y"
{
			register struct timeval *t;
			if((t = xalloc(sizeof(struct timeval))) == NULL) {
				YYERROR;
			}
			t->tv_sec = (int) yyvsp[0].number;
			t->tv_usec = 0;
			if((yyval.action = newaction(A_SLEEP, t)) == NULL) {
				YYERROR;
			}
		}
break;
case 52:
#line 331 "config.y"
{
			if((yyval.action= newaction(A_NONE, NULL)) == NULL) {
				YYERROR;
			}
		}
break;
case 53:
#line 336 "config.y"
{
			if((yyval.action = newaction(A_EVENT, yyvsp[0].event)) == NULL) {
				YYERROR;
			}
		}
break;
case 54:
#line 344 "config.y"
{
			if((yyval.ups_reg = REGISTERNAME(yyvsp[0].string)) == NULL) {
				yyerror("incorrect register for this ups");
				YYERROR;
			}
		}
break;
case 55:
#line 353 "config.y"
{
			if((yyval.ups_trig = TRIGGERNAME(yyvsp[0].string)) == NULL) {
				yyerror("incorrect trigger for this ups");
				YYERROR;
			}
		}
break;
case 56:
#line 362 "config.y"
{ yyval.number = LOG_EMERG; }
break;
case 57:
#line 363 "config.y"
{ yyval.number = LOG_ALERT; }
break;
case 58:
#line 364 "config.y"
{ yyval.number = LOG_CRIT; }
break;
case 59:
#line 365 "config.y"
{ yyval.number = LOG_ERR; }
break;
case 60:
#line 366 "config.y"
{ yyval.number = LOG_WARNING; }
break;
case 61:
#line 367 "config.y"
{ yyval.number = LOG_NOTICE; }
break;
case 62:
#line 368 "config.y"
{ yyval.number = LOG_INFO; }
break;
case 63:
#line 369 "config.y"
{ yyval.number = LOG_DEBUG; }
break;
case 64:
#line 370 "config.y"
{ yyval.number = DEFAULT_LOG_PRIORITY; }
break;
#line 1164 "config.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