Nombas Logo

  • Return to main SE:WSE page
  • Introduction
  • Installation instructions for ScriptEase:WebServer Edition
  • A description of the Javascript language
  • A tutorial for some ScriptEase:Webserver Edition demos
  • A description of the Clib object
  • A description of the SElib object
  • The ScriptEase Language

    This chapter is an introduction to and a description of the ScriptEase programming language.

    ScriptEase provides the most powerful and advanced form of JavaScript available today. Whereas other flavors of JavaScipt are embedded in web browsers and restricted to scripts that have been transmitted along with HTML documents, the ScriptEase processor allows you to run scripts locally, so you can use ScriptEase to write full fledged programs. In addition, ScriptEase has added commands and directives that increase and extend its power without interfering with the operation of standard JavaScript. These enhancements include preprocessor directives such as #include and #define, the switch/case statement, and the built-in Buffer object.

    Program Structure

    Computers, contrary to popular opinion, are not intelligent. They are able to carry out simple calculations (add, subtract, multiply, divide) at a dizzying speed, and make tests to see if a is equal to b , for example, but that's pretty much it. Even though the computer can perform these tasks far more quickly and accurately than humans, it never thinks about what it is doing. A computer cannot make decisions. The closest it can come to thinking is to see if a condition is met and then perform an action based on the results of that condition. If a certain button must be pressed to save the world, the computer won't do it unless it is told to do it, or programmed to do it when a certain number of conditions are met (e.g., if this event happens and that event happens, press the button). It will never realize the world needs saving and press the button on its own.

    A computer language is designed to give instructions to computers in a way they can understand, so that they can carry out their programmed task. This means that before you write a program, you must have a good idea how to go about doing the task yourself. As in real life, this is easier (and less daunting) if you break the given task down into smaller, easier to handle sections.

    For example, let's suppose you have a list of friends whom you wish to call and leave a message about your weekend plans. This can be broken down into five major steps:

    • Get a name from the list
    • Call them
    • Leave a message
    • Hang up
    • Get the next name on the list; repeat the process until everyone's been
    • called.
    In code, this would look like this:
        while( ThereAreUncalledNamesOnTheList() != false){
        name=GetNameFromTheList();
           CallthePerson(name);
           LeaveTheMessage();
        }
    Now you have a framework for your program, and a clear idea of the sub-tasks that need to be accomplished to achieve your goal. By breaking the task into smaller pieces, it is easy to translate your thoughts into ScriptEase. (In computer terminology, each of these steps is called a function. A function has a name followed by a pair of parentheses, which may or may not have anything in them).

    Another advantage to breaking your task up comes when you need to make changes. If you need to make a change in your main task, you don't need to rewrite the entire program, just the part where the change occurs. For example, if you want to leave a different message the next time you run the program, you only need to change the `LeaveTheMessage()' section of the program.

    Whitespace Characters

    Characters that govern the spacing of text are called whitespace characters. The white characters are the space, tab, carriage return and newline. Whitespace makes the code more readable for humans, but is ignored by the interpreter.

    A line ends with a carriage return, and each line is usually a separate statement (a more detailed explanation of statements and lines comes later in this chapter). The following statements are equivalent to each other:

        x=a+b
        x =  a+   b
        x = a            +          b
        x = a
        + b
    A space indicates the end of a variable name. "a b" represents two variables, "a" and "b"; "ab" represents only one.

    Tabs are usually not used in writing code, because tab settings are different for different users and what looks good on one system may look awful on another. Instead of using tabs, use two or three spaces.

    Comments

    Comments help bridge the gap between computer language and human language. A comment is a section of code that the processor will ignore when running the script. By using comments to explain the code in plain English, you will save yourself a lot of time if you have to go back to it later. If a section of code is commented, you know exactly what that section of code does and why it is there without having to decipher it. If you need to modify a script at some time in the future, you will thank yourself for placing comments in your program.

    In ScriptEase, two slash characters (//) signal the beginning of the comment; the comment extends to the end of the line. Anything after the two slashes is considered a comment and is ignored by the ScriptEase interpreter. Likewise, anything between a slash-asterisk (/*) and an asterisk-slash (*/) is a comment (this type of comment may extend over many lines). Comments may not be nested inside each other, i.e., comments may not contain comments. Here are some examples of comments:

        // this is a comment line
        
       /********************************
        *** This is one big comment  ***
        *** block. Isn't it pretty?  ***
        ********************************/
        
        FavoriteAnimal = "dog"; // except for poodles
        //This line is a comment but
        this line is not.

    Variables

    A variable is a symbol that may be assigned data. Variables are used as places to store and represent information in the program you are writing. Javascript variable names can be any length within reason. The following naming guidelines must be followed:
    • variable names cannot start with a number,
    • the following characters cannot be used +-<>&|=!*/%^~?:{};()[].'"`#,
    • embedded spaces or tabs are not allowed.
    All other characters -- letters, numbers, the underscore (`_') and dollor sign --are legitimate characters for variable names. The interpreter is case sensitive, so sid and Sid represent two different variables. The following are valid variable names:
         Sid
         Nancy7436
         annualReport
         sid_and_nancy_prepared_the_annualReport
         alice
    The following variable names are not valid:
         1sid
         2nancy
         this&that
         Sid and Nancy
         ratsAndCats?
    The first time a variable is used, it may be declared with the var keyword:
         var Marie_Antoinette = "doomed queen"
    Variables created with the var keyword are local to the function in which they are created and are undefined in other functions unless explicitly passed to them. If a variable is created with the var keyword that has the same name as a global variable, the variable name will refer to the created variable while in the function - the global variable must be referred to as a member of the global object, global.variable, e.g. The following words have special meaning to the interpreter, and cannot be used as variable names:
    breakcasecatchclassconst
    continuedebuggerdefaultdeletedo
    elseenumexportextendsfalse
    finallyforfunctionifimport
    innewnullreturnsuper
    switchthisthrowtruetry
    typeofwhilewithvarvoid

    Expressions, Statements, andBlocks

    An expression or statement is any sequence of code that performs a computation or takes an action (e.g., "Count=1", "(2+4)*3"). ScriptEase code is executed one statement at a time in the order in which it is read. A semicolon (;) may be put at the end of a statement; the semicolon is optional but recommended to improve readability. Each program statement is usually written on a separate line to make the code easy to read.

    A block is a group of statements enclosed in curly braces ({}). The braces indicate that the enclosed statements are a group and are to be treated as one statement, containing multiple sub-statements. A block can be used anywhere a statement can be used.

    The first example of this chapter has a statement block:

      while( ThereAreUncalledNamesOnTheList() == true){
      name=GetNameFromTheList();
         CallthePerson(name);
         LeaveTheMessage();
      }
    GetNameFromTheList(), CallthePerson(), and LeaveTheMessage() are grouped together within braces to show that they should be treated as a unit. If the braces were left out, the while statement would only apply to the first line following it. In this case, the program would go through and get every name on the list, and then call only the last one.

    The indentation of statements is not necessary, but is recommended for readability.

    Data Types

    Data is assigned to a variable with an equal sign (=), regardless of the form the data may take:
    happyVariable = 7;
    joyfulVariable = "free chocolate";
    theWorldIsFlat = true;
    The first time a variable is used, its type is determined. The example above creates three variables, each of a different type: the first is a number, the second is a string, and the third is a boolean variable. The variable types are described below. For the most part, you won't have to worry about making sure that a variable is of the correct type, since Javascript will automatically convert from one type to another when it needs to. Numbers : the most self explanatory data type, a variable of the type number represents a number. Both integers and numbers with a decimal component are numbers.

    Strings : A series of characters linked together. A string is written enclosed in quotation marks, e.g. "I am a string." or "344". Note that the string "344" is different from the number 344; one is a set of characters to be printed, while the other is a value that may be used in numerical calculations.

    ScriptEase automatically converts strings to numbers and vice versa, depending on context. In other words, if you use a number in a `string' context, it will be converted into a string; likewise, if you use a string in a `number' context, it will be converted to a numerical value. Automatic type conversion is discussed in detail on See Automatic Type Conversion .

    Undefined : If a variable is created and has nothing assigned to it, it is of type "undefined". You cannot do much with an undefined variable; it just takes up space and waits for a value to be assigned to it. When the variable is assigned a value it will be assigned a new type according to its value.

    Boolean : A variable of type Boolean may only have one of two possible values: true or false. When a Boolean variable is used in a numeric context, it will be converted to 1 if it is true, or 0 if it is false.

    Null : Null is a special data type that indicates an variable is empty. In other words, the variable in question holds no value. When used in string context, a null variable converts to the string "null"; when used in a numeric context, it converts to 0.

    Object : An object is a compound data type, consisting of one or more pieces of data (of any type) grouped together; data that are part of an object are called properties of the object. The object data type is equivalent to the structure data type in C and in previous versions of ScriptEase; however, the object data type also allows functions (methods) to be used as object properties.

    Here are some examples of variables and their corresponding data types:

      Larry = 1
      Moe = 0x3EF2
      Curly = 3.1415
      Larry, Moe and Curly are all numbers.
      Bill = "politician"
      Hilary = "lawyer"
      address = "The White House"
      Bill, Hilary and address are strings.
      variable
      An undefined variable; since it contains no data, its data type has not yet been determined so it is classed as type `Undefined'.
      TheWorldIsFlat = true
      MyDogEatsNuts = false
      TheWorldIsFlat and MyDogEatsNuts are Boolean.
      Anteater.eyes = 2
      Anteater.feet = 4
      Anteater.diet = "ants"
      Anteater is an Object; it has three elements, two numbers and a string.
    The typeof operator
    The typeof operator provides a way to test a variable's type. It looks like this:
         result = typeof variable
    After this call, the variable `result' will be set to a string that is the variable's type: "undefined", "boolean", "string", "object", "number", etc.

    The delete operator
    The delete operator deletes a variable. Any data in the variable will be lost, and if you try to access the variable's type, it will be undefined.

         delete variable;
    Strings
    In ScriptEase version 4.x, strings are their own data type, as opposed to being arrays of bytes as in C and previous versions of ScriptEase. There are some differences and many similarities in the way strings are handled in the two versions of the language. One major difference is that in ScriptEase version 4.x, a string is not null-terminated. Although the null character is a valid string component, the existence of a null character doesn't indicate the end of the string; "\0\0\0" is a valid string.

    Escape Sequences for Characters
    As mentioned earlier, the most common way to indicate that data is a string is to put it in double quotes, e.g. "This is a string". Some characters (such as the quotation mark) which have meaning to the processor must be indicated with special character combinations when used in strings. This allows the processor to distinguish between the quotation mark that is part of a string and the quotation mark that indicates the end of the string. The table below lists the characters which are indicated with escape sequences:
    \a Audible bell
    \b Backspace
    \f Formfeed
    \n Newline
    \r Carriage return
    \t Tab
    \v Vertical tab
    \' Single quote
    \" Double quote
    \\ Backslash character
    \0### Octal number (e.g., `\033' is the decimal number 27).
    \x## Hex number (e.g., `\x1B' is the decimal number 27).
    \0 Null character
    Note that these escape sequences cannot be used within back-tick strings (see below). Also, any integer value starting with 0 is treated specially. 0 alone signifies octal, 0x specifies hexadecimal.

    Single quote strings
    You can declare a string with single quotes instead of double quotes. There is no difference between the two, except that double quote strings are less commonly used. (In a function declared with the cfunction keyword, the difference is more important; see the description of cfunction on See The cfunction keyword ).

    Back-quote strings
    ScriptEase provides the back-quote (`), also known as the back-tick or grave accent, as an alternative quote character to indicate that escape sequences are not to be translated. Any characters represented with a backslash followed by a letter ('\n', e.g.) cannot be used in back-tick strings.

    For example, here are two ways to describe the same file name:

         "c:\\autoexec.bat"// traditional C method
         `c:\autoexec.bat`// alternative ScriptEase method
    Backquote strings are not supported in most versions of JavaScript, so if you are planning to port your script to some other JavaScript processor, you should not use them.

    Long Strings -- Using + to join (concatenate) strings
    You can use the `+' symbol to join strings. For example:

         proverb = "A rolling stone " + "gathers no moss."
    will create the variable proberb and assign it the string "A rolling stone gathers no moss."

    If you try to concatenate a string with a number, the number will be converted into a string:

         newstring = 4 + "get it";
    This bit of code creates the string variable newstring and assigns it the string "4get it".

    This is the standard way of creating long strings in JavaScript; with ScriptEase, the `+' symbol is optional. For example, the following:

         badJoke ="I was standing in front of an Italian "
         "restaurant waiting to get in when this guy came "
         "up and asked me, \"Why did the Italians lose the "
         "war?\" I told him I had no idea. \"Because they "
         "ordered ziti instead of shells,\" he replied."
    creates a long string containing the entire bad joke.

    Clib.sprintf()
    ScriptEase allows you to include the standard C library as an object in your code. Each method in the Clib object corresponds to one of the standard C functions. In this manual, Clib.sprintf() is used in the examples to create a formatted string; the value of the first parameter passed will contain the string. It is in most respects exactly like sprintf(); follow the link see the full documentation.

    Mathematical Operators
    ScriptEase code usually contains some mathematical operations, such as adding numbers together, multiplying, dividing, etc. These are written as you'd expect, i.e., write "2 + 3" when you want to add two and three. The next few subsections define the mathematical operators used in ScriptEase, followed by a line of sample code.

    Basic Arithmetic
    The arithmetic operators in ScriptEase are pretty standard:

      = assignment: sets a variable's value
      + addition: adds two numbers
      - subtraction: subtracts a number
      * multiplication:
      / division
      % modulo: remainder after division
    Here are some examples using variables and arithmetic operators:
    i = 2; // i is 2
    i = i + 3; // i is now (2+3) or 5
    i = i - 3; // i is now (5-3) or 2 again
    i = i * 5; // i is now (2*5) or 10
    i = i / 3; // i is now (10/3) or 3 (the remainder is ignored)
    i = 10;  
    i = i % 3; // i is now (10%3) or 1
    Expressions may be grouped to affect the sequence of processing: first all multiplications and divisions are calculated for the expression, and then all additions and subtractions. Expressions inside parentheses are processed first. Notice that:
         4 * 7 - 5 * 3;// 28 - 15 = 13
    has the same meaning, due to the order of precedence, as:
         (4 * 7) - (5 * 3);// 28 - 15 = 13
    but has a different meaning than:
         4 * (7 - 5) * 3;// 4 * 2 * 3 = 8 * 3 = 24
    which is still different from:
         4 * (7 - (5 * 3));// 4 * (7 - 15) = 4 * -8 = -32
    Even though parentheses may not be necessary, their use is recommended. They make your scripts a lot easier to understand.

    Assignment Arithmetic
    Each of the above operators can be combined with the assignment operator (=) as a shortcut for performing the operation with the first variable and then assigning the result to the same variable. Using assignment arithmetic operators, the above code could be simplified as follows:
    = assignment: sets a variable's value
    += assign addition: adds number
    -= assign subtraction: subtracts a number
    *= assign multiplication
    /= assign division
    %= assign remainder: remainder after division
    Here are some examples using assignment arithmetic:
    i = 2; // i is 2
    i += 3; // i is now (2+3) or 5; same as i = i + 3
    i -= 3; // i is now (5-3) or 2 again; same as i = i - 3
    i *= 5; // i is now (2*5) or 10; same as i = i * 5
    i /= 3; // i is now (10/3) or 3; same as i = i / 3
    i = 10;  
    i %= 3; // i is now (10%3) or 1; same as i = i % 3
    Auto-Increment (++) and Auto-Decrement (--)
    If you just want to add one (1) to a variable, you can use the auto-increment (++) and auto-decrement (--) operators. These operators add or subtract 1 (one) from the value to which they are applied. ("i++" is a shortcut for "i += 1", which is in itself a shortcut for "i = i + 1").

    These operators can be used before (prefix) or after (postfix) their variables. If used before, then the variable is altered before it is used in the statement; if used after, then the variable is altered after it is used in the statement. This is demonstrated by the following code:
    i = 4; // i is initialized to 4
    j = ++i; // j is 5, i is 5 (i was incremented before use)
    j = i++; // j is 5, i is 6 (i was incremented after use)
    j = --i; // j is 5, i is 5 (i was decremented before use)
    j = i--; // j is 5, i is 4 (i was decremented after use)
    Bit Operators
    ScriptEase contains many operators for operating on the binary bits in a byte or an integer. If you're not familiar with binary and hexadecimal numbering, then you may want to skip this section on Bit Operators.
    ><< shift left: shift all bits left by value
    <<= assignment shift left
      i = 0x146
    i <<= 2;shift i (0x146) left 2, so i = 0x518
    >> shift right: shift all bits right by value
    >>= assignment shift right
      i >>= 3; shift i (0x518) right 3, so i = 0xA3
    & bitwise AND
    &= assignment bitwise and
      i &= 0x35; and i (0xA3) with 0x35, so i = 0x21
    | bitwise OR
    |= assignment bitwise OR
      i |= 0xC5; OR i (0x21) with 0xC4, so i = 0xE5
    ^ bitwise XOR: exclusive OR
    ^= assignment bitwise XOR
      i ^= 0xF329 XOR i (0xE5) with 0xF329,
    so i = 0xF3CC
    ~ Bitwise complement: (turn 0 bits to 1, and 1 to 0)
      i = ~i;complement i (0xF3CC),
    so i = 0xFFFF0C33
    Logical Operators and Conditional Expressions
    Logical operators compare two values and evalute whether the resulting expression is true or false, where false is represented by zero, and true means anything that is not false (i.e., not zero). A variable or any other expression by itself can be true or false (i.e., non-zero or zero). An expression that does a comparison is called a conditional expression.

    Note that there can be many values that are evaluated as true; everything, in fact, except 0. Therefore it is safer to compare things to false (with only one possible value) than to true (with many). These expressions can be combined with logic operators to make complex true/false decisions.

    The logical operators are usually used with statements that will perform different actions based on how the conditional expression evaluates. As an example, let's suppose you were designing a simple guessing game. The computer thinks of a number between 1 and 100, and you guess what it is. The computer will tell you if you're right or not, and whether your guess is higher or lower than the target number. The script might have a structure similar to the one below (GetTheGuess() is a function that gets your guess).

         guess = GetTheGuess(); //get the user input
         if (guess > target_number){
            ...guess is too high...
         }
         if (guess < target_number){
            ...guess is too low...
         }
         if (guess == target_number){
            ...you guessed the number!...
         }
    The if statement, used in the example above, is described in the next section of this manual. This is a very simple example, but it illustrates how logical operators can be used to make decisions in ScriptEase.

    The logical operators are:
    ! NOT: opposite of decision. If (a + b) is true (i.e., does not equal zero), then !(a + b) is false.
    && AND: true if and only if both expressions are true. Since both expressions must be true for the statement as a whole to be true, if the first expression is false there is no need to evaluate the second expression, since the whole expression is false.
    || OR: true if either expression is true. Since only one of the expressions in the OR statement needs to be true for the expression to evaluate as true, if the first expression evaluates as true the processor returns true and doesn't bother with evaluating the second.
    == EQUALITY: true if the values are equal, otherwise it is false
    * DO NOT CONFUSE this with `=' used for assignment *
    != INEQUALITY: true if the values are not equal, else false
    < LESS THAN: a < b is true if a is less than b.
    > GREATER THAN: a > b is true if a is greater than b.
    <= LESS THAN OR EQUAL TO: a <= b is true if a is less than or equal to b.
    >= GREATER THAN OR EQUAL TO: a >= b is true if a is greater than b.
    Notice the difference between one equals sign (=), used to state that a variable has a certain value; and two equals signs (==), used to test for equality. If you use one equals sign when you mean two, your script will not function the way you want it to. This is a common pitfall even among experienced programmers. Unfortunately, the two meanings of equals must be kept separate, since there are times where you have to use them both in the same statement and there is no way the computer can differentiate them by context.

    Flow Decisions:Loops, Conditions, and Switches
    This section describes the statements that control the flow of your program. You use these statements to tell your program how to make decisions. You'll notice blocks of code are often indented; this makes the code much easier to read.

    if statement
    The if statement is the most commonly used mechanism for making decisions in a program. It allows you to test a condition and act on it. If an if statement finds the condition you test to be true, the block or statement of code following it will be executed: If you are hungry, then eat something. If the condition tests false, the processor will skip over the block or statement and execute the code that follows it.

      if ( goo < 10 )
      {
        Clib.printf("goo is smaller than 10\n");
      }
      Clib.printf("Print this, regardless of goo's value.")
    else statement
    The else statement is an extension of the if statement. It allows you to tell your program to do something else if the condition in the if statement was found to be false. In ScriptEase code, it looks like this:
         if ( goo < 10 ) {
            Clib.printf("goo is smaller than 10\n");
         }
         else {
            Clib.printf("goo is not smaller than 10\n");
         }
    To make more complex decisions, else can be combined with if to match one out of a number of possible conditions. The following code demonstrates the if, else, and else if statements:
      if ( goo < 10 ) {
        Clib.printf("goo is less than 10\n");
        if ( goo < 0 )
        {
          Clib.printf("negative goo is less than 10\n");
        }
      }
      else if ( goo > 10 )
      {
        Clib.printf("goo is greater than 10\n");
      }
      else
      {
        Clib.printf("goo is 10\n");
      }
    while statement
    The while is used to execute a particular section of code over and over again until an expression evaluates as false.
         while (expression){
             DoSomething()
          }
    When the interpreter comes across a while statement it first tests to see whether the expression is true or not. If it is, it will carry out the statement or block following it (in this case the function DoSomething()). Then it will test the expression again. This loop repeats until the test evaluates to false, whereupon the program jumps over the block of code associated with the while statement and continues execution.

    The first example in this chapter uses a while statement:

         while( ThereAreUncalledNamesOnTheList() != false){
            name=GetNameFromTheList();
            CallthePerson(name);
            LeaveTheMessage();
         }
    do {...} while
    This is different from the while statement in that the code block is executed at least once, before the test condition is checked.
          do {
             value++;
             ProcessData(value);
          } while( value < 100 );
    The code used to demonstrate the while statement could also be written this way:
         do {
           name=GetNameFromTheList();
           CallthePerson(name);
           LeaveTheMessage();
          while (name != TheLastNameOnTheList());
    Of course, if there are no names on the list, the script will run into problems!

    for statement
    The for statement is a special looping statement. It allows for more precise control of the number of times a section of code is executed. The for statement takes the following form.

         for ( initialization; conditional; loop_expression ){
            statement
         }
    The initialization is performed first. Then the conditional is tested. If the conditional is true (or if there is no conditional expression), the statement is executed. Then the loop_expression is executed, and the loop begins again, testing the conditional and executing the code following it if it is true. If the conditional is false then the statement will not be executed and the program continues with the next line of code after the statement. For example, the following code will print out the numbers from 0 to 9:
         for (x=0; x<10; x++){
            Clib.printf(x);
         }
    None of the statements that appear in the parenthesis following the for statement are mandatory, so the above code demonstrating the while statement would be rewritten this way if you preferred to use a for statement:
         for( ; ThereAreUncalledNamesOnTheList() ; ){
            name=GetNameFromTheList();
            CallthePerson(name);
            LeaveTheMessage();
         }
    Since we aren't keeping track of the number of iterations in the loop, there is no need to have an initialization or loop_expression statement. You can use an empty for statement to create an endless loop (this is not recommended!):
      for(;;)
      {
        //the code in this block will repeat forever,
        //unless the program breaks out of the for loop
      }
    break and continue
    break and continue are used to control the behavior of the looping statements for, while, and do.

    break terminates the innermost loop (for, while, or do). The program resumes execution on the next line following the loop. The break statement is also used at the close of a case statement (see below). This bit of code does nothing but illustrate the break statement:

         for(;;){
            break;
         }
    continue jumps to the test condition in the nearest do or while loop, and jumps to the loop_expression in the nearest for loop (i.e., jumps to the next iteration of the loop).

    switch, case, and default
    The switch statement is a fancy way of making a decision based on the value of a variable or statement. The switch statement follows this format:

         switch( switch_variable ) {
           case value1:
               statement1
               break;
           case value2:
               statement2
           break;
           case value3:
           statement3
           break;
           case value4:
           statement4
           break;
           case value5:
           statement5
               break;
           ...    
           default:
               default_statement
               break;
         }
    switch_variable is evaluated, and then it is compared to all of the values in the case statements (value1, value2, value3, etc...) until a match is found. The statement (or statements) following the matched case are then executed until the end of the switch block is reached or until a break statement exits the switch block. If no match is found, the default: statement is executed if there is one.

    For example, suppose you had a series of account numbers, each beginning with a letter that determines what type of account it is. You can use a switch statement to carry out actions depending on that first letter. The same can be accomplished with a series of nested if statements, but that requires a lot more typing and is harder to read.

         switch ( key[0] ) {
            case `A':
               printf("A");//handle `A' accounts...
               break;
            case `B':
               printf("B");//handle `B' accounts...
               break;
            case `C':
               printf("C");//handle `C' accounts...
               break;
            default:
               printf("nvalid account number entered.\n");
               break;
         }
    A common mistake is to omit a break statement. In the preceding example, if the break after the printf("B") statement were omitted the computer would print both "B" and "C", because when a match for a case statement is found, the computer will execute commands until a break statement is encountered.

    goto and labels
    You may jump to any location within a function block (see functions) by using the goto statement. The syntax is:

         goto LABEL;
    where LABEL is an identifier followed by a colon (:).
         beginning:
         a = getche(); //get a value for a
         if (a<2)
           goto beginning;
         printf("%d", a);
    gotos should be used sparingly, for they make it difficult to track program flow.

    Conditional Operator ?:
    The conditional operator is a strange-looking statement that is simply a useful shortcut. It is a limited variation of the IF statement. The syntax is:

         test_expression ? expression_if_true : expression_if_false
    First, test_expression is evaluated. If test_expression is non-zero (true) then expression_if_true is evaluated and the value of the entire expression replaced by the value of expression_if_true. If test_expression is false, then expression_if_false is evaluated and the value of the entire expression is that of expression_if_false.

    For example:

      foo = ( 5 < 6 ) ? 100 : 200;       // foo is set to 100
      printf("Name is %s\n",(null==name) ? "unknown" : name);
    To see how the conditional operator is a shortcut, consider that this if/else code to get the maximum of two numbers:
         if ( Num1 < Num2 )
           MaxNum = Num2;
         else
           MaxNum = Num1
    is equivalent to this conditional operator code:
         MaxNum = ( Num1 < Num2 ) ? Num2 : Num1 ;
    Functions
    A function is an independent section of code that receives information from a program and performs some action on it. Once a function has been written, you won't have to think again about how to perform that action; you just call the function and let it handle the work for you. You only need to know what information the function needs to receive (parameters) and whether it returns a value back to the statement that called it.

    Clib.printf() is an example of a function, providing an easy way to display formatted text. It receives a template string and variables from the program that called it, prints out the formatted string, and returns the number of characters printed to the program that called it. In the case of Clib.printf(), people rarely look at the return value.

    Functions can perform actions of any complexity, but are used in statements just like variables. Almost any place where you can use a variable in a statement you can use a function instead. For example, let's suppose you had a function called DoubleAndDivideByFive(number), which takes the variable number , doubles it and divides the result by five. The computer will interpret

         a=DoubleNumberAndDivideByFive(number)
    as
         a=(number*2)/5
    This is a simple function, so the value of one method over the other is not clear in this case. But functions can get very complex; instead of "DoubleandDivideByFive()", think "RecalculateBasedOnCurrentInterestRate()."

    Any valid variable name may be used as a function name. Functions are distinguished from variables by the parenthesis that follow them. Like comments, using descriptive function names helps you keep track of what is going on with your script.

    Several sets of built-in functions are included as part of the ScriptEase interpreter. These functions are all described in this manual. They are internal to the interpreter, and may be used at any time. In addition, ScriptEase ships with a number of external libraries or .jsh files. These functions must be explicitly included in your script to use them; see the description of the #include statement.

    ScriptEase allows you to have two functions with the same name. The interpreter will use the function nearest the end of the script; that is, the last function to load is the one that will be executed. This way you can write functions that supersede the ones included in the processor or the .jsh files.

    Function definition
    A function definition consists the keyword 'function' followed by the name of the function and a list of parameters to it in parenthses.

         function FunctionName(Parameter1,Parameter2,Parameter3)
         {
            statements...
            return result;
         }
    A call is made to a function in this format:
         FunctionName(Value1,Value2,Value3)
    A call to FunctionName() will result in the execution of FunctionName() with the parameters passed, and then be equivalent in the calling code statement to whatever value FunctionName() returns.

    Function return statement
    The return statement causes a function to return to the code that initially called the function. The calling code will receive the value that the function returned, and any code in the function following the return statement will be ignored. The value to be returned may be enclosed in parenthesis.

         DoubleAndDivideBy5(a)
         {
            return (a*2)/5
         }
    Here is an example of a script using the above function:
         a = DoubleAndDivideBy5(10);
         a = DoubleAndDivideBy5(20);
         Clib.printf(a + b);
    This script will print out the value "12".

    Some functions don't return anything, and therefore don't have return statements. These functions are called void functions. Void functions return no value to the calling code. A function that just prints out a message, for example, is a void function:

         GreetingFunction()
         {
           Clib.printf("Hello and welcome to ScriptEase!");
    Passing variables to functions
    ScriptEase uses different methods to pass variables to functions, depending on the type of variable being passed. This ensures that the information gets to the function in the most complete and logical way.

    Strings, numbers, and boolean variables are passed by value. The value of the variable is passed to the function; if the function changes the value, the changes will not be visible outside of the function where the change took place.

    Objects are passed by reference. When ScriptEase passes an object, instead of passing the value of the object (i.e., the values of each of its properties and methods), it passes a reference to the object, indicating where in the computer's memory the values of the object's properties are stored. If you make a change in one of the objects values, that change will be reflected throughout the script.

    Function Example
    This code demonstrates a simple function that multiplies two integers by adding them:

      num1 = 4;
      num2 = 6;
      // use the standard method of multiplying numbers
      Clib.printf("%d times %d is %d.\n",num1,num2,num1*num2);
    
      // now call our function to do the same thing
      Clib.printf("%d times %d is %d.\n",num1,num2,
                  Multiply(num1,num2));
    
      // declare a function that multiplies two integers. Notice
      // that the integers are defined as i and j, so that's how
      // they'll be called in this function, no matter what they
      // were named in the calling code. This function will
      // return i added to itself j times. (It will fail if j<0).
    
      function Multiply(i,j)
      {
        total = 0;
        for ( count = 0; count < j; count++ )
          total += i;
        return(total); // caller will receive this value
      }
    When executed, this code will return two identical strings, "4 times 6 is 24." This example demonstrates several features of functions. Notice that in calling Clib.printf() the parameter "num1*num2" is not passed to Clib.printf(), but the result of "num1*num2" is. Likewise, "Multiply(num1, num2)" is not a parameter to Clib.printf(); instead, Clib.printf() receives the return value of Multiply() as its parameter.

    Function properties -- arguments[]
    The arguments[] property is an array of all of the arguments passed to the function. In the example above, two arguments were passed to the function Multiply(). In the function definition they are stored in the variables i and j. However, you can also use the arguments property to access the variables. The first variable passed to the function is referred to as Multiply.arguments[0], and the second as Multiply.arguments[1]. If you had passed a third parameter, it would be called Multiply.arguments[2]. The total number of parameters passed is represented by the variable Multiply.arguments.length.

    The most useful aspect of this property is that it allows you to have functions with an indefinite number of arguments. Here is an example of a function that takes however many arguments you pass it and returns the sum of all of them:

         function SumAll()
         {
            total = 0;
            for (ssk = 0; ssk<SumAll.arguments.length; ssk++){
              total += SumAll.arguments[ssk];
            }
            return total;
         }
    Function recursion
    A recursive function is a function that calls itself, or calls some other function that then goes back and calls the function that first called it. Be aware that recursion has its limits; if a function calls itself too many times the script will run out of memory and abort. For example, the following function, factor(), factors a number. Factoring is an ideal candidate for recursion because it is a repetitive process where the result of one factor is then itself factored according to the same rules.
      factor(i)// recursive function to print all factors of i,
      {// and return the number of factors in i
        if ( 2 <= i )
        {
          for ( test = 2; test <= i; test++ )
          {
            if ( 0 == (i % test) )
            {
              // found a factor, so print this factor then call
              // factor() recursively to find the next factor
              return( 1 + factor(i/test) );
            }
          }
        }
        // if this point was reached, then factor not found
        return( 0 );
      }
    Error checking for functions
    Some functions will return a special value if they failed to do what they are supposed to do. For example, the function Clib.fopen() opens or creates a file for a script to read or write to. But suppose that the computer was unable to open the file for some reason. In that case, the fopen function returns null.

    If you try to read or write to the file you will get all kinds of errors, because the file was never opened. To prevent this from happening, make sure that the fopen didn't return null when it opened the file. Instead of just calling fopen like this:

         fp = Clib.fopen("myfile.txt", "r");
         //check to make sure that null has not been returned:
         if (null == (fp = Clib.fopen("myfile.txt", "r"))){
            ErrorMsg("Clib.fopen returned null");
         }
    You will still have to abort the script in this case, but at least you know why.

    cfunction keyword
    The ScriptEase cfunction keyword defines a function whose behavior is somewhat different than that of standard functions. The cfunction keyword is provided for the convenience of C programmers who are used to the way the C language handles functions and variables. The cfunction is not standard JavaScript and should not be used if you intend to run your scripts with other interpreters.

    In a function declared with the cfunction keyword, there is no data conversion between numbers and strings. Instead of being treated as a special data type, strings are considered to be an array of bytes (i.e. numbers). The first character of the string is assigned to string[0], the second to string[1], and so on until the end of the string.

    The last character of a string is always '\0', which defines the end of the string. If you assign a variable to a string, defining the string in double quotes, this character will automatically be appended to the end of the string. To assign a string to a variable without appending the '\0' character, put the string in single quotes. This is most often done with single characters. For example, if

         boy = "m";
         girl = 'm';
    the variable boy is an array: boy[0] = 'm' and boy[1] = '\0'. The variable girl is a character, containing the letter 'm'. Internally, characters are converted to numbers according to the ASCII standard.

    You can change the contents of strings (or parts of them) by assigning a new character value a character's array member. For example:

         string = "file"
         string[0] = 'b'
    This snippet of code creates a string containing the word "bile". There is no automatic type conversion in functions defined with the cfunction keyword. If you try to add a number to a string, instead of converting the number to a string and concatenating the two, the starting point of the string will be shifted forward by the number of characters in number. For example, the statement:
    "This is a test" + 3
    would evaluate to "This is a test3" in a standard function. In a cfunction, however, this statement would evaluate to "s is a test". The starting point of the string has been shifted by three, so that string[0] is now 's' instead of 'T'. The `T', `h', and `i' of the original string will be found at indices [-3], [-2], and [-1], respectively.

    The methods and properties normally available to strings are available to strings in cfunctions.

    Variables passed to cfunctions are passed by reference. If you have two variables:

         George = "one"
         Martha = "one"
    and you compare them with the `==' operator, the comparison will evaluate as false, not true as you might expect. This is because while George and Martha have the same value, they are not the same variable, and therefore are not equal to each other. In functions declared with the function keyword, variables are compared by value, so the actual values of George and Martha are compared. In this case the result of the comparison is true. Variable Scope
    Variables in ScriptEase may be either global or local. Most variables are local: they only have meaning within the function in which they were created. If you want to use the variable in some other function, you must explicitly pass the variable to that function. Note that two identically-named local variables in different functions are not the same variable (unless, of course, one function passed the variable to the other). Each instance of a recursive function has its own set of local variables. In other words, a variable that is not referenced outside of a function only has meaning (and that meaning is unique) while the code for that function is executing.

    Global variables, on the other hand, are visible to all functions in a script. There are two ways to make a global variable: you can declare it outside of any function, or you can assign it to the global object when you create it. The example below demonstrates the difference between global and local variables. foo is a global variable created outside of any function, while roo is a global variable created inside of a function (note that the name of the global object is not capitalized). goo is the name for two different local variables, each with a different value and each valid only within the function where they were created.

         foo=8
         function Afunction()
         {
            goo = 6;
            Clib.printf(goo + foo);
            global.roo = 10;
         }
         
         function Anotherfunction()
         {
            goo = 8;
            Clib.printf(goo + foo);
            Clib.printf(roo)
         }
    It is possible to have local and global variables with the same name. In this case, the var keyword must be used to define the local variable. The global variable may still be referenced as a property of the Global object (Global.variable, e.g.), but the variable name used by itself will refer to the local variable.

    Objects
    ScriptEase allows you to group variables and functions together and assign a variable name to the entire group. A compound variable of this sort is called an object; each individual item that makes up the object is called a property of the object. This is an expansion of the `structure' data type of C and earlier versions of ScriptEase in that functions may now be included as structure members.

    Variables that are parts of objects are called properties of the object. To refer to a property of an object, you use both the name of the object and the name of its property, separated by the `.' operator. Any valid variable name may be used as a property name. For example, if you had a rectangle object with height and width properities, you would assign their values like this:

         rectangle.height = 4
         rectangle.width = 6
    If the properties do not exist, they will be created. Properties that have not had values assigned to them are of the special value `undefined'.

    Objects do not need to be explicitly created in ScriptEase. However, for compatibility with JavaScript ScriptEase provides the `new' operator, which creates a new object. For example, the code

         block = new Object();
    creates an object called block with no members.

    Predefining Objects
    If you have a script that will use a number of similar objects, you can create a function that automatically creates objects that conform to a certain pattern. All of the similar objects are said to belong to the same `class' of object. The function used to create the objects is called a constructor function.

    The constructor function uses the special `this' keyword to initialize its values. For example, to create a rectangle object with width and height properties as in the example above, you would use a constructor function like this:

         function Rectangle(width, height)
         {
            this.width = width;
            this.height = height;
         }
    Once you have created the constructor function, you can use it to create instances of the object: LASS="Code-in-Body">
        joe = new Rectangle(3,4)
        sally = new Rectangle(5,3);
    This will create two rectangle objects, one named joe with a width of 3 and a height of 4, and one named sally with a width of 5 and a height of 3. The values passed as parameters are assigned to the properties of the newly created object.

    This particular example creates a class of `Rectangle' objects; each copy of the Rectangle object is called an instance of the object. All of the instances of a class share the same properties, although a particular instance of the class may have additional properties unique to it.

    Methods - assigning functions to objects
    Objects may contain functions as well as variables. A function that has been assigned to an object is called a method. A method can be assigned to a single instance of an object, or to an entire class of objects (as defined by a constructor function).

    Like a constructor function, a method refers to its variables with the `this' operator. Here is an example of a method that computes the area of a rectangle:

         function rectangle_area()
         {
            this.width * this.height
         }
    Because there are no parameters passed to it, this function is meaningless unless it is called from an object. It needs to have an object to provide values for this.width and this.height.

    A method is assigned to an object like this:

    joe.area = rectangle_area;
    The function will now use the values for height and width that were defined when we created the rectangle object joe.

    Methods may also be defined as part of an object's constructor function. For example, the following code:

         function rectangle_area()
         {
            this.width * this.height
         }
         
         function Rectangle(width, height)
         {
            this.width = width;
            this.height = height;
            this.area = rectangle_area;
         }
    creates an object class `Rectangle' with the rectangle_area method included as one of its properties. The method is available to any instance of the class:
         joe = Rectangle(3,4)
         sally = Rectangle(5,3);
         area1 = joe.area
         area2 = sally.area
    This code will set the variable area1's value to 12 (3 * 4) and area2's value to 15 (5 * 3)

    Object prototypes
    In addition to being created in an object's constructor function, an object's variables may be initialized in an object prototype. All instances of an object inherit the methods and properties of its prototype. When an object property that has not been explicitly assigned a value (either in the object's constructor function or somewhere else in the script) is accessed, the prototype is consulted and its variable provides the value for the property.

    When the two Rectangles joe and sally were created in the previous section, they were each assigned an area method. Memory was allocated for this function twice, even though the method is exactly the same in each instance. This redundant memory waste can be avoided by putting the shared function (or property) in the object's prototype. Then all instances of the object will use the same function instead of each using their own copy of it. This ensures that all instances of the object use the same mechanism for their methods and conserves the amount of memory needed to run your script.

    Here is how we'd create the Rectangle object with the area method in a prototype:

         function rectangle_area()
         {
         this.width * this.height
         }
         
         function Rectangle(width, height)
         {
         this.width = width;
         this.height = height;
         }
          
         Rectangle.prototype.area = rectangle_area;
    You can now access the rectangle_area method as a property of any Rectangle object:
         area1 = joe.area;
         area2 = sally.area;
    You can add methods and data to an object's prototype at any time. The object class must be defined, but there don't have to create an instance of the object before assigning it prototype values. If you assign a method or data to an object prototype, all instances of that object will be updated to include the prototype.

    If you try to write to an property variable that is assigned through a prototype, a new variable will be created for the newly assigned value. This value will be used for the value of this instance of the object's property; all other instances of the object will still refer to the prototype for their values. If for the sake of example we assume that joe is a special Rectangle, whose area is equal to three times its width plus half its height, we can modify joe like this:

         joe.area = joe_area;
       function joe_area()
       {
          return (this.width * 3) + (this.height/2);
       }
    This creates a value (in this case, a function) for joe.area that supercedes the prototype value. Sally.area will still be the default value defined by the prototype; joe will use the new definition for its area method.

    for...in
    The for...in statement is a way to loop through all of the properties of an object. It takes the following form:

         for (property in object){ 
            DoSomething(object.property)
         }
    where object is a the name of an object previously defined in the script. Using the for...in statement in this way, the statement block will execute once for every property of the object. For each iteration of the loop, `property' contains the name of one of the properties of object and may be accessed with `object.property'. Note that properties marked with the DontEnum attribute won't be counted in the for...in statement.

    with
    The with statement is used to save time when you are working with objects. It lets you assign a default object to a statement block, so you needn't put the object name in front of its methods; the object is assumed. For example:

         with (Clib){
            srand();
            xxx = rand() % 5;
            sprintf(string, "The number is %d", xxx);
         }
    The Clib methods srand(), rand(), and sprintf() in the sample above will all be called as if they had been written with the prefixed "Clib." All code in the block following the with statement is treated as if the methods associated with the with object were global functions. Global functions are still treated normally, i.e. you don't need to prefix global. to them unless you are distinguishing between two like-named functions common to both objects.

    If you were to jump to another part of the code from within the with statement, the with statement would no longer apply. In other words, the with statement only applies to the code within the block, regardless of how the processor accesses or leaves the block.

    If you want to include two objects in the with filter, do it like this:

         with (Math) with (Clib){
            ...
         }
    Arrays
    An array is a special kind of object. Instead of refering to its properties with their name and the `.' operator, an array uses a numeric or string identifier, called an index, to identify them. The index follows the array name in brackets. Array elements do not all need to be of the same data type.

    The following are all valid arrays:

         array[0] = "fish";
         array["seven"] = "fowl";
         array[foo] = "creeping things"
         array[goo + 1] = "etc."
    The variables foo and goo must represent numbers or strings.

    Arrays allow you to use a variable as an object's property identifier. The variable will then be interpreted and the corresponding value applied to the array.

    For example:

         age[0] = "ten"
         age[1] = "not ten";
         if (yourAge == 10) ckc = 0
         else ckc = 1;
         printf ("You are " + sge[ckc] + " years old.");
    Since an array is a type of object, you can use array notation to access object properties. For example, if
         object.red = "apple";
         object.yellow = "banana"
         if (condition == true) indexVariable = "red"
         else indexVariable = "yellow";
         printf(object[indexVariable]);
    This code will print out "apple" or "banana" depending on whether condition is true or not.

    Another advantage of arrays is that you can use a number for an identifier, rather than a string. This gives you an easy way to access the members of the array. For example, suppose you wanted to keep track of how many jelly beans you ate each day, so you can graph your jelly bean consumption at the end of the month. Arrays are ideal for storing this kind of data:

         April[1] = 233;
         April[2] = 344;
         April[3] = 155;
         April[4] = 32; (...)
    Now you have all your data stored conveniently in one variable. You can find out how many jelly beans you ate on day x by checking the value of April[x]:
      for(x=1; x<32; x++)
      {
        printf("On April " + x + " I ate " + April[x]
               + " jellybeans.\n" );
      }
    Note that arrays do not have to be continuous. If you went away for January 5th and 6th and ate no jelly beans, your next datum could be
         January[7] = 539
    If you then tried to acces the value of January[5] or January[6], you'd get an undefined value back, because these two variables haven't been assigned a value yet.

    Usually arrays start at index [0], not index [1]. This is consistent with C, C++, and JavaScript.

    Creating Arrays
    Since arrays are objects, you can create them in the same way:

        anArray = new Object();
         array[0] = 5;
         array[1] = 4;
         array[2] = 3...
    You can also use the predifined Array() constructor function. The Array() function may be called in three different ways. If called with no parameters,
         a = new Array();
    it creates an empty array, with no elements. This is the equivalent to calling
         a = new Object();
    except that the array methods and properties (see below) are only available to arrays created with the Array() constructor.

    You can also pass a number to the Array() function. This will create an array with a length of the number you passed:

         b = new Array(31)
    creates an array with a length of 31.

    Finally, you can pass a number of elements to the Array() function. This creates an array containing all of the parameters passed. For example:

         c = new Array(5, 4, 3, 2, 1, "blastoff");
    creates an array with a length of 6. c[0] is set to 5, c[1] is set to 4, and so on up to c[5], which is set to the string "blast off".

    Methods and properties of arrays
    When an array is created with the Array() constructor function, a number of methods and properties become available to it. Array.length
    The Array() constructor function contains a length property, which will return one more than the largest index of the array. Note that this is not necessarily the same as the number of elements in the array, since the elements don't have to be contiguous.

    For example, suppose we had two arrays "ant" and "bee", with the following elements:

        ant[0] = 3  bee[0] = 88
        ant[1] = 4  bee[3] = 99
        ant[2] = 5
        ant[3] = 6
    The length property of both ant and bee is equal to 4, even though ant has twice as many elements as bee does.

    By changing the value of the length property, you can remove array elements. For example, if we change ant.length to 2, ant will only have the first two members; the values stored at the other indices will be lost. If we set bee.length to 2, then bee will consist of two members: bee[0], with a value of 88, and bee[1], with an undefined value.

    Array.join
    Arrays created with the Array() constructor function have three methods to help organize an array's elements. The first is the join() method, which creates a string of all of the array elements. Join() has an optional parameter, a string which represents the character or characters that will separate the array elements. If no parameter is supplied, a comma is used as the separator character. For example:

         a = new Array(3, 5, 6, 3)
         string = a.join();
    will set the value of `string' to "3,5,6,3". Likewise
         a = new Array(3, 5, 6, 3)
         string = a.join("*/*");
    creates the string "3*/*5*/*6*/*3".

    Array.sort()
    The sort() method sorts members of an array and puts them in alphabetic order. Elements will be converted to strings to do the conversion, which may cause some confusion. For example, the following code:

         a = new Array(32, 5, 6, 3)
         a.sort(); 
         string = a.join();
    creates a string "3, 32, 5, 6".

    This is probably not the behavior you want in a sort function. Fortunately, the sort() method allows you to specify a different way to sort the array elements. The name of the function you are using to compare values is passed as the only parameter to sort().

    If a compare function is supplied, the array elements are sorted according to the return value of the compare function. If a and b are two elements being compared, then:

    If compareFunction(a, b) is less than zero, sort b to a lower index than a.
    If compareFunction(a, b) returns zero, leave a and b unchanged with respect to each other, but sorted with respect to all different elements.
    If compareFunction(a, b) is greater than zero, sort b to a higher index than a.

    If you want to compare numbers instead of strings, you can use the following function to compare values:

         function compareNumbers(a, b) { 
            return a - b
         }
    Array.reverse
    The reverse() method switches the order of the elements of an array, so that the last element becomes the first. If you had the following code:
         array[0] = "ant"
         array[1] = "bee"
         array[2] = "wasp"
         array.reverse()
    It would produce the following array:
         array[0] = "wasp"
     array[1] = "bee"
     array[2] = "ant"
    The global object and its properties
    Global variables are members of the global object. To access global properties, you do not need to use the Object name. For example, to access the isNan function, which tests to see whether a value is equal to the special Not a Number value, you can call either isNAN(value); or global.isNaN(value);

    eval(expression) This method evaluates whatever is represented by the expression variable. If expression is not a string variable, it will be returned. Calling eval(5) returns the value 5, e.g.

    If expression is a string variable, the processor tries to interpret the string as if it were Javascript code. If successful, it will return the last variable that it was working with (the return variable, e.g.). If it is not successful, it will return the value undefined.

    parseInt
    This function converts an alphanumeric string to an integral number. The first parameter, string, is the string to be converted; the second parameter is an optional number indicating which base the number is to be written in. If this parameter is not supplied, it defaults to base 10 (decimal). If the first digit of string is a zero, radix will default to base 8 (consistant with normal octal notation); if the first digit is zero followed by an `x', it will default to base 16 (normal hexadecimal notation)

    Whitespace characters at the beginning of the string are ignored. The first non-whitespace character must be either a digit or a minus sign (-). All numeric characters following the string will be read, up to the first non-numeric character, and the result will be converted into a number, expressed in the base specified by the radix variable. All characters including and following the first non-numeric character are ignored. If the string is unable to be converted to a number, the special value NaN will be returned.

    parseFloat(string)
    This function is much like parseInt() (see above) except that it reads decimal numbers. In other words, the first `.' in the string is considered to be a decimal point and any digits following are the decimal part of the number. parseFloat doesn't take a second parameter.

    escape(string) The escape string takes a string and escapes the special characters so that the string may be used with a URL. All uppercase and lowercase letters, numbers, and the following symbos: @ * + - . / will appear in the string. All other characters will be replaced with their respective UNICODE sequence.

    unescape(string)
    This function is the reverse of the escape function, removing escape sequences from the string and replacing them with the relevant character.

    defined(variable)
    This function returns true if the variable is defined. If the variable is of type undefined, it returns false.

    undefine(variable)
    This function changes the type of a variable to undefined. Any data contained in the variable will be lost. This function is identical to the delete keyword.

    isNaN(number)
    This function returns true if the variable number is a number (or can be converted to a number. Otherwise it returns false.

    isFinite(number)
    This function returns true if the variable number is (or can be converted to) a number; if the variable evaluates as Nan, Number.POSITIVE_INFINITY or Number.NEGATIVE_INFINITY the function returns false.

    Properties and methods of the basic data types
    The basic data types (Number, String, etc.) have properties and methods assigned to them that may be used with any variable of that type. In other words, all String variables may use the String methods, etc.

    The properties and methods of the basic data types are retrieved in the same way as from objects. If you have a string variable called name and you want to know the size of the string, you can access the length property of the string to get this information:

    x = name.length
    The following two properties are common to all variables. For the most part, they are used internally by the processor, but you may use them if you wish to.

    .toString()
    This method returns the value of the variable expressed as a string

    .valueOf()
    This method returns the value of the variable.

    String properties and methods
    Often you will need to get information about a string, such as its length or the position of a certain character. You may obtain this information with one of the string properties and methods described below. To access properties and methods, use the name of the string, followed by the property operator `.', followed by the name of the property or method you are accessing. The properties and methods available to strings are described below.

    String.length
    The length of a string may be obtained by using the length property. For example:

    string = "No, thank you."
    printf("%d", string.length)
    will print out the number 14, the number of characters in the string.

    String.charAt()
    The charAt method tells you what character is at a certain place in the string. If you want to know the first character in a string, you can use

    string.charAt(0);
    To get the last character in a string, use

    string.charAt(string.length - 1);

    String.charCodeAt(index)
    This method returns a number representing the unicode valude of the character at the index position of this string. If there is no character at that position, it will return NaN.

    String.fromCharCode(char1, char2...)
    This method returns a string created from the character codes that are passed to it as parameters. The arguments passed to this method are assumed to be unicode characters.

    String.substring()
    Use the substring method to retrieve a section of the string. For example, if you want the first ten characters in the string, you would write substring = string.substring(0,9);

    String.indexOf(substring [, offset])
    The indexOf method returns the index of the first appearance of the specified substring. For example,

    string.indexOf("a") Returns the position of the first `a' appearing in the string. String.indexOf() may take an optional second parameter. This parameter is an integer indicating the index where the method is to start searching the string. For example,

         magicWord = "abracadabra";
         secondA = magicWord.indexOf("a", 1);
    will return `3' , the index of the first "a" in the string when you start searching from the second letter of the string (which is index 1 - remember that string indices start at 0).

    String.lastIndexOf(substring [, offset])
    This is the same as String.indexOf(), except that it finds the last occurrence of the character rather than the first.

    String.toUpperCase(), String.toLowerCase()
    Strings have two built in methods for changing the case of the string: string.toUpperCase(), which returns a copy of the string with all of the letters changed to upper case; and string.toLowerCase(), which returns a copy of the string with all of the letters changed to lower case.

    String.split([substring])
    The string method string.split() will split a string up into an array of strings. This method takes one optional parameter, a substring that determines where the string will be split. If there is no delimeter, the entire string will be returned.

    For example, if we wanted to create an array of all of the words in a sentence, we could do it like this:

         sentence = "I am not a crook"
         wordArray = sentence.split(' ');
    The Number object
    Variables of the type `Number' may be treated as if they were objects of this type.In addition to the toString and valueOf properties, the following properties are part of the Number object:

    Number.MAX_VALUE
    The largest possible number that ScriptEase can represent.

    Number.MIN_VALUE
    The smallest possible number that ScriptEase can represent.

    Number.NaN
    Not a Number - a special value that is returned when a calculation returns an undefined value (dividing by zero, e.g.).

    Number.POSITIVE_INFINITY
    Special value to represent infinity.

    Number.NEGATIVE_INFINITY
    Special value to represent negative infinity.

    The Buffer object
    The buffer object provides a way to manipulate data at a very basic level. It is needed whenever the relative location of data in memory is important. Any type of data may be stored in a buffer object. Buffer objects have two important properties that determine how data is read from them: the .cursor property and the .window property. The cursor property indicates the place in the buffer that data will be read from. The window property indicates how much data is to be considered.

    newBuffer = new Buffer(size);
    This simply creates an empty buffer of the specified size. To create a buffer and assign data to it, create the new Buffer with one of the following syntaxes:

    newBuffer = new Buffer(string [, offset [,size]][ ,isASCII])
    This syntax copies the string variable string into the buffer object. If offset is specified, the Buffer will begin at the offset specified. I.e., if the string is "bread" and the offset is 1, the buffer will contain the string "read". If size is provided, only that many bytes of data past offset will be read. The final optional variable, isASCII, is a boolean value which must be set to true if you are using ASCII strings. The default (false) assumes you are using UNICODE strings. For example, the following code:

         newBuffer = new Buffer("starfish", 0, 4);
    will create a buffer newBuffer containing the UNICODE string "star". Since UNICODE characters are two bytes each, the size of the buffer will be ten bytes.

    newBuffer = new Buffer(array [,offset [, size]][,signed])
    This syntax is used to create a buffer from an array of numbers. If signed is set to true, each number is truncated for an integer in [-127-127]; if false, to [0, 255].

    Buffer.size
    The size property of a buffer object is equivalent to the size (in bytes) of the data the buffer is scoping.

    Buffer.cursor
    This property returns the current cursor position in the buffer.

    Buffer.comparableTo(Abuffer)
    This method tests to see whether Abuffer refers to the same internal data as the Buffer object.

    Buffer.compareEnds(Abuffer)
    Checks to see whether ABuffer and the current Buffer object refer to the same data; if so, this method returns the relative values of the ends of their respective windows.

    Buffer.compareStarts()
    This method returns the relative values of the starts of their respective windows. An error is generated if they do not refer to the same data.

    Buffer.getCursor()
    This returns the position of the cursor relative to the absolute beginning of data in the buffer.

    Buffer.getSize()
    This object gets the current window size, i.e. how much data can be read at once.

    Buffer.isValidIndex(index)
    This function determines whether index is a valid index for the buffer.

    Buffer.setCursor(offset)
    This sets the value of the cursor to be equal to whatever offset. Offset must be a number between 0 and Buffer.getMaximumSize().

    Buffer.setSize()
    This method sets the size of the window, i.e. how much data it can read at once.

    Buffer.shift()
    This method shifts the cursor value by the amount specified by offset; this may be a positive or a negative amount. An attempt to shift the cursor past either end of the data will trigger an error.

    Buffer.shiftWindow()
    This method shifts the cursor but the size of the window remains constant. If the cursor is so close to the end of the data that there is not enough to fill the window, the size of window will shrink.

    Buffer Get Methods
    These methods all retrieve data from the buffer. Use the method whose name corresponds to the type of data expected, e.g. use Buffer.getFloat() to retrieve a float. Data will be read from the current cursor position, or at the specified offset from the current cursor position. You can specify whether data is written in big endian or little endian mode with the bigEnd parameter. true directs the processor to store data in big endian mode, and false little endian. This will default to whatever your system defines as standard.

    Buffer.getUint32([offset] [, bigEnd])
    Buffer.getUint16([offset] [, bigEnd])
    Buffer.getFloat([offset] [, bigEnd])
    There is some redundancy among the methods for retrieving characters and strings from the buffer to accommodate the discrepencies between UNICODE and ASCII strings. Buffer.getUNICODEValue() will retrieve a UNICODE character (i.e. 2 bytes) from a buffer, while Buffer.getByte() will retrieve a single byte (i.e., an ASCII character). Buffer.getChar() retrieves a character; whether it is UNICODE or ASCII depends on the defaults set in the interpreter.

    Buffer.getUNICODEValue([offset] [, bigEnd])
    Buffer.getByte([offset] [, bigEnd])
    Buffer.getChar([offset] [, bigEnd])
    Likewise, Buffer.getString will get a string according to the current defaults, while Buffer.getUNICODEString and Buffer.getASCIIString get UNICODE and ASCII strings, respectively. The methods for retrieving strings have an additional optional parameter, length , which specifies the length of the string to be retrieved. Length is in characters, not bytes, and so will be the same regardless of whether you are using ASCII or UNICODE strings. Note that you must supply an offset if you wish to supply a length.

    Buffer.getASCIIString([offset [, length]][, bigEnd])
    Buffer.getUNICODEString([offset [, length]] [, bigEnd])
    Buffer.getString([offset [, length]] [, bigEnd]) Buffer Set Methods
    These methods all write data to the buffer. Use the method whose name corresponds to the type of data being written, e.g. use Buffer.setFloat() to write a float. value is the data to be written to the buffer. Data will be written to the current cursor position, or at the specified offset from the current cursor position. You can specify whether data is written in big endian or little endian mode with the boolean bigEnd parameter: true directs the processor to store data in big endian mode, and false little endian.

    Buffer.setUint32(value [,offset][, bigEnd])
    Buffer.setUint16(value [, offset][, bigEnd])
    Buffer.setFloat(value [, offset][, bigEnd])
    As with the `get' methods, there is redundancy among the methods for writing characters and strings from the buffer to accommodate both UNICODE and ASCII strings. Buffer.setUNICODEValue() will retrieve a UNICODE character (i.e. 2 bytes) from a buffer, while Buffer.setByte() will retrieve a single byte (i.e., an ASCII character). Buffer.setChar() retrieves a character; whether it is UNICODE or ASCII depends on the defaults set in the interpreter.

    Buffer.setUNICODEValue(value [, offset][, bigEnd])
    Buffer.setByte(value [, offset][, bigEnd])
    Buffer.setChar(value [, offset][, bigEnd])
    Likewise, Buffer.setString will read a string according to the current defaults, while Buffer.setUNICODEString and Buffer.setASCIIString get UNICODE and ASCII strings, respectively. The methods for retrieving strings have an additional optional parameter, length , which specifies the length of the string to be retrieved. Length is in characters, not bytes, and so will be the same regardless of whether you are using ASCII or UNICODE strings. Note that you must supply an offset if you wish to supply a length.

    Buffer.setUNICODEString(value [, offset [, length]] [, bigEnd])
    Buffer.setASCIIString(value [, offset [, length]] [, bigEnd])
    Buffer.setString(value [, offset [, length]] [, bigEnd])

    The Math object
    Math.E
    The number value for e, the base of the natural logarithms, which is approximately 2.7182818284590452354.

    Math.LN10
    The number value for the natural logarithm of 10, which is approximately 2.302585092994046.

    Math.LN2
    The number value for the natural logarithm of 2, which is approximately 0.6931471805599453.

    Math.LOG2E
    The number value for the base-2 logarithm of e, the base of the natural logarithms; this value is approximately 1.4426950408889634. (Note that the value of Math.LOG2E is approximately the reciprocal of the value of Math.LN2.) Math.LOG10E
    The number value for the base-10 logarithm of e, the base of the natural logarithms; this value is approximately 0.4342944819032518. (Note that the value of Math.LOG10E is approximately the reciprocal of the value of Math.LN10.)

    Math.PI
    The number value for p, the ratio of the circumference of a circle to its diameter, which is approximately 3.14159265358979323846.

    Math.SQRT1_2
    The number value for the square root of 1/2, which is approximately 0.7071067811865476. (Note that the value of Math.SQRT1_2 is approximately the reciprocal of the value of Math.SQRT2.)

    Math.SQRT2
    The number value for the square root of 2, which is approximately 1.4142135623730951.

    Math.abs(x)
    Returns the absolute value of x. If x is not convertible to a numerical value, returns NaN.

    Math.acos(x)
    Returns the arc cosine of x. The result is expressed in radians and ranges from 0 to p. Returns NaN if x is not convertible to a numerical value, is greater than 1 or less than -1.

    Math.asin(x)
    Returns an implementation-dependent approximation to the arc sine of the argument. The result is expressed in radians and ranges from -p/2 to +p/2. Returns NaN if x is not convertible to a numerical value, is greater than 1 or less than -1.

    Math.atan(x)
    Returns an implementation-dependent approximation to the arc tangent of the argument. The result is expressed in radians and ranges from -p/2 to +p/2.

    Math.atan2(x, y)
    Returns an implementation-dependent approximation to the arc tangent of the quotient y/x of the arguments y and x, where the signs of the arguments are used to determine the quadrant of the result. Note that it is intentional and traditional for the two-argument arc tangent function that the argument named y be first and the argument named x be second. The result is expressed in radians and ranges from -p to +p.

    Math.ciel(x)
    Returns the smallest number value that is not less than the argument and is equal to a mathematical integer. If the argument is already an integer, the result is the argument itself. If x is not convertible to a numerical value, returns NaN.

    Math.cos(x)
    Returns an implementation-dependent approximation to the cosine of the argument. The argument is expressed in radians. If x is not convertible to a numerical value, returns NaN.

    Math.exp(x)
    Returns an implementation-dependent approximation to the exponential function of the argument (e raised to the power of the argument, where e is the base of the natural logarithms). If x is not convertible to a numerical value, returns NaN.

    Math.floor(x)
    Returns the greatest number value that is not greater than the argument and is equal to a mathematical integer. If the argument is already an integer, the result is the argument itself.

    Math.log(x)
    Returns an implementation-dependent approximation to natural logarithm of the argument.

    Math.max(x, y)
    Returns the larger of the two arguments. Returns NaN if either argument cannot be converted to a number.

    Math.min(x, y)
    Returns the smaller of the two arguments. Returns NaN if either argument cannot be converted to a number.

    Math.pow(x, y)
    Returns the value of x to the power of y.

    Math.random()
    Returns a number value with positive sign, greater than or equal to 0 but less than 1. This function takes no arguments.

    Math.round(x)
    Returns the number value that is closest to the argument and is equal to a mathematical integer, i.e, rounds the number up or down, depending on whether the fractional part is less than .5. Numbers whose fractional portion equals .5 will be rounded up.

    Math.sin(x)
    Returns the sine of x, expressed in radians. Returns NaN if x cannot be converted to a number.

    Math.sqrt(x)
    Returns the square root of x. Returns NaN if x is a negative number or cannot be converted to a number.

    Math.tan(x)
    Returns he tangent of x, expressed in radians. Returns NaN if x cannot be converted to a number.

    The Date object
    ScriptEase provides two different ways to retrieve the current time and date. One is with the standard C functions, mktime(), localtime, strftime(), time(), and ctime(). These functions and their use are described with the other functions in the section on Date and Time functions.

    ScriptEase also provides a date object, with built in methods for handling date conversions and extracting data.

    To create a date object set to the current date and time, use the new operator (as you would for any object):

    currentDate = new Date();
    There are several ways to create a date object that is set to some other day and time. The following are all valid ways to get dates:
         aDate = new Date(milliseconds);
         bDate = new Date(datestring);
         cDate = new Date(year, month, day);
         dDate = new Date(year, month, day, hours, minutes, seconds);
    The first syntax listed returns a date and time that is the number of milliseconds after midnight, January 1st, 1970. This is a standard way of representing dates that makes it very easy to calculate the amount of time between one date and another. Generally you don't create dates in this way, but will convert them to millisecond format before doing the calculation.

    The second syntax accepts a string representing the entire date. The time may also be included. The format of a datestring is:

         month day, year hours:minutes:seconds
    for example:
         Friday 13, 1995 13:13:15
    This produces datestring with the date Friday 13, 1995 and a time of one thirteen and fifteen seconds. The time specification is optional and may be omitted; the seconds field may be omitted from the time specification.

    The third and fourth syntaxes are self-explanitory. All of the parameters passed are integers.

    year - The year. If the year is in the twentieth century (i.e. 19xx), you need only supply the final two digits; otherwise four digits must be supplied.
    month - The month, specified as an integer from 0 (January) to 11 (December).
    day - The day of the month, from 1 to 31.
    hours - The hour, specified as an integer from 0 (midnight) to 23 (11 PM).
    minutes - The minutes in the hour, specified as an integer from 0 to 59.
    seconds - The seconds in the minute, specified as an integer from 0 to 59.

    For example:

      aDate = new Date(1492, 9, 12)
    creates a date object containing the date October 12, 1492.

    The following methods are available to all Date objects:

    Date.getDate()
    This method returns the day of the month, from 1 to 31.

    Date.getDay()
    This method returns the day of the week, from 0 (Sunday) to 6 (Saturday).

    Date.getHours()
    This returns a number between 0 (midnight) and 23 (11 PM) representing the hours field of the date object.

    Date.getMinutes()
    This method returns the number of minutes specified by the date object. It will be a number between 0 and 59.

    Date.getMonth()
    This method returns the month field of the specified date object. It will be an integer from 0 (January) to 11 (December).

    Date.getSeconds()
    This method returns the number of seconds specified by the date object. It will be a number between 0 and 59.

    Date.getTime()
    This returns the millisecond representation of the specified date object, in the form of an integer representing the number of seconds between midnight GMT on 1/1/70 and the date and time specified by the date object.

    Date.getTimezoneOffset()
    This method returns the difference, in minutes, between Greenwich Mean Time (GMT) and the local time.

    Date.getYear()
    This method returs the year field of the specified date object.

    Date.setDate(day_of_month)
    This method sets the date of the specified date object to day_of_month. day_of_month must be an integer between 1 and 31.

    Date.setHours(hours)
    This method sets the hours field of the date object to hours. hours must be a number between 0 (midnight) and 23 (11 PM).

    Date.setMinutes(minutes)
    This method sets the minutes field of the date object to whatever is specified by the minutes parameter. minutes must be a number between 0 and 59.

    Date.setMonth(month)
    This method sets the month field of the date object to whatever is specified by the month parameter. month must be an integer between 0 (January) and 11 (December).

    Date.setSeconds(seconds)
    This method sets the seconds field of the date object to whatever is specified by the seconds parameter. seconds must be a number between 0 and 59.

    Date.setTime(milliseconds)
    This function will set the date object to the date and time that is the specified number of milliseconds past midnight on January 1, 1970 GMT.

    Date.setYear(year)
    This method sets the year field of the date object to whatever is specified by the year parameter. year must be a four digit number specifying the year.

    Date.toGMTString()
    This method converts the date to a string, using Greenwich Mean Time.

    Date.toLocaleString()
    This method returns a string representing the date and time of the object in the time zone of the user.

    Special Date methods
    The Date object has two special methods that are called from the object itself, rather than from an instance of it: Date.parse(), and Date.UTC.

    Date.parse(datestring)This method takes a string and converts it to a date. The string must be of the following format:

         Friday, October 31, 1998 15:30:00 -0500
    This is the format written by the Date.toGMTString() method, and also the format used with email and internet applications. The day of the week, time zone, time specification or seconds field may be omitted.
         theDate = Date.parse(datestring);
    is equivalent to:
         theDate = new Date(datestring);
    Date.UTC(year, month, day, [, hours [,minutes [,seconds]]])
    This method takes the parameters above, interprets them as a date, and returns the number of milliseconds between the specified date/time and midnight, January 1, 1970. The parameters are understood to refer to a date in Greenwich Mean Time (GMT).

    Dynamic objects
    ScriptEase Javascript allows for direct access to the interior workings of how object properties are called. If you wish, you may specify how an object accesses its data by replacing one of the following (internal) routines. The following methods are available for modifying how an object calls its members. In all cases, the parameter property is the name of the property being called.

    .get(property)
    Whenever the value of a property is accessed, the get() method is called. By defining a new .get() routine for an object, you can modify the way it accesses property values.

    .put(property, value)
    This method controls the way that new data is assi

    .canPut(property)
    This method returns a boolean value indicating whether the property can be written to or not (i.e., whether it is read-only or not). You could modify this property to notify users when they try to change read-only values, for example.

    .hasProperty(property)
    This method returns a boolean value indicating whether the property exists in this object.

    .delete(property)
    This method will be called whenever the property is deleted with the `delete' operator.

    .defaultValue(hint)
    This function call returns the primitive value of the variable. hint should be either a string or a number, and will indicate the preferred data type to return. (If hint is a string, it will return a string, e.g.).

    .construct(...)
    This method is called whenever a new object is created with the `new' operator. The object will have been already created and passed as the `this' variable to the .construct() method.

    .call(...)
    The call function is called whenever an object method is called. Whatever parameters are passed to the original function will be passed to the call() function.

    This example creates an Annoying object that beeps whenever it retrieves the value of a property:

         function myget(prop)
         {
            System.beep();
            return this[property];
         }
         new Object = Annoying;
         Annoying.get = myget;
    Note that the System.beep() method exists only for the sake of example, and cannot be called unless you explicitly create such a method.

    Preprocessor directives
    The following ScriptEase statements are collectively called preprocessor directives, since they are processed before the rest of the script and direct the way the script commands are interpreted.

    define
    #define is used to replace a token (a variable or a function name) with other characters. The #define statement is executed while the script is being read into the processor, before the script itself, so you'll have all the substitutions in place before the code is read). A #define statement has the following structure:

         #define token replacement
    This results in all subsequent occurrences of token to be replaced with replacement. For example:
         #define NumberOfCountriesInSouthAmerica 13
    The define statement increases program legibility and makes it easier to change your code later on. If Bolivia and Peru decide someday to unite, you only have to change the #define statement to bring your program up to speed. Otherwise, you'd have to go through your program looking for 13's, decide which ones refer to the number of countries in South America (as opposed to the 13's representing the Original Colonies of the United States, which stay 13's) and change them all to 12's.

    Likewise, if you write screen routines for a 25-line monitor, and then later decide to make it a 50-line monitor, you're better off altering #define ROW_COUNT 25 to #define ROW_COUNT 50 and using ROW_COUNT in your code (or ROW_COUNT-1, ROW_COUNT+2, ROW_COUNT/2, etc...) than if you had to search for every instance of the numbers 25, 24, 26, etc...

    #include
    The #include directive lets you include other scripts, and all of the functions contained therein, as a part of the code you are writing. Usually #include lines are placed at the beginning of the script and consist only of the #include statement and the name of the file to be included, for example:

         #include <gdi.hmm>
    This line will make all of the functions in the library file gdi.hmm available to the program.

    The quote characters (` or ") may be used in place of < and >.To include all of C:\CMM\LIB.JSE

    #include <c:\CMM\LIB.JSE>
    To include lots of little files into one big one program
    #include <screen.jse>
    #include <keyboard.jse>
    #include <init.jse>
    #include <comm.jse>
    The ScriptEase interpreter will not include a file more than once, so if a file has already been included, a second (or third) #include statement will have no effect. ScriptEase ships with a large number of libraries of pre-written functions you can use. Library files are plain text files (as are all ScriptEase code documents) and have the extension .jsh.

    Since these libraries are external to ScriptEase, they are less static than the standard function libraries, and can be easily expanded or modified as the need arises. The most recent versions of .hmm libraries are listed on the Nombas downloads page at

         http://www.nombas.com/downloads/index.htm.
    #link
    #link is a command to incorporate additional functions into the ScriptEase processor. In practice, it works much like the #include statement with no parameters. However, while #include is used to include text files of ScriptEase code, #link is used to include precompiled extensions or .DLL files. For example, the command
         #link "oleautoc"
    lets the processor use the functions for OLE automation.

    The files which may be included with #link are discussed in another chapter. #link takes no parameters other than the name of the library being linked to.

    By keeping these functions in external libraries (instead of incorporating them directly into the ScriptEase processor as is the case with functions like Clib.sprintf() and Clib.strcat()) the processor is kept to a more manageable size, saving disk space and cutting down on the amount of time it takes a script to run.

    Since these libraries are external to ScriptEase, they are less static than the standard function libraries, and can be easily expanded or modified as the need arises. The most recent versions of #link libraries are listed on the Nombas downloads page at http://www.nombas.com/downloads/index.htm.

    #ifdef, #elif, #else, #endif
    There are times when you want to #define one file if certain conditions are true, and #define a different file if the condition tests false. You can do this with the #if statement. #if differs from the regular if statement in that it executes while the code is being read into the processor (as opposed to executing when the code itself is run). #elif is the corresponds to the else if statement, and #else corresponds to the else statement. A #if statement must be closed with a terminating #endif statement.

    Another way of looking at this is to think of #if as an if statement to use with #include and #define statements, which are also executed while the code is read. This is frequently used to determine which platform the script is running on, so that it will include the proper files and act appropriately to the operating system.

    For example, suppose you had a script that built long path names from directories supplied to it in different variables. If you were working in a DOS-based environment, the backslash character is used to separate directories, so you could indicate the full path of a file as follows:

      fullPathOfFile = Clib.rsprintf("%s\\%s\\%s\\%s",
         rootdirectory, subdirectory1,
         subdirectory2, filename);
    If you ported this script to a UNIX machine, however, you'd run into problems, because UNIX uses the forward slash to separate directories.

    You can get around this problem by defining the separator character differently for each operating system:

    #if Clib.defined(_UNIX_) 
    #define PathChar `/'
    #elif Clib.defined(_MAC_)
    #define PathChar `:'
    #else
    #define PathChar `\\'
    #endif
    By putting the separator character in a variable, you can make this script work on any operating system:
      fullPathOfFile = Clib.rsprintf("%s%c%s%c%s%c%s",
        rootdirectory, PathChar, subdirectory1, Pathchar,
        subdirectory2, PathChar, filename);
    The #ifdef statement is a limited form of the #if statement, equivalent to #if defined(var)... The example above could be rewritten with #ifdef statements like this:
         #ifdef (_UNIX_)
         #define PathChar `/'
         #ifdef (_MAC_)
         #define PathChar `:'
         #else
         #define PathChar `\\'
         #endif
    Initialization
    All code that is outside of any function is part of the global initialization function. This code is executed first, before calling any function (unless a function is called from this initialization code). Then main() is called.

    Any variables referenced in the initialization section are global.

    To execute code when program terminates, see the Clib.atexit() function.

    Automatic Type Conversion
    When a ScriptEase variable is used in a context where it makes sense to convert it to a different type, ScriptEase will automatically convert the variable to the appropriate type. This most commonly happens with numbers and strings. For example:

         "dog" + "house" = "doghouse" // two strings are joined
         "dog" + 4 = "dog4" // a number is converted
         4 + "4" = "44" // to a string
         4 + 4 = 8 // two numbers are added<
         23 - "17" = 6 // a string is converted
         // to a number
    Converting numbers to strings is fairly straightforward; however, when converting strings to numbers there are a number of limitations. While subtracting a string from a number (or vice versa) converts the string to a number and subracts the two, adding the two converts the number to a string and concantenates them. The string will always convert to a base 10 number, and must not contain any characters other than digits. The string "110e" will not convert to a number, because the ScriptEase processor doesn't know what to make of the `e' character.

    You can specify a more stringent conversion by using the ParseInt() and ParseFloat() methods. main(ArgCount, ArgStrings)

    After the initialization has been performed, the main() function is called and is given the arguments that the operating system passed to the ScriptEase program. If there is no function main(), the program will end after running through all of the steps in the initialization.

    ScriptEase is less picky about the main function than C is. While a C program must have a main() function, in ScriptEase this is not the case. The following two programs do exactly the same thing:

         b=20
         a=b*b
    and
         main()
         {
            b=20
            a=b*b
         }
    These two programs both set the value of a to 400. There are some differences in the way the variables will be handled, however. In the first example, a and b are global variables, and are available to any function in the program. In the second, a and b are local variables, and are only available to the main function. To make these variables available to any other function, they must be explicitly passed to it.

    One advantage to the main() function is that it receives any parameters included on the command line when the script was first called. The call to the function main() looks like this:

    main(argc, argv)
    The argc tells you how many variables were passed, while the variable argv is an array of all of the variables passed. The first variable passed (argv[0]) is the name of the script being called, so if argc = 1 then no variables were passed. These behave like any other local variable. If you don't need to pass parameters to main(), it is recommended that your program have a main() function anyway, with no parameters; in this case the parenthesis following the main() should be left empty.

    Argc, sometimes referred to as ArgCount, is identical to the global _argc variable. Argv, sometimes referred to as argStrings, is identical to the global _argv variable.