We put the Speed in!
   
 

1 The Moto Preprocessor

Even without making use of moto's programmatic constructs, the moto preprocessor can do away with much of the repetition involved in hand coding pages of HTML. It provides functionality for text file inclusion and macro substitution.

1.1 Text File Inclusion

#include(moto page)  

Just as in the C preprocessor the include directive is used to copy the contents of another file into a moto page at the point in the page where the directive is used. This directive may be used as a replacement for server side includes to include image maps or common web page navigation. Moreover, since file inclusion occurs in the preprocessor phase, included files can contain moto source code. The path to the include is relative to the including page or, if the path begins with a /, is relative to the file system root.

1.2 Macro Substitution

The moto preprocessor also has the capability to do macro expansion within moto pages. Macros are used like moto constructs in that they also begin with a dollar sign. This document uses macros to format each of it's examples. The example above was formatted by the following code:

$BEGIN_USAGE
   #include(path to include)
$END_USAGE
 

Macros may require arguments. These arguments need not (and often should not) be quoted as they will be substituted without modification where they are used in the macro definition. Argument lists are comma delimited thus if one argument contains a comma (or a close paren ')') it must be escaped with a backslash '\'. An example of a macro that takes arguments used in the construction of this document is the macro used for specifying section headers:

$BEGIN_SECTION("Macro Substitution")  

The #readdefs preprocessor directive makes the macros contained in a text file (called a macro library) available for substitution in the preprocessing phase.

#readdefs(path to macro library file)  

The path to the macro library can be relative to the page containing the readdefs directive or fully qualified from your root directory. Macro libraries have names ending with '.lib'. The rules for constructing a library file are as follows:

  1. Lines beginning with a pound sign '#' are ignored. These are comments in the library file.
  2. Lines beginning with text (without indentation) begin a macro definition. The first word on that line is the macro name.
  3. If the macro is to take arguments, the macro name should be immediately followed by an open paren '(', then a comma delimited list of argument names, and finally a close paren ')'.
  4. Lines beginning with white space are considered part of the current macro definition thus a macro definition ends when the file ends or the next macro definition begins.
  5. Macros may be used in the definitions of other macros but self referential macro calls are prohibited.
  6. A macro argument is used within the body of a macro as if it were another macro i.e. they are called by $macro argument name

The macro library used in the creation of this document looks like:

#
# Called at the beginning of a document, this macro sets up the variables
# needed to create and store the outline of that document
#

INIT_FORMAT
  $use("codex.util")

  $declare(int levelCounter)
  $declare(int chapNum = 0)
  $declare(Stack outline = new Stack())
  $declare(Vector curLevel = new Vector())
  
  $do(outline.push(curLevel))

#
# This macro should be called at the beginning of a section or
# or subsection with the header for that section or subsection. It
# will add the section header to the outline and compute and display
# the appropriate section / subsection number. It will also insert an HTML
# anchor tag so that this section may be linked to from the outline
# (autmatically generated by the DISPLAY_OUTLINE macro)
#

BEGIN_SECTION(section)

  $do(curLevel = <Vector>outline.peek())

  $do(curLevel.add($section))
  $do(curLevel.add(new Vector()))

  <h3>
     $for(levelCounter=outline.size();levelCounter>1;levelCounter--)
        $((<Vector>(outline.peekAt(levelCounter))).size()/2 +
          (levelCounter==outline.size()?chapNum:0)).
     $endfor
     $(curLevel.size()/2 + (levelCounter==outline.size()?chapNum:0))
        <a name="$($section)">$($section)</a>
  </h3>

  $do(outline.push(curLevel.get(curLevel.size()-1)))

#
# This macro should be called at the end of a section or subsection
#

END_SECTION $do(outline.pop())

#
# This macro is used to generate the HTML for a hyperlinked outline of
# a document marked up with the preceding macros
#

GENERATE_OUTLINE(outputFile)

  $declare(int curIndex = 0)
  $declare(IntStack istck = new IntStack())
  $declare(Stack ostck = new Stack())
  $declare(StringBuffer obuffer = new StringBuffer())

  $do(ostck.push(outline.peek()))
  $do(istck.push(0))

  $while(ostck.size() > 0 )

     $do(curLevel = <Vector>ostck.peek())
     $do(curIndex = istck.peek())

     $if(curIndex == curLevel.size() )
        $do(curLevel = <Vector>ostck.pop())
        $do(curIndex = istck.pop())

        $if(istck.size()>0)
           $do(istck.push(istck.pop()+2))
        $endif

        $continue
     $endif

     $for(levelCounter=istck.size();levelCounter>0;levelCounter--)
        $do(obuffer.append(istck.peekAt(levelCounter)/2 + 1))
        $do(obuffer.append('.'))
     $endfor

     $do(obuffer.append("<a href=\"docs"))
     $do(obuffer.append(istck.peekAt(istck.size())/2 + 1))
     $do(obuffer.append(".moto#"))
     $do(obuffer.append(<String>curLevel.get(curIndex)))
     $do(obuffer.append("\" onClick=\"return targetopener(this)\">"))
     $do(obuffer.append("<nobr>"))
     $do(obuffer.append(<String>curLevel.get(curIndex)))
     $do(obuffer.append("</nobr>"))
     $do(obuffer.append("</a><br>\n"))

     $do(istck.push(0))
     $do(ostck.push(curLevel.get(curIndex+1)))

  $endwhile

  $do(putFile($outputFile,obuffer.toString()))
 

2 The Moto Language

Moto is an embedded language. That means that any text file, HTML page, or XML document is by default a legal moto file. The contents of such a file would pass through the moto interpreter and print out unmodified. Moto actually does something when, in the process of parsing a file, it runs into a moto construct. These are special directives that begin with the character $.

2.1 Comments

To comment out a block of text you want moto to ignore, surround that text by $* and *$ . Unlike HTML comments, commented text will not appear in the output of either the moto compiler or interpreter.

$* comment *$  

2.2 Using the $ in Moto

To use the dollar sign $ in your moto file without what follows being interpreted as a macro or malformed moto construct you must escape it with a backslash

\$  

Note that backslashes not followed by a dollar sign are treated as literal and need not be escaped. Thus the code used to produce the previous example was

\\$  

2.3 Local Variables

Moto supports the use of local variables. Prior to use, a local variable must first be declared.

$declare(variable type variable name)  

The initial value of a variable may also be set at declaration time.

$declare(variable type variable name = initial value )  

You may not declare a variable with the same name more than once in a page. That means that you may not declare a variable with the same name in a macro that is used on the page or in a file that is included in the page. Unlike C, moto does not require all declarations to be at the beginning of a page , but it's still good practice.

The storage for local variables is lost after executing a page. Thus these variables are said to have a page lifetime. Variables declared within a loop or conditional block may not be used after (outside of) that conditional block or loop. Such variable have a scope lifetime.

Variables may be of basic types or object types. Basic types include:

double may be assigned any byte, char, int, float, long or double value
float may be assigned any byte, char, int, float, long or double value
long may be assigned any byte, char, int, float, long or double value. Moto longs are 64 bits in length thus the maximum and minimum values are 9223372036854775807 and -9223372036854775808 respectively
int may be assigned any byte, char, int, float, long or double value. Moto ints are 32 bits thus the maximum and minimum values are 2147483647 and -2147483648 respectively
byte may be assigned any byte, char, int, float, long or double value. Bytes are signed ints 8 bits long thus the maximum and minimum values are 127 and -128 respectively
boolean may be assigned true or false or the value of a relational expression
char may be assigned any character in sigle quotes '' including standard C escape characters such as '\n' '\r' or '\t'. It may also be assigned a value in hex or octal representation e.g. '\x41' == '\101' == 'A' as well as any numeric value
 

The char, byte, double, float, long, and int types collectively make up the supported basic numerical types. They can be combined to form expressions via the following operations:

