GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/dvmrpd/parse.c Lines: 0 203 0.0 %
Date: 2017-11-07 Branches: 0 174 0.0 %

Line Branch Exec Source
1
#include <stdlib.h>
2
#include <string.h>
3
#define YYBYACC 1
4
#define YYMAJOR 1
5
#define YYMINOR 9
6
#define YYLEX yylex()
7
#define YYEMPTY -1
8
#define yyclearin (yychar=(YYEMPTY))
9
#define yyerrok (yyerrflag=0)
10
#define YYRECOVERING() (yyerrflag!=0)
11
#define YYPREFIX "yy"
12
#line 25 "parse.y"
13
#include <sys/types.h>
14
#include <sys/time.h>
15
#include <sys/stat.h>
16
#include <sys/socket.h>
17
#include <netinet/in.h>
18
#include <arpa/inet.h>
19
#include <net/if.h>
20
#include <ctype.h>
21
#include <err.h>
22
#include <limits.h>
23
#include <unistd.h>
24
#include <errno.h>
25
#include <stdarg.h>
26
#include <stdio.h>
27
#include <string.h>
28
#include <syslog.h>
29
30
#include "igmp.h"
31
#include "dvmrp.h"
32
#include "dvmrpd.h"
33
#include "dvmrpe.h"
34
#include "log.h"
35
36
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
37
static struct file {
38
	TAILQ_ENTRY(file)	 entry;
39
	FILE			*stream;
40
	char			*name;
41
	int			 lineno;
42
	int			 errors;
43
} *file, *topfile;
44
struct file	*pushfile(const char *, int);
45
int		 popfile(void);
46
int		 check_file_secrecy(int, const char *);
47
int		 yyparse(void);
48
int		 yylex(void);
49
int		 yyerror(const char *, ...)
50
    __attribute__((__format__ (printf, 1, 2)))
51
    __attribute__((__nonnull__ (1)));
52
int		 kw_cmp(const void *, const void *);
53
int		 lookup(char *);
54
int		 lgetc(int);
55
int		 lungetc(int);
56
int		 findeol(void);
57
58
TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
59
struct sym {
60
	TAILQ_ENTRY(sym)	 entry;
61
	int			 used;
62
	int			 persist;
63
	char			*nam;
64
	char			*val;
65
};
66
int		 symset(const char *, const char *, int);
67
char		*symget(const char *);
68
69
static struct dvmrpd_conf	*conf;
70
char				*start_state;
71
struct iface			*iface = NULL;
72
73
static struct {
74
	u_int32_t	 probe_interval;
75
	u_int32_t	 query_interval;
76
	u_int32_t	 query_resp_interval;
77
	u_int32_t	 startup_query_interval;
78
	u_int32_t	 startup_query_cnt;
79
	u_int32_t	 last_member_query_interval;
80
	u_int32_t	 last_member_query_cnt;
81
	u_int32_t	 dead_interval;
82
	u_int16_t	 metric;
83
	u_int8_t	 robustness;
84
	u_int8_t	 igmp_version;
85
} *defs, *grdefs, globaldefs, groupdefs, ifacedefs;
86
87
void		 clear_config(struct dvmrpd_conf *xconf);
88
struct iface	*conf_get_if(struct kif *);
89
struct iface	*new_group(void);
90
91
typedef struct {
92
	union {
93
		int64_t		 number;
94
		char		*string;
95
	} v;
96
	int lineno;
97
} YYSTYPE;
98
99
#line 100 "parse.c"
100
#define INTERFACE 257
101
#define FIBUPDATE 258
102
#define GROUP 259
103
#define METRIC 260
104
#define PASSIVE 261
105
#define ROBUSTNESS 262
106
#define QUERYINTERVAL 263
107
#define QUERYRESPINTERVAL 264
108
#define STARTUPQUERYINTERVAL 265
109
#define STARTUPQUERYCNT 266
110
#define LASTMEMBERQUERYINTERVAL 267
111
#define LASTMEMBERQUERYCNT 268
112
#define IGMPVERSION 269
113
#define ERROR 270
114
#define STRING 271
115
#define NUMBER 272
116
#define YYERRCODE 256
117
const short yylhs[] =
118
	{                                        -1,
119
    0,    0,    0,    0,    0,    0,    0,    2,    2,    1,
120
    4,    3,    3,    7,    7,    7,    7,    7,    7,    7,
121
    7,    7,    8,    8,    9,   11,    5,   10,   10,   10,
122
   12,   12,   13,   13,   15,    6,   14,   14,   16,   16,
123
   16,
124
};
125
const short yylen[] =
126
	{                                         2,
127
    0,    2,    3,    3,    3,    3,    3,    2,    1,    1,
128
    3,    2,    1,    2,    2,    2,    2,    2,    2,    2,
129
    2,    2,    2,    0,    2,    0,    4,    4,    3,    0,
130
    2,    1,    2,    2,    0,    7,    2,    1,    2,    2,
131
    2,
132
};
133
const short yydefred[] =
134
	{                                      1,
135
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
136
    0,    0,    0,    0,    0,    2,    0,    0,    0,    0,
137
   13,    7,   26,   10,   12,    0,    0,   16,   19,   17,
138
   18,   21,   20,   15,   14,   22,    0,    3,    4,    5,
139
    6,    0,   23,    0,    9,    0,    0,   27,   35,    8,
140
    0,    0,    0,   29,    0,    0,   32,    0,    0,    0,
141
    0,   38,    0,   33,   34,   28,   31,   41,   39,   40,
142
   36,   37,   25,
143
};
144
const short yydgoto[] =
145
	{                                       1,
146
   25,   46,   17,   18,   59,   20,   55,   27,   64,   48,
147
   42,   56,   57,   61,   52,   62,
148
};
149
const short yysindex[] =
150
	{                                      0,
151
  -10,   -4, -261, -260,    2, -259, -258, -257, -256, -254,
152
 -253, -252, -251, -250,  -37,    0,   15,   17,   18,   19,
153
    0,    0,    0,    0,    0,    2,  -93,    0,    0,    0,
154
    0,    0,    0,    0,    0,    0, -239,    0,    0,    0,
155
    0,  -90,    0,    2,    0, -237,    2,    0,    0,    0,
156
  -84, -197,   25,    0,   25,  -74,    0,   25,   25,   25,
157
  -94,    0,    2,    0,    0,    0,    0,    0,    0,    0,
158
    0,    0,    0,};
