Now that we have a basic understanding of the language's underlying concepts, it's time to get down into the actual syntax. Everything in the language is case-insensitive; for stylistic purposes, in our examples, actual language keywords and outside module names are in all-caps, while names of procs, nebuloids, etc. are all lowercase.
It is possible to include another source file anywhere within your script. Simply use the keyword:
INCLUDE "filename"
where filename is the name of the file you want to include. Files will be included from various directories. In order of preference, the compiler looks in those listed on the command line with the -I option, listed in OLCINCLUDE environment variable, the current directory, and then /opt/hafta/include.
Occasionally it may be useful for clarity to define a macro. This is done using the syntax:
DEFINE macro replacementtext
where macro is the name given to the macro, and replacementtext is the text which replaces it when used in code. For example:
DEFINE verbosity 5 ... log(verbosity, "Hello!");
The Overlord runtime uses a stack to execute the compiled scripts. It is concievable that a script could be written which overruns this stack. Thus the Overlord compiler provides a method of specifying the stack size:
STACKSIZE size
where size is the size of the stack in nodes. This must be placed before the beginning of the SYSTEM definition. The default is 256. It is also possible to specify the Overlord's behaviour when the stack is overrun. By default, it will assume that it's running on a constrained system, and die rather than taking up additional resources. However, you can also tell the Overlord to grow the stack when it runs out, using the STACKPOLICY directive, like so:
STACKPOLICY [DIE | GROW]
where DIE is used if you want the Overlord to die instead of growing the stack, and GROW is used if you want the Overlord to grow its stack as necessary.
If it is required that some nebuloids be implicitly instantiated, it is required that the modules to be used be declared before the system declaration. The syntax for this is relatively straightforward, it's simply:
MODULE name (static argument list) (dynamic argument list)where name is, obviously, the name of the module you wish to use in your script.
The static and dynamic argument lists require a tad more explanation; they are lists of the types of arguments taken during instantiation and actual use. Thus, the declaration for the LOG module would look like:
MODULE LOG (NUM, STRING) (NUM, STRING)
Thankfully, this should only really matter to you if you write your own modules, as we provide a headers for all standard nebuloid types.
The bulk of the language script is contained in the SYSTEM declaration. This is quite simple; it works as follows:
SYSTEM: dependencies
{
policy
}
where dependencies is a list of process names within the system
which must be running for the system to work, and policy is the
various procedures, procs, and nebuloids contained within the system.
Within a SYSTEM definition, you can declare processes, using the PROCESS keyword. This looks like so:
PROCESS name interval: [dependencies]
{
policy
}
name refers to the name used to refer to this process in script
code. interval is the number of milliseconds between checks to
see whether or not this process is still alive and running.
dependencies is an optional list of other processes which this
process requires to be running before it can function. policy
includes not only proc and nebuloid definitions, but START,
RESTART and DEPENDFAIL definitions as well. These are
basically special-case procs which are only called by the Overlord; they
tell the Overlord how to start the process, what to do when the process
dies to restart it, and how to react when one of its dependencies fails,
respectively.
The text for this section has not been completed. Please see the ``Getting Started'' tutorial for an explanation of these concepts.
Many Overlord modules require that you instantiate a nebuloid, usually with some arguments to define exactly what it is it's supposed to be doing. Nebuloids can be declared either within a system, or within a process. The declaration for nebuloids is as follows:
modulename instancename ([argument1 [, argument2 [, ...]]]) [interval
{
script
}]
modulename is the name of the type of nebuloid you are instantiating. instancename is the name you will use in Overlord script to refer to that nebuloid. The arguments can be either a number or a string literal.
If a nebuloid is used specifically for checking some condition of the system, it may be desirable to add the script to actually check this condition right in the nebuloid definition. In this case, you would specify interval as the number of milliseconds between each check, and then write the appropriate script.