Cmm Introduction

The Cmm language is an interpreted language based on a streamlined version of “C”. It has a simplified syntax that does not require pointers or declarations. The purpose of including the interpreter in this software is to provide a mechanism for the user to automate correlator data collection sequences. Typically, the user will execute a script that will automate a sequence such as sweeping a goniometer through a list of pre-defined angles, stopping to collect correlation functions along the way, which are saved to the database for future analysis.

To activate the interface for the Cmm scripting environment, choose Cmm from the Tools menu option of the main menu. The interface to the scripting language consists of three windows. The first window, titled Cmm 1 (Source Code), is a simple text editor. You may load programs into this window from disk files or type source code directly into the window. You will not be able to modify a program while it is running.

The next window, titled Cmm 1 (Output), is used to provide a place for printed output from your program. This is often useful when the user is interested in inspecting the status of a data collection sequence. The script may make use of the printf () function in order to provide a record of the progress of a running program. The printed results may be copied into the clipboard and pasted into a text editor to be saved as a file for a more permanent record. The Cmm output window can hold approximately 30000 characters before it is full. When it is full then future output will result in the loss of earlier printf () statements to make room for the new text.

The last window, titled Cmm 1, is used to control the program flow. You may Run the program or Single Step through the code. You may also Pause the program and restart it or terminate execution of the script by pressing End. This window will also indicate the Line number of the script that is being executed while the script is running.

The reaminder of this manual is devided into four sections. The first section of this manual is for people who are not familiar with the C language. If you are already comfortable with C programming then you may wish skip to the section two, “Cmm vs. C”, which discusses the differences between Cmm and C. Section three provides actual correlator control programming examples. Section four covers additional commands in the scripting language that allow control of the Dynamic Light Scattering Software interface from within user programs.

Section 1: Cmm

Cmm Comments

Any text on a line following two slash characters (//) is considered a comment and is ignored by the Cmm interpreter. Likewise, anything between a slash-asterisk (/*) and an asterisk-slash (*/) is a comment. Here are examples of comments:

// this is a comment line

/*

This is one big comment

block.

*/

Liquid = “Aqueous”; // This is another comment

Cmm primary data types

There are three basic data types in Cmm

Byte: A character (e.g., ‘A’, ‘B’, ‘C’, ‘D’) or a whole number between 0 and 255

Integer: A whole number value: this is the most common numeric data type (examples: 0, -100, 567)

Float: A floating point numbers; any number containing a decimal point (examples: 0.567, 3.14159, -5.456e-12)

Cmm determines the data type of a number by how it is used; for example in the following the “1” on the first line is an integer because that is the default type for numbers without a decimal point.

1// integer

0// integer

0x3EF2// integer in hexadecimal format

-300// integer

3.14//float

-3.45e-20// float

‘A’// byte

‘\033’// byte in octal format

Cmm Variables

A Cmm variable is a symbol that may be assigned data. Variables may be named within the following guidelines.

variables names cannot start with a number

variable names may not include the following characters “+-&|=!*/%^~?:{};()[].’”’#”

variable names may not include imbedded spaces or tabs

The assignment of data to a Cmm variable is usually performed by the equal sign (=). The first time a variable is used, its type is determined.

Count = 1;// Count is an integer

Character = ‘A’;// Character is a byte

Viscosity = 0.89;// Viscosity is a float

After variables has been assigned, they can be treated as their data type. So after these statements:

Count2 = 1;// assign Count2 as the integer 1

Count2 = Count2 + 2;// same as: Count2 = 1 + 2

Basic Arithmetic

=assignment: sets a variable’s value

i = 2; // i is 2

+addition: adds two numbers

i = i + 3;// i is now (2 + 3) or 5

-subtraction: subtracts a number

i =i - 3;// i is now (5-3) or 2 again

*multiplication:

i =i * 5;// i is now (2 * 5) or 10

/division:

i= i / 3// i is now (10/3) or 3 (no remainder)

%remainder: remainder after division

i = 10;

i = i % 3;// i is now (10%3) or 1

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 first variable. Using assignment arithmetic operators, the above code can be simplified as follows:

=assignment: sets a variable’s value

i = 2;// i is 2

+addition: adds two numbers

i += 3;// i is now (2 + 3) or 5

-subtraction: subtracts a number

i -= 3;// i is now (5-3) or 2 again

*multiplication:

i *= 5;// i is now (2 * 5) or 10

/division:

i /= 3// i is now (10/3) or 3 (no remainder)

%remainder: remainder after division

i = 10;

i %= 3;// i is now (10%3) or 1

Auto-Increment and Auto-Decrement (--)

Other arithmetic shortcuts are the auto-increment (++) and auto-decrement (--) operators. These operators ass or subtract 1 (one) from the value to which they are applied. These operators can be use 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 sequence.

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)

