EXECUTION MODEL

The NSL interpreter is a tree of executon environment. Each execution environment is comparably independent from others and in principle communicate with them via sharable objects. The root of this tree is the environment holding the script loaded at startup. Strictly speaking, the structure may be not a tree, since enviroments are sharable objects, so the parent may export itself and its child will import it as a subordinated environment, thus yielding a loop. An environment has no implicit reference to its parent, so it may freely consider itself the topmost.

Sharable objects include streams, storages, procedures, automata sequences and environments (also called subinterpreters). Variables are with the help of pools – sets of variables available to all the environments.

At a given moment each environment executes a certain procedure. Procedures are sequences of calls to other procedures, builtins and control statements. Builtin calls are atomic in the sense that trap and error handling do not occur when a builtin is executed. A call have a certain number of arguments which consist of chunks. (see SYNTAX OVERVIEW section below). Arguments are always evaluated prior to the call itself. Chunks are evaluated left to right, the result of their evaluation being added to the current execution buffer. New buffers are allocated when a subordinate call or a block is evaluated. When the call is done, its result is added to the upper-level buffer. However, unlike in other languages, NSL builtins and functions may affect the parent buffer in other way than just adding to it. It may e. g. completely replace the contents of the buffer. Functions with such behaviour are supposed to have their names started with '.'

COMMAND SUMMARY

-(arg)

RETURNS:arg

tag(tag-name)

RETURNS:a value of a tag parameter with the name tag-name; if tag-name is empty, the name of the tag; tag-name = '#' – number of tag params; tag-name = '*' – a string of pairs 'name <TAB value <NL>' for every tag parameter, where <TAB> means a tab character, <NL> – a newline character, spaces are for clarity only if the current tag is a character, two pseudo names are recognized:
If there is no current tag, empty string

settag(tag-name value)

sets the value of a tag parameter tag-name to value. If there is no such parameter, it is added
ERROR:no current chunk

settagchar(tag-char)

sets the type of the current chunk to char with the value tag-char.
ERROR:no current chunk

cleartag()

clears the current chunk. If there was no current chunk, it is created.

rmtag(tag-name)

removes a tag parameter tag-name from the current chunk
ERROR:no current chunk

passtag(subint)

replaces the current chunk of a subint with a copy of the current chunk of the master interpreter. If there is no current chunk, the current chunk of the subint is deleted altogether.

var(varname)

RETURNS:the value of a variable varname; if no such variable exists, a null string is returned

arg(arg-no)

RETURNS:the value of arg-noth argument of the current procedure.
ERROR:invalid parameter index: arg-no

if arg-no ≤ 0

passargs(arg-no)

passes a list of arguments of the current function starting with arg-no to a current call

shift

shifts the argument list of the current procedure one position to the left. The last argument is set to null.
RETURNS:the former first argument

shift var1 var2 [var3 ...]

