Go to the previous, next section.
macro
in your
`.sm' file is searched for a file `default', and then the
macro startup
from that file is executed. At the time of writing of
this manual, startup
was defined as:
startup ## macro invoked upon startup FOREACH 1 { default_font device edit file_type history_char \ macro macro2 overload printer prompt prompt2 SHELL 2 { DEFINE $1 : } FOREACH 1 { TeX_strings case_fold_search fan_compress \ line_up_exponents noclobber overload \ remember_history_line traceback uppercase 2 { DEFINE $1 : IF($?$1) { IF('$$1' == '0') { DEFINE $1 DELETE } } } IF($?prompt) { PROMPT $prompt\n DEFINE prompt DELETE 2 ELSE { PROMPT : 2 IF($?device) { DEVICE $device 2 ELSE { DEFINE device nodevice 2 IF($?default_font && $?TeX_strings == 0) { echo You can only define a default font if you use TeX } IF($?history_char) { # use $history_char as history character IF('$history_char' != '0' && '$history_char' != '1') { EDIT history_char $history_char } EDIT ^ ^ DEFINE history_char DELETE } # load the default macros DEFINE mfiles < stats utils > # $mfiles is used by `sav' FOREACH f ( mongo $mfiles ) { MACRO READ "$!macro"$f 2 FOREACH var ( x_col y_col data_file ) { DEFINE $var . 2 # load uppercase if defined in .sm file IF($?uppercase) { MACRO READ "$!macro"uppercase } # and overload keywords such as erase, if so desired set_overload $?overload # and some keymaps IF($?edit) { READ EDIT "$!edit" 2 # and an optional macro file, with macro startup2 IF($?macro2) { MACRO READ "$!macro2"default IF(is_set(startup2,1)) { startup2 2 # startup2 is defined } # provide a \n after the IFAs this macro is executed every time that you run SM, let us consider it in some detail. After setting the prompt, it looks for entries for a number of variables in your `.sm' file. Some (such as
printer
)
are simply DEFINE
d, while some (such as TeX_strings
)
are only DEFINE
d if they
have a non-zero value. Because some of the values might not be numeric,
the comparison is forced to be done on strings by enclosing the quantities
in single quotes.
An entry prompt
is interpreted as a primary prompt, mostly for
compatibility with the use of $prompt2
to set the secondary prompt.
If device
is defined it is used to set the default plotting
device, and both it and printer
are used by a couple
of macros (hcopy
and hmacro
) that produce hardcopy.
The variables
TeX_strings
and default_fonts
are used in producing
labels (see section SM's Fonts).
Because TeX uses ^
for superscripts, we
allow you to put a history_char
line in `.sm' to specify a
character to use rather than ^
for history (I use `
).
If you use 0
, or omit the value (so it is set to 1
), no
history character is defined to replace ^
.
The variable file_type
is used by the IMAGE
command to
determine the file format that you use (e.g. C, or unformatted fortran).
Startup
doesn't have to check that macro
was successfully
defined as it must have been found for startup
to have been read
in the first place. Macro
specifies where to look for macro libraries,
and startup
next sets the variable mfiles
containing the
names of some of
the system macros to be loaded, and reads them.
The macro load
defined below also maintains the mfiles
list, as does unload
. It is used by the
sav
macro, which is discussed below the main listing of macros that
follows.
We also set some variables used by the id
macro.
As part of our effort to be nice
to users, if you have uppercase 1
in your `.sm' file,
we also load the uppercase
macros.
Next startup
overloads some keywords if overload
is
in your `.sm' file, reads a file of keybindings (if edit
is given in `.sm'), and
finally tries to read a second optional macro directory
macro2
, and executes a macro startup2
if it's defined
(that's what the macro is_set
is checking).
This is quite important, as it provides a way to customise SM
to your personal taste without convincing the local SM guru
that your taste should be foisted on everyone. If you want a prompt that
is different, or a definition of q
that just quits without asking
questions, you can get them by using macro2
.
You can see that it is possible
to tailor SM pretty much as you wish without changing a line of
code, just by playing with the startup
macro.
SM provides various compatibility
macros, and some to package often-used functions.
The macro files `stats' and `utils', which are read when SM
is started, provide various useful
macros, a few of which are presented here. To see a current list, either
look at the files directly, set VERBOSE
to zero and list all the
macros, look at the listing in this manual (see section The System Macro Libraries),
or use lsm
to list macro files
(this only works if you are running Unix; try lsm demos
).
We give here a number of macros taken from the files `default',
`mongo', `stats', and `utils'.
Among those not listed are those like lin
defined to be lines
that are pure
abbreviations, those like xlogarithm
defined as
SET x=lg(x)
which provide functionality in a perhaps familiar form,
and many more like those that are given here which provide
enhancements (e.g. the macro barhist
).
A discussion of a few of the more interesting or obscure follows.
Keywords are written in uppercase, because you might have been playing
tricks with overloading the lowercase equivalents.
Many of these macros, in fact all from `default' and `mongo',
start with ##
so as not to show up in listings made when VERBOSE
is 0, and so as not to be SAVE
d. In the interest of
brevity we have omitted most of these initial comments.
cumulate 2 # Find the cumulative distribution of $1 in $2 DEFINE sum 0 SET $2=0*$1 SET HELP $2 Cumulation of $1 DO i=0,DIMEN($1)-1 { DEFINE sum ( $sum + $1[$i] ) SET $2[$i] = $sum } define sum delete da 1 DATA "$1" del1 1 DELETE HISTORY \n dev 1 del1 DEFINE device $1 DEVICE $1 dra 2 # Draw, accepting expressions define 1 ($1) define 2 ($2) draw $1 $2 edit_hist # Edit the history list del1 MACRO all 0 100000 # define "all" from buffer WRITE STANDARD Editing History Buffer\n MACRO EDIT all # do the editing DELETE 0 100000 # empty history buffer WRITE HISTORY all # replace history by "all" era del1 ERASE gauss 1 # Evaluate a Gaussian : N($mean,$sig) SET $0 = 1/(SQRT(2*PI)*$sig)*EXP(-(($1-$mean)/$sig)**2/2) get 2 # Syntax: get i j. Read a column from a file. # Name of vector is jth word of line i. DEFINE nn READ $1 $2 echo reading $nn\n READ $nn $2 SET HELP $nn Column $2 from $data_file DEFINE nn DELETE hardcopy DEVICE nodevice # close old device hcopy 13 ## hcopy [printer] [l1] [l2] Make hardcopy of playback buffer # optionally specify printer ($1) and desired lines ($2-$3) # if the printer ($1) is omitted (i.e. $1 is missing or a # number), it will be taken from the value of the environment # variable PRINTER, if defined. IF($?printer == 0) { DEFINE printer ? { what kind of printer? 2 } IF($?1) { IF(WHATIS($1) == 0) { # a number if($?2) { DEFINE 3 $2 2 DEFINE 2 $1 DEFINE 1 DELETE } } IF($?1) { DEVICE $printer $1 2 ELSE { IF($?PRINTER == 0) { DEFINE PRINTER : 2 # which one? IF($?PRINTER) { DEVICE $printer $PRINTER 2 ELSE { DEVICE $printer } } IF($?2 == 0) { DEFINE 2 0 DEFINE 3 10000 2 ELSE { IF($?3 == 0) { DEFINE 3 $2 2 } playback $2 $3 \n DEVICE $device bell hmacro 12 ## hmacro [macro] [printer] Make hardcopy of a macro # If only 1 argument is present, it is taken to be the printer # unless an environment PRINTER variable is defined, when # that's used as a printer, and the argument is taken to be # a macro. If no macro is specified, make a temp one IF($?printer == 0) { DEFINE printer ? { what kind of printer? 2 } del1 IF($?2 == 0) { # only one arg IF($?PRINTER == 0) { DEFINE PRINTER : 2 IF($?PRINTER) { DEFINE 2 $PRINTER } } IF($?1) { if($?2) { # 2 args DEFINE _mac $1 DEFINE _temp 0 # no temp macro 2 ELSE { # 1 arg, take as printer DEFINE 2 $1 # printer DEFINE _temp 1 # need temp macro } 2 ELSE { # no $1 IF($?2 == 0) { DEFINE 2 " " 2 DEFINE _temp 1 # need temp macro } IF($_temp) { DEFINE _mac _mac echo "Create temporary macro, exit with ^X" MACRO EDIT $_mac IF(is_set($_mac,1) == 0) { DEFINE _mac DELETE DEFINE _temp DELETE DEFINE _test DELETE RETURN } } DEVICE $printer $2 $_mac \n DEVICE $device IF($_temp) { MACRO $_mac DELETE 2 DEFINE _mac DELETE DEFINE _temp DELETE bell load # load macros in default directory DEFINE macro : # get default directory MACRO READ "$!macro"$1 # read macro file IF($?mfiles == 0) { DEFINE mfiles $1 2 ELSE { DEFINE 3 0 FOREACH 2 ( $mfiles ) { IF('$2' == '$1') { DEFINE 3 1 2 } IF($3 == 0) { DEFINE mfiles < $mfiles $1 > 2 } load2 1 # load macros in (second) default directory DEFINE macro2 : # get directory IF($?macro2) { MACRO READ "$!macro2"$1 # read macro file 2 ELSE { echo Directory macro2 is not defined } logerr 3 # logerr x y error, where y is logged, and error isn't SET _y = 10**$2 SET d_y = LG(_y + $3) - $2 ERRORBAR $1 $2 d_y 2 SET d_y = $2 - LG(_y - $3) ERRORBAR $1 $2 d_y 4 DELETE _y DELETE d_y lsq 4 # Do a least squares fit to a set of vectors # Syntax: lsq x y x2 y2 Fit line y2=$a*x2+$b to x y SET _n = DIMEN($1) # number of points SET _sx = SUM($1) # Sigma x SET _sy = SUM($2) # Sigma y SET _sxy = SUM($1*$2) # Sigma xy SET _sxx = SUM($1*$1) # Sigma xx DEFINE a ( (_n*_sxy - _sx*_sy)/(_n*_sxx - _sx*_sx) ) DEFINE b ( (_sy - $a*_sx)/_n ) SET $4=$a*$3+$b FOREACH v ( _n _sx _sy _sxy _sxx ) { DELETE $v 2 playback ## define "all" from buffer, and run it # with args, only playback those lines IF($?1 == 0) { DEFINE 1 0 DEFINE 2 10000 2 ELSE { IF($?2 == 0) { DEFINE 2 $1 2 } del1 MACRO all $1 $2 all read_old 1 del1 # read a Mongo file onto the history buffer READ OLD temp $1 WRITE HISTORY temp MACRO temp { DELETE 2 rel 2 # Relocate, accepting expressions define 1 ($1) define 2 ($2) relocate $1 $2 reverse 1 # reverse the order of a vector SET _i = DIMEN($1),1,-1 SORT < _i $1 > DELETE _i sav 1 # Save to a file $1, don't save from files `$mfiles' _save $1 _save 1 # Save to a file $1, don't save from files `$mfiles' del1 FOREACH 2 ( $mfiles ) { MACRO DELETE "$!macro"$2 2 DEFINE 2 0 define 2 ? { save vectors? 2 SAVE "$!1" 1 $2 1 FOREACH 2 ( $mfiles ) { MACRO READ "$!macro"$2 2
Cumulate
is given as a way not to write macros if you can
help it (in this case, I couldn't). A better example is reverse
which reverses the order of
the elements in a vector without resorting to a DO
loop.
The macro da
could have been defined to be DATA
, but there
are various special characters that appear in filenames;
try data /usr/spool/junk
or
data disk$data:[ETHELRED]junk.dat
. The macro da
provides a set of double quotes to escape these unwanted interpretations.
Incidently, da "/usr/spool/junk"
won't work.
DELETE HISTORY
deletes the last command on the history buffer, so
del1
alone on a line will delete itself, which can be used to
prevent a command from appearing on the history
list, for example changing devices with dev
. Dev
also defines
a variable device
which is used by the hcopy
and hmacro
macros to make hardcopies, while returning you to your initial device. The
startup
macro listed above also sets device
, if it is specified
in your `.sm' file. You should be careful not to include more
than one del1
macro in any macro that you write yourself, as
each del1
will remove a command from history and you could find commands mysteriously
disappearing.
Gauss
evaluates a Gaussian, e.g. SET x=-3,3,0.05 SET g=gauss(x)
lim x g box con x g
, an example of using a macro like a function definition.
(For this example to work, you have to define variables mean
and
sig
first).
There is an example of reading variables from files and using
them in macro get
. This reads a word from a line in a file with
the DEFINE nn READ i j
command, which sets $nn
to be the
j
th word on
line i
of the current data file. This variable is then used to
READ
a
vector, which is given the appropriate name. So if a file looks like:
This is an example file alpha beta gamma delta 1 10 0.1 1e1 2 20 0.2 1e2 3 30 0.3 1e3 4 40 0.4 1e4 5 50 0.5 1e5then the commands
GET 2 1 GET 2 2 GET 2 3 GET 2 4will read `1 2 3 4 5' into vector
alpha
, `10 20 30 40 50' into beta
and so
forth. Note that
DEFINE READ file_id 1 LABEL $file_idwill write out `This is an example file' to the current position of the plot pointer (see, e.g.
RELOCATE
). Incidently, READ ROW omega 5
would set the vector omega
to have values `3 30 0.3 1e3'.
The macros hcopy
and hmacro
make hardcopies of, respectively,
the playback buffer and a macro. Both assume that the variables
device
and printer
are set. device
is set from
your `.sm' file and by the dev
macro; printer
is assumed
set in `.sm'. (See `startup' file above). If all is well, the macros
switch to device printer
(with an argument to specify which
sub-printer is desired. We have so many laser printers here...), execute
the desired commands, and return to the initial device
. When the
printer
device is closed, hardcopy will result. Note the use of
\n
to ensure that no nasty things happen;
if there were no \n
and the buffer ended with LABEL Hi
, the
plot could appear with a label Hi device tek4010
.
The versions of hcopy
and hmacro
given here
accept a variable number of arguments (`13' means up to 3 arguments).
The first (if present) is
taken to be the desired laser printer
@footnote #{Actually, if the environment (VMS: logical)
`.sm' variable PRINTER
is defined the macros pretend that
it was the first argument, so you can simply type hcopy
.}
, the next argument is the number
of the first line that you want played back, and the third is the last
line number. (If you omit both line numbers you'll get the whole
buffer; if you omit the second you'll just get the one line).
The macro sees what it has been given by using $?
to see which
variables are defined, and acts accordingly. Hmacro
is somewhat
similar, except that if you omit an argument it is taken to be the
macro name, and a temporary one is created for you.
The playback
macro deals
with its arguments in a similar way, and is discussed further in the examples
at the end of this section.
load
enables you to read a set of macros from a directory
specified as macro
in your environment file.
Load2
is similar, but it looks in directory macro2
. The macro
unload
(not listed here) will undefine the load
ed macros.
Note that a list of all the load
ed macros is kept in $mlist
, which is used by the sav
macro to avoid SAVE
ing
lots of system macros. Sav
is written in terms of a macro
_save
so that it won't itself be forgotten (by MACRO
DELETE
) while in the middle of saving macros.
If you want to put errorbars on logarithmic plots, logerr
is the macro
you've been looking for. It calculates the correct length for the errorbars,
and plots them de-logging and re-logging as appropriate.
The macros rel
and dra
illustrate a method of using expressions,
rather than numbers, in the commands RELOCATE
and DRAW
. There
are Good Reasons why DRAW
won't accept an expression
directly (see section The Command Interpreter).
These macros exploit the fact that the arguments to a macro are whitespace
delimited, so a string such as 1+2/$x
comprises one argument.
Redefining the arguments means that the macros don't have to define,
and then delete, a couple of variables to hold the expressions.
Now that you have had your appetite whetted, we strongly recommend that you take the time to look through the other macros that are available (see section The System Macro Libraries). Otherwise how would you know that there are macros to draw arrows on plots, do KS and Wilcoxon tests on vectors, and a host of other good things?
Go to the previous, next section.