 |
Mscript Programmers Guide
- Introduction
- How it Works
- Your First Program
- Passing Arguments
- Expressions
- Controlling Program Flow
- Variables, Numbers, and Strings
- Meta Commands
- Functions
- User Defined Functions
- String Functions
- I/O Functions
- Directory Functions
- DBM Functions
- MySQL Functions
- Math Functions
- Bit Functions
- Time and Date Functions
- CGI Functions
- GIF Functions
- Miscellaneous Functions
In 1994 I was experimenting with creating my own interpreted programming
languages when I developed "M-Script". This was a simple yet effective
language, truly interpreted. It did not allow for complex expressions
or tests, but it was fast as far as interpreted languages go. It was a
general purpose language that was sophisticated enough that I wrote a
custom UNIX shell in M-Script and launched a successful ISP based on
it (Islandnet.com).
Recently I began the task of recreating M-Script from scratch, with the
goal of making it into a CGI programming language. CGI stands for
"Common Gateway Interface" and is the means by which computer programs
manipulate data gathered from web page submissions. The result is
M-Script II, a much more sophisticated language that runs even faster
than its precursor.
Using M-Script II, you can create your own CGI programs to process
HTML forms, build a better shopping cart system, calculate mortgage
and loan payments, make a custom hit counter, or practically anything
else you can think of.
An M-Script II program is simply a list of expressions in an ASCII
text file. The M-Script II interpreter is a program that reads and
executes the expressions. You write the programs, the interpreter
is installed on the server by your ISP.
Unlike many interpreted languages, the M-Script II interpreter reads
in the entire program file at once, converting keywords into numbers
and pre-parsing all the expressions. This results in a tremendous
speed up, especially if there are many loops (sections that repeat
one or more times) in your program.
To invoke the interpreter and run your program, you use an URL like
this:
/cgi-bin/ms2/LOGIN/PROGRAM
Replace the word LOGIN with your account name. The interpreter will
look up the home directory for that account and use that to locate the
program file. It will also restrict your program so that it cannot
manipulate files above that point.
Replace the word PROGRAM with the name of your MS2 program. If your
program file is named "demo.ms2" (All M-Script II programs must end
with a lower case ".ms2" extension) then you would replace PROGRAM in
the above example with "demo". Note that you do not specify the file
extension - it is assumed.
There are various ways you can cause an M-Script II program to be executed.
The first way is to simply type the URL into your browser like any other
URL. You can also use an URL like this as a clickable link so that it executes
whenever a user selects a link or button:
http://www.islandnet.com/cgi-bin/ms2/LOGIN/PROGRAM
If your program depends on form input, then you would use something like this
on your form page:
<form method=post action="/cgi-bin/ms2/LOGIN/PROGRAM">
If your program should be run automatically every time a page is loaded, you
can use an exec tag like this:
<!--#exec cgi="/cgi-bin/ms2/LOGIN/PROGRAM" -->
You can also invoke a CGI via an image tag, like this:
<img src="/cgi-bin/ms2/LOGIN/PROGRAM">
Note that if you use this method, your program must output data
using the "image/gif" mime type (see the mimetype() function).
All .ms2 files (the files you create) must be located within an "ms2"
subdirectory off of your home directory. If you specified "demo" in
the URL, then the interpreter will look for the file "ms2/demo.ms2" in
your account.
If the interpreter does not find the specified program in your account,
it will then look in a special public directory. This allows your ISP
to set up public CGI's that any customer can use. If you write a CGI
that you think may be useful to others, ask your ISP to put a copy in
the public MS2 directory.
Traditionally the first program anyone learns to write in a new
programming language is a simple one that displays "Hello world". This
simple M-Script II program does exactly that:
; hello.ms2 by Mark Morley
print( "Hello world" )
The first line is a comment, since it starts with a semicolon. Any
blank lines or lines that start with a semicolon are ignored. It is a
good idea to use blank lines and comments throughout your program to
make it easier to read, although they are not required.
The one and only statement in the example simply prints the message
"Hello world". If we were to run this program, the user would see a
simple web page with nothing else except "Hello world" printed on it.
If we wanted it to appear in large letters, we could change that line
to:
print( "<h1>Hello world</h1>" )
You can pass values (arguments) into a program in several ways. The
most obvious way would be via a form. Your script can extract form
values using the form() function.
Sometimes you want to pass arguments into a program without requiring
an actual form. One way is to specify form variables and values right
in the URL like this:
/cgi-bin/ms2/LOGIN/PROGRAM?var1=val1&var2=val2
Note that a single question mark separates the program name and the
list of form variables. Each form variable is followed by an equal
sign and the value. A single ampersand symbol separates each form
variable.
Note: There can be no spaces in an URL. Spaces and tabs and other
characters (including question marks and ampersands that are meant to
be part of a value) must be replaced with a percent sign and a two-digit
hexidecimal ASCII code. Some common codes are:
%20 Space
%09 Tab
%25 Percent Sign
%26 Ampersand
%3F Question Mark
Any program that expects form input can be called in this manner (it has
no way of knowing if there was really a form involved or not), since your
program must also use the form() function to extract these values. It's a
handy way to test certain programs without filling in a new form each time.
One other way to pass arguments to a script is like this:
/cgi-bin/ms2/LOGIN/PROGRAM/VAL1/VAL2/VAL3
You can then use the varget() function to access the "arg" array. The
first element in the array will always be the login name. The second
element is the name of the script. The third element will be the first
parameter passed (VAL1 in the example above), and so on. A special
numeric variable called "numargs" specifies how many arg array elements
there are.
The "hello world" example consisted of only one "expression". An
expression is one or more literal values, variables, functions, and
operators, optionally grouped together with parenthesis:
- 10.6
- Literal number. Numbers are made up of '+', '-', '.', and the
digits '0' through '9'.
- "Mark"
- Literal string. Strings are any characters enclosed within a pair
of double quotes. To embed a double quote within a string, escape it
with a single backslash. For example,
print( "He said, \"Hello!\"" )
The following special character pairs have special meaning within
strings: \r is a carriage return, \n is a newline,
and \t is a tab.
- varname
- A variable. Variable names are made up of the letters 'a' through
'z', the digits '0' through '9', and the underscore. The first
character must always be a letter. Variable names ay be virtually
any length.
- function()
- A function. Function names are made up of the letters 'a' through
'z', the digits '0' through '9', and the underscore. The first
character must be a letter. A function must always be followed by a
pair of parenthesis, even if there are no arguments being passed to it.
If there are arguments to a function they must appear within the
parenthesis, separated by commas. Function names may be virtually any
length.
Operators usually appear between two values and serve to combine them
in some way or perform some sort of test. Operators include:
- +
- Plus. If both values on either side of this operator are numeric,
then this operator adds them together. If one or both of the values
are strings, then the result is a concatenation of the strings. For
example, 5 + 2 is the number 7, while
"5" + "2" is the string "52".
- -
- Minus. Applies to numeric values only. For example,
5 - 2 is the number 3.
- *
- Multiply. Applies to numeric values only. For example,
2 * 6 is the number 12.
- /
- Divide. Applies to numeric values only. For example,
10 / 3 is 3.33333
- //
- Integer divide. Applies to numeric values only. Works just like
the normal divide operator, except that any fractional part of the
result is ignored. For example, 10 // 3 is the
number 3.
- %
- Modulo. Applies to numeric values only. Returns the remainder of
an integer division. For example, 10 % 3 Is the
number 1.
- =
- Assigns a value to a variable. For example,
x = 5 + 10 assigns the number 15 to the
variable named "x", and name = "Mark" assigns the
string "Mark" to the variable named "name".
- ==
- Equal. This test is true if the two values are the same. Case is
significant when comparing strings.
- !=
- Not equal. This test is true if the two values are not the same.
Case is significant when comparing strings.
- <<
- Begins with. Applies to strings only. This test is true if the
first string begins with the second string. Case is significant.
For example, "This is a test" begins with "This is".
- >>
- Ends with. Applies to strings only. This test is true if the
first string ends with the second string. Case is significant. For
example, "This is a test" ends with "a test".
- <
- Less than. This test is true if the first value is less than the
second one. Case is significant when comparing strings.
- <=
- Less than or equal to. This test is true if the first value is
less than or equal to the second one. Case is significant when
comparing strings.
- >
- Greater than. This test is true if the first value is greater than
the second one. Case is significant when comparing strings.
- >=
- Greater than or equal to. This test is true if the first value is
greater than or equal to the second one. Case is significant when
comparing strings.
- *=
- Wildcard match. Applies to strings only. This test is true if the
first string matches the pattern in the second string. The second
string may contain the wildcards '*' (matches zero or more characters)
or '?' (matches a single character). Useful for testing file names.
For example, "myfile.db" matches "*.db"
- -=
- Keyword match. Applies to strings only. This test is true if the
first string matches the pattern in the second string. The second
string contains one or more words separated by commas, and each word
may contain a dash to indicate minimum abbreviation length. For
example, "quit" matches "q-uit,ex-it", as does "q", "qu", "qui", "ex",
"exi", and "exit".
- ~=
- Regexp match. Applies to strings only. This test is true if the
first string matches the regular expression in the second string. Some
sample regular expressions include:
^Hello Matches any string that begins with "Hello"
test$ Matches any string that ends with "test"
^Bob$ Matches the string "Bob" only
. Matches any single character string
[a-z] Matches "a", "b", "c", through to "z" only
[a-z]* Matches "" or any string of lower case letters
[a-c,X-Z] Matches "a", "b", "c", "X", "Y", or "Z" only
[A,m,t] Matches "A", "m", or "t" only
[a-z]. Matches any two character string that begins with a lower case letter
- $
- Contains. Applies to strings only. True if the first string
contains the second string. Case is significant. For example,
"This is a test" contains "is a".
- and
- This test is true if both expressions on either side of it are
true. You may also use &&, which means the same thing.
- or
- This test is true if one or both expressions on either side of
it are true. You may also use ||, which means the same thing.
- not
- This test toggles the result of the expression to the right of
it. You may also use !, which means the same thing.
NOTE: It is possible to spread a single expression
over multiple lines. If the last character on a line is a backslash, then
the following line of code is assumed to be part of the same expression. This
is useful if you have long, complex test conditions for example. This does not
apply to comments, nor can you insert a comment line in the middle of a
multi-line expression. The maximum size of a single line of code (even if
it's broken up across multiple lines) is 8Kbytes.
Normally a program is executed line by line from beginning to end.
This is not always desirable however. Flow control constructs can
alter the flow of the program, or cause a section of the program to
repeat, etc. Flow control constructs can be nested within other flow
control constructs to virtually any depth.
All of the flow control constructs depend on the "trueness" or
"falseness" of an expression. Any expression can be used in a flow
control test because every expression returns a value. If the net
result of an expression is 0, then the expression is false. If the net
result is a non-zero number or any string at all, then it is true.
Flow control constructs include:
if expression
one or more expressions
elif expression
one or more expressions
else
one or more expressions
endif
If/elif/else/endif allows you to conditionally execute blocks of code.
The if and endif statements are required, while the elif and else
statements are optional. You can have as many elif statements as you
need.
while expression
one or more expressions
endwhile
While/endwhile will repeat a section of code as long as the test expression
is true. The code within the loop may be executed zero or more
times.
loop
one or more expressions
until expression
Similar to the while construct, the loop/until construct repeats a
section of code. The difference is that the code is always executed
at least once, and it repeats as long as the test expression is
false.
break
The break statement will terminate the inner-most while/endwhile or loop/until
construct. This allows you to "break out" of a loop if necessary.
return
The return statement forces the current function to return (ie: exit). If
the current function is the main one, then the program terminates. When used
to exit from a user defined function, you can optionally specify a value
to be returned, like this: return x * y
|
Variables, Numbers, and Strings
|
Variables have both a name and a value. The name may be virtually any
length and may consist of the letters 'a' through 'z', the digits '0'
through '9', and the underscore character. The first character of a
variable name must always be a letter. Variable names are case sensitive,
that means that "abc", "Abc", and "ABC" would be three distinct variables.
A variable may have either a numeric or a string value. The
difference is in how the values are treated in tests and by various
functions.
Consider these two snippets of M-Script II code:
a = 10
b = 5
c = a + b
print( "C = ", c )
and
a = "10"
b = "5"
c = a + b
print( "C = ", c )
The first example assigns numeric values to the variables. The
result that it prints would be C = 15.
The second example is similar, except it uses string values
instead of true numbers. The result that it prints would be
C = 105, which is the concatenation of the strings
"10" and "5".
Any variable may have either a numeric value or a string value, but
not both at the same time. You can reassign a new value to a variable
at any time, and it does not need to be the same type as it was
before.
It is possible to create and access variable arrays using
the varget() and varset() functions, which are documented in
the Miscellaneous Functions section.
NOTE: If you reference a variable name that
has not been set to any specific value, it will default to having a
numeric value of zero.
Meta Commands are special commands that aren't actually part of a
program, instead they control how the M-Script II interpreter behaves.
All meta commands start with an ampersand character.
- @include filename
- This command tells the interpreter to open the named file and to start
reading lines from it as if it were part of the current file. When it is
finished with that file, it continues with the next line in the current one.
This allows you to put frequently used functions in an external file which
you can then include in numerous MS2 programs. Included files may in turn
include other files, up to 8 levels deep. The file is assumed to be
relative to your root directory.
- @echo and @endecho
- Any lines that appear between these two commands are printed to the
display according to the same properties as the echo() and includes()
functions. Double quotes and backslashes are escaped with a backslash,
and a newline character is added to the end of each line.
-
- @comment and @endcomment
- Any lines that appear between these two commands will be treated as
if they each had a ';' character at the beginning, even if they don't.
In this way you can create large comments that are easier to read. It's
also a useful tool for temporarily shutting off parts of your program
while you test. These may be nested up to any level.
Functions are similar to variables, except that they cannot be assigned
a value. Instead, a function performs some sort of calculation or
operation and returns a result. Some functions return a number while
others return a string. The only visual difference between a function
and a variable is that all functions are followed with a pair of
parenthesis. For example, abs is a variable name, while
abs() is a function name.
Most functions require you to pass them one or more arguments. These
are placed within the parenthesis, separated with commas. For example,
the hypot() function takes two numeric parameters like this:
hypot( 10, 15 )
There are two different types of functions. Intrinsic functions
are built into the M-Script II programming language. User defined
functions work exactly the same way, except you define them yourself in
your program. All intrinsic functions have lower case names, but any
functions you define yourself may have upper or lower or mixed case names.
Don't forget that function names are case sensitive.
Functions are often referred to as "routines" or "subroutines".
User Defined Functions
Every M-Script II program has at least one user defined function called
the "main" function. This is, generally, the program itself and it does
not necessarily need to be explicitly defined.
Often it is desirable to define your own functions that you can call
just like an intrinsic function. This is useful if you have to perform
a similar calculation several times throughout your program, for example,
or even just to break your program up into a more modular (and therefore
more readable) format.
To define a function you use the define keyword, like this:
define hypot2( a, b )
return sqrt( a * a + b * b )
This example defines a new function called "hypot2", which takes two
parameters called "a" and "b". It calculates and returns the hypotenuse
of a right triangle who's sides adjacent to the right angle are "a" and "b"
units long.
Note that we didn't name this function "hypot" because that is the name of
an intrinsic function that does the same thing, and you cannot redefine
intrinsic functions.
Once defined, you could use this function in exactly the same manner that
you would use the intrinsic function hypot(). Of course, the intrinsic
version is compiled and will run much faster than a user defined version.
Normally you would place all function definitions after the
main part of your program. If you prefer to put them at the top, however,
you will then need to explicitly define the main function so that the
interpreter knows where it starts in the file. In this case simply add
the line define main() before the first expression in the
main function.
In the above example we define two parameters, "a" and "b". These are
variable names by which your function can refer to whatever values are
passed in to it. But what happens if you have a global variable
called "a"? Well, as long as your function is executing, it will have it's
own "a" variable and will be unable to reference the global one. Also note
that if this function were to call other user defined functions, they will
inherit the local value of "a" (unless they define their own local
variable "a").
Function names may be virtually any length.
String Functions
- addanchors( string )
- Adds HTML anchor tags around any embedded URLs in the string. For example,
addanchors( "Go to www.islandnet.com!" ) would return "Go
to <a href="http://www.islandnet.com/>www.islandnet.com</a>!".
- asc( string )
- Returns the numeric ASCII code for the first letter in the specified
string. For example, asc( "A" ) returns 65.
- chr( number )
- Returns a string, one character in length, consisting of the
character who's ASCII code is the number. For example,
chr( 65 ) returns "A", and
chr( 13 ) returns a carriage return. If multiple
numbers are given, a longer string is returned. For example,
chr( 65, 66, 67 ) returns "ABC". A
maximum of 16 numbers can be specified at once.
- collapse( string )
- Returns the specified string with all extraneous spaces removed.
It leaves a single space between words.
- countchar( string, delim )
- Returns the number of times that "delim" appears in "string". If
"delim" is left out then the default delimiter value is used.
- escapehtml( string )
- Returns the specified string with any HTML tags "escaped". That is,
less than signs and greater than signs are replaced with "<" and
">". The resulting string can be displayed on a web page without
being interpretted as HTML.
- first( string, delim )
- Returns the first token from the specified string that consists of
characters not in "delim". If not specified, "delim" defaults to a
space. For example,
first( "This is a test" ) returns
"This", while first( "one:two:three", ":" )
returns "one".
- hex( string )
- Converts the hexidecimal value of "string" into a number. For example,
oct( "0xff" ) returns 253.
- inlist( key, value1, value2, value3, ... )
- Returns 1 if "key" is equal to value1, 2 if it equals value2, and
so on. If the key does not match any of the values then the function
returns 0. Works with strings or numbers.
- insert( string1, string2, start, len )
- This function inserts "string1" into "string2" starting at position
"start". "len" specifies how many characters in "string2" are to
be replaced by the characters in "string1". If you leave
this parameter out it defaults to 0. For example,
insert( "123", "abcdef", 3, 2 )
returns "ab123ef" ("123" is inserted at position 3 and replaces 2
characters.
- join( delim, string1, string2, ... )
- Joins all the strings together using "delim" as a delimiter.
- last( string, delim )
- Returns the last token from the specified string that consists of
characters not in "delim". If not specified, "delim" defaults to a
space. For example,
last( "This is a test" ) returns
"test", while last( "one:two:three", ":" )
returns "three".
- left( string, length )
- Returns the first "length" characters of "string". For example,
left( "This is a test", 6 )
returns "This i".
- len( string )
- Returns the length of the string.
- lower( string )
- Returns the string with all letters converted to lower case.
- md5( string )
- Calculates and returns the 32 byte MD5 hash value of a string.
- mid( string, start, length )
- Returns the section of the string that is "length" characters long,
starting with character number "start". For example,
mid( "This is a test", 6, 4 )
returns "is a".
- nth( string, number, delim )
- Returns the "nth" token from the specified string that consists
of characters not in "delim". If not specified, "delim" defaults to a
space. For example,
nth( "This is a test", 3 )
returns "a", while
nth( "one:two:three", 2, ":" ) returns
"two".
- num( string )
- Converts the string into a numeric value. For example,
num( "10" ) returns 10.
- oct( string )
- Converts the octal value of "string" into a number. For example,
oct( "077" ) returns 63.
- pad( string, width, style )
- This function returns the string, padded with blanks to make it "width"
characters in length. If no style is specified, then the original string
is left justified within the new value. If you specify a style 1, then
the original string will be centered within the new value. A style of 2
will right-justify the original string in the new value. If the length
of the original string is longer than the specified width then it simply
returns the original string as is (it is not truncated).
- pos( needle, haystack, start )
- This function returns the position (a number) of the string "needle"
in the string "haystack", or zero if "haystack" doesn't contain "needle"
at all. "start" is a number telling it which position in "haystack" to
start searching. If left out, "start" defaults to 1. The search for
"needle" always proceeds freom left to right. For example,
pos( "is", "This is a test" )
returns the number 3.
- proper( string )
- Returns the string with the first letter of each word converted to
upper case and all other letters converted to lower case. For example,
proper( "mark morley" ) returns "Mark Morley".
- repeat( string, number )
- This function returns a new string that consists of "number" copies
of "string". For example, repeat( "*", 10 )
returns "**********".
- rest( string, delim )
- Returns the rest of the specified string minus the first token
that consists of characters not in "delim". If not specified, "delim"
defaults to a space. For example,
rest( "This is a test" ) returns "is a
test", while rest( "one:two:three", ":" )
returns "two:three".
- reverse( string )
- Returns the specified string with all characters reversed. For example,
reverse( "1234" ) returns "4321".
- right( string, length )
- Returns the last "length" characters of the string. For example,
right( "This is a test", 6 )
returns "a test".
- str( number )
- Converts the number into a string value. For example,
str( 10 ) returns "10".
- strip( string, chars )
- Returns the specified string, stripped of all chararacters in "chars".
For example, strip( "This is a test", "aeiou" )
returns "Ths s tst".
- striphtml( string )
- Returns the specified string stripped of all HTML tags. For example,
striphtml( "<i>Testing</i>" ) returns
"Testing".
- trim( string )
- Returns the specified string stripped of any leading or trailing
spaces or tabs.
- triml( string )
- Returns the specified string stripped of any leading spaces or tabs.
- trimr( string )
- Returns the specified string stripped of any trailing spaces or tabs.
- upper( string )
- Returns the string with all letters converted to upper case.
- wild( string, pattern )
- Returns 1 if "string" matches the wildcard pattern. "Pattern" may
contain the "*" and "?" wildcards. This is equivalent to using the
*= operator.
- words( string )
- Returns the number of "words" in the specified string. A words is
considered to be any string of characters that is not a space, tab,
carriage return, or newline.
I/O Functions
These functions allow you to print to the screen, and read and write to
files.
- close( f )
- Closes file number 'f'. 'F' is a number previously returned by
the open(), opensorted(), or mail() functions. You can close
multiple files at the same time by listing multiple file numbers like this:
close( f1, f2, f3 )
- delete( filename )
- Deletes the specified file. Filenames are relative to your home
directory. Returns 1 if it is successful, otherwise it returns 0.
This is permanent! You cannot undelete a file once it is gone.
- echo( value1, value2, ... )
- This function works almost exactly like the print() function, except
that values enclosed in curly braces are interpretted just like the
includes() function.
- eof( f )
- Returns 1 if the file indicated by the file number is at the
end-of-file, otherwise it returns 0. 'F' is a number previously
returned by the open() function.
- exists( filename )
- Returns 1 if the specified file exists, otherwise it returns 0.
Filenames are relative to your home directory.
- filesize( filename )
- Returns the size in bytes of the specified file. Filenames are
relative to your home directory.
- filetime( filename )
- Returns a string representing the date and time that the specified
file was last modified. The time is in the format "1998-05-01 12:30:15".
Filenames are relative to your home directory. If the file does not
exist, it returns 0.
- filetype( filename )
- Returns a string indicating what type the specified file is. It
returns "dir" if it's a directory, "link" if it's a symbolic link,
and "file" if it's a regular file. If the file does not exist it
returns a 0.
- flush()
- Normally everything your output to the screen is buffered, which means
it may not be printed immediately. Sometimes there are cases where you
display something then have to wait while a task completes. Use this
function to flush the output buffer, forcing everything printed so far
to be displayed.
- include( filename, f )
- Dumps the contents of the specified file to the specified file
number. "F" is a number previously returned by the open() function.
If the file number is left out, then it dumps the contents to the
display instead of a file. This is useful for displaying common
header or footer files, or for sending a canned email message, etc.
- includes( filename, f )
- Works exactly like include() except that strings within the file that
are enclosed within curly braces are interpretted to be M-Script II
variables and they are replaced on the fly with the variable value.
For example, if the variable NAME is set to "Mark", and the file named
"sample.html" consisted of the line "Hello {NAME} how are you?", then
includes( "sample.html" ) would display "Hello Mark
how are you?"
- lockf( file )
- Locks a currently open file number so that other scripts (or other
instances of the same script) don't attempt to write to the same file.
The file is automatically unlocked when you close it or when your script
stops running. Returns 0 on failure (which means that another program has
it locked OR it's not a currently open file), and 1 on success. It returns
immediately, it does not wait for a file to become unlocked.
- mail( address )
- This function opens an email message addressed to "address". It returns
a file number, exactly like the open() function does. You can then use
write() or include() to fill in headers and a body. As soon as you close()
it the message will be sent.
- move( from, to )
- Moves (renames) a file or directory. Returns 1 if it is
successful, otherwise it returns 0. The new location does not need
to be in the same directory as the current one. File and directory
names are relative to your home directory.
- open( filename, mode )
- Opens the specified file using the specified mode. Both the filename
and the mode are strings. The default mode is "r" (Read Only). Other
modes include "w" (Write only - always creates a new file), "a" (Append -
opens an existing file for writing, creates it if necessary), and "r+"
(Read/Write - opens a file for reading and writing). This function returns
a number indicating the file number, or 0 if it fails. As many as 10
files may be opened simultaneously.
- opensorted( filename, field, flags, delim )
- This function can only be used to open a file for reading. The
difference between this and the regular open() function is that lines
are not necessarily read sequentiallty from the file. Instead, each
subsequent read() call returns the next sorted line. "field"
is the field number within each line to sort on, it defaults to 1
which is the first field. "flags" is an optional string of letters.
Each letter turns on a sorting option as follows:
r - Reverses the sort order
n - Sort numeric data as numbers not letters
d - Use dictionary order (only letters and numbers count)
f - Fold case (treat lower/upper case letters the same)
m - Month order - data must start with "Jan", "Feb", "Mar", etc.
"delim" is the delimiter to use when sorting on a field other than 1. For
example, if you have a data file that consists of first name/last name pairs
separated with a colon, you could read them in sorted on the last name like
this:
if input = opensorted( "names.dat", 2, 0, ":" )
while (line = read( input )) != 0
print( "Name: ", nth( line, 2, ":" ), ", ", first( line, ":" ), "\n" )
endwhile
endif
- openswish( index, words, max, tags )
- This function opens the specified Swish index file and searches it for
the specified keywords. You read the results of the search one line at a
time using read(). "max" is optional and is used to specify the maximum
number of hits to return. "tags" is an optional string indicating which
tags should be searched.
The results from a swish search may begin with a hash mark, in which case
they are comments and may be ignored. A line consisting of a single period
means you've reached the end of the results. All other lines returned will
be in the following format:
score url "title" size
where "score" is a number between 0 and 1000 indicating how relevent the
hit is (the results are always sorted with the highest scoring entries
listed first). "url" is the URL of the document, "title" is the title
(enclosed in a pair of double quotes), and "size" is the document size
in bytes.
- print( ... )
- Prints one or more values to the screen. "..." represents one or
more strings or numbers. For example,
print( "2 + 2 = ", 2 + 2 )
will display "2 + 2 = 4".
- printf( format, ... )
- Prints the format string to the screen, replacing any embedded formatting
codes with the string or number values supplied. Formatting codes include
%s to insert a string value, %n to insert an integer value,
and %f to insert a floating point value. Optional codes and values
may appear between the '%' symbol and the 's', 'n', or 'f' to further control
the formatting.
Normally an inserted value will take up the minimal amount of space required.
You can force a value to fill up at least N spaces by inserting a number
between the '%' and the 's', 'n', or 'f'. If the result is shorter than N
characters, it is padded on the left with spaces. You can cause the padding
to occur on the right by placing a hyphen immediately after the '%' symbol.
A string value can be truncated to the first N characters by adding ".N"
just before the 's'.
You can control the number of decimal places displayed for floating point
numbers by adding ".N" just before the 'f'.
Numeric values will be left-padded with zeros instead of blanks if you have
a zero immediately after the '%' symbol.
For the following examples, let's assume the variable "name" is set to "Fred
Flintstone" and "wage" is set to the number "7.5". We'll show printf()
example followed by the output generated. I am using underscore characters
to represent spaces to better illustrate what happens.
printf( "%s was here.", name )
Fred Flintstone was here.
printf( "It was %30s who did it.", name )
It was _______________Fred Flintstone who did it.
printf( "It was %-30s who did it.", name )
It was Fred Flintstone_______________ who did it.
printf( "%.4s was here.", name )
Fred was here.
printf( "%10.4s was here.", name )
Fred______ was here.
printf( "%.4s makes %f an hour.", name, wage )
Fred makes 7.500000 an hour.
printf( "%.4s makes %.2f an hour.", name, wage )
Fred makes 7.50 an hour.
printf( "%.4s makes %10.2f an hour.", name, wage )
Fred makes ______7.50 an hour.
printf( "%.4s makes %010.2f an hour.", name, wage )
Fred makes 0000007.50 an hour.
- read( f )
- This function returns the next line of text from the open filed
indicated by the file number given. If there are no more lines left
in the file, it returns 0. A "line" may be up to 10,000 characters
in length. Lines longer than this are truncated and treated as two
or more lines. All carriage returns and newlines are stripped from
the end of each line. Here's is how you would read through every line of
a file:
if input = open( "filename.txt" )
while (line = read( input )) != 0
; Do whatever you want with "line" here...
endwhile
close( input )
endif
- rewind( f )
- This function rewinds the the open file 'f' so that any subsequent
read() or write() calls will be relative to the beginning of the file.
This is functionally equivalent to
seek( f, 0, 0 ).
- seek( f, offset, mode )
- This function repositions the pointer for the currently open file 'f'
based on the two parameters given. If "mode" is 0, then the pointer will
move to "offset" bytes from the beginning of the file. If mode is "1"
then it will move "offset" bytes relative to its current position. If "mode"
is 3, then it is relocated to "offset" bytes from the end of the file.
This function is most useful in conjunction with the tell() function.
- tell( f )
- This function returns the current position of the file pointer for the
open file 'f'. The file pointer is the byte offset within the file where
the next read() or write() will occur. This is useful to remember a location
within an open file, so that you can seek() back to the same spot instantly
later on.
- unlockf( file )
- Unlocks an open file number that was previously locked with the lockf()
function. This is not necessary if you close the file or exit your
script.
- write( f, ... )
- Writes one or more values to the open file indicated by the file
number. "F" is a number previously returned by the open() function.
"..." represents one or more strings or numbers.
- writef( f, format, ... )
- Writes the format string to the open file 'f', replacing any embedded
formatting codes with the string or number values supplied. Formatting codes
include %s to insert a string value, %n to insert an integer
value, and %f to insert a floating point value. Optional codes and
values may appear between the '%' symbol and the 's', 'n', or 'f' to further
control the formatting.
For more details, refer to the printf() function.
Directory Functions
These functions allow you to create, delete, and read directories.
- closedir( handle )
- Closes a directory handle that was previously returned by the opendir()
function.
- opendir( dirname )
- Opens the specified directory for reading and returns a directory
handle.
- mkdir( dirname )
- Creates the specified directory. Directory names are relative to
your home directory. Returns 1 if it is successful, otherwise it
returns 0.
- readdir( handle )
- Returns the next filename in the directory pointed at by the directory
handle. If there are no more filenames available it returns 0.
This example would simply print the name of every file in your "ms2"
directory:
if DIR = opendir( "ms2" )
while FILE = readdir( DIR )
printf( "%s\n", FILE )
endwhile
closedir( DIR )
endif
- rewinddir( handle )
- Rewinds the directory handle so that the next readdir() will start at
the beginning again.
- rmdir( dirname )
- Removes the specified directory. The directory must be empty for
it to work. Directory names are relative to your home directory.
Returns 1 if it is successful, otherwise it returns 0.
- seekdir( handle, location )
- Moves the directory handle pointer to the specified location. The
location is a number that was previously obtained via the telldir() function.
- telldir( handle )
- Returns a number that marks the current location of the directory
handle pointer which you can later pass to seekdir() to return to the
same spot. Note that the return value is only good for the current
session - if you close the dir and open it again the location is not
guaranteed to stay the same.
DBM Functions
The DBM functions allow you to create and manipulate a UNIX DBM database.
DBM databases store only two values per record - a "key" and a "value".
You can use these to create an index into a flat file database by using
the result from the tell() function as the value. Both the key and the
value can be either a number or a string, however duplicate keys are not
allowed.
- dbmclose( dbm )
- Closes the specified DBM database.
- dbmdelete( dbm, key )
- Deleted the specified key from the DBM database.
- dbmfetch( dbm, key )
- Locates the key in the specified DBM database and returns the corresponding
value.
- dbmfirstkey( dbm )
- Returns the first key in the DBM database (that's the KEY, not the
corresponding value). Note that the order in which keys are returned
is abritrary, DBM files cannot be sorted in any fashion.
- dbmnextkey( dbm )
- Returns the next key in the DBM database (assumes you've already called
dbmfirstkey()). Note that the order in which keys are returned
is abritrary, DBM files cannot be sorted in any fashion.
- dbmopen( name )
- Opens a DBM database and returns a DBM handle. If the database does
not exist then it is created. A DBM database consists of two files, so if
you were to dbmopen( "sample" ) you'd see the files "sample.pag" and
"sample.dir" get created.
- dbmstore( dbm, key, value, replace )
- Store the key/value pair in the DBM database. If "replace" is 0, then
this will only insert the value if the key does not already exist. If
"replace" is 1 then any exisiting key will be replaced. DBM files may not
have duplicate keys.
MySQL Functions
SQL (pronounced "ess que ell", not "sequel") stands for "Structured Query
Language". It is an industry standard database interface, perhaps the most
popular in the world. MySQL is a popular SQL
implementation that provides a very fast and robust database system.
M-Script II has a full set of functions that allow you to access an SQL
server, perform searches, and manipulate tables and indexes.
Rarely will you have permission to create a new database yourself, usually
your ISP will need to create an empty database for you. Once you have a
database (and a username and password to go with it) you can create the
tables and indexes within it as required.
A database may contain zero or more "tables" (although you'll need at least one
before it's useful for anything). A table is a set of zero or more "rows"
(aka "records"). Each row within a table has the same number and type of
"columns" (aka "fields").
- mysqlconnect( server, username, password )
- This function opens a connection to the specified SQL server. You must
also supply a username and password (MySQL databases are password protected
to prevent unauthorized changes to your data). This function returns 0 if
it is unable to connect, otherwise it returns a database handle that you
will need to reference in subsequent function calls.
- mysqlclose( handle )
- This function closes the connection to the specified database server.
"handle" is a number previously returned by a successful mysqlconnect() call.
Always close your connections when you no longer need them to free up RAM.
- mysqlcreatedb( handle, database )
- This function creates a new, empty database with no defined tables or
indexes. You must have connected to the server with a username and password
that has permission to create new databases.
- mysqldropdb( handle, database )
- This function drops (deletes) an entire database, including all tables
and indexes. You must have connected to the server with a username and
password that has permission to drop databases.
- mysqlselectdb( handle, database )
- Once you have opened a connection to the database server, you must select
a database to work with. "database" is a string naming the database. The
database must already exist, although it may not have any tables yet. This
function returns 0 on failure (either the database named does not exist on
the server or the username/password you connected with has no permission).
- mysqlquery( handle, query )
- This function sends the SQL query to the database server. SQL "queries"
are not just search commands, they can also be commands to create new tables
or indexes, insert or delete data, etc. "query" is a string. This function
returns 0 on an error, or 1 if it is successful.
- mysqlstoreresult( handle )
- Depending on the the nature of a query (and whether it's successful or
not), you need to call this function to actually transfer the data from the
server to your program. It returns a 0 if it fails, otherwise it returns
a "result handle". You need to use this handle access individual rows.
- mysqlfreeresult( result )
- When you are done with the results of a query, you must free the result
handle returned by the mysqlstoreresult() function to release any RAM or
disk space used.
- mysqlfetchrow( result )
- This function grabs the next row of data from the specified result handle
and places each field value into the "field" array. Use the varget() function
to access each field value. The variable "numfields" is also set to indicate
how many fields are available. Note that all field values are returned as
strings, regardless of their actual field type.
- mysqldataseek( result, n )
- This function lets you reposition the "pointer" within the specified
set of result rows, so that the next call to mysqlfetchrow() will retrieve
the specified row number. The first row is always 0.
- mysqlnumrows( result )
- This function returns the number of rows in the specified result.
- mysqlnumfields( result )
- This function returns the number of fields in the specified result.
- mysqlaffectedrows( handle )
- This function returns the number of rows that were affected by the last
deletion or update query.
- mysqleof( handle )
- This function returns 1 if the last mysqlfetchrow() attempted to access
beyond the last row in the results.
- mysqlerror( handle )
- If a mysql function fails for any reason, you can call this function to
get an error message explaining what went wrong. It returns 0 if there was
no error to report.
Math Functions
These functions are used in mathematical calculations. They all return
numeric values and take numeric arguments.
- abs( number )
- Returns the absolute value of the number. For example,
abs( 10 ) is 10, and so is
abs( -10 ).
- acos( number )
- Returns the arc cosine of the specified number. The number is
assumed to be in radians, not degrees.
- asin( number )
- Returns the arc sine of the specified number. The number is
assumed to be in radians, not degrees.
- atan( number )
- Returns the arc tangent of the specified number. The number is
assumed to be in radians, not degrees.
- cbrt( number )
- Returns the cube root of the specified number.
- ceil( number )
- Returns the smallest integer value that is greater than or equal to
the specified number.
- cos( number )
- Returns the cosine of the specified number. The number is assumed
to be in radians, not degrees.
- deg( radians )
- Converts radians to degrees.
- exp( number )
- Returns the exponent of the specified number.
- floor( number )
- Returns the largest integer value that is less than or equal to
the specified number.
- hypot( number1, number2 )
- Given the length of the two sides adjacent to the right angle in a
right triangle, this function returns the length of the hypotenuse.
- log( number )
- Returns the natural log of the number.
- log10( number )
- Returns the base 10 log of the number.
- max( n1, n2, ... )
- Returns the maximum value from the specified list of numbers.
- min( n1, n2, ... )
- Returns the minimum value from the specified list of numbers.
- pi()
- Returns the value of PI.
- pow( number1, number2 )
- Returns number1 raised to the number2 power. For example,
pow( 10, 2 ) returns 100.
- rad( degrees )
- Converts degrees to radians.
- random( number1, number2 )
- Returns a random integer number. If no parameters are provided,
it returns a number between 0 and 100. If only "number1" is provided,
then it returns a number between 0 and "number1". If both numbers are
provided, it returns a number between "number1" and "number2".
- round( number, decimals )
- Returns the specified number rounded to "decimal" decimal places.
For example, round( 3.49, 1 ) returns 3.5,
while round( 1.333, 2 ) returns 1.33.
- sign( number )
- Returns -1 if the number is less than zero, otherwise it returns 1.
- sin( number )
- Returns the sine of the specified number. The number is assumed to
be in radians, not degrees.
- sqrt( number )
- Returns the square root of the specified number.
- tan( number )
- Returns the tangent of the specified number. The number is assumed
to be in radians, not degrees.
Bit Functions
These functions can be used to manipulate bit vectors.
- andbits( b1, b2, ... )
- This function returns the value that results when all the numeric
values are combined logically using AND.
- notbits( b )
- This function returns the value that results when the single numeric
parameter is negated.
- orbits( b1, b2, ... )
- This function returns the value that results when all the numeric
values are combined logically using OR.
- shiftleft( b, n )
- This function shifts the bits in "b" left by "n" places.
- shiftright( b, n )
- This function shifts the bits in "b" right by "n" places.
- xorbits( b1, b2, ... )
- This function returns the value that results when all the numeric
values are combined logically using XOR.
Time and Date Functions
- checkdate( year, month, day )
- This function returns 1 if the year, month, and day combine to give
a valid date, otherwise it returns 0. Leap years are taken into account.
- gettime()
- This function returns the current time as a number that represents the
number of seconds since 00:00:00 on January 1st 1970 (the beginning of UNIX
time).
- leapyear( year )
- Returns 1 is the specified year is a leap year, otherwise it returns 0.
"year" may be either a number or a string value.
- maketime( year, month, day, hour, minute, second )
- This function returns a number that represents the number of seconds
since 00:00:00 on January 1st 1970 (the beginning of UNIX time), based
on the parameters provided.
- time( format, time )
- Returns a string containing the specified time using the specified
format. "time" may be a number as returned by the gettime() and maketime()
functions, or it may be a string in the format "YYYY-MM-DD HH:MM:SS". If
you leave it out completely then the current time is used. If "format" is
not present it defaults to "%Y-%m-%d %H:%M:%S". The format value may
contain any text, but the following codes are replaced (case is important):
- %%
Same as %
- %Y
Year (4 digits)
- %y
Year (2 digits)
- %m
Month (01-12)
- %d
Day of month (01-31 - leading zero)
- %e
Day of month (1-31 - no leading zero)
- %H
Hour (00-23 - leading zero)
- %k
Hour (0-23 - no leading zero)
- %I
Hour (01-12 - leading zero)
- %l
Hour (1-12 - no leading zero)
- %M
Minute (00-59)
- %S
Second (00-59)
- %p
AM or PM
- %a
Day name (Sun - Sat)
- %A
Day name (Sunday - Saturday)
- %b
Month name (Jan - Dec)
- %B
Month name (January - December)
- %U
Week number (01-52 - Sunday is the first day)
- %W
Week number (01-52 - Monday is the first day)
- %w
Day of week (0-6 - Sunday is day 0)
- %Z
Time zone.
- %D
Date as %m/%d/%y
- %p
Time as %I:%M:%S %p
- %T
Time as %H:%M:%S
- %j
Day of year (001-366)
- %n
Newline character
- %t
Tab character
- timeadd( time, number, units )
- Adds the specified number of units to the specified date/time.
"time" may be a number as returned by gettime() and maketime(), or a
string in the format "YYYY-MM-DD HH:MM:SS". "units" may be one of "seconds",
"minutes", "hours", "days", "weeks", "months", or "years". If "time" was
a number, then this function returns a number, otherwise it returns a
string. For example, timeadd( time(), 2, "weeks" )
will return today's date/time plus 2 weeks. You can subtract time by
using a negative number.
- timesub( time1, time2 )
- Subtracts time2 from time1 and returns the difference in seconds.
Time1 and time2 may be numbers as returned by gettime() and maketime(), or
strings in the format "YYYY-MM-DD HH:MM:SS".
CGI Functions
These functions take care of dealing with the CGI interface.
- decode()
- This function is used in password authorization scenarios. After
a call to the getauth() function, the user's browser will respond
with a new request for the same URL, but with an encrypted username
and password header. This function decodes these values and returns
a single string of the format USERNAME:PASSWORD. You can easily use
the first() and rest() string functions to extract one value or the
other. For example, if a user entered "Aladdin" and "Open Sesame" as
their username and password, decode() would return "Aladdin:Open Sesame".
- encode( string )
- Returns the "URL encoded" version of the string, suitable for use in
URLs. For example, spaces are converted to + signs, and certain other
characters are converted to their two digit hex value, etc.
- form( varname, num )
- Looks up the specified HTML form variable and returns the value as
a string. If the specified form value does not exist, it returns 0.
In the event you have multiple form values with the same name, you can
specify which one you want by providing "num" (the default is 1).
This is how you retrieve values entered by a user on your web page.
Form variable names are NOT case sensitive. All form variables are
string values, so you may need to use the num() function in some
cases.
NOTE: If you reference the same form value more than
once in your program, it is a good idea to assign it to a real variable first,
then reference the variable name instead of calling the form() function each
time. Once the value is stored in a variable it can be accessed much more
quickly.
Handling Mulipart Forms (uploading files): M-Script II supports the
use of multipart/form-type form encoding. This allows people to
upload entire files as part of an HTML form. For example, consider the
following HTML form:
<form enctype="multipart/form-data" method=post
action=/cgi-bin/ms2/LOGIN/upload>
File to upload: <input type=file name=upload1>
Description: <input name=description>
<input type=submit value="Upload it now">
Note the enctype="multipart/form-data" and the type=file
tags. The form above will allow the user to select a file on their computer,
and type in a brief description. When they submit this form the file
will be uploaded. Unlike other types of form values, an uploaded file
is not accessible via the form() function. Instead, the file is given
a unique number and saved in your "temp" subdirectory. For the example
above, there would be four form variables available to you via form():
form( "description" ) will contain the description, this one is no different
then regular input form values.
form( "upload1" ) will contain the name of the file as entered by the
user. This is NOT the name of the file in your temp directory, it's the
name of the file on the user's computer. For example, this might have
a value like "C:\WINDOWS\DESKTOP\report.xls".
form( "upload1-type" ) will contain the mime type of the file as defined
by the web browser. For example, if you uploaded a GIF image, this would
have the value "image/gif". This will be blank in many cases, especially
for unknown file types. Note that the BROWSER defines this, not M-Script.
form( "upload1-file" ) will contain the name of the file as it is locally
stored. A sample value would be "temp/1890921".
- formname( num )
- This function returns the name of form variable "num", where num starts
at 0. This is useful if you don't know exactly what fields the input form
is providing. See formvalue() for an example.
- formvalue( num )
- The counterpart to formname(), this function returns the value of form
value "num". Here's an example that prints every form value submitted:
i = 0
while (name = formname( i )) != 0
value = formvalue( i )
printf( "%s = %s<br>\n", name, value )
i = i + 1
endwhile
- getauth( realm )
- This function will output the necessary headers to request "authorization".
This means the user's browser will normally prompt them for a username and
password pair, then try and connect to the same URL again (this time passing
the username and password to the CGI program via encrypted headers). For
example, to require a username/password to access a given program, it may
include code like this:
if decode() != "Aladdin:Open Sesame"
getauth( "Secret Cave" )
print( "Sorry, you need to specify a username and password." )
exit
endif
print( "Welcome..." )
The "realm" is a short string that is passed back to the browser. It
is normally used in the prompt message that the user's browser will display
when requesting a username and password. Please note that this is not
necessarily used in the prompt message, and there is no way to specify
an alternate prompt message.
Notice that after calling the getauth() function we exit the program. This
is because the browser will reconnect to the program after the user enters
the username and password. The error message printed after the getauth()
call will only appear to the user if they cancel the username/password
request.
- getcookie( cookie )
- If the specified cookie is set, then its value is returned as a string,
otherwise it returns 0.
- getenv( var )
- If "var" is a string, then this function returns the string value of
the specified environment variable. If "var" is a number, then it returns
the Nth environment variable as a string like "NAME=VALUE". Environment
variable names ARE case sensitive. Some variables you can access include:
- HTTP_USER_AGENT
The name and version of the browser software.
- REMOTE_ADDR
The IP address of the user's machine.
- PATH_INFO
The arguments given to the "ms2" interpreter.
- DOCUMENT_NAME
The name of the page that invoked this program.
- DOCUMENT_URI
The name of the page that invoked this program, path expanded.
- QUERY_STRING
The list of form values passed to the program via the GET method.
- mimetype( mimetype )
- This function will print a valid HTML Content-Type header using the
specified mime type. You only need to use this function if you are
outputting something other than text or HTML, like an image or a sound
file. If you use this function, it absolutely must be called
prior to any other functions that output data to the display. For
example, if you were going to output a GIF image you would use
mimetype( "image/gif" ).
- redirect( url )
- This function will cause a browser to be redirected to the specified
URL. If you use it you cannot have any other output before or after it.
- setcookie( cookie, value, expires )
- This function allows you to set a cookie value in the user's browser.
This can be used to store information between visits by the same person.
If you use this function, it must be used prior to any functions
that print to the screen (like print() or include()). At a minimum you
must supply a cookie name and a value. For example,
setcookie( "PRODUCT", "Fuzzy Pink Dice" ). If
you do not provide an expiry date, then the cookie will stay in the
user's browser until they close and restart it. You can make a cookie
more persistent by providing an expiry date of the format "Weekday,
DD-Mon-YYYY HH:MM:SS GMT". For example, "Thursday, 24-Apr-1998 19:00:00
GMT". No other date format is supported, and you must always use the "GMT"
timezone (this is part of the cookie specs, not a limitation of
M-Script II).
GIF Functions
These functions allow you to create and manipulate GIF images on the fly.
They are based on Thomas Boutell's GD
library.
- arc( number, x, y, xr, yr, start, end, color )
- This function draws an arc on an in-memory image using the specified
color. The arc is part of an ellipse that has its center at "x,y" and has
an X radius of "xr" and a Y radius of "yr". The arc is drawn starting at
"start" degrees and ending at "end" degrees.
- borderfill( number, x, y, border, color )
- This function flood fills an in-memory image with the specified color,
starting at "x,y". All pixels in all directions are changed to the new
color, until a pixel of the color "border" is reached.
- box( number, x1, y1, x2, y2, color )
- This routine draws a filled in box on the specified in-memory image and
in the specified color. "x1,y1" defines the top left corner of the box,
and "x2,y2" defines the bottom right corner.
- circle( number, x, y, r, color )
- This function draws a circle on an in-memory image in the specified color.
The center of the circle is "x,y" and the radius is "r".
- closegif( number )
- This routine "closes" the specified image, freeing up memory.
- colors( number )
- This function returns the current number of colors in the palette of the
specified in-memory image. An image can have up to 256 colors total.
- copy( source, x1, y1, width, height, dest, x2, y2 )
- This function copies part of the in-memory image "source" onto the
in-memory image "dest". A rectangle "width" pixels wide and "height"
pixels high with it's top left corner at "x1,y1" is copied to the destination
image at "x2,y2". If the source image has any transparent pixels, these are
not copied. If the source and destination images have different color palettes,
this function will convert the pixels in the copied chunk so that they fit
in with the destination's palette as well as possible.
- ellipse( number, x, y, xr, yr, color )
- This function draws an ellipse on an in-memory image in the specified
color. The center of the ellipse is at "x,y", the X radius is "xr", and
the Y radius is "yr".
- findcolor( number, red, green, blue )
- This function will search the specified in-memory image's palette for
a color entry that most closely matches the red, green, and blue values
given. "Red", "green", and "blue" are numbers between 0 and 255. This is
useful if you are working with an image that has 256 colors already, and you
need to draw on it in a specific color and you don't know which color number
to use.
- floodfill( number, x, y, color )
- This function flood fiils an in-memory image with the specified color,
starting at "x,y". A flood fill takes the current color at location "x,y"
and then changes that pixel and all adjoining pixels of the same color
to the new specified color. Once it runs into a pixel of another color
it stops flooding in that direction.
- getpoint( number, x, y )
- This function returns the color number of the specified pixel in the
specified in-memory image.
- height( number )
- This function returns the height, in pixels, of the specified in-memory
image.
- interlace( number, state )
- This turns on or off interlacing for the specified image. This setting
only comes into affect when writing the GIF to the display or to disk. By
default an image created with newgif() does not have interlacing turned on.
IAn interlaced image will appear in "stages", while a non-interlaced image
is displayed from top to bottom. "State" should be 0 to turn it off,
or any other number to turn it on.
- line( number, x1, y1, x2, y2, color )
- This routine draws a line from "x1,y1" to "x2,y2" on the specified
in-memory image in the specified color. The line if drawn using the current
line style.
- loadgif( filename )
- This routine loads an existing GIF file into memory. It returns a number
that indicates the in-memory image number.
- newcolor( number, red, green, blue )
- This function finds an empty entry in the specified in-memory image's
palette and fills it with the specified color. It returns the color number,
which you can then use in drawing functions. It returns -1 if there are no
empty color entries (ie: the image has 256 colors in use already). "Red",
"green", and "blue" are numbers between 0 and 255. For example,
y = newcolor( gif, 255, 255, 0 )
creates the color yellow.
- newgif( width, height )
- This function will create a new blank (all black) image that is "width"
pixels wide and "height" pixels high. This image exists only in memory,
it is not an actual GIF file. The function returns a number indicating
the in-memory image number. An image created this way starts out with a
simple 32 color palette. The rest of the 256 colors are undefined. You
cannot create an image larger than 1024 x 768.
- rectangle( number, x1, y1, x2, y2, color )
- This routine draws a rectangle on the specified in-memory image and
in the specified color. "x1,y1" defines the top left corner of the rectangle,
and "x2,y2" defines the bottom right corner.
- setpoint( number, x, y, color )
- This function plots a single pixel on the specified image using the
specified color.
- text( number, x, y, text, font, color )
- This function writes "text" onto the specified in-memory image using
the specified font and color. "x,y" indicates the top left corner where
the text should begin. "Font" is a number between 1 and 16 (or you can
use the special keywords FONT5x8, FONT6x9, FONT6x10, FONT6x12, FONT6x13,
FONT6x13B, FONT7x13, FONT7x13B, FONT7x14, FONT8x13, FONT8x13B, FONT8x16,
FONT9x15, FONT9x15B, FONT10x20, or FONT12x24).
To the left are samples of
all sixteen available fonts. This image is generated on the fly by an
M-Script II program.
- textheight( text, font )
- Returns the height, in pixels, that the text would be if drawn in the
specified font.
- textv( number, x, y, text, font, color )
- This function works exactly like text(), except that the text is written
vertically on a 90 degree angle. "x,y" specifies the bottom left corner where
the text is to begin.
- textwidth( text, font )
- Returns the width, in pixels, that the text would be if drawn in the
specified font.
- transparent( number, color )
- This function sets which color in the specified image should be treated
as "transparent", allowing the background to show through. By default,
images created with newgif() have no transparent color. To turn it off
use the color -1.
- width( number )
- This function returns the width, in pixels, of the specified in-memory
image.
- writegif( number, filename )
- This function writes the specified in-memory image to the specified file
name as a GIF image. If you don't specify a file name, then the image is
written to the display. If the image is sent to the display instead of
a file, the function will automatically output an "image/gif" mimetype
header if necessary.
NOTE: When an image is loaded from a GIF file,
the color palette is set according to what's in the file. However, if you
create a gif from scratch using newgif(), then the first 32 entries in the
palette are predefined with some common colors for you to draw with.
When specifying colors to a function, you normally just provide a number
between 0 and 255, but if you created the image with newgif() you can
use upper case constants like BLACK, WHITE, and so on. To the left is
a chart showing the 32 predefined colors and the special constants you can
use to specify them. If the image was loaded
from a file, or if you have altered the palette in any way, "BLACK" simply
becomes color #0, which may no longer be black. Likewise WHITE represents
color #1, and so on.
This color chart is generated on the fly by an M-Script II program.
Miscellaneous Functions
Here's where we list any left over functions that don't quite fit in the
other categories.
- accepted( filename )
- Returns 1 or 0 depending on if the IP number or host name of the current
user is accepted or rejected according to the contents of the named file.
This mechanism provides a handy way of banning certain sites from accessing
your site, normally due to abusive behavior. For example, if you find that
your guestbook is being filled with abusive messages from a particular
site, you can add their site to the specified file without having to modify
your M-Script II code to deal with them explicitly.
The file itself is an ordinary ASCII text file containing lines like this:
accept scooby.islandnet.com
reject 199.175.107.*
reject *freenet.victoria.bc.ca
This example always grants access to "scooby.islandnet.com", but rejects
everything else with a 199.175.107.* IP number. It also rejects all
accesses from freenet.victoria.bc.ca.
Each line must either accept or reject an IP number or a host
name. The wildcard '*' may be used at the end of an IP number or the
beginning of a host name. The first line in the file that matches the
current visitor is the one that counts.
- alarm( minutes )
- By default, an MS2 program will kill itself after 2 minutes, regardless
of what it is doing. This is plenty of time for most CGI applications, and
it protects the system against programming mistakes that cause infinite
loops. In some cases you may want to override this with the alarm()
function. Simply specify the number of minutes that the script should be
allowed to run. A value of 0 will allow it to run as long as necessary.
Use this with caution and only if you really need it.
- bxparse( expression )
- This function is used in conjunction with either bxteststring() or
bxtestfile() to process "boolean expresions". A boolean expression is
a string containing one or more "words" joined together with "and",
"or", "not", or parenthesis. Each "word" may be a literal word, a
wildcard pattern, or a "sounds like" word. Use bxparse() to prepare a
boolean expression, then use one or both of the related functions to test
the expression against strings or files as many times as necessary. You
only need to call bxparse() once, or whenever you want to use a different
boolean expression. The following example will test each line of a file
to see if it contains the word "peanut" and either "fudge" or "choc*"
(note that "choc*" is a wildcard "word"):
if input = open( "goodies.dat" )
bxparse( "peanut and (fudge or choc*)" )
while (line = read( input )) != 0
if bxteststring( line )
print( line )
endif
endwhile
endif
The "words" in a boolean expression may be any of the following:
- A literal word like "fudge". This matches "fudge" as well as "FUDGE".
- A literal word like "=PeaNut". This matches "PeaNut" but not "peanut" or "PEANUT".
- A wildcard word like "choc*". An asterisk ("*") matches zero or more
characters, while a question mark ("?") matches a single character.
- A "sounds like" word like "~chokalat". The leading tilde tells it to
use the SOUNDEX algorithm to check for words that sound similar.
- bxtestfile( filename )
- This function is used in conjunction with bxparse() to test to see
if the specified file matches a boolean search expression. It returns 1
if the contents of the file match, or 0 if they don't.
- bxteststring( string )
- This function is used in conjunction with bxparse() to test to see
is a specified string matches a boolean search expression. It returns 1
if the string matches, or 0 if it doesn't.
- cctype( string )
- Returns a string, one character in length, indicating what type of
credit card number the string is. It returns "v" for VISA, "m" for
MasterCard, "a" for American Express, "d" for Discover, "c" for Carte
Blanche, and 0 if the specified string does not represent a valid
credit card number. This function uses the LUHN algorithm to
determine if the credit card number *could* be legitimate. There is no
way to determine if the number has yet been assigned to anyone by
the credit card company however.
- count( filename, key, number )
- This function allows you to maintain a set of counter values in a single
file. Each line in the file contains a keyword/number pair. To get the
current counter value for a specified key, either leave out the number or
pass in a zero value. If "number" is not zero, then it is added to the
counter value. Normally "number" will be 1. Negative numbers will decrement
the counter value. If the specified file does not exist it is created.
- crypt( string, salt )
- This function returns the encrypted version of "string". "salt" is a two
character string that is used to permutate the encryption in one of 4096
ways. The resulting value will always start with the salt value itself.
The encryption is one-way only, useful for storing passwords for example.
- currency( amount, from, to )
- This function converts an amount from one currency into another. Over
170 currencies from around the world are supported. "Amount" is a numeric
value, "from" is a three-character ISO currency code representing the
currency you want to convert from, and "to" is a similar code representing
the currency you want to convert to. For example, to convert $100 US into
Canadian you would use n = currency( 100, "USD", "CAD" ).
Click here for a currency table
- currencylist( code )
- This function outputs a list of all the supported currencies, one per
line, in this format:
<option value=CAD>Canadian Dollar. It is meant to
be part of a select list, but you must provide the <select ...>> and
</select> tags. If you provide a currency code, then it will be
marked as the currently selected option.
- defined( function )
- This function tests to see if the specified function is defined. This
can be used in conjunction with the "@include" meta command to create
optional "plug-in" functions.
- gettitle( filename )
- This function assumes that the filename you give it is that of an HTML
file, and it attempts to extract the title (the text that appears between
the <TITLE> and </TITLE> tags. If it can find a title in the
first 1K of the file, it returns it, otherwise it returns 0.
- hash( key, num )
- This function hashes the string "key" and returns a number between 0
and "num". The hash function used is fast and good for any value of "key"
and should generate a fairly even distribution.
- match( n )
- Returns the N'th match from a previous regular expression comparison.
For example, after the expression "TEST-123" ~= "([A-Z]*)-([0-9]*)",
match( 1 ) will equal "TEST" and match( 2 ) will equal "123". match( 0 )
always equals the entire string, in this example "TEST-123".
- precision( n )
- This function sets the default precision to use when outputting floating
point numbers.
- resolve( ip )
- Attempts to resolve the specified IP number and returns the host
name. If it is unable to resolve the IP number, it returns 0. For
example, resolve( "199.175.106.1" ) returns
"islandnet.com". Note that such lookups can sometimes take quite
a while and might slow down your program.
- sleep( seconds )
- This function causes the program to sleep, or pause, for the specified
number of seconds.
- soundex( string, len )
- Returns the soundex code for the specified string. Similar
sounding words will have the same soundex code. This is useful if you
need to compare two words where the spelling may be off. For example,
the soundex codes for "Morley" and "Morelay" are the same. The standard,
default, and minimum value for "len" is 4, but you can specify a higher
number (up to 10) if you want longer soundex codes.
- testurl( url )
- This functions attempts to access the specified URL to see if it is valid.
It returns an HTTP protocol status code to indicate what happened. If the
URL is good, then a status code of 200 is what you would expect. The status
code is returned as a number, not a string. Possible status codes and their
meanings include:
- 200 OK
- 302 Moved (usually because you forgot a trailing slash)
- 400 Bad Request
- 401 Unauthorized (ie: password protected)
- 403 Forbidden
- 404 Not found
- 500 Internal server error
A few special codes that are not part of the HTTP protocol include:
- 1 Unable to resolve host name
- 2 Unable to connect to host
Note that this only works for insecure URL's. If the URL begins with
an "https://" it will try and access it as an insecure url instead, which
may result in an error even though the URL itself may be valid. There is
currently no way to test secure URLs.
- varget( varname, index )
- This function allows you to retrieve the value of a variable. It is
the counterpart to the varset() function. The variable name must be
enclosed in double quotes.
- varexists( varname, index )
- This function is similar to varget(), except that instead of returning
the value of a variable it simply returns 1 if the variable is defined
and 0 if it is not. The variable name must be enclosed in double quotes.
- varset( varname, index, value )
- This function allows you to set a variable value. If you don't specify
an index, it is no different than using an equal sign to assign a value.
The variable name must be enclosed in double quotes. For example, the
following two lines are identical in function:
x = 10
varset( "x", 10 )
You can create an "array" by using one or more indexes. Currently there
is no way other than varset() to set an array element. For example you
can assign 3 different values to "x" in this way:
varset( "x", 1, 5 )
varset( "x", 2, 10 )
varset( "x", 3, 15 )
The variable "x" is now an array containing three elements numbered 1, 2, and
3. Each element has its own value. Unlike arrays in other programming
languages, elements do not need to be sequential. We could just have
easily created a three element array with 10, 20, and 50 as the indexes.
In fact, array index values do not even have to be numeric. These are also
valid arrays:
varset( "x", "john", 20 )
varset( "x", "paul", 40 )
varset( "x", "george", 60 )
varset( "x", "ringo", "drummer" )
Note that variable values may be numeric or string values. You can create
multi-dimensional arrays by specifying multiple indexes. If we wanted to
keep track of a Tic-Tac-Toe board we would want a 3x3 array. We might
initialize it like this:
x = 1
while x < 4
y = 1
while y < 4
varset( "board", x, y, " " )
y = y + 1
endwhile
x = x + 1
endwhile
We could then set the top left square of the Tic-Tac-Toe board like this:
varset( "board", 1, 1, "X" )
Or the bottom middle square like this:
varset( "board", 2, 3, "O" )
This function returns the value of the array element.
|