[comp.bugs.4bsd] C-shell expression bug with fix. My fix.

greim@sbsvax.UUCP (Michael Greim) (03/23/88)

Hi folks,

Sorry that I am a little late with this fix, but our computers got
moved to a new building, so we were rather isolated the last few days.

In <479@sol.warwick.ac.uk> Rob McMahon writes :

>One of our students reported the following bug to me:
>
> 	% if ( abc =~ * ) echo yes
> 	<silence>
> 	% if ( abc =~ ** ) echo yes
> 	yes
> 
> Further investigation gave the following:
> 
> 	% if ( 0 =~ * ) echo yes
> 	yes
> 	% if ( 2 == 2 + ) echo yes
> 	yes
> 	% if ( 2 == + 2 ) echo yes
> 	yes
> 
> The * is being treated as multiply, and the shell doesn't care that it's
> got no operands, it just fills them in with 0.  I've applied the
> following fix, but I'm slightly unsure about it because I may have
<rest deleted>

Well the fix causes some new bugs. I present here my own fix,
which seems to work slightly better. I append a file I used for testing
which demonstrates the use of patterns.

I don't think it should be an error if you tried
	if ( 2 == 2 + ) echo yes
because the manual explicitly says :
	"... Null or missing arguments are considered '0'"
so my fix only fixes the behaviour when dealing with a pattern.


FIX:

*** sh.exp.c.old	Wed Mar 23 14:29:26 1988
--- sh.exp.c	Wed Mar 23 14:27:53 1988
***************
*** 156,164 ****
  #endif
  	if (i = isa(**vp, EQOP)) {
  		(*vp)++;
! 		if (i == EQMATCH || i == NOTEQMATCH)
  			ignore |= NOGLOB;
! 		p2 = exp3(vp, ignore);
  #ifdef EDEBUG
  		etracc("exp2c p2", p2, vp);
  #endif
--- 156,167 ----
  #endif
  	if (i = isa(**vp, EQOP)) {
  		(*vp)++;
! 		if (i == EQMATCH || i == NOTEQMATCH) {
  			ignore |= NOGLOB;
! 			p2 = **vp;
! 			(*vp)++;
! 		} else
! 			p2 = exp3(vp, ignore);
  #ifdef EDEBUG
  		etracc("exp2c p2", p2, vp);
  #endif

TESTS:

if ( abc =~ * ) then
	echo "ok 1"
else
	echo "false 1"
endif
if ( "abc" =~ * ) then
	echo "ok 2"
else
	echo "false 2"
endif
set abc='d b'
if ( "$abc" =~ d\ * ) then
	echo "ok 3"
else
	echo "false 3"
endif
set abc='234 - zzz'
if ( "$abc" =~ [1-9]*\ -\ ??? ) then
	echo "ok 4"
else
	echo "false 4"
endif
set abc='"abc"'
if ( $abc =~ \"*\" ) then
	echo "ok 5"
else
	echo "false 5"
endif
set abc='misty?hallo'
set def='call.me'
if ( $abc =~ *\?* && $def !~ *\?me ) then
	echo "ok 6"
else
	echo "false 6"
endif


Running this file through old csh should produce :
false 1
false 2
ok 3
ok 4
ok 5
misty?hallo: no match

Running cured csh returns for all cases "ok".


Have a nice day,

		Michael

cudcv@daisy.warwick.ac.uk (Rob McMahon) (04/04/88)

In article <469@sbsvax.UUCP> greim@sbsvax.UUCP (Michael Greim) writes:
>In <479@sol.warwick.ac.uk> Rob McMahon [me] writes :
>> [bug ...]
>> 	% if ( abc =~ * ) echo yes
>> 	<silence>
>> 	% if ( abc =~ ** ) echo yes
>> 	yes
>> [strange behaviour ...]
>> 	% if ( 2 == 2 + ) echo yes
>> 	yes
>
>Well the fix causes some new bugs.

( Are there other bugs introduced besides rejecting the missing argument ? )

>I don't think it should be an error if you tried
>	if ( 2 == 2 + ) echo yes
>because the manual explicitly says :
>	"... Null or missing arguments are considered '0'"
>so my fix only fixes the behaviour when dealing with a pattern.

Well having R'edTFM a bit better, I have to agree you're right, my fix
was wrong, and it should accept missing arguments.  (I would contend
that this is just to protect people who leave the quotes off their
variables in ( $file == "" ), and delays their script breaking until
their variable contains a metacharacter, but that's another matter.)

However the fixed fix also goes against the manual, because suddenly =~
and !~ get tightly coupled to the next argument, and ignore the
precedence rules on the right hand side.  Now, since there are no
operators that return strings, that could contain metacharacters, and I
don't suppose anyone would enclose their pattern in (), =~ could be
replaced by == in these cases, but in that case the manual entry should
be changed, and it does preclude ever adding string operators.

Note that my original fix was in two parts, to cure the two problems as
I saw them, and "unpatching" the one that changed return("") to
bferr("...") would fix "( x =~ * )" without breaking "( 2 == 2 + )" or
'set file = ""; if ( $file == "" )'.

Anybody "official" want to comment on which fix is fixed ?

>Have a nice day,
>		Michael

And seasons greetings to you too.

Rob

-- 
UUCP:   ...!mcvax!ukc!warwick!cudcv	PHONE:  +44 203 523037
JANET:  cudcv@uk.ac.warwick.cu          ARPA:   cudcv@cu.warwick.ac.uk
Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England