Hamilton LaboratoriesHamilton C shell 2012User guideTutorials


Oregon Coast

Previous | Next


Environment variables
Set variables
Local variables
Variable substitutions
How variables are stored
See also

As with any conventional programming language, the shell provides a facility for storing values in variables.

Environment variables

Some of the variables are part of the environment, passed along to any child process. Many of the environment variables will have been created just this way, e.g., set to a value passed along when you start the C shell from a shortcut on your desktop. To list those currently defined, use the setenv command.

146 D% setenv COMSPEC C:\WINDOWS\system32\cmd.exe HOME d:\Nicki INCLUDE d:\Nicki\Include LIB d:\Nicki\lib PATH .;d:\Program Files\Hamilton C shell 2012 x64\Bin; d:\Program Files\Hamilton C shell 2012 x64\Samples;C:\WINDOWS\system32; C:\WINDOWS PROMPT1 $@ $CDISK% PROMPT2 $@ $CDISK? SHELL d:\Program Files\Hamilton C shell 2012 x64\Bin\csh.exe TABS 3 TMP e:\tmp

Variable names are case-preserving but case-insensitive on Windows. They can be of arbitrary length. A name must start with an upper- or lower-case alphabetic character or underscore_ or at-sign @; remaining characters may any of these or decimal digits. Many of the environmental variables have specific meanings. For example, the PATH variable tells where to look for executable files, etc. Details describing the meaning of each variable are given in the language reference section.

The setenv command can also be used to create a new environmental variable or alter or display the value of an existing one:

147 D% setenv zork = this is the zork variable 148 D% setenv zork zork this is the zork variable 149 D% _

If the list of words being assigned to the variable includes any special tokens, it’s often useful to use the parenthesized variant of setenv. In this example, the > would have been confused as an i/o redirection if it weren’t inside parenthesis. Notice that the parenthesis are stripped off before the assignment is made.

149 D% setenv greatest = (At Berkeley, they say 4.3 > V) 150 D% setenv greatest greatest At Berkeley, they say 4.3 > V

Even though the special meaning is lost, text inside the parenthesis is still broken down into words, as shown in this example:

151 D% setenv pdirs = (.;d:\Nicki\bin;d:\Nicki\LastRTM;d:\Nicki;) 152 D% setenv pdirs pdirs . ; d:\Nicki\bin ; d:\Nicki\LastRTM ; d:\Nicki

(To avoid having the text broken up into words, use single or double quotes around the string instead.)

Set variables

Set variables do not get passed to a child process but are shared among all threads. To get a list of those currently defined, use the set command:

153 D% set CDISK D argv cdhome 0 cdisk d : : path . d:\Nicki\bin d:\Nicki\LastRTM d:\Nicki precision 6 : :

Some of the set variables are linked to the environmental variables: you change one, and the other changes too. For example, path contains the same information as PATH but, because it’s been parsed into individual words, it’s often a bit more useful.

On Windows, this linkage can pose a bit of a problem. Since the convention is that environmental variables are supposed to be case-insensitive, there clearly is a conflict between, for example, the PATH environmental and path set variables. The C shell resolves this by making the set, unset and @ statements case-sensitive (so you can still create set variables that differ from environmental variables only by case) but the setenv and unsetenv and $var and other variable references first try case-sensitive, then case insensitive variable lookups.

Many of the set variables are predefined by the shell to control various aspects of how errors are handled, etc. In some cases, each thread maintains its own copy. For example, it wouldn’t do to insist that all threads must use the same value for the cwd (current working directory) variable! The rest of the variables, including any defined by the user, are shared among all threads: if one thread changes a value, all the other threads see the change immediately. As we’ll see later, this has some implications when spawning background activities.

In other respects, set works just like setenv:

154 D% set privatezork = this is the private zork variable 155 D% set privatezork privatezork this is the private zork variable 156 D% _

Once a variable has been created as either a set or an environmental variable, it stays that way: to change it from set to environmental, you must first unset it, then redefine it.

Local variables

We just mentioned that not all the predefined set variables are shared. Individual threads get their own private copies of some because to do otherwise wouldn’t be sensible. Sometimes you need the same sort of control over the variables you create. You don’t want to share a variable with other threads or even with commands outside a very narrow context.

You accomplish this making the variable local, which means it’s hidden from outer control blocks or other threads. Local variables are really important, as we’ll see later, for recursive procedures or for procedures you want to use from multiple threads. To define a variable as local, use the local statement, which accepts a list, separated with commas, of all the variable names you want to be local. When a new local variable is created, its initial value is always null (zero words), even if there was a previous definition. Here you can see how the variable i is redefined inside the nested statements but once you exit from the nest, the old value of i is again visible:

156 D% set i = hello world 157 D% echo $i hello world 158 D% (local i; echo $i; set i = how are you; echo $i) how are you 159 D% echo $i hello world

When you spawn a child thread, e.g., as a background activity or as the second or following stage of a pipeline, it gets copies of all your local variables, snapshotted at the time it’s spawned. If either the parent or the child later changes to the value of any those local variables, they affect only its own copy.

Variable substitutions

The simplest way to use a variable is in a simple substitution, where a dollar sign is used to indicate that a variable name follows, similar to using a % in cmd.exe. The value is substituted in and the statement is evaluated.

160 D% echo $HOME d:\Nicki

Text surrounding the variable reference is generally just pasted around the value that’s substituted in:

