Programming

Autodeclare

There is a mechanism in DXL called auto-declare, which means that the programmer need not specify the type of a variable. The interpreter deduces the type from the assignment statement.

This is a very dangerous feature, because if you make a mistake when typing a variable name, the interpreter will assume that a new variable is being used. Errors like this are extremely hard to find.

So, once you have mastered your first “Hello World” program in DXL, and before you attempt any real programming, you should turn off the interpreter’s auto-declare function by adding the line

XFLAGS_ &= ~AutoDeclare_

to the bottom of the file $DOORSHOME/lib/dxl/startup.dxl

Single String Parameter Functions

When the DXL interpreter encounters a function that takes a single string parameter, it ignores the parentheses, thus causing unsuspected results for the unwary programmer. This means that you should not use these functions in-line with other strings as the interpreter will concatentate the string parameter and any following string(s) and then pass the result to the function.

For example, if you run the following DXL

string s1 = "one"
string s2 = "two"
print upper(s1) " " s2 "n"

you would expect to get

"ONE two"

In fact, you get

"ONE TWO"

The fix for this is to enclose the function call in parentheses as follows:

print (upper(s1)) ” ” s2 “n”

Nested Functions

DXL supports nested functions. In other words, you can declare functions within a function. However, local variables declared within the parent function are not available to the child function. In this respect, DXL does not support nesting as you might expect. But one child function can call other child functions as long as they are in scope.

The following example demonstrates how this works. This code runs without error. Notice that function sally() can call harry(), but harry cannot call sally() because the latter is out of scope (i.e. declared after the former).

void printNames()
{
	string localVar = ""

	string harry()
	{
		// this won't work - no access to local variable...
		//print(localVar)

		// ...nor will this because sally is out of scope
		//print(sally)

		return("Harry")
	}

	string sally()
	{
		string sue()
		{
			return("Sue")
		}

		// this works because harry() is in scope
		return("Sally. Their names are " harry " and " sue ".")
	}

	// nested functions are in scope
	print("My name is " harry) "n"
	print("My name is " sally) "n"
}

printNames()

A possible use for this is if you wanted to make a function globally available, but did not want to allow direct access to call the other functions it calls. In the above example, harry() and sally() are hidden outside of printNames().

Undocumented DXL

Certain features of the DXL programming language are either incorrectly documented or not documented at all. This collection aims to address this issue by describing useful undocumented features of DXL.

Please note that your use of undocumented features of DXL may not be supported by Telelogic, therefore I cannot accept any responsibility for your use of any information provided here.

If you know of an undocumented feature of DXL that is not described here then please tell me and I will endeavour to add the information to this collection.

DOORS Perms

The following are listings of perms defined for each version of DOORS. These are provided for your interest on the understanding that you use undocumented features of the DXL programming language at your own risk.

DOORS 7.1 Perms and Constants.

DOORS 8.2 Perms.

DxlObject

The DxlObject type is similar to the C struct. This data type allows you to store related values of any type. Used together with skip lists, this allows you to build efficient and easy to use data structures.

Example usage:

DxlObject d = new()

d->"Name" = "Tony"
d->"Age"  = 21  // I wish

myAge = (int d->"Age")
myName = (string d->"Name")

delete(d)

A more complete example of how to use the DxlObject data type in a proper application can be seen in the History Viewer script.

Go to History Viewer page.

rootName_

This undocumented perm returns the full name of the item starting from the database root, not the nearest ancestor project which is what fullName() returns.

Usage:

string rootName_({Item i|Folder f|Project p|Module m|ModName_ modRef})

Memory Leaks and the String Table

Memory de-allocation is not automatic for the dynamic types Skip, Array, Buffer, DB, OleAutoArgs, IPC and Stat. Repeated use of these types can consume memory and reduce performance of DOORS. In some cases this can even lead to DOORS crashing.

To avoid such memory leaks you must explicitly de-allocate memory used by these variables. This means that you should have a delete() or destroy() function call for every create() function call in your program.

There is no function for de-allocating memory used by string variables. Every new string declared or constructed in DXL is added to the “string table”. The memory used by the string table is not released until the DOORS session is terminated.

Memory being consumed by the string table is a particular problem in scripts such as Layout DXL that are run many times.

Avoid creating unecessary strings through concatenation. The following prints out object identifiers:

Object o

for o in current Module do
{
	print("Object: " identifier(o) "n")
}

This is inefficient because the new strings being added to the string table are, for example

"Object: SR 1n", "Object: SR 2n", "Object: SR 3n"

Rewriting the pre as follows factors out the strings “Object: ” and “n” and thus uses less space in the string table.

Object o

for o in current Module do
{
	print("Object: ")
	print(identifier(o))
	print("n")
}

New strings being added to the string table are, for example:

"Object: ", "n", "SR 1",  "SR 2", "SR 3"

If you are doing a lot of string processing use Buffers instead of strings. If you need to convert a Buffer to a string you can use the undocumented function

string tempStringOf(Buffer)

Which converts a buffer to a string without using the string table. The string created is very temporary and cannot be relied upon to exist beyond the statement in which it is used.

Interestingly, string space is released if the DXL is executed within an eval_() command.