Arrays

An array is a group of individual data elements. Each individual item in the array is called an array element. An element of an array is itself a variable, much like any other variable. Any particular element of the array is selected by specifying the element’s offset in the array. This offset is an integer in square brackets ([]). It is important to note that the first element is an array is found at the 0th offset. For example:

prime [0] = 2;

prime [1] = 3;

prime [2] = 5;

month [0] = “January”;

month [1] = “February”;

month [2] = “March”;

An array in Cmm does not need to be pre-defined for size and data type, as it does in other languages. Arrays can be initialized by initializing specific elements as in:

my_data [5]= 7;

my_data [2] = -100;

my_data [1] = 43;

or by enclosing all the initial statements in curly braces, which will cause the array to start initializing at the element 0, as in:

angle_list = { 15.0, 45.0, 60.0, 45.0, 90.0};

Strings

Strings are arrays of bytes that end in a null-byte (zero). “String” is just a shorthand way to specify this array of bytes. A string is most commonly specified by writing test within two quote characters.

The statement:

my_string = “word”;

is equivalent to the statement:

my_string (‘w’, ‘o’, ‘r’, ‘d’);

In both cases, the value of my_string [0] is ‘w’, and at my_string [2] is ‘r’.

When one array is assigned to the other, as in:

string1 = “water”;

string2 = string1;

both variables define the same array and start at the same offset 0. In this case, if string1 [2] is changed then you will find that string2 [2] has also been changed.

Integer addition and subtraction can also be performed on arrays. Array addition or subtraction sets where the array is based. By altering the previous code to:

string1 = “water”;

string2 = string1 + 1;

string1 [2] refers to the same array element as string2 [1].

To demonstrate:

string1 = “cat”;// string1 [0] is ‘c’, string1 [1] is ‘a’

string2 = string1 + 1;// string2 [0] is ‘a’, string2 [1] is ‘t’

string2 [0] = ‘u’;// string2 [0] is ‘u’, string1 [1] is ‘u’

string2--;// string1 [0] is ‘c’, string2 [0] is ‘c’

printf () syntax

printf () prints to the Cmm output window, providing useful feedback from your program. The basic syntax of printf () is:

printf (FormatString, data1, data2, data3,...);

FormatString is the string that will be printed on the screen. When FormatString contains a percent character (%) followed by another character, then instead of printing those characters printf () will print the next data item (data1, data2, data3,...). The way the data will be presented is determined by the characters immediately following the percent sign (%). There are many such data formats, but here are a few of the more common ones.

%%prints a percentage sign

%dprints a decimal integer

%xprints a hexadecimal integer

%cprints a character

%fprints a floating point value

%eprints a floating point value in scientific format

%sprints a string

There are also special characters that cause unique screen behavior when they are printed, some of which are:

\ngoto next line

\ttab

\rcarriage-return

\”print the quote character

\\print a backslash

Here are some examples of printf () statements:

printf (“The variable count contains %d\r\n”, count);

printf (“a character = %c, an integer = %d, a float = %f\r\n”, ‘a’, 2, 4.26);

printf (“%d in hexadecimal is %x\r\n”,16, 16);

printf (“The suspension fluid is %s\r\n”, “aqueous”);

my_string = “aqueous”; // define a string to print

printf (“The suspension fluid is %s\r\n”, my_string);

Note that the Cmm output window requires both the \r and \n to advance to the beginning of the next line. As previously stated, the Cmm output window can hold approximately 30000 characters before it is full. When it is full then future output will result in the loss of earlier printf () statements to make room for the new text.

Logical Operators and Conditional Expressions

A conditional expression can be evaluated as TRUE or FALSE, where FALSE is represented by zero, and TRUE means anything that is not FALSE (not zero). A variable or any other expression by itself can be TRUE or FALSE (non-zero or zero). TRUE and FALSE are keywords defined as part of the Cmm language. With logic operators, these expressions can be combined to make complex TRUE/FALSE decisions.

