Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!mnetor!seismo!uwvax!mcvoy From: mcvoy@uwvax.UUCP Newsgroups: comp.unix.questions Subject: Re: argv ==> stdin, got it Message-ID: <2982@rsch.WISC.EDU> Date: Fri, 21-Nov-86 23:11:33 EST Article-I.D.: rsch.2982 Posted: Fri Nov 21 23:11:33 1986 Date-Received: Sat, 22-Nov-86 06:52:30 EST Organization: U of Wisconsin CS Dept Lines: 74 Summary: A better way In article <4379@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >In article <2976@rsch.WISC.EDU> mcvoy@rsch.WISC.EDU (Lawrence W. McVoy) writes: >>/* >> * code to fork a child and have control of the child's stdin/out >> * from usenet. Works. Fast, too. The idea is that the command line >> * is fed to the stdin of the child. This is so that you don't have >> * to f*ck with the stupid code in y.tab.c or lex.yy.c. It should work ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >> * for anything that wants stdin. >> */ > >So what is so hard about making lex read argv rather than stdin? >Here is a trivial parser that accepts only `foo bar;'. Note that >the semicolon must be quoted to protect it from the shell. [ about 100 lines of code deleted, showing how to make lex take input from argv ] Well, I tried something like that. It works fine with lex, but not with yacc. Yacc must actually diddle various input buffers and just redefining the input and unput routines was not enough to make it fly. Now, I know the hackers out there (such as chris) are going to say, "look, it's easy. All you have to do is be intimately familiar with the way lex & yacc interact. And it's only about 20 lines of code spread over lex.yy.c, y.tab.c, and /usr/src/usr.lib/libl/somefile." Well, a better solution has been suggested. Just use a pipe and send the command line into the pipe. As someone pointed out, for a cl you don't even have to fork, the pipe is big enough to buffer it up. Here's the code, and thanks for all the help... # include # define write_end in[1] # define read_end in[0] /* * code to stuff the command line into a pipe and then call a function that * expects input from stdin. * suggested by - aweinste@diamond.bbn.com * Bugs - the cl had better be smaller tthan the pipe or this code * will hang (blocked on the write). */ main(argc, argv) char** argv; { int in[2]; int i; /* set it up so that stdin is the read side of pipe (in[1]) */ pipe(in); close(0); dup(read_end); /* stdin <-- pipe */ close(read_end); /* don't need this (now extra) fd */ /* stuff the cl into the write side of the pipe */ for (i=1; i