You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
7.5 KiB
HTML
193 lines
7.5 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
|
|
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
|
<!-- $Id: script.html 269 2001-10-10 00:38:28Z garland $ -->
|
|
|
|
<html>
|
|
|
|
<head>
|
|
<title>libgfx: Simple File Format Scripting</title>
|
|
<link rel=stylesheet href="cdoc.css" type="text/css">
|
|
<meta name="Author" content="Michael Garland">
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h2>Simple File Format Scripting</h2>
|
|
|
|
<p>The <tt>libgfx</tt> library provides a very simple scripting facility which
|
|
is primarily intended to support parsing of input files and control scripts.
|
|
To use this package, you must include the header file:
|
|
<pre>
|
|
#include <gfx/script.h>
|
|
</pre>
|
|
|
|
<p>For more information about this package, you may want to examine the
|
|
sample <a href="ex-script.html">scripted application</a>.
|
|
|
|
<h3>File Structure</h3>
|
|
|
|
<p>Scripts processed by this package are assumed to be composed of a sequence
|
|
of lines. Each line is processed separately, in sequence, and falls into one
|
|
of the following categories:
|
|
<ol>
|
|
<li>Lines containing only whitespace are ignored
|
|
<li>Lines whose first non-whitespace character is a '#' (hash mark) are
|
|
treated as comments and are ignored
|
|
<li>All other lines are assumed to be a sequence of whitespace-separated
|
|
tokens where the first token is a command name and subsequent tokens are
|
|
arguments to this command.
|
|
</ol>
|
|
|
|
<h3>Processing Scripts</h3>
|
|
|
|
<p>In order to process scripts, you must (at minimum) perform the following
|
|
steps:
|
|
<ol>
|
|
<li>Instantiate a <i>scripting environment</i> of type <tt>CmdEnv</tt>.
|
|
<li>Register your command(s) with <tt>CmdEnv::register_command()</tt>
|
|
or <tt>CmdEnv::register_method()</tt>.
|
|
<li>Feed the text of the script to the parsing system.
|
|
</ol>
|
|
The specifics of these steps are detailed in the following sections.
|
|
|
|
<h4>The Scripting Environment</h4>
|
|
|
|
<p>The primary task of the scripting system is to map command name tokens into
|
|
command procedures. These procedures, also referred to as "handlers", are
|
|
responsible for actually performing the computation associated with a
|
|
particular command.
|
|
Handlers should conform to the following type definition:
|
|
<pre>
|
|
typedef int (*CmdHandler)(const CmdLine &cmd);
|
|
</pre>
|
|
The <tt>CmdLine</tt> type manages the text of a particular command line, and
|
|
provides various methods for parsing that information (see details below).
|
|
|
|
<p>The <tt>CmdEnv</tt> class manages the mapping of command names to
|
|
handlers. In particular, handler names are mapped to pointers to
|
|
objects derived from the base class <tt>CmdObject</tt>. All derived
|
|
classes of <tt>CmdObject</tt> are required to override the
|
|
<tt>operator()</tt> invocation virtual method. By using this virtual
|
|
function, handler objects are allowed to encapsulate arbitrary data in
|
|
their definition (i.e., to create closures). The standard scripting
|
|
framework defines two kinds of <tt>CmdObject</tt> handlers: (1) the
|
|
<tt>CmdFunction</tt> class to encapsulate normal functions and static
|
|
methods and (2) and the <tt>CmdMethod</tt> template class to
|
|
encapsulate member functions.
|
|
|
|
|
|
<p>New handler procedures (non-member functions)
|
|
can be associated with names using
|
|
the method:
|
|
<pre>
|
|
void register_command(const std::string& name, CmdHandler proc);
|
|
</pre>
|
|
Member functions can be bound to names uses the templated member
|
|
function:
|
|
<pre>
|
|
template<class T>
|
|
void register_method(const std::string& name,
|
|
T *obj,
|
|
int (T::*fn)(const CmdLine&));
|
|
</pre>
|
|
Note that in both cases, prior bindings of <tt>name</tt> associated
|
|
with another handler will be overwritten.
|
|
Existing handlers can be located by name
|
|
using the method:
|
|
<pre>
|
|
CmdObject *lookup_command(const std::string& name);
|
|
</pre>
|
|
which returns <tt>NULL</tt> if no handler is bound to the given name.
|
|
|
|
<h4>Submitting Text for Execution</h4>
|
|
|
|
<p>Several procedures are available for submitting script text to the parsing
|
|
system. All of them require a <tt>CmdEnv</tt> argument that will determine
|
|
the mapping of command names to handlers.
|
|
|
|
<p>The underlying method for parsing text is:
|
|
<pre>
|
|
int script_do_line(std::string &line, CmdEnv &env);
|
|
int script_do_line(const char *line, CmdEnv &env);
|
|
</pre>
|
|
It assumes that its input is a string consisting of a single line — any
|
|
embedded newlines will be treated like any other whitespace.
|
|
It will
|
|
split this line it a series of whitespace-separated tokens, interpreting the
|
|
first such token as a command name. If <tt>env</tt> provides a binding for
|
|
this name, the appropriate handler will be called.
|
|
|
|
<p>For convenience, the scripting package also provides the following methods:
|
|
<pre>
|
|
int script_do_stream(std::istream &in, CmdEnv &env);
|
|
int script_do_file(const char *name, CmdEnv &env);
|
|
int script_do_string(const char *str, CmdEnv &env);
|
|
</pre>
|
|
They operate by extracting a single line from the input source and processing
|
|
that line with <tt>script_do_line()</tt>. They repeat this line-by-line
|
|
process until the file/stream/string has been exhausted.
|
|
The first time the processing of a line fails with an error code, these
|
|
procedures return this error code immediately without completing the
|
|
processing of the rest of the input.
|
|
|
|
|
|
<h3>Writing Command Handlers</h3>
|
|
|
|
<p>A command procedure is declared as follows:
|
|
<pre>
|
|
int proc(const CmdLine& cmd);
|
|
</pre>
|
|
The <tt>CmdLine</tt> structure contains all the necessary data about the line
|
|
being processed. It provides the following fundamental accessors:
|
|
<pre>
|
|
class CmdLine
|
|
{
|
|
public:
|
|
const std::string &line; // Raw text of the (complete) line
|
|
std::string opname() const; // Name of the command being invoked
|
|
std::string argline() const; // Argument string
|
|
int argcount() const; // Number of argument tokens
|
|
};
|
|
</pre>
|
|
The argument string returned by <tt>argline()</tt> is unparsed except that
|
|
whitespace following the command name and trailing whitespace at the end of
|
|
the line have been removed.
|
|
|
|
|
|
<p>It is up to the handler to parse the command line in whatever way it likes.
|
|
However, the scripting system assumes that command will be given
|
|
whitespace-separated token lists. Therefore, it pre-computes the indices of
|
|
these tokens in the command line text before invoking the handler. To access
|
|
an individual token, you can use the <tt>CmdLine</tt> methods:
|
|
<pre>
|
|
std::string token_to_string(int i) const;
|
|
double token_to_double(int i) const;
|
|
float token_to_float(int i) const;
|
|
int token_to_int(int i) const;
|
|
</pre>
|
|
Tokens are numbered from <tt>[0 .. argcount()-1]</tt>. Note that, for
|
|
efficiency, these methods <em>do not perform range checking.</em> It is up to
|
|
the caller to verify that the given indices are valid.
|
|
|
|
<p>In addition to accessing single argument tokens, you can collect all
|
|
argument tokens into lists with the following <tt>CmdLine</tt> methods:
|
|
<pre>
|
|
int collect_as_strings(std::vector<std::string> &v) const;
|
|
int collect_as_numbers(std::vector<double> &v) const;
|
|
int collect_as_numbers(std::vector<int> &v) const;
|
|
|
|
int collect_as_numbers(double *v, int size) const;
|
|
int collect_as_numbers(float *v, int size) const;
|
|
int collect_as_numbers(int *v, int size) const;
|
|
</pre>
|
|
These methods always return the number of tokens collected.
|
|
The <tt>vector</tt>-based methods will always collect all available tokens.
|
|
In contrast, those which accept raw arrays will either collect <tt>size</tt>
|
|
or <tt>argcount()</tt> tokens, whichever is smaller.
|
|
|
|
<p>See the accompanying <a href="ex-script.html">scripting example</a> for more
|
|
details on how to write command handlers.
|
|
|
|
</body>
|
|
</html>
|