ia64/xen-unstable

view tools/xfrd/sxpr_parser.c @ 1820:3d4f8eb89670

bitkeeper revision 1.1106.1.2 (40faa780dekT3E5arFwcbQDu1MbX6g)

Cleaned up Xen's instruction emulator.
author kaf24@scramble.cl.cam.ac.uk
date Sun Jul 18 16:38:24 2004 +0000 (2004-07-18)
parents bae23a1177c6
children 4b6b3f4ac66d d6216cd62518
line source
2 #ifdef __KERNEL__
3 # include <linux/config.h>
4 # include <linux/module.h>
5 # include <linux/kernel.h>
6 # include <linux/string.h>
7 # include <linux/errno.h>
8 #else
9 # include <stdlib.h>
10 # include <errno.h>
11 #endif
13 #include "iostream.h"
14 #include "lexis.h"
15 #include "sxpr_parser.h"
16 #include "sys_string.h"
17 #include "enum.h"
19 /** @file
20 * Sxpr parsing.
21 *
22 * So that the parser does not leak memory, all sxprs constructed by
23 * the parser must be freed on error. On successful parse the sxpr
24 * returned becomes the responsibility of the caller.
25 *
26 * @author Mike Wray <mike.wray@hpl.hp.com>
27 */
29 #define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
30 #define printf(fmt, args...) IOStream_print(iostdout, fmt, ##args)
32 static void reset(Parser *z);
33 static int inputchar(Parser *p, char c);
34 static int savechar(Parser *p, char c);
35 extern void parse_error(Parser *in);
36 extern void parse_error_id(Parser *in, ParseErrorId id);
38 static int begin_start(Parser *p, char c);
39 static int state_start(Parser *p, char c);
40 static int end_start(Parser *p);
42 static int begin_comment(Parser *p, char c);
43 static int state_comment(Parser *p, char c);
44 static int end_comment(Parser *p);
46 static int begin_string(Parser *p, char c);
47 static int state_string(Parser *p, char c);
48 static int end_string(Parser *p);
49 static int state_escape(Parser *p, char c);
50 static int state_octal(Parser *p, char c);
51 static int state_hex(Parser *p, char c);
53 static int begin_atom(Parser *p, char c);
54 static int state_atom(Parser *p, char c);
55 static int end_atom(Parser *p);
57 static int state_list(Parser *p, char c);
58 static int begin_list(Parser *p, char c);
59 static int end_list(Parser *p);
61 /** Print a parse error.
62 *
63 * @param in parser
64 * @param msg format followed by printf arguments
65 */
66 void eprintf(Parser *in, char *msg, ...){
67 va_list args;
68 if(in->error_out){
69 va_start(args, msg);
70 IOStream_vprint(in->error_out, msg, args);
71 va_end(args);
72 }
73 }
75 /** Print a parse warning.
76 *
77 * @param in parser
78 * @param msg format followed by printf arguments
79 */
80 void wprintf(Parser *in, char *msg, ...){
81 va_list args;
82 if(in->error_out){
83 va_start(args, msg);
84 IOStream_vprint(in->error_out, msg, args);
85 va_end(args);
86 }
87 }
89 /*============================================================================*/
91 /** Record defining the message for a parse error. */
92 typedef struct {
93 ParseErrorId id;
94 char *message;
95 } ParseError;
97 /** Format for printing parse error messages. */
98 #define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
100 /** Message catalog for the parse error codes. */
101 static ParseError catalog[] = {
102 { PARSE_ERR_UNSPECIFIED, "unspecified error" },
103 { PARSE_ERR_NOMEM, "out of memory" },
104 { PARSE_ERR_UNEXPECTED_EOF, "unexpected end of input" },
105 { PARSE_ERR_TOKEN_TOO_LONG, "token too long" },
106 { PARSE_ERR_INVALID_SYNTAX, "syntax error" },
107 { PARSE_ERR_INVALID_ESCAPE, "invalid escape" },
108 { 0, NULL }
109 };
111 /** Number of entries in the message catalog. */
112 const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
114 void ParserState_free(ParserState *z){
115 if(!z) return;
116 objfree(z->val);
117 deallocate(z);
118 }
120 int ParserState_new(ParserStateFn *fn, char *name,
121 ParserState *parent, ParserState **val){
122 int err = 0;
123 ParserState *z;
124 z = ALLOCATE(ParserState);
125 if(z){
126 z->name = name;
127 z->fn = fn;
128 z->parent = parent;
129 z->val = ONULL;
130 } else {
131 err = -ENOMEM;
132 }
133 if(!err) *val = z;
134 return err;
135 }
137 /** Free a parser.
138 * No-op if the parser is null.
139 *
140 * @param z parser
141 */
142 void Parser_free(Parser *z){
143 if(!z) return;
144 objfree(z->val);
145 z->val = ONONE;
146 deallocate(z);
147 }
149 /** Create a new parser. The error stream defaults to null.
150 */
151 Parser * Parser_new(void){
152 Parser *z = ALLOCATE(Parser);
153 int err = -ENOMEM;
155 if(!z) goto exit;
156 err = 0;
157 reset(z);
158 exit:
159 if(err){
160 Parser_free(z);
161 z = NULL;
162 }
163 return z;
164 }
166 /** Get the next character.
167 * Records the character read in the parser,
168 * and sets the line and character counts.
169 *
170 * @param p parser
171 * @return error flag: 0 on success, non-zero on error
172 */
173 static int inputchar(Parser *p, char c){
174 int err = 0;
175 if(c=='\n'){
176 p->line_no++;
177 p->char_no = 0;
178 } else {
179 p->char_no++;
180 }
181 return err;
182 }
184 static int savechar(Parser *p, char c){
185 int err = 0;
186 if(p->buf_i >= p->buf_n){
187 err = -ENOMEM;
188 goto exit;
189 }
190 p->buf[p->buf_i] = c;
191 p->buf_i++;
192 exit:
193 return err;
194 }
196 int Parser_input_char(Parser *p, char c){
197 int err = 0;
198 if(at_eof(p)){
199 //skip;
200 } else {
201 inputchar(p, c);
202 }
203 if(!p->state){
204 err = begin_start(p, c);
205 if(err) goto exit;
206 }
207 err = p->state->fn(p, c);
208 exit:
209 return err;
210 }
212 int Parser_input_eof(Parser *p){
213 int err = 0;
214 p->eof = 1;
215 err = Parser_input_char(p, IOSTREAM_EOF);
216 return err;
217 }
219 int Parser_input(Parser *p, char *buf, int buf_n){
220 int err = 0;
221 int i = 0;
222 if(buf_n <= 0){
223 err = Parser_input_eof(p);
224 goto exit;
225 }
226 for(i = 0; i<buf_n; i++){
227 err = Parser_input_char(p, buf[i]);
228 if(err) goto exit;
229 }
230 exit:
231 err = (err < 0 ? err : buf_n);
232 return err;
233 }
235 int Parser_push(Parser *p, ParserStateFn *fn, char *name){
236 int err = 0;
237 err = ParserState_new(fn, name, p->state, &p->state);
238 return err;
239 }
241 int Parser_pop(Parser *p){
242 int err = 0;
243 ParserState *s = p->state;
244 p->state = s->parent;
245 ParserState_free(s);
246 return err;
247 }
249 int Parser_return(Parser *p){
250 int err = 0;
251 Sxpr val = ONONE;
252 if(!p->state){
253 err = -EINVAL;
254 goto exit;
255 }
256 val = p->state->val;
257 p->state->val = ONONE;
258 err = Parser_pop(p);
259 if(err) goto exit;
260 if(p->state){
261 err = cons_push(&p->state->val, val);
262 } else {
263 val = nrev(val);
264 p->val = val;
265 }
266 exit:
267 if(err){
268 objfree(val);
269 }
270 return err;
271 }
273 /** Determine if a character is a separator.
274 *
275 * @param p parser
276 * @param c character to test
277 * @return 1 if a separator, 0 otherwise
278 */
279 static int is_separator(Parser *p, char c){
280 return in_sep_class(c);
281 }
283 /** Return the current token.
284 * The return value points at the internal buffer, so
285 * it must not be modified (or freed). Use copy_token() if you need a copy.
286 *
287 * @param p parser
288 * @return token
289 */
290 char *peek_token(Parser *p){
291 return p->buf;
292 }
294 /** Return a copy of the current token.
295 * The returned value should be freed when finished with.
296 *
297 * @param p parser
298 * @return copy of token
299 */
300 char *copy_token(Parser *p){
301 return strdup(peek_token(p));
302 }
304 static int do_intern(Parser *p){
305 int err = 0;
306 Sxpr obj = intern(peek_token(p));
307 if(NOMEMP(obj)){
308 err = -ENOMEM;
309 } else {
310 p->state->val = obj;
311 }
312 return err;
313 }
315 static int do_string(Parser *p){
316 int err = 0;
317 Sxpr obj;
318 obj = string_new(peek_token(p));
319 if(NOMEMP(obj)){
320 err = -ENOMEM;
321 } else {
322 p->state->val = obj;
323 }
324 return err;
325 }
327 void newtoken(Parser *p){
328 memset(p->buf, 0, p->buf_n);
329 p->buf_i = 0;
330 p->tok_begin_line = p->line_no;
331 p->tok_begin_char = p->char_no;
332 }
334 int get_escape(char c, char *d){
335 int err = 0;
336 switch(c){
337 case 'a': *d = '\a'; break;
338 case 'b': *d = '\b'; break;
339 case 'f': *d = '\f'; break;
340 case 'n': *d = '\n'; break;
341 case 'r': *d = '\r'; break;
342 case 't': *d = '\t'; break;
343 case 'v': *d = '\v'; break;
344 case c_escape: *d = c_escape; break;
345 case c_single_quote: *d = c_single_quote; break;
346 case c_double_quote: *d = c_double_quote; break;
347 default:
348 err = -EINVAL;
349 }
350 return err;
351 }
353 int Parser_ready(Parser *p){
354 return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));
355 }
357 Sxpr Parser_get_val(Parser *p){
358 Sxpr v = ONONE;
359 if(CONSP(p->val)){
360 v = CAR(p->val);
361 p->val = CDR(p->val);
362 } else if (CONSP(p->start_state->val)){
363 p->val = p->start_state->val;
364 p->val = nrev(p->val);
365 p->start_state->val = ONULL;
366 v = CAR(p->val);
367 p->val = CDR(p->val);
368 }
369 return v;
370 }
372 Sxpr Parser_get_all(Parser *p){
373 Sxpr v = ONULL;
374 if(CONSP(p->val)){
375 v = p->val;
376 p->val = ONONE;
377 } else if(CONSP(p->start_state->val)){
378 v = p->start_state->val;
379 p->start_state->val = ONULL;
380 v = nrev(v);
381 }
382 return v;
383 }
385 int begin_start(Parser *p, char c){
386 int err = 0;
387 err = Parser_push(p, state_start, "start");
388 if(err) goto exit;
389 p->start_state = p->state;
390 exit:
391 return err;
392 }
394 int state_start(Parser *p, char c){
395 int err = 0;
396 if(at_eof(p)){
397 err = end_start(p);
398 } else if(in_space_class(c)){
399 //skip
400 } else if(in_comment_class(c)){
401 begin_comment(p, c);
402 } else if(c == c_list_open){
403 begin_list(p, c);
404 } else if(c == c_list_close){
405 parse_error(p);
406 err = -EINVAL;
407 } else if(in_string_quote_class(c)){
408 begin_string(p, c);
409 } else if(in_printable_class(c)){
410 begin_atom(p, c);
411 } else if(c == 0x04){
412 //ctrl-D, EOT: end-of-text.
413 Parser_input_eof(p);
414 } else {
415 parse_error(p);
416 err = -EINVAL;
417 }
418 return err;
419 }
421 int end_start(Parser *p){
422 int err = 0;
423 err = Parser_return(p);
424 return err;
425 }
427 int begin_comment(Parser *p, char c){
428 int err = 0;
429 err = Parser_push(p, state_comment, "comment");
430 if(err) goto exit;
431 err = inputchar(p, c);
432 exit:
433 return err;
434 }
436 int state_comment(Parser *p, char c){
437 int err = 0;
438 if(c == '\n' || at_eof(p)){
439 err = end_comment(p);
440 } else {
441 err = inputchar(p, c);
442 }
443 return err;
444 }
446 int end_comment(Parser *p){
447 return Parser_pop(p);
448 }
450 int begin_string(Parser *p, char c){
451 int err = 0;
452 err = Parser_push(p, state_string, "string");
453 if(err) goto exit;
454 newtoken(p);
455 p->state->delim = c;
456 exit:
457 return err;
458 }
460 int state_string(Parser *p, char c){
461 int err = 0;
462 if(at_eof(p)){
463 parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
464 err = -EINVAL;
465 } else if(c == p->state->delim){
466 err = end_string(p);
467 } else if(c == '\\'){
468 err = Parser_push(p, state_escape, "escape");
469 } else {
470 err = savechar(p, c);
471 }
472 return err;
473 }
475 int end_string(Parser *p){
476 int err = 0;
477 err = do_string(p);
478 if(err) goto exit;
479 err = Parser_return(p);
480 exit:
481 return err;
482 }
484 int state_escape(Parser *p, char c){
485 int err = 0;
486 char d;
487 if(at_eof(p)){
488 parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
489 err = -EINVAL;
490 goto exit;
491 }
492 if(get_escape(c, &d) == 0){
493 err = savechar(p, d);
494 if(err) goto exit;
495 err = Parser_pop(p);
496 } else if(c == 'x'){
497 p->state->fn = state_hex;
498 p->state->ival = 0;
499 p->state->count = 0;
500 } else {
501 p->state->fn = state_octal;
502 p->state->ival = 0;
503 p->state->count = 0;
504 err = Parser_input_char(p, c);
505 }
506 exit:
507 return err;
508 }
510 int octaldone(Parser *p){
511 int err = 0;
512 char d = (char)(p->state->ival & 0xff);
513 err = Parser_pop(p);
514 if(err) goto exit;
515 err = Parser_input_char(p, d);
516 exit:
517 return err;
518 }
520 int octaldigit(Parser *p, char c){
521 int err = 0;
522 p->state->ival *= 8;
523 p->state->ival += c - '0';
524 p->state->count++;
525 if(err) goto exit;
526 if(p->state->ival < 0 || p->state->ival > 0xff){
527 parse_error(p);
528 err = -EINVAL;
529 goto exit;
530 }
531 if(p->state->count == 3){
532 err = octaldone(p);
533 }
534 exit:
535 return err;
536 }
538 int state_octal(Parser *p, char c){
539 int err = 0;
540 if(at_eof(p)){
541 parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
542 err = -EINVAL;
543 goto exit;
544 } else if('0' <= c && c <= '7'){
545 err = octaldigit(p, c);
546 } else {
547 err = octaldone(p);
548 if(err) goto exit;
549 Parser_input_char(p, c);
550 }
551 exit:
552 return err;
553 }
555 int hexdone(Parser *p){
556 int err = 0;
557 char d = (char)(p->state->ival & 0xff);
558 err = Parser_pop(p);
559 if(err) goto exit;
560 err = Parser_input_char(p, d);
561 exit:
562 return err;
563 }
565 int hexdigit(Parser *p, char c, char d){
566 int err = 0;
567 p->state->ival *= 16;
568 p->state->ival += c - d;
569 p->state->count++;
570 if(err) goto exit;
571 if(p->state->ival < 0 || p->state->ival > 0xff){
572 parse_error(p);
573 err = -EINVAL;
574 goto exit;
575 }
576 if(p->state->count == 2){
577 err = hexdone(p);
578 }
579 exit:
580 return err;
581 }
583 int state_hex(Parser *p, char c){
584 int err = 0;
585 if(at_eof(p)){
586 parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
587 err = -EINVAL;
588 goto exit;
589 } else if('0' <= c && c <= '9'){
590 err = hexdigit(p, c, '0');
591 } else if('A' <= c && c <= 'F'){
592 err = hexdigit(p, c, 'A');
593 } else if('a' <= c && c <= 'f'){
594 err = hexdigit(p, c, 'a');
595 } else if(p->state->count){
596 err =hexdone(p);
597 if(err) goto exit;
598 Parser_input_char(p, c);
599 }
600 exit:
601 return err;
602 }
604 int begin_atom(Parser *p, char c){
605 int err = 0;
606 err = Parser_push(p, state_atom, "atom");
607 if(err) goto exit;
608 newtoken(p);
609 err = savechar(p, c);
610 exit:
611 return err;
612 }
614 int state_atom(Parser *p, char c){
615 int err = 0;
616 if(at_eof(p)){
617 err = end_atom(p);
618 } else if(is_separator(p, c) ||
619 in_space_class(c) ||
620 in_comment_class(c)){
621 err = end_atom(p);
622 if(err) goto exit;
623 err = Parser_input_char(p, c);
624 } else {
625 err = savechar(p, c);
626 }
627 exit:
628 return err;
629 }
631 int end_atom(Parser *p){
632 int err = 0;
633 err = do_intern(p);
634 if(err) goto exit;
635 err = Parser_return(p);
636 exit:
637 return err;
638 }
640 int state_list(Parser *p, char c){
641 int err = 0;
642 if(at_eof(p)){
643 parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
644 err = -EINVAL;
645 } else if(c == c_list_close){
646 p->state->val = nrev(p->state->val);
647 err = end_list(p);
648 } else {
649 err = state_start(p, c);
650 }
651 return err;
653 }
655 int begin_list(Parser *p, char c){
656 return Parser_push(p, state_list, "list");
657 }
659 int end_list(Parser *p){
660 return Parser_return(p);
661 }
663 /** Reset the fields of a parser to initial values.
664 *
665 * @param z parser
666 */
667 static void reset(Parser *z){
668 IOStream *error_out = z->error_out;
669 int flags = z->flags;
670 memzero(z, sizeof(Parser));
671 z->buf_n = sizeof(z->buf) - 1;
672 z->buf_i = 0;
673 z->line_no = 1;
674 z->char_no = 0;
675 z->error_out = error_out;
676 z->flags = flags;
677 }
679 /** Set the parser error stream.
680 * Parse errors are reported on the the error stream if it is non-null.
681 *
682 * @param z parser
683 * @param error_out error stream
684 */
685 void set_error_stream(Parser *z, IOStream *error_out){
686 if(z){
687 z->error_out = error_out;
688 }
689 }
691 /** Get the parser error message for an error code.
692 *
693 * @param id error code
694 * @return error message (empty string if the code is unknown)
695 */
696 static char *get_message(ParseErrorId id){
697 int i;
698 for(i=0; i<catalog_n; i++){
699 if(id == catalog[i].id){
700 return catalog[i].message;
701 }
702 }
703 return "";
704 }
706 /** Get the line number.
707 *
708 * @param in parser
709 */
710 int get_line(Parser *in){
711 return in->line_no;
712 }
714 /** Get the column number.
715 *
716 * @param in parser
717 */
718 int get_column(Parser *in){
719 return in->char_no;
720 }
722 /** Get the line number the current token started on.
723 *
724 * @param in parser
725 */
726 int get_tok_line(Parser *in){
727 return in->tok_begin_line;
728 }
730 /** Get the column number the current token started on.
731 *
732 * @param in parser
733 */
734 int get_tok_column(Parser *in){
735 return in->tok_begin_char;
736 }
738 /** Report a parse error.
739 * Does nothing if the error stream is null or there is no error.
740 *
741 * @param in parser
742 */
743 static void report_error(Parser *in){
744 if(in->error_out && in->err){
745 char *msg = get_message(in->err);
746 char *tok = peek_token(in);
747 IOStream_print(in->error_out, PARSE_ERR_FMT,
748 get_tok_line(in), get_tok_column(in), msg);
749 if(tok && tok[0]){
750 IOStream_print(in->error_out, " '%s'", tok);
751 }
752 IOStream_print(in->error_out, "\n");
753 }
754 }
756 /** Get the error message for the current parse error code.
757 * Does nothing if there is no error.
758 *
759 * @param in parser
760 * @param buf where to place the message
761 * @param n maximum number of characters to place in buf
762 * @return current error code (zero for no error)
763 */
764 int parse_error_message(Parser *in, char *buf, int n){
765 if(in->err){
766 char *msg = get_message(in->err);
767 snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
768 }
769 return in->err;
770 }
772 /** Flag an unspecified parse error. All subsequent reads will fail.
773 *
774 * @param in parser
775 */
776 void parse_error(Parser *in){
777 parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
778 }
780 /** Flag a parse error. All subsequent reads will fail.
781 * Does not change the parser error code if it is already set.
782 *
783 * @param in parser
784 * @param id error code
785 */
786 void parse_error_id(Parser *in, ParseErrorId id){
787 if(!in->err){
788 in->err = id;
789 report_error(in);
790 }
791 }
793 /** Test if the parser's error flag is set.
794 *
795 * @param in parser
796 * @return 1 if set, 0 otherwise
797 */
798 int has_error(Parser *in){
799 return (in->err > 0);
800 }
802 /** Test if the parser is at end of input.
803 *
804 * @param in parser
805 * @return 1 if at EOF, 0 otherwise
806 */
807 int at_eof(Parser *p){
808 return p->eof;
809 }
811 //#define SXPR_PARSER_MAIN
812 #ifdef SXPR_PARSER_MAIN
813 /* Stuff for standalone testing. */
815 #include "file_stream.h"
816 #include "string_stream.h"
818 int stringof(Sxpr exp, char **s){
819 int err = 0;
820 if(ATOMP(exp)){
821 *s = atom_name(exp);
822 } else if(STRINGP(exp)){
823 *s = string_string(exp);
824 } else {
825 err = -EINVAL;
826 *s = NULL;
827 }
828 return err;
829 }
831 int child_string(Sxpr exp, Sxpr key, char **s){
832 int err = 0;
833 Sxpr val = sxpr_child_value(exp, key, ONONE);
834 err = stringof(val, s);
835 return err;
836 }
838 int intof(Sxpr exp, int *v){
839 int err = 0;
840 char *s;
841 unsigned long l;
842 if(INTP(exp)){
843 *v = OBJ_INT(exp);
844 } else {
845 err = stringof(exp, &s);
846 if(err) goto exit;
847 err = convert_atoul(s, &l);
848 *v = (int)l;
849 }
850 exit:
851 return err;
852 }
854 int child_int(Sxpr exp, Sxpr key, int *v){
855 int err = 0;
856 Sxpr val = sxpr_child_value(exp, key, ONONE);
857 err = intof(val, v);
858 return err;
859 }
861 int eval_vnet(Sxpr exp){
862 int err = 0;
863 Sxpr oid = intern("id");
864 int id;
865 err = child_int(exp, oid, &id);
866 if(err) goto exit;
867 dprintf("> vnet id=%d\n", id);
868 exit:
869 dprintf("< err=%d\n", err);
870 return err;
871 }
873 int eval_connect(Sxpr exp){
874 int err = 0;
875 Sxpr ovif = intern("vif");
876 Sxpr ovnet = intern("vnet");
877 char *vif;
878 int vnet;
880 err = child_string(exp, ovif, &vif);
881 if(err) goto exit;
882 err = child_int(exp, ovnet, &vnet);
883 if(err) goto exit;
884 dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
885 exit:
886 dprintf("< err=%d\n", err);
887 return err;
888 }
890 int eval(Sxpr exp){
891 int err = 0;
892 Sxpr oconnect = intern("connect");
893 Sxpr ovnet = intern("vnet");
895 if(sxpr_elementp(exp, ovnet)){
896 err = eval_vnet(exp);
897 } else if(sxpr_elementp(exp, oconnect)){
898 err = eval_connect(exp);
899 } else {
900 err = -EINVAL;
901 }
902 return err;
903 }
905 /** Main program for testing.
906 * Parses input and prints it.
907 *
908 * @param argc number of arguments
909 * @param argv arguments
910 * @return error code
911 */
912 int main(int argc, char *argv[]){
913 Parser *pin;
914 int err = 0;
915 char buf[1024];
916 int k;
917 Sxpr obj;
918 //Sxpr l, x;
919 int i = 0;
921 pin = Parser_new();
922 set_error_stream(pin, iostdout);
923 dprintf("> parse...\n");
924 while(1){
925 k = fread(buf, 1, 1, stdin);
926 err = Parser_input(pin, buf, k);
927 while(Parser_ready(pin)){
928 obj = Parser_get_val(pin);
929 printf("obj %d\n", i++);
930 objprint(iostdout, obj, 0); printf("\n");
931 }
932 if(k <= 0) break;
933 }
934 /* obj = Parser_get_all(pin); */
935 /* for(l = obj ; CONSP(l); l = CDR(l)){ */
936 /* x = CAR(l); */
937 /* objprint(iostdout, x, 0); printf("\n"); */
938 /* eval(x); */
939 /* } */
940 dprintf("> err=%d\n", err);
941 return 0;
942 }
943 #endif