159
const short yyrindex[] =
160
	{                                      0,
161
    0,    0,    0,    0,  -87,    0,    0,    0,    0,    0,
162
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
163
    0,    0,    0,    0,    0, -122,    0,    0,    0,    0,
164
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
165
    0,   27,    0, -183,    0,   28,  -64,    0,    0,    0,
166
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
167
    0,    0, -108,    0,    0,    0,    0,    0,    0,    0,
168
    0,    0,    0,};
169
const short yygindex[] =
170
	{                                      0,
171
    0,    0,    0,    0,   38,    0,    1,  -21,  -51,    0,
172
    0,    0,  -16,    0,    0,  -18,
173
};
174
#define YYTABLESIZE 261
175
const short yytable[] =
176
	{                                      16,
177
   24,   21,   24,   65,   43,   22,   68,   69,   70,   23,
178
   24,   26,   28,   29,   30,   31,   24,   32,   33,   34,
179
   35,   36,   49,   37,   38,   51,   39,   40,   41,   44,
180
   71,   45,   47,   50,   63,   24,   30,   11,   19,   67,
181
   54,   73,   72,    0,    0,    0,    0,    0,    0,    0,
182
   66,    0,   60,    0,    0,    0,    0,    0,   58,    3,
183
   24,   60,    6,    0,    7,    8,    9,   10,   11,   12,
184
   13,   14,   24,   24,    0,    0,   24,    0,   24,   24,
185
   24,   24,   24,   24,   24,   24,    0,    0,    0,    0,
186
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
187
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
188
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
189
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
190
    0,    0,    0,   24,   24,    0,    0,   24,   24,   24,
191
   24,   24,   24,   24,   24,   24,   24,   24,   24,    0,
192
    0,   24,   24,   24,   24,   24,   24,   24,   24,   24,
193
   24,   58,    3,    0,    0,    6,    0,    7,    8,    9,
194
   10,   11,   12,   13,   14,    6,   53,    7,    8,    9,
195
   10,   11,   12,   13,   14,    6,   53,    7,    8,    9,
196
   10,   11,   12,   13,   14,   24,   24,   24,   24,   24,
197
   24,   24,   24,   24,   24,    0,    0,    0,    0,    0,
198
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
199
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
200
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
201
    0,    0,    0,    0,    0,    2,    3,    4,    5,    6,
202
    0,    7,    8,    9,   10,   11,   12,   13,   14,    0,
203
   15,
204
};
205
const short yycheck[] =
206
	{                                      10,
207
  123,    1,  125,   55,   26,   10,   58,   59,   60,  271,
208
  271,   10,  272,  272,  272,  272,  125,  272,  272,  272,
209
  272,  272,   44,   61,   10,   47,   10,   10,   10,  123,
210
  125,  271,  123,  271,   10,  123,   10,   10,    1,   56,
211
  125,   63,   61,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
212
  125,   -1,   52,   -1,   -1,   -1,   -1,   -1,  256,  257,
213
  125,   61,  260,   -1,  262,  263,  264,  265,  266,  267,
214
  268,  269,  256,  257,   -1,   -1,  260,   -1,  262,  263,
215
  264,  265,  266,  267,  268,  269,   -1,   -1,   -1,   -1,
216
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
217
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
218
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
219
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
220
   -1,   -1,   -1,  256,  257,   -1,   -1,  260,  261,  262,
221
  263,  264,  265,  266,  267,  268,  269,  256,  257,   -1,
222
   -1,  260,  261,  262,  263,  264,  265,  266,  267,  268,
223
  269,  256,  257,   -1,   -1,  260,   -1,  262,  263,  264,
224
  265,  266,  267,  268,  269,  260,  261,  262,  263,  264,
225
  265,  266,  267,  268,  269,  260,  261,  262,  263,  264,
226
  265,  266,  267,  268,  269,  260,  261,  262,  263,  264,
227
  265,  266,  267,  268,  269,   -1,   -1,   -1,   -1,   -1,
228
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
229
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
230
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
231
   -1,   -1,   -1,   -1,   -1,  256,  257,  258,  259,  260,
232
   -1,  262,  263,  264,  265,  266,  267,  268,  269,   -1,
233
  271,
234
};
235
#define YYFINAL 1
236
#ifndef YYDEBUG
237
#define YYDEBUG 0
238
#endif
239
#define YYMAXTOKEN 272
240
#if YYDEBUG
241
const char * const yyname[] =
242
	{
243
"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
244
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'='",0,0,0,0,0,0,0,
245
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
246
0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
247
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
248
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
249
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTERFACE",
250
"FIBUPDATE","GROUP","METRIC","PASSIVE","ROBUSTNESS","QUERYINTERVAL",
251
"QUERYRESPINTERVAL","STARTUPQUERYINTERVAL","STARTUPQUERYCNT",
252
"LASTMEMBERQUERYINTERVAL","LASTMEMBERQUERYCNT","IGMPVERSION","ERROR","STRING",
253
"NUMBER",
254
};
255
const char * const yyrule[] =
256
	{"$accept : grammar",
257
"grammar :",
258
"grammar : grammar '\\n'",
259
"grammar : grammar conf_main '\\n'",
260
"grammar : grammar varset '\\n'",
261
"grammar : grammar interface '\\n'",
262
"grammar : grammar group '\\n'",
263
"grammar : grammar error '\\n'",
264
"string : string STRING",
265
"string : STRING",
266
"yesno : STRING",
267
"varset : STRING '=' string",
268
"conf_main : FIBUPDATE yesno",
269
"conf_main : defaults",
270
"defaults : LASTMEMBERQUERYCNT NUMBER",
271
"defaults : LASTMEMBERQUERYINTERVAL NUMBER",
272
"defaults : METRIC NUMBER",
273
"defaults : QUERYINTERVAL NUMBER",
274
"defaults : QUERYRESPINTERVAL NUMBER",
275
"defaults : ROBUSTNESS NUMBER",
276
"defaults : STARTUPQUERYCNT NUMBER",
277
"defaults : STARTUPQUERYINTERVAL NUMBER",
278
"defaults : IGMPVERSION NUMBER",
279
"optnl : '\\n' optnl",
280
"optnl :",
281
"nl : '\\n' optnl",
282
"$$1 :",
283
"interface : INTERFACE STRING $$1 interface_block",
284
"interface_block : '{' optnl interfaceopts_l '}'",
285
"interface_block : '{' optnl '}'",
286
"interface_block :",
287
"interfaceopts_l : interfaceopts_l interfaceoptsl",
288
"interfaceopts_l : interfaceoptsl",
289
"interfaceoptsl : PASSIVE nl",
290
"interfaceoptsl : defaults nl",
291
"$$2 :",
292
"group : GROUP optnl '{' optnl $$2 groupopts_l '}'",
293
"groupopts_l : groupopts_l groupoptsl",
294
"groupopts_l : groupoptsl",
295
"groupoptsl : interface nl",
296
"groupoptsl : defaults nl",
297
"groupoptsl : error nl",
298
};
299
#endif
300
#ifdef YYSTACKSIZE
301
#undef YYMAXDEPTH
302
#define YYMAXDEPTH YYSTACKSIZE
303
#else
304
#ifdef YYMAXDEPTH
305
#define YYSTACKSIZE YYMAXDEPTH
306
#else
307
#define YYSTACKSIZE 10000
308
#define YYMAXDEPTH 10000
309
#endif
310
#endif
311
#define YYINITSTACKSIZE 200
312
/* LINTUSED */
313
int yydebug;
314
int yynerrs;
315
int yyerrflag;
316
int yychar;
317
short *yyssp;
318
YYSTYPE *yyvsp;
319
YYSTYPE yyval;
320
YYSTYPE yylval;
321
short *yyss;
322
short *yysslim;
323
YYSTYPE *yyvs;
324
unsigned int yystacksize;
325
int yyparse(void);
326
#line 362 "parse.y"
327
328
struct keywords {
329
	const char	*k_name;
330
	int		 k_val;
331
};
332
333
int
334
yyerror(const char *fmt, ...)
335
{
336
	va_list		 ap;
337
	char		*msg;
338
339
	file->errors++;
340
	va_start(ap, fmt);
341
	if (vasprintf(&msg, fmt, ap) == -1)
342
		fatalx("yyerror vasprintf");
343
	va_end(ap);
344
	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
345
	free(msg);
346
	return (0);
347
}
348
349
int
350
kw_cmp(const void *k, const void *e)
351
{
352
	return (strcmp(k, ((const struct keywords *)e)->k_name));
353
}
354
355
int
356
lookup(char *s)
357
{
358
	/* this has to be sorted always */
359
	static const struct keywords keywords[] = {
360
		{"fib-update",			FIBUPDATE},
361
		{"group",			GROUP},
362
		{"igmp-version",		IGMPVERSION},
363
		{"interface",			INTERFACE},
364
		{"last-member-query-count",	LASTMEMBERQUERYCNT},
365
		{"last-member-query-interval",	LASTMEMBERQUERYINTERVAL},
366
		{"metric",			METRIC},
367
		{"passive",			PASSIVE},
368
		{"query-interval",		QUERYINTERVAL},
369
		{"query-response-interval",	QUERYRESPINTERVAL},
370
		{"robustness",			ROBUSTNESS},
371
		{"startup-query-count",		STARTUPQUERYCNT},
372
		{"startup-query-interval",	STARTUPQUERYINTERVAL}
373
	};
374
	const struct keywords	*p;
375
376
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
377
	    sizeof(keywords[0]), kw_cmp);
