icifunc(1)

NAME
icifuncs - ICI core language function

DESCRIPTION
The following list summarises the standard functions. Following this is a detailed description of each of them.
	float|int = 	abs(float|int)
	float = 	acos(number)
	mem = 	alloc(int [, int])
	string = 	argv[]
	array = 	array(any...)
	float = 	asin(number)
	any = 	assign(struct, any, any)
	float = 	atan(number)
	float = 	atan2(number, number)
	array|struct = 	build(dims... [, options, content...])
	float|struct = 	calendar(struct|float)
	any = 	call(func [, arg...], args)
	float = 	ceil(number)
		chdir(string)
		close(file)
	int = 	cmp(a, b)
	any = 	copy(any)
	any = 	any:copy()
	float = 	cos(number)
	float = 	cputime([foat])
	file = 	currentfile([string])
	int = 	debug([int])
		del(aggr, any)
	array = 	dir([path], [, regexp] [, format])
	int = 	eof(file)
	int = 	eq(any, any)
		eventloop()
		exit([int|string|NULL])
	float = 	exp(number)
	array = 	explode(string)
		fail(string)
	any = 	fetch(struct, any)
	float = 	float(any)
	float = 	floor(number)
	int = 	flush([file])
	float = 	fmod(number, number)
	file = 	fopen(string [, string])
	string = 	getchar([file])
	string = 	getcwd()
	string = 	getenv(string)
	string = 	getfile([file])
	string = 	getline([file])
	string = 	gettoken([file|string [,string]])
	array = 	gettokens([file|string [,string [,string]]])
	string = 	gsub(string, regexp, string)
	string = 	implode(array)
	struct = 	include(string [, struct])
	int = 	int(any [, int])
	string|array = 	interval(string|array, int [, int])
	int = 	inst|class:isa()
	int = 	isatom(any)
	array = 	keys(struct)
	any = 	load(string)
	float = 	log(number)
	float = 	log10(number)
	mem = 	mem(int, int [,int])
	file = 	mopen(string [, string])
	int = 	nels(any)
	inst = 	class:new(...)
	float = 	now()
	int|float = 	num(string|int|float [, int])
	struct = 	parse(file|string [, struct])
	string = 	parsetoken(file)
	any = 	parsevalue(file)
	string = 	path[]
	any = 	pop(array)
	file = 	popen(string [, string])
	float = 	pow(number, number)
		printf([file,] string [, any...])
		profile(filename)
	any = 	push(array, any)
		put(string [, file])
		putenv(string [, string])
	int = 	rand([int])
		reclaim()
	regexp = 	regexp(string)
	regexp = 	regexpi(string)
		rejectchar(file)
		rejecttoken(file)
		remove(string)
		rename(string, string)
	int = 	inst|class:respondsto(string)
	any = 	rpop(array)
		rpush(array, any)
	struct = 	scope([struct])
	int = 	seek(file, int, int)
	set = 	set(any...)
	string|func = 	signal(int|string [, func|string])
	string = 	signam(int)
	float = 	sin(number)
		sleep(number)
	array = 	smash(string [, regexp [, string...] [, int]]);
	file = 	sopen(string [, string])
	array = 	sort(array, func [, arg])
	string = 	sprintf(string [, any...])
	float = 	sqrt(number)
	string = 	strbuf([string])
	string = 	strcat(string [, int] , string...)
	string = 	string(any)
	struct = 	struct(any, any...)
	string = 	sub(string, regexp, string)
	struct = 	super(struct [, struct])
	int = 	system(string)
	float = 	tan(number)
	exec = 	thread(callable [, args...])
	string = 	tochar(int)
	int = 	toint(string)
	any = 	tokenobj(file)
	any = 	top(array [, int])
	int = 	trace(string)
	string = 	typeof(any)
	string = 	version()
	array = 	vstack([int])
		wakeup(any)
	struct = 	which(key [, struct])

DETAILS

  float|int = abs(float|int)

Returns the absolute value of its argument. The result is an int if the argument is an int, a float if it is a float.

  angle = acos(x)

Returns the arc cosine of x in the range 0 to pi.

  mem = alloc(nwords [, wordz])

Returns a new mem object referring to nwords (an int) of newly allocated and cleared memory. Each word is either 1, 2, or 4 bytes as specified by wordz (an int, default 1). Indexing of mem objects performs the obvious operations, and thus pointers work too.

  string = argv[]

An array of strings containing the command line arguments set at interpreter start-up. The first element is the name of the ICI program and subsequent elements are the arguments passed to that program.

On Windows platforms ICI performs wildcard expansion in the traditional MS-DOS fashion. Arguments containing wildcard meta-characters, ? and *, may be protected by enclosing them in single or double quotes. On UNIX-like systems, the operating environment is expected to handle this.

  array = array(any...)

Returns an array formed from all the arguments. For example:

    array()

will return a new empty array; and

    array(1, 2, "a string")

will return a new array with three elements, 1, 2, and "the string".

This is the run-time equivalent of the array literal. Thus the following two expressions are equivalent:

    $array(1, 2, "a string")

    [array 1, 2, "a string"]

  float = asin(x)

Returns the arc sine of x in the range -pi/2 to pi/2.

  value = assign(struct, key, value)

Sets the element of struct identified by key to value, ignoring any super struct. Returns value.

  angle = atan(x)

Returns the arc tangent of x in the range -pi/2 to pi/2.

  angle = atan2(y, x)

Returns the angle from the origin to the rectangular coordinates x, y (floats ) in the range -pi to pi.

  array|struct = build(dims... [, options, content...])

