The files that are useful for an application of the command interpreter
are the library itself libinter.a
(or libint_m.a for the mini-interpreter)
and the file interp.h which should
be included by each source file where functions of the library are used.
One or several initialization files must also be written for each
application. In the version 1.2 of the command interpreter the names of
the built-in commands must not be put in an initialization file, they are
already known by the interpreter. The user is concerned only by the new
commands of the application.
void prog_c (int argc, char * argv[], char * A, char B[], int n);
The main function of the program should contain only a call to the function prog_c , and should be written as follows :
int
main(int argc,
char * argv[])
and the parameters argc and argv[] are passed to the function prog_c . If the main program has no argument, the interpreter will execute the command given in the !init section of the initialization file (if this section is present) and then the interpreter will wait for new commands. If the !init section exists, the greeting message will not be printed. If there is an argument for the main program it will be used as a filename which will be executed as a command file. The program will then run silently (the commands in the file will not be printed) and stop when the command file is finished. This way of using the interpreter can be used for example with programs like Geomview that can use external modules. In this situation, Geomview creates pipes connected to the interpreter output, and interprets this output as graphics .
Before running the interpreter, the function prog_c will call the function
void init_prog (void)
which must be provided by the user, and contains all the initializations required by the program. It may be an empty function.
After the exit command that terminates the execution of the interpreter the function
void exit_prog (void)
will be called. It must also be written by the user, and must contain at least a call to the function exit() to end the program.
As explained in section 2 there are two ways of using the initialization file. The first way is to let the interpreter read it at the beginning of the execution, the second way is to include it in the executable file. In the first way the main function will be like this
int
main(int argc,
char * argv[])
{
prog_c(argc, argv, "interp.ini", NULL, 0);
return 0;
}
Here interp.ini is the name of the initialization file. In the second way the main function will be like this
extern
int int_nb;
extern
char int_txt[];
int
main(int argc,
char * argv[])
{
prog_c(argc, argv, NULL, int_txt, int_nb);
return 0;
}
Here the array int_txt and the
integer int_nb are defined in an
auxilliary source file. This source file is produced from a usual initialization
file, using the utility
convert (in the directory of
the same name of the distribution). For example, if the initialization
file is interp.ini the program
convert is used like this
convert interp.ini init.c int_txt int_nb
This will create the source file init.c defining int_txt and int_nb . This source file must then be compiled and linked with the program. It contains the same information as interp.ini .
The user must also write the function
void dest_prop (int, int);
(which can be empty) cf. section
5.4.
The initialization file for the glogal application must contain the sections that can appear only once (i.e. the sections !param, !rep and !init, cf. section 2). These sections must then be removed from the initialization files of the applications. Then the initialization files of the applications must be included in the main one (for example by using sections !include (cf. section 2.11)). It is now necessary to define the array proc (cf. sections 4 and 11.1.2) containing the function lists of each application, in the same order as the order of the corresponding !func in the initialization files.
There can be problems with the order of the messages defined in the sections !message of the applications. This is why the arguments of the function error_mess in theses applications should be given in an appropriate way : for example if in some application the message number 32 is to be printed we will use something like
error_mess(32 + __APPLI3)
rather than simply error_mess(32).
Here __APPLI3 is a globally defined
variable corresponding to the given application to be glued. It will be
set in the global application : its value is the number of messages defined
in the global initialization file before the !message
section of the given glued application appears. Of course in the particular
application its value is set to 0. The same should be done for the object
or structure types defined in the initial applications.
- In the section !func of the initialization file, suppress all the commands that come from the library.
- In the array proc[] containing the functions corresponding to commands, suppress the functions corresponding to the built-in commands.
- Rename the array proc[] (proc_b for example).
- Add the following somewhere :
pfi *proc[]
=
proc\_b,
};
The directories mini/test and mini/test2 contain the same basic examples for the mini-interpreter (i.e. a smaller version of the interpreter that does not support the complex numbers and objects and structures).
The directory appli contains
two applications of the full command interpreter. The first one (in appli/appli1)
can be used to define and use numerical functions of one real variable.
The second (in appli/appli2) is based
on the graphic library g2 written
by Lj. Milanovic and H. Wagner. The directory appli/glue contains the global
application obtained by glueing the two preceeding ones.
#include
"interp.h"
FUNCTION
*Funcs;
pfi *proc[]
= { } /* Here only the basic commands of
the interpreter
are implemented */
int
main(int argc,
char *argv[])
{
Funcs = Funcs_interp;
/* Default array of functions for */
_NBFONC = _NBFONC0; /* the expression
evaluator */
prog_c(argc, argv, "interp.ini", NULL, 0);
/* the initialization file is interp.ini */
return 0;
}
#include
"interp.h"
extern
int int_nb;
extern
char int_txt[];
pfi *proc[]
= { };
FUNCTION
*Funcs;
int
main(int argc,
char *argv[])
{
Funcs = Funcs_interp;
_NBFONC = _NBFONC0;
prog_c(argc, argv, NULL, int_txt, int_nb);
return 0;
}
For the application funct :
#include "interp.h"
/* include file for the command interpreter library */
#include "funct.h"
/* include file for the application */
int
_XRANGE_F = 1;
int
_XRANGE_D = 2;
int
_RFUNC_F = 3;
int
_RFUNC_D = 4;
int
_CFUNC_F = 5;
int
_CFUNC_D = 6;
int
_FOUR_TR = 7;
int
_BESS_PAR = 8;
int
_FUNC_MESS; /* 0 */
FUNCTION
*Funcs;
pfi *proc[]
=
{
proc_func, /* Array of functions corresponding
to the
additional commands of the application */
};
int
main(int argc,
char *argv[])
{
Funcs = Funcs\_func;
/* Here the application
has its own array of functions
for the expression evaluator */
_NBFONC = _NBFONC_FUNC;
prog_c(argc, argv, "funct.ini", NULL, 0);
return 0;
}
Here _XRANGE_F = 1 is used to
represent the number of the first type of objects defined in funct
: it will be actually 0, and so on for the other object types (see the
source functcmd.c to see how these
variables are used). _FUNC_MESS (here
0) is the number of the first message in funct.
For the application graph :
#include
"interp.h"
#include
"graph.h"
FUNCTION
*Funcs;
int _GRAPH_MESS
= 0;
int _GRAPH_X11
= 1;
int _GRAPH_PS
= 2;
int _GRAPH_COL
= 3;
int _GRAPH_FRAM
= 4;
FUNCTION
*Funcs;
pfi *proc[]=
{
proc_graph,
};
int
main(int argc,
char *argv[])
{
Funcs = Funcs_interp;
_NBFONC = _NBFONC0;
prog_c(argc, argv, "graph.ini", NULL, 0);
return 0;
}
Here _GRAPH_X11 = 1 is used
to represent the number of the first type of objects defined in graph
: it will be actually 0, and so on for the other object types (see the
source graphcmd.c to see how these
variables are used). _GRAPH\_MESS (here 0)
is the number of the first message in graph.
#include
"interp.h"
#include
"funct.h"
#include
"graph.h"
int
_XRANGE_F = 1;
int
_XRANGE_D = 2;
int
_RFUNC_F = 3;
int
_RFUNC_D = 4;
int
_CFUNC_F = 5;
int
_CFUNC_D = 6;
int
_FOUR_TR = 7;
int
_BESS_PAR = 8;
int
_FUNC_MESS = 0;
int
_GRAPH_MESS = 23;
int
_GRAPH_X11 = 9;
int
_GRAPH_PS = 10;
int
_GRAPH_COL = 11;
int
_GRAPH_FRAM = 12;
pfi *proc[]
=
{
proc_func,
proc_graph,
};
int
main(int argc,
char *argv[])
{
Funcs = Funcs_func;
_NBFONC = _NBFONC_FUNC;
prog_c(argc, argv, "glue.ini", NULL, 0);
return 0;
}
Here the numbers corresponding to the objects and messages of
graph are not the same since they are
stored after those of funct. This means
also that the inclusion of the initialization file of funct
is done before that of the initialization file of graph.