Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!spool.mu.edu!sdd.hp.com!zaphod.mps.ohio-state.edu!ncar!gatech!usenet.ins.cwru.edu!odin!chet From: chet@odin.INS.CWRU.Edu (Chet Ramey) Newsgroups: comp.unix.shell Subject: Re: Bourne Shell bug? Have a look.. Message-ID: <1991Jan31.161817.16865@usenet.ins.cwru.edu> Date: 31 Jan 91 16:18:17 GMT References: <1991Jan16.152933.7288@usenet.ins.cwru.edu> <1991Jan16.153557.15548@ms.uky.edu> <1067@mwtech.UUCP> Sender: news@usenet.ins.cwru.edu Reply-To: chet@po.CWRU.Edu Organization: Case Western Reserve Univ. Cleveland, Ohio, (USA) Lines: 84 Nntp-Posting-Host: odin.ins.cwru.edu In article <1067@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes: >You further know (or again you just learn it), that there can be more >than one redirection per line: > > echo hello >file foo >baz > >Now: Which redirection is the one that is finally in effect when the >programm (the `echo' in the above example) runs, if you combine both >of the above "strange" ways to do I/O-direction? (What I want is not >the answer to a specific example, but the general rule!) I'll post the >answer in a week or so if noone solves this). That command will leave `baz' empty and "hello foo" in `file', but this is wrong. I claim that the general rule that Martin is asking for is in fact a bug in sh, and a long-standing one at that. Consider that echo hello foo > file > baz leaves `file' empty and "hello foo" in `baz'. According to the sh `grammar', and the claim that redirections may appear anywhere in a command, this command and Martin's should produce identical results. I'll bet that the presence of the word `foo' between the redirections in Martin's example somehow causes sh not to reverse the chain of redirections that it builds, so that `file' is active when the command is run. Here is an example of what I consider correct behavior. When bash processes the command line that Martin gave, to use an example I'm familiar with, it separates the redirections from the command words right away, in the yacc grammar actions. Bash incrementally builds a chain of redirections by processing left to right. (This is what Posix specifies, though the language in the 1003.2 draft is `beginning to end'.) Bash builds the chain in a rather inefficient manner, appending each redirection to the chain already built. If bash simply appended the chain to the redirection, the chain would need to be reversed to have redirections processed in the proper order, and bash would have to do this before processing any of them when it is time to exec the command. This is the piece of the yacc grammar that accomplishes that (lots and lots of essential support code and other rules omitted): redirections: redirection { $$ = $1; } | redirections redirection { register REDIRECT *t = $1; while (t->next) t = t->next; t->next = $2; $$ = $1; } ; Sh obviously wants to do something like this, as evidenced by the supposed equivalent command I wrote above, but does not when presented with the command Martin used. I say it's a bug. Bash, ash, ksh-86, and ksh-88 agree with me. All AT&T versions of sh up to and including V.3.2 do not. Another thing: sh allows redirections anywhere in the command only for a simple command. For example: slc2$ sh slc2$ > foo for i in 1 2 3 for: not found slc2$ >foo echo hello slc2$ cat foo hello slc2$ Chet -- Chet Ramey ``There's just no surf in Network Services Group Cleveland, U.S.A. ...'' Case Western Reserve University chet@ins.CWRU.Edu My opinions are just those, and mine alone.