marty@wuphys.UUCP (Marty Olevitch) (07/10/89)
It appears that csh does not correctly handle nested if-then-else statements. The following script illustrates the problem, which appears in versions of csh on MORE/bsd (mt Xinu 4.3), SunOS 3.1, SunOS 4.0, and Ultrix 2.0. Am I missing some bug in this script? If not, it looks like a bug in csh (an equivalent sh program works fine). #! /bin/csh set v1 = $1 set v2 = $2 echo "v1 = $v1 and v2 = $v2" if($v1 == 1) then echo checkpoint 1 if($v2 == 1) then echo 11 else echo 12 endif echo checkpoint 2 else echo checkpoint 3 if($v2 == 1) then echo 21 else echo 22 endif echo checkpoint 4 endif Here is a little chart showing the command lines issued, the expected results, and the actual results. command line expect get ------------ ------ ------- iftest 1 1 checkpoint 1 checkpoint 1 11 11 checkpoint 2 checkpoint 2 checkpoint 4 iftest 1 2 checkpoint 1 checkpoint 1 12 12 checkpoint 2 checkpoint 2 checkpoint 4 iftest 2 1 checkpoint 3 12 21 checkpoint 2 checkpoint 4 checkpoint 4 iftest 2 2 checkpoint 3 12 22 checkpoint 2 checkpoint 4 checkpoint 4 Marty Olevitch Internet: marty@wuphys.wustl.edu Washington University UUCP: uunet!wugate!wuphys!marty Physics Department, Campus Box 1105 Bitnet: marty@wuphys.WUSTL St Louis MO 63130 USA Tel: (314) 889-6285
tale@pawl.rpi.edu (David C Lawrence) (07/11/89)
In <685@wuphys.UUCP> marty@wuphys.UUCP (Marty Olevitch) writes:
Marty> It appears that csh does not correctly handle nested if-then-else
Marty> statements. The following script illustrates the problem, which appears
Marty> in versions of csh on MORE/bsd (mt Xinu 4.3), SunOS 3.1, SunOS 4.0, and
Marty> Ultrix 2.0. Am I missing some bug in this script? If not, it looks like
Marty> a bug in csh (an equivalent sh program works fine).
Yes it's a bug, no it's not a bug. It's one of those ambivalent
things. If you know what it is, you adjust your style by one
character or so and life goes on correctly again.
Major hacking on the script follows ...
Marty> #! /bin/csh
[...]
Marty> if($v1 == 1) then
Marty> echo checkpoint 1
Marty> if($v2 == 1) then
[...]
Marty> if($v2 == 1) then
[...]
If you change the "if(" to "if (" in each of the nested conditionals
you should find that your problem has vanished. The problem is that
whitespace becomes significant within the first if block, at least as
far as further nested if blocks are concerned. The parser used within
the if block is not the same one which parsed out the top if.
Dave
--
(setq mail '("tale@pawl.rpi.edu" "tale@itsgw.rpi.edu" "tale@rpitsmts.bitnet"))
"Drinking coffee for instant relaxation? That's like drinking
alcohol for instant motor skills." -- Marc Price
chris@mimsy.UUCP (Chris Torek) (07/11/89)
In article <685@wuphys.UUCP> marty@wuphys.UUCP (Marty Olevitch) writes: >It appears that csh does not correctly handle nested if-then-else >statements. This is false. It does handle them, but it is finicky. >Am I missing some bug in this script? [all but the `if' lines deleted] >if($v1 == 1) then > if($v2 == 1) then > if($v2 == 1) then You must put a space after the `if', before the `('; and you must have a space between the `)' and the `then' (which must be the last word on the line, after stripping comments). The reason is that the C shell's `skip to end of false construct' code uses a completely different line parser than usual. The `execute this line' parser breaks lines at whitespace and at the characters ( ) & | and perhaps a few others. (&& and || are collected as a unit before causing word breaks.) The `skip to end of false if' routine winds up doing if (strcmp("if(", "if") == 0 && strcmp("then", "then") == 0) in the particular cases given above. Had you written if ($v2 == 1)then it would have tried if (strcmp("if", "if") == 0 && strcmp(")then", "then") == 0) and also failed. Only if ($v2 == 1) then and similar constructs pass its test. (One such construct is if (this, {which is not &syntactically! correct, goes undetected then the c shell sucks endif which counts as an `if-then' during false-if skipping, but causes an error otherwise.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
envbvs@epb2.lbl.gov (Brian V. Smith) (07/11/89)
In article <685@wuphys.UUCP>, marty@wuphys.UUCP (Marty Olevitch) writes:
<
< It appears that csh does not correctly handle nested if-then-else
< statements. The following script illustrates the problem, which appears
< in versions of csh on MORE/bsd (mt Xinu 4.3), SunOS 3.1, SunOS 4.0, and
< Ultrix 2.0. Am I missing some bug in this script? If not, it looks like
< a bug in csh (an equivalent sh program works fine).
<
[ csh script follows ]
Well, on our Vaxstation II running Ultrix 2.0 machine and out
Vaxstation 2000's and II's running Ultrix 3.0, the script worked
just as it should (the "expected" results).
_____________________________________
Brian V. Smith (bvsmith@lbl.gov)
Lawrence Berkeley Laboratory
We don't need no signatures!
envbvs@epb2.lbl.gov (Brian V. Smith) (07/11/89)
In article <TALE.89Jul10131139@imagine.pawl.rpi.edu>, tale@pawl.rpi.edu (David C Lawrence) writes:
< Yes it's a bug, no it's not a bug. It's one of those ambivalent
< things. If you know what it is, you adjust your style by one
< character or so and life goes on correctly again.
<
< Major hacking on the script follows ...
< Marty> #! /bin/csh
< [...]
< Marty> if($v1 == 1) then
< Marty> echo checkpoint 1
< Marty> if($v2 == 1) then
< [...]
< Marty> if($v2 == 1) then
< [...]
<
< If you change the "if(" to "if (" in each of the nested conditionals
< you should find that your problem has vanished. The problem is that
< whitespace becomes significant within the first if block, at least as
< far as further nested if blocks are concerned. The parser used within
< the if block is not the same one which parsed out the top if.
I *didn't* include the spaces as David recommends, and I still didn't see
the problem under Ultrix 2.0 OR Ultrix 3.0. The script (and, hence csh)
works fine.
I used "cut/paste" with X to copy the script, so I know I didn't make any typos.
_____________________________________
Brian V. Smith (bvsmith@lbl.gov)
Lawrence Berkeley Laboratory
We don't need no signatures!
peter@ficc.uu.net (Peter da Silva) (07/11/89)
Basically, it is undesirable to use the 'C' shell for any complicated scripts... or any scripts at all other than .cshrc and .login. -- Peter da Silva, Xenix Support, Ferranti International Controls Corporation. Business: peter@ficc.uu.net, +1 713 274 5180. | Th-th-th-that's all folks... Personal: peter@sugar.hackercorp.com. `-_-' | -- Mel Blanc Quote: Have you hugged your wolf today? 'U` | May 30 1908 - Jul 10 1989
grr@cbmvax.UUCP (George Robbins) (07/13/89)
In article <4948@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: > Basically, it is undesirable to use the 'C' shell for any complicated > scripts... or any scripts at all other than .cshrc and .login. This is a fairly widely held viewpoint, but when you get down to it, neither the bourne shell, nor c-shell provide very elegant programming languages. C-shell does allow "prettier code", but the inconsistancies will nip you from time to time. Bourne shell scripts do have the major advantage of being transportable back into the USG world, which may or may not matter for the task at hand. I here there's now a alt.computers.religion topic for just this sort of rwar... -- George Robbins - now working for, uucp: {uunet|pyramid|rutgers}!cbmvax!grr but no way officially representing arpa: cbmvax!grr@uunet.uu.net Commodore, Engineering Department fone: 215-431-9255 (only by moonlite)
rbj@dsys.ncsl.nist.gov (Root Boy Jim) (07/14/89)
? From: Peter da Silva <peter@ficc.uu.net> ? Basically, it is undesirable to use the 'C' shell for any complicated ? scripts... or any scripts at all other than .cshrc and .login. I disagree. CSH is much more natural to use than SH. The constructs are more natural. In csh, I don't have to resort to `expr' and `test' because these are builtin. The only things I see SH is good for are: 1) portability - sh exists everywhere 2) trivial scripts - starts faster 3) complex file redirection - but how often do you do 3> anyway? 4) shell fns - neat 5) piping to `for' and `while' - but how often? Of course, newer SH's and KSH help quite a bit. ? Peter da Silva, Xenix Support, Ferranti International Controls Corporation. ? Business: peter@ficc.uu.net, +1 713 274 5180. | Th-th-th-that's all folks... ? Personal: peter@sugar.hackercorp.com. `-_-' | -- Mel Blanc ? Quote: Have you hugged your wolf today? 'U` | May 30 1908 - Jul 10 1989 Root Boy Jim Have GNU, Will Travel.
m5@lynx.uucp (Mike McNally) (07/14/89)
rbj@dsys.ncsl.nist.gov (Root Boy Jim) writes: >I disagree. CSH is much more natural to use than SH. The constructs are >more natural. Like the nightmare of trying to continue quoted strings across lines? (OK, OK, a backslash or two isn't that bad). C shell variable manipulation always confuses me too. Then again, the quaint Bourne shell technique of using "set $blah" to implement arrays is a bit crude. The bizarre csh problems with nested complex commands are of course a true pain (like the way quotes magically disappear after the first iteration of a loop...). > In csh, I don't have to resort to `expr' and `test' >because these are builtin. Agreed, although getting at test via [ ... ] isn't painful. > The only things I see SH is good for are: > 1) portability - sh exists everywhere > 2) trivial scripts - starts faster Like *lots* faster. 32K!!!! > 3) complex file redirection - but how often do you do 3> anyway? Never. > 4) shell fns - neat I guess. > 5) piping to `for' and `while' - but how often? **** a l l t h e t i m e !!!!!!!!!!!!! This is in my opinion one of the nicest things about the Bourne shell (or maybe it's one of the worst things about the C shell). >Of course, newer SH's and KSH help quite a bit. Give me version 7 sh or give me death! > Root Boy Jim > Have GNU, Will Travel. Why am I posting this? Maybe somebody should yell at me for wasting bandwidth. -- Mike McNally Lynx Real-Time Systems uucp: {voder,athsys}!lynx!m5 phone: 408 370 2233 Where equal mind and contest equal, go.
hjg@amms4.UUCP (Harry Gross) (07/14/89)
In article <7293@cbmvax.UUCP> grr@cbmvax.UUCP (George Robbins) writes: >I here there's now a alt.computers.religion topic for just this sort of rwar... ^^^^^^^^^^^^^^^^^^^^^^ Read that as alt.religion.computers - it was created about a week or so ago, and I already have 141 articles posted to it. -- Harry Gross | reserved for | something really Internet: hjg@amms4.UUCP (we're working on registering)| clever - any UUCP: {jyacc, rna, bklyncis}!amms4!hjg | suggestions?
peter@ficc.uu.net (Peter da Silva) (07/15/89)
Might I make a request. Would people who post news *AND* send mail please *SAY SO*? Anyway, I bitched about how crummy CSH is for scripts... In article <20243@adm.BRL.MIL>, rbj@dsys.ncsl.nist.gov (Root Boy Jim) writes: > I disagree. CSH is much more natural to use than SH. The constructs are > more natural. The constructs are more conventional, but they sure don't match UNIX filter semantics very well. What do you mean by "natural"? > In csh, I don't have to resort to `expr' and `test' > because these are builtin. In SH I don't have to worry about my control structures screwing up, because they're parsed instead of being implemented as commands. CSH control structures remind me more of assembler macros. > The only things I see SH is good for are: > 1) portability - sh exists everywhere > 2) trivial scripts - starts faster > 3) complex file redirection - but how often do you do 3> anyway? Not often, but I do 2> quite a bit. > 4) shell fns - neat > 5) piping to `for' and `while' - but how often? (piping, redirecting, etc...) All the time. This construct: generate_a_list_of_file_names | while read FNAME do do_something_with FNAME done is second nature. And it's impossible in csh without massive inconvenience. By comparison, having TEST and EXPR builtin is a minor optimisation. > Of course, newer SH's and KSH help quite a bit. For interactive use, maybe. I still prefer CSH history. -- Peter da Silva, Xenix Support, Ferranti International Controls Corporation. Business: peter@ficc.uu.net, +1 713 274 5180. | Th-th-th-that's all folks... Personal: peter@sugar.hackercorp.com. `-_-' | -- Mel Blanc Quote: Have you hugged your wolf today? 'U` | May 30 1908 - Jul 10 1989
tchrist@convex.UUCP| (Tom Christiansen) (07/15/89)
In article <7293@cbmvax.UUCP| grr@cbmvax.UUCP (George Robbins) writes: |In article <4948@ficc.uu.net| peter@ficc.uu.net (Peter da Silva) writes: || Basically, it is undesirable to use the 'C' shell for any complicated || scripts... or any scripts at all other than .cshrc and .login. sigh. i used to disbelieve this. i've learned the hard way. it's more true that not true. |This is a fairly widely held viewpoint, but when you get down to it, |neither the bourne shell, nor c-shell provide very elegant programming |languages. C-shell does allow "prettier code", but the inconsistancies [sic] |will nip you from time to time. Bourne shell scripts do have the |major advantage of being transportable back into the USG world, which |may or may not matter for the task at hand. This is also so. That's why where I used to write shell scripts with reams of embedded awk and sed calls, I now use perl, another wonderful piece of Larry Wall-ware. It's a real programming language, optimized for sysadmin tasks. If you haven't looked at it, consider doing so. And it runs on a googol of architectures, thanks to a lot of work towards this goal and his metaconfig program. Try it, you'll like it. --tom
srg@quick.COM (Spencer Garrett) (07/16/89)
In article <5016@ficc.uu.net>, peter@ficc.uu.net (Peter da Silva) writes:
-> generate_a_list_of_file_names |
-> while read FNAME
-> do
-> do_something_with FNAME
-> done
->
-> is second nature. And it's impossible in csh without massive inconvenience.
-> By comparison, having TEST and EXPR builtin is a minor optimisation.
What are you talking about? It's easy and much more natural under csh.
foreach fname (`generate_a_list_of_file_names`)
do_something_with_fname
end
peter@ficc.uu.net (Peter da Silva) (07/16/89)
In article <3171@quick.COM>, srg@quick.COM (Spencer Garrett) writes: > In article <5016@ficc.uu.net>, peter@ficc.uu.net (Peter da Silva) writes: > -> generate_a_list_of_file_names | > -> while read FNAME > -> do > -> do_something_with FNAME > -> done > -> is second nature. And it's impossible in csh without massive inconvenience. > What are you talking about? It's easy and much more natural under csh. > foreach fname (`generate_a_list_of_file_names`) > do_something_with_fname > end Oh, right. I can do: for i in `generate a list of file names` do ... done too. But what if thise file names are generated by: find / -type f -print Just how much stuff can *you* put in command substitutions? To do this under csh, I basically have to do something like: cat > foo << 'EOF' # do_something_with_$* EOF find ... | xargs csh foo -- Peter da Silva, Xenix Support, Ferranti International Controls Corporation. Business: peter@ficc.uu.net, +1 713 274 5180. | Th-th-th-that's all folks... Personal: peter@sugar.hackercorp.com. `-_-' | -- Mel Blanc Quote: Have you hugged your wolf today? 'U` | May 30 1908 - Jul 10 1989
merlyn@iwarp.intel.com (Randal Schwartz) (07/17/89)
In article <3171@quick.COM>, srg@quick (Spencer Garrett) writes: | In article <5016@ficc.uu.net>, peter@ficc.uu.net (Peter da Silva) writes: | | -> generate_a_list_of_file_names | | -> while read FNAME | -> do | -> do_something_with FNAME | -> done | -> | -> is second nature. And it's impossible in csh without massive inconvenience. | -> By comparison, having TEST and EXPR builtin is a minor optimisation. | | What are you talking about? It's easy and much more natural under csh. | | foreach fname (`generate_a_list_of_file_names`) | do_something_with_fname | end Unless (and there are far far far too many "unless"-es with CSH...) generate_list_of_file_names returns more than 5120 characters, *or* the resulting list can't be globbed properly (I just got bit on /bin/*... try it... it bites the big one on "/bin/[") *or* some other combination of events that I'll probably run across tomorrow... Gaaaaccckkk! Gimme /bin/sh any day. True parsing. No nonsense. Of course, as soon as /bin/ksh becomes *the* standard, I'll like it much better. Until then, I'm stuck with csh for my top level shell because of command history and job control, but all my scripts (well, non-Perl scripts :-) are /bin/sh. Just an old-time UNIX hacker, -- /== Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ====\ | on contract to Intel, Hillsboro, Oregon, USA | | merlyn@iwarp.intel.com ...!uunet!iwarp.intel.com!merlyn | \== Cute Quote: "Welcome to Oregon... Home of the California Raisins!" ==/
bet@orion.mc.duke.edu (Bennett Todd) (07/18/89)
In article <3171@quick.COM>, srg@quick (Spencer Garrett) writes: >In article <5016@ficc.uu.net>, peter@ficc.uu.net (Peter da Silva) writes: > >-> generate_a_list_of_file_names | >-> while read FNAME >-> do >-> do_something_with FNAME >-> done >-> >-> is second nature. And it's impossible in csh without massive inconvenience. >-> By comparison, having TEST and EXPR builtin is a minor optimisation. > >What are you talking about? It's easy and much more natural under csh. > >foreach fname (`generate_a_list_of_file_names`) > do_something_with_fname >end I am *so* glad bash is out; I used to use a C-shell for interactive work just to get history and job control; I was always having to fire up /bin/sh to do serious looping work. Here are some things csh croaks on: find ... -print | while read filename;do ... done If you try rewrite that as foreach f (`find ... -print`) ... end csh will bomb on command line too long. IFS=: while read login passwd uid gid gcos home shell;do # process /etc/passwd with fields broken down done </etc/passwd I wouldn't know how to try that in csh -- without running a separate invocation of sed(1) over /etc/passwd once per record. for f in ... # or while ... ... done & csh won't let me background an entire loop. Basically, I get the impression that csh's attempts at programming constructs are afterthoughts hacked in imperfectly, rather than properly parsed grammar constructs. -Bennett bet@orion.mc.duke.edu