Build allows construction of a regular data structure such as a multi-dimensional array or an array of structures. dims... is a sequence of dimension specifications. For example:

    build(20, 10);

returns a 20 x 10 array of NULLs (that is, an array of 20 arrays, each of size 10).

Each dimension specification is either:

an int
    causing an array of that many elements to be made and have every element set through recursive application on subsequent dimensions, or

an array
    causing a struct with the elements of the array as keys to be made and each value set through recursive application on subsequent dimensions.

So, for example:

    build(10, [array "x", "y"], 2)

Returns an array of ten structures, each with fields x and y. Each field is set to an array of length 2.

If options and content... are supplied, they may be used to supply initialising data to the leaf fields of the data structure rather than the default NULL. Options is a string, which may be:

"c" Cyclical. The content is used and assigned cyclically to leaf items.

"r" Restart. The content is used and assigned cyclicly, but the content list is also restarted from the first item on the commencement of each bottom level aggregate.

"l" Last repeats. The content is used and assigned in sequence to leaf items, but once it is exhausted, the last content item is used repeatedly for subsequent leaf items.

"a" Arrays. Each of the content items must be an array. Content is taken firstly from the first element of each array in turn, then from the second element of each in turn etc. If any array is too short, NULL is used as the value.

"i" Integer increment. The content is incrementing integer values. The first content value, if given is the start value, default 0. The second content value, if given, is the step, default 1.

So, for example, supposing names_array is an array of names of some sort:

    build(names_array, [array "count", "sum"], "c", 0, 0.0)

will return a struct which, when indexed by a name in names_array reveals a struct with fields count and sum initialised to 0 and 0.0 respectively.

Also:

    build(50, "i", 1, 2)

will return an array filled with the odd integers from 1 to 99.

Finally, if names is an array of names of some sort and values is a corresponding array of values:

    build(nels(names), [array "name", "value"], "a", names, values)

will transpose them into an array of structs, each with a name and value field.

  float|struct = calendar(struct|float)

Converts between calendar time and arithmetic time. An arithmetic time is expressed as a signed float time in seconds since 0:00, 1st Jan 2000 UTC. The calendar time is expressed as a structure with fields revealing the local (including current daylight saving adjustment) calendar date and time. Fields in the calendar structure are:

second
    The float number of seconds after the minute.

minute
    The int number of minutes after the hour.

hour
    The int number of hours since midnight.

day The day of the month (1..31).

month
    The int month number, Jan is 0.

year
    The int year.

wday
    The day since Sunday (0..6)

yday
    Days since 1st Jan.

When converting from a local calendar time to an arithmetic time, the fields second, minute, hour, day, month, year are used. They need not be restricted to their nomal ranges.

  return = call(func [, any...], array|NULL)

Calls the function func with the arguments any... plus arguments taken from the array. If array is NULL it is ignored, else it must be an array. Returns the return value of the function.

This is often used to pass on an unknown argument list. For example:

    static
    db()
    {
        auto vargs;

        if (debug)
            return call(printf, stderr, vargs);
    }

  float = ceil(x)

Returns the smallest integral value greater than or equal to x as a float, where x is a number (int or float).

  chdir(path)

Change the current working directory to the specified path.

  close(file)

Close the given file, releasing low level system resources. After this operation the file object is still a valid object, but I/O operations on it will fail. (File objects that are lost and collected by the garbage collector will be closed. But due to the indeterminate timming of this, it is preferable to close them explicitly.)

On some files and systems this may block, but will allow thread switching while blocked.

  int = cmp(a, b)

Returns -1, 0 or 1 depending if a < b, a == b, or a > b. The operands may be any type for which the < and > operators are defined. This is the default comparison function for sort().

  any = copy(any)

Returns a copy of an object. That is, an object that is distinct (not eq) but of equal value (==), unless the object is intrinsically atomic or unique (in which case the original object is returned).

  any = any:copy()

The method form of copy(). Otherwise as above.

  x = cos(angle)

Returns the cosine of angle (a float interpreted in radians).

  float = cputime([float])

Returns the accumulated CPU time of the current process in seconds. The precision and accuracy is system dependent.

