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