[comp.unix.wizards] csh variable syntax '${x1[2]}' is broken.

bbadger@x102c.harris-atd.com (Badger BA 64810) (04/05/89)

Variable expansion in csh isn't done properly.
The problem is shown by this example:

% set verbose
set verbose
set verbose 
% set x1=(a b c)
set x1= ( a b c ) 
% echo ${x1[2]}		
echo 1${x[2]} 
Variable syntax.
% 

Here's a more complete transcript, showing that a variable name with no 
digits in it works correctly:

% set echo
% set verbose
set verbose
% set xx=(a b c)
set xx= ( a b c ) 
set xx= ( a b c )
% set x1=(d e f)
set x1= ( d e f ) 
set x1= ( d e f )
% alias x 'echo ${x\!:1[2]}'
alias x 'echo ${x!:1[2]}' 
alias x echo ${x!:1[2]}
% alias x_ 'echo $x\!:1[2]'
alias x_ 'echo $x!:1[2]' 
alias x_ echo $x!:1[2]
% echo ${xx[2]}
echo ${xx[2]} 
echo b
b
% x x
x x 
echo b
b
% echo $xx[2]
echo $xx[2] 
echo b
b
% x_ x
x_ x 
echo b
b
% echo $x1[2]
echo $x1[2] 
echo e
e
% x_ 1
x_ 1 
echo e
e
% echo ${x1[2]}		
echo 1${x[2]} 
Variable syntax.
% !!
echo 1${x[2]} 
x: Undefined variable.
% x 1
x 1 
Variable syntax.
% !!
x 1 
Variable syntax.
% 

The work-around seems to be to not use {}'s.
Bernard A. Badger Jr.	407/984-6385          |``Use the Source, Luke!''
Secure Computer Products                      |``Get a LIFE!''  -- J.H. Conway
Harris GISD, Melbourne, FL  32902             |Buddy, can you paradigm?
Internet: bbadger%x102c@trantor.harris-atd.com|'s/./&&/g' Tom sed expansively.

chris@mimsy.UUCP (Chris Torek) (04/06/89)

Date: Wed, 13 Jan 88 20:36:53 EST
From: Chris Torek <chris@gyre.umd.edu>
To: 4bsd-bugs@ucbvax.Berkeley.EDU
Subject: csh mislexes $var1iables

Index: bin/csh/sh.lex.c 4.3BSD Fix
Reference: 4.3BSD/bin/114

Description:
	The C shell's `lexical analyser' (if you can call it that)
	thinks that variables are either all digits or all numbers.
	As far as it is concerned, $a1bc is the variable $a followed
	by the string `1bc'.  Everyone is happy: the lexer sees a
	properly-formed variable ($a) plus a string, and later, the
	variable evaluator looks up $a1bc.

	If, however, one writes instead ${a1bc}, the lexer is not
	happy.  It sees a variable (${a) that is not proper: the
	closing brace `}' is missing.  It complains about variable
	syntax (an ambiguous error, but here the real meaning is not
	the intended one!), and the evaluator never gets a chance.

Repeat-by:
	% set a1=ok
	% echo ${a1}
	Variable syntax.
	% man csh
	(read section on shell variable syntax)

Fix:
	It seems to work.  The code is all twisty and devious, so
	maybe it will break something.  I doubt it.

Chris

*** sh.lex.c.old	Wed Jan 13 20:22:06 1988
--- sh.lex.c	Wed Jan 13 20:22:10 1988
***************
*** 373,377 ****
  			}
  		} else if (letter(c))
! 			while (letter(c = getC(DOEXCL))) {
  				if (np < &name[sizeof name / 2])
  					*np++ = c;
--- 373,377 ----
  			}
  		} else if (letter(c))