378
379
	if (p)
380
		return (p->k_val);
381
	else
382
		return (STRING);
383
}
384
385
#define MAXPUSHBACK	128
386
387
u_char	*parsebuf;
388
int	 parseindex;
389
u_char	 pushback_buffer[MAXPUSHBACK];
390
int	 pushback_index = 0;
391
392
int
393
lgetc(int quotec)
394
{
395
	int		c, next;
396
397
	if (parsebuf) {
398
		/* Read character from the parsebuffer instead of input. */
399
		if (parseindex >= 0) {
400
			c = parsebuf[parseindex++];
401
			if (c != '\0')
402
				return (c);
403
			parsebuf = NULL;
404
		} else
405
			parseindex++;
406
	}
407
408
	if (pushback_index)
409
		return (pushback_buffer[--pushback_index]);
410
411
	if (quotec) {
412
		if ((c = getc(file->stream)) == EOF) {
413
			yyerror("reached end of file while parsing "
414
			    "quoted string");
415
			if (file == topfile || popfile() == EOF)
416
				return (EOF);
417
			return (quotec);
418
		}
419
		return (c);
420
	}
421
422
	while ((c = getc(file->stream)) == '\\') {
423
		next = getc(file->stream);
424
		if (next != '\n') {
425
			c = next;
426
			break;
427
		}
428
		yylval.lineno = file->lineno;
429
		file->lineno++;
430
	}
431
432
	while (c == EOF) {
433
		if (file == topfile || popfile() == EOF)
434
			return (EOF);
435
		c = getc(file->stream);
436
	}
437
	return (c);
438
}
439
440
int
441
lungetc(int c)
442
{
443
	if (c == EOF)
444
		return (EOF);
445
	if (parsebuf) {
446
		parseindex--;
447
		if (parseindex >= 0)
448
			return (c);
449
	}
450
	if (pushback_index < MAXPUSHBACK-1)
451
		return (pushback_buffer[pushback_index++] = c);
452
	else
453
		return (EOF);
454
}
455
456
int
457
findeol(void)
458
{
459
	int	c;
460
461
	parsebuf = NULL;
462
463
	/* skip to either EOF or the first real EOL */
464
	while (1) {
465
		if (pushback_index)
466
			c = pushback_buffer[--pushback_index];
467
		else
468
			c = lgetc(0);
469
		if (c == '\n') {
470
			file->lineno++;
471
			break;
472
		}
473
		if (c == EOF)
474
			break;
475
	}
476
	return (ERROR);
477
}
478
479
int
480
yylex(void)
481
{
482
	u_char	 buf[8096];
483
	u_char	*p, *val;
484
	int	 quotec, next, c;
485
	int	 token;
486
487
top:
488
	p = buf;
489
	while ((c = lgetc(0)) == ' ' || c == '\t')
490
		; /* nothing */
491
492
	yylval.lineno = file->lineno;
493
	if (c == '#')
494
		while ((c = lgetc(0)) != '\n' && c != EOF)
495
			; /* nothing */
496
	if (c == '$' && parsebuf == NULL) {
497
		while (1) {
498
			if ((c = lgetc(0)) == EOF)
499
				return (0);
500
501
			if (p + 1 >= buf + sizeof(buf) - 1) {
502
				yyerror("string too long");
503
				return (findeol());
504
			}
505
			if (isalnum(c) || c == '_') {
506
				*p++ = c;
507
				continue;
508
			}
509
			*p = '\0';
510
			lungetc(c);
511
			break;
512
		}
513
		val = symget(buf);
514
		if (val == NULL) {
515
			yyerror("macro '%s' not defined", buf);
516
			return (findeol());
517
		}
518
		parsebuf = val;
519
		parseindex = 0;
520
		goto top;
521
	}
522
523
	switch (c) {
524
	case '\'':
525
	case '"':
526
		quotec = c;
527
		while (1) {
528
			if ((c = lgetc(quotec)) == EOF)
529
				return (0);
530
			if (c == '\n') {
531
				file->lineno++;
532
				continue;
533
			} else if (c == '\\') {
534
				if ((next = lgetc(quotec)) == EOF)
535
					return (0);
536
				if (next == quotec || c == ' ' || c == '\t')
537
					c = next;
538
				else if (next == '\n') {
539
					file->lineno++;
540
					continue;
541
				} else
542
					lungetc(next);
543
			} else if (c == quotec) {
544
				*p = '\0';
545
				break;
546
			} else if (c == '\0') {
547
				yyerror("syntax error");
548
				return (findeol());
549
			}
550
			if (p + 1 >= buf + sizeof(buf) - 1) {
551
				yyerror("string too long");
552
				return (findeol());
553
			}
554
			*p++ = c;
555
		}
556
		yylval.v.string = strdup(buf);
557
		if (yylval.v.string == NULL)
558
			err(1, "yylex: strdup");
559
		return (STRING);
560
	}
561
562
#define allowed_to_end_number(x) \
563
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
564
565
	if (c == '-' || isdigit(c)) {
566
		do {
567
			*p++ = c;
568
			if ((unsigned)(p-buf) >= sizeof(buf)) {
569
				yyerror("string too long");
570
				return (findeol());
571
			}
572
		} while ((c = lgetc(0)) != EOF && isdigit(c));
573
		lungetc(c);
574
		if (p == buf + 1 && buf[0] == '-')
575
			goto nodigits;
576
		if (c == EOF || allowed_to_end_number(c)) {
577
			const char *errstr = NULL;
578
579
			*p = '\0';
580
			yylval.v.number = strtonum(buf, LLONG_MIN,
581
			    LLONG_MAX, &errstr);
582
			if (errstr) {
583
				yyerror("\"%s\" invalid number: %s",
584
				    buf, errstr);
585
				return (findeol());
586
			}
587
			return (NUMBER);
588
		} else {
589
nodigits:
590
			while (p > buf + 1)
591
				lungetc(*--p);
592
			c = *--p;
593
			if (c == '-')
594
				return (c);
595
		}
596
	}
597
598
#define allowed_in_string(x) \
599
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
600
	x != '{' && x != '}' && \
601
	x != '!' && x != '=' && x != '#' && \
602
	x != ','))
