DragonFly On-Line Manual Pages
KLELAPI(1) libklel KLELAPI(1)
NAME
KL-EL - an embedded expression language
SYNOPSIS
#include <klel.h>
Basic Usage
KLEL_CONTEXT *KlelCompile
(
const char *pcExpression,
unsigned long ulFlags,
KLEL_TYPE_CALLBACK pfTypeCallback,
KLEL_VALUE_CALLBACK pfValueCallback,
void *pvData
);
KLEL_VALUE *KlelExecute
(
KLEL_CONTEXT *psExpression
);
void KlelFreeResult
(
KLEL_VALUE *psValue
);
void KlelFreeContext
(
KLEL_CONTEXT *psContext
);
Handling Errors
void KlelReportError
(
KLEL_CONTEXT *psContext,
const char *pcFormat,
...,
NULL
);
void KlelReportMemoryAllocationError
(
KLEL_CONTEXT *psContext,
);
void KlelClearError
(
KLEL_CONTEXT *psContext,
);
const char *KlelGetError
(
KLEL_CONTEXT *psError
);
const char *KlelGetFirstError (deprecated)
(
KLEL_CONTEXT *psError
);
const char *KlelGetNextError (deprecated)
(
KLEL_CONTEXT *psError
);
Getting Information About Expressions
int KlelIsValid
(
KLEL_CONTEXT *psContext
);
char *KlelGetName
(
KLEL_CONTEXT *psContext
);
KLEL_EXPR_TYPE KlelGetTypeOfExpression
(
KLEL_CONTEXT *psContext
);
uint32_t KlelGetChecksum
(
KLEL_CONTEXT *psContext,
unsigned long ulFlags
);
Working With Private Data
void *KlelGetPrivateData
(
KLEL_CONTEXT *psContext
);
void KlelSetPrivateData
(
KLEL_CONTEXT *psContext,
void *pvData
);
Creating Values
KLEL_VALUE *KlelCreateBoolean
(
int bBool
);
KLEL_VALUE *KlelCreateInteger
(
int64_t iInteger
);
KLEL_VALUE *KlelCreateReal
(
double dReal
);
KLEL_VALUE *KlelCreateString
(
size_t szLength,
const char *pcString
);
KLEL_VALUE *KlelCreateFunction
(
KLEL_EXPR_TYPE iType,
KLEL_VALUE *(fCallback)(KLEL_VALUE **, void *)
);
KLEL_VALUE *KlelCreateUnknown
(
void
);
Working With Guarded Commands
int KlelIsSuccessReturnCode
(
KLEL_CONTEXT *psContext,
unsigned int uiCode
);
int KlelIsGuardedCommand
(
KLEL_CONTEXT *psContext
);
KLEL_COMMAND *KlelGetCommand
(
KLEL_CONTEXT *psContext
);
char *KlelGetCommandInterpreter
(
KLEL_CONTEXT *psContext
);
char *KlelGetCommandProgram
(
KLEL_CONTEXT *psContext
);
void KlelFreeCommand
(
KLEL_COMMAND *psCommand
);
Converting Values and Expressions to Strings
char *KlelExpressionToString
(
KLEL_CONTEXT *psContext,
unsigned long ulFlags
);
void KlelSetQuotedChars
(
const char *pcChars
);
void KlelSetQuoteChar
(
char cChar
);
char *KlelValueToQuotedString
(
KLEL_VALUE *psValue,
size_t *ulLength
);
char *KlelValueToString
(
KLEL_VALUE *psValue,
size_t *ulLength
);
Obtaining Release Information
uint32_t KlelGetReleaseNumber
(
void
);
const char *KlelGetReleaseString
(
void
);
int KlelGetReleaseMajor
(
void
);
int KlelGetReleaseMinor
(
void
);
int KlelGetReleasePatch
(
void
);
Obtaining Library Information
int KlelGetVersionCurrent
(
void
);
int KlelGetVersionRevision
(
void
);
int KlelGetVersionAge
(
void
);
DESCRIPTION
The KL-EL API is used to embed one or more KL-EL compilers and
interpreters in a program. Though there are many functions, most exist
only to provide advanced features. It is recommended that programmers
read kklleellllaanngg(3) to understand the expression language and kklleellttuutt(3)
for a tutorial introduction to this API.
All applications embedding KL-EL follow the same basic workflow:
Compile an expression using KlelCompile.
Execute a compiled expression some number of times using KlelExecute.
Free the result value using KlelFreeResult.
Free the compiled expression after use using KlelFreeContext.
BASIC USAGE
Compiling an Expression
A KL-EL expression is compiled using the KlelCompile function, which
has the following prototype:
KLEL_CONTEXT *KlelCompile
(
const char *pcExpression,
unsigned long ulFlags,
KLEL_TYPE_CALLBACK pfTypeCallback,
KLEL_VALUE_CALLBACK pfValueCallback,
void *pvData
);
pcExpression is a NULL-terminated string that represents the expression
to compile.
ulFlags is zero or more of the following flags ORed together:
MUST_BE_GUARDED_COMMAND
This flag indicates that the expression must be a guarded command.
MUST_BE_GUARDED_COMMAND_WITH_RETURN_CODES
This is a convenience flag that can be used instead of
MUST_BE_GUARDED_COMMAND ORed with MUST_SPECIFY_RETURN_CODES.
MUST_BE_NAMED
This flag indicates that the expression must include a name.
MUST_SPECIFY_RETURN_CODES
This flag indicates that the expression must specify 'pass' or
'fail' codes. Note that if this flag is set, the library
automatically sets the MUST_BE_GUARDED_COMMAND flag since only
guarded commands can have return codes.
pfTypeCallback is a pointer to a function that the library will call
whenever it needs to know the type of a variable that has been exported
into the KL-EL runtime. This function must have the following
prototype:
KLEL_EXPR_TYPE callback
(
const char *pcName,
void *pvContext
);
where pcName is the name of the variable under consideration and
pvContext is a pointer to the context. This callback must return one
of the predefined KL-EL variable types (see TYPES below) or
KLEL_TYPE_UNKNOWN, in which case KL-EL will automatically check its
standard library to see if the variable is defined there.
Exported variables are of exactly one type and that type can never
change. In other words, given the same arguments, the pfTypeCallback
function must always return the same value.
pfValueCallback is a pointer to a function that the library will call
whenever it needs to know the value of a variable that has been
exported into the KL-EL runtime. This function must have the following
prototype:
KLEL_VALUE *callback
(
const char *pcName,
void *pvContext
);
where pcName and pvContext have the same meanings as for the type
callback. This function returns the value of the named variable,
created using one of the value creation functions (see CREATING VALUES
below). While a variable's type may never change, its value can change
at any time. This allows for variables to have different values in
different situations. A variable's value can change during execution
and in between exections with no limitations.
pvData is a void pointer that can be retrieved using the current
context and KlelGetPrivateData. The data referenced by this pointer
are never touched by the library. Typically these data would be used
to help compute the types or values of variables, or they may be used
for any other user-defined purpose. These data may be changed at any
point using KlelSetPrivateData.
KlelCompile returns a pointer to an opaque KLEL_CONTEXT structure.
This structure should be passed to KlelIsValid to determine if
compilation succeeded. Note that contexts are not thread-safe.
Therefore, it is recommended that the same context only be accessed
from a single thread at a time. If needed, a context can be shared
across threads, but only if its access and manipulation are serialized.
There is no predefined limit to the number of contexts that may exist
within a single program or thread.
Checking If Compilation Succeeded
Once an expression has been compiled, the result of KlelCompile should
be passed to KlelIsValid, which returns nonzero if the expression
compiled without errors or zero if the compilation had errors. If the
compilation had errors, the context is unusable except to retrieve
error information using KlelGetError.
Executing an Expression
A compiled expression can be executed by passing its context to
KlelExecute. This function executes the expression and returns a
pointer to a KLEL_VALUE structure, which represents the result of
execution. A given compiled expression can be executed as many times
as desired; there is no need to recompile it. The returned KLEL_VALUE
structure has the following members:
iType
One of KLEL_TYPE_BOOLEAN, KLEL_TYPE_INT64, KLEL_TYPE_REAL, or
KLEL_TYPE_STRING.
bBoolean
A boolean value if iType is KLEL_TYPE_BOOLEAN. This value is
encoded as an integer in the underlying implementation.
llInteger
An integer value if iType is KLEL_TYPE_INT64. This value is
encoded as an int64_t in the underlying implementation.
dReal
A real value if iType is KLEL_TYPE_REAL. This value is encoded as
a double in the underlying implementation.
szLength
The length in bytes of the string value if iType is
KLEL_TYPE_STRING. This value is encoded as a size_t in the
underlying implementation.
acString
An array of szLength characters if iType is KLEL_TYPE_STRING. This
value is encoded as an array of characters in the underlying
implementation.
Note that strings can contain NULL bytes. The length of a string is
always its length in bytes, regardless of encoding. The returned
KLEL_VALUE is not owned by the library -- it's up to the programmer to
free this value once it's no longer needed using KlelFreeResult.
If the compiled expression is a guarded command (see klellang(3)), the
resulting value will be the result of the expression's guard. Other
information about the guarded command can be retrieved using the helper
functions documented below.
Freeing Results and Contexts
When a context is no longer needed, it should be passed to
KlelFreeContext. Results from expressions should be freed using
KlelFreeResult. Guarded command structures (see klellang(3)) should be
freed using KlelFreeCommand.
Handling Errors
If compilation or execution of an expression fails, an error message
will be present. To retrieve this error, call KlelGetError. This
function returns a string describing errors, which may be printed or
otherwise reported. These strings are owned by the library and should
not be freed by the programmer.
To report an error during execution of a callback function, call
KlelReportError, which takes a context, a printf(3)-style format
string, and a variable number of arguments. This creates an error
string that is added to the context. The final argument must be NULL.
Callbacks are free to report errors in any way the developer chooses,
but those errors reported with KlelReportError are only available via
the KlelGetError function.
Getting Information About a Compiled Expression
KlelIsValid will check a compiled expression to see if it compiled
without errors. There is no need to check to see if the pointer is
NULL before passing it to this function.
KlelGetName will return the name of a compiled expression, if the
expression was named. If the expression was not named, the library
will generate a name based on the input expression. Note that the
returned string should not be freed.
KlelGetTypeOfExpression returns the type of a compiled expression (one
of KLEL_TYPE_BOOLEAN, KLEL_TYPE_INT64, KLEL_TYPE_REAL, or
KLEL_TYPE_STRING).
KlelGetChecksum computes a checksum of the expression. This is useful
for comparing two expressions for equality. Note that such comparisons
are performed on the compiled representation rather than the input
string, meaning that things like whitespace are ignored. The ulFlags
argument is the same as for KlelExpressionToString.
Working With Private Data
The private data of a compiled expression (i.e., the void pointer that
is passed to the type- and value-producing callbacks) can be retrieved
or set using KlelGetPrivateData or KlelSetPrivateData, respectively.
The private data can be set at any time, including during execution,
and that change takes place immediately -- there is no need to
recompile the expression.
Creating Values
The value callback passed to KlelCompile should return the value of
variables when asked. These callback functions create new values to be
used by the library representing the value of the specified variable at
that point in time. As was stated above, a variable's type may never
change, but a variable's value can change at any time and as often as
the programmer desires.
Boolean values are created using KlelCreateBoolean, which takes a
single numeric argument. Zero means false, all other values mean true.
Integer values are created using KlelCreateInteger, which takes a
single numeric argument. Integers in KL-EL are always signed 64-bit
integers; the argument passed to this function will be cast as
necessary.
Real values are created using KlelCreateReal, which takes a single
double argument. Note that integer values are automatically cast as
necessary.
String values are created using KlelCreateString, which takes two
arguments: a size_t indicating the length in bytes of the string (not
including any terminating zero), and a pointer to a string. The
library makes a copy of this string, so it may be freed at any time.
Function values are slightly more complicated. They are created using
KlelCreateFunction, which takes three arguments: a type descriptor,
which describes the function's return type and argument types; a name
(as a normal zero-terminated C string); and a function pointer to the
function that should be invoked when KL-EL executes the function. The
type descriptor is constructed as described in TYPES below.
If the named variable is "unknown" to the callback (i.e., not exported
by the host application), then the callback function should return the
result of KlelCreateUnknown, which instructs KL-EL to search its
standard library for the named variable. If there is an error in
calculating the value of the named variable, but it is "known" to the
callback, then the callback should return NULL, which instructs KL-EL
to immediately report the error without searching its standard library.
Working With Guarded Commands
Guarded commands are KL-EL expressions that contain extra metadata. A
programmer can determine if an expression is a guarded command by
calling KlelIsGuardedCommand, which returns nonzero if the expression
is a guarded command.
The interpreter (the first argument to the special eval function) and
program (the second argument to the special eval function) can be
retrieved using KlelGetCommandInterpreter and KlelGetCommandProgram,
respectively. These functions return a pointer to a string. Note that
these strings should not be freed.
If the programmer wishes to evaluate the contents of the eval function
(presumably when the guard is true, but in theory at any time), the
function KlelGetCommand can be used. This returns a pointer to a
KLEL_COMMAND structure. The format of this structure is:
typedef struct _KLEL_COMMAND
{
char pcInterpreter[KLEL_MAX_NAME + 1];
char pcProgram[KLEL_MAX_NAME + 1];
size_t szArgumentCount;
char *ppcArgumentVector[KLEL_MAX_FUNC_ARGS + 1];
int aiCodes[256];
} KLEL_COMMAND;
pcInterpreter is the first argument to the eval function, and pcProgram
is the second.
szArgumentCount indicates the number of arguments to the eval function,
not including pcInterpreter; the corresponding members of
ppcArgumentVector are filled in. The library automatically converts
all of the values in that vector to strings. The first member of the
ppcArgumentVector array is identical to pcProgram.
The aiCodes array stores which codes were specified as "successful"
codes by the guarded command. If a code is successful, the value at
its index in this array will be nonzero, otherwise it will be zero. If
no codes are specified in the expression, zero is defined as a
successful return code.
Note that the library assigns no meaning to any of these fields, it
simply passes the values from the compiled expression to the
programmer. It is up to the programmer to determine what to do with
guarded commands. Conventionally, pcInterpreter specifies an
interpreter or an environment, while pcProgram specifies a program to
run, and the arguments are passed to the executed program. The
programmer is free to ignore these conventions.
When a programmer is done using a KLEL_COMMAND structure, it should be
freed using KlelFreeCommand.
Converting Values and Expressions to Strings
A value can be converted to a string using KlelValueToString, which
takes two arguments: the value to convert, and a pointer to a size_t
variable in which the length of the resulting string is stored.
Values can also be converted to "quoted strings" using
KlelValueToQuotedString. A quoted string is identical to the string
produced by KlelValueToString, but any special characters are prefixed
with a quoting character. What characters are considered special is
determined by calling KlelSetQuotedChars with a string (each character
of which will be considered special). The string passed to
KlelSetQuotedChars should not be freed. What character is used for
quoting is set by calling KlelSetQuoteChar with a single character.
An expression as a whole can be converted to a string by calling
KlelExpressionToString, which takes two arguments: the compiled
expression, and a set of flags. The flags are zero or more of the
following ORed together:
KLEL_EXPRESSION_ONLY
include only the expression without its name. If the expression is
a guarded command, include only the guard expression
KLEL_EXPRESSION_PLUS_COMMAND_LINE
like KLEL_EXPRESSION_ONLY, but include its eval function if it's a
guarded command
KLEL_EXPRESSION_PLUS_RETURN_CODES
like KLEL_EXPRESSION_ONLY, but include any return code
specifications if it's a guarded command
KLEL_EXPRESSION_PLUS_NAME
like KLEL_EXPRESSION_ONLY, but include the expression's name if one
was specified
KLEL_EXPRESSION_PLUS_EVERYTHING
include all parts of the expression
The string returned by KlelExpressionToString should be freed once it's
no longer needed.
TYPES
When exporting values into the KL-EL environment using the type and
value callbacks passed to KlelCompile, each variable must be given a
type descriptor. Type descriptors are represented using integers and
constructed using various macros.
Simple types (boolean values, integers, real numbers, and strings) have
simple type descriptors:
KLEL_TYPE_BOOLEAN
KLEL_TYPE_INT64
KLEL_TYPE_REAL
KLEL_TYPE_STRING
Function types are, however, slightly more complicated. A function's
type encodes its return type and the number and types of its arguments.
The macros to encode a function's type have the following form:
KLEL_TYPE_t_FUNCTIONn(a0, a1, ... aN);
where t is the return type of the function (which must be a simple
type), n is the number of arguments [0-13], and a0 through aN represent
the types of the corresponding positional arguments. For functions
taking zero arguments, the macro's argument list should be left empty.
For example, a function returning an integer and taking a single string
argument would look like this:
KLEL_TYPE_INT64_FUNCTION1
(
KLEL_TYPE_STRING
);
A function returning a string and taking three arguments (two integers
and a boolean) would look like this:
KLEL_TYPE_STRING_FUNCTION3
(
KLEL_TYPE_INT64,
KLEL_TYPE_INT64,
KLEL_TYPE_BOOLEAN
);
RETURN VALUES
KlelCompile returns a pointer to a KLEL_CONTEXT structure or NULL
indicating that no context could be created. To determine if any
errors occurred, the pointer (whether it's NULL or not) should be
passed to and evaluated by KlelIsValid.
KlelExecute returns a pointer to a KLEL_VALUE structure or NULL
indicating a failure. If the call failed, the error that occurred can
be retrieved using KlelGetError. The value returned by KlelExecute
should be freed using KlelFreeResult once it's no longer needed.
KlelIsValid returns nonzero (i.e., true) if the specified KLEL_CONTEXT
structure represents a valid expression (i.e., the expression compiled
without errors) and zero (i.e., false) otherwise.
KlelGetError returns the last error or NULL if there are no errors.
Also note that the string returned by this function should not be freed
since that resource is managed by the implementation.
All other functions return a pointer to a result on success or NULL
indicating a failure. The programmer is responsible for freeing the
values returned by these functions.
SEE ALSO
klel-expr(1), klellang(3), klelstdlib(3), kleltut(3)
1.1.0 2015-09-16 KLELAPI(1)