shifts the values of variables one position to the left (i. e. var1 gets the values of var2, var2 – of var3 etc. The last variable is set to null
NOTE:The whole stacks of values are affected, not just the last (visible) values
ERROR:shift is not rotate

– if called with a single argument

RETURNS:the former value of var1

rotate and rotate var1 var2 [var3 ...]

is similar to shift but does a cyclic shift, so that the first argument or variable becomes the last.

rotate(val)

RETURNS:val rotated, i. e. the first character moved to the end

ref(varname)

RETURNS:a reference to a varname. This value may be used in any place where a variable name is acceptable, e. g. as an argument to var, a first argument to set, etc. This allows to implement a pass-by-refererence technique, since the properties of a reference are the same as of the original variable, incl. the state of its stack
NOTE:ref should be used with care when applied to local variables, since if the reference is accessed after the end of the variable lifetime, the result is unpredictable.
NOTE:applications should treat references as opaque data and not try to analyse or construct them besides calling ref.
NOTE:since references are implemented as pointers, their presence is a considerable security hole even if there are no 'ref' calls in the script. Therefore, they may be disabled at all at compile-time by passing –disable-ref to ./configure

pool(name)

creates a new shared pool named name. If such pool already exists, nothing happens.

rmpool(name)

deletes a pool name. If the pool does not exist, does nothing

using([pool-name])

selects the shared pool pool-name for further use. If pool-name is empty, no pool is selected. If pool-name is omitted, the current pool is not changed.
RETURNS:the name of a pool previously in use
ERROR:pool 'pool-name' undefined

eval(arg)

Parses and evaluates arg as a valid NSL argument expression
RETURNS:the value of evaluated arg

void(arg)

Only discard the value of arg. It is hardly to be used explicitly, though the interpreter inserts it implicitly every time a built-in function which returns a value is used at the top level
NOTE:Top level only

if cond1 ops1 [elsif cond2 ops2]... [else opsn] endif

If condi is non-empty, opsi are evaluated, otherwise opsn if present
NOTE:Top level only
ERROR:'if'/'else'/'elsif' without 'endif'

switch arg ... case pattern ops ... caserange arg1 arg2 ops ... breaksw ... endsw

ops are evaluated following 'case' where arg matches pattern, or 'caserange' where arg is between arg1 and arg2 Evaluation stops after encountering 'breaksw' or 'endsw'
NOTE:Top level only
ERROR:switch without endsw

while [arg] ... continue ... break ... loop[(arg2)]

executes the loop while arg and arg2 are both not null If arg or arg2 missing, there are considered always true 'break' exits the loop immediately 'loop' skips until the next pass
NOTE:Top level only

foreach var storage ... loop

Repeats the loop for every record in storage Every time var is assigned the record key 'loop', 'continue', 'break' are used just like with 'while'
NOTE:Top level only

return[(arg)]

Finished the current procedure returning argto a parent. If arg is not present, a null string is returned

.return(arg)

Finishes the current procedure joining arg to the parent buffer

once(arg)

RETURNS:arg and replaces itself with it. This allows to create self-modifying programs
ERROR:'once' called in an inappropriate context

Exit

ends the main execution loop, forcing next input chunk to be read and processed
NOTE:Top level only

exit[(code)]

unconditionally ends the execution of the program code may be either success or failure or an integer. If it is missing, success is assumed.
NOTE:Top level only

export kind int-name ext-name

exports an object of a kind with a name int-name as ext-name. Kind may be one of storage, stream, autoseq, proc, subint[.] As a special case, export subint self ... exports the current interpreter
ERROR:kind 'int-name' undefined

embed(subint kind int-name remote-name)

like export, but instead of global exporting directly embeds the object int-name into the interpreter subint as remote-name

subint may be a special value ^ which denotes the calling environment. This feature is useful for returning shared objects from functions.

A remote name may be null or * in which case a unique name is chosen.

RETURNS:an assigned remote name
ERROR:kind 'int-name' undefined

ERROR:kind 'int-name' already defined

isexport(kind ext-name)

RETURNS:true if an object of the kind is exported as ext-name.

import(kind int-name ext-name)

import an object of the kind with external name ext-name as int-name. int-name may be null or * in which case a unique name is chosen.
RETURNS:an assigned internal name

acquire(subint kind int-name remote-name)

like import, but operates not on exported objects, but on those from subint. Like with embed, subint may be ^ to denote the calling environment. If int-name is null or *, a unique name is generated

allow(kind int-name subint-names ...) and deny(kind int-name subint-names ...)

allows or denies access to an object of the kind named int-name for environments listed under subint-names. If a subint-name is *, access is granted to or revoked from any environment. If a subint-name starts with ::, the rest of it is a local name of a environment, otherwise – an exported one.
NOTE:Only the object owner may change its access lists.
NOTE:Access list takes precedence over deny list; if both are empty, access is granted to everybody
NOTE:If you allow or deny access to an object to an environment and the environment is already denied or allowed access, the previous access rule is discarded. Consequently, when you deny/allow access to everybody, the opposite access list is cleared.

rename(kind old-name new-name [force])

renames an object old-name of the kind to new-name. If the object doesn't exist an error occurs unless force is present and not empty.

listof(kind [arg])

RETURNS:the list of entities of the kind. It is a plain list like those created by list. It contains names only no values whatsoever. The following kinds are supported by the core:

NOTE:arg is not used by the core, but the extensions provided by modules might use it.

declare(name declspec)

declares a procedure name according to declspec

if name is already declared, nothing happens

override(name declspec)

declares a procedure name according to declspec overriding the previous declaration if present

declof(name)

RETURNS:the declaration specification for name

undeclare(name)

removes the most recent declaration of name. If there was an overriden declaration for name, it becomes visible

release(kind int-name)

decrements the reference counter of an object int-name of the kind. If the counter reaches zero, the object is destroyed.

gensym()

RETURNS:an unique identifier

load(script-file)

loads the script-file in the same way as if being included by .include directive.
NOTE:This command affects the current execution environment; to create a new environment, use subload.

subload(int-name script-file)

Creates a new execution environment with the name int-name and loads a script from script-file to it.
NOTE:An execution environment may be restricted only after creating, so the script-file will have access to all builtins of the NSL.
TIP:You can load a script within a restricted environment with following trick:

subload some-name empty

restrict <all-necessary-functions> load

callin some-name load untrusted-script

Using load cannot break security, so it is safe to allow it even in untrusted scripts.

module(modulename)

Loads a dynamically pluggable module modulename (if not yet loaded) and attach it to the current environment (if not yet attached)
NOTE:All module's builtins will be available only thru subsequent call and eval calls

pragma(module arg)

Sends a pragma arg to a module

callin(subint proc-name [arg ...])

Calls a proc-name with args within the execution environment subint where proc-name may be either a user-defined procedure or a builtin. Restrictions of the subint do apply.
RETURNS:the result of executing proc-name

restrict(subint [!]bi-pattern ...)

removes from the subint all builtins which do not match any of bi-patterns. Patterns are the same as in match etc. If a pattern is prepended by !, it is inverted

revoke(subint bi-pattern ...)

removes from the subint all builtins which do match any of bi-patterns. Patterns are the same as in match etc.

trace() or trace(arg ...)

enables tracing procedures whose names match one of args; an argument # enables line tracing; no arguments is equivalent to '*'

notrace() or notrace(arg1 ...)

disables tracing procedures with names matching arg1... without arguments, disables tracing for all procedures
NOTE:procedure name patterns should coincide with those in 'trace'

dispatch

starts the handler for the current chunk
ERROR:nothing to dispatch

prefix() or prefix(arg)

if arg is present, sets the current dispatching prefix to arg
RETURNS:previous DP

echo(arg1 ...)

prints arg1... to stderr. If the last argument ends with \r, no carriage return occurs after printing the message.
NOTE:top level only

error(arg1 ...)

generates a recoverable error error message is concatenated from arg1...
NOTE:top level only

fatal-error(arg1 ...)

generates a fatal error error message is concatenated from arg1...
NOTE:top level only

pass-error arg

passes an error 'arg' to the built-in error handler useful within a user error handler
NOTE:top level only

onerror() or onerror(arg)

if arg is present, makes the procedure arg a user error handler
RETURNS:the name of the previous error handler

cancel and cancel(proc)

passes the control to the next top-level instruction of the calling function or to the caller of the calling function, if `proc' is present.
NOTE:Since errors may occur both at parse- and run-time, you should think a lot before using this function in an error handler which may be called from within eval and the like, since the point where execution goes depends on the kind of error. You'd better use catch ... throw.
NOTE:Top level only

catch(arg) and throw(throw-arg)

catch simply returns its arg if no throw was called during arg evaluation. Otherwise, throw-arg is returned.

throw sets the executiomn point to the innermost catch in the execution chain, making it return throw-arg.

ERROR:uncaught throw 'throw-arg'

trap(signame handler)

sets the handler of a signal signame to handler. If handler is empty, the previous handler is restored. If handler is `ignore', the signal will be ignored; if handler is `default', the default behaviour is set.

stop

stops the current process (i. e the interpreter itself)
NOTE:the behaviour of this builtin depends on how the system handles SIGSTOP. On non-Unix systems this may do nothing or terminate the process.

write(arg1 ...)

writes arg1... to the current output stream
ERROR:output stream not defined

NOTE:top level only

writeto(stream arg1 ...)

like write, but uses stream instead of the current output.

writetag() or writetag(tag-name [param-name1 param-val1 ...])

with no arguments, echoes the current input chunk to the output stream; with arguments, writes a tag named tag-name with parameters param-name1 = param-val1 to the output stream
ERROR:output stream not defined

ERROR:no chunk to echo

writetagto(stream tag-name [param-name1 param-val1 ...])

like writetag2, but uses stream instead of the current output.

ioctl(stream ctl-str)

sends a control string ctl-str to the stream. The exact effect is determined by the stream type
RETURNS:a stream-specific value
ERROR:don't know how to process request 'ctl-str'

getpos(stream)

RETURNS:a current input position in the stream
ERROR:stream doesn't support repositioning

NOTE:the value returned by the function can only be used in a subsequent 'setpos' call

setpos(stream pos)

sets the current input position of the stream to pos
NOTE:only values returned by 'getpos' can safely be used here
NOTE:top level only
ERROR:input stream not defined

rewind(stream)

resets the current input position of the stream to the beginning of the stream
NOTE:Top level only

def(var-name1 [= var-value1] ...)

defines local variables var-name1... ands sets the value to var-value1...
NOTE:Top level only
ERROR:redefinition of local 'varname'

global(var-name1 [= var-value1] ...)

defines global variables var-name1... ands sets the value to var-value1...
ERROR:redefinition of local 'varname'

ERROR:redefinition of global 'varname'

globalin(subint var-name1 [= var-value1] ...)

defines global variables with an execution environment subint no matter whether it allows the 'global' builtin. In other respects is analogous to global.

shared(var-name1 [= var-value1] ...)

defines shared variables var-name1... within the current pool and sets the value to var-value1...
NOTE:unlike def and global, shared is idempotent, i. e. if var-name is already defined, nothing happens.
NOTE:Top level only
ERROR:redefinition of local 'varname'

ERROR:no current pool

undef(var-name1 ...)

undefines local variables with names var-name1 ...
NOTE:undef says nothing about variables already undefined
NOTE:top level only

defined(var-name)

RETURNS:true if var-name is defined and available at the point of a call

isglobal(var-name)

RETURNS:true if var-name is a global variable

readonly(var1 ... varn)

makes variables var1 ... varn read-only

set(var-name [=] var-value)

sets the variable var-name to var-value
RETURNS:var-value
ERROR:variable 'var-name' not defined

ERROR:missing 'set' value

push(var-name [[=] var-value])

pushes the current value of the variable var-name and sets it to var-value or null if var-value is missing
RETURNS:var-value
ERROR:variable 'var-name' not defined

pop(var-name)

replaces the curent value of var-name with the last pushed value or null if the stack is empty
RETURNS:the new value of var-name
ERROR:variable 'var-name' not defined

clear(var-name)

clears the internal stack of var-name
NOTE:top level only
ERROR:variable 'var-name' not defined

depth(var-name)

RETURNS:the depth of the internal stack of var-name, including the current visible value
ERROR:variable 'var-name' not defined

copy(dest-var src-var)

copies the whole internal stack of src-var to dest-var. the stack of src-var is completely lost
NOTE:top level only
ERROR:variable 'dest-var or src-var' not defined

revstack(var-name)

reverses the internal stack of var-name
NOTE:Top level only
ERROR:variable 'var-name' not defined

exch(var-name)

exchanges two topmost items in the stack of var-name
ERROR:variable 'var-name' not defined

iseof()

RETURNS:true, if there is no current chunk

readline(prompt)

shows a prompt and waits for a user to type in a string
RETURNS:a user string
NOTE:This builtin only simulates the true readline. If you have the GNU readline, you may access it via readline module.

read[(autoseq)]

reads the next token from the input stream and translates it with the autoseq. If autoseq is not given, the identical translations is accepted. The read process stops when a tag is encountered.
RETURNS:the translated sequence
ERROR:no input stream

ERROR:translation undefined: 'autoseq'

readfrom(stream [autoseq])

like read but uses stream instead of the current input
NOTE:there is a single current chunk for all the streams, so a call to readfrom will replace the chunk read by e. g. main reading loop.

array[(name [val1 ...])]

creates an array named name. If name is missing, is empty, or is equal to '*', a unique name is generated
RETURNS:the name of the array
ERROR:storage 'name' already defined

table(name extname) and hash(name extname)

creates a table/hash named name. See array. and links it with a Berkley DB file named extname (Btree is used for table, hash for hash). If extname has no extenstion, .t is assumed. If extname is not absolute, the file is search in the current directory and in the directory given by SL_TABLE_PATH (if present). If the first character of extname is '!', the new file is created even if it existed before. If the first character of extname is '+', the table file is opened read-only

If extname is null, the table exists solely in memory

Tables support two special items: __readonly__ which disables modifying a table (note that setting __readonly__ cannot be undone); and __reversed__ table only) which controls the traversal order: ascending, when null, and descending otherwise. This parameter may be changed at any time, even in the middle of enumerating.