603
604
	if (isalnum(c) || c == ':' || c == '_') {
605
		do {
606
			*p++ = c;
607
			if ((unsigned)(p-buf) >= sizeof(buf)) {
608
				yyerror("string too long");
609
				return (findeol());
610
			}
611
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
612
		lungetc(c);
613
		*p = '\0';
614
		if ((token = lookup(buf)) == STRING)
615
			if ((yylval.v.string = strdup(buf)) == NULL)
616
				err(1, "yylex: strdup");
617
		return (token);
618
	}
619
	if (c == '\n') {
620
		yylval.lineno = file->lineno;
621
		file->lineno++;
622
	}
623
	if (c == EOF)
624
		return (0);
625
	return (c);
626
}
627
628
int
629
check_file_secrecy(int fd, const char *fname)
630
{
631
	struct stat	st;
632
633
	if (fstat(fd, &st)) {
634
		log_warn("cannot stat %s", fname);
635
		return (-1);
636
	}
637
	if (st.st_uid != 0 && st.st_uid != getuid()) {
638
		log_warnx("%s: owner not root or current user", fname);
639
		return (-1);
640
	}
641
	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
642
		log_warnx("%s: group writable or world read/writable", fname);
643
		return (-1);
644
	}
645
	return (0);
646
}
647
648
struct file *
649
pushfile(const char *name, int secret)
650
{
651
	struct file	*nfile;
652
653
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
654
		log_warn("malloc");
655
		return (NULL);
656
	}
657
	if ((nfile->name = strdup(name)) == NULL) {
658
		log_warn("malloc");
659
		free(nfile);
660
		return (NULL);
661
	}
