Chapter 1 -- Fundamentals


This section describes some of the internal workings of DataCAD.


All angles in DCAL (and therefore internal to DataCAD), are expressed in radians starting at 0 to the right (east). Angles increase counterclockwise.

NOTE: The internal representation has no effect on how DataCAD displays angles to the user.

Coordinate System

Internally DataCAD stores all distances and coordinates as 1 unit = 1/32 inch. This is also true for metric units.
When converting distances to strings or strings to distances, the current scaling type (feet-inches-fractions, meters, decimal feet, etc.) determines the format of distance strings. This does not, however, affect the way that DataCAD maintains distances internally.


Every primitive graphic shape that DataCAD understands is called an entity. Currently supported entities include:

  • 3D arc
  • ellipse
  • 3D line
  • line
  • arc
  • point
  • associative dimension
  • polygon
  • bezier
  • skew box
  • bezier surface
  • slab
  • bspline
  • symbol
  • circle
  • text string
  • cone
  • torus
  • cylinder
  • truncated cone
  • dome

Each entity has certain information associated with it such as which layer it is on, color, line type, line spacing, line weight, overshoot factor, and an attribute (integer). Each entity also has an address associated with it which is a handle to the entity in the drawing file. The address of an entity does not change, either during an editing session or between editing sessions.


A DataCAD macro perceives the keyboard differently from other programs. To simplify writing macros, all keys are returned from the keyboard as integers, not as characters. This allows DataCAD to represent the entire 256 extended ASCII character set, as well as any 'special' key. 'Special' keys return escape codes.

A special key is any key that has a macro- interpretable function. For instance, the function keys are special keys, as are the arrow keys, (Ins) and (Del). Some keys are special keys only some of the time. For instance, (q) returns an escape code under some circumstances which causes DataCAD to increment the current line type, and at other times (while reading a string) returns a normal key code.

Several of the DCAL routines return a result that tells you how they were exited. These result codes are res_normal for a normal finish and res_escape for an interruption because an escape code was read. A result of res_escape typically means that the user pressed a function key while the macro was requesting some type of input. The escape code that was pressed returns from these routines as an integer.


Each entity is on a layer. Each layer is scanned during any search of DataCAD's database. When a layer is not searched, every entity on that layer is ignored. Ignoring certain layers (for instance layers that are off) or confining a search to a specific layer or set of layers improves search speed.

Selection Sets

DataCAD supports 16 selection sets. A selection set is a collection of entities. Every entity can be a member of some, none, or all of the selection sets. Selection sets are convenient ways of grouping entities so you can act upon them together. Selection sets also provide an alternative to using layers to group entities. The first eight selection sets are available to you and DCAL, while the other eight are reserved for DataCAD's internal use.

Selection sets exist across uses of a drawing file. That is, you can set up and manipulate a selection set. If the drawing is exited and then reentered, the selection set still exists. In this respect, selection sets are similar to layers as a way to group entities.

Local Variables

Routines can declare local variables. These variables can only be used inside this routine or any routine local to it. They are pushed on the stack and exist only during the lifetime of the routine.


A symbol is similar to any other DataCAD entity. However, a symbol is a reference to a group of other entities that are drawn where the symbol is inserted. A symbol, as created at the DataCAD template menu, is referenced by its file name (including the path). With a symbol defined by a macro, however, all you need is a unique symbol name.

Symbols are instanced, that is, their geometry exists only once in the database. They can be globally updated, but no longer individually edited.


DCAL is a block-structured language similar to Pascal and Modula-2. DCAL supports recursive procedures and functions, as well as nested routines, local variables and constants, reference and value parameters, and conformant arrays.

Case Sensitivity

The functions and procedures in DCAL can be entered in either upper- or lower-case characters. DCAL is not case sensitive, therefore, ABC, abC, and AbC are all the same to DCAL.


A comment is text that prints within the code of a macro, but is ignored by the macro. DCAL allows two different types of comments:

* Comments that start with a left brace ({) and end with a right brace (}).

