URL: http://www.firstbasesoftware.com/man/man5/macro.htm
Last modified: 26 January 2000
Copyright © by FirstBase Software.
[
Index of Contents] [
FirstBase RDBMS Overview]
NAME
macro - overview of FirstBase macro language
SYNOPSIS
Description of the FirstBase macro language
DESCRIPTION
The macro language, one component of
FirstBase, is a powerful, easy to use
text and record processing language for Unix/Linux.
Similar to C, macro
includes many familiar programming constructs,
including conditionals, loop constructs, user defined functions,
and printf mechanisms.
This high level language also supports
associative arrays, run time loadable code, strings, and
all of the FirstBase data types. Plus, there are
many built in functions covering math, string, date, screen input/output,
stream input/output, and CGI/HTML processing. The macro
language provides a powerful general purpose processing tool that
can be used with or without a FirstBase database.
Macro files are simple text files containing macro code.
Macro code can be used in three places within FirstBase.
The first use is general database, text, CGI and HTML processing
with the FirstBase generator tool
dbmacro(1).
The second macro code use is to provide extensibility
within
dbvedit(1).
This feature allows flexible control over the record editing process, including
complex defaults and conditional field editing.
The third FirstBase
tool that will process macro code is
fbtstmac(8).
This tool checks for syntax errors in macro code.
MACRO CODE GENERAL PROCESSING
Dbmacro is a general purpose information processor for
FirstBase databases, text files, CGI requests and HTML forms.
With or without a default database,
dbmacro executes
macro(5) code supplied via standard input,
or from the command line use of macro_file or the -m script
option. Output is written to standard output.
See
dbmacro(1) for more details.
MACRO LANGUAGE DEFINITION
FirstBase macro code consists
of sections of statements, with each section identified as one of
begin, body, end, or function.
After parsing the provided macro code, execution begins with the
first body section, or the function named main, for
dbvedit(1) or for
dbmacro(1) without a default database.
When dbmacro is invoked with a default database, execution starts
with the begin section, the body section is done once for each
record, and then the end section is done once.
Each of these sections is declared using its respective keyword,
and each section can contain any number of macro statements.
Only function sections require more than the keyword to define.
Any number of functions can be defined using the following syntax
(again, the square brackets denote optional parts and are not part
of the function section syntax):
function fname( [ arg1 [, arg2 ] ... ] )
{
/* macro statements */
}
The function name fname must be a valid variable name different than
any built in function names.
Function parameters (or arguments) are optional, but the parentheses must still
be used.
Functions can accept any number of parameters and can
return multiple return values, of any type, including arrays.
All function parameters are local.
When a function is executed, the number of arguments can vary, if needed.
For example, if three parameters are
defined in a particular function, but only two are passed as arguments,
the third argument will be empty at run time.
Functions pass all arguments, even arrays,
by value, after expression evaluation, and
can return any number of expressions, objects, scalars, strings, or arrays.
Within each section, statements are sequentially executed until the end of
the section, a return statement or an exit statement.
The exit statement can return a status value to the outside caller.
The return statement returns control to the caller, or exits if
control is inside the body section or main function.
An expression value can be passed back to
dbvedit(1) for screen or
record control.
The following is a list of all FirstBase macro code statements:
local var1 [ , var2 ] ...
if ( conditional ) statement [ else statement ]
while ( conditional ) statement
for ( [ expr-list ] ; [ conditional ] ; [ expr-list ] ) statement
switch ( expr ) {
case expr: [ statement ] [ break ] ...
[ default: statement ... ] }
break
continue
{ [ statement ] ...}
variable = expression
return [ ( [ expr1 [ , expr2 ] ... ] ) ]
exit [ ( [ expr ] ) ]
function ( [ arg1 [ , arg2 ] ... ] )
Statements
are terminated by semicolons, NEWLINE characters or right braces.
Compound statements are grouped into a simple statement with curly braces.
Note that the square brackets are not part of the statements -- they
merely denote optional components.
The switch statement is similar to C in that each set of statements
after a matching case is executed until a break (thereby allowing
overloading of many cases that execute a single set of statements).
However, dbmacro supports case expressions, not just scalars.
In addition, syntactically, the beginning and ending curly braces
are required and the optional default section must be the
last clause.
Expressions are strings or numbers, depending on how they are used,
and are built using the operators +, -, *, /, %. Additionally, the `+'
is overloaded to indicate concatenation for strings.
The C operators ++, --, +=, -=, *=, /=, %=,
<<=, >>=, ^=, &=, |= are also available in expressions.
An expression list is a comma separated list of expressions.
Furthermore, these additional binary operators can be used to build up
expressions and conditionals: <<, >>, <, >, <=, >=, ==, !=, &, ^, |, &&, ||.
Variables are dynamically created without being declared and
are global in all situations unless specified as local
using the local directive. These variables can take on any of
these data types: float, date, string, associative array, or database array.
Variables are initialized to zero (0).
String constants are quoted. Octal constants require a leading 0.
Arrays are subscripted using square brackets. The subscript can be
any value, numeric or string, but is always converted to a string.
This means that array[3] will reference the exact same value as
array["3"]. Array functions, key, countkey
findkey, and rmkey can be used to maintain arrays.
Variables and numbers will have a default precision of six digits past the
decimal,
though this is easily tuned using the functions round() and
trunc(). Database variables will either adhere to this precision, or
be locked into a certain precision as specified in the database dictionary.
See
ddict(5).
Comments inside macro code are either the C method of /* to open
a comment and */ to close it, spanning as many lines as needed,
or the use of the # character, which comments out remaining characters
until the next NEWLINE.
To denote a database field,
a `$' is prepended to either the field name, a variable
scalar, or to a number representing that field location in the database record.
If a scalar is used to access a field, it is evaluated before the field is
referenced. Furthermore, the `$' can be used on entire expressions, as in
the fragment `$(i + 10)'.
However, if the variable or scalar used has not been assigned a value
using an assignment operator, the scalar is
assumed to be an actual field name. For example,
the string `$Field1' will work as long as Field1 is not a previously used
variable.
Assignments to fields change the contents of the field.
Very little type checking is done. The size of the field is
checked, and the entry will be truncated if it is too long.
Arrays are used to access fields of databases opened using the macro
function opendb. Once a database is open,
an array is associated with that particular
database using the initrec function. This association
only needs to be done one time, but can also be used to clear all field values.
In addition, the first call to opendb sets the default database
(see the default_dbase function).
After the array/database association, elements of the array represent
FirstBase fields within the current record. Note that values will not
be accessible via these arrays until after a getrec or getxrec
of some kind, and
that a putrec or an addrec is needed to actually write these
array represented fields as a record to a database.
The subscript used to access a field via an array
is either a field number, like
dbase[3], or a string, like dbase["Name"].
If the variable Name does not exist, dbase[Name]
is equivalent to dbase["Name"]. If an existing variable is used,
its value will be the subscript.
An array associated with a database cannot be used
to hold other subscripted values.
A large number of builtin in functions are provided.
Some of these functions take a variable number of
arguments, but most are fixed at either zero, one, or two arguments.
Arguments are evaluated before being passed to the builtin functions.
The following lists are arranged by function type.
All builtin macro functions and their expected arguments are listed.
Argument types are given as e for general expressions, n
for integer expressions, and se for string expressions.
DATABASE FUNCTIONS
In the following FirstBase database functions, db
is used to represent an open database, like a channel or
pointer. The value of db is a returned from opendb.
-
addrec(db)
-
physically adds a new record to the database db,
complete with record locking and autoindex entries. See
addrec(3).
Returns AOK (1) on success, ERROR (-1) on failure.
-
checkfields(db)
-
checks the fields of the current record in database db
for adherence to the range specifications as defined in the database
dictionary. Additionally, checks all auto indexes
from both the database dictionary and the dbase.auto file
(autoindex(5))
that are supposed to remain unique. Checkfields will return
AOK if there are no data discrepancies, otherwise ERROR will be returned.
-
closedb(db)
-
close the database db. See closedb(3).
-
default_dbase(db)
-
sets the "default" database to db
so that $var evaluates to a field from db.
-
delrec(db)
-
delete the current record from database db and remove all autoindex
references to this record.
Returns AOK (1) on success, ERROR (-1) on failure.
-
eval(expr)
-
evaluates the expression as if it were a variable.
Using this mechanism, an array can be rebuilt from a series of
similarly named variables (perhaps from a CGI form):
var1 = "abc"
var2 = "def"
for (i = 1; i <= 3; i++)
array[i] = eval("var" + i)
As another example, eval can be used with database fields:
for (i = 1; i <= 2; i++){
val = "$field" + i
print(eval(val))
}
Note that the following is equivalent (without using eval):
for (i = 1; i <= 2; i++){
val = "field" + i
print($val)
}
But, here is another example of the eval function:
array["hello"] = 16
ww101="hello"
a = "ww10"
b = a + 1
print(b) # ww101
print(eval(b)) # hello
print(ww101) # hello
print(array[ww101]) # 16
print(array[b]) # 0
print(array[eval(b)]) # 16
-
fgetrec(n, db)
-
used for non-btree indexes only, fgetrec returns the
actual database record number (to be used with getrec)
of the nth entry in the current open database index.
-
field_default(e, db)
-
return the default of the field in database db represented by
the general expression e. If e is numeric, the eth
field is used. If e is a string, the field with the same name is used.
The default of a field is the string as defined in the database dictionary.
See
ddict(5).
-
field_name(i, db)
-
return the name of the ith field in database db.
-
field_size(e, db)
-
return the size of the field in database db represented by
the general expression e. If e is numeric, the eth
field is used. If e is a string, the field with the same name is used.
-
field_type(e, db)
-
return the type of the field in database db represented by
the general expression e. If e is numeric, the eth
field is used. If e is a string, the field with the same name is used.
-
firstxrec(db)
-
loads the first indexed record into database db. See
firstxrec(3).
Returns AOK (1) on success, ERROR (-1) on failure.
-
free_globals()
-
mechanism to free and reset global database memory allocations and
resources. For more details, see
free_globals(3).
-
get_failrec()
-
Provides access to the FirstBase global variable extern long cdb_failrec.
If the value of this function is zero (0), then a failed search for a
record via getxrec has gone beyond the right edge of the btree index.
See also set_loadfail and getirec.
-
getirec(n, db)
-
reads logical record n from database db, and, under a certain
set of conditions, synchronizes the current record with the current index
so that subsequent calls to nextxrec and prevxrec locate the
indexed records after and before the database record n.
See
getirec(3), and functions get_failrec and set_loadfail.
-
getrec(n, db)
-
reads record n from database db, returns actual number of
characters read, or ERROR (-1) on failure. See
getrec(3).
-
getxrec(se, db)
-
get an indexed record.
Use search key se on the current index to load a record
from database db.
Returns AOK (1) on success, ERROR (-1) on failure.
-
initrec(var, db)
-
associates an array of name var with database db.
By referencing an array element or assigning a value to it,
implicit database field fetch and store commands are done.
Initrec also initializes all database fields.
-
ireccnt(db)
-
returns the number of indexed records in the current open index for database
db.
-
lastxrec(db)
-
loads the last indexed record into database db. See
firstxrec(3).
Returns AOK (1) on success, ERROR (-1) on failure.
-
lock(n, db, wait)
-
lock record n of database db.
The wait argument controls lock request failures:
if wait is zero, lock returns control to the caller
with an ERROR (-1) return code; if wait is one,
lock will block until the lock request can be granted.
An AOK (1) is returned when a lock request is granted.
-
makess(se, type, n)
-
returns a search string that is based on se, a FirstBase
field type specified by the string type, placed in a field n
characters wide. The returned string is used for getxrec calls.
Common types are "d" (date) and "n" (numeric).
In addition, see functions field_type and field_size.
-
nextxrec(channel)
-
loads the next indexed record into database db. See
nextxrec(3).
Returns AOK (1) on success, ERROR (-1) on failure.
-
nfields(db)
-
returns the number of fields in database db.
-
opendb(dbase, mode, iname)
-
opens database with name dbase using mode, either "r" for
READ, or "w" for READWRITE.
Optionally, index iname can be opened as well. However, use of
autoindexes and the useidx function is the best method of index
manipulation. Opendb returns an integer used as the database
channel or pointer, referred to as db in many other
macro code database functions. See
opendb(3).
-
prevxrec(db)
-
loads the previous indexed record into database db.
Returns AOK (1) on success, ERROR (-1) on failure.
See
nextxrec(3).
-
putrec(n, db)
-
write the current record as logical record n to database db.
Returns AOK (1) on success, ERROR (-1) on failure.
See
putrec(3).
-
reccnt(db)
-
returns the current number of records in the database db.
-
recno(db)
-
returns the currently loaded record number from database db.
-
set_loadfail(n)
-
Sets the global cdb_loadfail variable to n, either 0 or 1.
When set to 1, a failed getxrec call will load the record
just past where the searched for record would have been, unless
the failure point is past the right edge of the btree index.
See also get_failrec and getirec.
-
unlock(n, db)
-
unlock record n of database db.
-
useidx(n, db)
-
makes the automatic index n from database db the "current"
index. The value of n is from 0 ... N-1, where N is the number
of indexes listed in the dbase.auto file.
Returns AOK (1) on success, ERROR (-1) on failure.
FIELD VERIFICATION FUNCTIONS
These functions are used to verify and return proper FirstBase
field strings.
In general, these functions accept a possibly formatted string se along
with any other data restrictions, like field size.
If se is verified, a FirstBase writable string is stored
in the variable named ret, and an AOK (1) is returned.
Otherwise a zero (0) is returned.
-
verify_ascii(ret, se, n)
-
verifies that each character of se is an ascii character in the range
decimal 32 (blank) to decimal 126 (tilde), or a decimal 10 (LF).
The CR character (decimal 13) is allowed, but it is stripped out.
The length of se is checked against the value n.
-
verify_date(ret, se)
-
verifies that se represents a proper FirstBase date string.
Most any kind of formatted or unformatted date representation is allowed.
-
verify_dollar(ret, se, n)
-
verifies that se represents a proper FirstBase dollar string.
The optional argument n can be used to validate field length as well.
Most any kind of formatted or unformatted dollar representation is allowed.
-
verify_float(ret, se, n)
-
verifies that se represents a proper FirstBase float string.
The optional argument n can be used to validate field length as well.
-
verify_numeric(ret, se, n)
-
verifies that se represents a proper FirstBase numeric string.
The optional argument n can be used to validate field length as well.
-
verify_pos_numeric(ret, se, n)
-
verifies that se represents a proper FirstBase positive
numeric string.
The optional argument n can be used to validate field length as well.
HTML FUNCTIONS
These functions generate and return
strings that are used to create HTML documents.
Many are used as open/close pairs of functions, while others
take arguments, surround them with HTML structure, and return
the entire string. So, these functions are typically used with
print or printf from the FirstBase tool
dbmacro(1).
-
HTML Structure
-
html_open(title, base_href, body_tag, excess_tag)
-
returns the string to begin an HTML document, using the string title
as the title of the document, base_href
as the BASE HREF of the document, and the optional body_tag argument
as additional components inside the HTML <BODY> tag.
The base_href argument is optional, but must be specified
(even as "") in order to pass in a body_tag argument.
The last optional argument, excess_tag, can be used to
pass in HTML tag elements that need to appear inside
the HTML <HEAD> tag, for example META or SCRIPT elements.
See html_meta() and html_script_open().
-
html_close()
-
returns the string to close an HTML document.
-
html_href(ref, se, target)
-
returns string to reference URL ref with the visual display
being shown as se. The optional argument target is the name
of a target frame, or the string "new" for a new window.
-
html_imgsrc(img, [align, hspace, border, alt])
-
returns string to reference image
with URL img. The other arguments are optional:
align can be one of top, middle, or bottom as string values;
hspace is a number that represents horizontal space; border
is a number representing outside border width; and alt is a string
set as the alternate text for the image (displayed when the pointer
is over the image or for text only browsers).
-
html_comment(se)
-
return a string that is se constructed as an HTML comment.
-
html_filter_lt(se)
-
return a string that is se, but all less than characters (<)
are replaced with the HTML equivalent of "<". This is sometimes needed
since the less than character is a special character in HTML.
-
HTML Format
-
html_blockquote_close()
-
string to close blockquote section.
-
html_blockquote_open()
-
string to open blockquote section.
-
html_br()
-
string to break and start a new line.
-
html_center(se)
-
string to center se/.
-
html_center_close()
-
string to close a centered section.
-
html_center_open()
-
string to open a centered section.
-
html_dd(se)
-
string to create a data definition of se.
Used with html_dl_open, html_dl_close and html_dt.
-
html_dl_close()
-
string to close a data definition list.
-
html_dl_open()
-
string to open a data definition list.
-
html_dt(se)
-
string to create a data term of se.
Used with html_dl_open, html_dl_close and html_dd.
-
html_h1(se)
-
string to create an H1 header of se.
-
html_h2(se)
-
string to create an H2 header of se.
-
html_h3(se)
-
string to create an H3 header of se.
-
html_h4(se)
-
string to create an H4 header of se.
-
html_h5(se)
-
string to create an H5 header of se.
-
html_h6(se)
-
string to create an H6 header of se.
-
html_h_close(n)
-
string to close a header of size n.
-
html_h_open(n)
-
string to open a header of size n, i.e. html_h_open(3) opens
an H3 header section.
-
html_hr(n)
-
string to produce a horizontal rule. The optional n can be used
to control the width. The default width is 4.
-
html_li(se)
-
string to create a list item se. Use after an html_ul_open
or html_ol_open.
-
html_link(se, ...)
-
string to create an HTML <LINK> tag used with stylesheets.
Each se argument is placed inside the tag, separated by a blank.
-
html_meta(se, ...)
-
string to create an HTML <META> tag.
Each se argument is placed inside the tag, separated by a blank.
-
html_ol_close()
-
string to close a numbered list.
-
html_ol_open(n)
-
string to open a numbered list using the optional argument n as
the starting value.
-
html_p_close()
-
string to close a paragraph. Actually, this is not needed right now, but
at some point in the future, paragraphs will be true HTML containers.
-
html_p_open()
-
string to open a paragraph.
-
html_pre_close()
-
string to close a pre-formatted section.
-
html_pre_open()
-
string to open a pre-formatted section.
-
html_script_close()
-
string to close a SCRIPT tag.
-
html_script_open(type)
-
string to create an HTML <SCRIPT> tag.
The type argument is quoted and placed inside the tag.
-
html_ul_close()
-
string to close an unnumbered list.
-
html_ul_open()
-
string to open an unnumbered list.
-
HTML Fonts
-
html_bold(se)
-
string that renders se as bold text.
-
html_bold_close()
-
string to close bold section.
-
html_bold_open()
-
string to open bold section.
-
html_em_close()
-
string to close emphasis section.
-
html_em_open()
-
string to open emphasis section.
-
html_font_close()
-
string to close the most recent font request.
-
html_font_color(color, typesize)
-
string to change the current font to the hex string color,
optionally adjusting the typesize.
Use html_font_close() to close.
-
html_font_open(typeface, typesize)
-
string to open font typeface using optional typesize n.
The optional argument typesize can be used to control the size,
and can be a relative number as well, for example -2.
-
html_fontsize_close()
-
string to close a font size.
-
html_fontsize_open(n)
-
string to open a font size bumped by n points, positive or negative.
-
html_italics(se)
-
string to render se in italics.
-
html_italics_close()
-
string to close italics section.
-
html_italics_open()
-
string to open italics section.
-
html_strong_close()
-
string to close strong section.
-
html_strong_open()
-
string to open strong section.
-
HTML Tables
-
html_table_open([border [, cellpadding [, directive ...]]])
-
string to open a table, using border value of border and
a cell padding of cellpadding.
Optionally, as many HTML directives
as desired can be listed. These complete directives, for example,
WIDTH=500 or CELLSPACING=0, will be listed inside the
TABLE tag.
-
html_table_close()
-
string to close a table.
-
html_table_headers(se, ...)
-
string representing a row of table headers with each se occupying one
column or cell.
-
html_row(se, ...)
-
string representing a row of table information with each se occupying
one column or cell. Special table formatting strings can be passed
as individual arguments to effect the next se. These special argument
strings are ALIGN= with LEFT, RIGHT or CENTER,
ROWSPAN= with a numeric value, WIDTH= with a numeric value,
and NOWRAP. For example, html_row("hotdogs", "align=right", 422)
will return a string representing this HTML table row with the number 422
right justified.
-
html_row_open(se, ...)
-
string representing the opening of a table row. Any of the optional se
arguments are assumed to be intact HTML row formatting commands
and are placed accordingly in the return string.
-
html_row_close()
-
string to close a table row.
-
html_cell_open(se, ...)
-
string representing the opening of a table cell. Any of the optional se
arguments are assumed to be intact HTML cell formatting commands
and are placed accordingly in the return string.
-
html_cell_close()
-
string to close a table cell.
-
HTML Forms
-
html_form_open(se, enctype)
-
emits string to open an HTML form using POST method and an action of
se.
If the enctype argument is the string multi
or multipart, then the generated HTML string will include
ENCTYPE=multipart/form-data inside the HTML <FORM> tag
to indicate a multipart CGI data transmission.
Multipart CGI transmissions are transparently processed by dbmacro.
Input variables that are not type FILE are directly available via
the name of the variable, in the standard macro manner.
However, FILE input variables will contain the name of a local temporary
file and the local temporary file will itself contain the contents of
the one multipart component referenced.
The location of the temporary file is controlled by the
FirstBase
setup(5) variable TEMPDIR. In addition, each
multipart transmission that dbmacro processes can control the
temporary file location itself by using an input variable named TEMPDIR
(usually a HIDDEN input variable). If such an input variable
exisits before the FILE input variable, then its contents
are used as the temporary directory used for multipart transmissions.
Another input variable that can be used to control multipart transmission
behavior is MAXSIZE. If the HTML input variable MAXSIZE exists before
the FILE input variable, then its value is used as
the maximum number of
of bytes that can be stored in the temporary file.
The temporary files generated by a multipart CGI transmission are
not deleted by dbmacro. Use rename to move them
(as long as they are on the same file system), or unlink
to delete them. Again, the macro script itself must clean up any
temporary files after a multipart CGI transmission.
-
html_form_close()
-
string to close an HTML form.
-
html_input(type, name, size, maxsize, value, cval)
-
string to create an HTML input field of type,
called name, that is size characters wide,
allowing a maximum of maxsize characters,
and an initial value of value.
Valid type strings are one of
text, number, password, checkbox, radio, submit, reset, file,
or hidden.
Only the first two arguments are required.
If type is file, make sure the html_form_open() uses
the multipart designator.
If type is a checkbox or a radio, then cval
can be set to the string CHECKED and that item will be
marked or selected.
When processed,
the special checkbox HTML forms input type is provided to
dbmacro as an array named the same name as the field name.
(The same applies to the use the keyword MULTIPLE in
an HTML SELECT statement, i.e. html_select_open()).
The subscripts or keys of this checkbox array are from
one to countkey(array).
In other words, dbmacro handles multiple occurrences of the same
variable passed in from an HTML form.
However, there is one caveat with these methods where the same
variable has multiple values as passed in from an HTML form:
If only one of many in the HTML checkbox or selection list is
selected, then
dbmacro will only see one occurrence of this HTML field name,
and the variable available at run time will not be an array, but will
be a simple variable like any other HTML input fields. In this case, the
countkey function will return a zero (0).
For example, this code prints all CGI variables coming
in (via an HTML form) as category:
max_i = countkey(category)
if (max_i == 0)
printf("%s\n", category)
else
for (i = 1; i <= max_i; i++)
printf("category[%d] = %s\n", i, category[i])
-
html_select(name, size, option, ...)
-
string to create an HTML selection list called name
and a window of size selections. The selection list
is made up of any number of passed in option arguments.
To force a particular option to be the default, pass a string argument
of SELECTED just before the selected option.
-
html_select_open(name, size [, directive ...])
-
string to open an HTML selection list called name
and a window of size selections. Optionally, as many HTML directives
as desired can be listed. These complete directives, for example,
WIDTH=500 or MULTIPLE, will be listed inside the
SELECT tag.
-
html_select_close()
-
string to close a selection list.
-
html_select_option(option, ...)
-
string representing options in a selection list. As many calls to
html_select_option can be done as needed, and each call can
list as many options as desired.
To force a particular option to be the default, pass a string argument
of SELECTED just before the selected option.
In addition, to generate HTML that displays one string, for example
Arizona, but returns a different string, for example, AZ,
a value= directive needs to be triggered by
prepending the string value= to the required value and
passing this as an argument. For example,
html_select_option("value=" + "AZ", "Arizona")
-
html_textarea(name, row, col, value)
-
string representing an HTML form text area of input.
The field name will be a text area row by col big,
with an optional value embedded.
MATH FUNCTIONS
-
abs(e)
-
absolute value of e.
-
acos(e)
-
arc cosine of e.
-
asin(e)
-
arc sin of e.
-
atan(e)
-
arc tangent of e.
-
atan2(e1,e2)
-
arc tangent of e1/e2.
-
atof(se)
-
convert string to number. same as ston(se).
-
ceil(e)
-
smallest integer not less than e.
-
cos(e)
-
cosine of e.
-
exp(e)
-
exponential function of e
-
floor(e)
-
largest integer not greater than e
-
hypot(e1,e2)
-
sqrt(e1*e1+e2*e2)
-
log(e)
-
natural logarithm of e.
-
max(e1,...)
-
maximum value of the e's.
-
min(e1,...)
-
minimum value of the e's.
-
pow(e1, e2)
-
e1 raised to the e2 power.
-
random()
-
return a random(3) number. Use srandom() to seed.
-
round(e, n)
-
round e to n places after the decimal.
-
sin(e)
-
sin of e.
-
srandom(e)
-
seed the random number generator using value e.
-
sqrt(e)
-
square root of e.
-
ston(e)
-
convert string to number. same as atof(se).
-
tan(e)
-
tangent of e.
-
trunc(e, n)
-
truncate e at n places after the decimal.
STRING FUNCTIONS
-
countlines(se, sep)
-
counts the number of lines (or fields separated by a sep marker)
within the string se.
The sep argument is optional and defaults to the NEWLINE separator.
(Nested choice types within FirstBase use a field separator of "|").
-
fmt(se,e)
-
convert a number to a string using sprintf(3). For example,
fmt("%5.3f", 16.1) returns the string 16.100.
-
formfield(e, type, size)
-
format a string using one of the firstbase data types, returns the formatted
string in a field size characters wide. Types to use
are "d" for date, "$" for dollar, or "a" for alpha.
For example, formfield(1234.56, "$", 10) yields the
string 1,234.56 in a field 10 characters wide.
Also, formfield("072691", "d", 8) produces 07/26/91.
Fixed width text fields can be produced using type alpha.
Note that print() formats these date and dollar
fields automatically.
-
gettoken(str, pos, buf, skip)
-
similar to getword() except that strings returned
are exact substrings known as tokens.
A token is either a run of characters and/or digits,
or a single other character, like a space, a parenthesis, etc.
The single character string skip is used to allow embedded
underscores, for example "_".
This function returns a new position value to be used in the next call
to gettoken() so as to get the next token, or a 0 (zero)
if there are no more tokens in str.
-
getword(str, pos, buf)
-
get a white space separated string from str beginning at
position pos and store this string in buf.
Returns a new position value to be used in the next call
to getword() so as to get the next word, or a 0 (zero)
if there are no more words in str.
-
index(se, sep)
-
returns the character position (one based) of the separator located in the
string se.
-
length(se)
-
length of string expression.
-
lower(se)
-
string se in all lower case letters.
-
rindex(se, sep)
-
returns the character position (one based) of the separator located in the
string se as determined from the right side of the string.
-
rmlead(se)
-
remove the leading blanks of se.
-
rmlinefeed(se)
-
truncates se at the first LINEFEED or NEWLINE character.
-
rmnewline(se)
-
truncates se at the first NEWLINE or LINEFEED character.
-
rmunderscore(se)
-
changes all underscore characters (_) in se to blanks.
-
sprintf(fmt,arg1,...)
-
implements the standard UNIX and C printf mechanism without printing
the results. Instead, the results are passed back, and can be captured using
the assignment mechanism. In other words, the result of the sprintf
function is a string.
For example, newstring = sprintf("Hi %d", number) would do as expected.
The result string must be less than 5120 characters. Also see printf.
-
subline(line, se, n, sep)
-
places a subline into line from se,
a large field or string containing newlines
or fields of data separated by a sep.
This function can be used to tear apart comma separated values, or a
long string line by line.
Note that sep is an optional argument, and defaults to "n"
(NEWLINE) if not specified.
The return value from subline is a status indicator. A one (1)
indicates success, a zero (0) means failure. Empty fields or lines are
considered to be proper elements.
The nth subline component from se is placed into line.
For example, subline(oneline, $longfield, 4) places the fourth
line from field longfield into the variable oneline.
As another example, the second component of the nested choice field
is placed into the variable choice by
subline(choice, $nested_choice, 2, "|").
A negative value for n counts fields or lines backwards from the end of
se. Also see the macro function countlines.
-
substr(se, pos, length)
-
returns the sub string within se starting at pos for length
characters. A negative pos marks a position at the end of the string.
As examples, substr(s, 1, 5) and substr(s, -5, 5) each
return strings
five characters long (assuming s is at least five characters).
One returns the first 5 characters of the string,
the other returns the last 5 characters of the string.
-
trim(se)
-
remove the trailing blanks of se.
-
upper(se)
-
string se in all upper case letters.
DATE FUNCTIONS
In the following functions, the argument s stands for seconds,
and represents an encoding of a time/date in seconds since January 1, 1970.
The functions that use an s below need to be passed an argument
that is already encoded. Some of the other functions return
a date encoded as a seconds argument.
Another type used in these functions is d, which represents the
FirstBase internal date type.
These are simple strings of the form MMDDYY.
-
cdbdate(s)
-
returns a FirstBase date representation (MMDDYY) of the seconds s.
-
cdbdts(d)
-
returns the seconds encoding of FirstBase date d.
-
date(s)
-
covert the time in seconds to a standard, 24 character, UNIX date of the
form Fri Jul 26 13:23:45 1991. Use substr() to tear this apart.
-
day(s)
-
returns the day of the month: 1 to 31.
-
dts(m,d,y)
-
returns m/d/y encoded in seconds.
-
hour(s)
-
returns number of hours since midnight: 0 to 23.
-
minute(s)
-
returns number of minutes since last full hour: 0 to 59.
-
month(s)
-
return the month: 1 (January) to 12 (December).
-
ndays(d1, d2)
-
return number of days between two FirstBase dates.
-
newdate(d, n)
-
return the FirstBase date d bumped by n days.
Negative days are allowed.
-
now()
-
return the current time encoded in seconds.
-
second(s)
-
returns number of minutes since last full minute: 0 to 59.
-
tts(h,m,s)
-
return h:m:s encoded in seconds since midnight
-
year(s)
-
return the year. Valid years start with 1970.
SCREEN FUNCTIONS
The following screen functions are allowed only when a macro is used from
the database editor
dbvedit(1). In other words, these functions
have no effect on the tool
dbmacro(1).
-
bell()
-
produce bell or visible bell according to the termcap entry
-
clear()
-
clear the entire screen.
-
clrtobot()
-
clear from the cursor to the bottom of the screen.
-
clrtoeol()
-
clear from the cursor to the end of the line.
-
editfield(f1,...)
-
edit one or more fields from the current page, as defined by
the visual editor,
dbvedit(1), and its visual dictionary file.
Note that the arguments do not use a $ -- field names or numbers
are used.
Returns a status value constant of PREV, NEXT, AOK, DEFAULT, or ABORT.
See the section below on editing topics.
-
error(se)
-
prints the string se as a standard FirstBase simple error message, and
requires a single key to be entered before execution is continued.
-
footer()
-
redraw the standard FirstBase footer line.
-
header()
-
redraw the standard FirstBase header line.
-
input(row, col, max, min, fmt, addr)
-
provides access to the standard FirstBase input mechanism, complete
with the "input dots" and intraline editing.
Returns a status value constant of PREV, NEXT, AOK, or ABORT.
See the section on editing topics below for more details.
-
move(row, col)
-
move the cursor to row and col. <1,1> is the upper left corner,
and <24,80> the lower right corner.
-
pause()
-
pauses macro execution with a FirstBase simple error message
requiring a single keystroke to continue. Sometimes helpful for debugging a
macro. See also error().
-
redraw()
-
redraw the current page of fields and text, as known and displayed by the
database editor
dbvedit(1).
-
refresh()
-
causes the screen manager to display all text in the screen buffer. In other
words, cursor motion and screen activity are not displayed until a refresh()
is done. However, input, error, and redraw type functions do implicit
refreshes.
-
rinput(max, min, fmt, addr)
-
same as input(), except row and col are defined as the current ROW and COL
being used by the invoking field. An additional runtime macro variable, LEN,
will contain the length of the current field.
-
status(se)
-
redraw the status area (upper right hand corner) with the string se.
STREAM INPUT/OUTPUT FUNCTIONS
The stream functions allow standard UNIX handling of files.
The arguments with these functions closely matches the arguments
of the corresponding functions in standard UNIX manual sections (2) and (3).
Note: to intersperse combinations of fgets and fread,
fseek must be used in between. The same rule applys for fputs and
fwrite.
-
access(path, mode)
-
returns a -1 if the path
cannot be found or if any of the access modes would
not be granted, otherwise a 0 value is returned. The mode is
an INCLUSIVE OR of the bits (test for read, write and execute/search
permissions). A mode of 0 tests directories leading to the file, and if the
file exists.
-
fclose(stream)
-
close the associated stream.
-
fflush(stream)
-
flush any output in the stream.
-
fgets(s, n, stream)
-
reads a maximum of n characters, or until a NEWLINE, from stream
placing the results in s. Returns 0 on EOF, 1 on successful reads.
-
fopen(filename, type)
-
opens a file named by filename and associates a stream with it.
If the open succeeds, fopen() returns an integer that is used as
the file stream. type is a character string from the following:
-
r
-
open for reading
-
w
-
truncate or create for writing
-
a+
-
append; open or create for update at EOF
-
r+
-
open for updating (reading and writing)
-
fprintf(stream, fmt, arg1, ...)
-
uses the standard printf mechanism,
but writes output to stream.
-
fputs(s, stream)
-
writes s to stream
-
fread(s, size, stream)
-
attempts to read size characters from stream and store in s.
The actual number of characters read is returned, or a 0 upon EOF.
-
fseek(stream, offset, ptrname)
-
set the position of the stream pointer for the next input or output operation.
-
fwrite(s, size, stream)
-
attempts to write size characters to stream from s.
The actual number of characters written is returned.
-
link(oldpath, newpath)
-
creates a hard link from oldpath to newpath.
Both files must be on the same file system.
Returns 0 for success, -1 for failure.
-
mktemp(template)
-
creates a unique file name, typically in a temporary file system.
The string in template should contain a file name with six trailing Xs
mktemp will replace the Xs with a letter and the current process ID.
-
pclose(stream)
-
close the associated stream opened with popen.
-
popen(pname, type)
-
opens a process named by pname and associates a standard file
stream with it.
If the popen succeeds, it returns an integer that is used as
the file stream, otherwise an ERROR (-1) is returned.
type is either an r
to read from process pname, or a
w to write to process pname.
-
rename(oldpath, newpath)
-
renames a file from oldpath to newpath.
Both files must be on the same file system.
Returns 0 for success, -1 for failure.
-
symlink(frompath, topath)
-
creates a symbolic link from frompath to topath.
Returns 0 for success, -1 for failure.
-
unlink(path)
-
removes the directory entry named by path. Returns 0 for success,
-1 for failure.
MISCELLANEOUS FUNCTIONS
-
cgi_read()
-
provides a hook to the CGI initialization routines when
macro code is executed using direct methods.
As
dbmacro(1) points out, if invoked as dbmacro.cgi,
CGI data is automatically converted to variables available
in the macro code at runtime and
dbmacro(1) also
emits the standard CGI script lines "Content-type: text/htmlnn".
However, if
dbmacro(1) is called from a shell script,
or is used as the command interpreter itself via
something like
#!/usr/local/firstbase/bin/dbmacro
as the first line of the CGI file, then the cgi_read mechanism
can be used to parse standard CGI parameters and values.
Note that the script will have to print the HTML Content-type directive
itself if needed.
-
chdir(se)
-
change directory to se and return the status of the chdir(2)
call, which is ERROR (-1) on failure and zero (0) on success.
-
countkey(array)
-
return the count of the keys or subscripts of array.
See also key.
-
findkey(key, s, array)
-
locate the element of array that has the value of s and place
its lookup or subscript value into key. Returns either AOK or ERROR.
-
fork()
-
standard fork(2) UNIX function. Returns 0 to the child and the childs
process ID to the parent.
-
getenv(se)
-
standard getenv(2) call, returns value of UNIX environment variable
se.
-
gets(s)
-
reads a single line from standard input and
places the results in s. Returns 0 on EOF, 1 on successful reads.
Used for
dbmacro(1) only.
-
in(e,e1,e2...)
-
returns a 1 if e is in the set of expressions e1 ... eN, else a 0.
-
key(val, array)
-
iterates through each of the keys or subscripts of array
on successive calls and returns one key each time. key places the
subscript value into val. A value of one (1) is returned on success and
zero (0) on errors or when key has iterated through all
subscripts. Iteration can then start again.
See also countkey.
-
load(se)
-
Load and parse the macro_file se.
This runtime load mechanism can be used to load sets of library style
macro functions, or load different macro code on demand.
Again, all variables in all files and functions, loaded or inline, are
global unless specifically declared using the local directive.
-
pattern(e, pat)
-
returns a 1 if e matches the pattern pat, else a 0.
Full regular expression pattern matching is done.
-
pattern_comp(pat)
-
compile the pattern pat. Use with pattern_exec().
-
pattern_eo(n)
-
returns the end character offset of the nth
remembered substring matched in pattern() or pattern_exec().
Note: return value is adjusted for one based string array.
-
pattern_exec(s)
-
match the string s against the pattern previously compiled
via pattern_comp().
-
pattern_icase(n)
-
Default pattern matching is case sensitive via pattern() and pattern_exec().
Using an n of 1 causes case to be ignored for these pattern matches,
and a 0 resets pattern matching to being case sensitive.
-
pattern_so(n, r)
-
returns the starting character offset of the nth
remembered substring matched in pattern() or pattern_exec().
Note: return value is adjusted for one based string array.
-
pattern_substr(str, n)
-
returns the nth matched remembered substring of str
after a call to pattern() or pattern_exec().
-
print(e1,...)
-
prints each of the expressions, formatting those that are of
type FirstBase dollar and FirstBase date. For screen macros,
use move() to position the cursor first.
-
printf(fmt,arg1,...)
-
implements the standard UNIX and C printf mechanism. The result string
must be less than 5120 characters. The result is printed. For screen macros,
use move() to position the cursor first. Also see sprintf.
-
putenv(se)
-
standard putenv(2) call, sets value for UNIX environment variable
se.
-
puts(s)
-
print a single line to standard output.
places the results in s. Returns AOK or ERROR.
Used for
dbmacro(1) only.
-
reverse(e1,...)
-
exactly like print() except characters are printed in reverse video
if possible.
-
rmkey(key, array)
-
removes element key from array.
-
sleep(n)
-
sleep n seconds.
-
standout(e1,...)
-
exactly like print() except characters are printed in standout video
if possible.
-
system(se)
-
use the UNIX system call to execute the command se. Returns the exit
status of the sub shell.
-
terminate(e)
-
terminates the process. Used only for exiting
from a process created via fork(). Terminates (exits) with status
e. Again, use exit or return for normal macro code, and
terminate only when you want the process to die completely.
-
usrlog(s)
-
writes error message s to the USRLOG file in the FIRSTBASEHOME
directory. Also see
setup(5).
SECURE FUNCTIONS
-
chgrp(e)
-
change the group for a record to the numeric group e.
-
chmod(e)
-
change the mode for a record to the numeric mode e.
-
chown(se)
-
change the owner for a record to the symbolic name use name specified by
se.
-
group()
-
return the group number for a record.
-
mode()
-
return the (numeric) mode for a record.
-
owner()
-
return the symbolic owner name for a record.
COMPLEX DEFAULTS
Complex defaults, conditional defaults, and assignments to
fields within the record based on large sets of criteria can all
be readily done using a macro file.
A simple assignment to a field will store the value into the field.
Later, when the record is written, this value will be written
to the disk copy of the record. For example, the following stores todays date
into a field named EntryDate:
$EntryDate = cdbdate(now())
redraw()
Other kinds of defaults can be done using conditional statements.
For example, the following only stores the date field named LastCont
only if a date
has already been entered into the date field NextCont.
if ($LastCont != "")
$NextCont = newdate($LastCont, 14)
else
$NextCont = ""
This example will set the field NextCont to two weeks past the
current value of LastCont at macro execution time (field edit time).
EDITING TOPICS
One of the features of FirstBase macro fields is the ability to
interactively edit fields from the current database within the flow of a
macro file. This interaction occurs when using the database editor,
dbvedit(1), or the visual database emitter,
dbvemit(1).
These are trigger fields, or conditional fields.
When a field is edited within a FirstBase macro, it is referred to as a
trigger field. But, the place the macro file is attached is called
the trigger point. Both trigger points and trigger fields can be edited
within a macro, but there is a distinction.
Trigger fields are edited using a very simple function, editfield().
Editfield accepts a list of comma separated fields, but the arguments
do not use the "$" to evaluate the fields. For example,
editfield(Address) would edit a field named Address
in the current FirstBase database.
Here are a few notes on trigger fields and trigger points.
First, fields that are listed in the outside visual
dictionary as "display only" can still be edited, and this is probably
preferred since the idea is to make the trigger fields editable from
the macro file only.
Second, editing the trigger point using
editfield() is disallowed (as is any cycle where this occurs).
In this case, input() must be used. See below.
And, third, when using editfield() or input(),
the return of a proper
status (signal) to the FirstBase database editor will produce better
field-to-field cursor motion during the editor's Field Level movements.
Note: in the following sections, the macro function rinput() can be
used whenever the related function input() is referenced.
When editing a field, sometimes the user elects to go by the field
using FirstBase keystrokes that move the cursor to the
NEXT or PREV fields. The macro functions
editfield() and input() both return a status value that can be used
to detect these situations. The macro constants PREV, NEXT, AOK, ABORT, DEFAULT
and END represent the possible signals returned.
Equivalent macro constants are
FB_PREV, FB_NEXT, FB_AOK, FB_ABORT, FB_DEFAULT
and FB_END.
A special note on the END token: Since END can be used
to define a sections of code that will only be executed one
time at the end of all database processing, some uses of END
will cause a syntax error. For example,
st = END
will not parse, however each of the next two will parse just fine:
st = END;
st = FB_END
In general, passing back the signal returned by editfield() or
input() will produce the proper effect. For example, this macro file
code fragment will produce normal editor behavior:
st = editfield(Address1, Address2, City)
return(st)
Note that when given more than one argument, editfield() will properly
handle the NEXT/PREV signals between these fields. If you need to use
multiple calls to editfield() within one macro-file, you will either
have to accept the editor behavior, or provide for the PREV/NEXT signals
in the code for the macro file. (See the examples below).
Another variable that helps in determining editor behavior is the macro
variable ST_UP. This variable is set to one when a macro file is invoked
by moving into the field UPWARD via a PREV signal.
Otherwise, ST_UP will be zero.
To allow generalized input, or input into a trigger point, the macro
function input() is provided. The input() function has many
arguments: row, col, max, min,
format, and address.
Additionally, an optional argument, extra_status, can appear last.
Input is taken
from the screen at coordinates row, col.
A maximum of max characters
will be allowed, with a required input of min characters.
(To make a forced entry, set min greater than zero).
The format is one of "aAd$fnNU", the core set of standard
internal FirstBase data types.
The next argument, address is
the macro variable where the input() information will be stored.
Note: address cannot be a FirstBase field -- use a temporary storage area
then assign back to a field if needed. Additionally, if address
is assigned a value BEFORE entering the input() function,
its contents are used with the FirstBase
intraline editing functions, if EDITINPUT is set via
setup(5).
As mentioned above, input() also returns a status. However,
its status is more generalized than editfield(). For example,
since input() detects signals and gathers keyboard input, the characters
gathered are stored in address only when an AOK status is
returned by input().
A specialized version of input() named rinput() will use the
row and column
of the current trigger point in calling input().
All other arguments remain the same.
For example, to simulate
dbvedit(1) behavior,
using the rinput() mechanism, on a
trigger point field, (or a field that has a defined macro that edits
the same field itself, recursively), the following
macro file code could be used:
val = $Field3
st = rinput(LEN, 0, "$", val, e_st)
if (st == AOK){
$Field3 = val
st = e_st
}
return(st)
The internal macro variable LEN will be set at run time to the length
of the current field, the field size.
This code also provides an example of the optional status argument
to input() and rinput(), here called e_st.
If passed this argument, these macro functions will store any excess status
signals in this variable.
An excess status signal is generated only when
changes are made to the editable area and a NEXT or PREV keystroke is
used to move the cursor. In this case, a final variable passed into
input() and rinput() (e_st) will be set to this
excess status, NEXT or PREV. The actual return code from the
function is AOK. The above code catches these excess signals properly.
Although it is much easier to use a trigger point and editfield()
with multiple arguments, it is possible to write macro code that will
edit the trigger point using rinput(), edit additional fields
using editfield(), and still provide normal
dbvedit(1) behavior.
The following code, again, unnecessary if you use a trigger point and
distinct trigger fields, does demonstrate all of the above nuances
to trigger point editing and signal behavior.
#
# loop to provide NEXT/PREV behavior between **these** fields
#
for (st = NEXT; ; ){
if (ST_UP == 0 || $Field3 == ""){ # if not here via PREV
val = $Field3
st = rinput(LEN, 0, "a", val, e_st) # edit the trigger point
if (st == AOK){
$Field3 = val # make assignment if AOK
st = e_st
}
redraw() # redraw rinput() always
}
ST_UP = 0
if (st != NEXT)
break
if ($Field3 != ""){ # maybe edit Field4
st = editfield(Field4)
if (st == PREV)
continue
st = NEXT
}
break
}
return(st)
Note that an equivalent piece of code using a trigger point field
different than the trigger fields is simply:
return(editfield(Field3, Field4))
With this smaller piece of code, the macro cannot be tied to either
Field3 nor Field4.
MACRO CODE AND DATABASE EDITING
This section describes how to use
macro(5) code
to extend the standard behavior of the FirstBase database editor.
Non licensed versions of dbmacro are not capable of
database interaction.
To be used within
dbvedit(1), the macro file is either
(a) tied to the database via the database dictionary or defaults file
(see
dbdbas(1) and
defaults(5)) or (b) named one of the special
macro file names that indicate macro execution at record entry,
record exit, of other dbvedit record editing points.
When the macro file is tied to an actual field, it will be executed
instead of the normal Field Level editing when the cursor is moved "onto"
that field. This macro-enabled field must be "editable"
according to the view dictionary (the vdict file).
The macro
file itself can modify other fields as long as they are listed on the same page
in the view dictionary. Furthermore, macro files can edit fields
that the view dictionary defines as "display only".
To provide for macro execution at record entry and record exit points,
special file names are used to store the macro code. The base file name
for these files is the name of the database. The additional extensions
are m_begin, m_end and m_endwrite.
For example, if the database is named dbase, then the begin
macro file name is dbase.m_begin, and the end macro
file name is dbase.m_end.
The begin record macro
file will be processed whenever a record is opened
for editing, and it will always allow record entry.
The end record macro file will be processed whenever a record
is exited, whether it will be written or not.
This end record macro file can deny exit
by controlling the value or status it returns. If this end record macro
returns a status other than END, for example ERROR, then
the record will not be written, and the user is returned to record level
on the same record (to correct the situation causing the failure).
The endwrite record macro
file will be processed after a record
is written to the database, meaning all automatic increments and defaults
will have been resolved. Note: changes made to the record here will not be
written to the database -- this macro
file is only for post-write processing.
Global variables inside each of these macro files are shared
so that state information or flags can be used during an editing session.
During the execution of each of these record macros,
an internally defined macro variable CREATE_RECORD will be set to
one (1) or zero (0) according to whether the record is a new (add) record
or not. Additionally, during both end record macros, an additional
internally defined macro variable WRITE_RECORD will be set to
one (1) or zero (0) depending on whether the record has been modified
and is about to be (or was) written to the database file. Still another
variable END_KEYSTROKE will be (1) or (0) during the end
or endwrite macros depending on whether the END keystroke was used
or whether the action was due to a w, WSIGNAL, or custom command.
There are two additional execution points within dbvedit where a
macro can be used to provide extensible editor behavior.
These two points are the command level macro
and the field level macro, each denoted by special
file name extension. Again, the base name is the name of the database, with
the extension being m_com and m_fld, respectively.
Each of these macro execution points can be used to
repaint the screen. Additionally, the field macro can make changes to
the database record and potentially provide trigger fields or sections.
SEE ALSO
dbedit(1),
dbdbas(1),
dbmacro(1),
fbtstmac(8)
FirstBase User's Guide and Reference Manual
URL: http://www.firstbasesoftware.com/man/man5/macro.htm
Last modified: 26 January 2000
Copyright © by FirstBase Software.
[
Index of Contents] [
FirstBase RDBMS Overview]