libmawk example − how to use the library
#include <libmawk.h>
Libmawk is a library that lets applications to embed awk scripts using the code of the popular implementation mawk. The normal process is to call libmawk_initialize() to set up a new mawk context (with script(s) loaded), then in the main loop feed it using libmawk_append_input(). For "out of band" communication, the program may also call functions implemented in awk and read (or modify) global variables of the awk script. The hos tapplication usally will also bind some of its functions to the context using libmawk_register_function, which allows the awk script to call the host applicaiton’s functions directly as they were awk builtins or user defined functions. After the main loop, the application destroys the context freeing up all memory allocated for the script(s).
One context is for one awk program. One awk program may consist of multiple script files (just as with command line awk, with multiple -f filename arguments). Libmawk is instance safe, the host application may create multiple instances of contexts with the same or with different set of awk scripts loaded. These contexts are totally separate, no variables, functions or any sort of states are shared. However, the host application may provide means of communication between those scripts by custom functions or by copying variable contents between them.
The following
example application creates a single context to demonstrate
all the above mentioned functionality.
#include <stdio.h>
#include <libmawk.h>
CELL
*blobb(mawk_state_t *context, CELL * sp, int a_args)
{
int n; |
|||
char buff[64]; |
|||
/* do something - print BLOBB and all arguments */ |
|||
printf("BLOBB! "); |
|||
for(n = a_args-1; n >= 0; n--) |
|||
printf("%d=’%s’ ", n, libmawk_print_cell((sp-n), buff, sizeof(buff))); | |||
printf("0); |
|||
/* restore the stack (remove all arguments) */ |
|||
sp = sp - a_args; |
|||
/* set a return value (find out where the return value is on the stack, |
|||
using libmawk_stackret()) */ |
|||
libmawk_set_cell(context, libmawk_stackret(sp), ’f’, (double)1234); |
|||
/* return the new stack pointer - should be the one that it was before |
|||
arguments had been pushed on the stack */ |
|||
return sp; |
}
int main(int
argc, char **argv)
{
mawk_state_t *m; | |
CELL ret, arrv, *vr; | |
char buff[64]; |
/* the simpler way is:
m = libmawk_initialize(argc, argv); | |
However, if the application wants to change the environment before | |
executing BEGIN, the following, 3 stage initialization should be done: |
*/
m = libmawk_initialize_stage1(); /* set up m */ |
|||||
custom_array_init(m); /* set up a new builtin array with side effects, before parsing scripts */ |
|||||
m = libmawk_initialize_stage2(m, argc, argv); /* parse args loads the script(s) */ |
|||||
m = libmawk_initialize_stage3(m); /* execute BEGIN {} */ |
|||||
ret.type = C_NOINIT; |
|||||
if (m != NULL) { |
|||||
/* test function call */ |
|||||
if (libmawk_call_function(m, "func", &ret, "dfs", (int)42, (double)1.234, (char *)"test string.") == 0) { |
|||||
printf("Return value of func is ’%s’0, libmawk_print_cell(&ret, buff, sizeof(buff))); |
|||||
libmawk_cell_destroy(m, &ret); |
|||||
} |
|||||
printf("Failed to call func()0); |
|||||
/* this is the same function call with a different syntax */ |
|||||
{ |
|||||
int i = 42; |
|||||
double d = 1.234; |
|||||
char *s = "test string."; |
|||||
void *args[] = {&i, &d, s}; |
|||||
if (libmawk_call_functionp(m, "func", &ret, "dfs", args) != 0) { |
|||||
printf("Return value of func is ’%s’0, libmawk_print_cell(&ret, buff, sizeof(buff))); | |||||
libmawk_cell_destroy(m, &ret); | |||||
} |
|||||
} |
|||||
/* register a C function (resolved runtime) */ |
|||||
if (libmawk_register_function(m, "blobb", blobb) != 0) { |
|||||
fprintf(stderr, "ERROR: Unable to register function blobb0); |
|||||
} |
|||||
/* run some data */ |
|||||
libmawk_append_input(m, "This is a0ultiline test input0ut in the artificial input buffer.0); |
|||||
libmawk_run_main(m); |
|||||
/* print var: scalar */ |
|||||
vr = libmawk_get_var(m, "var"); |
|||||
if (vr != NULL) |
|||||
printf("Variable var = ’%s’0, libmawk_print_cell(vr, buff, sizeof(buff))); |
|||||
else |
|||||
printf("No such variable |
|||||
/* print var: array */ |
#warning TODO
arrv.type = C_NOINIT; |
||||
if (libmawk_get_array_at(m, "arr", "hello", &arrv, 0) > 0) |
||||
printf("Variable arr[ | ||||
else |
||||
printf("No such variable |
#warning todo: array set
/* set var: array; change the existing (arr["hello"]) */ |
|||||
// |
if (ret != NULL) |
||||
// |
libmawk_set_cell(m, ret, ’s’, "WORLD"); | ||||
/* set var: array; create a new index */ |
#warning todo: array set
// |
libmawk_get_array_at(m, "arr", "bye", &arrv, 1); | |||
// |
libmawk_set_cell(m, ret, ’s’, "universe"); | |||
/* run some more data */ | ||||
libmawk_append_input(m, "Second0); | ||||
libmawk_append_input(m, "run.0); | ||||
libmawk_run_main(m); | ||||
custom_array_print(m); | ||||
/* run end */ | ||||
libmawk_uninitialize(m); | ||||
} |
||||
else { |
||||
printf("Init failed.0); | ||||
} |
||||
printf("END0); |
||||
return 0 ; |
}