The logic operators are:

!NOT: opposite of decision

!TRUE// FALSE

!FALSE// TRUE

!(‘D’)// FALSE

!(5-5)// TRUE

AND: TRUE if and only if both expressions are true

TRUE & FALSE// FALSE

TRUE & TRUE// TRUE

0 & (x + 2)// FALSE

!(5-5) & 4// TRUE

||OR: TRUE if either expression is true

TRUE || FALSE// TRUE

TRUE || (4 + 2)// TRUE

FALSE || (4 + 2)// TRUE

FALSE || 0// FALSE

0 || 0.345// TRUE

0 || !(5 - 5)// FALSE

==EQUALITY: TRUE if both values are equal, else FALSE

5 == 5// TRUE

5 == 6// FALSE

!=INEQUALITY: TRUE if both values not equal, else false

5 != 5// FALSE

5 != 6// TRUE

LESS THAN

5 < 5 // FALSE

5 < 6// TRUE

GREATER THAN

5 > 5// FALSE

5 > -1// TRUE

<=LESS THAN OR EQUAL TO

5 <= 5// TRUE

5 <= 6// TRUE

5 <= -1// FALSE

>=GREATER THAN OR EQUAL TO

5 >= 5// TRUE

5 >= 6// FALSE

5 >= -1// TRUE

IF statement

The IF statement is the most commonly used mechanism for making decisions in a Cmm program. It allows to test a condition and act on it. If an IF statement finds the condition you test to be TRUE (not FALSE), the block or statement of Cmm code following it will be executed. The format for the if statement is:

count = 0;

if (count < 10)

{

count++;

}

Because there is only one statement in the block of code following the IF statement, the example above could also be written as:

count = 0;

if (count < 10)

count++;

ELSE statement

The Else statement is an extension of the if statement. It allow you to tell the program to do something else if the condition in the if statement is FALSE. To make more complex decisions, ELSE can be combined with IF to match one of a number of possible conditions. For example:

count = 0;

if (count < 10)

{

count++;

if (count < 5)

printf (“count < 5”);

if (count == 5)

printf (“count = 5”);

else

printf (“count > 5”);

}

WHILE statement

The WHILE is used to execute a particular section of Cmm code over and over again while the condition being tested is found to be TRUE. The test statement is checked before every execution of the Cmm code associated with the WHILE statement. If the test evaluates to FALSE,. the Cmm program will continue after the block of code associated with the WHILE statement.

test_string = “WHO ARE YOU?”;

while ( test_string[0] != ‘A’)

{

printf (“%s\r\n”, test_string);

test_string++;

}

printf (“DONE\r\n”);

The output of the above code would be:

WHO ARE YOU?

HO ARE YOU?

O ARE YOU?

ARE YOU?
DONE

DO...WHILE

This is different form the WHILE statement in that the Cmm code block is executed at lease once, before the test condition is checked.

number = 1;

do

{

number *= 5;

printf (“number = %d\r\n”, number);

} while (number < 100);

printf (“DONE\r\n”);

The output of the above code would be:

5

25

125

DONE

FOR statement

The FOR statement is a special looping statement. The FOR statement takes on 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) then statement is executed. Then the loop_expression is executed, and so on back to the testing conditional. If the conditional is FALSE then statement is not executed and the program continues beyond statement. The FOR statement is a shortcut for this form of WHILE:

initialization;

while (conditional)

{

statement;

loop_expression;

}

The previous code demonstrating the WHILE statement could be rewritten this way if you used the FOR statement:

for (test_string = “WHO ARE YOU?”; test_string[0] != ‘A’; test_string++)

printf (“%s\r\n”, test_string);

printf (“DONE\r\n”);

Conditional Operator ?:

The conditional operator is simply a useful shortcut. It is a limited variation or 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) the expression_if_true is evaluated and the value of the entire expression is replaced by the value of expression_if_true. If test_expression is FALSE, then expression_if_false is evaluated ant the value of the entire expression is that of expression_if_false.

For example:

number = (5 < 6) ? 100 : 200; // number is set to 100

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 takes a form such as this:

FunctionName (Parameter1, Parameter2, Parameter3)

{

statements...

return result;

}

where the function name is followed by a list of input parameters in parentheses.

A call is made to a function in this format:

returned_result = FunctionName (Value1, Vlaue2, Value3);

