CommuniGate Programming Language (CG/PL)

Intro
Installation
SysAdmin
Network
Objects
Transfer
RealTime
Access
Services
Directory
Clusters
Applications 
Data 
CLI/API 
CGPL
Rules 
Helpers 
PBXApp 
WebApp 
WSSP 
AppCodes 
WebMail
PBX
Miscellaneous
Licensing
The CommuniGate Programming Language (CG/PL) is a powerful, yet simple procedural language. It can be used with various components of the CommuniGate Pro Server software, including:

The language structure and the language features are the same for all applications, but different applications use different sets of built-in functions and procedures.

Language Elements

The following is a simple CG/PL program:
//	
// A simple CG/PL application
//
entry Main is
  myName = "Jim" + " " + "Smith";
  if length(myName) > 10 then
    myName = Substring(myName,0,8) + "..";
  end if;
end;


Data Model

Information is presented as objects. An object can be a string, a number, a datablock, a timestamp, an ip-address, an array, or a dictionary. See the Data section for more details.

An object can also be a mailbox handle, a task handle, or any other special object defined within a particular environment.

A special type of object is a null-value (null value or "no object" value).

When processing logical (boolean) values, a null-value is used as a false-value, and a string "YES" is used as a true-value.


Lexemes

The program source code is a plain text encoded using the UTF-8 character set.

The language lexemes are:

A comment is a double-slash (//) sign and all following symbols up to and including the next EOL (end-of-line) symbol.

white-space is a sequence of 1 or more space symbols, tabulation symbols, EOL symbols, and/or comments. At least one white space is required between a name and a keyword, other lexemes can be separated with zero or more white spaces.


Variables

Any name not declared as a procedure or function name, and not matching a built-in procedure or function name is a name of a variable.
Each variable has a value assigned to it. Initially, this value is a null-value. Any object can be assigned to any variable to become that variable value.
myCount = 3;           // the myCount variable is created and
                       // a numeric value 3 is assigned to it
myCount = myCount + 2; // myCount variable value changed to 5
myCount = "Service";   // myCount variable value changed to a string

Variables are local to the function/procedure instance (invocation) where they were created. All their values are destroyed when the function/procedure exits (returns).


Expressions

The language implements unary operations. Unary operations are specified as
operation operand

The following unary operations are supported:

-
unary minus. If the operand value is a number, operation value is the number with the opposite sign, otherwise the operation value is the number 0.
The following expressions have the value of -5:
-5
-(3+2)

+
unary plus. If the operand value is a number, operation value is that number, otherwise the operation value is the number 0.
The following expressions have the value of 5:
+5
+(10/2)

not
Negation. If the operand value is a null-value, the operation value is a true-value, otherwise the operation value is a null-value.
The ! sign can be used instead of the not keyword.
The following expressions have the value of "YES":
not null
!(2 == 3)

The unary operations have a higher priority than binary and ternary operations. The following expression has the value of -1, not -3:

-2 + 1

The language implements binary operations. Binary operations are specified as

left-operand operation right-operand

Unless explicitly specified otherwise, both operands are calculated first (in a non-specified order), and the operation is applied to the operand values.

The following binary operations are supported, listed in the descending priority order:

*, /, %
These arithmetic operations can be applied to numeric operand values only.
If one of the operands is not a Number, or if the right operand of the / or % operations is number 0, the operation value is a null-value.
The following expressions have the value of 10:
5 * 2
-20 / -2
30 % 20

+, -
These arithmetic operations can be applied to numeric operand values.
The + operation can be applied to a pair of string operand values, producing a string value with their catenation.
The + operation can be applied to a pair of datablock operand values, producing a datablock value with their catenation.
The + operation can be applied to a timestamp and a numeric value operands, producing a timestamp value that is the numeric value seconds later than the timestamp operand value.
The - operation can be applied to a left operand with a timestamp value and a right operand with a numeric value, producing a timestamp value that is the numeric value seconds earlier than the timestamp operand value.
The - operation can be applied to a pair or operands with timestamp values, producing a numeric value - the number of seconds between the left and the right operand values.
In other cases the operation value is a null-value.
The following expressions have the value of 5:
3 + 2
-2 - -7
The following expression has the value of "John Doe":
"Joh" + "n Doe"

<, <=, ==, !=, >=, >
These comparison operations can be applied to a pair of numeric operands, to produce a true-value when the arithmetic comparison condition is met.
These comparison operations can be applied to a pair of timestamp operands, to produce a true-value when the arithmetic comparison condition is met.
The ==, != comparison operations can also be applied to any pair of objects, checking if they are "equal":
  • A null-value is equal to and only to a null-value.
  • Numbers are equal if their numeric values are equal.
  • Strings are equal if they have the same length and have the same symbol in each string position.
  • Datablocks are equal if they have the same length and have the same data byte in each block position.
  • Arrays are equal if they have the same number of elements and elements in each position are equal.
  • Dictionaries are equal if they have the same number of key-value pairs, the key strings are equal, and the values for each key are equal in both dictionaries.
  • For all other object types, evert object is equal to itself only (no two different objects are considered equal).

In other cases the comparison operation value is a null-value.
The following expressions have the value of "YES":
1+2 == 3
2+2 != 3
2+2 >= 3
"Joe" == "Joe"
null == (2 == 3)

and, or, xor, and then, or else
these logical operations compare their operands with null-values.
The and operation value is a true-value if both operand values are not null-values, and a null-value otherwise.
The & sign can be used instead of the and keyword.
The or operation value is a true-value if at least of the operand values is not a null-value, and a null-value otherwise.
The | sign can be used instead of the or keyword.
The xor operation value is a null-value if none or both operand values are null-values. Otherwise, the operation value is the operand value that is not a null-value.
The ^ sign can be used instead of the xor keyword.
The and then operation computes the left operand value first. If that value is a null-value, the right operand is not computed, and the operation value is a null-value. Otherwise the right operand is computed and its value becomes the operation value.
The && sign can be used instead of the and then keywords.
The or else operation computes the left operand value first. If that value is not a null-value, the right operand is not computed, and the left operand value becomes the operation value. Otherwise the right operand is computed and its value becomes the operation value.
The || sign can be used instead of the or else keywords.
The following expressions have the value of "YES":
1+2 == 3 & 2+2 == 4
2+2 == 3 or else 7-5 == 2
false ^ true

The binary operations of the same priority group left-to-right: X op Y op Z is the same as ( X op Y ) op Z .

The binary operations have a higher priority than the ternary operations.

The language implements one ternary operation:

The language implements the indexing operation:

object[index]
where
the object expression should have an array or a dictionary value (otherwise the operation results in a program exception), and
the index expression should have a numeric value smaller than the number of object elements.

If the object expression value is an array, the operation references the array element number index (the first element has the number 0).
Retrieving an element that does not exist results in a null-value.
Assigning a new value to the first array element that does not exist adds the value to the array as a new element.
An attempt to assign a new value to any other non-existing array element results in a program exception.
If SquareArray value is (1,4,9,16,25), the following expression has the value of 9:
SquareArray[2]
while the following operator:
SquareArray[5] = "Blue";
changes the SquareArray value to (1,4,9,16,25,"Blue"),

If the object expression value is a dictionary, the operation references the dictionary key number index (the first key has the number 0).
Retrieving a key that does not exist results in a null-value.
An attempt to assign a new value to a referenced key results in a program exception.
If SquareDictionary value is {"one" = 1; "two" = "four"; "three"=9;}, the following expression has the value of "three":

SquareDictionary[2]

The language implements the key, or dictionary-element operation:

dictionary.keyName
where
the dictionary expression should have a dictionary value (otherwise the operation results in a program exception), and
the keyName is a name.

The operation references the dictionary element with the key keyName.
Retrieving an element for a key that does not exist results in a null-value.
Assigning a null-value to a key results in the key-value pair being removed from the dictionary.
Assigning a non-null-value to a key that does not exist results in a new key-value pair being added to the dictionary.
If SquareDictionary value is {"one" = 1; "two" = "four"; "three"=9;},
the following expression has the value of 9:
SquareDictionary.three

and the following expression has the value of null:
SquareDictionary.four

The language implements the computed key, or dictionary-element operation:

dictionary.(keyExpr)
where
the dictionary expression should have a dictionary value, and
the keyExpr expression should have a string value (otherwise the operation results in a program exception).

The operation references the dictionary element for the keyExpr key.
If SquareDictionary value is {"one" = 1; "two" = "four"; "three"=9;}, the following expression has the value of 9:
SquareDictionary.("th" + "ree")

The language implements function calls. A function call is specified as a name followed by parentheses optionally containing a list of expressions (parameter-expressions).
The name used should be a name of a built-in function or an already defined function. Parameter expressions (if any) are computed, and the function code is executed using the parameter expression values.
A function result is an object, and the indexing and dictionary-element operations can be applied to a function result.
If MyFunction function has 2 parameters and its returned value is an array (1,"four",9), the following expression has the value of "four":

MyFunction(1,"zzz")[1]

The keywords null and false can be used in expressions to specify a null-value, while the keyword true can be used to specify a true-value.


Operators

An operator sequence contains zero or more operators, followed by the semicolon (';') sign.

An empty operator performs no action:

;

A null operator consists of the keyword null. It performs no action:

null;

An assignment operator consists of a data container reference (a variable, an array element, or a dictionary element), the = sign and an expression that will be computed and assigned to the specified data container.

myVar = 123 + 111;
myVar = "string";

If a data container reference is an array element, that element must exist or it must be the first non-existent array element, i.e. if an array has 3 elements, you can assign values to elements number 0,1,2, and 3. In the last case, a new element is added to the array.

If a data container reference is a dictionary element, assigning a null-value effectively removes the element from the dictionary.

A procedure call operator is specified in the same way as a function call expression. The name used should be a name of a built-in procedure or an already defined procedure.
If MyProc procedure has 2 parameters, the following operator is a correct procedure call:

MyProc(1,"zzz");

A stop operator terminates the Task execution. It consists of the stop keyword:

stop;
If there is an active connection, that connection is closed.

A return operator finishes function or procedure execution.
A return operator within a function consists of the return keyword and an expression. This expression is computed and its value becomes the value of the function call.

return 12*year+month;

A return operator within a procedure consists of the return keyword.
return;

A conditional operator consists of the if keyword followed by an expression (if-expression), the end keyword, an operator sequence (if-sequence), and the end keyword optionally followed by the if keyword. The if-expression is computed, and if its value is not a null-value, the if-sequence is executed, and the conditional operation execution ends.
The following example increases the myCount variable value by 2 if its value is less than 10:

if myCount < 10 then
  myCount = myCount + 2;
end if;

A conditional operator can optionally contain one or more elif-portions after the if-sequence. Each elif-portion consists of the elif keyword, an expression (elif-expression), the then keyword, and an operator sequence (elif-sequence).
If the if-expression value is a null-value, the first elif-expression is computed, and if its value is not a null-value, its elif-sequence is executed and the conditional operation execution ends. If the elif-expression value is a null-value, the next elif-portion is processed.
In the following example the myCount variable value is checked. If the value is less than 10, the variable value is increased by 2. Otherwise (i.e. if the variable value is not less than 10), if the value is less than 20, it is decreased by 3:
if myCount < 10 then
  myCount = myCount + 2;
elif myCount < 20 then
  myCount = myCount - 3;
end if;

A conditional operator can optionally contain an else-portion. It is specified after the if-sequence and after all optional elif-portions. The else-portion consists of the else keyword and an operator sequence (else-sequence).
If the if-expression value is a null-value, and all optional elif-expression values are null-values, the else-sequence is executed and the conditional operator execution ends.
The following example increases the myCount variable value by 2 if the value is less than 10, it decreases the variable value by 3 if the value is not less than 10, but it is less than 20, and the variable value is multiplied by 4 in all other cases:
if myCount < 10 then
  myCount = myCount + 2;
elif myCount < 20 then
  myCount = myCount - 3;
else
  myCount = myCount * 4;
end if;

The loop operator consists of the loop keyword, optionally prefixed with the while keyword and an expression (while-expression), an operator sequence (initial sequence), and the end keyword optionally followed by the loop keyword.

If a while-expression is specified, it is computed, and if its value is null the loop operator execution ends. Otherwise the operator sequence is executed, and the loop operator execution repeats.
The following example checks the myCount variable value and keeps increasing it by 2 while that value is less than 10:

while myCount < 10 loop
  myCount = myCount + 2;
end loop;

The following example calls the myProc procedure in an unconditional loop:
loop
  myProc(2,"test.wav");
end loop;

The loop operator can optionally contain one or more exitif-portions between the initial sequence and the end keyword. Each exitif-portion consists of the exitif keyword, followed by an expression (exitif-expression), the semicolon (';') sign, and an operator sequence. After the initial sequence is executed, the first exitif-expression is computed. If its value is not null, the loop operator execution ends. Otherwise the exitif operator sequence is executed, and the next exitif expression is computed. After the last exitif operator sequence is executed, the loop operator execution repeats.
The following example appends the "aaa" string to the myWord variable, checks the variable lengths, and if the length is less than 20, appends the "bbb" string to the myWord variable, and repeats the process:

loop
  myWord = myWord + "aaa";
exitif length(myWord) >= 20;
  myWord = myWord + "bbb";
end loop;

Alternative Forms

Some operators in a sequence may be presented in an alternative form. Operators in an alternative form are not followed by the semicolon sign.

The alternative form of a conditional operator consists of the if keyword followed by an expression (if-expression), and an operator sequence (if-sequence) enclosed in left ({) and right (}) brace signs.

The alternative form of a conditional operator can optionally contain one or more elif-portions after the enclosed if-sequence. Each elif-portion consists of the elif keyword, an expression (elif-expression), and an operator sequence (elif-sequence), enclosed into braces.

The alternative form of a conditional operator can optionally contain an else-portion. It is specified after the enclosed if-sequence and after all optional elif-portions. The else-portion consists of the else keyword and an operator sequence (else-sequence) enclosed in braces.
The following example increases the myCount variable value by 2 if the value is less than 10, it decreases the variable value by 3 if the value is not less than 10, but it is less than 20, and the variable value is multiplied by 4 in all other cases:

if (myCount < 10) {
  myCount = myCount + 2;
} elif (myCount < 20) {
  myCount = myCount - 3;
} else {
  myCount = myCount * 4;
}

Note: it is not required to use parentheses to enclose if-expressions or elif-expressions.

The alternative form of a loop operator consists of the while keyword, an expression (while-expression), a left brace ('{') sign, an operator sequence (initial sequence), zero or more exitif-portions and a right brace ('}') sign.
Each optional exitif-portion consists of the exitif keyword, followed by an expression (exitif-expression), the semicolon (';') sign, and an operator sequence.
The following example appends the "aaa" string to the myWord variable, checks the variable lengths, and if the length is less than 20, appends the "bbb" string to the myWord variable, and repeats the process:

while ( true ) {
  myWord = myWord + "aaa";
exitif (length(myWord) >= 20);
  myWord = myWord + "bbb";
}

Note: it is not required to use parentheses to enclose while-expressions or exitif-expressions.


Code Sections

A program code is a set of code sections:

The procedures and functions can be called recursively: a procedure or a function can call itself - directly or via calling some other procedures or functions.

All code sections are reenterabale: the same code section can be used by several program activations or Tasks at the same time.

Code sections must be declared before they can be used. Declarations include forward-declarations, external-declarations, and definitions.

A program code should contain exactly one external-declaration or exactly one definition (but not both) of each code section used.
A program code may contain not more than one forward-declaration of a code section, specified before its definition.
Forward-definitions are used in programs containing two or more code sections calling each other, so it is not possible to define each section before it is used in the other code section.

External-declarations allow code sections to call code sections defined in separate program code modules.
External-declarations are allowed only in the environments that support them, such as the Real-Time Application environments. See the environment description for more details.
The code section name and its parameter names specified in an external-declaration must match the code section name and its parameter names specified in the code section definition given in an external program code module.
The code section definition can specify more parameters than an external-declaration. The missing parameters are assigned null-values when such an external-declaration is used.

Entries

An entry declaration consists of the entry keyword, the entry name, followed by one of the following:

for a forward-declaration:
the forward keyword followed by the semicolon (;) sign
for an entry definition:
the is keyword followed by an operator sequence, followed by the end keyword (optionally followed by the entry keyword), and followed by the semicolon (;) sign.
for an alternative entry definition:
the left brace ({) sign followed by an operator sequence, followed by the right brace (}) sign.

If a running program reaches the end of an entry section operator sequence, an implicit stop operator is executed.

The following example shows an entry for a Real-Time Application. It tries to accept an incoming call, and if succeeds, it plays a sound. The entry code ends, quitting the program and thus finishing the call:

entry main is
  if acceptCall() == null then
    playFile("greeting.wav");
  end if;
end entry;

Or, in the alternative form, and using the alternative form of the conditional operator:

entry main {
  if (acceptCall() == null) {
    playFile("greeting.wav");
  }
}

Procedures

A procedure declaration consists of the procedure keyword, the procedure name, the left parenthesis, an optional list of parameter names, the right parenthesis, followed by one of the following:

for a forward-declaration:
the forward keyword followed by the semicolon (;) sign
for a procedure definition:
the is keyword followed by an operator sequence, followed by the end keyword (optionally followed by the procedure keyword), and followed by the semicolon (;) sign.
for an alternative entry definition:
the left brace ({) sign followed by an operator sequence, followed by the right brace (}) sign.
for an external-declaration:
the external keyword followed by the semicolon (;) sign

If a running program reaches the end of a procedure operator sequence, an implicit return operator is executed.

The following example shows a Real-Time Application procedure that speaks the specified number:

procedure SayNumber(x) is
  x = x % 100;
  if x >= 10 then
    playFile(String(x/10*10)+".wav");
  end if;
  if x != 0 then
    playFile(String(x%10)+".wav");
  end if;
end procedure;

If a forward-declaration is used, the procedure definition must have exactly the same parameters as its forward-declaration.

Example:

procedure SayMoney(x,units) forward;
procedure SayNumber(x,units) forward;
procedure SayMoney(x,units) is
  SayNumber(x);
  playFile(units+".wav");
end procedure;

Functions

A function declaration is the same as a procedure declaration, but the function keyword is used instead of the procedure keyword.

All program control paths in a function code section must end with a return or a stop operator.

The following example defines a function calculating the factorial of its argument:

function Factorial(x) is
  if x <= 1 then return 1; end if;
  return Factorial(x-1)*x;
end function;

Below is the same function in the alternative form, using the ternary operator:

function Factorial(x) {
  return x <= 1 ? 1 : Factorial(x-1)*x;
}

All code section (entry, procedure, and function) names used within the same program code must be unique.


Built-in Procedures and Functions

The following procedures and functions are built into the language, and they are available to all applications. You should not use their names for user-defined procedures or functions.

Same(arg1,arg2)
This function returns a true-value if the values of arg1 and arg2 are the same object or if both values are null-values or both values are true-values. In other cases the function returns a null-value.

The value of Same("J" + "ack","Jack") value is a null-value.

In the following example:

x = "my string";
y = "my string";
z = x;
test1 = Same(x,y);
test2 = Same(x,x);
test3 = Same(x,z);
the resulting value of test1 is a null-value, while the values of test2 and test3 are true-values.

Length(arg)
If arg is a string, this function returns the string size (in bytes);
If arg is a datablock, this function returns the datablock size (in bytes);
If arg is an array, this function returns the number of array elements;
If arg is a dictionary, this function returns the number of dictionary keys;
If arg is a mailbox handle, this function returns the number of messages in the mailbox;
In all other cases, this function returns the number 0.

Void(arg1)
This procedure does nothing, it just discards the arg1 value. Use this procedure when you need to call a function, but you do not want to use the function result.

Strings

IsString(arg)
This function returns a true-value if the arg value is a string, otherwise the function returns a null-value.

String(arg)
If the arg value is a string, this function returns this string.
If the arg value is a number, this function returns a string with the decimal representation of that number.
If the arg value is an ip-address, this function returns a string with the cannonical representation of that network address.
If the arg value is a null-value, this function returns a null-value.
In all other cases, this function returns a string with a textual representation of the arg value.

FindSubstring(str,substr)
If the str value is a string, and the substr value is a string, and the latter is a substring of the str value, this function returns the position of the substring substr in the str string (positions start with 0).
For example, the value of FindSubstring("forest","for") is 0.
In all other cases this function returns the number -1.

Substring(str,from,len)
If the str value is a string, and the from value is a number, and the len value is a non-negative number, this function returns a string that is a substring of the str value, with the len length.

If the from is non-negative, the substring starts at the from position (the first symbol of the string has the position 0),
If from is a negative value, then the substring ends at the 1-from position from the string end (to include the last str symbol, from should be -1).
If the from value (or 1-from value) is equal to or greater than the str value length, the result is an empty string.
If the from + len (or 1-from + len) value is greater than the str value length, the resulting string is shorter than len.
In all other cases this function returns a null-value.

EOL()
This function returns a string containing the EOL (end-of-line) symbol(s) used on the Server OS platform.

CRLF()
This function returns a string with the Internet EOL (<carriage-return><line-feed>) symbols.

EmailDomainPart(address)
If the address value is a string, and the string contains the @ symbol, this function returns a string containing the address string part after its first the @ symbol.
Otherwise, the function returns a null-value.

EmailUserPart(address)
If the address value is not string, this function returns a null-value.
If the address value is a string not containing the @ symbol, this function returns the same string.
Otherwise (the address value is a string containing the @ symbol), this function returns the address string part before the first @ symbol.

Numbers

IsNumber(arg)
This function returns a true-value if the arg value is a number, otherwise the function returns a null-value.

Number(arg)
If the arg value is a number, this function returns this number.
If the arg value is a string, this function returns the numeric value of that string, till the first non-numeric symbol.
For example, the value of Number("123#") is 123.
In all other cases, this function returns the number 0.

TimeStamps

IsDate(arg)
This function returns a true-value if the arg value is a timestamp, otherwise the function returns a null-value.

GMTTime()
This function returns a timestamp object with the current GMT time.

LocalTime()
This function returns a timestamp object with the current local time.

GMTToLocal(arg)
If the arg value is a timestamp object, this function returns a timestamp object containing the arg value converted from the GMT to the local time.
In all other cases, this function returns a null-value.

LocalToGMT(arg)
If the arg value is a timestamp object, this function returns a timestamp object containing the arg value converted from the local time to the GMT.
In all other cases, this function returns a null-value.

Year(arg)
If the arg value is a timestamp object, this function returns a number containing the arg value year.
In all other cases, this function returns a null-value.

Month(arg)
If the arg value is a timestamp object, this function returns a string containing the arg value month name (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec).
In all other cases, this function returns a null-value.

MonthNum(arg)
If the arg value is a timestamp object, this function returns the arg value month number (1 for January).
In all other cases, this function returns a null-value.

MonthDay(arg)
If the arg value is a timestamp object, this function returns a number containing the day of month for the arg value date (the number 1 is returned for the first day of month).
In all other cases, this function returns a null-value.

WeekDay(arg)
If the arg value is a timestamp object, this function returns a string containing the name of week day of the arg value date (Mon, Tue, Wed, Thu, Fri, Sat, Sun).
In all other cases, this function returns a null-value.

YearDay(arg)
If the arg value is a timestamp object, this function returns a number containing the day of year for the arg value date (the number 1 is returned for the 1st of January).
In all other cases, this function returns a null-value.

TimeOfDay(arg)
If the arg value is a timestamp object, this function returns the number of seconds between the date arg value and the start of its day.
In all other cases, this function returns a null-value.

DateNumber(arg)
If the arg value is a timestamp object, this function returns the number of full days between the arg value date and 01-Jan-1970.
In all other cases, this function returns a null-value.

DateByMonthDay(year,monthNum,monthDay)
The year, monthNum, monthDay values should be positive numbers. If any of these values is incorrect, this function returns a null-value. Otherwise, the function returns a timestamp object presenting midnight of the specified date.
The following expression timestamp value is midnight, 05-Nov-2006:
DateByMonthDay(2006,11,5)

DateByYearDay(year,yearDay)
The year, yearDay values should be positive numbers. If any of these values is incorrect, this function returns a null-value. Otherwise, the function returns a timestamp object presenting midnight of the specified date.
The following expression timestamp value is midnight, 01-Feb-2006:
DateByYearDay(2006,32)

IP Addresses

IsIPAddress(arg)
This function returns a true-value if the arg value is an ip-address, otherwise the function returns a null-value.

IPAddress(arg)
If the arg value is an ip-address, this function returns this ip-address.
If the arg value is a string with a correct presentation of an IP address (with an optional port number), the function returns that ip-address.
In all other cases, this function returns a null-value.

Datablocks

IsData(arg)
This function returns a true-value if the arg value is a datablock, otherwise the function returns a null-value.

Arrays

IsArray(arg)
This function returns a true-value if the arg value is an array, otherwise the function returns a null-value.

NewArray()
This function returns a newly created empty array.

Invert(arg)
The arg value should be an array, otherwise this function call results in a program exception.
This function returns an array containing the same elements as the arg value, but in the reversed order.

Find(source,object)
If the source value is an array, this function returns a number - the index in the array for the first element equal to the object value. If the source array does not contain such an object, a negative numeric value is returned.
If the source value is not an array, a negative numeric value is returned.

RemoveElement(target,index)
This procedure removes an element from an array.
The target value should be an array, otherwise this procedure call results in a program exception.
The index value should be a number or a string containing a decimal number, specifying the array element to remove. In other cases the first (the zero index) element is removed.

If the myArray value is (1,4,9,16,25), the RemoveElement(myArray,2) changes the myArray value to (1,4,16,25).

InsertElement(target,index,element)
This procedure inserts an element into an array.
The target value should be an array, otherwise this procedure call results in a program exception.
The index value should be a number or a string containing a decimal number, specifying where to insert the element value. All existing array elements with index number of index and bigger increase their index number by one.

If the myArray value is (1,4,9,16,25), the InsertElement(myArray,2,"Jack") changes the myArray value to (1,4,"Jack",9,16,25).

Dictionaries

IsDictionary(arg)
This function returns a true-value if the arg value is a dictionary, otherwise the function returns a null-value.

NewDictionary()
This function returns a newly created empty dictionary.

Data Conversion

ObjectToString(arg)
This function returns a string with a textual representation of the arg value.
If the arg value is a null-value, the function returns a null-value.

TextToObject(arg)
The arg value should be a string or a datablock, otherwise this function call results in a program exception.
This function returns an object textually represented with the arg value. If conversion fails, the function returns a null-value.

Environment

Vars()
This function returns a dictionary unique for this Task (a program invocation). This dictionary can be used to store variables visible in all procedures and functions.

Addresses and URIs

SIPURIToEmail(uri)
This function converts the uri value from a SIP URI into an E-mail string.
If the uri value is not a string, or if it cannot be parsed as a SIP URI, the function returns a null-value.
EmailToSIPURI(email)
This function converts the email value from an Email into a SIP URI string.
If the email value is not a string, or if it cannot be parsed as an E-mail, the function returns a null-value.

Account Data

The following functions and procedures are available when the program (a Task) has a "current Account" set.

MyDomain()
This function returns a string with the current Domain name, if there is one. If there is no Account or Domain associated with the current Task, this function returns a null-value.
MyEmail()
This function returns a string with the current Account E-mail, if there is one. If there is no Account associated with the current Task, this function returns a null-value.

ReadSiteFile(fileName)
This function reads a file from the current Account Personal File Site.
The fileName value should be a string. It specifies the name of the file to read.
This function returns a datablock value with the file content or a null-value if the specified file is not found.

WriteSiteFile(fileName,data)
This function stores the data datablock or string into the fileName file in the current Account Personal File Site.
If fileName is not a string or data is not a datablock nor it is a string, this function call results in a program exception.
This function returns a null-value if the file was successfully written, otherwise it retuns a string with an error code.

DeleteSiteFile(fileName)
This function deletes the fileName file from the current Account Personal File Site.
This function returns a null-value is the file was successfully deleted, otherwise it retuns a string with an error code.

RenameSiteFile(oldFileName,newFileName)
This function renames the oldFileName file in the current Account Personal File Site into newFileName. Both parameters must have string values.
This function returns a null-value is the file was successfully renamed, otherwise it retuns a string with an error code.

ListSiteFiles(folderName)
This function returns information about all files in the specified subdirectory of the current Account Personal File Site.
If folderName is not a string, information about the top-level File Site directory is returned.
This function returns a null-value is an error occurred. Otherwide, the function returns a dictionary. Each dictionary key is a file or a subfolder name. For folders, the dictionary value is an empty array. For files, the dictionary value is a dictionary with the following elements:
STCreated
a timestamp value with the file creation date.
STModified
a timestamp value with the file modification date.
STFileSize
a numeric value with the file size in bytes.

ReadGroupMembers(groupName)
This function reads a Group from the current Domain.
The groupName value should be a string. It specifies the name of the Group to read.
This function returns an array of strings containing Group member E-mail addresses. This function returns a null-value if there is no Group with the specified name.

Mailbox Handles

Mailbox handles are internal objects representing a Mailbox.

OpenMailbox(mailboxName)
This function opens a Mailbox. The mailboxName value should be a string. It specifies the Mailbox name.
If the name does not start with the ~ symbol, the mailbox is opened in the current Account, if any.
The current Account (if any) must have the Read/Select access right for the specified mailbox.
The function returns a mailbox handle if the mailbox was opened successfully, otherwise it returns a null-value.

MailboxUIDs(boxRef,flags)
This function returns an array of numbers - mailbox message UIDs.
The boxRef value should be a mailbox handle.
If the flags value is a string, it should contain a comma-separated list of message flag Names and/or Negative Names. Only UIDs of messages that have flags specified with the flag Names and do not have flags specified with the Negative Names are included into the resulting array.
The following example retrieves UIDs of all messages that have the Seen flag and do not have the Deleted flag:
myMailbox = OpenMailbox("INBOX");
seen = MailboxUIDs(myMailbox,"Seen,Undeleted");

MailboxInternalTimeByUID(boxRef,uid)
This function returns a timestamp object containing the message Internal Date.
The boxRef value should be a mailbox handle, the uid value should be a number - the message UID.
If a message with the specified UID does not exist in the mailbox, the function returns a null-value.

MailboxFlagsByUID(boxRef,uid)
This function returns a string containing a comma-separated list of mailbox message flags Names.
The boxRef value should be a mailbox handle, the uid value should be a number - the message UID.
If a message with the specified UID does not exist in the mailbox, the function returns a null-value.

MailboxSetFlagsByUID(boxRef,uid,flags)
This function modifies mailbox message flags.
The boxRef value should be a mailbox handle, the uid value should be a number - the message UID, the flags value should be a comma-separated list of message flag Names and/or Negative Names.
The function sets the flags specified by their Names and resets the flags specified with their Negative Names.
The function returns a null-value if the current Account (if any) has sufficient Mailbox Access Rights to modify the flags, and flags have neen successfully modified, otherwise the function returns an error code string.

MailboxExpunge(boxRef)
This function removes all mailbox messages marked as "purgable" or "deleted".
The boxRef value should be a mailbox handle, the uid value should be a number - the message UID,

MailboxAudioByUID(boxRef,uid)
This function returns a datablock containing an audio section of the message.
The boxRef value should be a mailbox handle, the uid value should be a number - the message UID.
If a message with the specified UID does not exist in the mailbox, or the message does not contain an audio part, the function returns a null-value.

Services

SysLog(arg)
This procedure places the textual representation of the arg value into the Server Log.

GetLanguage()
This function value is a string with the currently "selected language".

SetLanguage(lang)
This procedure sets the "selected language". The lang value should be a string with the language name, or a null-value to select the default language.

GetTimeZoneName()
This function value is a string with the currently selected time zone name. If no time zone is selected (the Server time offset is used), the function returns a null-value.

SetTimeZone(zoneName)
This procedure sets the current time zone. The zoneName value should be a string with a known time zone name. If an unknown zone name is specified, or if the zoneName value is not a string, the no zone fictitious value is set, and the Server current time offset is used.

Communications

HTTPCall(URL,parameters)
This function performs an HTTP transaction.
The URL value should be a string. It specifies the request URL. The URL schema should be http or https.
The parameters value should be a dictionary. It specifies the request parameters and, optionally, the request body. The following dictionary elements are processed (all of them are optional):
body
a datablock with the request body.
Content-Type
a string with the request body content type. This element is used only when a body is specified.
Content-Subtype
a string with the request body content subtype. This element is used only when a body and Content-Type elements are specified.
method
a string with the request method. If this element is absent, the GET method is used if no body is specified, otherwise the POST method is used.
Cookie
a string with the Cookie field data.

The function returns an error code string if the HTTP transaction failed. Otherwise the function returns a dictionary with the following elements:
responseCode
a number with the HTTP response code.
body
a datablock with the response body (may be absent).
Content-Type
a string with the response body content type.
Content-Subtype
a string with the response body content subtype.
charset
a string with the response body charset.
Date, Last-Modified, Expires
timestamp elements with the response header field values.
Server, Location, Set-Cookie
string elements with the response header field values.

SendEMail(fromAddress,subject,to,headers,content)
This function composes and sends an E-mail message.
The fromAddress value should be a string. It specifies the message From: address.
The subject value should be a string. It specifies the message Subject: field.
The to value should be an E-mail string or an array of E-mail strings. It specifies the message To: address(es).
The headers value should be a null-value or a dictionary. This dictionary specifies the header field values for the composed E-mail message. The following elements are processed (all of them are optional):
Cc
the element value should be an E-mail string or an array of E-mail strings. It specifies the message Cc: address(es).
Bcc
the element value should be an E-mail string or an array of E-mail strings. It specifies the message Bcc: address(es).
sourceType
the element value should be a string. It specifies the message source. If this element is absent, the "CGPL" string value is used.
sourceAddress
the element value should be a string. It specifies the address of the message source (network address, remote system name, etc.).
protocol
the element value should be a string. It specifies the name of the protocol used to submit this message.
Content-Class
the element value should be a string. It specifies the E-mail header Content-Class: field value.

The content value specifies the E-mail message body. If the value is a dictionary, then the dictionary body element is the actual content, and other dictionary elements specify various body parameters (content header fields). Otherwise the content itself is the actual content and the content body parameters set is an empty one.
The following content body parameters (dictionary elements) are processed (all of them are optional):
Content-Type
the element value should be a string. It specifies the content body Content-Type. If this element is not specified, the Content-Type is set to "text" if the actual content is a string, otherwise it the Content-Type is set to "application".
Content-Subtype
the element value should be a string. It specifies the content body Content-Type subtype. If this element is absent, and the Content-Type is set to "text", the Content-Subtype is set to "plain".
filename
the element value should be a string. It specifies the content body file name.
Content-Disposition
the element value should be a string. It specifies the content body Content-Disposition. If this element is absent, and the fileName element is present, the Content-Disposition value is set to "attachment".

If the actual content is a string, it is stored "as is", using the 8bit Content-Transfer-Encoding.
If the actual content is a datablock, it is stored using the base64 Content-Transfer-Encoding.
If the actual content is an array, the content is a multi-part one. Only the Content-Subtype parameter element is used, if it is absent, the "mixed" value is used.
Each array element is stored in the same way as the content value itself.
If the actual content is not an array, a string, or a datablock, an empty content body is stored.
This function returns a null-value if an Email message has been composed and sent (submitted to the Queue). Otherwise, this function returns an error code string.

In the following example, a simple text message is sent.

  result = SendEmail("from@sender.dom","Test Message","To@recipient.dom",null,"Test Message\eEnd Of Message\e");

In the following example, a multipart/mixed message is sent. It contains an HTML text and a binary attachment.

  content = NewArray();

  textPart = NewDictionary();
  textPart.("Content-Type") = "text";
  textPart.("Content-Subtype") = "html";
  textPart.body = "<HTML><BODY>This is an <B>HTML</B> text</BODY></HTML>";
  content[0] = textPart;

  dataPart = NewDictionary();
  dataPart.("Content-Type") = "image";
  dataPart.("Content-Subtype") = "gif";
  dataPart.fileName = "file.gif";
  dataPart.body = ReadSiteFile(dataPart.fileName);
  content[1] = dataPart;

  headers = NewDictionary();
  headers.("Content-Class") = "message";

  result = SendEmail("from@sender.dom","Test Attachment","To@recipient.dom",headers,content);

SendInstantMessage(fromAddress,toAddress,content)
This function composes and sends an Instant Message.
The fromAddress value should be a string. It specifies the message From: address.
The toAddress value should be a string. It specifies the message To: (recipient) address.
The content value should be a string. It specifies the message content.
The function only initiates an Instant Message signalling operation, it does not wait for this operation to complete.
This function returns a null-value if an Instant Message has been composed and sent (submitted to the Signal component). Otherwise, this function returns an error code string.


Multitasking

Certain environments (such as Real-Time Application environments) provide multitasking functionality. In these environments, program invocations (Tasks) can locate each other and exchange data. This section defines the additional language features available in these multitasking environments.

Task handles are internal objects representing a Task. In a Cluster environment, a Task handler includes a reference to the cluster member running the Task.

Spawning

A program (a running Task) can create a new Task by using the spawning expression. It is specified using the spawn keyword followed by a name of an entry code section. A new Task is created and it starts to run concurrently with the task that used the spawning expression, executing the specified entry code section.
The spawning expression value is a task handle for the newly created task, or null if the system failed to create a new task.

In the following example, a program executing the Main entry code section creates a new task that starts to execute the DoBackup entry code section, which copies files "file1","file2",...."file100" into "backup1","backup2",..., files.

entry DoBackup is
  nameIndex = 1;
  while nameIndex <= 100 loop
    fileData = ReadSiteFile("file" + String(nameIndex));
    if fileData != null then
      resultCode = WriteSiteFile("backup" + String(nameIndex));
      if resultCode != null then
        Log("failed to backup file" + String(nameIndex) + ". Error Code=" + resultCode);
      end if;
    end if;
  end loop;
end entry;
 
entry Main is
  backuper = spawn DoBackup;
  if backuper == null then
    Log("Failed to start a Backup Task");
  end if;
end entry;

Tasks do not share any variables, even when a Task directly creates a new Task using the spawning expression.

Events

Tasks can exchange data by sending Events:

SendEvent(taskRef,eventName,eventParam)
This function sends an Event to a task. It returns a null value if an Event was sent successfully, or a string with an error code otherwise (for example, when the specified task does not exist).
The taskRef value should be a task handle, the eventName value should be a string starting with a Latin letter, and an eventParam value should be null or any other "unmodifiable" object - i.e. the eventParam value cannot be an array or a dictionary.
If you need to send an array or a dictionary parameter with an Event, send its textual representation instead.
The function only sends an Event to the specified (target) task. It does not wait till the task receives an event, nor does it wait for any response from the target task.

ReadInput(secsToWait)
Events sent to a task are enqueued, and the task can read the first Event in queue using this function. The function value is a dictionary containing the event data.
The secsToWait value should be a non-negative number. If the Task Event queue is empty and the task does not receive a new Event within the specified number of seconds, the function returns a null-value.
If this function returns a dictionary value, the dictionary contains the following elements:
sender
the task handle of the sender Task (the Task that has sent this event). In a Cluster environment, this Task and the current Task may be running on different Cluster member computers.
what
the string value of the eventName parameter used in the SendEvent operation in the sender Task.
parameter
the value of the eventParam parameter used in the SendEvent operation in the sender Task.

Note: depending on the environment, the ReadInput function can return various other objects. For example, if the function is used in a Real-Time Application environment, it can return a string containing the first enqueued DTMF symbol.
Note: the ReadInput function may have "false wakeups", i.e. it can return a null-object even before the specified time period has elapsed.

Meetings

The Meeting mechanism allows a Task to make itself known to other Tasks associated with the same Account.

Each Account can have several named Meeting Sets and an unnamed Default Meeting Set. Several named Meetings can be created in any Meeting Set. Each Meeting is a dictionary object that can contain zero or one task handle.

CreateMeeting(setName,key,param)
This function creates a Meeting object in some Meeting Set within the current Account.
The setName parameter specifies the Meeting set name. If the parameter value is a null-value or an empty string, the Default Meeting Set is used.
The key parameter must be a string. It specifies a unique ID or name for the new Meeting. For example, an application implementing real-time conferencing can generate a random numeric string to be used as the conference password, and it can create a Meeting using that string. Other Tasks associated with the same Account can find that Meeting (and a task handle for the Task associated with it) if they know the key and the setName parameter values used with the CreateMeeting operation.
The parameter parameter value is stored with the Meeting. Note that the value is stored using its textual representation, so only the standard objects can be used as the parameter values or the parameter value sub-elements. For example, you cannot store mailbox or task handles.
This function returns a null-value if a Meeting has been created. Otherwise, this function returns an error code string.

ActivateMeeting(setName,key)
This function adds the current Task task handle to a Meeting in the current Account.
The setName and key parameter values specify an already created Meeting.
There should be no other Task handle stored in this Meeting.
The current Task becomes the Meeting Active Task.
This function returns a null-value if the task handle has been successfully added. Otherwise, this function returns an error code string.

DeactivateMeeting(setName,key)
This function removes the current Task task handle from a Meeting in the current Account.
The setName and key parameter values specify an already created Meeting, and that Meeting should contain the current Task task handle.
When this operation completes successfully, the Meeting has no Active Task.
This function returns a null-value if the task handle has been successfully removed. Otherwise, this function returns an error code string.

RemoveMeeting(setName,key)
This function removes a Meeting from a current Account Meeting Set.
The setName and key parameter values specify the Meeting to remove.
This function returns a null-value if the Meeting has been successfully removed or if the specified Meeting has not been found. Otherwise, this function returns an error code string.

FindMeeting(setName,key)
This function retrieves Meeting information from a current Account Meeting Set.
The setName and key parameter values specify the Meeting to look for.
If the Account does not have the specified Meeting, the function returns null.
Otherwise, the function returns the Meeting information dictionary containing the following elements:
parameter
the value of the parameter parameter used with the CreateMeeting operation.
id
a task handle of an Active Task, if any.
In a Cluster environment, the Active Task and the current Task may be running on different Cluster member computers.

Queues

The Queue mechanism allows a Task to make itself known to other Tasks associated with the same Account. When a Task registered in a Queue is found by some other Task, the found Task is removed from the Queue.

Enqueue(queueName,parameter,pty)
This function registers the current Task with the Account associated with it.
An Account may have several Queues with Task registrations. The queueName parameter specifies the Queue name. If this parameter value is a null-value or an empty string, the default Queue of the associated Account is used.
The parameter parameter value is stored with the Task registration. Note that the value is stored using its textual representation, so only the standard objects can be used as the parameter values or the parameter value sub-elements. For example, you cannot store mailbox or task handles.
The pty parameter value should be a string containing a decimal number with one digit, the dot (.) sign and any number of digits. The Task is placed in the Queue before all other Tasks with a smaller pty parameter value, but after all tasks with the same or larger pty parameter value. If the pty parameter value is a null-string, the default "1.0" value is assumed.
A Task may register itself several times in different Queues, but it can be registered only once with any given Queue. If the Enqueue function is used by a Task that has been already enqueued into the same Queue, the function does not create a second registration. Instead, the function updates the parameter value enqueued with the Task and may change the Task position in the Queue according to the new pty parameter value.
The function returns a null-value if registration has failed. If registration was successful, the function returns a dictionary containing the following elements:
length
a number - the total number of Tasks in the Queue.
position
a number - the current position of the current Tasks in the Queue.
The position of the first Task in the Queue is 0 .

CheckQueue(queueName)
This function checks the current Task position in an Account Queue.
The queueName parameter specifies the Queue name.
The function returns a null-value if it has failed to access the specified Queue. Otherwise, it returns the same dictionary as the Enqueue function.
Note: the position element exists in the returned dictionary only if the current Task is currently enqueued into the specified Queue. If current Task was not enqueued, or if it has been already removed from the Queue by some other task, this elements will be absent.

Dequeue(queueName)
This function removes the current Task from the Account Queue.
The queueName parameter specifies the Queue name.
The function returns a null-value if it has failed to access the specified Queue. Otherwise, it returns the same dictionary as the Enqueue function. The position element will not exist in the returned dictionary.

ReadQueue(queueName)
This function retrieves the first Task from the Account Queue.
The queueName parameter specifies the Queue name.
The function returns a null-value if there is no Tasks in the specified Queue.
Otherwise, the function returns a dictionary containing the following elements:
id
the task handle of the retrieved Task. In a Cluster environment, this Task and the current Task may be running on different Cluster member computers.
parameter
the value of the parameter parameter used when the Task was enqueued.

Note: this function removes the first Task from the Queue. Unless the retrieved Task re-enqueues itself into the same Queue, no other Task will find it in that Queue.


Formal Syntax


string      ::= "string-data"
number      ::= digits
name        ::= alpha-numeric-and-underscore-starting-with-alpha

variable    ::= name

basicData   ::= variable | funcCall
dataRef     ::= basicData | dataRef [ expr ] | dataRef . name | dataRef . ( expr )
spawnExpr   ::= spawn name
basicExpr   ::= string | number | dataRef | null | false | true | spawnExpr

unaryOp     ::= ! | not | - | +
unary       ::= basicExpr | unaryOp unary | ( expr )
multOp      ::= * | / | %
multBinary  ::= unary | multBinary multOp unary
addOp       ::= + | -
addBinary   ::= multBinary | addBinary addOp multBinary
cmpOp       ::= < | <= | == | != | >= | >
cmpBinary   ::= addBinary | cmpBinary cmpOp addBinary
logicOp     ::= & | and | | | or | && | and then | || | or else
logicBinary ::= cmpBinary | logicBinary logOp cmpBinary
ternary     ::= logicBinary | logicBinary ? logicBinary : ternary
expr        ::= ternary

argList     ::= expr 0*(, expr)
funcCall    ::= name ( [argList] )
procCall    ::= name ( [argList] )

leftSide    ::= variable | dataRef [ expr ] | dataRef . name | dataRef . ( expr )
letOper     ::= letOper = expr

nullOper    ::= | null
stopOper    ::= stop
returnOper  ::= return [ expr ]

ifOper      ::= if expr then opSequence 0*( elif expr then opSequence ) [ else opSequence ] end [ if ]
altIfOper   ::= if expr { opSequence } 0*( elif expr { opSequence } ) [ else { opSequence } ]

loopOper    ::= [while expr ] loop opSequence 0*( exitif expr ; opSequence) end [ loop ]

altLoopOper ::= while expr { opSequence 0*( exitif expr ; opSequence) }

oper        ::= nullOper | procCall | letOper | returnOper | stopOper | ifOper | loopOper |
altOper     ::= altIfOper | altLoopOper
seqOper     ::= oper ; | altOper
opSequence  ::= 0*( seqOper )

entryBody   ::= forward ; | is opSequence end [ entry ] ; | { opSequence }
procBody    ::= forward ; | external ; | is opSequence end [ procedure ] ; | { opSequence }
funcBody    ::= forward ; | external ; | is opSequence end [ function ] ; | { opSequence }
parmList    ::= name 0*(, name)
entry       ::= entry name entryBody
procedure   ::= procedure name ( [ paramlist] ) procBody
function    ::= function name ( [ paramlist] ) funcBody

program    ::= 1*(entry | procedure | function)


CommuniGate® Pro Guide. Copyright © 1998-2006, Stalker Software, Inc.