NOTE:In versions prior to 0.8 GDBM format was used
NOTE:Only a single traversal at a time may be performed on a given hash. E. g. nested foreach statements on the same hash will result in an error. However, this shouldn't matter very much, since hash elements are in no meaningful order.

list([name1 [= value1] ...])

creates a property list with a unique name. Lists allow any data as keys, like tables, but they are not persistent; in addition, unlike other storages, property lists may store multiple values of the same key though only the last stored one is accessible.
RETURNS:the name of the storage created

sequence(seq-def)

generates a sequence of integers which fits a range definition given in seq-def. The syntax of seq-def is that of ranges in automata defintions (see
sla ).
NOTE:This function is constant, unlike other storage constructors, so you should not use it as an argument to local if it have a constant argument.

iota(int-num)

this is equivalent to sequence('[1-int-num]')

new(subint [arg ...])

creates a new instance of a user-defined storage whose handlers are in the execution environment subint. args are passed to the init function of the storage.

local(storage)

make the storage local, that is it automatically released when leaving the current block.

get(storage key)

RETURNS:a storage record with the key
ERROR:depends on a storage type

check(storage key)

RETURNS:true if a record key is in storage

put(storage key val)

puts a pair key - val into storage. For most types of storages, if a key is not already in storage, an error occurs.

