libgfx: Simple Scripted Program
Author: Michael Garland

## 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 creates a scripting environment (`class CmdEnv` and registers a set of scripting commands. Once these handlers have been installed, it loops over every file name specified on the command line and executes it as a script.

    main(int argc, char *argv[])
    {
        CmdEnv env;

        env.register_command("add", proc_add);
        env.register_command("avg", proc_add);
        env.register_command("echo", proc_echo);
        env.register_command("vec3", proc_vec3);

        for(int i=1; i&argc; i++)
    	script_do_file(argv[i], env);

        return 0;
    }

### 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 CmdLine &cmd)
    {
        double sum = 0.0;
        int count;

        std::vector<double> values;
        cmd.collect_as_numbers(values);
        for(count=0; count<values.size(); count++)
    	sum += values[count];

        if( cmd.opname() == "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 CmdLine &cmd)
    {
        if( cmd.argcount() != 3 )  return SCRIPT_ERR_SYNTAX;

        Vec3 v;
        cmd.collect_as_numbers(v, 3);

        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 CmdLine &cmd)
    {
        cout << cmd.argline() << 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