[comp.unix.wizards] csh oddity

dcornutt@murphy.UUCP (Dave Cornutt) (01/07/88)

I have discovered something peculiar about csh variable substitution.  Is
this a bug or am I doing something wrong?  Watch this:

example 1:
% set xyz=qwert
% echo $xyz
qwert
% set xyz=${xyz}_123
% echo $xyz
qwert_123
%

example 2:
% set xy1z=qwert
% echo $xy1z
qwert
% set xy1z=${xy1z}_123
Variable syntax.
% echo $xy1z
qwert
%

Note that the only difference between these two examples is in the variable
name.  After further experimenting, I discovered that the ${foo} form
seems to choke whenever the variable name has a digit in it; variable
names consisting solely of lower-case alphabetics always work.  (I haven't
tried using other characters.)  I tried quoting the string in various ways,
none of which made any difference.  Has anyone ever seen this?  Is it a bug,
or did I just get up too early?

The OS involved here is UTX/32, rev 2.0, which is BSD4.3 based.  However,
I have gotten the same results on Sun 3.2, which is 4.2-based, so I think
it's generic to csh.  Any hints?
---
Dave Cornutt, Gould Computer Systems, Ft. Lauderdale, FL
[Ignore header, mail to these addresses]
UUCP:  ...!{sun,pur-ee,brl-bmd,uunet,bcopen,rb-dc1}!gould!dcornutt
 or ...!{codas,mia,hrshcx}!novavax!gould!dcornutt
paths to codas: allegra,ucf-cs,peora,killer,burl,mtune,ufsvax2,flnexus,toynix
ARPA: dcornutt@gswd-vms.gould.com

"The opinions expressed herein are not necessarily those of my employer,
not necessarily mine, and probably not necessary."

paul@devon.UUCP (Paul Sutcliffe Jr.) (01/10/88)

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?  Watch this:
| 
| % set xy1z=qwert
| % echo $xy1z
| qwert
| % set xy1z=${xy1z}_123
| Variable syntax.
| % echo $xy1z
| qwert
| 
| The OS involved here is UTX/32, rev 2.0, which is BSD4.3 based.  However,
| I have gotten the same results on Sun 3.2, which is 4.2-based, so I think
| it's generic to csh.  Any hints?
+----------

I tried this same thing on the csh on Microsoft Xenix 3.0 (Xenix/68000 on
a Tandy 16), and got the same results.

Not having source, I cannot suggest what is causing this (or offer a
fix), but I thought I mention this for those who can.

- paul

-- 
Paul Sutcliffe, Jr.

UUCP (smart):  paul@devon.UUCP
UUCP (dumb):   ...{rutgers,ihnp4,cbosgd}!bpa!vu-vlsi!devon!paul

hansen@mips.UUCP (Craig Hansen) (01/11/88)

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?

You're doing something wrong. The correct syntax is:
 
% set xy1z={$xy1z}_123

-- 
Craig Hansen
Manager, Architecture Development
MIPS Computer Systems, Inc.
...{ames,decwrl,prls}!mips!hansen or hansen@mips.com

jam@philabs.Philips.Com (John A. Murphy) (01/12/88)

In article <590@devon.UUCP> paul@devon.UUCP (Paul Sutcliffe Jr.) writes:
>In article <826@murphy.UUCP> dcornutt@murphy.UUCP (Dave Cornutt) writes:
>+----------
Instead of   >| % set xy1z=${xy1z}_123
% set xy1z={$xy1z}_123
>| % echo $xy1z
qwert_123


-- 
jam@philabs.uucp

schaefer@ogcvax.UUCP (Barton E. Schaefer) (01/12/88)

In article <mips.1269> hansen@mips.UUCP (Craig Hansen) writes:
>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?
>
>You're doing something wrong. The correct syntax is:
>
>% set xy1z={$xy1z}_123
>-- 
>Craig Hansen

Sorry, Craig, that syntax changes the meaning of the {} from "variable
substitution" to "filename substitution" as in

% set xy1z="one,two,three"
% set xyz={$xy1z}_step
% set
xy1z	one,two,three
xyz	(one_step two_step three_step)

The syntax ${xy1z} SHOULD work, but it doesn't (confirmed here for Mt. Xinu
4.3 BSD csh as well).  Does anyone happen to know why it fails?  Does it have
anything to do with ${1} being a synonym for $1 (and ${2} for $2 and so on)?
-- 
Bart Schaefer			CSNET:	schaefer@cse.ogc.edu
				UUCP:	...{tektronix,verdix}!ogcvax!schaefer
