What is Preprocessor ?

What is Preprocessor and How it Works ?

Preprocessor  Primer ( .pdf )

Preprocessor Primer

What is Preprocessor and How it Works ?

Preprocessor Primer ( .pdf )

Design of Clipper

build the truly reusable routine

C5 Flow Control Commands, Statements and Funtions

Commands :

CALL* :

Execute a C or Assembler procedure

CALL <idProcedure> [WITH <exp list>]

CANCEL* :

Terminate program processing

CANCEL* | QUIT

DO* :

Call a procedure

DO <idProcedure> [WITH <argument list>]

QUIT

Terminate program processing

QUIT | CANCEL*

RUN :

Execute a DOS command or program

RUN | !* <xcCommandLine>

SET KEY :

Assign a procedure invocation to a key

SET KEY <nInkeyCode> TO [<idProcedure>]

SET PROCEDURE *:

Compile procedures/functions into the current .OBJ file

SET PROCEDURE TO [<idProgramFile>[.<ext>]]

WAIT* :

Suspend program processing until a key is pressed

WAIT [<expPrompt>] [TO <idVar>]

Statements :

ANNOUNCE :

Declare a module identifier

ANNOUNCE <idModule>

 BEGIN SEQUENCE :

Define a sequence of statements for a BREAK

BEGIN SEQUENCE
       <statements>...
    [BREAK [<exp>]]
       <statements>...
    [RECOVER [USING <idVar>]]
       <statements>...
END [SEQUENCE]

DO CASE :

Execute one of several alternative blocks of statements

DO CASE
   CASE <lCondition1>
       <statements>...
   [CASE <lCondition2>]
       <statements>...
   [OTHERWISE]
       <statements>...
END[CASE]

DO WHILE :

Execute a loop while a condition is true (.T.)

[DO] WHILE <lCondition>
    <statements>...
    [EXIT]
    <statements>...
    [LOOP]
    <statements>...
END[DO]

EXIT PROCEDURE :

Declare an exit procedure

EXIT PROCEDURE <idProcedure>
    [FIELD <idField list> [IN <idAlias>]]
    [LOCAL <identifier> [[:= <initializer>]]]
    [MEMVAR <identifer list>]
    .
    . <executable statements>
    .
[RETURN]

EXTERNAL* :

Declare a list of procedure or user-defined function names

EXTERNAL <idProcedure list>

FOR :

Execute a block of statements a specified number of times

FOR <idCounter> := <nStart> TO <nEnd> [STEP <nIncrement>]
    <statements>...
    [EXIT]
    <statements>...
    [LOOP]
NEXT

FUNCTION :

Declare a user-defined function name and formal parameters

[STATIC] FUNCTION <idFunction>[(<idParam list>)]
    [LOCAL <identifier> [[:= <initializer>], ... ]]
    [STATIC <identifier> [[:= <initializer>], ... ]]
    [FIELD <identifier list> [IN <idAlias>]]
    [MEMVAR <identifier list>]
    .
    . <executable statements>
    .
RETURN <exp>

IF :

Execute one of several alternative blocks of statements

IF <lCondition1>
    <statements>...
[ELSEIF <lCondition2>]
    <statements>...
[ELSE]
    <statements>...
END[IF]

INIT PROCEDURE :

Declare an initialization procedure

INIT PROCEDURE <idProcedure> [(<idParam list>)]
    [FIELD <idField list> [IN <idAlias>]]
    [LOCAL <identifier> [[:= <initializer>]]]
    [MEMVAR <identifer list>]
    .
    . <executable statements>
    .
[RETURN]

NOTE :

Place a single-line comment in a program file

NOTE This is a comment line

PARAMETERS :

Create private parameter variables

PARAMETERS <idPrivate list>

PROCEDURE :

Declare a procedure name and formal parameters