The return statement causes a function to return to the code that initially called the function. A function may indicate more than one return statement. The return statement may also return a value.

minimum (a, b)

{

if (a < b)

return a;

else

return b;

}

By default. parameters to functions are passed by reference. If a function alters the parameter variable, then the variable in the calling function is altered as well. This function returns a value (n * 2.5), and it changes the value of the input parameter (n).

test_func (n)

{

n *= 4.0;

return n * 2.5;

}

main ()

{

number1 = 3.0;

number2 = test_func (number1);

printf ( “number1 = %f, number2 = %f \r\n”, number1, number2);

}

The code above would result in output of:

number1 = 12.000000, number2 = 30.000000

Variable Scope

A variable in Cmm is either global or local. A global variable is any variable that is referenced outside of any function, making it visible to all functions. A local variable is declared inside a function and only has meaning within that function.

scope_test (n)

{

n *= 4;

n2 = 7; // local variable seen only in this function... not the same as n2 in main ()

n3 = n3 * 5; // global variable

}

n3 = 3; // global variable

main ()

{

n1 = 1; // local variable seen only in this function

n2 = 2; // local variable seen only in this function

printf ("n1 = %d, n2 = %d, n3 = %d\r\n", n1, n2, n3);

scope_test (n1);

printf ("n1 = %d, n2 = %d, n3 = %d\r\n", n1, n2, n3);

}

The printed results this program would be:

n1 = 1, n2 = 2, n3 = 3

n1 = 4, n2 = 2, n3 = 15

In the main () function the variable n1 is modified by the function scope_test (). The scope_test () function refers to the variable n1 from main () as n. When n is modified in the scope_test () function the modified value remains altered in the variable n1 of the main () function. The variable n2 is defined and used in both the functions main () and scope_test (). These are different local variables and both may contain different values. Notice that the value of n2 in main () is not modified after the use of the local variable n2 in the scope_test (). The variable n3 is defined outside any function and is seen as the same variable in all functions.

Section 2: Cmm vs. C

Case Sensitivity

Cmm is not case sensitive. This holds true for function and variable names.

Data Types

The only recognized data types are Float, Long, and Byte. The words “Float”, “Long” and “Byte” do not appear in Cmm source code; instead, the data types are determined by context. For instance 6 is a Long, 6.0 is a Float, and ‘6’ is a Byte. Byte is unsigned, and the other types are signed.

Automatic Type Deceleration

There are no type declarators and no type casting. Types are determined from context. If the code says “n = 6” then n is Long, unless a previous statement has indicated otherwise.

For instance, this C code:

int Max (int a, int b)

{

int result;

result = (a < b) ? b : a;

return result;

}

could become this Cmm code:

Max (a,b)

{

result = ( a < b) ? b : a;

return result;

}

Automatic Array Allocation

Arrays are dynamic. Any index (positive or negative) into an array is valid. If an element of an array is referred to, then Cmm must see to it that such an element will exist. For instance if the first statement in the Cmm source code is:

a [4] = 7;

then the Cmm interpreter will make an array of 5 integers referred to by the variable a. If a statement further on refers to a[6] then the Cmm interpreter will expand a, if is has to, to ensure that the element a[6] exists.

Literal Strings

A Cmm literal string is any byte array (string) appearing in source code within double quotes. When comparing strings, if either side of the comparison operator is a literal string, then the comparison is performed as if you were using strcmp (). If one or both vars are a literal string then the following comparison operation translation is performed.

if (liquid == “aqueous”)// i.e. if (strcmp (liquid, “aqueous”) == 0)

if (liquid < “aqueous)// i.e. if (strcmp (liquid, “aqueous”) < 0)

if (“aqueous” > liquid)// i.e. if (strcmp (“aqueous”, liquid) > 0)

In Cmm, this code:

liquid = “toluene”;

if (liquid == “toluene”)

printf (“The liquid is toluene.\r\n”);

would print “The liquid is toluene.”

Function Parameters and Literal Strings

When a literal string is a parameter to a function, then it is always passed as a copy. For example, this code:

for (n = 0; n < 3; n++)

{

str = strcat (“dog” , “house”);

printf (“%s\r\n”, str);

}

results in this output:

doghouse

doghouse

doghouse

Return and Literal Strings

When a literal string is returned from a function with the return statement, then it is returned as a copy of the string. This code: