Home Why Omnibasic Features FAQ Examples
Reviews Keyword/Syntax On-Line Manual Download Manual ScreenShots

Chapter 9

Compiler Directives

#SET, #FIX, CONST

The #SET compiler directive is used to define compiler variables and to set them to a numeric (long integer) value. The most common use of the compiler variable is to assign values to symbolic constants. Typically, since BASICs do not contain this feature, all constants must be literals (200, $0f, etc). Just as named variables such as Radius, Total, SubTotal, etc. are helpful and named labels such as GetInput, PrintList, etc. are more useful than line numbers, symbolic constants add much more meaning to the program than do abstract literal numbers. Any place that literal numeric constants are used (such as in expressions and DATA statements) symbolic constants may be used. The #Set directive may be used to set the same variable as many times as desired throughout the program. Thus when a compiler variable is referenced the value last assigned by a #SET directive is the value referenced. Compiler variables are also used to control the flow of conditional compilation by being tested with the #IF compiler directive. The #FIX directive is a permanent #SET. CONST (although technically a statement) is the same as #FIX. CONST is provided for QB compatability. The general form of the #SET compiler directive is as follows:

#SET CompVar=OPERAND1{OPERATOR|OPERAND2}

CompVar is the desired symbol name (the naming rules are the same as for BASIC variable, labels, etc.). The name must be unique from any other compiler variable, label, BASIC variable, macro, etc. or a symbol already defined error will occur. The “=” is mandatory as is OPERAND1. OPERAND1 (and OPERAND2 if used) must be either a compiler variable (previously created and defined with a #SET directive) or a numeric literal (either a decimal integer or Hexadecimal). Hexadecimal is indicated by a leading “$”. The OPERATOR must be a “+”, “-“, “*”, “/”, “&”, “|”, “<<” or “>>” indicating addition, subtraction, multiplication, division, AND, OR, left shift, or right shift respectively. If the OPERATOR is used it must be immediately followed by OPERAND2. Examples of the use of #SET directive follow:

#SET xyz=1 \ creates the compiler variable xyz and sets it to 1

A=A+xyz \ implied LET statement equivalent to A=A+1

#SET xyz=$ff \ changes xyz to equal Hexadecimal $ff (255)

Label DATA “test”,xyz \ equivalent to Label DATA “test”,255

#SET Side=4 \ creates the compiler variable Side and sets it to 4

Area=Side*Side \ implied LET statement equivalent to Area=4*4

#SET xyz=2 \ now equals 2

#SET abc=xyz \ creates the compiler variable abc and sets it to the value of xyz

#FIX xyz=xyz+abc \ now equals 4 (permanently)

#IF xyz=5 \ example of testing a compiler variable for conditional compilation

The #SET directive may also be used in the body of a macro declaration such as:

#MACRO MacroName \ declares a macro named MacroName
#SET CompVar=~0
DATA CompVar
#ENDM \ defines end of macro declaration

MacroName

Results in the following source code generation:

DATA 1

DATA 2

#IF, #ELSE, #ENDIF, #C, #ENDC

These compiler directives are used to provide conditional compilation, which is a feature commonly found in assemblers and “C” compilers, but rarely in Basic. Conditional compilation is useful when it is necessary to maintain more than one version of a program, which has many common sections but some different sections. Conditional sections may be nested up to 20 deep.

The argument to the #IF Directive is a simple condition of equality.

The general syntax is as follows:

#IF CompVar=Const

CompVar is a compiler variable which may be declared by a #SET or #FIX directive or on the compiler command line. Const is a constant, which may be a decimal or hexadecimal integer value or another compiler variable.

The most common way to use this feature is to assign a compiler variable at the command line. For example:

cb testprog c=1

The #ELSE directive is optional and follows the body of code after the #IF directive. The #ENDIF directive ends the conditional section.

An example follows which would go with the command line example above:

#IF c=1
print “c=1”
#ELSE
print “c<>1”
#ENDIF

The above example is of no practical use, but shows the effect of conditional compilation.

Also note that macros may be declared inside conditional sections, which effectively offers conditional macros. This is especially useful in writing I/O drivers.

#C, #ENDC

These directives allow the use of C code blocks within a program or function. After the #C directive, all input is simply passed through to the output file until a #ENDC directive is encountered. C code may also be used on a single line basis by writing a “;” in column 1.

#MACRO, #ENDM

The #MACRO and #ENDM compiler directives are used to declare MACROS. The purpose of macros is to allow the programmer to create complex blocks of code and then use them as if they were a single instruction with a descriptive name. At first glance the use of a macro might appear as a subroutine. This is not the case, however, because a subroutine appears only once in a program but may be called many times, while a macro is replicated in the code each time it is used. Also, the macro invocation allows the specification of up to 16 arguments, which are assigned to corresponding variables in the macro. The general form of the macro declaration and invocation are as follows:

Declaration:

#MACRO MacroName
{body of macro}
#ENDM

Invocation:

MacroName Arg#1,Arg#2,Arg#3,Arg#4,Arg#5,Arg#6,Arg#7,Arg#8,Arg#9

The macro declaration begins with the #MACRO compiler directive. All compiler directives may begin in any position. OmniBasic allows the substitution of “$” for “#” in directives, making them resemble meta statements from other basics. For example, $INCLUDE is the same as #INCLUDE. The body of the macro may contain no tilde characters (~) except where an argument is being specified. The body of the macro will when invoked be expanded to enter the source input stream, so the syntax within the body must conform to compiler syntax rules. Any occurrence of the tilde character without a single digit 0-9 or A-F immediately following will result in an invalid macro argument error. Any occurrence of the tilde character immediately followed by a single digit (0-9) will be replaced when the macro is invoked with the corresponding invocation argument or in the case of ~0 with the macro invocation number. Macros may NOT be nested. This means that a macro declaration (#MACRO) may not appear in the body of a macro. This will result in a nested macro error. The macro declarations are stored in a fixed size macro buffer (50,000 bytes as of this writing) and if this limit is exceeded a macro buffer full error will occur. The macro declaration is terminated by an #ENDM compiler directive. An #ENDM directive without a prior #MACRO directive will result in an #ENDM without #MACRO error. If a macro is declared which already exists the result will be a macro already defined error.

The macro invocation begins with the MacroName followed by a space followed by up to 16 macro arguments. If the macro definition has no arguments then none should be supplied in the invocation (the macro is invoked with the MacroName only). The MacroName must NOT begin in character position #1 as it will be taken for a Label. If there are less arguments in the macro invocation than are used in the macro declaration a macro argument error will occur. Macro invocation arguments are separated by a comma, and NULL arguments are specified by adjacent commas (I.E. no argument). Alphanumeric strings (including “_”,”@”, and “$”) are valid arguments as are single special characters such as “!”, “#”,”%”, etc. The SPACE and BACKSLASH characters are NOT permitted. Quoted strings are passed as arguments with the quotes themselves included in the argument. Macros must be declared before they are invoked or the invocation will result in an undefined symbol error. Macro names must not conflict with other symbol names such as variables, labels, compiler variables, etc. or a symbol already defined error will occur.

The following example illustrates a simple macro declaration and invocation:

#MACRO GetName \ declares a macro named “GetName”
PRINT “Enter Name”
INPUT ~1
PRINT ~2
#ENDM \ defines end of macro declaration

GetName UserName,”Thank You”

The invocation of the macro (GetName UserName) causes the generation of the following lines in the source code stream:

PRINT “Enter Name”
INPUT UserName
PRINT “Thank You”

The tilde character in the declaration followed by the numeral 1 indicates a macro argument, which is assigned a value during invocation. In this example it is assigned “UserName” because it is argument #1 and UserName is the first invocation argument. Accordingly the second argument (~2) is assigned the quoted string “Thank You”. Each macro may have up to 9 such arguments, which may appear any number of times in the macro declaration.

A special argument (~0) is also available in the declaration, which is replaced by the invocation number. For example, the first time a macro is invoked the ~0 will be replaced with a “1”, the second time with a “2” and so on. This function is particularly useful in generating labels within a macro. For Example:

#MACRO Demo \ declares a macro named “Demo”
Label~0 A=A+1
IF A<200 THEN Label~0
#ENDM \ defines end of macro declaration

The first invocation of the Demo macro causes the generation of the following lines in the source code stream:

Label1 A=A+1
IF A<200 then Label1

The seventh invocation of the Demo macro causes the generation of the following lines in the source code stream:

Label7 A=A+1
IF A<200 THEN Label7

For the advanced user, the macro declaration body may contain a series of C,C++ language statements (or BASIC statements or both) with the effect of implementing new statements not included in the language. This practice will eliminate much of the “trickery” and “cheat coding” often found in BASIC programs and result in much cleaner and readable code with faster execution speed. The user may accumulate a MACRO library through freeware, shareware, and purchased software.

#USE, #SBRTN, #LIB, #FCN #STRUCT, #ENDSTRUCT

The #USE compiler directive is used to incorporate other files into the source data stream. It is equivalent to the “include” directive in “C” and is especially useful in declaring macros and functions. The #USE directive may be nested up to 20 deep. This is to say that a file called by #USE may have a #USE directive itself. (#INCLUDE can be used in place of #USE). The general syntax of the #USE directive is as follows:

#USE PathList

PathList is any legal path list to a file to be included in the source data stream.

The #SBRTN compiler directive is no longer required. It is allowed for backward compatibility, but actually does nothing.

#SBRTN SubroutineName

The #LIB compiler directive is used to declare any library files which may contain relocatable files required by the program. Library files are merely a collection of relocatable modules. The #LIB directive may also be used to invoke C compiler options. The general syntax is as follows:

#LIB LibList

The #FCN compiler directive is used to declare functions. The name of the function is declared as well as the number of arguments. The general syntax is as follows:

#FCN FcnName(NumArgs)

NumArgs is a simple integer such as 1,2,3.etc. (or none).

The #STRUCT and #ENDSTRUCT are used to declare data structures just as the TYPE statement does. The only difference is that the #STRUCT directive allows declarations that are not limited by line length and the structure is more clear to look at. For example:

#STRUCT UsrType
Name:STRING[20}
Address:STRING[30]
ZipCode:BYTE
#ENDSTRUCT

The above example is equivalent to:

TYPE UsrType=Name:STRING[20];Address:STRING[30];ZipCode:BYTE

Next Page: Chapter 10 Part 1
Table of Contents


Home || Why Omnibasic || Features || FAQ || Examples
Reviews || Links || Privacy Statement || Top of Page

 

   Innomation Systems, Inc.

117 Morrison Ave. Morrison, MO 65061 (573) 294-6130

OmniBasic is a trademark of Innomation Systems, Inc., other trademarks are the property of their respective owners.
Innomation Systems, Inc. reserves the right to change prices and specifications without prior notice.
Copyright © 2000, 2001, 2002 Innomation Systems, Inc.