mcvoy@rsch.WISC.EDU (Lawrence W. McVoy) (11/20/86)
Hi there. I'm using lex & yacc to do some work for me and I can't quite get it. The scanner & parser part works, but only if it's getting input from stdin. I diddled lex.yy.c to change the getc(yyin) call in the input() define to call my routine which feed sit characters from argv. This works if I call yylex() from main, but if yyparse calls it then I get a "syntax error". The same program works if I don't diddle the input() routine. And I can't figure out what's wrong with my diddling..... So, I'm stuck. Does anyone have a cute way to feed a short byte stream to stdin backwards? Or a better solution? I'm not willing to do anything as kludgey as #!/bin/sh cat << EOF | my_problem_program $* EOF But that is _exactly_ what I want to do, only faster (no sh start up). I suppose I could do the fork() and feed the child the command line as stdin, but even that is sort of yucko. All suggestions welcome, and apologies to unix-wizards, but I figure you don't read unix-questions anymore :-( -- Larry McVoy mcvoy@rsch.wisc.edu, {seismo, topaz, harvard, ihnp4, etc}!uwvax!mcvoy "They're coming soon! Quad-stated guru-gates!"
grady@ic.Berkeley.EDU (Steven Grady) (11/20/86)
I hope someone comes up with a good solution, because I'm not satisfied with the way I had to handle it: #include <stdio.h> /* Make a file pointer point to a string */ FILE * set_fp_to_str(fp, str) FILE *fp; char *str; { /* Check out the src to sscanf, etc, for more fun.. */ fp->_flag = _IOREAD|_IOSTRG; fp->_ptr = fp->_base = str; fp->_cnt = 0; while (*str++) { fp->_cnt++; } fp->_bufsiz = fp->_cnt; return(fp); } /* Use yyparse() on a string */ foo(str) char *str; { FILE tmp; /* Save old value of stdin */ tmp = *stdin; set_fp_to_str(stdin, str); yyresult = yyparse(); *stdin = tmp; }
scabel@diku.UUCP (11/21/86)
In article <2972@rsch.WISC.EDU> mcvoy@rsch.WISC.EDU (Lawrence W. McVoy) writes: >Hi there. I'm using lex & yacc to do some work for me and I can't >quite get it. The scanner & parser part works, but only if it's >getting input from stdin. I diddled lex.yy.c to change the getc(yyin) >call in the input() define to call my routine which feed sit characters >from argv. This works if I call yylex() from main, but if yyparse calls >it then I get a "syntax error". The same program works if I don't >diddle the input() routine. And I can't figure out what's wrong >with my diddling..... I have made a program using lex and yacc, which either reads from a argument to the program, or from stdin. Here is the important parts from the lex file.. %C %{ #ifdef input #undef input #endif # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):nextchar())==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) extern int ARGEXPR; extern char *argexpr; %} %% /* The lex program */ %% int nextchar() { static int i = 0; if (ARGEXPR) { if (*argexpr == '\0') return(i++ == 0?'\n':EOF); return(*argexpr++); } else return(getc(yyin)); } -- Niels Schachtschabel, Institute of Datalogy, University of Copenhagen E-mail: scabel@diku.uucp / ...!seismo!mcvax!diku!scabel
mouse@mcgill-vision.UUCP (11/23/86)
In article <2972@rsch.WISC.EDU>, mcvoy@rsch.WISC.EDU (Lawrence W. McVoy) writes: > So, I'm stuck. Does anyone have a cute way to feed a short byte stream > to stdin backwards? Or a better solution? I'm not willing to do > anything as kludgey as [shell script hack] This situation is made-to-order for one of my stdio extensions: FILE *fopenstr(str,len,mode) char *str; int len; char *mode; which produces a stdio stream which reads from or writes into (according as mode is "r" or "w") the given string. For BSD systems at least, this is easy (I believe someone already posted pretty much what is necessary). I don't know how easy it would be on a USG system. There's also fopenfxn(), which makes stdio call a specified function whenever it wants a character - with this you can build anything you want. der Mouse USA: {ihnp4,decvax,akgua,utzoo,etc}!utcsri!mcgill-vision!mouse think!mosart!mcgill-vision!mouse Europe: mcvax!decvax!utcsri!mcgill-vision!mouse ARPAnet: think!mosart!mcgill-vision!mouse@harvard.harvard.edu [USA NSA food: terrorist, cryptography, DES, drugs, CIA, secret, decode]
jimbi@copper.UUCP (Jim Bigelow) (12/01/86)
In article <2972@rsch.WISC.EDU>, mcvoy@rsch.WISC.EDU (Lawrence W. McVoy) writes: > Hi there. I'm using lex & yacc to do some work for me and I can't > quite get it. The scanner & parser part works, but only if it's > getting input from stdin. I diddled lex.yy.c to change the getc(yyin) > call in the input() define to call my routine which feed sit characters > from argv. This works if I call yylex() from main, but if yyparse calls One method I haven't seen posted yet is to fopen a file name from argv and give yyin the value: /* * main -- read command line params, open/process/close files */ #include <stdio.h> extern FILE *yyin; /* input to lexical analyzer */ extern char *func_name; extern char *optarg; /* used and set by getopt */ extern int optind; opterr; int Debug = 0; /* debug flag */ int Verbose = 0; /* verbose flag */ usage(name) char *name; { printf("Usage: %s [-lnv] func_name [file...]\n", name); } main (argc, argv) int argc; char **argv; { int c; while((c = getopt(argc, argv, "lnvdp:")) != EOF) switch(c) { case 'v': Verbose = 1; break; case 'd': Debug = 1; break; case '?': usage(argv[0]); exit(1); break; } if(optind == argc) yylex(); else for(; optind < argc; optind++) { if(( yyin = fopen(argv[optind], "r"))== NULL) { printf("%s: cannot open %s\n",argv[0], argv[optind]); } else { yylex(); fclose(yyin); } } }
mikes@apple.UUCP (Mike Shannon) (12/03/86)
To people using yacc & lex and trying to read from a file, not stdin, you should note that in the code generated by lex for reading a character, a call is made to getc(yyin). yyin is simply a variable statically initialized to be stdin, but you can *easily* re-assign it via a call to fopen(), as in yyin = fopen(argv[1]) or some such. Look at the code generated by these tools! It's easy to change it! -- Michael Shannon {apple!mikes}
mcvoy@rsch.WISC.EDU (Lawrence W. McVoy) (12/04/86)
In article <347@apple.UUCP> mikes@apple.UUCP (Mike Shannon) writes: >To people using yacc & lex and trying to read from a file, not stdin, >you should note that in the code generated by lex for reading a character, >a call is made to getc(yyin). > yyin is simply a variable statically initialized to be stdin, but >you can *easily* re-assign it via a call to fopen(), as in > yyin = fopen(argv[1]) > or some such. I've seen one too many of these float by to take it any more. Please read what I asked in the first place and answer that. Your answers imply that I'm an idiot. While that is sometimes true, it's not the case here: From the original posting: Subject: Re: argv ==> stdin (fast) Keywords: make the commandline look like a file? ^^^^^^^^^^^ I am _NOT_ asking how to use fopen. Jeez. I'm asking how to make the characters typed on the command line look like they are in a file. From the point of view of lex/yacc. For example if I said % a.out 1+2/3 I want lex to see '1', '+', '2', '/', '3' EOF By the way, I have a zillion solutions, and thanks go out to all who replied. The best one said "get a pipe, stuff argv into it, close stdin, dup the read side of the pipe". Sorry, I can't remember who sent it, but thanks anyways... > Look at the code generated by these tools! It's easy to change it! >-- > Michael Shannon {apple!mikes} Look at the posting generated by these fingers! It's easy to read! -- Larry McVoy mcvoy@rsch.wisc.edu, {seismo, topaz, harvard, ihnp4, etc}!uwvax!mcvoy "They're coming soon! Quad-stated guru-gates!"