A + B adds A and B together or converts one variable to a String and concatenates it to the other if the other is already a String.
A - B subtracts B from A
A * B multiplies A and B
A / B divides A by B. When B is 0 a division by zero exception will be thrown
A % B provides A mod B (only works if A and B are longs or ints
 

When numeric variables of different types appear in an expression, expanding casts are used so that the most precise answer is maintained (i.e. a long plus an int yields a long, an int divided by a float yields a float etc...). Only numeric variables and chars are implicitly cast, booleans are not. The set of boolean operators will be described in the section on conditionals.

The integral types byte, char, int, and long may also be acted on by bit manipulation operators

A | B Bitwise OR will turn any bit to 1 in the expression result that was 1 in either A or B. The corresponding bit in the result will be 0 otherwise
A & B Bitwise AND will turn any bit to 1 in the expression result that was 1 in both A and B. The corresponding bit in the result will be 0 otherwise
A ^ B Bitwise XOR will turn any bit to 1 in the expression result that was 1 in either A and B but not both. The corresponding bit in the result will be 0 otherwise
~A Bitwise NOT will turn any bit to 1 in the expression result that was 0 in A. Otherwise the corresponding bit in the result will be 0
A << B Left shift shifts the bits of A B bits to the left and fills the rightmost B bits with 0. The A << 2 would multiply A by 4
A >> B Right shift shifts the bits of A B bits to the right and fills the leftmost B bits with 0. The A >> 2 would divide A by 4
 

Object types are anything else. As a rule, all basic types begin with a lower case letter all object types begin with an uppercase letter. There is language level support for three types of objects :

String may be assigned a character string between double quotes ""
Regex may be assigned a regular expression between forward slashes /.../
Object may be assigned an object of any typed
 

The plus operator may also be used to append Strings together. When basic types are added to strings they are automatically converted to strings first.

Other types of objects become available via the $use keyword.

When creating a new object use the new keyword and then call that objects constructor

$declare(Hashtable htab = new Hashtable())  

Objects you create may need to be deleted later depending upon which memory manager you are using. This is done using the delete keyword.

delete htab  

All object types may also be assigned the special value null

$declare(Hashtable htab = null)  

The capital 'O' Object type is special in that it may be assigned a value of any other object type.

$declare(Object htab = new Hashtable())  

This is important for objects that are designed to store other objects such as Vectors or Stacks. There are no methods that can be called on a pure Object type. Rather, before an Object can be used it must be cast to the appropriate type.

$declare(Object obj = new Hashtable())
$declare(Hashtable htab = <Hashtable>obj)
 

2.4 Doing things

$do( expression )  

To call a function or assign a value to a previously declared variable use the $do construct. The following operators assign values to variables:

A = B The variable A is assigned the value of expression B
A += B If A and B are both numeric types the variable A is incremented by the result of expression B. If A is a String then the result of evaluating expression B is converted to a String and appended to A.
A -= B The variable A is decremented by the result of expression B (note that A and B must both be numeric types)
A *= B The variable A is multiplied by the result of expression B (note that A and B must both be numeric types)
A /= B The variable A is divided by the result of expression B (note that A and B must both be numeric types)
A++ The integer, long, byte, or char variable A is incremented by 1
A-- The integer, long, byte, or char variable A is decremented by 1
++A The integer, long, byte, or char variable A is incremented by 1
--A The integer, long, byte, or char variable A is decremented by 1
 

2.4.1 The Comma Operator

There are times when you might want to do 'more than one thing at once' . For this you can use the comma operator. The comma operator allows you to execute multiple expressions one after another as a single expression. The result and type of the compound expression is determined solely by the last expression executed:

$do(foo(),B=C,A=B)  

2.5 Output

$( expression)  

Read 'dollar print', this construct is used to output an expression or result of a function call. All non String expression results are converted to Strings prior to being output.

2.6 Conditionals

2.6.1 If construct

$if(condition)
   code to be executed if condition is true
$elseif(some other condition)
   code to be executed if other condition is true
$else
   code to be executed if previous conditions are false
$endif
 

As in other languages, the basic conditional statement consists of an opening if construct, followed by any number of else if conditions, followed by an optional else construct, then a mandatory endif. Unlike languages such as C however, conditions in moto must be booleans. The following comparison operators return boolean values:

A > B numeric variable A is greater than numeric variable B
A >= B numeric variable A is greater than or equal to numeric variable B
A < B numeric variable A is less than numeric variable B
A <= B numeric variable A is less than or equal to numeric variable B
A == B the value of basic variable A equals the value of basic variable B OR the reference variable A refers to the same object as the reference variable B
A != B the value of basic variable A does not equal the value of basic variable B OR the reference variable A does not refer to the same object as the reference variable B
A eq B the String variable A has the same content as the String variable B
A ne B the String variable A does not have the same content as the String variable B
A lt B The String A would come before B when sorted alphabetically
A gt B The String A would come after B when sorted alphabetically
A lte B The String A would come before B when sorted alphabetically OR A has the same content as B
A gte B The String A would come after B when sorted alphabetically OR A has the same content as B
A =~ B the regular expression B matches a substring of the String A
A !~ B the regular expression B does not match any substring of the String A
 

In addition the following operations can be used on boolean expressions to create more complex boolean typed expressions.

A && B Expression is true if and only if subexpressions A and B are true
A || B Expression is true if either subexpression A or B is true
!A Expression is true if subexpression A is false
 

Like C, short circuit evaluation is used when evaluating compound boolean operators.

2.6.2 Switch construct

$switch(expression)
   code for default case
$case(value 1)
   code for case 1
$case(value 2)
   code for case 2
$case(value 3)
   code for case 3
$endswitch
 

You can switch on any basic type expression as well as Strings. Unlike C, execution does not 'fall through' cases, rather the next case ends the previous. Another important difference from C is the lack of an explicitly specified default case. In moto, the default behavior is to execute whatever code is specified between the switch statement and the first case. The following example illustrates how switch statements are used to display the examples used in this document.

$use("codex.util")

$declare(String example = getFile("/content/moto/parse_example.moto"))
$declare(StringBuffer displayExample = new StringBuffer())

$declare(int i=0)
$declare(char lastchar = '\0')

$for(i=0;i<example.length();i++)
  $switch(example.charAt(i))
     $* default *$
        $do(displayExample.append(example.charAt(i)))
     $case('<')
        $do(displayExample.append("&lt;"))
     $case('>')
        $do(displayExample.append("&gt;"))
     $case('&')
        $do(displayExample.append("&amp;"))
     $case('\n')
        $do(displayExample.append("<br>\n"))
     $case('\t')
        $do(displayExample.append("&nbsp;&nbsp;&nbsp;"))
     $case(' ')
        $if(lastchar == ' ')
           $do(displayExample.append("&nbsp;"))
        $else
           $do(displayExample.append(' '))
        $endif
  $endswitch
  $do(lastchar = example.charAt(i))
$endfor

$(displayExample.toString())
 

2.6.3 The Ternary Operator

condition ? A : B  

Not a construct, but an operator, the ternary operator may be used to within an expression to return one of two same typed outputs. In the example above the expression returns the subexpression A if the specified condition evaluates true, B otherwise.

2.7 Loops

2.7.1 For loops

For loops in moto work very similar to for loops in C, C++, or Java.

$for(initialization;condition;increment)
   code to be repeated
$endfor
 

The initialization expression is executed prior to looping. It is used to set up the initial conditions for the loop itself. The condition expression is tested on each iteration of the loop (including the first iteration immediately after initialization). Unline C or C++ the condition expression must be a boolean expression. The increment expression is executed after each iteration of the loop. It is immediately after the increment expression is executed that the condtion is tested again. When the condition expression becomes false the loop terminates. For instance to execute a loop ten times you might write

$for(i=0;i<10;i++)
   code to be repeated
$endfor
 

This assumes the variable 'i' was declared prior to being used in the loop. Like Java a variable may be declared within the initialization expression.

$for(int i=0;i<10;i++)
   code to be repeated
$endfor
 

2.7.2 While loops

$while(condition)
   code to be repeated
$endwhile
 

Executes the code to be repeated while the boolean condition remains true.

2.7.3 Break and Continue

$while(condition)
   code to be repeated
   $if(some other condition)
      $break    $endif    more code to be repeated
$endwhile
 

Breaks out of the last open loops (continues after the next $endfor or $endwhile)

$while(1st condition)
   code to be repeated
   $if(2nd condition)
      $continue    $endif    code to be repeated only if 2nd condition is false
$endwhile
 

Returns to the first line of the most recently opened loop (and increments the counter in a for loop).

2.8 Re-Use Constructs

2.8.1 Moto Functions

To define a function in moto use the $define construct. In it you must specify the return type of the function (use the return type void if the function returns nothing). Follow the return type with the name of the function and then the arguments the function will take in parenthesis. The argument list should take the form type argument-name,type argument-name, ... for as many arguments as you have. You can specify an empty argument list.

$define(return-type name(argument list))
...
$return(expression)
...
$enddef
 

Function definition in moto must occur in the top scope. You cannot define a new function inside a condition, iterative, or scoping block. You can however use functions before they are defined within a moto page. Unlike C there is no need (and no way) to explicitly prototype functions before using them.

To return a value from a function use the $return construct. The type of the expression returned must however match the specified type of the function. $return must be inside a $define ... $enddef scope or else it is a syntax error.

You can specify multiple functions with the same name as long as they take a different number of arguments, or different argument types, or the same argument types in a different order.

Functions in moto do not normally have access to variables declared outside of them. Only variables declared as global before the function definition can be used within a moto function. Otherwise only arguments to that function and variables declared within the body of the function can be used. To declare a variable as global use the global type qualifier

$declare(global int statements=0)  

Like functions, globals can only be declared at the top level and are not allowed in nested scopes.

2.8.2 Moto Classes

A Class is used to aggregate data of different types into a new type and associate with that new type methods which act on the aggregated data. Once a class is defined, variables can be declared of type Class Name. These variables can then be assigned instances of the Class also called Objects.

Class definition must occur in the top scope. You cannot define a new Class inside a condition, iterative, function definition, or scoping block. A Class is defined with the following syntax:

$class(<class name>)
   <member variable declarations>
   <method definitions>
$endclass
 

Variable declarations inside a Class definition become member variables of that Class. Functions defined within Class Definitions become methods of the Class. Methods with the same name as the Class are called constructors. Constructors must not specify a return type.

Assignments to member variables at declaration time become part of the Class's Implicit Constructor. These assignments will take place whenever an instance of the Class is created. Class instances are created by using the 'new' keyword.

$declare(<class name> <var name> = new <class name>(<constructor arguments>))  

Three distinct operations occur when an Object is instantiated:

  • Storage is allocated for the Object
  • The implicit constructor is called assigning initial values to the Object's member variables
  • The explicit constructor (the constructor whose arguments match those passed in) is called to do further initialization of member variables.
If no no-arg constructor is explicitly defined then calling

$declare(<class name> <var name> = new <class name>())  

will still succeed and the implicit constructor alone will be called. If arguments are passed to the constructor then and explicit constructor with matching arguments must be defined

Member variables are retrieved using the dereference operator '.'.

$do( <variable name>.<member variable name> = <value>)  

Class member variables are used within method definitions by using the member variable's name. However, member variables may be shadowed within a method if the method takes an argument or declares a local variable of the same name. Even this case member variables can still be accessed by making use of the special variable 'this'. The value of the variable 'this' is always the instance of the class the method is being called on. Thus within a method definition the expression 'this.<member variable name> will return the specified member variable. The variable 'this' may not be shadowed or assigned to or re-declared as a local variable or argument.

Methods are called on Objects by using the dereference operator '.'.

$do( <variable name>.<method name>(<method arguments>))  

2.8.3 Extension Libraries

$use(extension)  

The $use construct provides access to extension libraries. These libraries, located on disk under the mx directory of your moto installation, provide definitions for a number of objects and functions. The extensions included with the moto distribution are

moto This extension library contains the definition for String objects as well as object wrappers for the fundamental types (Boolean, Character, Double, Float, Integer, and Long). This extension is used automatically by moto and does not need to be explicitly used in a moto page.
cstdlib This extension library makes a number of functions from the C standard libraries available to moto programmers
codex.util This extension library provides interfaces to the codex library of utility objects. These objects include : Enumeration, FileIO, Hashset, Hashtable, IntEnumeration, Inthashtable, IntSet, IntStack, ItoIHashtable, KMPString, Stack, StringBuffer, Stringset, SymbolTable, Tokenizer and Vector.
codex.http This extension library provides objects for session and state management in web applications, as well as basic function libraries for interoperating with the Apache webserver. The interfaces included are: Context, Session State, and HTTPRequest.
codex.io This extension library provides objects for interacting with a Posix file system. Objects included are: PosixFileSystem.
codex.db.mysql This extension library provides objects for interacting with a MySQL database. Objects included are: MySQLConnection and MySQLResultSet.
codex.db.pgsql This extension library provides objects for interacting with a Postgres database . Objects included are: PGConnection and PGResultSet.
 

The $use construct can only be placed in the top level scope of a moto page and may not be placed inside any conditional, iterative, or scoping block.

New extensions can be added by the creation of subdirectories under the mx directory. Objects may be added to an extension via the creation of an interface (.i) file for that object.

2.9 Arrays

In Moto, arrays are also considered a subclass of Object.

You cannot however instantiate an object of type "Array", rather you must declare and instantiate an array based upon the sub-type it stores.

$declare(int foo[] = new int[5])  

The above example declares an int array 'foo' and then allocates the storage for five ints with the new keyword

To get or set the value of of one of the indexes in the array you use the subscript operator '[' ']'

$do(foo[1] = 3)
$(foo[1])
 

All array indexes start at 0 so in the above example 0 through 4 would be valid indexes in the array 'foo'. If foo[5] was accessed at runtime an ArrayBoundsException would be thrown. Only integer typed expressions can be used for array access, thus in moto only expresions of type int or type long may be used.

If you know the contents of the array at declaration time you can specify it inline as follows.

$declare(int[] bar = {1,2,3})  

Note that the above example is really just shorthand for assigning the array 'bar' new int[3] and then setting the individual elements of that array to 1,2, and 3 from first to last. The allocation still occurs dynamically on the heap.

You can use similar syntax to construct instances of pre-defined arrays anywhere in your code. This is done using the cast operator.

$(new String(<char []>{'h','e','l','l','o',' ','w','o','r','l','d'}))  

Moto also allows for the declaration and instantiation of multi-dimensionsal arrays.

$declare(char bar[][] = new char [3][2])  

The above example declares the variable bar to be a two dimensional array of characters, then assigns to it a new two dimensional array for characters size 3 by 2. Multi-dimensionsal arrays in Moto work the same way they do in Java. Instead of allocating one Object of size dim 1 * dim 2 * dim 3 etc. multiple Objects are allocated so that the above new statement actually creates the following 4 Objects:

This allows the flexibility of declaring arrays where the dimensions of nested arrays are not equal (to represent adjacency lists for example)

$declare(char bar[][] = new char[3][])
$do(bar[0] = new char[3])
$do(bar[1] = new char[1])
$do(bar[2] = new char[2])
 

Since arrays are objects, sub-arrays of multi-dimensional Array may even correspond to the same Array

$declare(char bar[][] = new char[3][])
$do(bar[0] = bar[1] = bar[2] = new char[2])
 

Arrays are passed to Moto functions by reference. Thus moto functions may alter the values of array subscripts.

$define(void foo(int bar[]))
$do(bar[0] = 27)
$enddef

$declare(int maka[] = new int[3])
$do(foo(maka))
$(maka[0])
 

Therefore the above example would output '27'.

The length of any array may be retrieved at runtime with the length() function thus

$declare(char bar[][] = new char[3][])
$(length(bar))
 

would output '3' .

Arrays may be implicitly cast to Objects for the purposes of function calls. Moreover arrays of subclasses of Objects and multidimensional arrays may be implicitly cast / assigned to object arrays (Object[]).

Character and byte arrays have special handling in the moto language. Both may be output using the print $() construct. Both may be appended to Strings with the string addition operators. Both may be converted to Strings directly using the String constructor or the str() function.

2.10 Exceptional Conditions

Sometimes things go wrong at runtime. For instance a program might request input from a user that is used to subscript an array at a certain index, but the index is outside of array bounds. Or perhaps the array was never initialized and is null. Both of these errors may be checked for ahead of time in the code, but others are not so easy to check for ahead of time. For instance when a program performs a long database query and halfway through the connection to the database is severed. Or a program needs to wrtie a file to disk but the disk is full, or write permissions haven't been properly granted to the program. In these last two examples the condition that causes the error could either not have been checked for ahead of time, or there are so many possible reasons the action might fail that checking for all of them individually just isn't code efficient.

2.10.1 Exception Handling Basics

In all of these cases moto will throw an Exception . Throwing and exception is a lot like returning from a function early. However when an exception is thrown, the active functions or methods on the moto stack will keep returning until the Exception is caught or until there is no possible code left to catch them at which point an Uncaught Exception error will be displayed.

What this really boils down to is that if you have a treacherous piece of code that may throw an Exception at runtime, that you want to be able to deal with, you must wrap that code in a try-catch block. Take for example the array bounds case from earlier.

$declare(char bar[] = new char[3])
$do(bar[4] = 'd')
 

The above cade segment will surely fail since we are accessing an array index outside of declared bounds. However, were we to write the following :

$declare(char bar[] = new char[3])
$try
   $do(bar[4] = 'd')
   $("I did a bad thing")
$catch(Exception e)
   $("I caught an exception!")
$endtry
 

The above code will not fail but instead will output 'I caught an exception!' . It will not output 'I did a bad thing' because as soon as the exceptional condition occurred the program started looking for a catch statement that would handle it.

From the syntax of of the $catch statement you may have already guessed that Exceptions are a type of Object. The catch statement declares a local variable within the catch block that references the exception so that important information may be gleaned from it and perhaps presented to the user. In the previous example we declared the exception e to refer to the Exception that was caught. All exceptions have at least the following methods :

Method Description
Exception Exception() Constructs a new Exception object
Exception Exception(String message) Constructs a new exception object with the specified message.
String toString() Returns the type of the exception and any message included in the exception as a String
String getFile() Returns the name of the file from which the Exception was thrown
int getLine() Returns the line number of the file where the Exception occurred
String getStackTrace() Returns a string representation of the call stack as it was when the Exception was thrown
 

Re-writing the previous example to use these methods we have:

$declare(char bar[] = new char[3])
$try
   $do(bar[4] = 'd')
   $("I did a bad thing")
$catch(Exception e)
   $("I caught an exception!")
   $(e.toString())
   $(e.getFile()+":"+e.getLine())
$endtry
 

This program would output :

ArrayBoundsException : Attempt to subscript array outside of declared bounds
myfile.moto:3
 

Notice that the type of the Exception is ArrayBoundsException. Yet what we caught was just Exception. This works because all Exceptions are sub-classes of Exception so simply catching an Exception will catch all runtime exceptional conditions. If we had wanted too, than in the above catach we could have caught ArrayBoundsException specifically. Only rarely do you want to catch all possible types of Exceptions. Rather a program should catch only the Exceptions that the program can handle.

$declare(char bar[] = new char[3])
$declare(String foo = null)
$declare(boolean keepTrying = true)
$declare(int index = 4)
$while(keepTrying)
   $try
      $do(bar[index] = 'd')
      $(foo.length())
      $do(keepTrying = false)
   $catch(ArrayBoundsException e)
      $("I caught an ArrayBoundsException, better set index!")
      $do(index=2)
   $catch(NullPointerException e)
      $("I caught a NullPointerException, better set foo!")
      $do(foo="happy")
   $endtry
$endwhile
 

When either an ArrayBoundsException or a NullPointerException is thrown in the above example the program takes the action neccessary to make sure that they are not thrown again. It keeps looping until all the statements in the try block execute successfully. This program outputs :

I caught an ArrayBoundsException, better set index!
I caught a NullPointerException, better set foo!
5
 

What the above program demonstrates is that a program can and should take different actions depending on the exception that is thrown. It also makes use of the third type of built in moto exception. While most Exceptions are thrown from extension function or method calls, Moto code may throw the following types of Exception at runtime :

Exception The superclass for all other exceptions, when caught handles all other Exceptions
NullPointerException Thrown whenever an null array is subscripted or a method is called on a null object or a null object is dereferenced
ArrayBoundsException Thrown whenever an array is subscripted outside its declared bounds.
MathException Thrown whenever a numeric type is divided by zero.
 

2.10.2 Throwing Exceptions

Perhaps you have written some code that has it's own set of unique exceptional conditions and you want to throw your own exceptions. This is accomplished by first constructing a new Exception, and second throwing it with the $throw construct.

$throw(new Exception("You shouldn't have done that"))
 

You may also throw any of the Exception subtypes loaded from different extensions. A common exception you might throw is an IllegalArgumentException. It should be thrown when a function or method gets passed an argument that it is not designed to work with.

$define(String getAreaCode(String phoneNumber))
   $declare(Regex phoneRx = /[(]([0-9][0-9][0-9])[)][0-9][0-9][0-9][\-][0-9][0-9][0-9][0-9]/)
   $if(phoneNumber == null)
      $throw(new IllegalArgumentException("The phone number string provided may not be null"))
   $endif
   $declare(Match match = phoneRx.match(phoneNumber))
   $if(match.subMatch(1) == null)
      $throw(new IllegalArgumentException("The phone number provided is in an incorrect format"))
   $endif
   $(match.subMatch(1))
$enddef
 

2.10.3 Finally

Often times it is important to have operations that are guaranteed to take place regardless of the success or failure of the preceeding operations. A common example of this occurs when dealing with pools of objects. The methodolgy for using an object pool is to grab an object out of it, call some methods on that object, and when you're done, return the object to the pool. During the course of calling methods on the object an exception may be thrown. Some types of exceptions you might want to catch, others you might not. In all cases you want to make sure that the object gets returned to the pool. If it is not your program will have a resource leak.

To specify code to execute regardless of the success or failure of the code you're trying to execute you must use the $finally keyword.

$try
   code we want to try to execute
$catch(FooException f)
   code to be executed if a FooException got thrown
$catch(BarException b)
   code to be executed if a BarException got thrown
$finally
   code we want executed regardless of whether an exception occurred even if we caught it
$endtry
 

A finally block gets executed no matter what. If the try block is inside of a function call and the function returns from inside the try block or a catch block, the finally block will still get executed. If the try block is inside a loop and the break or continue statement is used, the finally block code will still get executed. If an exception gets thrown but not caught and passes through three different try-catch-finally blocks, the finally blocks of all three will be executed.

2.10.4 In Depth Exception Handling Semantics

The semantics of Moto Exception handling are the same as Exception handling in Java. An exception, once thrown will jump to the end of the most recently opened try block. Its type will be compared with the types of exceptions caught in any catch block opened after that try block. If its type matches than that exception is said to have been handled and the code for that catch block is executed. Regardless of whether the exception was handled or not, or whether or not there was an exception, the finally block code, if present, is then executed. If there was an exception thrown and it was not handled then once any finally block code has been executed the exception is re-thrown.

If an exception is thrown from within a catch block, and it is not handled (by way of a nested try-catch block) than that exception overrides the current exception. However exceptions thrown from within catch blocks are not compared with the types of Exceptions handleable by the current try-catch block. Rather the finally code is executed and the new exception is re-thrown.

If an exception is thrown from within a finally block, and it is not handled by way of a nested try-catch block, than that exception overrides the current exception if there is one and it is immediately re-thrown. If an exception is generated from within a finally block but is handled by that same finally block (by way of a nested try catch) but another exception had already been generated and not handled before entering the finally block, than after finally block execution the original exception is re-thrown.

If a break, return, or continue is generated from within a try block than the finally block is executed and the break, return, or continue action takes place. If however within the finally block there is a different sort of jump statement such as another break, return, or continue, or even an exception getting thrown, than that action overrides the action specified within the try block. If a break, return, or continue action is generated from within a catch block than it can still be overridden by an action in the finally block.

3 Embedded Block Syntax

Moto supports an additional, more compact syntax for embedding large 'blocks' of code into a page without worrying about whitespace treatment. This syntax may be used in addition to the single construct syntax described in the previous section.

3.1 Coding an Embedded Block

Embedded blocks begin with the escape sequence ${ and ends with }$. Inside and embedded block you can have multiple moto statements. Each statement must be terminated by a semicolon ';' .

${
   statement 1;
   statement 2;
   statement 3;
}$
 

3.2 Embedded Comments

To comment out a block of text you want moto to ignore from within an ebmedded block surround that text with /* and */ .

/* comment */  

You can also comment out all text until the next end of line by preceeding the comment with //

print "hello"; // this statement prints "hello"  

3.3 Variable Declaration

Inside of an embedded block you can declare variables just as you can in C or java

variable type variable name ( = optional variable value )  

The embedded block syntax for declarations is much more compact than with $declare()

${
  Date d = new Date();
  String month = getValue("_month",str(d.getMonth()+1));
  String day = getValue("_day",str(d.getDayOfMonth()));
  String year = getValue("_year","2002");
  int i;
  String curtok;
  Tokenizer stok = new Tokenizer("Jan|Feb|Mar|Apr|Mar|Jun|Jul|Aug|Sep|Nov|Dec",'|');
}$
 

3.4 Doing things in Embedded Land

Every statement inside an embedded block is essentially a $do() statement. Anything you would use a $do() construct for you can write as a statement inside an embedded block.

${String foo = "bar"; int l; l=foo.length() ; l++; foo=foo+foo; }$  

3.5 Embedded Output

${ expression;}$  

You can print something out from an embedded block statement by preceding your expression with the print keyword.

${print 7.00e+10 ;}$
${print 7.00E+10 ;}$
${print 7.00e-10 ;}$
${print 7.00E-10 ;}$
${print false; }$
${print 7.0F; }$
${print 7.0f; }$
${ print 7;}$
${
 print 7L;
 print "\n";
 print 7l;
}$
${print null;}$
${print "string";}$
 

3.6 Embedded Conditionals

3.6.1 Embedded If construct

If statements in embedded blocks work just like they do in C or Java

     ${
        String qryQuestions;
        if (idTopic eq "0")
           qryQuestions =
              "SELECT q.*,iu.imageURL,p.uname FROM "+
              "tblQuestion q LEFT OUTER JOIN tblImageURL iu ON q.idImageURL=iu.idImageURL "+
               ", tblPrincipal p WHERE p.idPrincipal=q.idOwner";
        else if (idTopic eq "-1")
           qryQuestions =
              "SELECT q.*,iu.imageURL,p.uname FROM "+
              "tblQuestion q LEFT OUTER JOIN tblImageURL iu ON q.idImageURL=iu.idImageURL " +
              "LEFT OUTER JOIN tblTopicToQuestion ttq ON ttq.idQuestion = q.idQuestion "+
              ", tblPrincipal p WHERE p.idPrincipal=q.idOwner AND ttq.idTopic is null ";
        else
           qryQuestions =
              "SELECT q.*,iu.imageURL,p.uname FROM "+
              "tblQuestion q LEFT OUTER JOIN tblImageURL iu ON q.idImageURL=iu.idImageURL " +
              ", tblTopicToQuestion ttq, tblPrincipal p WHERE ttq.idQuestion = q.idQuestion "+
              "AND ttq.idTopic = "+idTopic+" AND p.idPrincipal=q.idOwner";
     }$
 

There is no elseif keyword in embedded blocks, rather the else matches up with the most recent if

3.6.2 Embedded Switch construct

The switch statement works similar to switch in C or Java but like in the $switch() construct, cases do not fall through. Unlike the $switch() construct however, the embedded switch statement does make use of a default keyword. It must however follow all cases in the switch block.

${foo="bang";
 switch(foo){
    case "bar": print "baz";
    case "maka": print "ok";
    case "bling": print "bing";
    default: print "zip";
 }
}$
 

3.7 Embedded Loops

3.7.1 Embedded For loops

For loops in embedded blocks have the same syntax as they do in C

${for(i=0;i<10;i++) print "hello "+str(i)+"\n"; }$  

3.7.2 Embedded While loops

So do While loops

${i=0; while(i<10) print "hello "+str(i++)+"\n"; }$  

3.7.3 Embedded Break and Continue

Break and continue are used just like any other statement

Embedded while
${i=0;
  while(true)
     if (i<10)
        print "hello "+str(i++)+"\n";
     else
        break;
  print "goodbye\n";
}$
Embedded continue
${i=0;
  while(true) {
     if (i<10) {
        print "hello "+str(i++)+"\n";
        continue;
     }
     break;
  }
  print "goodbye\n";
}$
 

3.8 Embedded Scopes

Within embedded blocks you can create explicit variable scopes by using the '{' and '}' operators. Again this works just like it does in C or Java. Declarations inside an embedded scope only exist within that scope. For example the following piece of moto code

${
  int j = 1;
  {
     int j = 1;
     print ++j; print "\n";
  }
  print j;print "\n";
}$
 

Would output

2
1
 

From the above example you can see also that redeclaration of an existing variable inside an embedded scope shadows the previous declaration.

You can also use moto scopes to escape from embedded blocks allowing you to intersperse static text or classic moto constructs with your embedded block structured code

${ i=0;
  while(true)
     if (i<10) {
}$
hello $(i++)
${
     } else {
}$
           $break
${
     }
  print "goodbye\n";
}$
 

3.9 Embedded Functions

They syntax for defining a function in an embedded block is the same as it is in C or Java

type name(arguments){
    ...
    return expression;
}
 

The to use the global type qualifier, just preceed the variable declaration with the keyword global

global int i=0;  

The following example defines two functions and declares three global variables

${
  global Vector debugQueries = new Vector();
  global Vector debugQueryTimes = new Vector();
  global Vector debugQueryResults = new Vector();

  MySQLResultSet doQuery(MySQLConnection conn, String qry){
     MySQLResultSet r;
     long t;

     t=time();
     r = conn.query(qry);
     t=t-time();

     debugQueries.add(qry);
     debugQueryTimes.add(new Long(t));
     debugQueryResults.add(new Integer(r.size()));

     return r;
  }

  void doDebugQueries(){
     int i;
     for(i=0;i<debugQueries.size();i++){
        print "<p><pre>";
        print <String>debugQueries.get(i);
        print "</pre>\n";
        print "Results Returned: "+str((<Integer>debugQueryResults.get(i)).getValue()) + "<br>\n";
        print "Execution Time: "+str((<Long>debugQueryTimes.get(i)).getValue()) + "<br>\n";
     }
  }
}$
 

3.10 Embedded Class Definitions

The syntax for defining a Class in an embedded block is the same as it is in Java

class class name {
    member variable declarations
    method definitions
}
 

The following example defines two classes


${

   class Question {
      int idQuestion;
      String qText;
      int idImageURL;
      int level;
      String explanation;
      int numanswers;
      int answers[];
      int canswer;
      int numtopics;
      int topics[];
   }

   class QuestionManager {

      Question get(int idQuestion){
         int i;
         MySQLResultSet rset;
         
         Question q = new Question();
         
         rset = doQuery(conn,
            "SELECT q.* FROM tblQuestion q WHERE q.idQuestion = "+str(idQuestion));

         if(!rset.next())
            return null;
         
         q.idQuestion = idQuestion;   
         q.qText = rset.getString("qText");
         q.idImageURL = rset.getInt("idImageURL");
         q.level = rset.getInt("level");
         q.explanation = rset.getString("explanation");
         
         rset=doQuery(conn,
           "SELECT a.idAnswer, qta.isCorrect " +
           "FROM tblQuestionToAnswer qta, tblAnswer a WHERE " +
           "   qta.idQuestion = "+str(idQuestion)+ " AND " +
           "   a.idAnswer = qta.idAnswer " +
           "ORDER BY a.aText"
        );
        
        q.numanswers = rset.size();
        q.answers = new int[rset.size()];
        
        for(i=0;i<rset.size();i++){
            rset.next();
            q.answers[i]=rset.getInt("idAnswer");
           if(rset.getInt("isCorrect")==1)
              q.canswer=rset.getInt("idAnswer");
        }
        
        rset=doQuery(conn,
           "SELECT ttq.idTopic " +
           "FROM tblTopicToQuestion ttq WHERE " +
           "   ttq.idQuestion = "+str(idQuestion)
          );
          
          q.numtopics = rset.size();
          q.topics = new int[rset.size()];
          
          for(i=0;i<rset.size();i++){
            rset.next();
            q.topics[i]=rset.getInt("idTopic");
        }      
        
        return q;
      }   
   }
}$

 

3.11 Embedded Try-Catch-Finally blocks

The syntax for try catch and finally is the same as it is in Java

try { ... }
catch (NullPointerException npe) { ... }
catch (Exception e) { ... }
finally { ... }
 

The syntax for throw is the same as well

throw new Exception();  

4 Regular Expressions In Moto

Regular expression support is built into the moto language. Regular expressions in moto are specified by a forward slash '/', followed by the regular expression definition, followed by a forward slash. An example regular expression would be /([a-zA-Z]+)@(([a-zA-Z]+[.])*[a-zA-Z]+)/ which would match for simple email addresses. Regular expressions in moto have the type Regex. New regular expressions may be constructed dynamically from Strings by calling a constructor.

$declare(Regex emailrx = new Regex("([a-zA-Z]+)@(([a-zA-Z]+[.])*[a-zA-Z]+)"))  

The String used for creating a regular expression must not contain opening and closing slashes.

As of moto version 0.12.0 regular expression functionality is now implemented by a variant of Ville Laurikari's excellent TNFA matching algorithms.

4.1 Specifying Regular Expressions

Regular expressions are specified with their own min-language within moto. Standard moto operators do not apply or work differently when constructing regular epxressions. The operators currently available for use in specifying a regular expressions are :

+ one or more of the immediately preceding character or subexpression
* zero or more of the immediately preceding character or subexpression
? zero or one of the immediately preceding character or subexpression
. matches any single character
| matches the expression that comes before the | or the expression that comes after it
\ treats the following character as literal except for \n \r and \t which match newline, carraige return, and tab respectively
(...) designates a subexpression. The values of matched subexpressions may be retrieved after a match is made by calling methods on the Match object
[...] designates a set of acceptable characters (character class) e.g. [1234567890] would specify that any numeric character was accepted.

The - operator may be used inside a character class to specify a range of accepted characters e.g. [1-9A-Za-z] would specify all numbers and letters as acceptable.

Starting a character class with a ^ negates the class, matching all characters or ranges not specified within it.

The \ operation also works within character classes the same as it does outside of them.

 

4.2 Searching and Matching

As was noted earlier there are operators built into that can test whether a regular expression is found within a String.

A =~ B the regular expression B matches a substring of the String A
A !~ B the regular expression B does not match any substring of the String A
 

These operators are used for searching and only return true or flase as to whether some substring of A matched B.

To find out whether a regular expression matches a String or whether it mathes a prefix or suffix of a String one must use methods of the Regex object.

Method Description
boolean matches(String s) Returns true if the specified string is matched by this regex
boolean matchesPrefix(String s) Returns true if the specified string starts with a prefix that is matched by this regex
boolean matchesSuffix(String s) Returns true if the specified string ends with a suffix that is matched by this regex
boolean matchesSubstring(String s) Returns true if the specified string contains any substring that is matched by this regex. This method returns the same results as using the =~ operator.
 

These methods are valuable for input validation e.g. you request that a user input an email address and you want to verify that what the user entered is at least of the form of a valid email address.

4.3 Details of the Match

Often times however it is not enough to know that an input String matched or contained a regular expression. Often one is interested in the details of how the match occurred. This information includes where in the input String the match was found, how long the match was, and what the contents of the matched subexpressions were. This information is retrieved via Regex methods which return Match objects.

Method Description
Match match(String s) Returns a Match object for the specified string matched by this regex
Match matchPrefix(String s) Returns a Match object for the specified string is matched by this regex requiring only the a prefix of s matches
Match matchSuffix(String s) Returns a Match object for the longest suffix of s matched by this regex
Match search(String s) Returns a Match object for the leftmost longest match of this regex in s
 

With a Match object in hand one can call methods on that object to return the relevant details of the match.

Method Description
String Match::subMatch(int i) Returns the substring of the matched string corresponding to the i'th subexpression of the regular expression used. The i'th subexpression is the subexpression started with the i'th opening parenthesis in the regular expression. Passing 0 to this method will return the entire string matched
String preMatch() Returns the substring of the String matched against occurring prior to the start of the match
String postMatch() Returns the substring of the String matched against occurring after the end of the match
int startIndex(int i) Returns the index in the String matched against where the i'th subexpression began. If i is set to 0 this method returns the index in the original String where the match begins
int endIndex(int i) Returns the index in the String matched against where the i'th subexpression ends. If i is set to 0 this method returns the index in the original String where the match ends
 

In the following example a Match object is used to pick out the pieces of an email address found in a string of text. The subexpressions of interest in this case are the name and the host in the email address.

${
   Regex rx = /([a-zA-Z]+)@(([a-zA-Z]+[.])*[a-zA-Z]+)/;

   String i2 = "email me at dhakim@webcodex.com!";
   Match m = rx.search(i2);
   print "Match was '"+m.subMatch(0)+"'\n";
   print "Name was '"+m.subMatch(1)+"'\n";
   print "Host was '"+m.subMatch(2)+"'\n";
   print "Pre-match was '"+m.preMatch()+"'\n";
   print "Post-match was '"+m.postMatch()+"'\n";
   print "Match was found at <"+m.startIndex(0)+","+m.endIndex(0)+"> in the input string\n";
}$
 

The output of this example is

Match was 'dhakim@webcodex.com'
Name was 'dhakim'
Host was 'webcodex.com'
Pre-match was 'email me at '
Post-match was '!'
Match was found at <12,31> in the input string

 

4.4 String Manipulation with Regular Expressions

The most powerful uses of regular expressions are for String manipulation. String manipulation with regard to regular expressions usually refers to two main activities :
  1. Using regular expressions to split a string wherever a matching pattern is found. This is known as tokenizing or splitting a string.
  2. Replacing all instances of a pattern in a String with something else. This is known generally as substitution.

4.4.1 Tokenizing with Regular Expressions

Suppose you have an input string that you want split by some pattern. Lets take as an example a string containing a numbered list of elements. The way you would do this in moto is by constructing a Tokenizer object from the input string and pattern. The pattern for a number followed by a period would be /[0-9]+\./ . Calling the next() method on the Tokenizer will return the next substring of the input string that does not contain the specified pattern. Calling next() repeatedly will continue doing this up until there are no further such substrings at which point next() will return null.

${
   use "codex.util";

   Regex rx=/[0-9]+\./;
   String s="1. foo 2. bar 3. maka";

   Tokenizer t= new Tokenizer(s,rx);
   String c;
       
   for(c=t.next();c != null;c=t.next())
      print "got '"+c+"'\n";
}$
 

The output of this program would be

got ' foo '
got ' bar '
got ' maka'

 

4.4.2 Pattern Substitution

Regular expression substitution is much more powerfull than the 'find and replace' functionality found in most word processors for two reasons:
  1. Patterns are matched as opposed to static strings.
  2. The substitution can make use of submatch information.
The following are some common examples of how substitution by regular expressions are used
  1. Escaping HTML
  2. Auto-markup of URLs
  3. Emoticonizing
  4. Colorizing source code
  5. Implementing find and replace
  6. Starring out dirty words
Most but not all of these examples can be accomplised by using the built in function sub(). The sub() function takes three arguments. The first is the input string. the second is pattern in the string we want to replace. The final argument is a substitution string. Thus if I wanted to replace all instances of the word "foo" with "bar" in my input string I would do that as follows :

$do(sub(input,/foo/,"bar"));  

A more usefull example would be using sub() in a function to escape reserved HTML characters.

   String st_escapeHTML(String input){
      return sub(sub(sub(input,/&/,"&amp;"),/>/,"&gt;"),/</,"&lt;");
   }
 

The sub function is capable of far more complex substitutions however because the substitution string can itself refer back to last match made. This is done by including variables in the substituion string of the form $# where # is the number of the subexpression in the regular expression you wish to substitute. $0 will substitute the entire last match. A concrete example of when to use this functionality is when doing auto-markup. Auto is the process of finding hyperlinkable strings in text and generating the HTML code around those strings to link them.

${ {
       Regex rx = /([a-zA-Z]+)@(([a-zA-Z]+[.])*[a-zA-Z]+)/;
       String substitution = "<a href=\"mailto:$0\">$1 at $2</a>";

       String input = "dhakim@webcodex.com is my email, my email is dhakim@webcodex.com";

       print "'"+input+"'"; print " =>\n\t"; print sub(input,rx,substitution); print "\n";

} }$

 

This script outputs :

'dhakim@webcodex.com is my email, my email is dhakim@webcodex.com' =>
   <a href="mailto:dhakim@webcodex.com">dhakim at webcodex.com</a> is my email, my email is <a href="mailto:dhakim@webcodex.com">dhakim at webcodex.com</a>


 

5 Higher Order Programming In Moto

In Moto, functions and methods have types and may be assigned to variables of the same types. These 'functional' variables may themselves be treated as functions. Thus functions and methods may be passed as arguments to other functions or methods. Functions may even be returned from other functions or methods. New functions can even be constructed at runtime by 'applying' some or all of the arguments of existing functions.

5.1 Implicitly Valid Types

Arrays are the simplest example of implicitly valid types in Moto. Given a valid type X, X[] is a valid type in Moto. Specifically X[] represents an array of X's . And X[][] is a type representing a two dimensional array of X's. This sort of dynamic type validation is common to many languages including Java.

There is another class of types in Moto that are 'implicitly valid' as long as their base types are valid. These are called functional types which can be described as follows:

  1. If X is a valid type X() is a valid type representing a function which takes no arguments and returns a value of type X
  2. If X and Y are valid types X(Y) is a valid type representing a function which takes an argument of type Y and returns a value of type X
  3. If X is a valid type and Z is comma delimited list of valid types than X(Z) is a valid type representing a function which takes arguments of the types listed in Z and returns a value of type X

Here are some concrete examples of declarations using functional types:

   int() f; // f can be assigned a function which takes no arguments and returns an int
   int(int) g; // g can be assigned a function which takes an int and returns an int
   int(int,String) h; // h can be assigned a function which takes an int and a String and returns an int
   int(int()) i; // i can be assigned a function which takes a function that takes no arguments but returns an int. i must also return an int.
   int(Vector(int),String()) j;
   Enumeration(StringBuffer(int),String())(String(),float) k;
   Object(int[](StringBuffer[][]),String())(String[](),float[]) l;
 

5.2 Functional Typed Variables

As you might have guessed by the name (and the above examples) functionally typed variables can be assigned real functions or methods who's arguments and return types match. Consider to the function atoi in cstdlib which takes a String and returns an int. We could define a functional variable 'myatoi' and assign it atoi:

int(String) myatoi = atoi;  

Functional variables can be called just like regular functions and methods.

int i = myatoi("3");  

5.3 What is the 'type' of a Function?

The type of a function or method in Moto is

  • The function or method's return type
  • followed by '('
  • followed by the types of each of the arguments it takes separated by commas
  • followed by ')'

Simple ... no ?

5.4 Function Identification

The atoi example is simple in that there is only one function in the system named atoi. Moto however, like C++ and Java, allows for multiple functions to have the same name but take different arguments. A good example of this is the getValue function from the codex.http library. There are two variants of getValue, one that takes one argument, and one that takes two. We can differentiate between the two by using the '?' or 'unknown argument' token.

String(String) myGetValue = getValue(?);
String(String,String) myGetValueWTwoArgs = getValue(?,?);
 

We can be even more specific by using casts in addition to the '?' token. Suppose we have two functions with the same name that take a single argument (but of two different types) :

void println(int i){ print i+"\n"; }
void println(String s) { print s+"\n"; }
 

We can specify which one we want to identify by casting the unknown:

void(int) myIntPrintln = println(<int>?);
void(String) myStringPrintln = println(<String>?);
 

The last thing worth noting here is that you can optionally use the '&' operator to make clear that you want to identify a function. The following are examples of fully qualified function identification:

void(int) myIntPrintln = &println(<int>?);
void(String) myStringPrintln = &println(<String>?);
 

The real reason for the '&' becomes clear in relation to partial application discussed later. For the sort of regular function identification that has been described using the '&' or 'function identification' operator can improve code readability but is generally optional. The only case where it is necessary is when we have multiple variants of a function with the same name and we need to identify the no-arg variant:

void println(int i){ print i+"\n"; }
void println(String s) { print s+"\n"; }
void println(){ print "\n"; }

void() myPrintln = println; // No good ... this is ambiguous
void() myPrintln = &println(); // Perfect ... this is fully qualified identification
 

5.5 Functions and Methods that take Functions as Arguments

Since functional types are no different from other types, creating functions that take functions as arguments is done just like you might suspect. The following function takes an array of Strings and a function to perform on each element of the array:

void each(String[] a,void(String) f){ for (int i=0;i<length(a);i++) f(a[i]); }  

We could pass this function a function println

void println(String s) { print s+"\n"; }  

To print out all the elements in an array of Strings :

each({"one","two","three"}, println);  

The Enumeration class has an each() method built in which calls the function passed to it on each element in the enumeration. Thus to print out all the keys in a hash you could now just write

stab.keys().each(<void(Object)>println);  

This is as opposed to

Enumeration e = stab.keys();
while(e.hasNext())
   println(<String>e.next());
 

Which is the 'non-functional' (Java) way of doing things.

Notice the explicit cast to type 'void(Object)' in the functional example . That is needed because that is the type of the function the each method expects to be passed while println has type 'void(String)'. Sometimes functions can be cast 'implicitly' but this is not one of those times.

No example of passing functions to functions would be complete without the classic example of sorting. Vectors have a sort() method. This method takes a function which can be used to compare two Objects in the Vector. Why does it need to take a function you ask ? Because there is no way to compare two arbitrary objects.

The function must take two Objects and return 0 if they are equal, 1 if the first one is 'greater' than the second, -1 if the first one is 'less' than the second. What 'less','greater', and 'equal' really mean in this context is that you want the the first element to appear before, after, or next to the second element in the final sorted list.

Luckily the is a function that does just that for Strings in the cstdlib extension called strcmp.

Thus to sort a Vector of Strings in Moto all you need to do is say

v.sort(<int(Object,Object)>strcmp)  

Again we need to explicitly cast strcmp to 'int(Object,Object)' from 'int(String,String)' . The reason is that the Vector doesn't know it's holding Strings. For all it knows it's holding Dates or any other kind of Object and so it expects functions that work on 'Object's and not sub-classes of Object. If it were holding Dates however you could sort them as follows:

int dcompare (Object a,Object b){
   Date l = <Date>a, r=<Date>b;
   return atoi(l.format("%Y%m%d")) - atoi(r.format("%Y%m%d")) ;
}
v.sort(dcompare);
 

5.6 Implicit Casting Rules

You don't need to explicitly cast functions (or functionally typed expressions) when assigning them or passing them to functions when they can be implicitly cast. The implicit casting rules for functional types are as follows:

  1. Like all reference types, (yes, functional types are reference types) values that have functional types can be implicitly cast to 'Object'.
  2. Any type X(...) can be implicitly cast to void(...) since 'void' really means we don't care what if anything the function returned.
  3. Any type X(...) can be implicitly cast to Y(...) as long as X is a descendent of Y. The reason is if we have a function foo, which for the sake of argument takes no arguments and returns a String, and we assign it to a variable of type 'Object()' that assignment should be valid since everything foo could return would also be an Object.
  4. Any type X(... Y ...) can be implicitly cast to X(... Z ...) as long as Y is an ancestor of Z. Suppose we have a variable of type 'void(String)'. This functional variable must be callable with any String. If we assigned to it a function of type 'void(Object)' than the requirement that 'any function assigned to it must handle all values of type String' is not broken. The function we assigned to it can handle all Strings and then some.

5.7 Explicit Casting Rules

The explicit casting rules for functionally typed expressions are like the implicit casting rules and their mirror image.

  1. If X can be implicitly cast to Y then X can be explicitly cast to Y
  2. If X can be implicitly cast to Y then Y can be explicitly cast to X

5.8 Partial Application

In cstdlib there is a function pow

double pow(double x, double y)  

which returns x to the power y (xy). Suppose we wanted to define a function square() which squares (x2) its input. We could say:

double square(double x) { return pow(x,2); }  

Or we could do this:

double(double) square = pow(?,2);  

What we've done is created a new function by partially applying the arguments to a function. We could partially apply the other argument to create a function twoToThePow (2x)

double(double) twoToThePow = pow(2,?);  

We could even apply both arguments to give us a function that returns the same thing all the time:

double() nine = pow(3,2) // No no no ... this won't work  

The above actually generates an error saying 'Expression of type double cannot be assigned to variable of type double()' . That's because moto thinks the expression 'pow(3,2)' is a function call, not a function identifier. To clarify the situation you need to use the '&' operator.

double() nine = &pow(3,2) // Bingo!  

5.9 Callbacks

Suppose we have a Vector v. We can say

void(Object) add = v.add;  

The above defines a new function add() which, every time it is called, adds an Object to v. This is actually a powerful example of partial application. Behind the scenes all methods secretly take the instance of the object they are called on as an argument. By identifying 'v.add' we are saying we want the 'add method on the Vector currently assigned to v'. If v were to be assigned a different vector later on the add function we just defined would still add objects to the original Vector.

So what makes this so powerful ? Lets look at some examples

// Cloning a Vector
v1.elements().each(v2.add);

// Pruning a Vector of duplicates
Stringset s1 = new Stringset()
v1.elements().each(<void(Object)>s1.add);
s1.elements().each(v2.add);

// Printing out the elements in a hash (SymbolTable)
void outputNV(Object n,SymbolTable s) { print <String>n +" => "+<String>s.get(<String>n)+"\n"; }
stab.keys().each(outputNV(?,stab));

// Inverting a hash
void valueToKey(Object oldkey, SymbolTable src, SymbolTable dest) {
   dest.put(<String>src.get(<String>oldkey),oldkey);  }
SymbolTable namesur = new SymbolTable();
surname.keys().each(valueToKey(?,surname,namesur));
 

6 Overloaded Operators In Moto

As in C++, operators in moto can be overloaded giving moto programmers concise semantics for expressing common operations on objects. When an operator for a class is overloaded moto programmers can write code using operators that expands behind the scenes to function and method calls. For example the moto code A[0]=B+C may be used as short hand for A.setAt(0,union(B,C)) depending on the types of the variables A,B, and C.

The String class is an example of a moto class that makes use of operator overloading. String addition with the + and += operators, or String comparison with the eq, ne, lt, gt, lte, and gte operators is not built in to the moto language. Rather it is implemented through the use of overloaded operators.

The moto utility classes (from the moto.util) extension make the widest use of this facility. You can set and retrieve objects from vectors and hashes using array notation. You can union or intersect sets using the + and * operators. You can even compare the contents of most any two objects of the same type with the 'eq' and 'ne' operators.

6.1 Arrays, Vectors, and Hashes

A primary use of overloaded operators is to make commonly performed operations on commonly used objects appear 'first class' in the language. This is the case with Vectors and Symboltables (hashes). This is due to their relation to Arrays.

Arrays are a first class feature of most all programming languages. Thus they are operated on by operators. Specifically, the [] and []= operators are used to set and get elements in an array.

$do(my_array[13] = "foo")
$return(my_array[27])
 

Vectors (from the codex.util extension) are just like arrays except they are not bounded and can grow as new objects are added to them. In both Java and Moto a Vector's contents can be set and retrieved through methods:

$do(my_vector.set(13,"foo"))
$return(my_vector.get(27))
 

However since a Vector is so much like an Array it makes sense that it should be accessible with the same concise operator syntax. Because of operator overloading, in Moto you can treat a Vector like an array using the very same syntax:

$do(my_vector[13] = "foo")
$return(my_vector[27])
 

SymbolTables are also a lot like arrays except they are unbounded and have keys that are Strings. But since they are so much like arrays it once again makes sense that programmers should be able to access them with the same semantics:

$do(my_symboltable["foo"] = "bar")
$return(my_symboltable["maka"])
 

6.2 Finding Overloaded Operators

You can find out what operations are overloaded for a particular class by looking at the class's interface. In the 'Method operators' and 'Related Functions operators' sections you will find all the overloaded operators for class:

StringSet
Method operators
StringSet StringSet::+=(StringSet i)

Returns the union of two StringSets

StringSet StringSet::*=(StringSet i)

Returns the intersection of StringSet i1 and StringSet i2

StringSet StringSet::-=(StringSet i)

Returns the difference StringSet i1 and StringSet i2

Related Functions operators
StringSet +(StringSet s1,StringSet s2)

Returns the union of two StringSets - {x:x is in s1 or x is in s2 }

StringSet *(StringSet s1,StringSet s2)

Returns the intersection of two StringSets - {x:x is in s1 and x is in s2 }

StringSet -(StringSet s1,StringSet s2)

Returns the difference StringSet i1 and StringSet i2 - {x:x is in s1, x is not in s2}

What the above interface is saying is that there are six overloaded operations having to do with StringSets. The + and += operations have been overloaded to mean set union when applied to StringSets. The * and *= operations have been overloaded to mean set intersection . The - and -= operations have been overloaded to mean set difference .

6.3 The difference between == and eq

There is a difference between an between an Object having the same content (or contents) as another object, and two variables referring to the same object.

If one were to create two vectors and add the String "foo" to both of them they would be equal in the sense that they are both vectors of size 1 with the String "foo" inside of them.

Vector v1 = new Vector();
Vector v2 = new Vector();
v1.add("foo");
v2.add("foo");
print v1 eq v2; // outputs true
print v1 == v2; // outputs false
 

However vectors v1 and v2 in the above example are not the same object. They have seperate storage in memory and can be altered independantly of one another. If however we re-wrote the above example as

Vector v1 = new Vector();
Vector v2 = v1;
v1.add("foo");
v2.add("foo");
print v1 eq v2; // outputs true
print v1 == v2; // outputs true
print v1.toString() // outputs {"foo","foo"}
 

Then v1 and v2 would be reffering to the same object. In this example only one object was ever created. Adding "foo" to v1 and then adding "foo" to v2 added two "foo"s to the same Vector!

This is the difference exposed by the == and eq operators. The eq operator will output true if two objects are equal, the == operator will output true if its operands are two references to the same object.

For this reason the == and != operators are never overloaded since there meaning is already well defined for all classes of objects. However the eq operator is overloaded for most every type of object and can be used to tell if the contents of two objects are equal.

7 Interacting with Apache

Both the moto module, and any of your own moto applications that you compile with mmc, run as dynamically loaded modules within the apache webserver. Thus they may be configured by modifying the httpd.conf file, they access HTTP Requests and Responses , they can parse HTTP headers and form submissions for cookies and file upload, via included APIs. To make use of these APIs from within your moto pages you must

$use("codex.http")  

7.1 Configuring Modules

Both the moto module, and any moto application compiled with mmc, may be configured in your httpd.conf . Basic configuration of your httpd.conf is necessary just to load the moto module:

LoadModule moto_module libexec/mod_moto.so
AddHandler moto .moto
 

Or to load a compiled moto module

LoadModule histoexam_module libexec/mod_histoexam.so
<IfModule mod_histoexam.c>
   <Location /histoexam1>
       SetHandler histoexam
       HistoexamOption Location /histoexam1
   </Location>
</IfModule>
 

In the above example there is an Apache directive you probably haven't seen before

HistoexamOption Location /histoexam1  

All compiled modules get a new directive that can be used to pass configuration information into the module. The directive is {Module Name (with the first letter capitalized)} + 'Option' (hereafter reffered to as ModOption) . Using a ModOption directive you can pass arbitrary configuration parameters into your module. In the above example the parameter 'Location' is being set. This parameter is present in all compiled moto modules and allows for them to be relocated elsewhere in your website. You can use ModOptions to set an arbitrary number of different parameters and just like other Apache directives, parameters nested within Location or Directory blocks take precendence over those outside and apply only inside those Directory or Location blocks.

<IfModule mod_iolio.c>
  IolioOption SharedHeapSize 128M
  <Location /iolio2 >
     SetHandler iolio
     IolioOption Location /iolio2
     IolioOption DBName iolio1
     IolioOption DBUser maka
     IolioOption DBPassword shlaka
  </Location>

  <Location /iolio3 >
     SetHandler iolio
     IolioOption Location /iolio3
     IolioOption DBName iolio2
     IolioOption DBUser foo
     IolioOption DBPassword bar
  </Location>
</IfModule>
 

To set parameters for the moto module (or for your application while it's still in development) use the directive 'MotoOption'.

<IfModule mod_moto.c>
  MotoOption SharedHeapSize 128M
  MotoOption SignalsThrowExceptions true
  AddHandler moto .moto

  <Location /iolio >
     MotoOption DBName iolio
     MotoOption DBUser root
     MotoOption DBPassword macamaca
  </Location>
</IfModule>
 

To access options set through this mechanism in your moto application use the function getConfigOption().

$* Set up the database connection *$

$declare(MySQLConnection conn = new MySQLConnection(
  "",
  getConfigOption("DBName"),
  getConfigOption("DBUser"),
  getConfigOption("DBPassword")
))
 

What follows is a list of configuration options that are built in to either the moto module or compiled modules

Directive Valid For ScopeDescription
Location mmc compiled modules location or directory block Sets the path prefix that pages within the compiled moto directory expect prior to the page name in the URL
SharedHeapSize mod_moto and mmc compiled modules global Sets the size of the shared heap.
SignalsThrowExceptions mod_moto and mmc compiled modules global Catches SIGSEGV and SIGBUS if raised during page interpretation and re-throws them as exceptions.
MXPath mod_moto global Lets you specify the paths that the moto interpreter will search for moto extensions. The value should be a ':' delimited list of paths.
LockDir mod_moto and mmc compiled modules global Lets you specify the directory that the .lock files used for concurrency control by the memory manager and context will be dropped off (the default is /tmp)
Session.Disable mod_moto and mmc compiled modules location or directory block Lets you turn off session tracking for location in which the directive applies.
Session.SetSSIDCookie mod_moto and mmc compiled modules location or directory block Lets you identify the current session via a cookie stored on the client browser. If the sid state variable is also present than the session identified by the sid state variable takes precedence.
Session.MatchSSIDCookie mod_moto and mmc compiled modules location or directory block If the sid state variable is also present in the URL then both sid and the ssid must agree thus providing a limited defense against 'session hijacking'. This option is only usefull in combination with the Session.SetSSIDCookie option.
Session.MatchClientIP mod_moto and mmc compiled modules location or directory block Including this option means that all requests for a given session must come from the same IP address that started the session thus providing a limited defense against 'session hijacking'.
Session.Timeout mod_moto and mmc compiled modules global Specifies the number of seconds of inactivity before a session will be 'timed-out'.
 

7.2 Inspecting the HTTP Request

Moto currently has basic support for letting you inspect the HTTPRequest. You get the request by calling the getRequest() function defined in codex.http. Once you have it you can call a variety of methods on it.

Method Description
String getHostname() Returns the hostname of the requested URL
String getURI() Returns the path part of the URL (after the host name but before the ?)
String getFileName() Returns the full path on disk of the reuested page
String getMethod() Returns the method by which the page was requested e.g. "POST" or "GET"
String getProtocol() Returns the protocol by which the page was requested e.g. "HTTP/1.1"
String getHeader(String header) Returns the value of the specified header e.g. getRequest().getHeader("User-agent") might return "Mozilla/4.5 (compatible; OmniWeb/4.1-beta-1; Mac_PowerPC)"
Cookie getCookie(String name) Returns the Client Side cookie with the specified name
Enumeration getCookies() Returns an enumeration of all the cookies that were parsed from the HTTPRequest
Enumeration getMIMEParts() Returns an enumeration of all the 'MIMEEntity's submitted to this page. Mime parts get submitted on file upload forms (or any form with enctype="multipart/form-data")
MIMEEntity getMIMEPart(String name) Returns the MIME part with the specified name. Mime parts get submitted on file upload forms. This function can be dangerous if you've specified a form with two fields named the same. This function will get you the first one only.
 

7.3 Getting and Setting Cookies

Moto supports the setting and retrieval of client side cookies. You can set a cookie by creating a new cookie object, setting the required fields, and finally calling setCookie on the HTTPResponse.

$declare(Cookie cookie = new Cookie())

$do(cookie.setName("maka"))
$do(cookie.setValue("shlaka"))
$do(cookie.setVersion("1"))

$declare(HTTPResponse res = getResponse())
$do(res.setCookie(cookie))
 

Once set, you may retrieve a cookie by name on subsequent pages views by calling the getCookie() method on the HTTPRequest object, or you can enumerate through all the cookies the client submitted via the getCookies() method

$declare(Enumeration cookies = getRequest().getCookies())
$while(cookies.hasNext())
  $declare(Cookie cur = <Cookie>cookies.next())
  <li>Got cookie: $(cur.toString())
$endwhile
 

With a cookie in hand you can inspect any of it's relevant fields (though only version,path and domain may get set when a cookie is transmitted from the browser back to the server

<pre>
Cookie Name      : $(cookie.getName())
Cookie Value     : $(cookie.getValue())
Cookie Domain    : $(cookie.getDomain())
Cookie Version   : $(cookie.getVersion())
Cookie Path      : $(cookie.getPath())
Cookie Comment   : $(cookie.getComment())
Is Cookie Secure : $(cookie.isSecure())

Cookie : $(cookie.toString())
</pre>
 

7.4 Multipart MIME Support

When users submit a form with enctype="multipart/form-data" they are actually submitting a multipart mime message to the webserver.

  <form method=post enctype="multipart/form-data">
      File: <input type="file" name="uploaded_file" size="30" /><br>
      <input type="submit">
  </form>
 

By filling the form input field with type=file, a user can upload a file to a webserver. This file may then be parsed out of the HTTPRequest on the next page. It's contents will be maide available to the moto page in a MIMEPart named with whatever name the form field was given.

  $if(getRequest().getMIMEPart("uploaded_file") != null &&
      getRequest().getMIMEPart("uploaded_file").getBodyLength() > 0)
     $do(
        putFileBytes(
           "/usr/local/wa/dhakim/httpd/htdocs/foo.gif",
           getRequest().getMIMEPart("uploaded_file").getBody(),
           getRequest().getMIMEPart("uploaded_file").getBodyLength()
        )
     )
  $endif
 

It's possible to present users with multiple file upload or other form fields. These will all be submitted as MIME parts. You can iterate over all submitted mime parts using the getMIMEParts() method of HTTPRequest. You can also inspect the mime headers associated with each part.

  Parts Sent:
  <ul>
     $declare(Enumeration parts = getRequest().getMIMEParts())
     $while(parts.hasNext())
        $declare(MIMEEntity curPart = <MIMEEntity>parts.next())
        <li>$(curPart.getName())
        <ul>
            <li><b>filename</b> : $(curPart.getFileName())
            <li><b>content type</b> : $(curPart.getContentType())
            <li><b>content transfer encoding</b> : $(curPart.getContentTransferEncoding())
            <li><b>body length</b> : $(curPart.getBodyLength())
        </ul>
     $endwhile
  </ul>
 

Regular forms (forms without the enctype set to multipart/form-data) do not submit their contents as multipart mime messages. An explanation of how values sent through those forms are retrieved is dealt with in the following section on state management.

8 Basic State Management

State management in moto allows for persistence of information in the Context, Sessions and States.

The Context and the Session store <Object>s. The Context stores objects that are global, may be set, updated and retrieved from any page, and never expire unless explicitly removed from the Context and deleted. The Session stores objects that are needed only for one user's Session and expire when that user's Session expires. The State stores variables passed in the URL or submitted via HTML form submissions (HTTP Post operations).

Before you can make use of moto's state management facilities however, you must $use("codex.http")

8.1 The State

State variables, also called CGI variables, are created by following a URL, submitting a HTML form, or HTTP redirection. Following the URL

http://www.webcodex.com/index.moto?foo=bar&maka=shlaka  

Will add two variables to the state when the index.moto page is executed. The state variable 'foo' will have the value 'bar' and the state variable 'maka' will have the value 'shlaka'.

<form action="index.moto">
  <input type="hidden" name="foo" value="bar">
  <input type="hidden" name="maka" value="shlaka">
  <input type="submit" value="click me">
</form>
 

Clicking the 'click me' button on this form will make the same two state variables with the same two values available to index.moto when it is executing.

$do(sendRedirect("index.moto?foo=bar&maka=shlaka"))  

Executing a moto page that redirects to another moto page via the above redirect will also result in our two state variable being added.

The values of state variables can be retrieved within the code for index.moto in one of three ways. First, the current state can be retrieved and a method can be called on it to get the value of the state variable

$(getState().getValue("foo"))  

Second, if you want the value of a state variable for the current state (as you usually do) than you can call the convenience function getValue() directly

$(getValue("foo"))  

Third, you can use the two argument version of getValue() to provide a default value if the state variable is not defined in the current state.

$(getValue("foo","bar"))  

8.1.1 State Variables As Arguments

There are usually multiple means of getting to a moto page some of which pass a certain state variable and some of which don't. If someone got to index.moto by typing

http://www.webcodex.com/index.moto  

directly into their browser for instance the variable 'foo' would not be defined. In this case the getValue function (or method) would return the value null. There are two ways in which to handle this case

In web application programming, state variables (URL or form variables) are often looked at as arguments to the dynamic web page. If the argument is a required argument then you would want it's non-existence to be treated as an error

$if(getValue("foo") == null) $(sendRedirect(some error page) $endif  

But if it was an optional argument than you will likely have some default value in mind. In this case the third method of retrieving state variables is useful

$(getValue("foo","bar"))  

In this case if the state variable foo was not passed than the default value 'bar' will be used in it's place.

8.1.2 Special characters in State Variables

The characters =, &, and ? separate variable names from variable values, variable name value pairs from each other, and the query string from the hostname and path. In the case a variable name or value contains these special characters (or spaces, or another special character '%') that name or value must first be URL encoded before it may used in a URL.

<a href="index.moto?foo=$(urlEncode(foovalue))">  

The function urlEncode() will replace the special characters with their hexadecimal counterparts %hex value which will be understood by the web server and decoded on the next page view. Thus there is no need to URL decode explicitly in your source code.

8.1.3 HTML Forms

State variable values may also be set through user input in HTML forms

<form name="login form" method="post" action="do_login.moto">
  User: <input type="input" name="user">
  Password: <input type="password" name="password">
  <input type="submit" name="_action" value="login">
</form>

 

Clicking the login button on this form will actually submit three variables. The state variable 'user' will contain whatever the user entered for the user prompt. The state variable 'password' will contain whatever the user entered for his or her password. There will also be a state variable '_action' which contains the value 'login'. Now let's suppose that the page do_login is coded as follows

$switch(getValue('_action',"login"))
  $case(login)
     $if(getValue("user","") eq "bob" && getValue("password","") eq "bobpw")
        $do(redirect("index.moto?sid="+getState().getSID()))
     $else
        $do(redirect("login.moto?sid="+getState().getSID()+"&_err=Password+rejected"))
     $endif
$endswitch
 

Here we see that if the user attempted to log in with user name 'bob' and password 'bobpw' then he will be forwarded on to index.moto, otherwise he will be redirected back to the login page.

8.2 The Session

For applications that make use of Sessions, the current Session is retrieved from the state by calling the method getSession()

$declare(State s = getState())
$declare(Session session = s.getSession())
 

Once you have the Session, you may retrieve named Session variables from it by calling the get() method

$declare(Integer idUser = <Integer>session.get("idUser"))
$declare(String username = <String>session.get("uname"))
 

Before you may get any objects out of the Session however, you must put objects into it. This is done by calling two methods on the Session object: put() and promote().

$do(session.put("idUser",session.promote(new Integer(rset.getInt(0)))))
$do(session.put("uname",session.promote(rset.getString(1))))
 

The put method does nothing more than associate a String valued key with the object you want to store in the Session. The action of the promote method is less obvious.

8.2.1 Object Lifetimes

All objects allocated in moto have an implicitly specified lifetime after which the storage for the object will be recovered by the memory manager. By default the lifetime of an object ends when the page that it was constructed on is done executing. These objects are said to have a page lifetime. Objects that we want to make available on subsequent page views (without reconstructing them) need to stick around longer than that. This is what the promote method does

When you call Session.promote() on an object you change its lifetime to the lifetime of the Session you are storing it in. In the following section you will find that there is a Context.promote() function as well. If promote() were not called on an object before it was put in the Session or Context then the reference stored in the Session or Context would be invalid since the object may have already been deleted.

Methods such as Session.put() do not implicitly call promote because there would be many cases it could not catch. For instance suppose a SymbolTable was allocated and stored in the Session. Then objects were put into the SymbolTable. In this case the reference for the SymbolTable may be valid on subsequent page views, but the references for objects in the SymbolTable would not be. The bottom line is anything that is put into anything that is put into anything that is put into the Session or Context must be promoted.

8.3 The Context

The Context is the appropriate place to store singletons, that is Objects that you only need one of for your application. This is because there is only one Context and every page can get objects out of or store objects in the Context. Perhaps the most common type of object to store in the Context are caches.

To store an object in the Context, the Context must first be retrieved by calling the function getContext(), the object to be stored should then be promoted by calling Context.promote(), and finally the object must be associated with a name in the Context by calling Context.put().

$do(getContext().promote(cardData))
$do(getContext().put("CardList",cardData))
 

To retrieve an object from the Context use the method Context.get()

cardData =<TabularData>getContext().get("CardList")  

9 Advanced State Management

There are a number of important factors to consider when evaluating what sort of state management to use for your application. Will the application need to be distributed, or does it require bookmarkable URLs ? Will there be multi-page interview processes ? Can you require your users to have client side cookies turned on ? Moto provides built in support for four state management systems :

Stateless : A stateless application requires no information to be maintained in a user's session from page view to page view. This would be the case for static web sites or web sites whose content does not change based upon who is viewing it.

Client-Side : An application that requires knowledge only of who is logged in in order to display information is a good candidate for client side state management. When a user connects to the application a client side cookie is deposited on the user's browser identifying the Session. Subsequent page executions may retrieve information from the Session identified by the cookie. Client side state management is preferable for bookmarkable applications but may suffer from time travel problems and may not be used by browsers that have disabled cookies.

Server-Side : Instead of setting a cookie on the user's browser to identify the Session a state id is included in every link or form submission by using a special state variable sid. The value of this variable changes from page view to page view and identifies not only the Session but the previous State. Through this mechanism state variables are automatically persisted across page views without sufferring from time travel problems. However, since the sid variable is included in every link bookmarking pages of the application is not recommended as the Session may have expired by the time the bookmark is used.

Hybrid Server-Side - Client-Side : In the hybrid system both a client-side cookie and the sid variable are used. A correctly written application can default to Server-Side state management if client-side cookies are turned off. Conversly, only application areas that require the power of parent state identification such as multi-page interview processes need to use the sid. Other bookmarkable pages will be able to identify the correct Session via the cookie.

The type of State management your application uses is determined through a combination of httpd.conf configuration options and coding practices used in writing the application. The following diagram provides a graphical overview of Moto's state management subsystem.

9.1 Stateless Applications

To identify your application as Stateless include the following configuration option in your httpd.conf:

<Application Name>Option Session.Disable TRUE  

Or when running unter the interpreter:

<Location /~dhakim/docs>
   MotoOption ExamplesPath /Users/dhakim/Workarea/content/moto/examples
   MotoOption Session.Disable TRUE
</Location>
 

What this will do is turn off session creation and tracking within the application (or application area) where the directive applies.

Stateless is somewhat of misnomer because States are still created with every pageview. What Stateless applications really lack are Sessions. Calling getSession() on the current state will always return null

9.2 Server-Side State Management

Server-Side state management is available to an application whenever Sessions are enabled. Using it involves coding in such a way that a special State variable sid is passed in every hypertext link, location redirect, and form submission.

9.2.1 The State Variable sid

Every time a user visits a page when Sessions are enabled Moto attempts to discover whether this user already has a Session. A Session in moto doesn't mean that the user is necessarily logged in, just that the user has been interacting with the application on previous page views and has browsed to this page by following links on those pages. When Moto cannot determine the 'current Session' a new Session is created.

States are created on every page view. If Sessions are enabled then when a State is created it is bound to the current Session. The way moto discovers the current Session under Server-Side state management is by looking at a State variable named 'sid'. If it is present in the current State then Moto can derive the current Session from it and bind the newly created State to that Session.

The 'sid' variable's value identifies a State. It is used to identify the parent State of the currently executing page. If it is not present then Moto assumes there was no 'parent State' and spawns a new Session. Otherwise the parent State is retrieved and the Session it was bound to identified. The newly created State is then bound to that same Session. The process perpetuates itself when, on the currently executing page, the new State's own id (returned by the method getSID()) is included in dynamically generated links.

<a href="http://www.webcodex.com/index.moto?sid=$(getState().getSID())>  

location redirects

$(sendRedirect("index.moto?sid="+getState().getSID()+))  

and form submission by passing the sid as a hidden variable

<form action="index.moto" method="post">
  <input type="hidden" name="sid" value="$(getState().getSID())>
  <input type="submit" value="click me">
</form>
 

When the link is followed, the form submitted, or the browser redirected, Moto recognizes the sid, discovers the State it refers to, and from that state discovers the Session.

This mechanism is used to provide continuity to the user experience not only through Session identification but by persisting the values of State variable between page views. State variables in the parent state that do not begin with an underscore '_' are copied into the current state. So if the state variable 'foo' was present in the parent state than it is present in the current state with the same value. It's value changes only when a new value is passed for it. Thus in the login page example from the previous section

<form name="login form" method="post" action="do_login.moto">
  User: <input type="input" name="user">
  Password: <input type="password" name="password">
  <input type="submit" name="_action" value="login">
</form>

 

$switch(getValue('_action',"login"))
  $case(login)
     $if(getValue("user","") eq "bob" && getValue("password","") eq "bobpw")
        $do(redirect("index.moto?sid="+getState().getSID()))
     $else
        $do(redirect("login.moto?sid="+getState().getSID()+"&_err=Password+rejected"))
     $endif
$endswitch
 

The value of the State variable "user" could be retrieved on all subsequent page views. This is handy because it does not require the extra work of inserting it into the Session or promoting its value. There are further benefits which are discussed in detail in subsequent sections.

9.2.2 HTML Forms With Server-Side State Management

Continuing from the previous example of login and do_login pages, a user has just entered a username (bob) and password on the login page, pressed submit taking him to the do_login page where his account was validated and his browser redirected to an index page.

If this were an application that made use of Server-Side state management then on the index page we could write

Welcome $(getState("user"))  

And it will print

Welcome bob  

We could not however print

You clicked $(getState("_action"))  

which would result in

You clicked null  

Since '_action' began with an underscore it's value is not copied to subsequent states and thus available to subsequent page views.

Form submissions account for the way Moto handles State variables with names that begin with '_'. In general:

  • Most values submitted in forms are only needed immediately after the form submission
  • Values from form submissions may be quite large and as such expensive to copy from page view to page view.

Consider a web application that is used for maintaining an employee directory. One could imagine a page containing a form that solicits data for a new hire which, upon submission, is inserted into a database. Let's suppose this form prompts for the employee name, address, and a photo that can be uploaded. All this data will be submitted to moto as state variables. The page that handles this submission will insert it into the database and then return to the index where upon the user can choose to add another employee or browse through other application pages. Either way this data is unnecessary, and, with regard to the employee photo, potentially quite large. We would definitely not want it copied with every page view.

When the Session.Disable option is present, all state variables are free'd after page execution. In Stateless applications the variable sid is meaningless and not prefixing state variables with an underscore has no effect. They all go away at the end of the page view to which they were submitted.

But why copy state variables, why not just keep one value around for every state variable name used in a user's session? The answer to this question requires some background...

9.2.3 Time Travel

When building web applications it is useful to diagram them out in Application Flow Diagrams. These diagrams map out the pages of a web application with arrows between them illustrating the links that a user could follow to transition from page to page. A simple application where users may view or modify a 'user profile' might be diagrammed as follows:

A user's activities in a web application can be viewed as a traversal of the transition diagram.

State 1 2 3 4 5 6 7 8
Parent State none 1 2 3 4 5 6 7
Page 1 2 1 2 3 4 5 4

For the traversal above the user forgot his password the first time and was sent back to the login page to start again. This is clear by comparing the pages the user visited to the transitions in the app flow diagram. The user then went on to the index page, viewed his profile, and successfully edited it. But what could we conclude happened if we then saw

State 9 10 11 12
Parent State 1 9 10 8
Page 1 2 3 5

The user backed up to the login page, openned up a new browser window and logged in as (potentially) a different user in it. Then went back to the original window and followed the edit profile link! If the only mechanism being used to determine what user profile to edit was based upon an identifier tied to the Session then the user whose profile will be edited in the first window will be the user who is logged in in the second. Another way to look at this is that the actions the user took by opening up a second window and logging in as a different user affected the behavior of a link that was generated previously. This is known as a time travel problem.

Implications of this sort of problem are

  1. Using the back button on applications that make extensive use of Session objects or (or Client-Side State management) may be unsafe.
  2. Following links by openning them up in new windows may effect the ability to follow links in other open windows.
  3. Session objects are tricky things that must be used with care.

Use of Session objects is the most common cause of unexpected time travel problems. If the 'current user' in the application diagrammed above was stored as a persistent State variable there would be no confusion as to which 'user' was being edited in which window. If you believe that the above example is somewhat contrived consider the role of an HR administrator who may be responsible for updating the profiles of multiple employees ... this sort of thing happens all the time.

One area where this comes up a lot is in relation to multi page interview processes. In these sorts of cases users are asked to enter information through a series of interactions with a web based application. In general the information is persisted in memory until it is ready to be stored. An example of this might be web page building application where fields of a web page template get filled in over successive page views

State 1 2 3 4 5 6 7
Parent State none 1 2 3 4 5 6
Page 1 2 3 2 3 2 3

In the above traversal the user has selected a page to edit and is entering data into each of it's fields

State 8 9 10
Parent State 1 7 9
Page 2 2 1

It seems as though the user has gone back to the directory screen by using the back button on his browser and selected a new page in a new browser window (perhaps to copy some information out of that page into the page he's working on). Back in his working window he then alters the field and then saves the page. But which page did he alter? If the data for a page is stored in a Session variable named 'page' for instance then the very act of opening up a second page in another window has undone all the users work.

9.3 Client-Side State Management

So now that we are aware of the hazards of Session objects because of time travel problems, one might ask why we should ever consider a State Management methodology where one is forced to use Sessions to persist data between page views. The biggest reason may be bookmarkability. Including the state variable sid in every URL means that bookmarking generated URLs may be useless or potentially dangerous if the link is distributed to others.

With pure Client-Side state management a Cookie named ssid is deposited on a users browser after his first page view against an application. This Cookie does nothing more than identifies the Session. If on subsequent page views Moto retrieves this Cookie then Moto can discover the current Session. If the cookie is not included within the HTTP GET or POST then Moto assumes there is no current Session and spawns a new one.

You can get this behavior by including the option

<Application Name>Option Session.SetSSIDCookie TRUE  

Or if using the interpreter use the following moto option in the location you want it applied:

MotoOption Session.SetSSIDCookie TRUE  

The lifetime of the ssid cookie is the same as the lifetime of the Session which is specified in seconds via the Moto option

MotoOption Session.Timeout 60  

The default value for this option is 1800.

The downsides of this system apart from the time travel phenomina we've already looked at are :

  • Some users may have client side cookies disabled
  • It becomes impossible to maintain multiple Sessions at once against the same application under one browser (sometimes this makes testing difficult)
  • State variables are not persisted meaning that all data for a users session must be promoted and stored in the Session

9.4 Hybrid State Management

The best State management systems for web applications are hybrid systems. They are also the most complex to implement. The way a hybrid system is implemented in Moto is by including the Session.SetSSIDCookie option in your httpd.conf file AND including the sid variable on all pages that could benefit from it and do not need to be bookmarked OR in every generated URL in cases where client side cookies are turned off.

You can discover whether cookies are working or not by trying to getCookie("ssid") on a page that expects it. If it is not found, include the State variable sid on all generated URLs.

Simply by enabling the SetSSIDCookie option on applications that are basically Server-Side State managed adds an extra level of security. If the Session identified by the sid and the Session identified by the ssid do not match then a new session is spawned.

10 Interacting With Databases

Like most web programming languages, the moto language was designed with database interaction in mind. Extensions are included with moto in order to facilitate interaction with Postgres and MySQL databases. To connect to one of these databases you must use the appropriate codex.db library

$use("codex.db.mysql")
$use("codex.db.pgsql")
 

10.1 Connecting to the Database

Prior to using a database you must connect to it, this is done in moto by constructing a connection object

$declare(MySQLConnection myconn = new MySQLConnection(server address,database name,user,password))
$declare(PGConnection pgconn = new PGConnection(server address,database name,user,password))
 

10.2 Querying the Database

Once you have a connection to the database you can issue SQL queries against it. Queries results are returned in a ResultSet.

$declare(String query =
  "SELECT cardsets.id,cardsets.name,cardsets.shortname,count(print.id) AS cardcount ,sum(price.buy) AS setprice,sum(price.diff) FROM cardsets,print,price WHEREprice.print=print.id AND print.edition=cardsets.id GROUP BY print.edition")

$switch(getValue("_orderby","Set"))
  $case("Set")
     $do(query = query + " ORDER BY cardsets.name")
  $case("Cards")
     $do(query = query + " ORDER BY cardcount DESC")
  $case("Price*")
     $do(query = query + " ORDER BY setprice DESC")
$endswitch

$declare(MySQLResultSet rset = conn.query(query))
 

Those results are then iterated over and either displayed or used in other computations. The result set object keeps track of what row you are currently looking at. Methods are called on the result set object to retrieve individual columns of the current row.

     $while( rset.next())
        <tr>
           <td align=center><img src="images/exp_sym_$(rset.getString(2)).gif"></td> <td >
              <a href="cardlist.moto?sid=$(
                 getState().getSID()
              )&searchby=set&set=$(
                 rset.getString(0)
              )">$(rset.getString(1))</a>
           </td> <td align=center >
              $(rset.getInt(3))
           </td> <td align=center ><nobr>
              $("$ ")$(rset.getString(4))
              $if(rset.getFloat(5) > 0)
                 <img src="images/uparrow1.gif">
              $elseif(rset.getFloat(5) < 0)
                 <img src="images/downarrow2.gif">
              $endif
           </nobr></td>
        </tr>
     $endwhile
 

The result set method next() must be called prior to retrieving values for fields in the result set. This method returns true if there are more rows in the result set then scrolls to the next one.

Values for specific columns in the result set are returned either by specifying the column number (as in the above example) or by referencing the column name. Column names are not case sensitive.

$(rset.getString("column name"))  

To find out how many rows were returned in the result set, call the method size() on the result set object

$if(rset.size() > 0)  

10.3 Modifying Data

You can also execute SQL inserts, updates, or deletes against the database. This occurs via the update method of the Connection object. This method returns the number of rows inserted, updated, or deleted by the method.

           $if(rset.next())
              $do(deckid=rset.getInt(0))
              $do(conn.update("DELETE FROM deckcards WHERE deck="+str(deckid)))
           $else
              $do(conn.update(
                 "INSERT INTO deck VALUES (0, '"+
                 conn.escape(getValue("_name"))+"','"+
                 conn.escape(getValue("_creator"))+"',"+
                 str(uid)+",0)"
              ))
              $do(deckid = conn.insertID())
           $endif

           $do(tok= new Tokenizer(ids,'|'))

           $while((curID=tok.next()) != null)
              $declare(String curQTY =getValue("_q"+curID))

              $if(curQTY != null && curQTY ne "0")
                 $do(conn.update(
                    "INSERT INTO deckcards VALUES ("+str(deckid)+","+curID+","+curQTY+",0)"))
              $endif

              $do(curQTY =getValue("_s"+curID))

              $if(curQTY != null && curQTY ne "0")
                 $do(conn.update(
                    "INSERT INTO deckcards VALUES ("+str(deckid)+","+curID+","+curQTY+",1)"))
              $endif
           $endwhile
 

When inserting String values into the database you should first escape the string value being inserted. This is accomplished by calling the connection method escape() on the value to be inserted. Binary data may also be escaped in this way for insertion into BLOB fields. The escape function effectively backslashes single quotes and other restricted characters.

conn.escape(String value to be escaped)
conn.escape(byte[] to be escaped)
 

10.4 Accessing Database Meta-Data

Once connected to a database you can retrieve a list of tables in the database as a result set by calling the listTables() method on your connection.

$do(rset=conn.listTables())
$while(rset.next())
   $(rset.getString(0))
$endwhile
 

Once you have a result set in hand you can retrieve the names and types of the columns returned

$declare(int cols=rset.getColumns())
$declare(int i)
$for(i=0;i<cols;i++)
   $(rset.getColumnName(i))
   $(rset.getColumnType(i))
$endfor
 

10.5 Persisting Queries Across Multiple Pages

ResultSets cannot be stored in the session or the context since the results are not stored in shared memory. Yet caching queries often provides a very good performance benefit. To do this, TabularData objects have been provided to store result sets in shared memory. The TabularData object is provided in the codex.util extension.

$use("codex.util")
$declare(TabularData ocs)
$if((ocs=<TabularData>getContext().get(query)) == null)
   $do(ocs = conn.query(query).store())
   $do(getContext().promote(ocs))
   $do(getContext().put(query,ocs))
$endif
 

TabularData objects are similar to result sets except the entire result is stored in memory. Thus rows my be accessed in an arbitrary order.

$for(i=0 ;i < ocs.getRows() ;i++)
   $do(curSet = ocs.getInt(i,0))
$endfor
 

The standard field retrieval functions getInt,getString,getFloat etc... take both a row and a column ( or a row and a column name)

TabularData objects are also modifyable and may be used as a convenient data structure with which to store arbitrary table data

  $declare(TabularData cardData)

  $if((cardData =<TabularData>getContext().get("CardList")) == null)

     $declare(MySQLResultSet cacherset = conn.query("SELECT max(id) from print"))
     $do(cacherset.next())

     $do(cardData = new TabularData(
        cacherset.getInt(0)+1,
        10,
        "shortname,name,card,print,color,type,cost,rarity,price,diff",
        "String,String,int,int,char,String,String,char,float,float")
     )

     $do(cacherset = conn.query(
        "SELECT cardsets.shortname,card.name,card.id,print.id" +
        ",card.color,card.type,card.cost,card.rarity,price.buy,price.diff "+
        "FROM cardsets,card,print LEFT OUTER JOIN price "+
        "ON price.print=print.id "+
        "WHERE card.id = print.card "+
        "AND print.edition = cardsets.id"
     ))

     $while(cacherset.next())
        $do(cardData.setString(cacherset.getInt(3),0,cacherset.getString(0)))
        $do(cardData.setString(cacherset.getInt(3),1,cacherset.getString(1)))
        $do(cardData.setInt(cacherset.getInt(3),2,cacherset.getInt(2)))
        $do(cardData.setInt(cacherset.getInt(3),3,cacherset.getInt(3)))
        $do(cardData.setChar(cacherset.getInt(3),4,cacherset.getChar(4)))
        $do(cardData.setString(cacherset.getInt(3),5,cacherset.getString(5)))
        $do(cardData.setString(cacherset.getInt(3),6,cacherset.getString(6)))
        $do(cardData.setChar(cacherset.getInt(3),7,cacherset.getChar(7)))
        $do(cardData.setFloat(cacherset.getInt(3),8,cacherset.getFloat(8)))
        $do(cardData.setFloat(cacherset.getInt(3),9,cacherset.getFloat(9)))
     $endwhile
     $do(getContext().promote(cardData))
     $do(getContext().put("CardList",cardData))
  $endif
 

11 Writing New Extensions for Moto

The moto language, like most web programming languages, was designed primarily for webmasters with some technical ability to intersperse programmatic constructs within web pages to create web applications. Moto was built with performance in mind because the history of web programming languages such as Coldfusion, ASP, and PHP, shows that they are used more often than not as the entire platform for rapid web application development. Nonetheless, the preferred way of using moto is for the user interface and form handling aspects of your web applications alone. Business logic, where possible, should be implemented in a classical programming language such as C.

To this end, an API has been provided for the creation of new moto objects and functions from your own C libraries.

11.1 The Moto Extension Architechture

Moto extensions are organized into libraries that can be used in your moto pages via the $use construct. These libraries reside under the mx directory of your moto home directory. The structure of the mx directory is loosly modelled after a java class library structure. It is heirarchical with the top level subdirectories conventionally named after the source company that maintains the moto extensions within. Underneath each top level directory there may be further subdirectories dividing the contained extensions into frameworks by function. Entensions are made available to the a moto page one folder at a time.

11.2 Adding A New Extension Library

To add a new extension library you should begin by creating a new directory underneath the mx directory. You should then copy the makefile file from one of the existing extensions folders into your new folder. You can now begin creating interface files that map extension functions and object methods to C functions in your own C libraries.

11.3 Writing A Moto Interface File

For each new object or set of related functions you wish to expose to your moto application, you should create one interface file (.i) . The convention is that this interface file be given the same name as the extension which it contains and thus start with a capital letter. Interface files have the following general structure:

Extension: 1st Extension / Class Name

LibraryPath: 1st library path needed to locate shared libs this extension depends upon
LibraryPath: 2nd library path needed to locate shared libs this extension depends upon
...

IncludePath: 1st path to header files needed to compile this extension
IncludePath: 2nd path to header files needed to compile this extension
...

Library: 1st shared library file needed for this extension
Library: 2nd shared library file needed for this extension
...

Archive: 1st archive needed for this extension
Archive: 2nd archive needed for this extension
...

Include: 1st C header file needed to compile this extension
Include: 2nd C header file needed to compile this extension
...

Interface:

prototype mapping ;
prototype mapping ;
prototype mapping ;
...
 

The prototype mapping is where moto functions and methods get translated to their C counterparts. A prototype mapping begins with the return type of the moto function or method preceded by the keyword tracked if the return value is an object created on the heap by the function or method call. If the function or method returns nothing then void should be specified as it's return value. Following the return type is the function or method name. In the case of a method name, the C++ style qualified name should be used

Class Name::Method Name  

After the method name there is an open paren '(' followed by a comma delimeted list of argument type argument name pairs followed by a close paren ')'. After the argument list comes the mapping symbol => and finally the C function prototype. A complete example of an interface file taken from the codex.util library for the SymbolTable class follows:

Extension: SymbolTable

Include: "symboltable.h"
Include: "enumeration.h"

Interface:

tracked SymbolTable SymbolTable::SymbolTable() =>
   SymbolTable *stab_createDefault();
   
void SymbolTable::~SymbolTable() =>
   void *stab_free(SymbolTable *this);
   
void SymbolTable::put(String key, Object value) =>
   void stab_put(SymbolTable *this, char *key, void *value);
   
Object SymbolTable::get(String key) =>
   void *stab_get(SymbolTable *this, char *key);

void SymbolTable::remove(String key) =>
   void *stab_remove(SymbolTable *this, char *key);
   
void SymbolTable::clear() =>
   void *stab_clear(SymbolTable *this);

tracked Enumeration SymbolTable::keys() =>
   Enumeration *stab_getKeys(SymbolTable *this);

int SymbolTable::size() =>
   int stab_size(SymbolTable *table);


 

11.4 Extension Dependencies

There are three important times when the dependencies for an extension must be known.

  1. When the extension is compiled with mxc into .a and .so libraries
  2. When the extension is dynamically loaded by the moto interpreter
  3. When the extension is linked to a binary or apache module with mmc

11.4.1 Includes and IncludePaths

At compilation time when the .a and .so files are created, header files that declare C prototypes used in .i files must be listed using the Include keyword so that they can be included when building extension object files. If these headers aren't in a standard location such as /usr/include the path to the directory containing these header files must also be specified using the IncludePath keyword so that mxc and mmc know where to look for them.

Using IncludePath to add the path to the moto include directory is not necessary as it is automatically included by mxc and mmc.

11.4.2 Libraries and LibraryPaths

The Library keyword in an interface file allows you to specify that your extension depends on a third party library. This keyword should only be used for linking to shared libraries. It will generate a runtime dependency from the extension (and therefore from modules compiled with that extension) to that library.

Libraries you should never link to via the library keyword include libmotom and libcodex. All the symbols from these libraries are included in the command line interpreter and in mod_moto and are automatically linked by mmc. Linking to these libraries will cause duplicate symbol errors on some platforms.

If the shared library you depend on is not in a standard location such as /usr/lib then you must specify the path to the directory containing the shared library by using the LibraryPath keyword.

Often times it is preferable to actually copy the necessary symbols out of a library directly into an extension. This is the case when you do not wish to have the runtime dependency on that library. Specifying a full path to an archive that contains the necessary symbols (a .a file) using the Archive keyword will tell both mxc and mmc to statically link to that archive (copy out symbols).

Sometimes archives and shared libraries may themselved be dependant on symbols in other libraries. These dependencies should also be listed with the Library or Archive keywords.

Often times there will be a choice to link to either a shared library or an archive. The general rule should be to link to common shared libraries that are guarenteed to be present in the same location on platforms where binaries compiled with your extension will be deployed. If you cannot guarentee that, then statically link to an archive if possible.

This diagram shows the current design of the libraries that are distributed with moto.

11.5 Writing an Extension in C

Always include "memsw.h" this is very important because this header redefines malloc, realloc, and free to allocate memory on the shared heap. If your methods in your extension return Objects (a constructor for example) than that memory needs to be allocated on the shared heap. If it is allocated with the plain old system malloc than that memory will leak and never get cleaned up. Worse, your object won't be promotable. That is, moto programmers won't be able to persist it in the session or context and if they try to, Apache will likely segfault when they next try to access it. Bottom line ... include memsw.h .

Usually include "excpfn.h" and "exception.h". With these you will be able to throw and catch exceptions using the macros TRY, CATCH, CATCH_ALL and END_TRY. This is much better than segfaulting (or returning error codes ... yuck) when something goes wrong inside your extension. Moreover excpfn.h defines a number of usefull function that mimic their C stdlib counterparts but allocate memory on the shared heap and throw exceptions when the arguments passed to them are bad. These functions include emalloc, erealloc, estrdup, and estrcmp.

Always create a destructor. Without a destructor moto will just call plain old free on your object and if you have any member objects those won't get cleaned up.