* The other type of comment is the comment until end of line. This starts with an exclamation mark (!) and continues until the end of the current line. Comments cannot be nested, and cannot appear within a string.


DCAL macros are composed of identifiers, both pre-defined and user-defined. Examples are: variable names, procedure names, and procedure parameters.

Valid DCAL identifiers begin with a letter, and are followed by letters, numbers, and underscores. Identifiers may be up to 20 characters long. Identifiers longer than 20 characters result in compile time errors. Therefore, these are valid identifiers:

These, however, are not valid identifiers:
123test Starts with a number.
_hello Starts with an underscore.
abcdefghijklmnopqrstuvwxyz More than 20 letters.
ab$de $ is an invalid character.

DCAL identifiers are not case sensitive, therefore, ABC, abC, and AbC are all the same identifier to DCAL.


A keyword is a word that is part of the DCAL language. Keywords are reserved and cannot be used for any other purpose. A complete list of keywords follows:

  • and
  • of
  • array
  • off
  • begin
  • on
  • by
  • or
  • const
  • out
  • do
  • procedure
  • else
  • program
  • elsif
  • public
  • end
  • record
  • external
  • repeat
  • false
  • return
  • for
  • string
  • function
  • then
  • if
  • to
  • in
  • true
  • include
  • type
  • message
  • until
  • mod
  • var
  • module
  • while
  • not

White Space

White space is ignored by the compiler. White space consists of spaces, newlines, and tabs that are not in a string or character literal.

Program Layout

Macro Header

There are two types of macro headers, depending on whether the .dcs file contains a program or a module:


As the sample macro spiral shows, DCAL program macros begin with the keyword program followed by the name of the macro, followed by a semicolon.


DCAL modules begin with the keyword module, followed by the name of the module, followed by a semicolon. Modules have no body, and thus no corresponding begin keyword. However, they do have an end followed by the module name and a period. The sample module wrtutl.dcs is an example of a module.


The Constant section, if present, starts with the keyword const. Following it are the constant identifier, an equal sign (=), followed by the value of the constant. Finally, a semicolon terminates each constant.

DCAL recognizes two types of constants, integers, and reals. The following is a valid constant section:

delta = 23.43; {real constant}
max_count = 45; {integer constant}


The Type section, when present, comes after the Constant section. It begins with the keyword type, followed by the type name, followed by the type definition.

Scalar Types

Scalar types consist of the DCAL built-in simple types which are described in the "Data Types" chapter. These simple types are indivisible: a DCAL macro cannot directly examine these variables to any greater degree.

Array Types

Array types are used by DCAL to group data together. To declare an array, use the keyword array, followed by a left bracket ([), followed by the lower bound, followed by two periods (..), followed by the upper bound, followed by a right bracket (]), followed by the keyword of, followed by the type of the element that the array is comprised of.

Notice that arrays can be made up of arrays. For instance:

x = ARRAY [0..9] OF ARRAY [3..5] OF integer;

A shorthand notation for this is:

x = ARRAY [0..9, 3..5] OF integer;


Records are the other way DCAL groups data together. DCAL records are similar to Pascal records, including the use of the case variant record. The only distinctions are that in a DCAL case variant record, the case selector (tag) must be an integer, and no explicit tag variable is allowed. For example, the following are valid record descriptors:

  rec1 = RECORD
    a : integer;
    b : real;
  rec2 = RECORD
    a : integer;
    CASE integer OF
    0 : (r : real);
    1 : (b : boolean);


Next comes the optional variables section. It begins with the keyword var, followed by a list of identifiers, each followed by a colon, then the type of variable, followed by a semicolon. For example:

  i : integer;
  x, y : real;
  dis_Array : dis_Type;  { a user defined type }

Notice that, unlike constants, more than one variable can be given the same type, as long as they are separated by commas.


A subprogram, or routine, is a procedure or function. A function is identical to a procedure except that it returns a value and can be used in an expression, if its type is appropriate for the expression. In this manual, the terms subprogram and routine mean either procedure or function.