662
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
663
		log_warn("%s", nfile->name);
664
		free(nfile->name);
665
		free(nfile);
666
		return (NULL);
667
	} else if (secret &&
668
	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
669
		fclose(nfile->stream);
670
		free(nfile->name);
671
		free(nfile);
672
		return (NULL);
673
	}
674
	nfile->lineno = 1;
675
	TAILQ_INSERT_TAIL(&files, nfile, entry);
676
	return (nfile);
677
}
678
679
int
680
popfile(void)
681
{
682
	struct file	*prev;
683
684
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
685
		prev->errors += file->errors;
686
687
	TAILQ_REMOVE(&files, file, entry);
688
	fclose(file->stream);
689
	free(file->name);
690
	free(file);
691
	file = prev;
692
	return (file ? 0 : EOF);
693
}
694
695
struct dvmrpd_conf *
696
parse_config(char *filename, int opts)
697
{
698
	int		 errors = 0;
699
	struct sym	*sym, *next;
700
	struct timeval	 now;
701
702
	if ((conf = calloc(1, sizeof(struct dvmrpd_conf))) == NULL) {
703
		errx(1, "parse_config calloc");
704
		return (NULL);
705
	}
706
707
	defs = &globaldefs;
708
	defs->probe_interval = DEFAULT_PROBE_INTERVAL;
709
	defs->last_member_query_cnt = DEFAULT_LAST_MEMBER_QUERY_CNT;
710
	defs->last_member_query_interval = DEFAULT_LAST_MEMBER_QUERY_INTERVAL;
711
	defs->metric = DEFAULT_METRIC;
712
	defs->query_interval = DEFAULT_QUERY_INTERVAL;
713
	defs->query_resp_interval = DEFAULT_QUERY_RESP_INTERVAL;
714
	defs->robustness = DEFAULT_ROBUSTNESS;
715
	defs->startup_query_cnt = DEFAULT_STARTUP_QUERY_CNT;
716
	defs->startup_query_interval = DEFAULT_STARTUP_QUERY_INTERVAL;
717
	defs->igmp_version = DEFAULT_IGMP_VERSION;
718
	defs->dead_interval = NBR_TMOUT;
719
720
	if ((file = pushfile(filename, 1)) == NULL) {
721
		free(conf);
722
		return (NULL);
723
	}
724
	topfile = file;
725
726
	gettimeofday(&now, NULL);
727
	conf->gen_id = (u_int32_t)now.tv_sec;	/* for a while after 2038 */
728
	conf->opts = opts;
729
730
	yyparse();
731
	errors = file->errors;
732
	popfile();
733
734
	/* Free macros and check which have not been used. */
735
	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
736
		if ((conf->opts & DVMRPD_OPT_VERBOSE2) && !sym->used)
737
			fprintf(stderr, "warning: macro '%s' not "
738
			    "used\n", sym->nam);
739
		if (!sym->persist) {
740
			free(sym->nam);
741
			free(sym->val);
742
			TAILQ_REMOVE(&symhead, sym, entry);
743
			free(sym);
744
		}
745
	}
746
747
	if (errors) {
748
		clear_config(conf);
749
		return (NULL);
750
	}
751
752
	return (conf);
