frank@odetics.com (Frank Merrow) (11/15/90)
I am pretty good at shell, but this one has me a little stumped: I am running a command out of "make" so the condition code is important in what I am doing . . . Step 1 gcc <parms> || (abort_script;exit 1) This statement lets me do some post processing when the compiler finds an error. Step 2 gcc is generating a SINGLE warning message that I want to suppress, BUT I want the warning in all cases except for one VERY special one. So what I want to do is something like: gcc <parms> 2>&1 | egrep -v "<re>" This has problems because the condition code that make seems to use is the one from the egrep NOT the gcc. Problem: Conceptually what I want is something like: gcc <parms> 2>&1 | egrep -v "<re>" || (abort_script;exit 1) Except that I want the || to use the condition code from the gcc (NOT the egrep) AND I want the condition code of the whole expression to be OK if the compile is OK or ERROR if the compile has an error. Note one possible solution I thought of was gcc <parms> 2>&1 > temp_file || (abort_script;exit1) egrep -v "<re>" temp_file The problem with this solution is that on Error the errors do NOT appear on stdout because the egrep doesn't get done. Another solution is to actually put a compound "if" shell statement in the makefile. My make does support this, but I personally think it looks tacky and would prefer to avoid this solution. Any shell wizards got a slick solution to this? Frank frank@odetics.com or uunet!odetics!frank
maart@cs.vu.nl (Maarten Litmaath) (11/21/90)
)... )gcc <parms> 2>&1 | egrep -v "<re>" ) )This has problems because the condition code that make seems to use is the )one from the egrep NOT the gcc. To obtain the exit status of a command in the middle of a pipeline you have to resort to things like this: a | b | (c; echo $? > /tmp/ecode$$) | d | e if [ `cat /tmp/ecode$$` != 0 ] ... If your OS supports named pipes (FIFOs) you could do this: TMPFIFO=/tmp/myfifo mknod $TMPFIFO p a | b | c > $TMPFIFO & < $TMPFIFO d | e wait $! echo "The exit status of c is $?" Still an ugly temp file hack. To avoid the temp file there's this gross construct: exec 3>&1 # Make file descriptor 3 a duplicate of stdout. # Below: make fd 4 a dup of the new stdout, i.e. the output stream # that's being captured. # Then execute each but the last component of the pipeline with # fd 3 closed; fd 4 is closed for each component but the one whose # exit status we want to capture. # The exit status is echoed to the remembered captured stdout. # Before the last component of the pipeline is started, its stdout # is connected to the original stdout, after which fd 3 can be # closed for this command as well. status=` exec 4>&1 a 4>&- 3>&- | b 4>&- 3>&- | (c 4>&-; echo $? >&4) 3>&- | d 4>&- 3>&- | e 4>&- >&3 3>&- ` exec 3>&- # We don't need it anymore. echo "The exit status of c is $status" In the case of a Makefile, however, we can easily avoid this whole mess: # Makefile for target target: dependencies (gcc <parms> 2>&1 || kill $$$$) | egrep -v "<re>" Make sure the final part of the pipeline doesn't exit without having read all of the output of the first stage, else the latter might be killed with a SIGPIPE, as illustrated in the following example: foo: (cat /etc/termcap; kill $$$$) | true Furthermore to prevent the `egrep' from getting killed instead of the shell started by `make', you may want to use this instead: (gcc <parms> 2>&1 || kill $$$$) | (egrep -v "<re>"; true) -- nreadwin@micrognosis.co.uk (Neil Readwin) on "snuff" films: "Seen one ? I was *in* one. They tortured me horribly and then killed me with a single shot in the back of the head ! Following total brain death I gave up acting and became a VMS hacker."
jan@golf.canberra.edu.au (Jan Newmarch) (11/21/90)
>Conceptually what I want is something like: >gcc <parms> 2>&1 | egrep -v "<re>" || (abort_script;exit 1) >Except that I want the || to use the condition code from the gcc (NOT the egrep) >AND I want the condition code of the whole expression to be OK if the compile >is OK or ERROR if the compile has an error. The shell variable `?' holds the exit code of the last instruction executed, so you could run your gcc, save the exit code, run egrep and the exit: gcc > ... code=$? egrep ... exit $code +----------------------+---+ Jan Newmarch, Information Science and Engineering, University of Canberra, PO Box 1, Belconnen, Act 2616 Australia. Tel: (Aust) 6-2522422. Fax: (Aust) 6-2522999 ACSnet: jan@ise.canberra.edu.au ARPA: jan%ise.canberra.edu.au@uunet.uu.net UUCP: {uunet,ukc}!munnari!ise.canberra.edu.au!jan JANET: jan%au.edu.canberra.ise@EAN-RELAY +--------------------------+
hartman@ide.com (Robert Hartman) (11/21/90)
In article <2258@megadon.UUCP> uunet!odetics!frank (Frank Merrow) writes: >... >I am running a command out of "make" so the condition code is important in what >I am doing . . . > >Step 1 > >gcc <parms> || (abort_script;exit 1) > >This statement lets me do some post processing when the compiler finds an error. > >Step 2 > >gcc is generating a SINGLE warning message that I want to suppress, BUT I want >the warning in all cases except for one VERY special one. ... [deleted discussion of options for getting around fact that return code from a pipeline is that of the last command in the pipeline] This seems like the wrong tack to me. I'd suggest putting the code to filter out the undesired instances of the error message in the post-processing script, invoking it as follows: gcc ... 2>&1 gcc.out || (abort_script < gcc.out; exit 1) Between make and the shell there are all sorts of clever things a person can do. However, it is often best not to (as anyone who's had to modify some of _my_ early makefiles will agree). -r