Procedures are declared by the keyword procedure, followed by the procedure name, followed by an optional parameter list. After that, a procedure may declare local constants, types, variables, and other routines. A procedure ends with control falling through to the final end statement, or by using the return statement.


Functions are similar to procedures, except they return a value of a certain type. Functions are declared with the keyword function, followed by the function name, an optional parameter list, a colon, and the type of variable the function returns. A function may declare local constants, types, variables, and other routines. In the body of the function, the return value is returned in the return statement. The returned value follows the keyword return. If control falls through to the final end in a function without encountering a return statement, a fatal runtime error occurs. Functions may only return scalar types.


In this manual, the function or procedure is listed with a description, followed by the parameters, with descriptions of the parameters concluding the section.

Passing Parameters

Parameters are passed to routines in one of three ways: IN mode, OUT mode, and IN OUT mode. You can specify the usage of the parameter; and the compiler determines whether to pass the parameter by reference or value.

Valid routine declarations with parameters are:

PROCEDURE calc (x, y : real; x1, y1 : OUT real);
FUNCTION dist (x1, y1, x2, y2 : real) : real;
PROCEDURE readint (i : IN OUT integer);

IN Mode

An in mode parameter may be read from, but not written to. When no mode is assigned to a parameter, in is the default. You can substitute an expression for an in parameter; therefore, both (3) and (3 * i) are valid in parameters.

OUT Mode

An out mode parameter can be written to, but cannot be read. An example is a procedure that returns several results in out parameters.

PROCEDURE average (data : ARRAY OF integer; mean : OUT integer;
sumation : OUT integer; median : OUT integer);


in out parameters can be both read from and written to. These parameters typically have an initial value with a final value returned from the routine.

Open Array Parameters

DCAL supports open array parameters to procedures. An open array (also called a conformant array) is an array that does not have specified bounds, for example, a procedure that sorts an array of integers. The procedure can sort an array of any size. The declaration is:

PROCEDURE sort (i : ARRAY OF integer);

The functions low and high (described later) are used by the procedure to determine the actual bounds of the array parameter.

Expressions and Logical Operators

This section discusses type compatibility issues. It also discusses mathematical operators that are valid in DCAL.

Type Compatibility

DCAL features strong type checking. Any operation may be performed on a variable as long as the operation is appropriate to the base type of that variable. However, variables and expressions must be the same type to operate or appear together in assignment statements.

For instance, if you declare:

count = integer;
a, b, c : count;
x, y, z : integer;

Then you can legally write:

a := b + c;

because a, b, and c are declared as identical types and the + operator is appropriate to the base type of count, which is integer.

However, you could not write:

a := b + x;

because b and x are not of the same type.

You can escape the type checking through type casting. For example:

a := b + count (x);

Here, the type name is used to relax the type checking. For this to work, the base type of x must be the same as the base type of the type count, as it is in this example (both are integers). You can use type casting to convert any type to any other type, as long as they are the same size in computer memory.


The mathematical operators *, /, +, and - are used for multiplication, division, addition, and subtraction, respectively. Use these operators with both real numbers and integer numbers. Both operands must be of the same type; with results of the same type.

The routines float, round, and trunc may be used within an expression in which both integer and real variables are mixed.

The operator mod is used only with integer operands and returns the integer remainder of division of the two numbers or variables.

Here are some examples of these operators:


rl1, rl2, : real;
int1, int2, : integer;
rlResult: real;
intResult : integer;


rlResult := (rl1 + rl2) / 2.0;
intResult := (int1 - int2) * 2;
rlResult := float (int1) * 34.75;
intResult := 7 mod 3;   { this gives intResult = 1 }
intResult := 7 / 3;     { this gives intResult = 2 }
intResult := round (rl1) / 4;
intResult := trunc (rl2) * 6;



This section describes the statements that make up DCAL.

Assignment Statement

The assignment statement is the statement DCAL uses to assign values to variables. Its use is identical to the Pascal assignment statement:

variable := expression;

The variable gets the value returned by the expression. The expression must evaluate to the same type as the variable (integers must be assigned to integer variables, reals to real variables, etc). The expression itself may be a variable.