If float is supplied it specifies a new origin, relative to the value being returned, from which subsequent calls are measured. Mostly commonly the value 0.0 is used here.

  file = currentfile([ raw"])"

Returns a file associated with the innermost parsing context, or NULL if there is no module being parsed. By default currentfile() returns a new file object that gives "cooked" access that layers on top of the parser's access to the file. This maintains line number tracking and normalises differing newline conventions to single newline characters even for binary files. Such a file is sutiable to calls to parsetoken(). If the string "raw" is given as an argument, the underlying file that is being parsed is returned directly, by-passing such operations.

This function can be used to include data in a program source file which is out-of-band with respect to the normal parse stream. But to do this it is necessary to know up to what character in the file in question the parser has consumed.

In general: after having parsed any simple statement the parser will have consumed up to and including the terminating semicolon, and no more. Also, after having parsed a compound statement the parser will have consumed up to and including the terminating close brace and no more. For example:

    static help = gettokens(currentfile(), "", "!")[0]
    ;This is the text of the help message.
    It follows exactly after the ; because
    that is exactly up to where the parser
    will have consumed. We are using the
    gettokens() function (as described below)
    to read the text.
    !
    static otherVariable = "etc...";

In the examples shown above, the default cooked mode is used so that line numbers are tracked and stay in sync for subsequence diagnostics. If the raw mode was used the parser would never see the data read out-of-band and would not realise how many lines have been skipped, thus giving inaccurate reports of line numbers on errors later in the file.

This function can also be used to parse the rest of a file within an error catcher. For example:

    try
        parse(currentfile(), scope())
    onerror
        printf("That didn't work, but never mind.);
    static this = that;
    etc();

The functions parse and scope are described below.

  int = debug([int])

Returns the current debug status, and, if an int is supplied as an argument, set it to that value.

When debugging is enabled, certain events such as each new source line, each function call and return, and errors, are passed to any active debugger. Debuggers are typically dynamically loaded extension modules that register themselves with the interpreter through an internal API.

  del(aggr, key)

Deletes an element of aggr, which must be a struct, a set or an array, as identified by key. Any super structs are ignored. For structs and sets this is an efficient operation. For arrays it is O(n) where n is the length from the index key, to the nearest end of the array (that is, either the beginning of the end). If key is not a current element of aggr there is no effect and no error. Returns NULL.

For example:

    static s = [struct a = 1, b = 2, c = 3];
    static v, k;
    forall (v, k in s)
        printf("%s=%d, k, v);
    del(s, "b");
    printf(");
    forall (v, k in s)
        printf("%s=%d, k, v);

When run would produce (possibly in some other order):

    a=1
    c=3
    b=2
    a=1
    c=3

  array = dir([path,] [regexp,] [format])

Read directory named in path (a string, defaulting to ".", the current working directory) and return the entries that match the regexp as an array of strings (or all names if no regexp is passed). The format string identifies what sort of entries should be returned. If the format string is passed then a path MUST be passed (to avoid any ambiguity) but path may be NULL meaning the current working directory (same as "."). The format string uses the following characters,

f   Return file names.

d   Return directory names.

a   Return all names (which includes things other than files and directories, e.g., hidden or special files).

The default format specifier is "f".

Note that when using dir() to traverse directory hierarchies that the "." and ".." names are returned when listing the names of sub-directories, these will need to be avoided when traversing.

  int = eq(obj1, obj2)

Returns 1 (one) if obj1 and obj2 are the same object, else 0 (zero). Note that this is more strict than the == operator, which tests whether two objects have equal value.

  int = eof([file])

Returns non-zero if end of file has been read on file. If file is not given the current value of stdin in the current scope is used.

  eventloop()

Enters an internal event loop and never returns. The exact nature of the event loop is system specific. Some dynamically loaded modules require an event loop for their operation. Allows thread switching while blocked.

  exit([string|int|NULL])

Causes the interpreter to finish execution and exit. If no parameter, the empty string or NULL is passed the exit status is zero. If an integer is passed that is the exit status. If a non-empty string is passed then that string is printed to the interpreter's standard error output and an exit status of one used.

  float = exp(x)

Returns the exponential function of x, that is, e raised to power x.

  array = explode(string)

Returns an array containing each of the integer character codes of the characters in string.

  fail(string)

Causes an error to be raised with the message string associated with it. See the section on error handling in the try statement above. For example:

    if (qf > 255)
        fail(sprintf("Q factor %d is too large", qf));

  value = fetch(struct, key)

Returns the value from struct (which actually may be any type of object) associated with key, ignoring any supers. Returns NULL if key is not an element of struct.

  value = float(x)

Returns a floating point interpretation of x, or 0.0 if no reasonable interpretation exists. x should be an int, a float, or a string, else 0.0 will be returned.

  float = floor(x)

Returns the largest integral value less than or equal to x as a float, where x is a number (int or float).

  flush([file])

Flush causes data that has been written to the file (or stdout if absent), but not yet delivered to the low level host environment, to be deliverd immediately.

On some files and systems this may block, but will allow thread switching while blocked.

  float = fmod(x, y)

Returns the float remainder of x / y where x and y are numbers (int or float). That is, x - i * y for some integer i such that the result has the same sign as x and magnitude less than y.

  file = fopen(name [, mode])

Opens the named file for reading or writing according to mode and returns a file object that may be used to perform I/O on the file. mode is the same as in C and is passed directly to the C library fopen function. If mode is not specified "r" is assumed. On Windows, directory separators may be either / or \ characters.

On some files and systems this may block, but will allow thread switching while blocked.

Note that this is one of many open functions. Different open functions open different types of files, like a standard I/O file in this case, and a string in the case of sopen. However, once the file is open, the same I/O functions and close function are used for all types of files.

  string = getchar([file])

Reads a single character from file

and returns it as a string. Returns NULL upon end of file. If file is not given, the current value of stdin in the current scope is used. On some files and systems this may block, but will allow thread switching while blocked.

  string = getcwd()

Returns the name of the current working directory.

  string = getenv(string)

Returns the value of an environment variable. (Under Windows only, a case insensitive match is done to work around some bugs in Windows.)

  string = getfile([file])

Reads all remaining data from file and returns it as a string. If file is not given, the current value of stdin in the current scope is used. If file is a string, it is taken as a file name and opened and closed using the current values of fopen and close in the current scope.

On some files and systems this may block, but will allow thread switching while blocked.

  string = getline([file])

Reads a line of text from file and returns it as a string. Any end-of-line marker is removed. Returns NULL upon end of file. If file is not given, the current value of stdin in the current scope is used.

On some files and systems this may block, but will allow thread switching while blocked.

  string = gettoken([file [, seps]])

Read a token (that is, a string) from file (which may be a file or a string).

seps must be a string. It is interpreted as a set of characters which do not from part of the token. Any leading sequence of these characters is first skipped. Then a sequence of characters not in seps is gathered until end of file or a character from seps is found. This terminating character is not consumed. The gathered string is returned, or NULL if end of file was encountered before any token was gathered.

If file is not given the current value of stdin in the current scope is used. If file is a string, characters are read from the string.

If seps is not given the string " \t\n" is assumed.

Currently, even if blocked while reading a file gettoken is indivisible with repect to other threads. This may be corrected in future versions.

  array = gettokens([file [, seps [, terms, [delims]]]])

Read tokens (that is, strings) from file. The tokens are character sequences separated by seps and terminated by terms. Returns an array of strings, NULL on end of file.

If seps is a string, it is interpreted as a set of characters, any sequence of which will separate one token from the next. In this case leading and trailing separators in the input stream are discarded.

If seps is an integer it is interpreted as a character code. Tokens are taken to be sequences of characters separated by exactly one of that character.

terms must be a string. It is interpreted as a set of characters, any one of which will terminate the gathering of tokens. The character which terminated the gathering will be consumed.

delims must be a string. It is interpreted as a set of self-delimiting single character tokens that will be seperated out as single character strings in the resulting array.

If file is not given the current value of stdin in the current scope will be used.

If seps is not given the string " \t" is assumed.

If terms is not given the string "\n" is assumed.

If delims is not given the string "" is assumed.

For example:

    forall (token in gettokens(currentfile()))
        printf("<%s>", token)
    ;This    is my line    of data.
    printf("\n");

when run will print:

    <This><is><my><line><of><data.>

Whereas:

    forall (token in gettokens(currentfile(), ':', "*", "$"))
        printf("<%s>", token)
    ;:abc::def$:ghi:*printf("\n");

when run will print:

    <><abc><><def><$><ghi><>

Currently, even if blocked while reading a file gettokens is indivisible with respect to other threads. This may be corrected in future versions.

  string = gsub(string, string|regexp, string)

gsub performs text substitution using regular expressions. It takes the first parameter, matches it against the second parameter and then replaces the matched portion of the string with the third parameter. If the second parameter is a string it is converted to a regular expression as if the regexp() function had been called. gsub does the replacement multiple times to replace all occurrances of the pattern. It returns the new string formed by the replacement. If there is no match this is the original string. The replacement string may contain the special sequence \& which is replaced by the string that matched the regular expression. Parenthesized portions of the regular expression may be matched by using \fPfP where n is a decimal digit.

For example:

    x = gsub("abc xbz xyz", #(.)b(.)#, "\\2b\\1");

will result is x having the value:

    "cba zbx xyz"

Notice that double backslashes were needed in the replacement string to get the single backslash required.

  string = implode(array)

Returns a string formed from the concatenation of elements of array. Integers in the array will be interpreted as character codes; strings in the array will be included in the concatenation directly. Other types are ignored.

  struct = include(string [, scope])

Parses the code contained in the file named by the string into the scope. If scope is not passed the current scope is used. include always returns the scope into which the code was parsed. The file is opened by calling the current definitions of the fopen and close in the current scope.

include first attempts to open the file exactly as named. If that failes, it looks for the file using the directories named in the path variable in the current scope (see path above).

  value = int(any [, base])

Returns an integer interpretation of any, or 0 if no reasonable interpretation exists. any should be an int, a float, or a string, else 0 will be returned. If any is a string and base is zero or absent, any will be converted to an int depending on its appearance; applying octal and hex interpretations according to the normal ICI source parsing conventions. (That is, if it starts with a 0x it will be interpreted as a hex number, else if it starts with a 0 it will be interpreted as an octal number, else it will be interpreted as a decimal number). If base is present and non-zero, it must be an int in the range 2..36, and it will be used as the base for intepretation of the string.

  subpart = interval(str_or_array, start [, length])

Returns a sub-interval of str_or_array, which may be either a string or an array.

If start (an integer) is positive the sub-interval starts at that offset (offset 0 is the first element). If start is negative the sub-interval starts that many elements from the end of the string (offset -1 is the last element, -2 the second last etc).

If length is absent, all the elements from the start are included in the interval. Otherwise, if length is positive that many elements are included (or till the end, whichever is smaller). Otherwise (i.e. length is negative) that much less than the number of elements in the str_or_array is used.

For example, the last character in a string can be accessed with:

    last = interval(str, -1);

And the first three elements of an array with:

    first3 = interval(ary, 0, 3);

And all except the last three elements of an array with:

    first3 = interval(ary, 0, -3);

  int = inst|class:isa(any)

Returns 1 if inst or class or any of their super classes is equal to any, else 0. That is, if inst or class is a, or is a sub-class of, any.

  int = isatom(any)

Return 1 (one) if any is an atomic (read-only) object, else 0 (zero). Note that integers and floats are always atomic and strings are atomic unless made with strbuf.

  array = keys(struct)

Returns an array of all the keys from struct. The order is not predictable, but is repeatable if no elements are added or deleted from the struct between calls and is the same order as taken by a forall loop.

  any = load(string)

Attempt to load a library named by string. This is the explicit form of the automatic library loading described in "Automatic library loading" in the ICI Programming Language. The library is loaded in the same way and the resulting object returned. (Actually, this is the real core mechanism. The automatic mechanis calls the function load() in the current scope to load the module. Thus overiding load() allows control to be gained over the automatic mechanism.)

  float = log(x)

Returns the natural logarithm of x (a float or an int).

  float = log10(x)

Returns the log base 10 of x (a float or an int).

  mem = mem(start, nwords [, wordz])

Returns a memory object which refers to a particular area of memory in the ICI interpreter's address space. Note that this is a highly dangerous operation. Many implementations will not include this function or restrict its use. It is designed for diagnostics, embedded systems and controllers. See the alloc function above.

  file = mopen(mem [, mode])

Returns a file, which when read will fetch successive bytes from the given memory object. The memory object must have an access size of one (see alloc and mem above). The file is read-only and the mode, if passed, must be one of "r" or "rb".

  int = nels(any)

Returns the number of elements in any. The exact meaning depends on the type of any. If any is an:

array
    the length of the array is returned; if it is a

struct
    the number of key/value pairs is returned; if it is a

set the number of elements is returned; if it is a

string
    the number of characters is returned; and if it is a

mem the number of words (either 1, 2 or 4 byte quantities) is returned;

and if it is anything else, one is returned.

  inst = class:new()

Creates a new instance of the given class. In practice new is often also defined in sub-classes. This is the global new. The new inst will be a fresh struct with class as its super.

  float = now()

Returns the current time expressed as a signed float time in seconds since 0:00, 1st Jan 2000 UTC.

  number = num(x [, base])

If x is an int or float, it is returned directly. If x is a string and base is zero or absent, x will be converted to an int or float depending on its appearance; applying octal and hex interpretations according to the normal ICI source parsing conventions. (That is, if it starts with a 0x it will be interpreted as a hex number, else if it starts with a 0 it will be interpreted as an octal number, else it will be interpreted as a decimal number.) If base is present and non-zero, it must be an int in the range 2..36, and it will be used as the base for intepretation of the string.

If x can not be interpreted as a number the error %s is not a number is generated.

  scope = parse(source [, scope])

Parses source in a new variable scope, or, if scope (a struct) is supplied, in that scope. source may either be a file or a string, and in either case it is the source of text for the parse. If the parse is successful, the auto scope structure of the sub-module is returned. If an explicit scope was supplied this will be that structure.

If scope is not supplied a new struct is created for the auto variables. This structure in turn is given a new structure as its super struct for the static variables. Finally, this structure's super is set to the current static variables. Thus the static variables of the current module form the externs of the sub-module.

If scope is supplied it is used directly as the scope for the sub-module. Thus the base structure will be the struct for autos, its super will be the struct for statics etc.

For example:

    static x = 123;
    parse("static x = 456;", scope());
    printf("x = %d, x);

When run will print:

    x = 456

Whereas:

    static x = 123;
    parse("static x = 456;");
    printf("x = %d, x);

When run will print:

    x = 123

Note that while the following will work:

    parse(fopen("my-module.ici"));

It is preferable in a large program to use:

    parse(file = fopen("my-module.ici"));
    close(file);

In the first case the file will eventually be closed by garbage collection, but exactly when this will happen is unpredictable. The underlying system may only allow a limited number of simultaneous open files. Thus if the program continues to open files in this fashion a system limit may be reached before the unused files are garbage collected. See also include().

  string = parsetoken(file)

parsetoken uses the interpreter's internal lexical analyser to read the next language token (as described in "The lexical analyser" in The ICI Programming Language) from the given file. The file must be one of the special files layered on top of ICI's parser, as returned by currentfile() or passed to a parser function in a user-parsed literal factor (See "User defined literal factors"). parsetoken skips white-space; which includes comments and lines starting with a #.

parsetoken returns a string, or NULL on end-of-file. The string is the literal text of the token for the following simple self-delimiting tokens:

    *      /      %      +      -      >>
    <<     <      >      <=     >=     ==
    !=     ~      !~     ~~     ~~~    &amp;
    ^      |      &&     ||     :      ?
    =      :=     +=     -=     *=     /=
    %=     >>=    <<=    &=     ^=     |=
    ~~=    <=>    (      )      {      }
    [      ]      .      ->     !      ++
    --     :      $      :^     @      ;

For identifiers, regular expressions, strings, ints and floats, the following strings are returned:

    name   regexp   string   int   float

however the associated value must be obtained by calling tokenobj() to find the actual identifier (a string), regular expression, string, int or float.

On return, the next character available to be read from the input stream will be the first character that is not part of the returned token. See also rejecttoken().

  any = parsevalue(file)

parsevalue parses and evaluates an expression from the given file. The file must be one of the special files layered on top of ICI's parser, as returned by currentfile() or passed to a parser function in a user-parsed literal factor (See "User defined literal factors"). parsevalue skips white-space; which includes comments and lines starting with a #.

On return, the next token (as readable by parsetoken()) will be the first token that is not part of the expression. However, the next character (as readable by getchar()) may be somewhere in advance.

  string = path[]

path is an array or directory names (strings) that is set by the ICI interpreter at startup, and may be modified from time to time by the executing ICI program. The current value of the the path variable in the current scope is used by the automatic module loading mechanism and the include() function as a search path for files. Typically these mechanisms will end up referencing this path variable which is defined in the outermost scope.

The initial value of the path array is set in a slightly system dependent manner:

UNIX-like systems
    The first elements are taken from the ICIPATH environment variable. Each directory name must be separated by a : (colon) in the usual manner. Then, where they exist, “/usr/local/lib/ici4”, “/opt/lib/ici4”, and “/sw/lib/ici4” are included.

    Thereafter the PATH environment variable is considered and for each element that ends in "/bin", the "/bin" is replaced by "/lib/ici4" and if that directory is accessable, it is included. (The usual installation for ICI on UNIX like systems places the ici executable in /usr/local/bin, and externsion modules in /usr/local/lib/ici4).

Windows
    The first elements are taken from the ICIPATH environment variable. Each directory name must be separated by a ; (semicolon) in the usual Windows manner.

    Thereafter the following directories are included: the directory of the current executing module, the "ici" subdirectory of that directory (if any), "." (i.e. the current directory), the Windows system directory, the "ici" subdirectory of the Windows system directory (if any), the Windows directory, the "ici" subdirectory of the Windows directory (if any). Thereafter, elements from the PATH environment variable. (This sequence similar to the normal Windows DLL search order.)

In all cases, if a directory has already been added in an earlier position, or if the directory can not be accessed, it is not included.

  any = pop(array)

Returns the last element of array and reduces the length of array by one. If the array was empty to start with, NULL is returned.

  file = popen(string, [mode])

Executes a new process, specified as a shell command line as for the system function, and returns a file that either reads or writes to the standard input or output of the process according to mode. If mode is "r", reading from the file reads from the standard output of the process. If mode is "w", writing to the file writes to the standard input of the process. If mode is not specified it defaults to "r".

On some commands and systems this may block, but will allow thread switching while blocked.

(popen is not currently available on Windows. This may be corrected in a future version.)

  float = pow(x, y)

Returns x^y where both x and y are floats.

  printf([file,] fmt, args...)

Formats a string based on fmt and args as per sprintf (below) and outputs the result to the file, or to the current value of the stdout variable in the current scope if the first parameter is not a file. The current stdout must be a file. See sprintf.

On some files and systems this may block, but will allow thread switching while blocked.

  profile(filename)

Enables profiling within the scope of the current function (must be called within a function). This profiler measures actual elapsed time so it's only very useful for quite coarse profiling tasks. The filename specifies a file to write the profiling records to once it is complete. The profiling completes when the function profile() was called from returns. The file contains a re-parsable ICI data structue of the form:

    auto profile = [struct
        total = <time in ms for this call>,
        call_count = <number of call to this func>,
        calls = [struct <nested profile structs...>],
    ];

For example, the following program:

    static
    count10000()
    {
        j = 0;
        for (i = 0; i < 10000; ++i)
            j += i;
    }
    static
    count20000()
    {
        count10000();
        count10000();
    }
    static
    prof()
    {
        profile("prof.txt");
        count10000();
        count20000();
    }
    prof();

Would produce a file "prof.txt" file looking something like:

    auto profile = [struct
     total = 153,
     call_count = 0,
     calls = [struct
      ("count20000()") = [struct
       total = 96,
       call_count = 1,
       calls = [struct
        ("count10000()") = [struct
         total = 96,
         call_count = 2,
         calls = [struct
         ],
        ],
       ],
      ],
      ("count10000()") = [struct
       total = 57,
       call_count = 1,
       calls = [struct
       ],
      ],
     ],
    ];

  any = push(array, any)

Appends any to array, increasing its length in the process. Returns any.

  put(string [, file])

Outputs string to file. If file is not passed the current value of stdout in the current scope is used.

  putenv(string)

Sets an environment variable. string must be of the forms name=value.

  int = rand([seed])

Returns a pseudo random integer in the range 0..0x7FFF. If seed (an int) is supplied the random number generator is first seeded with that number. The sequence is predictable based on a given seed.

  reclaim()

Force a garbage collection to occur.

  re = regexp(string [, int])

Returns a compiled regular expression derived from string This is the method of generating regular expressions at run-time, as opposed to the direct lexical form. For example, the following three expressions are similar:

    str ~ #*.c#
    str ~ regexp("*\.c")
    str ~ $regexp("*\.c")

except that the middle form computes the regular expression each time it is executed. Note that when a regular expression includes a # character the regexp function can be used, as the direct lexical form has no method of escaping a #. (Although you can concatenate it with a string.)

The optional second parameter is a bit-set that controls various aspects of the compiled regular expression's behaviour. This value is passed directly to the PCRE package's regular expression compilation function. Presently no symbolic names are defined for the possible values and interested parties are directed to the PCRE documention included with the ICI source code.

Note that regular expressions are intrinsically atomic. Also note that non-equal strings may sometimes compile to the same regular expression.

  re = regexpi(string [, int])

Returns a compiled regular expression derived from string that is case-insensitive. I.e., the regexp will match a string regardless of the case of alphabetic characters. Literal regular expressions to perform case-insensitive matching may be constructed using the special PCRE notation for such purposes, see the chapter on regular expressions for details.

  rejectchar(file, str)

Where file is one of the special files layered on top of the interpreter's internal parser (as returned by currentfile() or passed to a parser function in a user-parsed literal factor as described in "User defined literal factors"), and str is the single character string read by an immediately proceeding call to getchar() on the file, rejectchar pushes the character back on the stream so it is available to be read by a subsequent call to getchar() or by the interpreter's internal parser.

  rejecttoken(file)

Causes the token read by a preceeding call to parsetoken() to be pushed back on the input stream and thus be available for re-reading by a subsequent call to parsetoken() or by the interpreters own parser. The file must be one of the special files layered on top of the interpreter's internal parser, and the last operation on the file must have been a call to parsetoken(). Note that this operation does not effect the file read position with respect to direct character I/O by functions such as getchar().

int = inst|class:respondsto(name)

Returns 1 if inst or class supports a function called name, else 0.

  remove(string)

Deletes the file whose name is given in string.

  rename(oldname, newname)

Change the name of a file. The first parameter is the name of an existing file and the second is the new name that it is to be given.

  any = rpop(array)

Returns the first element of array and removes that element from array, thus shortening it by one. If the array was empty to start with, NULL is returned. After this the item that was at index 1 will be at index 0. This is an efficient constant time operation (that is, no actual data copying is done).

  any = rpush(array, any)

Inserts any as the first element of the array, increasing the length of array in the process. After this the item that was at index 0 will be at index 1. The passed any is returned unchanged. This is an efficient constant time operation (that is, no actual data copying is done).

  current = scope([replacement])

Returns the current scope structure. This is a struct whose base element holds the auto variables, the super of that hold the statics, the super of that holds the externs etc. Note that this is a real reference to the current scope structure. Changing, adding and deleting elements of these structures will affect the values and presence of variables in the current scope.

If a replacement is given, that struct replaces the current scope structure, with the obvious implications. This should clearly be used with caution. Replacing the current scope with a structure which has no reference to the standard functions also has the obvious effect.

  int = seek(file, int, int)

Set the input/output position for a file and returns the new I/O position. The arguments are the same as for the C library's fseek function. The second argument is the offset to seek to and the third is 0, 1 or 2 dependng if the seek should be relative to the beginning, current position, or end of the file. If the file object does not support setting the I/O position, or the seek operation fails.

  set = set(any...)

Returns a set formed from all the arguments. For example:

    set()

will return a new empty set; and

    set(1, 2, "a string")

will return a new set with three elements, 1, 2, and "the string".

This is the run-time equivalent of the set literal. Thus the following two expressions are equivalent:

    $set(1, 2, "a string")

    [set 1, 2, "a string"]

  func = signal(string|int [, string|func])

Allows control of signal handling to the process running the ICI interpreter. The first argument is the name or number of a signal. Signal numbers are defined by the system whilst the function signam() may be used to obtain signal names. If no second argument is given, the function returns the current handler for the signal. Handlers are either functions or one of the strings "default" or "ignore". If a second argument is given the signal handler's state is set accordingly, either being reset to its default state, ignored or calling the given function when the signal occurs. The previous signal handler is returned in this case.

  string = signam(int)

Returns the name of a signal given its number. If the signal number is not valid an error is raised.

  x = sin(angle)

Returns the sine of angle (a float interpreted in radians).

  sleep(num)

Suspends execution of the current thread for num seconds (a float or int). The resolution of num is system dependent.

  array = smash(string [, regexp [, replace...] [, include_remainder])

Returns an array containing expanded replacement strings that are the result of repeatedly applying the regular expression regexp to successive portions of string. This process stops as soon as the regular expression fails to match or the string is exhausted.

Each time the regular expression is matched against the string, expanded copies of all the replace strings are pushed onto the newly created array. The expansion is done by performing the following substitutions:

\0  Is substituted with any leading unmatched portion between the end of the last match (or the start of the string if this is the first match) and the first character that was matched by this match.

\&  Is substituted with the portion of the string that was matched by this application of the regular expression.

\1 \2 \3 ...
    Is substituted with the portions of the string that were matched by the successive bracketed sub-portions of the regular expression.

\\  Is substituted with a single \ character.

If the final argument, include_remainder, is supplied and is a non-zero integer, any remaining unmatched portion of the string is also added as a final element of the array. Else any unmatched remainder is discarded.

If regexp is not supplied, the regular expression #\n#

is used. If no replace arguments are supplied, the single string "\0"

is used. Thus by default smash will break the given string into its newline delimited portions (although it will discard any final undelimited line unless include_remainder is specified).

For example:

    lines = smash(getfile(f), 1);

will result in an array of all the lines of the file, with newlines characters discarded. While:

    smash("ab cd ef", #(.) #, "x\\0", 1);

will result in an array of the form:

     [array "xa", "xc", "ef"]

Notice that it is generally necessary to use two backslash characters in literal strings to obtain the single backslash required here.

  file = sopen(string [, mode])

Returns a file, which when read will fetch successive characters from the given string. The file is read-only and the mode, if passed, must be one of "r" or "rb", which are equivalent.

  array = sort(array [, func [, arg]])

Sort the content of the array in-place using the heap sort algorithm with func as the comparison function. The comparison function is called with two elements of the array as parameters, a and b, and the optional arg. If a is equal to b the function should return zero. If a is less than b, -1, and if a is greater than b, 1.

For example,

    static compare(a, b, arg)
    {
        return a < b ? -1 : a > b;
    }
    static a = array(1, 3, 2);
    sort(a, compare);

If arg is not provided, NULL is passed. If func is not provided, the current value of cmp in the current scope is used. See cmp(). Returns the given array.

  string = sprintf(fmt, args...)

Return a formatted string based on fmt (a string) and args.... Most of the usual % format escapes of ANSI C printf are supported. In particular; the integer format letters diouxXc are supported, but if a float is provided it will be converted to an int. The floating point format letters feEgG are supported, but if the argument is an int it will be converted to a float. The string format letter, s is supported and requires a string. The % format to get a single % works. In addition to these standard formats, a format letter of a (any) is supported. This takes any object and converts it to a short human readable form of less than 30 characters length, and thereafter behaves as an s specification. This representation of an object is suitable for diagnostics only.

The flags, precision, and field width options are supported. The indirect field width and precision options with * also work and the corresponding argument must be an int.

For example:

    sprintf("%08X <%4s><%-4s>", 123, "ab", "cd")

will produce the string:

    0000007B <  ab><cd  >

and

    sprintf("%0*X", 4, 123)

will produce the string:

    007B

sprintf does not currently handle nul characters in the fmt string. This may be corrected in future releases.

  x = sqrt(float)

Returns the square root of float.

  string = strbuf([string])

Returns a new non-atomic string that is either zero length, or, if a string argument is given, is initilised with characters copied from that string. This is the only function that produces non-atomic strings. All other operations that produce strings make atomic (immutable, read-only) strings. Note that a non-atomic string will not reference the same element of a struct as an atomic string of equal value. See also strcat().

  string = strcat(string [, int] , string...)
Copies string(s) onto the end of (or to some integer offset in) a given non-atomic string, extending the non-atomic string as necessary. The first argument must be a non-atomic string (see strbuf() above). If the optional int argument is given, that offset from the start of the non-atomic string will be the starting point for the placement of the concatenated string data, else the end of the string is used. All the remaining string arguments are used as a source of characters to be copied into the non-atomic string. The (updated) non-atomic string is returned.

  string = string(any)

Returns a short textual representation of any. If any is an int or float it is converted as if by a %d or %g format. If it is a string it is returned directly. Any other type will returns its type name surrounded by angle brackets, as in <struct>.

  struct = struct([super,] key, value...)

Returns a new structure. This is the run-time equivalent of the struct literal. If there are an odd number of arguments the first is used as the super of the new struct; it must be a struct. The remaining pairs of arguments are treated as key and value pairs to initialise the structure with; they may be of any type. For example:

    struct()

returns a new empty struct;

    struct(anotherStruct)

returns a new empty struct which has anotherStruct as its super;

    struct("a", 1, "b", 2)

returns a new struct which has two entries a and b with the values 1 and 2; and

    struct(anotherStruct, "a", 1, "b", 2)

returns a new struct which has two entries a and b with the values 1 and 2 and a super of anotherStruct.

Note that the super of the new struct is set after the assignments of the new elements have been made. Thus the initial elements given as arguments will not affect values in any super struct.

The following two expressions are equivalent:

    $struct(anotherStruct, "a", 1, "b", 2)

    [struct:anotherStruct, a = 1, b = 2]

  string = sub(string, string|regexp, string)

Sub performs text substitution using regular expressions. It takes the first parameter, matches it against the second parameter and then replaces the matched portion of the string with the third parameter. If the second parameter is a string it is converted to a regular expression as if the regexp function had been called. Sub does the replacement once (unlike gsub). It returns the new string formed by the replacement. If there is no match this is the original string. The replacement string may contain the special sequence \& which is replaced by the string that matched the regular expression. Parenthesized portions of the regular expression may be matched by using \n where n is a decimal digit. (Remember to use an extra backslash in a literal string to get a single backslash. For example "\&".

  current = super(struct [, replacement])

Returns the current super struct of struct, and, if replacement is supplied, sets it to a new value. If replacement is NULL any current super struct reference is cleared (that is, after this struct will have no super).

  int = system(string)

Executes a new process, specified as a shell command line using the local system's command interpreter, and returns an integer result code once the process completes (usually zero indicates normal successful completion).

This will block while the process runs, but will allow thread switching while blocked.

  x = tan(angle)

Returns the tangent of angle (a float interpreted in radians).

  exec = thread(callable, args...)

Creates a new ICI thread and calls callable (typically a function or method) with args in the new ICI execution context in that thead. Returns an execution context object ("exec"). When the thread terminates (by returning from the called function) this object is woken up with wakeup().

  string = tochar(int)

Returns a one character string made from the character code specified by int.

  int = toint(string)

Returns the character code of the first character of string.

  any = tokenobj(file)

tokenobj returns the object associated with an immediately proceeding call to parsetoken() on the given file where parsetoken() returned one of the values: name, int, float, regexp, or string (in other cases it will return NULL). It can be called any number of times until some other I/O operation is done on the file.

  any = top(array [, int])

Returns the last element of array (that is, the top of stack). Or, if int is supplied, objects from deeper in the stack found by adding int to the index of the last element. Thus:

    top(a, 0)

and

    top(a)

are equivalent, while

    top(a, -1)

returns the second last element of the array. Returns NULL if the access is beyond the limits of the array.

  string = typeof(any)

Returns the type name (a string) of any. See the section on types above for the possible type names.

  string = version()

Returns a version string of the form.

    @(#)ICI 4.0.0 config-file build-date config-str (opts...)

For example:

    @(#)ICI 4.0.0, conf-w32.h, Feb 22 2002, Microsoft Win32 platforms (math trace system pipes sockets dir dload startupfile debugging )

  array = vstack([int])

With no arguments, returns a copy of the call stack of the current program at the time of the call. This is an array of the successive outer scope structures. The last element of the array is the current innermost scope structure, the second last is the innermost scope structure of the caller, etc.

With an integer argument, returns the scope structure from that many callers back. Zero is the current scope, one is the caller etc. This is generally more efficient, as it avoids the array copy of the first form.

This can be used both for stack tracebacks, and to discover the value of a particular variable in the callers context (in the way that, say, getline() uses the value of stdin in the callers context).

  wakeup(any)

Wakes up all ICI threads that are waiting for any (and thus allow them to re-evaluate their wait expression).

  struct = which(key [, struct])

Finds the first struct (or other object) in a super chain that has the given key as an element. If the argument struct is given (which is normally a struct, but may be any object that supports a super), that object is used as the base of the search, else the current scope is used. Returns NULL if key was not an element of any object in the super chain.

SEE ALSO
ici(1), icinet(1), icioo(1), iciops(1), icisyn(1), icitypes(1), iciex(1)