753
}
754
755
int
756
symset(const char *nam, const char *val, int persist)
757
{
758
	struct sym	*sym;
759
760
	TAILQ_FOREACH(sym, &symhead, entry) {
761
		if (strcmp(nam, sym->nam) == 0)
762
			break;
763
	}
764
765
	if (sym != NULL) {
766
		if (sym->persist == 1)
767
			return (0);
768
		else {
769
			free(sym->nam);
770
			free(sym->val);
771
			TAILQ_REMOVE(&symhead, sym, entry);
772
			free(sym);
773
		}
774
	}
775
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
776
		return (-1);
777
778
	sym->nam = strdup(nam);
779
	if (sym->nam == NULL) {
780
		free(sym);
781
		return (-1);
782
	}
783
	sym->val = strdup(val);
784
	if (sym->val == NULL) {
785
		free(sym->nam);
786
		free(sym);
787
		return (-1);
788
	}
789
	sym->used = 0;
790
	sym->persist = persist;
791
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
792
	return (0);
793
}
794
795
int
796
cmdline_symset(char *s)
797
{
798
	char	*sym, *val;
799
	int	ret;
800
	size_t	len;
801
802
	if ((val = strrchr(s, '=')) == NULL)
803
		return (-1);
804
805
	len = strlen(s) - strlen(val) + 1;
806
	if ((sym = malloc(len)) == NULL)
807
		errx(1, "cmdline_symset: malloc");
808
809
	strlcpy(sym, s, len);
810
811
	ret = symset(sym, val + 1, 1);
812
	free(sym);
813
814
	return (ret);
815
}
816
817
char *
818
symget(const char *nam)
819
{
820
	struct sym	*sym;
821
822
	TAILQ_FOREACH(sym, &symhead, entry) {
823
		if (strcmp(nam, sym->nam) == 0) {
824
			sym->used = 1;
825
			return (sym->val);
826
		}
827
	}
828
	return (NULL);
829
}
830
831
struct iface *
832
conf_get_if(struct kif *kif)
833
{
834
	struct iface	*i;
835
836
	if (kif->ifindex >= MAXVIFS) {
837
		yyerror("interface %s index too large", kif->ifname);
838
		return (NULL);
839
	}
840
841
	LIST_FOREACH(i, &conf->iface_list, entry)
842
		if (i->ifindex == kif->ifindex) {
843
			yyerror("interface %s already configured",
844
			    kif->ifname);
845
			return (NULL);
846
		}
847
848
	i = if_new(kif);
849
	i->passive = 0;
850
	i->recv_query_resp_interval = DEFAULT_QUERY_RESP_INTERVAL;
851
852
	return (i);
853
}
854
855
void
856
clear_config(struct dvmrpd_conf *xconf)
857
{
858
	/* XXX clear conf */
859
		/* ... */
860
}
861
#line 854 "parse.c"
862
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
863
static int yygrowstack(void)
864
{
865
    unsigned int newsize;
866
    long sslen;
867
    short *newss;
868
    YYSTYPE *newvs;
869
870
    if ((newsize = yystacksize) == 0)
871
        newsize = YYINITSTACKSIZE;
872
    else if (newsize >= YYMAXDEPTH)
873
        return -1;
874
    else if ((newsize *= 2) > YYMAXDEPTH)
875
        newsize = YYMAXDEPTH;
876
    sslen = yyssp - yyss;
877
#ifdef SIZE_MAX
878
#define YY_SIZE_MAX SIZE_MAX
879
#else
880
#define YY_SIZE_MAX 0xffffffffU
881
#endif
882
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
883
        goto bail;
884
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
885
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
886
    if (newss == NULL)
887
        goto bail;
888
    yyss = newss;
889
    yyssp = newss + sslen;
890
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
891
        goto bail;
892
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
893
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
894
    if (newvs == NULL)
895
        goto bail;
896
    yyvs = newvs;
897
    yyvsp = newvs + sslen;
898
    yystacksize = newsize;
899
    yysslim = yyss + newsize - 1;
900
    return 0;
901
bail:
902
    if (yyss)
903
            free(yyss);
904
    if (yyvs)
905
            free(yyvs);
906
    yyss = yyssp = NULL;
907
    yyvs = yyvsp = NULL;
908
    yystacksize = 0;
909
    return -1;
910
}
911
912
#define YYABORT goto yyabort
913
#define YYREJECT goto yyabort
914
#define YYACCEPT goto yyaccept
915
#define YYERROR goto yyerrlab
916
int
917
yyparse(void)
918
{
919
    int yym, yyn, yystate;
920
#if YYDEBUG
921
    const char *yys;
922
923
    if ((yys = getenv("YYDEBUG")))
924
    {
925
        yyn = *yys;
926
        if (yyn >= '0' && yyn <= '9')
927
            yydebug = yyn - '0';
928
    }
929
#endif /* YYDEBUG */
930
931
    yynerrs = 0;
932
    yyerrflag = 0;
933
    yychar = (-1);
934
935
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
936
    yyssp = yyss;
937
    yyvsp = yyvs;
938
    *yyssp = yystate = 0;
939
940
yyloop:
941
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
942
    if (yychar < 0)
943
    {
944
        if ((yychar = yylex()) < 0) yychar = 0;
945
#if YYDEBUG
946
        if (yydebug)
947
        {
948
            yys = 0;
949
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
950
            if (!yys) yys = "illegal-symbol";
951
            printf("%sdebug: state %d, reading %d (%s)\n",
952
                    YYPREFIX, yystate, yychar, yys);
953
        }
954
#endif
955
    }
956
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
957
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
958
    {
959
#if YYDEBUG
960
        if (yydebug)
961
            printf("%sdebug: state %d, shifting to state %d\n",
962
                    YYPREFIX, yystate, yytable[yyn]);
963
#endif
964
        if (yyssp >= yysslim && yygrowstack())
965
        {
966
            goto yyoverflow;
967
        }
968
        *++yyssp = yystate = yytable[yyn];
969
        *++yyvsp = yylval;
970
        yychar = (-1);
971
        if (yyerrflag > 0)  --yyerrflag;
972
        goto yyloop;
973
    }
974
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
975
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
976
    {
977
        yyn = yytable[yyn];
978
        goto yyreduce;
979
    }
980
    if (yyerrflag) goto yyinrecovery;
981
#if defined(__GNUC__)
982
    goto yynewerror;
983
#endif
984
yynewerror:
985
    yyerror("syntax error");
986
#if defined(__GNUC__)
987
    goto yyerrlab;
988
#endif
989
yyerrlab:
990
    ++yynerrs;
991
yyinrecovery:
992
    if (yyerrflag < 3)
993
    {
994
        yyerrflag = 3;
995
        for (;;)
996
        {
997
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
998
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
999
            {
1000
#if YYDEBUG
1001
                if (yydebug)
1002
                    printf("%sdebug: state %d, error recovery shifting\
1003
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
1004
#endif
1005
                if (yyssp >= yysslim && yygrowstack())
1006
                {
1007
                    goto yyoverflow;
1008
                }
1009
                *++yyssp = yystate = yytable[yyn];
1010
                *++yyvsp = yylval;
1011
                goto yyloop;
1012
            }
1013
            else
1014
            {
1015
#if YYDEBUG
1016
                if (yydebug)
1017
                    printf("%sdebug: error recovery discarding state %d\n",
1018
                            YYPREFIX, *yyssp);
1019
#endif
1020
                if (yyssp <= yyss) goto yyabort;
1021
                --yyssp;
1022
                --yyvsp;
1023
            }
1024
        }
1025
    }
1026
    else
1027
    {
1028
        if (yychar == 0) goto yyabort;
1029
#if YYDEBUG
1030
        if (yydebug)
1031
        {
1032
            yys = 0;
1033
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1034
            if (!yys) yys = "illegal-symbol";
1035
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1036
                    YYPREFIX, yystate, yychar, yys);
1037
        }
1038
#endif
1039
        yychar = (-1);
1040
        goto yyloop;
1041
    }
1042
yyreduce:
1043
#if YYDEBUG
1044
    if (yydebug)
1045
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1046
                YYPREFIX, yystate, yyn, yyrule[yyn]);
1047
#endif
1048
    yym = yylen[yyn];
1049
    if (yym)
1050
        yyval = yyvsp[1-yym];
1051
    else
1052
        memset(&yyval, 0, sizeof yyval);
1053
    switch (yyn)