IF Statement

The IF statement is used for testing Boolean conditions and branching based on the result. Several valid IF statements are:




dosecond (f);



IF apple + orange < pineapple THEN









IF today = monday THEN

getOutOfBed (late);

goToWork (late);


Conditional Expressions

Follow the keyword IF with an expression which returns a Boolean result. When the result is true, the code following the THEN keyword is executed. When the result is false, the code following the ELSE keyword is executed.

THEN Statements

The statements between the THEN and the following END, ELSE, or ELSIF are executed when the Boolean expression evaluates to true.

ELSE Statements

The statements between the ELSE and the corresponding END or ELSIF are executed when the Boolean test expression evaluates to false. The ELSE section is optional. When the ELSE section is not present and the test expression evaluates to false, no action is taken and control falls through to the next statement following the corresponding END of the IF statement.


Use the keyword ELSIF to shorten the number of lines needed for multiple IF statements. The following code:

IF key = 1 THEN



IF key = 2 THEN



IF key = 3 THEN







using ELSIF could be written as:

IF key = 1 THEN


ELSIF key = 2 THEN


ELSIF key = 3 THEN





Using ELSIF in this way can be a substitute for the Pascal CASE statement, which DCAL lacks.

Procedure Call Statement

With the procedure call statement you can execute procedures you have written or procedures that are built into DCAL and DataCAD. To call a procedure, simply use the procedure's name, followed by its parameters, if any. Example procedure calls are:

wrterr ('Unable to open file.');write_prompt; { call proc. w/o parameters }
add (x, y);
testit (3 + 4, a);

RETURN Statement

The RETURN statement occurs in two slightly different forms depending on whether it is used in a procedure or in a function. Both procedures and functions may have any number of RETURN statements.

RETURN Used in Procedures

When used in a procedure, the keyword RETURN appears by itself. It causes the execution of the procedure to terminate and control to return to the calling routine. There is an implicit RETURN statement at the end of every procedure.

RETURN Used in Functions

When used in a function, the keyword RETURN is followed by the expression that is returned as the value of the function. If control falls through to the final END of a function, a run- time error occurs. The value that follows a RETURN statement is returned to the calling routine.

WHILE Statement

The WHILE statement implements a loop. The keyword WHILE is followed by a Boolean expression, followed by the keyword DO. Following this are one or more statements, followed by END. The expression is evaluated at the top of the loop. When the statement is true, the statements in the loop are executed. The expression is then re-evaluated and the loop is rerun until the Boolean expression evaluates to false.

Notice that a loop can be executed zero times when the expression evaluates to false the first time it is tested.

A valid WHILE statement is:

i := 1; { initialize counter }

done := false;


    IF test (i) THEN;

        i := i + 1; { increment counter }


        done := true;



REPEAT Statement

The REPEAT statement is another looping structure in DCAL. Unlike the WHILE loop, the body of the REPEAT statement is executed at least one time. The REPEAT loop consists of the keyword REPEAT, followed by the statements that make up the body of the loop, followed by the keyword UNTIL, followed by a Boolean expression. Every time control passes to the UNTIL statement, the Boolean expression is evaluated. When the expression evaluates to true, control passes through to the statement following UNTIL. When the expression is false, control goes back to the statement following the REPEAT statement.

A valid REPEAT statement is:

i := 10;
    write_file (i);
    i := i - 1;
UNTIL i = 0;

FOR Statement

The FOR statement is used to loop a specified number of times. The syntax of a FOR statement is:

FOR <ivar> := <startval> TO <endval> | BY <iconst> | DO <stmts> END;

The index variable (<ivar>) must be an integer variable that can be assigned. The optional BY is followed by an integer constant. This is the step size used in the FOR statement which may be positive or negative. When the BY section is not included, the step size is one (1). The <stmts> are executed until the value of <ivar> is greater than <endval>. <endval> is only evaluated once, when the loop is entered. When <startval> is greater than <endval> (and the step size is positive), the <stmts> are never executed.