We describe here the steps needed to write an application using the command interpreter library.
Step 1 - The function prog_c and the way initialization files are used
The interperter is called with the function
void prog_c(int argc, char *argv[], char *A, char B[], int n, char *pr, int cas);of the library. The main function of the program should contain 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 wait for new commands when the command file is finished. This way of using the interpreter can be used for instance 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.
As explained in 3 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[]) { Funcs = Funcs_interp; _NBFONC = _NBFONC0; . . . prog_c(argc, argv, "interp.ini", NULL, 0, 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[]) { Funcs = Funcs_interp; _NBFONC = _NBFONC0; . . . prog_c(argc, argv, NULL, int_txt, int_nb, NULL, 0); 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 interp_convert (in the directory convert of the distribution). For instance, if the initialization file is interp.ini the program interp_convert is used like this
interp_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.
Step 2 - The name of the custom initialization file
The name of the custom initialization file must be specified, using the variable User_Init_File, when a built-in initialization file is used when the program is run for the first time. It can be NULL, an then the internal initialization file will always be used. If it is not NULL, a copy of the internal initialization file will be made on a file in the user's home directory the first time the program is used, with the specified name. This new initialization file will be used in subsequent executions of the program. It can be of course modified (for instance the user can specify a new command and result directories). For instance
extern int int_nb; extern char int_txt[]; int main(int argc, char *argv[]) { Funcs = Funcs_interp; _NBFONC = _NBFONC0; . . . User_Init_File = ".init_file"; prog_c(argc, argv, NULL, int_txt, int_nb, NULL, 0); return 0; }
Step 3 - The initialization functions init_prog and exit_prog
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 may contain for instance a call to the function exit() to end the program.
Step 4 - Initialization function for additional expression evaluators
The function init_expr_GEN must be written (cf .7.7). It can be empty if no additional expression evaluator are defined. The array Funcs_Gen[] of functions corresponding to the new expression evaluators must also be defined.
Step 5 - Thread-specific functions
Each thread (in particular the main thread) will call the functions
void init_thread_param(flow_data *) void clean_thread_param(flow_data *)
that must be provided by the user (see 10.4.2). If the application needs no thread-specific parameters, these functions can be empty.
Step 6 - Commands and numeric functions
The following must also be declared in some source file (outside functions)
FUNCTION *Funcs; FUNCTIONC *Funcs_C; pfi *proc[]={ . . . };
(see 5, 7.2). The values of Funcs, Funcs_C and of the corresponding integers _NBFONC, _NBFONC_C (cf. 7.2, 7.7.1) must be defined before the function prog_c is called. To use the default values provided by the library we can do
Funcs = Funcs_interp; _NBFONC = _NBFONC0; Funcs_C = Funcs_interp_C; _NBFONC = _NBFONC0_C;
Step 7 - The function dest_prop
The user must also write the function
void dest_prop(int, int);
(which can be empty) cf. 6.6.
Step 8 - User defined sections of the initialization file
Two definitions must be provided by the user :
pfib procb_user[] = { func1, . . funcn, NULL, }; char *namesb_user[] = { name_1, . . . name_n, "", };
where name_1,..., name_n are the names of the new sections, and func1,..., funcn the associated functions. They are of the following type :
int func1(FILE *, char *, flow_data *)
To see how they can be written see the file com_sys.c which contains the functions corresponding to the builtin sections of the initialization file.
Even if no user defined sections will be defined the two preceeding definitions must be done. In this case we only put
pfib procb_user[] = { NULL, }; char *namesb_user[] = { "", };