insert(storage key val)

adds a pair key - val into storage. For most types of storages, if a key is already in storage, an error occurs.

remove(storage key)

removes a pair with the key from the storage. For property list, this may give access to a previously stored key.

apply(storage func [args ...])

applies a user-defined function func to all the items of the storage. The function is passed storage, a current item and all the args.
RETURNS:concatenation of returned values for each item
NOTE:a builtin may not be used in place of func[.]

mark-remove(storage key)

marks the item key of the storage as removed. This function was introduced since it is generally not safe to delete items while inside an enumeration loop. Note that items marked for removal do not hide from following operations
NOTE:Removal marking is done by maintaining a linear list of items attached to a storage, so marking a large amount of items may slow down your system and even exceed the system's memory.
NOTE:if you need to zap the whole storage, the better way in many cases would be releasing the storage altogether and recreating it (This won't work if your storage is shared among several environments; if it has a generated name you need to recreate it with the same name not with a newly generated one).

unmark-remove(storage key)

if the item key of the storage has been previously marked as removed, clear that mark. Otherwise, nothing happens.

ismark-remove(storage key)

RETURNS:true of the item key of the storage is marked for removal

cancel-remove(storage)

clears all removal marks

sto.enum(storage handle-var)

RETURNS:if the value of handle-var is empty, the first key in the storage and puts a handler to an enumeration into handle-var. Otherwise, the next key from the enumeration and adjusts it resp. When there are no more items, handle-var is cleared.
NOTE:value held in handle-var is opaque; you shouldn't try use it but with sto.enum and sto.break functions

sto.break(storage handle-var)

cleans up the enumeration of storage whose handler is in handle-var. The latter is cleared.

do-remove(storage)

physically removes all the marked items from the storage

count(storage)

RETURNS:the number of items in storage.
NOTE:It is not guaranteed that this is a total number of accessible items nor that this is the number of iterations of a foreach loop, though in most cases both statements holds true

defautoseq(as-name autoseq)

defines a sequence of automata autoseq under the name as-name. For the syntax of autoseq see
sla(1)

rmautoseq(as-name)

equivalent to release autoseq as-name

au.load(au-name)

loads an automaton au-name

au.new(au-name)

creates an empty automaton named au-name
ERROR:automaton 'au-name' already defined

au.build(au-name au-definition)

parses au-definition as described in sla(1) and adds it to an automaton au-name. Several au.builds may be applied to the same automaton.
NOTE:it is recommended to use this function only with empty or explicitly loaded automata with no automata sequences using them.

itranslatez(as-name string)

passes the string thru the automata sequence as-name. The leading zero is passed too.
RETURNS:the output of the last automaton in the sequence as a list of hexadecimal numbers

itranslate(as-name string)

same as itranslate but the leading zero is not passed.

translatez(as-name string)

same as itranslatez, but the result is an ASCII string.
NOTE:If an output value is outside the ASCII range, an error occurs.

translate(as-name string)

same as translate, but the leading zero is not passed

ctranslate(as-name int-val)

passes a character whose code is int-val (possibly, outside the ASCII range) thru the automata sequence as-name
RETURNS:an empty string if the input is rejected; otherwise the decimal code of the output character prepended by '+' if there are no more output characters for this input and '-' otherwise. If the output is empty a single + or - is returned.
NOTE:an empty int-val is not treated as zero, but rather as no input

reset(as-name)

resets the automata sequence as-name to its initial state
RETURNS:as-name so that it is possible to use this function where an automata sequence name is required

state(as-name)

RETURNS:the state of the last automata from the automata sequence as-name

topstack(as-name)

RETURNS:the topmost item of the internal stack of the last automata from the sequence as-name or null if the stack is empty

mapstate(as-name state-name)

RETURNS:the value of the macro state-name in the last automaton from the sequence as-name or null if no such macro. See sla(1) for more details.

statename(as-name prefix value)

RETURNS:a name of a macro in the last automaton from the sequence as-name whose value is value and name starts with prefix

isfinal(as-name)

RETURNS:true if the active automaton from the sequence as-name is in one of its final states.

isaccepted(as-name)

RETURNS:null if the active automaton from as-name has recently failed to recognize an input

isint(arg)

RETURNS:true if arg is a valid representation of an integer

add(val1 ...)

RETURNS:the sum of vals.

postincr(var val)

increments var to val
RETURNS:the old value of var

incr(var val)

increments var to val
RETURNS:the new value of var

postdecr(var val)

decrements var to val
RETURNS:the old value of var

decr(var val)

decrements var to val
RETURNS:the new value of var

mul(val1 ...)

RETURNS:the production of vals

sub(val1 val2)

RETURNS:the result of subtracting val2 from val1

div(val1 val2)

RETURNS:the integral quotient of dividing val1 to val2
ERROR:zero division

rem(val1 val2)

RETURNS:the remainder of dividing val1 to val2
NOTE:if val1 is negative, the result is system-dependent. Consult your C compiler reference or experiment.
ERROR:zero division

neg(val)

RETURNS:the negation of val

abs(val)

RETURNS:the absolute value of val

bitand(val1 ...)

RETURNS:a bitwise AND of all val[s] regarded as integers

bitor(val1 ...)

RETURNS:a bitwise OR of all val[s] regarded as integers

bitxor(val1 ...)

RETURNS:a bitwise XOR of all val[s] regarded as integers

bitinv(val)

RETURNS:a bitwise complement of val

bitshift(val1 shift)

RETURNS:shifts val to shift bits left if the shift is positive or right if negative

int(val)

RETURNS:An internal representation of integers, suitable for numeric comparisons.
NOTE:This function is deprecated, use int modifier of comparison functions instead.

dec(val)

RETURNS:a decimal representation of val

hex(val)

RETURNS:a hexadecimal representation of val

oct(val)

RETURNS:an octal representation of val

uint8(val)

converts an integer as it's been converted from unsigned char to signed

uint16(val)

converts an integer as it's been converted from unsigned short to signed

Comparison functions

All the comparison functions may take two or three arguments (three or fours resp. in case of between. In case of three arguments, the first one indicates the type of comparison. The core defines two types: int for comparing integers and string for comparing strings. Pluggable modules may define other types. If there are two arguments, the type string is assumed.
ERROR:unknown type specifier: type

eq([type] arg1 arg2)

RETURNS:true if arg1 is equal to arg2

neq([type] arg1 arg2)

RETURNS:true if arg1 is not equal to arg2

eqi(arg1 arg2)

RETURNS:true if arg1 is equal to arg2 ignoring the case
NOTE:this function cannot be used with a type specifier

less([type] arg1 arg2)

RETURNS:true if arg1 is less than arg2

greater([type] arg1 arg2)

RETURNS:true if arg1 is greater than arg2

le([type] arg1 arg2)

RETURNS:true if arg1 is less than or equal to arg2

ge([type] arg1 arg2)

RETURNS:true if arg1 is greater than or equal to arg2

expr(arg)

RETURNS:the result of evaluating arg as arithmetic expression
NOTE:the syntax is the same as for expressions in automata definitions (see sla(1)). This means, in particular, that no variable expansion is done

match(pattern arg)

RETURNS:true if arg matches a pattern. Patterns have the same syntax as shell globbing patterns.

matchi(pattern1 arg)

RETURNS:true if arg matches a pattern ignoring the case.

between([type] arg1 arg2 arg3)

RETURNS:true if arg2 lies between arg2 and arg3.

and(arg1 ...)

RETURNS:true if all of args are not null
NOTE:this function is not short-circuit

or(arg1 ...)

RETURNS:true if any of args is not null
NOTE:this function is not short-circuit

not(arg)

RETURNS:true if arg is null

cond(condition if-arg [else-arg])

RETURNS:if-arg if condition is not null, otherwise else-arg or null if the latter is not present
NOTE:this function is not short-circuit. Alas!

length(arg)

RETURNS:the length of the string arg

ascii(arg)

RETURNS:the ASCII code of the first character of arg (zero if arg is null)

char(arg)

RETURNS:a character whose ASCII code is equal to arg. Null is returned if arg is zero. If arg doesn't fit the ASCII range, the result is system-dependent.

trim(arg)

RETURNS:arg with leading and trailing spaces stripped away

substr(arg init-pos [len])

RETURNS:a substring of arg staring from init-pos with the length len. If len is not present, the substring is from init-pos till the end of arg.
NOTE:the first character is number 0

.substr(init-pos [len])

same as substr, but it operates on the contents of the current execution buffer

index(arg substr [startpos])

RETURNS:a position at which substr occurs in arg. If substr is not contained in arg, null is returned. If startpos is present, it specifies the initial position for seeking.

rindex(arg substr)

RETURNS:a position of last occurence of substr within arg

isprefix(arg prefix)

RETURNS:true if arg starts with a prefix

issuffix(arg suffix)

RETURNS:true if arg ends in a suffix

commonprefix(arg1 arg2)

RETURNS:the most common prefix of arg1 and arg2

auindex(arg aseq [len-var])

RETURNS:a position of the first substring in arg which is accepted by the automata sequence aseq. If len-var is present, it is stored the length of the substring.

auindexmax(arg aseq [len-var])

like auindex but seeks for the maximal length substring

indexi(arg substr [start-pos])

like index but ignoring case

rindexi(arg substr [start-pos])

like rindex but ignoring case

replace(arg start len [subst])

replaces the substring of arg which starts at start having the length of len with subst or null if the latter is omitted

.replace(start len [subst])

same as replace but operates on the current execution buffer

repeat(arg count)

RETURNS:arg repeated count times; null if count is zero
ERROR:negative counter (count) for 'repeat'

split(arg fs rs var1 ...)

splits args into fields delimited by one of characters in fs. Splitting ends when the list of variables is over or when a character from rs is met. If a var is null, when a field is processed but not stored.
NOTE:This function does not strip leading separators, so two consecutive characters will result in an empty field.
RETURNS:the rest of arg

stosplit(args fs rs storage [start-with])

like split but stores fields into storage with field numbers as keys. If a key is found in storage, its value is overwritten The first key is start-with if it is present, 0 otherwise.

ausplit(arg auf aur var ...)

like split but uses automata sequence to detect field/record boundaries.
NOTE:Automata recognize fields/records, not delimiters; moreover, it is the output of automata that consitute a field, not the original string.
NOTE:Prior to v0.9 ausplit and austosplit had different behaviour and different number of arguments. This is no longer supported in any way

austosplit(arg auf aus storage [start-with])

like ausplit but uses storage to keep parsed fields

toksplit(fmt val varcnt var1 ...)

splits val into tokens like those used in NSL itself: integral values, characters, names and strings. The types of fields are given in fmt in C scanf manner, via %-sequences. A space is treated as an arbitrary sequence of spaces comments. All other characters in fmt should be present in val.

Resulting tokens are put into vari... if it is not empty; otherwise eaten (as with split ). The number of successfully processed fields (including those not really assigned) is put into varcnt if it is not empty

The valid %-codes are: