<name_of_file
will launch the reading of the file and the execution of all the commands in it.
The second way is to write programs (i.e. sequences of commands or calls to programs), load them and execute them as commands.
Both command files and programs accept parameters and can call programs or read command files.
In a prior version of the command interpreter the possibility to load
and execute programs was not implemented. Programs are easier to use and
run faster than command files. Moreover everything done will command files
can also be done with programs. Nevertheless the possibility to use command
files has been kept in this version of the command interpreter.
Example : Suppose that the command file x.cmd contains the following lines
Xcom1 #1
#2
Xcom2
Xcom3 #2
Then the command
<x.cmd A B
will produce the execution of
Xcom1 A
B
Xcom2
Xcom3 B
(provided that the commands Xcom1 , Xcom2 , Xcom3 mean something).
In a command line, in expressions of type {1, {2, ..., a substitution
of # to { is made.
Example :
- interpreter
-> a=1
1.000000
- interpreter
-> b=-2
-2.000000
- interpreter
-> newvar=a+b
-1.000000
(here - interpreter -> is the prompt of the interpreter). It is possible also to insert spaces :
- interpreter -> newvar = a + b
This will give the same result, except of course if you have a command called newvar . So in general it is better to put no spaces inside a numerical expression.
It is possible to substitute the value of a numerical expression to this expression in strings of characters. Suppose for example that you have a command defobj1 defining some type of objects (cf section 5), and want to create objects p_0 , p_1 , p_2 , and so on up to n (a variable). This is the correct way to write it in a program :
do i
0 n
defobj1
p_!(i)
enddo
(for the do loop, see section 3.6). Here the numerical expression i is converted to an integer, and this integer is substituted to !(i) in the argument. It is possible to put any kind of numerical expression inside !() (for example !(i*j+2) ). It is possible also to substitute floating point values : if you write
defobj1 p_%(i)
you will obtain p_0.000000 , p_1.000000 , p_2.000000 , and so on up to n .
The library contains some functions that can be used to evaluate the arguments of commands with the expression evaluator (cf. &6). For example if the command Xcom1 needs a floating point parameter, it may be useful to be allowed to write
- interpreter -> Xcom a*(b+cos(x))
as well as
- interpreter -> Xcom 2.252
In this case the parameter must be parsed inside the C-function corresponding
to the command Xcom , using the appropriate
function of the library (cf. section
6).
- interpreter -> si ccc
where ccc is a variable name. In this case the interpreter will evaluate ccc . If the resulti is 0 or negative, the commands that follow will be ignored, until the interpreter receives the command
- interpreter -> is ccc
and then the commands will be again accepted. It is also possible to avoid the following instructions if ccc is positive, by using
- interpreter
-> si non ccc
Example :
interpreter ->
c=1
1.000000
interpreter ->
d=-1
-1.000000
interpreter ->
a=24
24.000000
interpreter ->
si c
interpreter ->
a
24.000000
interpreter ->
si d
interpreter ->
a
interpreter ->
is d
interpreter ->
a
24.000000
interpreter ->
si non d
interpreter ->
a
24.000000
interpreter ->
is d
interpreter ->
is c
The maximal number of current conditions (not closed with is...) is
fixed in the initialization file (cf. section
2.1).
interpreter -> <name_of_file arg1 arg2 ...
where name_of_file is the name of the command file, and arg1 , arg2 ,... are the arguments (if any, cf. section 3.2). It the command file is somewhere else than in the command directory, its adress relatively to this directory must be given, instead of its name.
A command file can call other command files or programs too. Comments
may be written in command files, in lines beginning with the character
; .
This can be done by using the commands loop ... , loopf... and repete ... The instruction
interpreter -> loop com1 com2 n1 n2 n3 par1 par2 ...
will create a command file called com1 (in the command directory). This file will contains n1 successive calls to com2 with the parameters
n2 par1
par2...
n2+n3 par1
par2...
.
.
n2+(n1-1)*n3
par1 par2...
Here n1 , n2
, n3 are numerical expressions that will
be evaluated as integers. There is a similar command loopf...
which
is the same except that n1 , n2
, n3 will be evaluated as floating point numbers.
Example : The instruction
interpreter -> loop com1 com2 4 100 10 A
will produce the command file com1 wich contains :
<com2
100 A
<com2
110 A
<com2
120 A
<com2
130 A
and
interpreter -> loopf com1 com2 4 100.5 0.1 A
will produce the command file com1 wich contains :
<com2
100.500000 A
<com2
100.600000 A
<com2
100.700000 A
<com2
100.800000 A
The instruction
interpreter -> repete com1 com2 xx1 xx2
will create a command file called com1
(in the command directory). This file will contain successive calls to
the command file com2 , the first with
the argument xx1 , the second with the argument
xx2 , and so on.
Example : The instruction
interpreter -> repete com1 com2 44.00 22 125 36
will produce the command file com1 wich contains :
<com2
44.00
<com2
22
<com2
125
<com2
36
It is possible also to create command files with commands containing
#1 (or #2, etc.). This can be done by replacing the # in the command line
by {.
Example : The instruction
interpreter -> loop com1 com2 4 100 10 {1
will produce the command file com1 wich contains :
<com2
100 #1
<com2
110 #1
<com2
120 #1
<com2
130 #1
Programs can reside in files (in the command directory, cf. section 2.4) or in the initialization file. A program file can contain several programs. A program begins in the following way
: name
n1
n2 ...
mode1 mode2
where name is the name of the program (don't forget the : before), and n1 , mode1 , mode2 ,..., n2 are integers.
The first integer n1 , is the number of arguments needed by the program.
The second integer n2 must be 0 or 1. If it is 0, the program will run silently, i.e. the successive instructions that it contains will not be printed on screen. This is useful if the program produces the execution of many instructions, if it contains loops for example. It is possible to run silently only a part of a program, by using the command silence... (cf. section 8). It is also possible to print something on screen inside a silent program (or part of program), by using the commands echo , echoi and echof (cf. section 8).
The integers mode1 , mode2 ,... are the running modes where it is allowed to use the program (cf. section 2.2). If the only mode -1 is put here, then the program can be used in all the running modes.
In a program file, a program ends when another one begins or when the file ends. A program can call other programs or command files.
Programs written in the initialization file will be loaded when the interpreter begins to run. Program files can be loaded using the command load . For example the instruction
interpreter -> load prog.cmd
will load the program file prog.cmd which resides in the command directory. The command
interpreter -> proglist
prints the list of all the loaded programs. If prog1 is one of them, the instruction
interpreter -> proglist prog1
prints the list of all the instructions of the program prog1 . The instruction
interpreter -> delprog prog1
deletes the program prog1 . Comments
may be written in programs, using lines beginning with the character
; .
3.6.2 Labels, conditional jumps and loops
A label in a program is a line of the following type
name:
where name is a string of characters (with no '#', '{', '&' or ':') followed by a ':'. It is possible to jump to this line (inside the same program) by using the instruction
goto name
It is possible also to make conditional jumps by testing the value of numerical expressions. The instruction
if> expr name1
will jump to label name1: or not, according to the numerical expression expr . If it is positive the program jumps to name1: , otherwise it goes to the next line. The label must of course exist somewhere in the program. It is also possible to test if an expression is negative or zero, by using
if< expr name1
in the first case, and
if= expr name1
in the second case.
The syntax of loops is as follows :
do var
var1 var2 incr
.
.
.
enddo
where var is a variable name, var1 , var2 and incr are numerical expressions. It is not necessary to define var before using it in this loop. Initially, var is set to var1 and in each step it if incremented by adding incr . The loop ends when var becomes larger than var2 . This will always work if var2 and incr are constant during the loop and incr is positive, and definitely never if var2 is constant and incr negative or zero. The parameter incr can be omitted. In this case it is assumed to be 1. It is possible to nest loops.
In fact there is not a real implementation of loops, but rather a translation
of the instructions do ..., enddo
when the program is loaded, using conditional jumps. It is possible to
see this by listing a program containing loops.
Example : Suppose that the file prog.cmd in the command directory contains the following lines :
:example1
3
1
-1
x=0
do i
#1 #2
x=x+i*i
enddo
Given two numbers a and b this program computes the sum of the integers between a and b.
The instruction
interpreter -> proglist example1
prints the following on the screen
x=0
i=#1-1
0:
i=i+1
if> i-(#2)
1
x=x+i*i
goto 0
1:
3.6.3 Questions and answers inside programs
It is possible that inside a function called by a command some data are asked to the user of the program. A standard way to do this is as follows :
int
i;
float
x;
printf("Enter
an integer : ")
scanf("%d", &i);
printf("Enter
a number : ")
scanf("%f", &x);
This is not good inside a program of the command interpreter, if you don't want it to stop to wait the answers. Instead of scanf one can use the library functions
void
read_int(int *);
void
read_float(float *);
void
read_char(char *);
(the last to read character strings). The program becomes
int
i;
float
x;
printf("Enter
an integer : ")
read_int(&i);
printf("Enter
a number : ")
read_float(&x);
In this case, the functions will behave like scanf if they are used in a command in a interactive way (i.e not in a program). Moreover the entered values will be parsed by the expression evaluator; you can enter for example :
Enter an
integer :
2*k+5
Enter a
number :
cos(y)+2*c-4.
If the command corresponding to the function containing this piece of code is used inside a program, the interpreter will read the following lines of the program (2 in this example). So the program of the command interpreter could look like
.
.
command_name
arg1 arg2 ....
2*k+5
cos(y)+2*c-4.
.
.
mon xxx
where xxx is a file name. If this instruction is given, the file is created if it did not exist, otherwise it is erased. All the subsequent instructions and messages of the command interpreter will be written not only on screen but also in this file, until the program ends, or the instruction end_mon appears. In the later case, the monitor file is closed. For the messages that come from functions written by the user, the function
void print(char*, ...);
can be used instead of the usual printf
. This function prints on screen and on the monitor file, if it has been
defined. Only the flags %d , %f
and %s have been implemented.