To use the preprocessorThe compiler
All preprocessor directives starts with a Include Files To include files this statement is used: Files included between < and > are searched in the Normally the filename between quotes is searched by using the
standard file redirection method. Suppose this entry occurs in
and there is an include statement like:
The file If a / occurs in the filename, the file is searched using the specified path name. When a file is included twice, the second include is ignored. Note that the preprocessor only works during compilation of a
3GL source because the standard generator Macro Definition To define macros this statement can be used: #define macroname[(arguments)] macro definition macro definition To undefine macros the following statement can be used: The macro names in the source are expanded to the macro definition. If a macro definition does not fit on one line, you can continue the definition on the next line(s) using the caret symbol ^ at the beginning of the next line. You can use arguments in the macro. Example: #define a(x, y, z) for i = x to y ^ z() ^ and for | The definition a(1, 100, func) | The invocation Macro definitions with the same name but with different number of arguments are different, as in this example: #define x definition without arguments #define x() definition with 0 arguments #define x(arg1) definition with 1 argument arg1 #define x(arg1,arg2) definition with 2 arguments #define x(...) definition with ellipsis ... (see below) Note that there is a difference between a macro without arguments x and a macro with zero arguments x(). In the first case you must use x in the program script and in the second case you must use x() in the program script to call the macro. The #define MAXLENGTH 1000 #define INCR 1 #define INCR(i) i=i+INCR ..... #undef MAXLENGTH #define INCR 2 | Redefines INCR ..... #undef INCR(i) If you apply #ifdef INCR | without arguments #undef INCR(i) #endif | of #ifdef / #endif calls See Conditional Compiling for a detailed description Variable Macro Arguments To define a macro, you can also use the ellipsis notation ( , ... ) to give the macro a varying number of arguments. Example #define fillbuf(buf1, format, ...) buf1 = sprintf$(format,...) | macro call string buffer(100) long l_val double d_val fillbuf(buffer, %d. %s = %d %5.2f, 1, Value, l_val, d_val) The macro definition can contain a number of arguments, but the
ellipsis notation must be the last argument. This notation can be used with
functions that also use the ellipsis notation, such as the Token Pasting In the macro you can enter a part of a variable as macro argument. The symbol ## is used to distinguish macro arguments and the rest of the macro, but is omitted in the macro call. You can paste more macro arguments together as one identifier. This principle is called token pasting. Example #define p(x) message("%d", var##x) #define q(x,y) message("%d", x##y) #define r(x,y,z) message("%d", x##y##z) long var1a, var1b p(1a) | becomes: message("%d", var1a) p(1b) | becomes: message("%d", var1b) q(var, 1a) | becomes: message("%d", var1a) q(var, 1b) | becomes: message("%d", var1b) r(var, 1, a) | becomes: message("%d", var1a) r(var, 1, b) | becomes: message("%d", var1b) This method is used to reuse parts of source code, where using functions is impossible or difficult to use functions. See this example. Example #define VRC(table,v,r,c) ^ tt##table##.vers = v ^ tt##table##.rele = r ^ tt##table##.cust = c VRC(adv100, "6.2", "a", "") VRC(adv200, "6.2", "a", "") VRC(adv300, "6.2", "a", "") Object Identifications To set an identification in the object, use this statement:
Example
A default identification is always placed in the object by the compiler with these contents: #ident "@(#)<source name>, YY/MM/DD, [HH/MM], From ${logname}" The UNIX what command writes all object lines beginning with '@(#)' on standard output. Besides this default identification the programmer can use his own identification which is also placed in the object. Pragma Codes Pragma codes are a kind of compiler options. These pragma codes can be used:
Example #pragma warning This is not a fine solution ! | After compilation the following warning appears: | <Source(line)>: Warning(15): This is not a fine solution ! In some cases the where-used list will not be updated automatically. For example, when a session code is entered but not expected. For example,
To put this session code into the where-used list, enter the following command line:
Following is an overall picture of the pragma codes to update the where-used list:
Usually the where-used list will be updated. In case of functions, the where-used list is updated if the function call contains the string value. (see example). Example mess("ttadvs0000", 1) | Where-used list will be updated str = "ttadvs0000" mess(str, 1) | Where-used list will not be updated #pragma used message ttadvs0000 Pragma codes can be placed everywhere in the source. For instance, you have set this pragma on top of the source:
After a number of warnings, you can enter this pragma:
Conditional Compiling #ifdef <macro> The source after #ifdef up to #else/#elif/#endif will be compiled if <macro> is defined. Otherwise this source is ignored. #ifndef <macro> The source after #ifndef up to #else/#elif/#endif will be compiled if <macro> is not defined. Otherwise this source is ignored. #if <constant expression> The source after #if up to #else/#elif/#endif will be compiled if <constant expression> is TRUE. Otherwise this source is ignored. #else If the condition belonging to #if/#ifdef/#ifndef/#elif is FALSE, the source after #else up to #endif will be compiled. If the condition belonging to #if/#ifdef/#ifndef/#elif is TRUE, the source after #else up to #endif will be ignored. #elif <constant expression> #elif is a combination of #else and #if. Example #if <constant expression> ... #else #if <constant expression> ... #else ... #endif #endif Is equal to: #if <constant expression> ... #elif <constant expression> ... #else ... #endif #endif To finish a part of the source started with #ifdef/#ifndef/#if #undef <macro> To delete a macro definition, which means that this macro is not known on a next #ifdef call. The <constant expression> in a #if, #elif is a numeric expression. In this expression you can only use macros of long type and operators such as +, -, *, /, =, <, >, <=, >=, <>, and, or, not, ?:, (). You can use nested #if structures. You can define a macro while starting the compiler by using the bic6.2 -D<macro> | no value means default 1 bic6.2 -D<macro>=<value> bic6.2 -D<macro>='any token string' These macros can also be used in the #if conditions as in these examples: bic6.2 -DDEBUG -DMYTEST <source> |source #if DEBUG and MYTEST message(Some debug information) ... #endif bic6.2 -DCUSTOMER_X -DCUSTOMER_Y <source> bic6.2 -DSTANDARD <source> #if STANDARD .... #elif ( CUSTOMER_X and (not CUSTOMER_Y) ) .... #endif You can inactivate a file with #ifdef: Example: #ifdef OLD .... .... .... #endif Note that the preprocessor only works during compilation of a
3GL source because the standard generator You cannot use a #ifdef statement in an embedded SQL query. This formula is not allowed: select * #ifdef STANDARD ... from x #else ... from y #endif where ... selectdo ... endselect But this construction is possible: #ifdef STANDARD select * from x where ... selectdo ... endselect #else select * from y where ... selectdo ... endselect #endif Two keywords are implemented to give debug information in 3GL sources: __FILE__ : contains the name of the current source __LINE__ : contains the line number of the current source Example message(This is at line %d in the source %s, __LINE__, __FILE__)
| |||||||||||||||||||||||||||||||||||||||||