1054
    {
1055
case 7:
1056
#line 134 "parse.y"
1057
{ file->errors++; }
1058
break;
1059
case 8:
1060
#line 137 "parse.y"
1061
{
1062
			if (asprintf(&yyval.v.string, "%s %s", yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
1063
				free(yyvsp[-1].v.string);
1064
				free(yyvsp[0].v.string);
1065
				yyerror("string: asprintf");
1066
				YYERROR;
1067
			}
1068
			free(yyvsp[-1].v.string);
1069
			free(yyvsp[0].v.string);
1070
		}
1071
break;
1072
case 10:
1073
#line 150 "parse.y"
1074
{
1075
			if (!strcmp(yyvsp[0].v.string, "yes"))
1076
				yyval.v.number = 1;
1077
			else if (!strcmp(yyvsp[0].v.string, "no"))
1078
				yyval.v.number = 0;
1079
			else {
1080
				yyerror("syntax error, "
1081
				    "either yes or no expected");
1082
				free(yyvsp[0].v.string);
1083
				YYERROR;
1084
			}
1085
			free(yyvsp[0].v.string);
1086
		}
1087
break;
1088
case 11:
1089
#line 165 "parse.y"
1090
{
1091
			char *s = yyvsp[-2].v.string;
1092
			if (conf->opts & DVMRPD_OPT_VERBOSE)
1093
				printf("%s = \"%s\"\n", yyvsp[-2].v.string, yyvsp[0].v.string);
1094
			while (*s++) {
1095
				if (isspace((unsigned char)*s)) {
1096
					yyerror("macro name cannot contain "
1097
					    "whitespace");
1098
					YYERROR;
1099
				}
1100
			}
1101
			if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
1102
				fatal("cannot store variable");
1103
			free(yyvsp[-2].v.string);
1104
			free(yyvsp[0].v.string);
1105
		}
1106
break;
1107
case 12:
1108
#line 183 "parse.y"
1109
{
1110
			if (yyvsp[0].v.number == 0)
1111
				conf->flags |= DVMRPD_FLAG_NO_FIB_UPDATE;
1112
			else
1113
				conf->flags &= ~DVMRPD_FLAG_NO_FIB_UPDATE;
1114
		}
1115
break;
1116
case 14:
1117
#line 192 "parse.y"
1118
{
1119
			if (yyvsp[0].v.number < MIN_LAST_MEMBER_QUERY_CNT ||
1120
			    yyvsp[0].v.number > MAX_LAST_MEMBER_QUERY_CNT) {
1121
				yyerror("last-member-query-count out of "
1122
				    "range (%d-%d)",
1123
				    MIN_LAST_MEMBER_QUERY_CNT,
1124
				    MAX_LAST_MEMBER_QUERY_CNT);
1125
				YYERROR;
1126
			}
1127
			defs->last_member_query_cnt = yyvsp[0].v.number;
1128
		}
1129
break;
1130
case 15:
1131
#line 203 "parse.y"
1132
{
1133
			if (yyvsp[0].v.number < MIN_LAST_MEMBER_QUERY_INTERVAL ||
1134
			    yyvsp[0].v.number > MAX_LAST_MEMBER_QUERY_INTERVAL) {
1135
				yyerror("last-member-query-interval out of "
1136
				    "range (%d-%d)",
1137
				    MIN_LAST_MEMBER_QUERY_INTERVAL,
1138
				    MAX_LAST_MEMBER_QUERY_INTERVAL);
1139
				YYERROR;
1140
			}
1141
			defs->last_member_query_interval = yyvsp[0].v.number;
1142
		}
1143
break;
1144
case 16:
1145
#line 214 "parse.y"
1146
{
1147
			if (yyvsp[0].v.number < MIN_METRIC || yyvsp[0].v.number > MAX_METRIC) {
1148
				yyerror("metric out of range (%d-%d)",
1149
				    MIN_METRIC, MAX_METRIC);
1150
				YYERROR;
1151
			}
1152
			defs->metric = yyvsp[0].v.number;
1153
		}
1154
break;
1155
case 17:
1156
#line 222 "parse.y"
1157
{
1158
			if (yyvsp[0].v.number < MIN_QUERY_INTERVAL ||
1159
			    yyvsp[0].v.number > MAX_QUERY_INTERVAL) {
1160
				yyerror("query-interval out of range (%d-%d)",
1161
				    MIN_QUERY_INTERVAL, MAX_QUERY_INTERVAL);
1162
				YYERROR;
1163
			}
1164
			defs->query_interval = yyvsp[0].v.number;
1165
		}
1166
break;
1167
case 18:
1168
#line 231 "parse.y"
1169
{
1170
			if (yyvsp[0].v.number < MIN_QUERY_RESP_INTERVAL ||
1171
			    yyvsp[0].v.number > MAX_QUERY_RESP_INTERVAL) {
1172
				yyerror("query-response-interval out of "
1173
				    "range (%d-%d)",
1174
				    MIN_QUERY_RESP_INTERVAL,
1175
				    MAX_QUERY_RESP_INTERVAL);
1176
				YYERROR;
1177
			}
1178
			defs->query_resp_interval = yyvsp[0].v.number;
1179
		}
1180
break;
1181
case 19:
1182
#line 242 "parse.y"
1183
{
1184
			if (yyvsp[0].v.number < MIN_ROBUSTNESS || yyvsp[0].v.number > MAX_ROBUSTNESS) {
1185
				yyerror("robustness out of range (%d-%d)",
1186
				    MIN_ROBUSTNESS, MAX_ROBUSTNESS);
1187
				YYERROR;
1188
			}
1189
			defs->robustness = yyvsp[0].v.number;
1190
		}
1191
break;
1192
case 20:
1193
#line 250 "parse.y"
1194
{
1195
			if (yyvsp[0].v.number < MIN_STARTUP_QUERY_CNT ||
1196
			    yyvsp[0].v.number > MAX_STARTUP_QUERY_CNT) {
1197
				yyerror("startup-query-count out of "
1198
				    "range (%d-%d)",
1199
				    MIN_STARTUP_QUERY_CNT,
1200
				    MAX_STARTUP_QUERY_CNT);
1201
				YYERROR;
1202
			}
1203
			defs->startup_query_cnt = yyvsp[0].v.number;
1204
		}
1205
break;
1206
case 21:
1207
#line 261 "parse.y"
1208
{
1209
			if (yyvsp[0].v.number < MIN_STARTUP_QUERY_INTERVAL ||
1210
			    yyvsp[0].v.number > MAX_STARTUP_QUERY_INTERVAL) {
1211
				yyerror("startup-query-interval out of "
1212
				    "range (%d-%d)",
1213
				    MIN_STARTUP_QUERY_INTERVAL,
1214
				    MAX_STARTUP_QUERY_INTERVAL);
1215
				YYERROR;
1216
			}
1217
			defs->startup_query_interval = yyvsp[0].v.number;
1218
		}
1219
break;
1220
case 22:
1221
#line 272 "parse.y"
1222
{
1223
			if (yyvsp[0].v.number < MIN_IGMP_VERSION ||
1224
			    yyvsp[0].v.number > MAX_IGMP_VERSION) {
1225
				yyerror("igmp-version out of range (%d-%d)",
1226
				    MIN_IGMP_VERSION, MAX_IGMP_VERSION);
1227
				YYERROR;
1228
			}
1229
			defs->igmp_version = yyvsp[0].v.number;
1230
		}
1231
break;
1232
case 26:
1233
#line 290 "parse.y"
1234
{
1235
			struct kif *kif;
1236
1237
			if ((kif = kif_findname(yyvsp[0].v.string)) == NULL) {
1238
				yyerror("unknown interface %s", yyvsp[0].v.string);
1239
				free(yyvsp[0].v.string);
1240
				YYERROR;
1241
			}
1242
			free(yyvsp[0].v.string);
1243
			iface = conf_get_if(kif);
1244
			if (iface == NULL)
1245
				YYERROR;
1246
			LIST_INSERT_HEAD(&conf->iface_list, iface, entry);
1247
1248
			memcpy(&ifacedefs, defs, sizeof(ifacedefs));
1249
			defs = &ifacedefs;
1250
		}
1251
break;
1252
case 27:
1253
#line 306 "parse.y"
1254
{
1255
			iface->probe_interval = defs->probe_interval;
1256
			iface->query_interval = defs->query_interval;
1257
			iface->query_resp_interval = defs->query_resp_interval;
1258
			iface->startup_query_interval =
1259
			    defs->startup_query_interval;
1260
			iface->startup_query_cnt = defs->startup_query_cnt;
1261
			iface->last_member_query_interval =
1262
			    defs->last_member_query_interval;
1263
			iface->last_member_query_cnt =
1264
			    defs->last_member_query_cnt;
1265
			iface->dead_interval = defs->dead_interval;
1266
			iface->metric = defs->metric;
1267
			iface->robustness = defs->robustness;
1268
			iface->igmp_version = defs->igmp_version;
1269
			if (grdefs)
1270
				defs = grdefs;
1271
			else
1272
				defs = &globaldefs;
1273
			iface = NULL;
1274
		}
1275
break;
1276
case 33:
1277
#line 338 "parse.y"
1278
{ iface->passive = 1; }
1279
break;
1280
case 35:
1281
#line 342 "parse.y"
1282
{
1283
			memcpy(&groupdefs, defs, sizeof(groupdefs));
1284
			grdefs = defs = &groupdefs;
1285
		}
1286
break;
1287
case 36:
1288
#line 346 "parse.y"
1289
{
1290
			grdefs = NULL;
1291
			defs = &globaldefs;
1292
		}
1293
break;
1294
#line 1287 "parse.c"
1295
    }
1296
    yyssp -= yym;
1297
    yystate = *yyssp;
1298
    yyvsp -= yym;
1299
    yym = yylhs[yyn];
1300
    if (yystate == 0 && yym == 0)
1301
    {
1302
#if YYDEBUG
1303
        if (yydebug)
1304
            printf("%sdebug: after reduction, shifting from state 0 to\
1305
 state %d\n", YYPREFIX, YYFINAL);
1306
#endif
1307
        yystate = YYFINAL;
1308
        *++yyssp = YYFINAL;
1309
        *++yyvsp = yyval;
1310
        if (yychar < 0)
1311
        {
1312
            if ((yychar = yylex()) < 0) yychar = 0;
1313
#if YYDEBUG
1314
            if (yydebug)
1315
            {
1316
                yys = 0;
1317
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1318
                if (!yys) yys = "illegal-symbol";
1319
                printf("%sdebug: state %d, reading %d (%s)\n",
1320
                        YYPREFIX, YYFINAL, yychar, yys);
1321
            }
1322
#endif
1323
        }
1324
        if (yychar == 0) goto yyaccept;
1325
        goto yyloop;
1326
    }
1327
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1328
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1329
        yystate = yytable[yyn];
1330
    else
1331
        yystate = yydgoto[yym];
1332
#if YYDEBUG
1333
    if (yydebug)
1334
        printf("%sdebug: after reduction, shifting from state %d \
1335
to state %d\n", YYPREFIX, *yyssp, yystate);
1336
#endif
1337
    if (yyssp >= yysslim && yygrowstack())
1338
    {
1339
        goto yyoverflow;
1340
    }
1341
    *++yyssp = yystate;
1342
    *++yyvsp = yyval;
1343
    goto yyloop;
1344
yyoverflow:
1345
    yyerror("yacc stack overflow");
1346
yyabort:
1347
    if (yyss)
1348
            free(yyss);
1349
    if (yyvs)
1350
            free(yyvs);
1351
    yyss = yyssp = NULL;
1352
    yyvs = yyvsp = NULL;
1353
    yystacksize = 0;
1354
    return (1);
1355
yyaccept:
1356
    if (yyss)
1357
            free(yyss);
1358
    if (yyvs)
1359
            free(yyvs);
1360
    yyss = yyssp = NULL;
1361
    yyvs = yyvsp = NULL;
1362
    yystacksize = 0;
1363
    return (0);
1364
}