161 D% echo My home directory is ---$HOME--- My home directory is ---d:\Nicki---

If the surrounding text would be confused as part of the variable name, it’s necessary to insulate the variable reference with braces. For example:

162 D% echo ${HOME}XXX d:\NickiXXX


If you try to reference a variable, procedure or an alias and it doesn’t exist, it’s considered an error unless you set the nonovar variable to indicate how you want the situation treated.

163 D% echo $nonesuch csh: The variable 'nonesuch' is not defined. To suppress this error, set nonovar = 1 (pass through) or 2 (discard). 164 D% set nonovar = 1 165 D% !e echo $nonesuch $nonesuch 166 D% set nonovar = 2 167 D% !e echo $nonesuch 168 D% set nonovar = 0

How variables are stored

Each variable is kept internally as a list (an array) of objects. An individual object can be a (possibly null) character string, a 32-bit integer or a 64-bit floating point value. Generally speaking, it’s not necessary to worry too much about how a specific object is represented, though, since the shell automatically does any necessary conversions to allow a value to be used sensibly in any given context.

Notice, however, that even though the value of an environmental variable may be a list, it is always rendered as a simple character string when it’s passed to a child process. Here’s an example using the $# notation to ask how many words are in a variable’s value:

169 D% echo $zork this is the zork variable 170 D% echo $#zork 5 171 D% csh Hamilton C shell(tm) x64 Release 5.0 Copyright (c) 1988-2011 by Hamilton Laboratories. 1 D% echo $zork this is the zork variable 2 D% echo $#zork 1 3 D% exit 172 D% _

In this example, zork holds five words: this, is, the, zork and variable. But when we start up a new child process running the shell, the child process sees zork as holding only a single word: this is the zork variable.

Here’s another example where we assign a floating point value to an environmental variable. In the current process, the exact binary floating representation is used. When it’s passed to a child process, the value is first converted to a character string, losing some of the precision. This example also introduces the calc statement which evaluates an expression and prints the value. In an expression, a variable name is recognized even without a $ to introduce it; in fact, that’s the preferable way to do it. If you use a $-style variable substitution, the shell pastes in a character-string representation, again losing precision. Also, the full range of C language expression operators is available.

172 D% setenv envVar = 0 173 D% calc ++envVar 1 174 D% calc envVar /= 7 0.142857 175 D% calc envVar*7 1.000000 176 D% csh <<eof 177 D? calc envVar*7 178 D? exit 179 D? eof Hamilton C shell(tm) x64 Release 5.0 Copyright (c) 1988-2011 by Hamilton Laboratories. 0.999999 180 D% calc $envVar*7 0.999999


Variables can hold a list of values indexed as an array. As with the C language, arrays are indexed, counting from zero, with an expression inside [...] brackets. The expression can be arbitrarily complex, but it must evaluate to an exact integer value. The next example shows how a floating point value can be used, but if it’s not precisely an integer, an error results. The precision variable controls the number of digits past the decimal point used when displaying a floating point value; the maximum is 17 digits.

181 D% set x = now is the time for all good men 182 D% calc x[5.000000] all 183 D% calc 2**500 3.27339061e+150 184 D% calc y = log2(!$)/100 calc y = log2 ( 2**500 ) /100 5.000000 185 D% calc x[y] csh: Couldn't evaluate the index to the variable 'x'. 186 D% set precision = 30 187 D% calc precision 17 188 D% calc y 5.00000000000000100 189 D% calc x[round(y)] all

An array cannot be sparse; i.e., before you can create an element 5, element 4 must exist and so on. But it’s perfectly legal to keep adding new elements onto the end of array as long as the new element is the zero-th element or only one past whatever’s currently the last element. Here’s an example using a for loop. The @ statement is like calc except it doesn’t print anything.

190 D% unset x 191 D% for i = 0 to 4 do 192 D? @ x[i] = 2*i 193 D? end 194 D% echo $x 0 2 4 6 8


When you index an array, if the element you specify doesn’t exist, that’s normally considered an error. For example, x contains 5 words; trying to reference a sixth fails:

195 D% calc x[5] csh: Illegal subscript in variable reference 'x[5]'. (To suppress this error, set nullwords = 1.)
The nullwords variable is used to tell the shell that you’d like to ignore subscripting errors when you try to evaluate a variable reference. nullwords has no effect over subscripting errors when you try to set the value of a non-existent element. Here are some examples:
196 D% set nullwords = 1 197 D% echo -- "--->$x[999]<---" ---><--- 198 D% calc x[999] = "does not work" csh: Illegal subscript in variable reference 'x[999]'.

The use of the -- option and of double quotes was important: -- told echo that it had reached the end of any options, allowing it to print something that began with a minus sign. The quotes were used, in the first case, to turn off recognition of redirection characters > and < but still get the variable substitution. The second time, it was to make the string, does not work a single word. (If you try leaving off the quotes or not using --, you’ll see that the error messages are what you’d expect.)

See also

The @, calc, set, setenv and local statements
Variable substitution syntax
Substitution modifiers
Predefined environment variables
Predefined shared variables
Predefined inherited variables
Predefined initialized variables
Combined list of predefined variables
Order of evaluation
Tutorial: Expressions

Previous | Next

Getting started with Hamilton C shell

Hamilton C shell, as it first wakes up.

Getting started with Hamilton C shell

A first few commands.

You can set the screen colors to your taste.

You can set the screen colors to your taste.