"A band of BIG, DUMB, LOUDMOUTHED, BUNGLING OGRES is a GREAT ASSET to the
neighbohood.  It keeps out the RIFF-RAFF."		-- Wormy

chris@mimsy.UUCP (Chris Torek) (01/14/88)

>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?

[the bug reduces to

	set x1=test
	echo ${x1}
]

In article <1269@mips.UUCP>, hansen@mips.UUCP (Craig Hansen) writes:
>You're doing something wrong. The correct syntax is:
>% set xy1z={$xy1z}_123

Naah.

*** 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;

The amusing part is that the code in sh.dol.c was all set to handle
text of the form `{ALPHA}{ALNUM}*', but sh.lex.c never let it get
that far.  This `Variable syntax' error is coming from the `lexical
analyser', not the variable evaluator.  That one has one of its
own, used if the `lexer' lets something wrong go through.  Sheer
idiocy: two routines to do the same job.

Craig's workaround is fine if the expansion of $xy1z does not
contain a comma.

	% set a=a,b,c
	% echo ${a}
	a,b,c
	% set a1=a,b,c
	% echo {$a1}
	a b c

Here the {}s indicate set notation, rather than variable name
restriction.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

nortond@mosys.UUCP (Daniel A. Norton) (01/14/88)

I am running a version of csh which comes with Convergent's CTIX
along with Sys V/3.0 and it does the same thing.  Put more simply,
if I have  a variable name with a digit in it, I cannot expand it
if I enclose the variable name in parentheses:

% set xy1z=asdf
% echo $xy1z
asdf
% echo ${xy1z}
Variable syntax.

I would call this a bug in CTIX, because the documention on csh reads:

$name
${name}
	Are replaced by the words of the value of variable
	name, each separated by a blank.  Braces insulate
	name from following characters which would otherwise
	be part of it.  Shell variables have names consisting of
	up to 20 letters and digits starting with a letter.  The
	underscore character is considered a letter.
-- 
Daniel A. Norton				nortond@mosys.UUCP
544 Cormorant Drive				...uunet!mosys!nortond
Voorhees, NJ   08043 				609/751-7381

hansen@mips.UUCP (Craig Hansen) (01/15/88)

In article <1530@ogcvax.UUCP>, schaefer@ogcvax.UUCP (Barton E. Schaefer) writes:
> In article <mips.1269> hansen@mips.UUCP (Craig Hansen) writes:
> >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?
> >
> >You're doing something wrong. The correct syntax is:
> >
> >% set xy1z={$xy1z}_123
> 
> Sorry, Craig, that syntax changes the meaning of the {} from "variable
> substitution" to "filename substitution" as in
> 
> % set xy1z="one,two,three"
> % set xyz={$xy1z}_step
> % set
> xy1z	one,two,three
> xyz	(one_step two_step three_step)
> 
> The syntax ${xy1z} SHOULD work, but it doesn't (confirmed here for Mt. Xinu
> 4.3 BSD csh as well).  Does anyone happen to know why it fails?  Does it have
> anything to do with ${1} being a synonym for $1 (and ${2} for $2 and so on)?

OK, OK, it's a bug.

I haven't tested the fix, but the following fragment of source file sh.lex.c
looks dubious:

	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;

Looks like the last call to letter() should be written as:

			while (letter(c = getC(DOEXCL)) || digit(c)) {

There's a macro called alnum(), which would be the obvious replacement,
but it evaluates the argument twice :-(.

-- 
Craig Hansen
Manager, Architecture Development
MIPS Computer Systems, Inc.
...{ames,decwrl,prls}!mips!hansen or hansen@mips.com

steve@edm.UUCP (Stephen Samuel) (01/21/88)

In article <590@devon.UUCP>, paul@devon.UUCP writes:
| 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?  Watch this:
| | % set xy1z=qwert
| | % echo $xy1z
| | qwert
| | % set xy1z=${xy1z}_123
| | Variable syntax.
| | % echo $xy1z
| | qwert
(bloody include counter.....)

It seems to be something with having the '1' inside the braces... The one fix
(workaround) I have is to take the qy1z out of the braces and trail it with
a null ('') string (delimits the end of the name.):
.......
% set qy1z=$qy1z''_123
% echo $qy1z
qwert_123

-- 
-------------
 Stephen Samuel 			Disclaimer: You betcha!
  {ihnp4,ubc-vision,seismo!mnetor,vax135}!alberta!edm!steve
  BITNET: USERZXCV@UQV-MTS