xref: /illumos-gate/usr/src/cmd/fs.d/udfs/fsdb/fsdb_yacc.y (revision 7c478bd9)
1 %{
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License, Version 1.0 only
7  * (the "License").  You may not use this file except in compliance
8  * with the License.
9  *
10  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11  * or http://www.opensolaris.org/os/licensing.
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  *
23  * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <locale.h>
31 #include <sys/param.h>
32 #include <sys/fs/udf_volume.h>
33 
34 char	shell_name[128] = "/bin/sh";
35 extern char	prompt[];
36 extern uint16_t ricb_prn;
37 extern uint32_t ricb_loc;
38 extern int32_t bsize, bmask, l2d, l2b;
39 
40 int	base = 16;
41 int	old_value = 0;
42 int	value = 0;
43 int	count = 0;
44 
45 
46 int	last_op_type = 0;
47 #define	TYPE_NONE	0
48 #define	TYPE_INODE	1
49 #define	TYPE_DIRENT	2
50 #define	TYPE_BLOCK	3
51 #define	TYPE_CD		4
52 
53 uint32_t i_number = 0;
54 uint32_t d_entry = 0;
55 int	error_override = 0;
56 
57 int	register_array[256];
58 char	cwd[MAXPATHLEN] = "/";
59 
60 int32_t ls_flags;
61 #define	LONG_LIST	0x1
62 #define	RECU_LIST	0x2
63 #define	LIST_LS		0x4
64 
65 int32_t find_flags;
66 #define	FIND_DIR	0x1
67 #define	FIND_NAME	0x2
68 #define	FIND_INODE	0x4
69 #define	FIND_DONE	0x8
70 char find_dir[1024];
71 char find_name[1024];
72 uint32_t find_in;
73 
74 %}
75 
76 %union
77 {
78 	uint8_t		*strval;
79 	uint64_t	intval;
80 };
81 
82 %token BASE BLOCK CD DIRECTORY TFILE FIND FILL
83 %token INODE LS OVERRIDE PROMPT PWD QUIT TAG BANG
84 
85 %token AVD MVDS RVDS INTS FSDS ROOT
86 %token ATTZ ATYE ATMO ATDA ATHO ATMI ATSE ATCE ATHU ATMIC
87 %token CTTZ CTYE CTMO CTDA CTHO CTMI CTSE CTCE CTHU CTMIC
88 %token MTTZ MTYE MTMO MTDA MTHO MTMI MTSE MTCE MTHU MTMIC
89 %token GID LN MD MAJ MIO NM SZ UID UNIQ
90 %token DOT
91 %token NL
92 
93 %token WORD
94 
95 %left '-' '+'
96 %left '*' '%'
97 
98 %type <strval>	WORD
99 %type <intval> expr
100 
101 %%
102 
103 session		: statement_list
104 
105 statement_list	: /* empty */			{ print_prompt(); }
106 		| statement_list statement
107 			{
108 				ls_flags = 0;
109 			}
110 		;
111 
112 statement	: empty_statement
113 		| current_value
114 		| register
115 		| base | block | cd | directory | file | find | fill
116 		| inode | ls | override | nprompt | pwd | quit | tag | shell
117 		| avd | mvds | rvds | ints | fsds | root
118 		| at | ct | gid | ln | mt | md
119 		| maj | min | nm | sz | uid | uniq
120 		| dump | texpr
121 		| error	{ yyclearin; yyerrok; }
122 		;
123 
124 empty_statement	: NL
125 			{
126 				print_prompt();
127 			}
128 		;
129 
130 
131 current_value	: DOT
132 			{
133 				if (last_op_type == TYPE_INODE) {
134 					print_inode(i_number << l2b);
135 				} else if (last_op_type == TYPE_DIRENT) {
136 					print_dent(i_number << l2b, d_entry);
137 				} else {
138 					fprintf(stdout,
139 						gettext("%x\n"), value);
140 				}
141 			}
142 			;
143 
144 register	: '<' WORD
145 			{
146 				if ((strlen((caddr_t)$2) == 1) &&
147 					((($2[0] >= 'a') &&
148 						($2[0] <= 'z')) ||
149 					(($2[0] >= 'A') &&
150 						($2[0] <= 'Z')))) {
151 					value = register_array[$2[0]];
152 				} else {
153 					fprintf(stdout,
154 						gettext("Registers can"
155 						" be only a-z or A-Z\n"));
156 				}
157 			}
158 		| '>' WORD
159 			{
160 				if ((strlen((caddr_t)$2) == 1) &&
161 					((($2[0] >= 'a') &&
162 						($2[0] <= 'z')) ||
163 					(($2[0] >= 'A') &&
164 						($2[0] <= 'Z')))) {
165 					register_array[$2[0]] = value;
166 				} else {
167 					fprintf(stdout,
168 						gettext("Registers can"
169 						" be only a-z or A-Z\n"));
170 				}
171 			}
172 		;
173 
174 base		: BASE '=' expr
175 			{
176 				if (($3 == 8) || ($3 == 10) || ($3 == 16)) {
177 					base = $3;
178 				} else {
179 					fprintf(stdout,
180 						gettext("Requested %x Only"
181 						" Oct, Dec and"
182 						" Hex are Supported\n"), $3);
183 				}
184 			}
185 		| BASE
186 			{
187 				fprintf(stdout,
188 					gettext("Current Base in Decimal"
189 					" : %d\n"), base);
190 			}
191 		;
192 
193 block		: BLOCK
194 			{
195 				last_op_type = TYPE_NONE;
196 				value = value * DEV_BSIZE;
197 			}
198 		;
199 
200 cd		: CD ' ' WORD
201 			{
202 				uint8_t fl;
203 				uint32_t temp;
204 				char temp_cwd[MAXPATHLEN];
205 
206 				strcpy(temp_cwd, cwd);
207 				if (strcmp((caddr_t)$3, "..") == 0) {
208 					if (strlen(temp_cwd) == 1) {
209 						if (temp_cwd[0] != '/') {
210 							fprintf(stdout,
211 							gettext("cwd is invalid"
212 							"setting to /\n"));
213 							strcpy(temp_cwd, "/");
214 						}
215 					} else {
216 						dirname(temp_cwd);
217 					}
218 				} else {
219 					int32_t len;
220 
221 					len = strlen(temp_cwd);
222 					if (temp_cwd[len - 1] != '/') {
223 						temp_cwd[len] = '/';
224 						temp_cwd[len + 1] = '\0';
225 					}
226 					strcat(temp_cwd, (caddr_t)$3);
227 				}
228 				if (inode_from_path(temp_cwd, &temp,
229 							&fl) != 0) {
230 					fprintf(stdout,
231 						gettext("Could not locate inode"
232 						" for path %s\n"), temp_cwd);
233 					strcpy(temp_cwd, "/");
234 					if ((temp = ud_xlate_to_daddr(ricb_prn,
235 						ricb_loc)) == 0) {
236 						fprintf(stdout,
237 						gettext("Failed to translate"
238 						" prn %x loc %x\n"),
239 						ricb_prn, ricb_loc);
240 					}
241 				} else {
242 					if ((fl & FID_DIR) == 0) {
243 						fprintf(stdout,
244 						gettext("%s is not a"
245 						" directory\n"), temp_cwd);
246 					} else {
247 						strcpy(cwd, temp_cwd);
248 						value = temp << l2b;
249 						last_op_type = TYPE_CD;
250 						i_number = temp;
251 					}
252 				}
253 			}
254 		| CD
255 			{
256 				uint32_t block;
257 
258 				(void) strcpy(cwd, "/");
259 				/*
260 				 * set current value to root icb
261 				 */
262 				if ((block = ud_xlate_to_daddr(ricb_prn,
263 						ricb_loc)) == 0) {
264 					fprintf(stdout,
265 						gettext("Failed to translate "
266 						"prn %x loc %x\n"),
267 						ricb_prn, ricb_loc);
268 				} else {
269 					value = block << l2b;
270 					last_op_type = TYPE_CD;
271 					i_number = block;
272 				}
273 			}
274 		;
275 
276 directory	: DIRECTORY
277 			{
278 				if (verify_dent(i_number << l2b, value) == 0) {
279 					last_op_type = TYPE_DIRENT;
280 					d_entry = value;
281 				}
282 			}
283 		;
284 
285 file		: TFILE
286 			{
287 			}
288 		;
289 
290 find		: xfind
291 			{
292 				if ((find_flags & (FIND_NAME | FIND_INODE)) &&
293 					(find_flags & FIND_DONE)) {
294 					if (find_dir[0] != '/') {
295 						char buf[1024];
296 
297 						strcpy(buf, find_dir);
298 						if ((strlen(cwd) == 1) &&
299 							(cwd[0] == '/')) {
300 							strcpy(find_dir, "/");
301 						} else {
302 							strcpy(find_dir, cwd);
303 							strcat(find_dir, "/");
304 						}
305 						strcat(find_dir, buf);
306 					}
307 					find_it(find_dir, find_name, find_in,
308 				(find_flags & (FIND_NAME | FIND_INODE)));
309 				}
310 				find_flags = 0;
311 				find_dir[0] = '\0';
312 				find_name[0] = '\0';
313 				find_in = 0;
314 			}
315 		;
316 
317 xfind		: FIND WORD
318 			{
319 				strcpy(find_dir, (char *)$2);
320 				find_flags = FIND_DIR;
321 			}
322 		| xfind ' ' WORD
323 			{
324 				if (find_flags == FIND_DIR) {
325 					if (strcmp((char *)$3, "-name") == 0) {
326 						find_flags = FIND_NAME;
327 					} else if (strcmp((char *)$3, "-inum")
328 							== 0) {
329 						find_flags = FIND_INODE;
330 					} else {
331 						fprintf(stdout,
332 				gettext("find dir-name {-name n | -inum n}\n"));
333 					}
334 				} else if (find_flags == FIND_NAME) {
335 					strcpy(find_name, (char *)$3);
336 					find_flags |= FIND_DONE;
337 				} else if (find_flags == FIND_INODE) {
338 					uint64_t temp;
339 
340 					if (check_and_get_int($3, &temp) ==
341 						0) {
342 						find_in = temp;
343 						find_flags |= FIND_DONE;
344 					} else {
345 						fprintf(stdout,
346 				gettext("find dir-name {-name n | -inum n}\n"));
347 					}
348 				} else {
349 					fprintf(stdout,
350 				gettext("find dir-name {-name n | -inum n}\n"));
351 				}
352 			}
353 		| xfind ' ' expr
354 			{
355 				if (find_flags == FIND_INODE) {
356 					find_in = $3;
357 					find_flags |= FIND_DONE;
358 				} else {
359 					fprintf(stdout,
360 				gettext("find dir-name {-name n | -inum n}\n"));
361 				}
362 			}
363 		;
364 
365 
366 fill		: FILL '=' WORD
367 			{
368 				fill_pattern(value, count, $3);
369 			}
370 		;
371 
372 inode		: INODE
373 			{
374 				uint32_t temp;
375 
376 				if (last_op_type == TYPE_CD) {
377 					temp = value;
378 				} else {
379 					temp = value << l2b;
380 				}
381 				last_op_type = TYPE_INODE;
382 				if (verify_inode(temp, 0) != 0) {
383 					i_number = temp >> l2b;
384 					d_entry = 0;
385 				}
386 			}
387 		;
388 
389 ls		: xls
390 			{
391 				if (ls_flags & LIST_LS) {
392 					list(".", i_number, ls_flags);
393 				}
394 			}
395 		;
396 
397 xls		: LS
398 			{
399 				/* Do nothing */
400 				ls_flags = LIST_LS;
401 			}
402 		| xls ' ' WORD
403 			{
404 				if (strcmp((caddr_t)$3, "-l") == 0) {
405 					ls_flags |= LONG_LIST;
406 				} else if (strcmp((caddr_t)$3, "-R") == 0) {
407 					ls_flags |= RECU_LIST;
408 				} else if ((strcmp((caddr_t)$3, "-lR") == 0) ||
409 					(strcmp((caddr_t)$3, "-Rl") == 0)) {
410 					ls_flags |= LONG_LIST | RECU_LIST;
411 				} else {
412 					list(".", i_number, ls_flags);
413 					ls_flags &= ~LIST_LS;
414 				}
415 			}
416 		;
417 
418 override	: OVERRIDE
419 			{
420 				if (error_override == 0) {
421 					error_override = 1;
422 					(void) fprintf(stdout,
423 					gettext("error checking on\n"));
424 				} else {
425 					error_override = 0;
426 					(void) fprintf(stdout,
427 					gettext("error checking off\n"));
428 				}
429 			}
430 		;
431 
432 nprompt		: PROMPT '=' WORD
433 			{
434 				(void) strcpy(prompt, (caddr_t)$3);
435 			}
436 		;
437 
438 pwd		: PWD
439 			{
440 				fprintf(stdout, gettext("%s\n"), cwd);
441 			}
442 		;
443 
444 quit		: QUIT
445 			{
446 				exit (0);
447 			}
448 		;
449 
450 tag		: TAG
451 			{
452 				print_desc(value, 0);
453 			}
454 		;
455 
456 shell		: BANG
457 			{
458 				system(shell_name);
459 			}
460 		;
461 
462 avd		: AVD	{ print_desc(NULL, AVD); }
463 		;
464 mvds		: MVDS	{ print_desc(NULL, MVDS); }
465 		;
466 rvds		: RVDS	{ print_desc(NULL, RVDS); }
467 		;
468 ints		: INTS	{ print_desc(NULL, INTS); }
469 		;
470 fsds		: FSDS	{ print_desc(NULL, FSDS); }
471 		;
472 root		: ROOT	{ print_desc(NULL, ROOT); }
473 		;
474 
475 at		: ATTZ '=' expr	{ set_file(ATTZ, i_number << l2b, $3); }
476 		| ATYE '=' expr	{ set_file(ATYE, i_number << l2b, $3); }
477 		| ATMO '=' expr	{ set_file(ATMO, i_number << l2b, $3); }
478 		| ATDA '=' expr	{ set_file(ATDA, i_number << l2b, $3); }
479 		| ATHO '=' expr	{ set_file(ATHO, i_number << l2b, $3); }
480 		| ATMI '=' expr	{ set_file(ATMI, i_number << l2b, $3); }
481 		| ATSE '=' expr	{ set_file(ATSE, i_number << l2b, $3); }
482 		| ATCE '=' expr	{ set_file(ATCE, i_number << l2b, $3); }
483 		| ATHU '=' expr	{ set_file(ATHU, i_number << l2b, $3); }
484 		| ATMIC '=' expr
485 			{
486 				set_file(ATMIC, i_number << l2b, $3);
487 			}
488 		;
489 
490 ct		: CTTZ '=' expr	{ set_file(CTTZ, i_number << l2b, $3); }
491 		| CTYE '=' expr	{ set_file(CTYE, i_number << l2b, $3); }
492 		| CTMO '=' expr	{ set_file(CTMO, i_number << l2b, $3); }
493 		| CTDA '=' expr	{ set_file(CTDA, i_number << l2b, $3); }
494 		| CTHO '=' expr	{ set_file(CTHO, i_number << l2b, $3); }
495 		| CTMI '=' expr	{ set_file(CTMI, i_number << l2b, $3); }
496 		| CTSE '=' expr	{ set_file(CTSE, i_number << l2b, $3); }
497 		| CTCE '=' expr	{ set_file(CTCE, i_number << l2b, $3); }
498 		| CTHU '=' expr	{ set_file(CTHU, i_number << l2b, $3); }
499 		| CTMIC '=' expr
500 			{
501 				set_file(CTMIC, i_number << l2b, $3);
502 			}
503 		;
504 
505 mt		: MTTZ '=' expr	{ set_file(MTTZ, i_number << l2b, $3); }
506 		| MTYE '=' expr	{ set_file(MTYE, i_number << l2b, $3); }
507 		| MTMO '=' expr	{ set_file(MTMO, i_number << l2b, $3); }
508 		| MTDA '=' expr	{ set_file(MTDA, i_number << l2b, $3); }
509 		| MTHO '=' expr	{ set_file(MTHO, i_number << l2b, $3); }
510 		| MTMI '=' expr	{ set_file(MTMI, i_number << l2b, $3); }
511 		| MTSE '=' expr	{ set_file(MTSE, i_number << l2b, $3); }
512 		| MTCE '=' expr	{ set_file(MTCE, i_number << l2b, $3); }
513 		| MTHU '=' expr	{ set_file(MTHU, i_number << l2b, $3); }
514 		| MTMIC '=' expr
515 			{
516 				set_file(MTMIC, i_number << l2b, $3);
517 			}
518 		;
519 
520 
521 gid		: GID '=' expr	{ set_file(GID, i_number << l2b, $3); }
522 		;
523 
524 ln		: LN '=' expr	{ set_file(LN, i_number << l2b, $3); }
525 		;
526 
527 md		: MD '=' expr	{ set_file(MD, i_number << l2b, $3); }
528 		;
529 
530 maj		: MAJ '=' expr	{ set_file(MAJ, i_number << l2b, $3); }
531 		;
532 
533 min		: MIO '=' expr	{ set_file(MIO, i_number << l2b, $3); }
534 		;
535 
536 nm		: NM '=' expr	{ set_file(NM, i_number << l2b, $3); }
537 		;
538 
539 sz		: SZ '=' expr	{ set_file(SZ, i_number << l2b, $3); }
540 		;
541 
542 uid		: UID '=' expr	{ set_file(UID, i_number << l2b, $3); }
543 		;
544 
545 uniq		: UNIQ '=' expr	{ set_file(UNIQ, i_number << l2b, $3); }
546 		;
547 
548 dump		: '/' WORD
549 			{
550 				if (strlen((char *)$2) != 1) {
551 					fprintf(stdout,
552 						gettext("Invalid command\n"));
553 				} else {
554 					dump_disk(value, count, $2);
555 				}
556 			}
557 		| '?' WORD
558 			{
559 				if (strcmp((char *)$2, "i") == 0) {
560 					if (verify_inode(value << l2b,
561 							0) != 0) {
562 						print_inode(value << l2b);
563 						i_number = value;
564 						last_op_type == TYPE_INODE;
565 					}
566 				} else if (strcmp((char *)$2, "d") == 0) {
567 					if (verify_dent(i_number << l2b,
568 							value) == 0) {
569 						print_dent(i_number << l2b,
570 							value);
571 						d_entry = value;
572 						last_op_type == TYPE_DIRENT;
573 					}
574 				} else {
575 					fprintf(stdout,
576 						gettext("Invalid command\n"));
577 				}
578 			}
579 		;
580 
581 texpr		: expr
582 			{
583 				value = $1;
584 				count = 0;
585 			}
586 		| expr ',' expr
587 			{
588 				value = $1;
589 				count = $3;
590 			}
591 		;
592 
593 expr		: '+'
594 			{
595 				if (last_op_type == TYPE_INODE) {
596 					if (verify_inode((i_number + 1) << l2b,
597 							0) != 0) {
598 						i_number ++;
599 						print_inode(i_number << l2b);
600 						$$ = i_number << l2b;
601 					}
602 				} else if (last_op_type == TYPE_DIRENT) {
603 					if (verify_dent(i_number << l2b,
604 							d_entry + 1) == 0) {
605 						d_entry ++;
606 						print_dent(i_number << l2b,
607 							d_entry);
608 					}
609 				} else {
610 					count = 0; $$ = value++;
611 				}
612 			}
613 		| '-'
614 			{
615 				if (last_op_type == TYPE_INODE) {
616 					if (verify_inode((i_number - 1) << l2b,
617 							0) != 0) {
618 						i_number --;
619 						print_inode(i_number << l2b);
620 						$$ = i_number << l2b;
621 					}
622 				} else if (last_op_type == TYPE_DIRENT) {
623 					if (verify_dent(i_number << l2b,
624 							d_entry - 1) == 0) {
625 						d_entry --;
626 						print_dent(i_number << l2b,
627 							d_entry);
628 					}
629 				} else {
630 					count = 0; $$ = value--;
631 				}
632 			}
633 		| '-' WORD
634 			{
635 				uint64_t number;
636 
637 				if (check_and_get_int($2, &number) == 0) {
638 					count = 0;
639 					$$ = value - number;
640 				}
641 			}
642 		| '+' WORD
643 			{
644 				uint64_t number;
645 
646 				if (check_and_get_int($2, &number) == 0) {
647 					count = 0;
648 					$$ = value + number;
649 				}
650 			}
651 		| '*' WORD
652 			{
653 				uint64_t number;
654 
655 				if (check_and_get_int($2, &number) == 0) {
656 					count = 0;
657 					$$ = value * number;
658 				}
659 			}
660 		| '%' WORD
661 			{
662 				uint64_t number;
663 
664 				if (check_and_get_int($2, &number) == 0) {
665 					if (number == 0) {
666 						fprintf(stdout,
667 						gettext("Divide by zero ?\n"));
668 					} else {
669 						count = 0;
670 						$$ = value / number;
671 					}
672 				}
673 			}
674 		| expr '-' expr		{ count = 0; $$ = $1 - $3; }
675 		| expr '+' expr		{ count = 0; $$ = $1 + $3; }
676 		| expr '*' expr		{ count = 0; $$ = $1 * $3; }
677 		| expr '%' expr
678 			{
679 				if ($3 == 0) {
680 					fprintf(stdout,
681 						gettext("Divide by zero ?\n"));
682 				} else {
683 					$$ = $1 / $3;
684 				}
685 				count = 0;
686 			}
687 		| WORD
688 			{
689 				uint64_t number;
690 
691 				count = 0;
692 				if (check_and_get_int($1, &number) == 0) {
693 					$$ = number;
694 				}
695 			}
696 		;
697 
698 %%
699 
700 int32_t
701 check_and_get_int(uint8_t *str, uint64_t *value)
702 {
703 	int32_t length, cbase, index, cvalue;
704 
705 	*value = 0;
706 	length = strlen((caddr_t)str);
707 	/*
708 	 * Decide on what base to be used
709 	 * and strip off the base specifier
710 	 */
711 	if ((str[0] == '0') && (str[1] == 'x')) {
712 		cbase = 0x10;
713 		index = 2;
714 	} else if ((str[0] == '0') && (str[1] == 't')) {
715 		cbase = 0xa;
716 		index = 2;
717 	} else if (str[0] == '0') {
718 		cbase = 0x8;
719 		index = 1;
720 	} else {
721 		cbase = base;
722 		index = 0;
723 	}
724 
725 	/*
726 	 * Verify if the string is integer
727 	 * and convert to a binary value
728 	 */
729 	for ( ; index < length; index++) {
730 		if (cbase == 0x8) {
731 			if ((str[index] < '0') ||
732 				(str[index] > '7')) {
733 				fprintf(stdout,
734 					gettext("Invalid Octal Number %s\n"),
735 					str);
736 				return (1);
737 			}
738 			cvalue = str[index] - '0';
739 		} else if (cbase == 0xa) {
740 			if ((str[index] < '0') ||
741 				(str[index] > '9' )) {
742 				fprintf(stdout,
743 					gettext("Invalid Decimal Number %s\n"),
744 					str);
745 				return (1);
746 			}
747 			cvalue = str[index] - '0';
748 		} else {
749 			if ((str[index] >= '0') &&
750 					(str[index] <= '9')) {
751 				cvalue = str[index] - '0';
752 			} else if ((str[index] >= 'a') &&
753 					(str[index] <= 'f')) {
754 				cvalue = str[index] - 'a' + 10;
755 			} else if ((str[index] >= 'A') &&
756 					(str[index] <= 'F')) {
757 				cvalue = str[index] - 'A' + 10;
758 			} else {
759 				fprintf(stdout,
760 					gettext("Invalid Hex Number %s\n"),
761 					str);
762 				return (1);
763 			}
764 		}
765 		*value = *value * cbase + cvalue;
766 	}
767 	return (0);
768 }
769 
770 void print_prompt();
771 extern FILE *yyin;
772 
773 void
774 print_prompt()
775 {
776 	fprintf(stdout, gettext("%s"), prompt);
777 }
778 
779 int32_t
780 run_fsdb()
781 {
782 	yyin = stdin;
783 	if (yyparse() != 0)
784 		return (-1);
785 	return 0;
786 }
787