Simple Scripted Program

This program demonstrates some of the basic features provided by the libgfx scripting package. Given a list of file names on the command line, it reads each of them in turn and executes the scripting commands contained within them.

Setup and Initialization

The program begins by including the headers for the libgfx modules which it uses:

#include <gfx/gfx.h>
#include <gfx/script.h>
#include <gfx/vec3.h>

The main() application entry point performs a very simple task. It loops over every file name specified on the command line and executes it as a script.

main(int argc, char *argv[])
{
    for(int i=1; i<argc; i++)
	script_do_file(argv[i]);
}

Note that it does not need to perform any initialization of the scripting system. This is because the registering of command procedures (or handlers) is done automatically at startup, before main() is ever called. The code that accomplishes the necessary initialization is

static script_defn handlers[] = {
    {"add", proc_add},
    {"avg", proc_add},
    {"echo", proc_echo},
    {"vec3", proc_vec3},
};

REGISTER_COMMANDS(handlers);

Command Procedures

Every scripting command is handled by some command procedure. The registration code above binds the actual procedures to the names of their scripting commands. Then, whenever a given command occurs in a script being processed, the corresponding handler is invoked.

The first command procedure actually implements two scripting commands: add and avg. It determines which command has been invoked by examining its name argument. It treats its command line as a whitespace-separated sequence of numbers, either adds or averages all of them, and then prints the result.

int proc_add(const char *name, char *argline)
{
    double sum = 0.0;
    double x;
    int count = 0;

    while( string_shift_numbers(&argline, &x, 1)==1 )
    {
	sum += x;
	count++;
    }

    if( !strcmp(name, "avg") && count!=0 )
	sum /= (double)count;

    cout << sum << endl;
    return SCRIPT_OK;
}

This next procedure requires precisely 3 numeric arguments, from which it constructs a 3-D vector using the Vec3 class. If the number of arguments is not 3, it returns a value indicating a syntax error occurred.

int proc_vec3(const char *name, char *argline)
{
    Vec3 v;

    if( string_shift_numbers(&argline, v, 3) != 3 )  return SCRIPT_ERR_SYNTAX;

    cout << v << endl;
    return SCRIPT_OK;
}

Finally, the echo procedure does not interpret its arguments at all. Instead, it simply prints the entire argument line as is.

int proc_echo(const char *name, char *argline)
{
    if(argline) cout << argline;
    cout << endl;
    return SCRIPT_OK;
}

Sample Execution

To demonstrate the action of this sample program, here is a particularly simple script.

# This is a test script meant to be fed to t-script.  It is not meant as an
# exhaustive test, but mainly as a demonstration.

echo The following sum should be 15
add 1 2 3 4 5

echo
echo The following average should be 3.5
avg 3 8 2 1

echo
echo The following is the vector [1 0 0]
vec3 1 0 0

When given to the sample program, it produces the following output

The following sum should be 15
15

The following average should be 3.5
3.5

The following is the vector [1 0 0]
1 0 0