! 			while (letter(c = getC(DOEXCL)) || digit(c)) {
  				if (np < &name[sizeof name / 2])
  					*np++ = c;

-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

greim@sbsvax.UUCP (Michael Greim) (04/10/89)

In article <1893@trantor.harris-atd.com>, bbadger@x102c.harris-atd.com (Badger BA 64810) writes:
> Variable expansion in csh isn't done properly.
[...]
You can fix this bug if you have source.
I have published a fix on 12. January 1988. I was relatively new to the net,
so I did not obey some conventions.
This fix is part of a set of fixes. One of the projects I have waiting on
my schedule is to bundle all the fixes, create diffs for the tahoe csh
(which has the same bugs, mostly) and publish all this in the appropriate
news group.
I always wondered who applied my fixes.

= From greim@sbsvax.UUCP Tue Jan 12 19:24:28 1988
= Path: sbsvax!greim
= From: greim@sbsvax.UUCP (Michael Greim)
= Newsgroups: comp.unix.wizards
= Subject: Re: csh oddity
= Summary: fix
= Keywords: csh variables substitution
= Message-ID: <373@sbsvax.UUCP>
= Date: 12 Jan 88 18:24:28 GMT
= References: <826@murphy.UUCP>
= Organization: Universitaet des Saarlandes, D-6600 Saarbruecken, FRG
= Lines: 87
= 
= This is in answer to an article by
= Dave Cornutt, Gould Computer Systems, Ft. Lauderdale, FL
= 
= He writes about a bug in csh.
= Doing
=         set a1b=abc
=         set b=${a1b}
= will provoke an error message "Variable syntax.", and in the
= history the last command will be entered as "set b=1${ab}".
= 
= This is really a bug, but it is relativly easy to find and to fix.
= I know some which are very difficult to fix.
= 
= Diagnosis:
=         Look in sh.lex.c, somewhere around line  390 in the routine getdol
=         there should be the following code (this here quoted from 4.3 BSD):
= 
=         case '*':
=                 if (special)
=                         goto vsyn;
=                 goto ret;
= 
=         default:
=                 if (digit(c)) {
= /*
=  * let $?0 pass for now
=                         if (special)
=                                 goto vsyn;
= */
=                         while (digit(c = getC(DOEXCL))) {
=                                 if (np < &name[sizeof name / 2])
=                                         *np++ = c;
=                         }
=                 } else if (letter(c))
=                         while (letter(c = getC(DOEXCL))) {
=                                 if (np < &name[sizeof name / 2])
=                                         *np++ = c;
=                         }
=                 else
=                         goto vsyn;
=         }
= 
=         This code causes the bug. After a $ is encountered the routine looks
=         if a number follows, it was '$1' or something like this, if not,
=         it wants to check whether the variable name is correct, but it
=         only tests if all characters a letters. Variable Names can contain
=         numberes too.
= 
=         Therapy:
=                 change to
= 
=         case '*':
=                 if (special)
=                         goto vsyn;
=                 goto ret;
= 
=         default:
=                 if (digit(c)) {
= /*
=  * let $?0 pass for now
=                         if (special)
=                                 goto vsyn;
= */
=                         while (digit(c = getC(DOEXCL))) {
=                                 if (np < &name[sizeof name / 2])
=                                         *np++ = c;
=                         }
=                 } else if (alnum(c))
=                         while (alnum(c = getC(DOEXCL))) {
=                                 if (np < &name[sizeof name / 2])
=                                         *np++ = c;
=                         }
=                 else
=                         goto vsyn;
=         }
= 
= 
[...]

= From greim@sbsvax.UUCP Mon Jan 18 17:12:59 1988
= Path: sbsvax!greim
= From: greim@sbsvax.UUCP (Michael Greim)
= Newsgroups: comp.unix.wizards,comp.bugs.4bsd
= Subject: Re: csh oddity, fix
= Keywords: csh variables substitution fix
= Message-ID: <374@sbsvax.UUCP>
= Date: 18 Jan 88 16:12:59 GMT
= Organization: Universitaet des Saarlandes, D-6600 Saarbruecken, FRG
= Lines: 95
= 
= In article <826@murphy.UUCP> dcornutt@murphy.UUCP (Dave Cornutt) writes:
= > I have discovered something peculiar about csh variable substitution.  Is
= > this a bug or am I doing something wrong?
= 
= Sorry folks,
= The fix I sent on 12. Jan. is not complete. It does not cover every
= instance of the bug.
= Like Chris Torek says in <10167@mimsy.UUCP> it is idiocy
= for two routines to handle the same job. But it comes even better :
= the test, whether a variable name is valid, is done differently in
= several parts of csh.
= 
= Try the following commands, and note the faulty behaviour
=     set xy1z=mist
= 1.) echo ${xy1z}          in sh.lex.c
= 2.) set 1a                in sh.set.c
= 3.) foreach a1b ...       in sh.func.c
= 
= If I have overlooked a bug instance, tell me. (But apply the fixes first:
= they will kill some bugs :-)
= 
= I do not give any context diff's, because my sourcecode is cluttered
= with ifdef's, so the output might be too confusing. And I am too lazy
= to revert to the original code in SCCS :^o
= 
= The first situation is covered by my fix from 12.Jan, which applied to
= the piece of code Chris Torek (<10167@mimsy.UUCP>) and Craig Hansen
= (<1326@mips.UUCP>) suspected.
[...]
= 
= + means new line
= - means deleted line
= ! means changed line
= 
= Fix2:
=         in sh.set.c, routine doset, about line 30
=         ...
=         do {
=                 hadsub = 0;
= +               if (!letter (*p))
= +                       goto setsyn;
=                 for (vp = p; alnum(*p); p++)
=                         continue;
=                 if (vp == p)
=                         goto setsyn;
=         ...
= 
= Fix3:
=         in sh.func.c, routine doforeach, about line 356
=         ...
=         cp = strip(*v);
= +       if (! letter (*cp))
= +               bferr("Variable syntax");
= !       while (*cp && alnum(*cp))
=                 cp++;
=         if (*cp || strlen(*v) >= 20)
=                 bferr("Invalid variable");
=         ...
= 
[...]

Absorb, apply and enjoy,
	-mg

email : greim@sbsvax.informatik.uni-saarland.dbp.de
  (some mailers might not like this. Then use greim@sbsvax.uucp)
  or  : ...!uunet!unido!sbsvax!greim
# include <disclaimers/std.h>
-- 
email : greim@sbsvax.informatik.uni-saarland.dbp.de
  (some mailers might not like this. Then use greim@sbsvax.uucp)
  or  : ...!uunet!unido!sbsvax!greim
# include <disclaimers/std.h>