DEFINE symbol = value
This statement defines the constant <symbol> to be equal to <value>. It was added to A-Shell in Build 923 of 15 March 2005. Some examples:
DEFINE TCRT'REVON = 32
DEFINE XTF'CTRLC = &h01000000
DEFINE MY'NAME$ = "JACK"
The names following the DEFINE must conform to the normal rules for variable names (start with an alphabetic character and contain alphabetic, numeric and apostrophe or underline characters plus an optional $ or % suffix).
The definition must either be a literal numeric value (as in the first two examples above), or a quoted string value.
These definitions act like macros, substituting the definition into the source code before each line of the program is compiled. Because of this, compiler error messages will usually display the line after macro expansions (which may look strange at first, but since the error messages also show the line number, it allows you to compare your source code to the result after the macro replacements.)
From a logic standpoint, the result is equivalent to using MAP statements, i.e.:
MAP1 TCRT'REVON,B,1,32
MAP1 XTF'CTRLC,B,4,&h01000000
MAP1 MY'NAME$,S,4,"JACK"
The main advantages of DEFINE over MAP statements are:
• You cannot assign a value to a DEFINEd symbol; thus, they act like true constants.
• DEFINEd constants take up no space in the RUN file unless they are used. Thus it is practical to create ++INCLUDE files which define constants for virtually every situation, without worrying about the overhead. (They do create some compiler overhead, but is that really something we need to worry about?)
• Even for constants that are referenced in the program, constants generally save space in the RUN file. A non-subscripted MAP statement with an initial value takes 16 bytes, and then it takes another 2 or 3 bytes to reference it in the code. A constant takes zero bytes to define, and generally only 2 bytes to reference. (Depending on the number of significant binary digits in the constant, it may take 4 or 6 bytes to represent. But in the vast majority of cases, DEFINEd constants are small integers or powers of 2 and can be represented in only 2 bytes. Strings require 2 bytes plus their length to reference as constants, so in that case, the use of constants may actually increase the size of the RUN, assuming they are referenced multiple times.)
• Because of the above, converting MAP statements to DEFINEd constants (assuming they are never assigned more than one value) will result in smaller RUN files, with a very slight bonus in performance, at the cost of a slight increase in compile times. But the main advantage comes in programming clarity when you use meaningful symbolic names for constant values in place of literal number or mapped variables.
Including a file containing an unknown set of DEFINEs is generally safe and should have no side effect on an existing program (unless you deliberately use the defined constants). There are, however, some scenarios to be aware of:
• If a DEFINE precedes a MAP statement for the same identifier, the MAP statement will generate a syntax error, because the MAP statement identifier will be replaced by the value of the DEFINEd symbol before it gets compiled. For example:
DEFINE CTLOP'ADD = 1
MAP1 CTLOP'ADD,B,2,1
Since the CTLOP'ADD in the MAP statement will be replaced by 1, it will be compiled (and a syntax error generated) as if it were:
MAP1 1,B,2,1
• If a DEFINE conflicts with an unmapped variable, a similar thing will happen when you try to assign a value to the variable:
DEFINE CANADA'VAT = .15
CANADA'VAT = .16 ! assignment to unmapped variable
This will also cause a syntax error, because it will look to the compiler as if it were:
.15 = .16
(If the unmapped variable is never referenced, you won't get a syntax error, but then again it won't matter to your program operation either.)
• The one case where you might have a problem is if you reference an unmapped (and unassigned) variable in an IF statement, i.e.:
IF CANADA'VAT = .16 THEN ...
This will compile as if it were:
IF .15 = .16 THEN ...
That is a perfectly legal statement, and won't be what you expected (although your test of an unmapped/unassigned variable probably won't be what you wanted either, unless you were counting on it being zero). To eliminate this possibility, compile your programs with /M !!!
• If you attempt to DEFINE a symbol that has already been MAPPED, you will get a duplicate label error. So it doesn't really matter whether you DEFINE all your symbols first or do all your MAPs first, or mix them together; any conflict between the two will generate a compilation error.
See Also
• UNDEF