[STATIC] PROCEDURE <idProcedure> [(<idParam list>)]
    [FIELD <idField list> [IN <idAlias>]
    [LOCAL <identifier> [[:= <initializer>], ... ]]
    [MEMVAR <identifier list>]
    [STATIC <identifier> [[:= <initializer>], ... ]]
    .
    . <executable statements>
    .
[RETURN]

REQUEST :

Declare a module request list

REQUEST <idModule list>

RETURN :

Terminate a procedure, user-defined function or program

RETURN [<exp>]

Functions :

BREAK() :

Branch out of a BEGIN SEQUENCE…END construct

BREAK(<exp>) --> NIL

EVAL() :

Evaluate a code block

EVAL(<bBlock>, [<BlockArg list>]) --> LastBlockValue

IF() :

Return the result of an expression based on a condition

[I]IF(<lCondition>, <expTrue>, <expFalse>) --> Value

PCOUNT() :

Determine the position of the last actual parameter passed

PCOUNT() --> nLastArgumentPos

SETKEY() :

Assign an action block to a key

SETKEY(<nInkeyCode>, [<bAction>]) --> bCurrentAction

SETCANCEL() :

Toggle Alt-C and Ctrl-Break as program termination keys

SETCANCEL([<lToggle>]) --> lCurrentSetting

WORD()* :

Convert CALL command numeric parameters from double to int

WORD(<nNumber>) --> NIL

C5 Pre-processor Directives

#command | #translate :

Specify a user-defined command or translation directive

#command <matchPattern> => <resultPattern>
#translate <matchPattern> => <resultPattern>

#define :

Define a manifest constant or pseudofunction

#define <idConstant> [<resultText>]
#define <idFunction>([<arg list>]) [<exp>]

#error :

Generate a compiler error and display a message

#error [<messageText>]

#ifdef :

Compile a section of code if an identifier is defined

#ifdef <identifier>
    <statements>...
[#else]
    <statements>...
#endif

#ifndef :

Compile a section of code if an identifier is undefined

#ifndef <identifier>
    <statements>...
[#else]
    <statements>...
#endif

#include :

Include a file into the current source file

#include "<otherSourceFileSpec>"

#stdout :

Send literal text to the standard output device

#stdout [<messageText>]

#undef :

Remove a #define macro definition

#undef <identifier>

#xcommand | #xtranslate :

Specify a user-defined command or translation directive

#xcommand <matchPattern> => <resultPattern>
#xtranslate <matchPattern> => <resultPattern>

#command and #translate

What are #command and #translate directives ?

#command | #translate :

Specify a user-defined command or translation directive.

Syntax :

#command <matchPattern> => <resultPattern>
#translate <matchPattern> => <resultPattern>

Arguments :

<matchPattern> is the pattern the input text should match.

<resultPattern> is the text produced if a portion of input text matches the <matchPattern>.

The => symbol between <matchPattern> and <resultPattern> is, along with #command or #translate, a literal part of the syntax that must be specified in a #command or #translate directive. The symbol consists of an equal sign followed by a greater than symbol with no intervening spaces. Do not confuse the symbol with the >= or the <= comparison operators.

Description :

#command and #translate are translation directives that define commands and pseudofunctions. Each directive specifies a translation rule. The rule consists of two portions: a match pattern and a result pattern. The match pattern matches a command specified in the program (.prg) file and saves portions of the command text (usually command arguments) for the result  pattern to use. The result pattern then defines what will be written to the result text and how it will be written using the saved portions of the matching input text.

#command and #translate are similar, but differ in the circumstance under which their match patterns match input text.

A #command directive matches only if the input text is a complete statement, while #translate matches input text that is not a complete statement. #command defines a complete command and #translate defines clauses and pseudofunctions that may not  form a complete statement. In general, use #command for most definitions and #translate for special cases.

#command and #translate are similar to but more powerful than the #define directive. #define, generally, defines identifiers that control conditional compilation and manifest constants for commonly used constant values such as INKEY() codes. Refer to any of the header files in the \CLIP53\INCLUDE directory for examples of manifest constants defined using #define.

#command and #translate directives have the same scope as the #define directive. The definition is valid only for the current program (.prg) file unless defined in Std.ch or the header specified with the /U option on the compiler command line. If defined elsewhere, the definition is valid from the line where it is specified to the end of the program file. Unlike #define, a #translate or #command definition cannot be explicitly undefined. The #undef directive has no effect on a #command or #translate definition.

As the preprocessor encounters each source line preprocessor, it scans for definitions in the following order of precedence: #define, #translate, and #command. When there is a match, the substitution is made to the result text and the entire line is reprocessed until there are no matches for any of the three types of definitions. #command and #translate rules are processed in stack-order (i.e., last in-first out, with the most recently specified rule processed first).

In general, a command definition provides a way to specify an English language statement that is, in fact, a complicated expression or function call, thereby improving the readability of source code. You can use a command in place of an expression or function call to impose order of keywords, required arguments, combinations of arguments that must be specified together, and mutually exclusive arguments at compile time rather than at runtime. This can be important since procedures and user-defined functions can now be called with any number of arguments, forcing any argument checking to occur at runtime. With command definitions, the preprocessor handles some of this.

All commands in Clipper are defined using the #command directive and supplied in the standard header file, Std.ch, located in the \CLIP53\INCLUDE directory. The syntax rules of #command and #translate facilitate the processing of all Clipper and dBASE-style commands into expressions and function calls. This provides Clipper compatibility, as well as avenues of compatibility with other dialects.

When defining a command, there are several prerequisites to properly specifying the command definition. Many
pre-processor commands require more than one #command directive because mutually exclusive clauses contain a keyword or argument. For example, the @…GET command has mutually exclusive VALID and RANGE clauses and is defined with a different #command rule to implement each clause.

This also occurs when a result pattern contains different expressions, functions, or parameter structures for different clauses specified for the same command (e.g., the @…SAY command). In Std.ch, there is a #command rule for @…SAY specified with the PICTURE clause and another for @…SAY specified without the PICTURE clause. Each formulation of the command is translated into a different expression. Because directives are processed in stack order, when defining more than one rule for a command, place the most general case first, followed by the more specific ones. This ensures that the proper rule will match the command specified in the program (.prg) file.

For more information and a general discussion of commands, please look at here :

Match Pattern :

The <matchPattern> portion of a translation directive is the pattern the input text must match. A match pattern is made from one or more of the following components, which the preprocessor tries to match against input text in a specific way:

. Literal values are actual characters that appear in the match pattern. These characters must appear in the input text, exactly as specified to activate the translation directive.

. Words are keywords and valid identifiers that are compared according to the dBASE convention (case-insensitive, first four letters mandatory, etc.). The match pattern must start with a Word.

#xcommand and #xtranslate can recognize keywords of more than four significant letters.

. Match markers are label and optional symbols delimited by angle brackets (<>) that provide a substitute (idMarker) to be used in the <resultPattern> and identify the clause for which it is a substitute. Marker names are identifiers and must, therefore, follow the CA-Clipper identifier naming conventions. In short, the name must start with an alphabetic or underscore character, which may be followed by alphanumeric or underscore characters.

This table describes all match marker forms:

 Match Markers :
 ---------------------------------------------------------------------
 Match Marker Name
 ---------------------------------------------------------------------
 <idMarker> Regular match marker
 <idMarker,...> List match marker
 <idMarker:word list> Restricted match marker
 <*idMarker*> Wild match marker
 <(idMarker)> Extended Expression match marker
 ---------------------------------------------------------------------

Regular match marker: Matches the next legal expression in the input text. The regular match marker, a simple label, is the most general and, therefore, the most likely match marker to use for a command argument. Because of its generality, it is used with the regular result marker, all of the stringify result markers, and the blockify result marker.

List match marker: Matches a comma-separated list of legal expressions. If no input text matches the match marker, the specified marker name contains nothing. You must take care in making list specifications because extra commas will cause unpredictable and unexpected results.

The list match marker defines command clauses that have lists as arguments. Typically these are FIELDS clauses or expression lists used by database commands. When there is a match for a list match marker, the list is usually written to the result text using either the normal or smart stringify result marker. Often, lists are written as literal arrays by enclosing the result marker in curly ({ }) braces.

Restricted match marker: Matches input text to one of the words in a comma-separated list. If the input text does not match at least one of the words, the match fails and the marker name contains nothing.

A restricted match marker is generally used with the logify result marker to write a logical value into the result text. If there is a match for the restricted match marker, the corresponding logify result marker writes true (.T.) to the result text; otherwise, it writes false (.F.). This is particularly useful when defining optional clauses that consist of a command keyword with no accompanying argument. Std.ch implements the REST clause of database commands using this form.

Wild match marker: Matches any input text from the current position to the end of a statement. Wild match markers generally match input that may not be a legal expression, such as #command NOTE <*x*> in Std.ch, gather the input text to the end of the statement, and write it to the result text using one of the stringify result markers.

Extended expression match marker: Matches a regular or extended expression, including a file name or path specification. It is used with the smart stringify result marker to ensure that extended expressions will not get stringified, while normal, unquoted string file specifications will.

. Optional match clauses are portions of the match pattern enclosed in square brackets ([ ]). They specify a portion of the match pattern that may be absent from the input text. An optional clause may contain any of the components allowed within a <matchPattern>, including other optional clauses.

Optional match clauses may appear anywhere and in any order in the match pattern and still match input text. Each match clause may appear only once in the input text. There are two types of optional match clauses: one is a keyword followed by match marker, and the other is a keyword by itself. These two types of optional match clauses can match all of the traditional command clauses typical of the CA-Clipper command set.

Optional match clauses are defined with a regular or list match marker to match input text if the clause consists of an argument or a keyword followed by an argument (see the INDEX clause of the USE command in Std.ch). If the optional match clause consists of a keyword by itself, it is matched with a restricted match marker (see the EXCLUSIVE or SHARED clause of the USE command in Std.ch).

In any match pattern, you may not specify adjacent optional match clauses consisting solely of match markers, without generating a compiler error. You may repeat an optional clause any number of times in the input text, as long as it is not adjacent to any other optional clause. To write a repeated match clause to the result text, use repeating result clauses in the <resultPattern> definition.

Result Pattern :

The <resultPattern> portion of a translation directive is the text the preprocessor will produce if a piece of input text matches the <matchPattern>. <resultPattern> is made from one or more of the following components:

. Literal tokens are actual characters that are written directly to the result text.

. Words are Clipper language keywords and identifiers that are written directly to the result text.

. Result markers: refer directly to a match marker name. Input text matched by the match marker is written to the result text via the result marker.

This table lists the Result marker forms:

Result Markers :
---------------------------------------------------------------------
Result Marker   Name
---------------------------------------------------------------------
<idMarker>      Regular result marker
#<idMarker>     Dumb stringify result marker
<"idMarker">    Normal stringify result marker
<(idMarker)>    Smart stringify result marker
<{idMarker}>    Blockify result marker
<.idMarker.>    Logify result marker
---------------------------------------------------------------------

Regular result marker:

Writes the matched input text to the result text, or nothing if no input text is matched. Use this, the most general result marker, unless you have special requirements. You can use it with any of the match markers, but it almost always is used with the regular match marker.

Dumb stringify result marker:

Stringifies the matched input text and writes it to the result text. If no input text is matched, it writes a null string (“”). If the matched input text is a list matched by a list match marker, this result marker stringifies the entire list and writes it to the result text.

This result marker writes output to result text where a string is always required. This is generally the case for
commands where a command or clause argument is specified as a literal value but the result text must always be written as a string even if the argument is not specified.

Normal stringify result marker:

Stringifies the matched input text and writes it to the result text. If no input text is matched, it writes nothing to the result text. If the matched input text is a list matched by a list match marker, this result marker stringifies each element in the list and writes it to the result text.

The normal stringify result marker is most often used with the blockify result marker to compile an expression while
saving a text image of the expression (See the SET FILTER condition and the INDEX key expression in Std.ch).

Smart stringify result marker:

Stringifies matched input text only if source text is enclosed in parentheses. If no input text matched, it writes nothing to the result text. If the matched input text is a list matched by a list match marker, this result marker stringifies each element in the list (using the same stringify rule) and writes it to the result text.

The smart stringify result marker is designed specifically to support extended expressions for commands other than SETs with <xlToggle> arguments. Extended expressions are command syntax elements that can be specified as literal text or as an expression if enclosed in parentheses. The <xcDatabase> argument of the USE command is a typical example. For instance, if the matched input for the <xcDatabase> argument is the word Customer, it is written to the result text as the string “Customer,” but the expression (cPath + cDatafile) would be written to the result text unchanged (i.e., without quotes).

Blockify result marker:

Writes matched input text as a code block without any arguments to the result text. For example, the input text x + 3 would be written to the result text as {|| x + 3}. If no input text is matched, it writes nothing to the result text. If the matched input text is a list matched by a list match marker, this result marker blockifies each element in the list.

The blockify result marker used with the regular and list match markers matches various kinds of expressions and writes them as code blocks to the result text. Remember that a code block is a piece of compiled code to execute sometime later. This is important when defining commands that evaluate expressions more than once per invocation. When defining a command, you can use code blocks to pass an expression to a function and procedure as data rather than as the result of an evaluation. This allows the target routine to evaluate the expression whenever necessary.

In Std.ch, the blockify result marker defines database commands where an expression is evaluated for each record. Commonly, these are field or expression lists, FOR and WHILE conditions, or key expressions for commands that perform actions based on key values.

Logify result marker:

Writes true (.T.) to the result text if any input text is matched; otherwise, it writes false (.F.) to the result text. This result marker does not write the input text itself to the result text.

The logify result marker is generally used with the restricted match marker to write true (.T.) to the result text if an optional clause is specified with no argument; otherwise, it writes false (.F.). In Std.ch, this formulation defines the EXCLUSIVE and SHARED clauses of the USE command.

. Repeating result clauses :

Are portions of the <resultPattern> enclosed by square brackets ([ ]). The text within a repeating clause is written to the result text as many times as it has input text for any or all result markers within the clause. If there is no matching input text, the repeating clause is not written to the result text. Repeating clauses, however, cannot be nested. If you need to nest repeating clauses, you probably need an additional #command rule for the current command.

Repeating clauses are the result pattern part of the #command facility that create optional clauses which have arguments. You can match input text with any match marker other than the restricted match marker and write to the result text with any of the corresponding result markers. Typical examples of this facility are the definitions for the STORE and REPLACE commands in Std.ch.

Notes :

. Less than operator:

If you specify the less than operator (<) in the <resultPattern> expression, you must precede it with the escape character (\).

. Multistatement lines:

You can specify more than one statement as a part of the result pattern by separating each statement with a semicolon. If you specify adjacent statements on two separate lines, the first statement must be followed by two semicolons.

Examples :

These examples encompass many of the basic techniques you can use when defining commands with the #command and #translate directives. In general, these examples are based on standard commands defined in Std.ch. Note, however, the functions specified in the example result patterns are not the actual functions found in Std.ch, but fictitious functions specified for illustration only.

. This example defines the @…BOX command using regular match markers with regular result markers:

#command @ <top>, <left>, <bottom>, <right> BOX ;
<boxstring>;
=>;
CmdBox( <top>, <left>, <bottom>, ;
<right>,<boxstring> )

. This example uses a list match marker with a regular result marker to define the ? command:

#command ? [<list,...>] => QOUT(<list>)

. This example uses a restricted match marker with a logify result marker to implement an optional clause for a command definition. In this example, if the ADDITIVE clause is specified, the logify result marker writes true (.T.) to the result text; otherwise, it writes false (.F.):

#command RESTORE FROM <file> [<add: ADDITIVE>];
=>;
CmdRestore( <(file)>, <.add.> )

. This example uses a list match marker with a smart stringify result marker to write to the result text the list of fields specified as the argument of a FIELDS clause. In this example, the field list is written as an array with each field name as an element of the array:

#command COPY TO <file> [FIELDS <fields,...>];
=>;
CmdCopyAll( <(file)>, { <(fields)> } )

. These examples use the wild match marker to define a command that writes nothing to the result text. Do this when attempting to compile unmodified code developed in another dialect:

#command SET ECHO <*text*> =>
#command SET TALK <*text*> =>

. These examples use wild match markers with dumb stringify result markers to match command arguments specified as literals, then write them to the result text as strings in all cases:

#command SET PATH TO <*path*> => SET( _SET_PATH, #<path> )
#command SET COLOR TO <*spec*> => SETCOLOR( #<spec> )

. These examples use a normal result marker with the blockify result marker to both compile an expression and save the text version of it for later use:

#command SET FILTER TO <xpr>;
=>;
CmdSetFilter( <{xpr}>, <"xpr"> )
#command INDEX ON <key> TO <file>;
=>;
CmdCreateIndex( <(file)>, <"key">, <{key}> )

. This example demonstrates how the smart stringify result marker implements a portion of the USE command for those arguments that can be specified as extended expressions:

#command USE <db> [ALIAS <a>];
=>;
CmdOpenDbf( <(db)>, <(a)> )

. This example illustrates the importance of the blockify result marker for defining a database command. Here, the FOR and WHILE conditions matched in the input text are written to the result text as code blocks:

#command COUNT [TO <var>];
[FOR <for>] [WHILE <while>];
[NEXT <next>] [RECORD <rec>] [<rest:REST>] [ALL];
=>;
<var> := 0,;
DBEVAL( {|| <var>++}, <{for}>, <{while}>,;
<next>, <rec>, <.rest.> )

. In this example the USE command again demonstrates the types of optional clauses with keywords in the match pattern. one clause is a keyword followed by a command argument, and the second is solely a keyword:

#command USE <db> [<new: NEW>] [ALIAS <a>] ;
[INDEX <index,...>][<ex: EXCLUSIVE>] ;
[<sh: SHARED>] [<ro: READONLY>];
=>;
CmdOpenDbf(<(db)>, <(a)>, <.new.>,;
IF(<.sh.> .OR. <.ex.>, !<.ex.>, NIL),;
<.ro.>, {<(index)>})

. This example uses the STORE command definition to illustrate the relationship between an optional match clause and a repeating result clause:

#command STORE <value> TO <var1> [, <varN> ];
=>;
<var1> := [ <varN> := ] <value>

. This example uses #translate to define a pseudofunction:

#translate AllTrim(<cString>) => LTRIM(RTRIM(<cString>))

Command Terms

Clause :

An optional or required section of a Clipper language command beginning with a keyword that modifies or enhances the command.

Command :

A statement to be translated by the Clipper preprocessor into source code that will perform a particular operation. All Clipper language commands are defined in the standard header file, STD.CH, located in …INCLUDE. Also, the preprocessor directives that define a command.

See Also: Header File, Statement, STD.CH

Condition :

A logical expression that determines whether an operation will take place. With database commands, a logical expression that determines what records are included in an operation. Conditions are specified as arguments of the FOR or WHILE clause.

Keyword :

A word that has a special meaning to a compiler or other utility program. Commands, directives, or options are often recognized by examining supplied text to see if it contains keywords.

List :

A list of expressions, field names, or filenames, separated by commas specified generally as command, procedure, or function arguments. Code blocks can also execute a list of expressions.

Optional Clause :

A portion of a match pattern that is enclosed in square ([ ]) brackets. An optional clause specifies part of a match pattern that need not be present for source text to match the pattern. An optional clause may contain any of the components legal within a match pattern, including other optional clauses. When a match pattern contains a series of optional clauses that are immediately adjacent to each other, the matching portions of the source text are not required to appear in the same order as the clauses in the match pattern. If an optional clause is matched by more than one part of the source text, the multiple matches may be handled using a repeating clause in the result pattern.

Scope :

In a database command, a clause that specifies a range of database records to be addressed by the command. The scope clause uses the qualifiers ALL, NEXT, RECORD, and REST to define the record scope.

See Also: Condition

Skeleton :

A wildcard mask used to specify a group of filenames or memory variables. The * is used to specify one or more characters and the ? to specify a single character.

Toggle :

As a verb, to choose between an on or off state. As a noun, a value or setting that can be either on or off. A toggle is often represented using a logical value, with true (.T.) representing on, and false (.F.) representing off.

Verb :

The first word of a command that describes the action to perform.

See Also: Command

#include directive

What is #include directive ?

#include

Include a file into the current source file

Syntax :

#include “<headerFileSpec>”

Arguments

<headerFileSpec> specifies the name of another source file to include in the current source file. As indicated in the syntax,  the name must be enclosed in double quotation marks.

<headerFileSpec> may contain an explicit path and file name as well as a file extension. If, however, no path is specified,  the preprocessor searches the following places:

. Source file directory

. Directories supplied with the /I option

. Directories specified in the INCLUDE environment variable

#include directives may be nested up to 15 levels deep–that is, a file that has been included may contain #include  directives, up to 15 levels.

Description

#include inserts the contents of the specified file in place of the #include directive in the source file. By convention, the file inserted is referred to as a header file. Header files should contain only preprocessor directives and external declarations. By convention header files have a .ch extension.

When deciding where to locate your header files, you have two basic choices. You can place them in the source file directory where they are local to the current system; or, you can make them globally available by placing them in the directory specified in the INCLUDE environment variable. A list of one or more directories can be specified.

Header files overcome the one major drawback of defining constants or inline functions–the #define directive only affects the file in which it is contained. This means that every program which needs access to these statements must have a list of  directives at the top. The solution to this problem is to place #define statements in a separate file and use the #include directive to tell the preprocessor to include that file before compiling.

For example, suppose the file “Inkey.ch” contains a list of #define directives assigning key values to constants. Instead of including these directives at the top of each program file (.prg) requiring access to them, you can simply place the following line at the top of each program file:

#include “Inkey.ch”

This causes the preprocessor to look for Inkey.ch and place all the directives contained within it at the top of this program.

Another advantage of using the #include directive is that all the #define statements are contained in one file. If any modifications to these statements are necessary, only the #include file need be altered; the program itself remains untouched.

Note that the scope of definitions within an included header file is the current program file unless the header file is included on the compiler command line with the /U option. In this case, the scope is all the program files compiled in the current invocation of the compiler.

Notes

Supplied header files: The compiler provides a number of header files containing manifest constants for common operations.

Std.ch–the standard header file: Std.ch is the standard header file provided with compiler. Std.ch contains the definitions of all compiler commands and the standard functions specified as pseudofunctions. It is strongly recommended that no changes be made to Std.ch. If changes are desired, it is advisable to copy Std.ch to a new name, make the changes, and compile with /U.

This header file differs somewhat from a header file you might #include in that everything defined in Std.ch, with #define, #translate, or #command, has a scope of the entire compile rather than the current source file.

Examples

This example uses #include to insert Inkey.ch, a file of common keyboard definitions, into a key exception handler called by an interface function:

#include "Inkey.ch"
FUNCTION GetEvent()
   LOCAL nKey, nResult
   nKey = INKEY(0)
   DO CASE
      CASE nKey = K_F10
         nResult := DoMenu("Browse")
      CASE nKey = K_ESC
         nResult := DoQuit()
      .
      . <statements>
      .
      CASE nKey = K_CTRL_RIGHT
          nResult := DoNextRec()
   ENDCASE

RETURN nResult

Pre-processor

What is Pre-processor and how it works ?

The Pre-processor is a translation program that prepares source code for compilation by  applying pre-defined text replacements. The replacements to be made are specified by  directives in the source file. The preprocessor operates transparently as a part of the  compilation process.

First phase of of compilation process is pre-processing. The portion of compile engine  that perform pre-processing phase is called pre-processor.

Before the later compilation  phases take place, pre-processor scan the source file from top to bottom for certain  directives and translate them into regular source code that can be compiled. The output of  the pre-processor is then used as input to the next step of compilation. The /P compiler  option can be used to write this pre-processor output (.ppo) file to disk so that you can  see the source code that was used as input to the next compilation phase. This option  is especially useful if you have used the #command and #translate directives to build  user-defined commands. You can look at the (.ppo) file to see whether or not commands  translated as you expected.

The following table summarize the pre-processor directives.

Directive              Meaning
--------------------   --------------------------------------------------------------
#define                Define a manifest constant or pseudo-function
#undef                 Remove a #define definition

#include               Include a file into the current source file

#command, #xcommand,   Specify a user defined command or translation 
#translate,            directive (This four directives are same as each
#xtranslate            others with some minor differences) . 

#ifdef                 Compile a section of code if an identifier is defined
#ifndef                Compile a section of code if an identifier is undefined

#error                 Generate a compiler error and display a message
#stdout                Send literal text to the standard output device

Here you can find pre-processor terms.