When the CGL interpreter starts up, it registers many built-in
procedures that are implemented in C. Many of these
built-in routines are general in nature. While other built-in's
work with the compiler engine of AMC to control the compilation of
source modules.
Of course, CGL is designed primarily to manipulate strings. To do this efficiently, CGL has quite a few built-in string manipulation functions:
ask(prompt)
This function displays prompt and then reads a line
of input. The line of input is returned.
ltrim(str, chars)
This function removes any character in the string chars from
the left of str until there are no more characters on the left
of str that are in chars.
match_pat(str, pattern)
This function will determine if str fits the
pattern string. The pattern string can contain
a * to mean a set of zero or more characters and a
? to mean any possible character.
quote_str(str, quote_set, [quote_char])
This function quotes a string. Any characters from str that
are in quote_set are replaced with a quoted version so that
the characters in quote_set do not appear in the result.
The quoted characters are represented by quote_char (which
defaults to + if not specified) followed by the hexadecimal
representation of the character (2 characters).
rtrim(str, chars)
This function removes any character in the string chars from
the right of str until there are no more characters on the
right of str that are in chars.
strdef(value, default)
If value is a zero-length string, then this evaluates to
default, otherwise, this evaluates to value.
strequ(a, b, [count])
Evaluates to ``true'' if a equals b. If
count is specified, only the first count
characters are compared.
strlen(a)
This function computes the length (number of characters) of the
string a.
strcount(str, set)
This function counts the number of times characters from
set appear in str.
strcmp(a, b, [count])
This function is similar to strequ except that it
returns a signed integer that is less than 0 if a is
lexicographically less than b; 0 if a is equal
to b; or greater than 0 if a is greater than
b.
strchr(str, set)
Return the position (0 based) in str of the first
ocurrance of any character in set.
If no characters from set are present in str,
-1 is returned.
strtake(var, set)
This routine takes the value of the variabled named var
and removes the first string delimited by any character
in set. The token is returned (without the separator
charcter). The variable named var is updated by removing
the token and separator character.
The variable named var must be bound at the time this
is called.
This function is very useful for pulling tokens, one-by-one off a string for processing.
substr(str, start, [length])
Returns a subset of str starting at character offset
start (0 based). If length is specified the
resultant substring will be no longer than length.
If length is not specified, the remaining length of the
input string is assumed.
strdel(str, pos, [count])
Remove count characters from str starting
at pos, zero-based index into str.
If count is not specified, it defaults to 1.
strins(str, pos, txt)
Insert txt at position pos in str.
strwalk(str, expr)
For each character in str, evaluate expr with
the variable cur_char bound to each character as it is
iterated over.
strempty(str)
Evaluates to ``true'' if str has a length of zero.
strcap(str)
Capitalize the first character of every word in str.
strlwr(str)
Make all characters in str lower-case.
strupr(str)
Make all characters in str upper-case.
strrept(count, str)
Evaluates to count concatenations of str.
strrepl(str, pattern, repl)
Search-and-replace all occurances of pattern
in str with repl. This is really quite
powerful because for each successive iteration both pattern
and repl are re-evaluated.
tokenize(str, expr, [separator])
This built-in separates out tokens from str and evaluates
expr for each one with the variable cur_token
bound to the value of that token. If separator is not
specified, it defaults to a comma (",").
For example, to read a comma-separated list of strings into a table the following code will work:
i = (0)
tokenize(string_list,
table_set(~result_table, i, cur_token)
i = (add(i, 1)))
trim(str, chars)
This function removes any character in the string chars from
the right and left of str until there are no more characters
on the either edge of str that are in chars.
unquote_str(str, [quote_char])
This function un-quotes a string. It performs the opposite action of
the quote_str built-in.
Any characters that were escaped by the quoting character
quote_char (which defaults to + if not specified)
are restored to the result.
quote_str and unquote_str are useful for
generating keys into the project state database file.
void(expr)
This function simply evaluates expr and ignores its result. This is necessary for cases when only the side-effects of a fragment of CGL code are necessary and the result must not be inserted in the result of the current procedure.
ws_sqz(str)
This function takes it argument and compresses runs of whitespace into a single whitespace.
CGL keeps all numbers in string format. While this does incur a performance penalty, it is well worth simplifying the language. Furthermore, few CGL applications do large amounts of arithmatic, making the performance penalty a minimum. The following procedures are available in CGL for doing integer arithmatic:
add(a, b, ...)
This procedure adds all of the numbers in its argument list and returns
the result. Unlike languages with a binary + operator,
add supports an infinite number of arguments to be added
together. This procedure takes a minimum of two arguments.
sub(a, b, ... )
This procedure subtracts all of the remaining arguments from
argument a. This procedure takes a minimum of two arguments.
div(a, b, ...)
This procedure divides all of the remaining arguments from
argument a. This procedure takes a minimum of two arguments.
mod(a, b, ...)
This procedure computes the remainder of the division as it would
be performed by the div function. It also takes a
minimum of two arguments.
mul(a, b, ...)
This procedure multiplies all of the arguments together and evaluates to the product. This procedure takes a minimum of two arguments.
min(a, b, ...)
This procedure returns the smallest of its arguments.
max(a, b, ...)
This procedure returns the largest of its arguments.
band(a, b, ...)
This procedure computes the bitwise and of all of its arguments.
bnot(a)
This procedure computes the bitwise compliment of its argument.
bor(a, b, ...)
This procedure computes the bitwise inclusive-or of all of its arguments.
bxor(a, b, ...)
This procedure computes the bitwise exclusive-or of all of its arguments.
shl(a, b)
Compute the value of a shifted left by b bits.
shr(a, b)
Compute the value of a shifted right by b bits.
Because built-in's can selectively evaluate their arguments (unlike ordinary user-defined CGL procedures) or evaluate their arguments multiple times, looping and flow-control primitives can be done as CGL built-in's.
and(cond_0, cond_1, ...)
This function is a logical ``and'' of its arguments. All of the arguments are evaluated, from left to right until one evaluates to false (in which case, the result of the expression is false) or there are no more arguments (in which case, the result of the expression is true). More simply, if any of the arguments evaluate to false, the result is false; otherwise, the result is true.
between(val, low, high)
This function evaluates to true if val is greater than or
equal to low and less than or equal to high.
bind_var(name, value)
This built-in sets the value of the variabled named name to
value. Unlike the CGL assignment operator (=), this
built-in takes the name of the variable as a string.
unbind_var(name)
If a variable is bound, unbind it. Any further references to the variable will result in a runtime error.
count(a, b, expr, [step])
Continually evaluates expr with the variable
counter taking on values from
a to b (inclusive). If the optional argument
step is provided, the variable
counter is incremented (or decremented) by this amount
while it is within the range. If b is greater than
a, the loop goes upward, otherwise, it goes downward.
The result of this function is the concatenation of the results
of evaluating expr as many times as was necessary.
dynamic_call(name, error, ...)
dynamic_call provides a way to call a function when you do not
know its name. Given a valid routine name as a string parameter,
dynamic_call will call the function associated with that name.
If the function can not be be found, the code passed as the second
parameter (error) is executed.
Arguments following the error handler are passed to the named routine. If the number of arguments is incorrect for the routine, the error handler is executed.
eacharg(expr)
For each argument (numbered 1 to the result of the
function argcnt), the expression expr is
evaluated with the variable current_arg bound to the value
of the current argument.
eq(a, b)
This function evaluates to true if a and b
are numerically equivilant.
eval_var(name)
This function evaluates the contents of the variable named name.
It allows you to access the variables with string names instead of being
fixed in the source code of your CGL programs. If the variable is not
bound, an exception is raised.
false
This function always evaluates to false.
gt(a, b)
This function evaluates to true if a is numerically
greater than b.
gte(a, b)
This function evaluates to true if a is numerically
greater than or equal to b.
if(cond, true_expr)
If cond is true, this function evaluates to the value
of true_expr. If cond is false,
true_expr is not evaluated and the function evaluates
to nothing.
if(cond, true_expr, false_expr)
If cond is true, this function evaluates to the value
of true_expr and false_expr is not
evaluated. If cond is false, true_expr
is not evaluated and the function evaluates to
false_expr.
ifnot(cond, false_expr)
If cond is false, this function evaluates to the value
of false_expr. If cond is true,
false_expr is not evaluated and the function evaluates
to nothing. This is equivilant to
if(not(cond), false_expr).
is_defined(name)
Referencing an undefined variable name in CGL code can cause a runtime
exception. To test for this and avert the runtime exception, this
built-in will return true if the named variable is defined.
Otherwise, it returns false and you can avoid the exception.
is_zero(a)
This function returns true if its argument is numerically zero.
var_enum(expr)
For each defined variable in the system, evaluate expr
with the variable var_name bound to the name of the
current variable.
local(var1, var2, ..., expr)
This built-in provides variable scoping to allow recursion. Every argument
except the last is considered to be the name of a variable. During the
evaluation of expr, the values of the variables are preserved.
If any of them were modified by expr they are restored to their
original value after expr is executed.
Remember that the arguments are the names of the variables as strings, not
the values of the variables. Therefore, it is usually necessary to use the
tilde (~) character to quote the variables names.
lt(a, b)
This function evaluates to true if a is numerically
less than b.
lte(a, b)
This function evaluates to true if a is numerically
less than or equal to b.
neq(a, b)
This function evaluates to true if a and
b are numerically different.
not(cond)
If cond evaluates to true, this function
evaluates to false. If cond evaluates
to false, this function evaluates to true.
or(cond_0, cond_1, ...)
This function is a logical ``or'' of its arguments. All of the arguments are evaluated, from left to right until one evaluates to true (in which case, the result of the expression is true) or there are no more arguments (in which case, the result of the expression is false). More simply, if any of the arguments evaluate to true, the result is true; otherwise, the result is false.
true
This function always evaluates to true.
until(cond, expr)
expr is evaluated until cond is true.
expr is always evaluated at least once and is always
evaluated before cond. The result of this function is the
concatenation of the results of evaluating expr
as many times as was necessary.
while(cond, expr)
While cond evaluates to true, expr
is evaluated. cond is evaluated first and always
before expr. If cond evaluates to false
when the while function is first called,
expr is never evaluated. The result of this
function is the concatenation of the results of evaluating
expr as many times as was necessary.
CGL normally propagates exceptions back to the initial caller of a CGL program. CGL programs can raise their own exceptions which will abort back to the inner-most catch block. Memory is never leaked during a raised excpetion but depending on your CGL program it may be necessary to do some other kinds of cleanup (reset state variables, delete tables, etc).
Exception processing is done with two built-in functions, catch
and throw. Catch is used at where errors should be
handled. The first argument is evaluated. If no exception is thrown,
catch ignores its second argument.
If throw is called any time while executing under the context of
a catch, the processing is aborted and execution resumes in
the second argument of the inner-most catch function. The
argument to throw is bound to the variable exception
while the handler in the catch block is running.
CGL has the ability to manipulate operating system files similar to the standard I/O library in ANSI C. The built-in procedures for doing this deal with a ``file ID'' which is a string that is used to refer to an open file. The string is very similar (but not identical) to a file handle in most operating systems.
f_open(file_name, mode)
This function opens a file named file_name. If the
argument mode is provided, the argument is passed to
the fopen system call. If mode is omitted, a
default of read-only access is used.
On success, a file id is returned.
f_close(file_id)
This function closes the specified file. After this function is called the file id may not be used anymore.
f_getch(file_id)
This function gets a single character from the specified file. The empty string is returned on end-of-file.
f_rewind(file_id)
This function re-positions the file pointer to the head of the file and resets any error indicators associated with the file (such as end-of-file).
f_fastforward(file_id)
This function re-positions the file pointer to the end of the file.
f_readln(file_id, result_var_name)
This function reads a line from the specified file upto (but not including
a newline terminator). The read line is stored in a variable named
result_var_name. The return value of the function is true if the
line was read successfully or false if an end of file occured.
This interface makes it very easy to iterate the lines of a text file, for example:
while (f_readln(my_file, ~input_line),
process_line(input_line))
process_line for each line in the file.
f_write(file_id, string)
This function writes string into the specified file.
f_getname(file_id)
This function gets the name associated with the specified file.
f_eof(file_id)
This function returns true if the next read request on the file would fail because the end of the file has been reached.
This is unlike the feof function in ANSI C which only
reports the end of file condition after it happens.
mkdir(path)
This function ensures that a particular directory path exists (so that a file can be created in that directory). If any components of the path do not exist, they are constructed.
This function returns an empty string on success or an error message string on failure.
To remain portable, AMC uses a set of routines to handle the manipulation of file names. These routines are exposed to CGL so that CGL routines are also portable. The abstraction AMC uses for filenames is simple and quite portable among different operating systems. Basically, a filename is a string that contains three components separated by certain lexicographic separators. The three components of a filename are:
This is basically where to find a particular file.
This is the actual name of a file
This is an identifier of what information the file contains.
The following CGL routines manipulate filenames when they are stored as CGL strings:
fn_loc(filespec)
This built-in evaluates to the location of filespec.
fn_rmloc(filespec)
This built-in evaluates to everything but the location of
the filespec.
fn_type(filespec)
This built-in evaluates to the type of filespec.
fn_rmtype(filespec)
This built-in evaluates to everything but the type of
the filespec.
fn_cons(location, name, type)
Construct a filename given a location, name, and type.
fn_normalize(filespec)
Most operating systems allow shortcuts in the way path names are specified. AMC has the ability to take the shortcut file name and compute the absolute (or so called "normalized" filename).
This built-in takes a file specification and returns the normalized
file specification if possible. If normalization is not possible (due to
error or system limitations) filespec is returned.
CGL also contains various ``useful'' utility routines that don't fit in other categories:
sysinfo(switch)
This routine obtains information from the operating system.
The kind of information obtained depends on first character
of the switch parameter:
o
The operating system name. This is a specific string
classifying the operating system on which AMC is running.
On UNIX systems, this is identical to the string obtained
from the uname system call.
h
The name of the machine on which AMC is running if available,
the empty string ("") if not.
l
The login/user/account name under which AMC is running.
u
The name of the person logged in who is running AMC.
t
The name of the hardware AMC is running on.
time(switch)
This routine obtains current time and date information from
the operating system. The kind of information depends on the
first character of the switch parameter (which is
a direct interface to the ANSI C strftime routine):
a
The abbreviated weekday name.
A
The full weekday name.
b
The abbreviated month name.
B
The full month name.
c
The preferred date and time representation.
d
The day of the month as a decimal number.
H
The hour as a decimal number using a 24-hour clock.
I
The hour as a decimal number using a 12-hour clock.
j
The day of the year as a decimal number.
m
The month as a decimal number.
M
The minute as a decimal number.
p
Either Am or Pm according to
the current time.
S
The second as a decimal number.
W
The week number of the current year.
w
The day of the week as a decimal number.
x
The preferred date representation.
X
The preferred time representation.
y
The year as a decimal number without a century.
Y
The year as a decimal number including the century.
z
The time zone or name or abbreviation.
tohex(number)
Converts number into hexadecimal format.
No leading 0x is printed.