Coding Guidelines

Coding Guidelines

( by Greg Holmes )

Language Syntax 
The general rule of thumb is: built-in features in lowercase, and custom-written functions in mixed case. 
When specifying the complete syntax of a language element in documentation, the input items, parameters, and so on are referred to using the following symbols:

 Symbol  Description
< >  Indicates user input item
( )  Indicates function argument list
[ ]  Indicates optional item or list
{ }  Indicates code block or literal array
| |  Indicates code block argument list
–>  Indicates function return value
 Repeated elements if followed by a symbol
Intervening code if followed by a keyword
,  Item list separator
|  Indicates two or more mutually exclusive options
@  Indicates that an item must be passed by reference
*  Indicates a compatibility command or function

For example:

    len(<cString>|<aArray>) --> nLength

Metasymbols provide a place holder for syntax elements, and they describe the expected data types. A metasymbol consists of one or more lowercase data type designators followed by a mixed case description. This is known as Hungarian Notation.

 Designator  Description
a  Array
b  Code block
c  Character expression
d  Date expression
exp  Expression of any type
id  Literal identifier
l  Logical expression
m  Memo field
n  Numeric expression
o  Object
x  Extended expression

In this example, dnLower and dnUpper can be either date or numeric:

    @...get...range <dnLower>, <dnUpper>
Filenames and Aliases 
All filenames, in any context, are in upper case. Filenames follow DOS naming conventions (preferably limited to letters, numbers, and the underscore).

    use CUSTOMER
    nHandle := fopen('DATAFILE.DAT')

When referring to specific file types in documentation, include the period.
e.g. “A program is stored in a text file with a .PRG extension.” 
Alias names follow the same conventions as filenames, but are limited to A-Z, 0-9, and the underscore. If a filename begins with a number or contains unusual characters, an alias must be specified when the file is opened or an error will result. 
Note that CA-Clipper does not natively support Windows 95 long filenames, although third-party libraries are available to add the capability.

Fieldnames 
Fieldnames are all uppercase, and always include the alias of the table. Fieldnames may contain underscores, but should not begin with one (because the underscore is generally used to indicate an internal symbol).

    @ 10, 10 say BANKS->BRANCH
    nAge := CUSTOMER->CUST_AGE
Memory Variables 
Memory variables consist of a lowercase type designator followed by a mixed case description (see Hungarian Notation). Although CA-Clipper only recognizes the first 10 characters as unique, variable names may be longer.

    cString := "Hello World"
    nYearlyAverage := CalcYearAvg()

If you use Hungarian Notation for your memory variable names and include the table alias with fieldnames, there will be no conflict between the two.

Commands, Functions, and Keywords 
All built-in commands, functions, and keywords are lowercase. In documentation, the font should be Courier or a similar font. If fonts are not available, then bold or CAPITALIZE the word for emphasis. 
Never use abbreviations — this practice is not necessary with a compiler, although it was common in the early days of dBase (which was an interpreter). 
There should never be a space between the function name and the opening parenthesis. Also, note that the iif() function should never be spelled if().

    replace CUSTOMER->CUSTNAME with cCustName
    nKey := inkey(0)

When specifying commands that have clauses in documentation, separate the keywords with an ellipsis (...) and do not include the to clause, unless it is followed by the file,print, or screen keywords.

    copy...sdf
    set message...center
    @...say...get
Programmer-Defined Functions & Procedures 
These begin with an uppercase letter, followed by mixed case letters as appropriate.

    ? StripBlanks("Hello there, this will have no spaces.")

Function and procedure names may contain underscores, but should not begin with one (they may conflict with internal functions which often start with an underscore). There should be only one return statement per function or procedure, and it should not be indented.

    function SomeFunc (...)
      .
      . <statements>
      .
    return cResult

The return value of a function is not enclosed in parentheses, although parentheses may be used to clarify a complex expression.

    return nValue
    return (nCode * 47) + nAnswer
Preprocessor Directives 
Preprocessor directives are lowercase and are preceded by the # sign.

    #include 'INKEY.CH'

Optionally, you may use single quotes around header files that come with CA-Clipper and double quotes around your own. This convention is purely voluntary, but it helps to distinguish between the two. For example:

    #include 'INKEY.CH'
    #include "MY_APP.CH"

Manifest constants are uppercase.

    #define ESCAPE   27
    if lastkey() == ESCAPE

Pseudo-function names should also be uppercase.

    #define AREA(length, width)   ((length)*(width))
Declarations 
Local variables are grouped according to functionality, and may be declared on one or more lines. The declarations appear as the first code at the beginning of a function or procedure.

    procedure Main ( )
    local nTop, nLeft, nBottom, nRight
    local cOldScreen, cOldColor, nOldCursor

Variables may be declared one per line and accompanied by a description.

    local nCount        // Number of records found.
    local nTotal        // Sum of dollars.

The description can be omitted if better variable names are chosen.

    local nRecordCount
    local nDollarTotal

Variables can be initialized when they are declared, although it is often clearer (and safer) to initialize them immediately before they are used.

    local nRecordCount:=0
    local nDollarTotal:=0
Logicals 
The .T. and .F. are typed in uppercase.
Operators 
The in-line assignment operator (:=) is used for all assignments, and the exact comparison operator (==) is used for all comparisons.

    lContinue := .T.
    nOfficeTotal := nRegionTotal := 0
    lDuplicate := (CUSTFILE->CUSTNAME == cCustName)
    if nLineCount == 4  ...
    if left(PRODUCT->CODE, 3) == left(cProdCode, 3)  ...

Although the compound assignment operators (+=-=*=, etc.) are convenient, they should not be used if readability suffers.

    // The traditional way to accumulate:
    nTotal := nTotal + INVDETAIL->PRICE
    // A good use of a compound assignment operator:
    nTotal += INVDETAIL->PRICE
    // But what does this do?
    nVal **= 2

The increment (++) and decrement (--) operators are convenient, but can lead to obscure code because of the difference between prefix and postfix usage.

    nRecCount++
    nY := nX-- - --nX        // Huh?
Spacing 
Whenever a list of two or more items is separated by commas, the commas are followed by a space.

    MyFunc(nChoice, 10, 20, .T.)

Spaces may be used between successive parentheses.

    DoCalc( (nItem > nTotal), .F. )
    cNewStr := iif( empty(cStr), cNewStr, cStr + chr(13) )

Spaces should surround all operators for readability.

    nValue := 14 + 5 - (6 / 4)

In declarations, often spaces are not used around the assignment operator. This tends to make searching for the declaration of a variable easier.

    local lResult:=.F., nX:=0

Thus, searching for “nX :=” would find the lines where an assignment is made, while searching for “nX:=” would find the declaration line (such as the local above).

Indentation 
Indenting control structures is one of the easiest techniques, yet it improves the readability the most. 
Indent control structures and the code within functions and procedures 3 spaces.

    procedure SaySomething
       do while .T.
          if nTotal < 50
             ? "Less than 50."
          elseif nTotal > 50
             ? "Greater than 50."
          else
             ? "Equal to 50."
          endif
          ...
       enddo
    return

Case statements in a do…case structure are also indented 3 spaces.

    do case
       case nChoice == 1
          ? "Choice is 1"
       case ...
          ...
       otherwise
          ...
    endcase
Tabs 
Do not use tabs in source code — insert spaces instead. Tabs cause problems when printing or when moving from one editor to another, because of the lack of a standard tab width between editors and printers. Typically, printers expand tabs to 8 spaces which easily causes nested control structures to fall off the right-hand side of the page. Commonly, a source code editing program will insert the appropriate number of spaces when the <TAB> key is hit.
Line Continuation 
When a line of code approaches the 80th column, interrupt the code at an appropriate spot with a semicolon and continue on the next line. Indent the line so that it lines up in a readable manner.

    set filter to CUSTFILE->NAME  == 'John Smith  ';
            .and. CUSTFILE->STATE == 'OR'

To continue a character string, end the first line with a quote and a plus sign and place the remainder on the next line. Try to choose a logical place in the string to break it, either at a punctuation mark or after a space.

    @ 10, 10 say "The lazy brown fox tripped over " + ;
                 "the broken branch."
Quotes 
Use double quotes for text that needs to be translated (will appear on the screen), and single quotes for other strings.

    ? "Hello World!"
    cColor := 'W+/B'
    SelectArea('PROP')

This is a simple but extremely effective technique because translation departments often want to see the messages in context (in the source code), so the different quote types indicate which messages are to be translated and which should be left alone.

Comments 
Comments are structured just like English sentences, with a capital letter at the beginning and a period at the end.

    // Just like a sentence.
    /* This comment is longer. As you
       can see, it takes up two lines */

You may encounter old-style comment indicators if you maintain older (Summer’87 and earlier) code.

    && This is an older-style of comment indicator.
    *  The asterisk is also old.

For in-line comments, use the double slashes.

    use CUSTOMER            // Open the data file.
    goto bottom             // The last record.

Note that the ‘//‘ of in-line comments begins at column 40, if possible. This leaves enough room for a useful comment.

Source :  http://www.ghservices.com/gregh/clipper/guide.htm

C5_#command | #translate

#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 in the Clipper language.

 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 preprocessor 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, refer to the
     "Basic Concepts" chapter in the Programming and Utilities Guide.

 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 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 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 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>))

See Also: #define #xcommand


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 )

.ch Files

What are .ch files ?

ch means “C header” and as name implied, this coding way borrowed from C language.

Normally, that files written individually and are included into .prg file via #include directive.

In general, .ch files includes pre-processor directives for constant declarations, pseudo functions and commands; including #include directives for other files. These lines are general purpose code line and may or not may #included by more than one .prg files.

For example, say we have some values like :

pi := 22 / 7
MaxUserCount := 10

If we declare this constants as above in the .prg file, this two identifiers are variables.

We can declare that values in another way :

#define pi 22 / 7
#define MaxUserCount 10

In this case this two identifiers are constant, so their values has been fixed, no changeable afterward. #define is a pre-processor directive, these two identifiers are meta-constants and can be use in the code (.prg) file, after defined place ( if defined at top of file, can be use anywhere in that file).

I we want use that two value into other code (.prg) files, we need repeat above two lines (consider a quite large list) for all that code (.prg) files. And of course when a modification required, we need edit all code files.

In this case we build a .ch file that contains that definitions and add an #include directive to code files that need this definitions.

That’s all.

.ch file extension is a general tradition and doesn’t implies any specific action to compiler.

Pre-processor Terms

Abbreviation :

A source token whose leftmost characters exactly match the leftmost characters of a keyword in a translation directive. Abbreviations must be at least four characters in length.

Blockify :

To change an expression in the source text into a code block definition. Blockifying is accomplished by surrounding the source text with braces and placing an empty block parameter list (a pair of vertical bars) just inside the braces. When the resulting code block is evaluated at runtime, the original expression will be evaluated.

Blockify Result Marker :

A result marker of the form <{id}>. id must correspond to the name of a match marker. A blockify result marker specifies that the corresponding source text is to be blockified. If the matched source text is a list of expressions, each expression in the list is individually blockified. If no source text matched the corresponding match marker, an empty result is produced.

Conditional Compilation :

Selective exclusion by the preprocessor of certain source code. The affected source code is bracketed by the #ifdef and #endif directives. It is excluded if the argument in the #ifdef directive is not a #defined identifier.

Define :

To #define an identifier to the preprocessor and optionally specify text to be substituted for occurrences of the identifier.

Directive :

An instruction to the preprocessor. Preprocessor directives must appear on a separate line, and must begin with a hash mark (#). Their scope or effect extends from the point where they are encountered to the end of the source file in which they appear.

Dumb Stringify Result Marker :

A result marker of the form #<{id}>. id must correspond to the name of a match marker. A dumb stringify result marker specifies that the corresponding source text is to be enclosed in quotes. If the matched source text constitutes a list of expressions, each expression in the list is individually stringified. If no source text was matched, an empty pair of quotes is produced.

Empty Result :

An absence of result text; the effect of certain result markers when the corresponding match marker did not match any source text (but when the translation directive as a whole was matched). An empty result simply implies that no result text is written to output.

Header File :

A source file containing manifest constant definitions; command or pseudofunctions; and/or program statements merged into another source file using the #include preprocessor directive.

Identifier :

A name that identifies a function, procedure, variable, constant or other named entity in a source program. In Clipper language, identifiers must begin with an alphabetic character and may contain alphabetic characters, numeric characters, and the underscore character.

Include File :

A source file included another source file via #include directive. Though it is a header file by convention, pratically may be any source file.

See : Header File, source file

List Match Marker :

A match marker indicating a position that will successfully match a list of one or more arbitrarily complex expressions. A list match marker marks a part of a command that is expected to consist of a list of programmer-supplied expressions. A list match marker has the form <id,…>. id associates a name with the match marker. The name can be used in a result marker to specify how the matching source text is to be handled.

Logify :

To change an expression in the source text into a logical value. Logifying is accomplished by surrounding the expression with periods.

Logify Result Marker :

A result marker of the form #<.id.>. id must correspond to the name of a match marker. This result marker writes true (.T.) to the result text if any input text is matched; otherwise, it writes false (.F.) to the result text. The input text itself is not written to the result text.

Manifest Constant :

An identifier specified in a #define directive. The preprocessor substitutes the specified result text whenever it encounters the identifier in the source text.

Match :

A successful comparison of source text with a match pattern (or part of a match pattern).

Match Marker :

A construct used in a match pattern to indicate a position that will successfully match a particular type of source text. There are several types of match markers, each of which will successfully match a particular type of source text.

Match Pattern :

The part of a translation directive that specifies the format of source text to be affected by the directive. A match pattern generally consists of words and match markers.

Normal Stringify Result Marker :

A result marker of the form <“id”>. id must correspond to the name of a match marker. A normal stringify result marker specifies that the corresponding source text is to be enclosed in quotes. If the matched source text is a list, each element of the list is individually stringified. If no source text was matched, an empty result is produced.

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.

Preprocessor :

A translation program that prepares source code for compilation by applying selective text replacements. The replacements to be made are specified by directives in the source file. In Clipper language, the preprocessor operates transparently as a part of the compiler program.

See Also : Compiler

Pseudofunction :

A function-like construct that is replaced with another expression via the #define directive, rather than compiled into a conventional function call. Pseudofunctions may contain parenthesized arguments that may be included in the substituted text.

Regular Match Marker :

A match marker indicating a position that will successfully match an arbitrarily complex expression in the source text. A regular match marker generally marks a part of a command that is expected to consist of arbitrary programmer-supplied text, as opposed to a keyword or other restrictive component. In order for the source text to match, it must constitute a properly formed expression. A regular match marker has the form <id>. id associates a name with the match marker. The name can be used in a result marker to specify how the matching source text is to be handled.

Regular Result Marker :

A result marker of the form <id>. id must correspond to the name of a match marker. This result marker writes the matched input text to the result text, or nothing if no input text is matched.

Repeating Clause :

A portion of a result pattern surrounded by square ([ ]) brackets. The text specified by the repeating clause is written to output once for each successfully matched match marker in the corresponding match pattern.

Restricted Match Marker :

A match marker indicating a position that will successfully match one or more specified keywords. A restricted match marker marks a part of a command that is expected to be a keyword. A restricted match marker has the form <id: wordList> where wordList is a list of one or more keywords. Source text is successfully matched only if it matches one of the keywords (or is an acceptable abbreviation). id associates a name with the match marker. The name can be used in a result marker to specify how the matching source text is to be handled.

Result Text :

The text that results from formatting matched source text using a result pattern. If the result text matches a match pattern in another preprocessor directive, then it becomes the source text for that directive. Otherwise, the result text is passed as input to the compiler.

Result Pattern :

The part of a translation directive that specifies the text to be substituted for source text that matches the match pattern. A result pattern generally consists of operators and result markers.

Smart Stringify Result Marker :

A result marker of the form <(id)>. id must correspond to the name of a match marker. A smart stringify result marker specifies that the corresponding source text is to be enclosed in quotes unless the source text was enclosed in parentheses. If the matched source text is a list, each element of the list is individually processed. If no source text was matched, an empty result is produced. The smart stringify result marker is used to implement commands that allow extended expressions (a part of a command that may be either an unquoted literal or a character expression).

Source Text :

Text from a source file, processed by the preprocessor. Source text is examined to see if it matches a previously specified match pattern. If so, the corresponding result pattern is substituted for the matching source text

STD.CH :

The standard header file containing definitions for all Clipper language commands.

Stringify :

To change source text into a literal character string by surrounding the text with quotes.

Text Replacement :

The process of removing portions of input text and substituting different text in its place.

Token :

An elemental sequence of characters having a collective meaning. The preprocessor groups characters into tokens as it reads the input text stream. Tokens include identifiers, keywords, constants, and operators. White space, and certain special characters, serve to mark the end of a token to the preprocessor.

Translation Directive :

A preprocessor instruction containing a translation rule. The two translation directives are #command and #translate.

Translation Rule :

The portion of a translation directive containing a match pattern followed by the special symbol (=>) followed by a result pattern.

Undefine :

To remove an identifier from the preprocessor’s list of defined identifiers via the #undefine directive.

Wild Match Marker :

A match marker indicating a position that will successfully match any source text. A wild match marker matches all source text from the current position to the end of the source line. A wild match marker has the form <*id*>. id associates a name with the match marker. The name can be used in a result marker to specify how the matching source text is to be handled.

#error and #stdout

What are #error and #stdout directives ?

#error : Generate a compiler error and display a message

Syntax :

#error [<messageText>]

Arguments :

<messageText> is the text of the message to be displayed. <messageText> is a literal character string–do not enclose the message in quotations unless you want them to appear as part of the display.

Description :

#error causes the compiler to generate error number C2074. If the <messageText> parameter is specified, an error message is displayed.

Examples :

. This example displays an error message based on whether or not a NETWORK identifier was defined:

 #ifdef NETWORK
 #error Network version not implemented.
 #endif

~~~~~~~~~~~~~~~~~~~~~~~

#stdout : Send literal text to the standard output device

Syntax :

#stdout [<messageText>]

Arguments :

<messageText> is the text of the message to display. <messageTest> is a literal character string. Do not enclose the message in quotation marks unless you want them to appear as part of the display.

Description :

#stdout causes the compiler to output the literal text to the standard output device (stdout) during compilation. If <messageText> is not specified, a carriage return/line feed pair echoes to stdout.

Warning! Manifest constants are not translated in #stdout. Implementation is identical to #error with the following exceptions: output is written to STDOUT and no compiler error is generated.

Examples :

This example demonstrates use of #stdout:

 #ifdef DEBUG
     #stdout Compiling debugging version...
 #endif
PROCEDURE Main()
 ? "Hello world"
RETURN
#stdout End of "Hello World" program

			

#define and #undef

What are #define and #undef directives ?

#define : Define a manifest constant or pseudofunction.

Syntax :

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

Arguments :

<idConstant> is the name of an identifier to define.

<resultText> is the optional replacement text to substitute whenever a valid <idConstant> is encountered.

<idFunction> is a pseudofunction definition with an optional argument list (<arg list>). If you include <arg list>, it is delimited by parentheses (()) immediately following <idFunction>. <exp> is the replacement expression to substitute when the pseudofunction is encountered. Enclose this expression in parentheses to guarantee precedence of evaluation when the pseudofunction is expanded.

Note: #define identifiers are case-sensitive, where #command and #translate identifiers are not.

Description :

The #define directive defines an identifier and, optionally, associates a text replacement string. If specified, replacement text operates much like the search and replace operation of a text editor. As each source line from a program file is processed by the preprocessor, the line is scanned for identifiers. If a currently defined identifier is encountered, the replacement text is substituted in its place.

Identifiers specified with #define follow most of the identifier naming rules. Defined identifiers can contain any combination of alphabetic and numeric characters, including underscores. Defined identifiers, however, differ from other identifiers by being case- sensitive. As a convention, defined identifiers are specified in uppercase to distinguish them from other identifiers used within a program. Additionally, identifiers are specified with a one or two letter prefix to group similar identifiers together and guarantee uniqueness. Refer to one of the supplied header files.

When specified, each definition must occur on a line by itself. Unlike statements, more than one directive cannot be specified on the same source line. You may continue a definition on a subsequent line by employing a semicolon (;). Each #define directive is specified followed by one or more white space characters (spaces or tabs), a unique identifier, and optional replacement text. Definitions can be nested, allowing one identifier to define another.

A defined identifier has lexical scope like a filewide static variable. It is only valid in the program (.prg) file in which it is defined unless defined in Std.ch or the header file specified on the compiler command line with the /U option. Unlike a filewide static variable, a defined identifier is visible from the point where it is defined in the program file until it is either undefined, redefined, or the end of the program file is reached.

You can redefine or undefine existing identifiers. To redefine an identifier, specify a new #define directive with the identifier and the new replacement text as its arguments. The current definition is then overwritten with the new definition, and a compiler warning is issued in case the redefinition is inadvertent. To undefine an identifier, specify an #undef directive with the identifier as its argument.

#define directives have three basic purposes:

. To define a control identifier for #ifdef and #ifndef

. To define a manifest constant : an identifier defined to represent a constant value

. To define a compiler pseudofunction

The following discussion expands these three purposes of the #define directive in your program.

Preprocessor Identifiers :

The most basic #define directive defines an identifier with no replacement text. You can use this type of identifier when you need to test for the existence of an identifier with either the #ifdef or #ifndef directives. This is useful to either exclude or include code for conditional compilation. This type of identifier can also be defined using the /D compiler option from the compiler command line. See the examples below.

Manifest Constants :

The second form of the #define directive assigns a name to a constant value. This form of identifier is referred to as a manifest constant. For example, you can define a manifest constant for the INKEY() code associated with a key press:

#define K_ESC 27
IF LASTKEY() = K_ESC
 .
 . <statements>
 .
ENDIF

Whenever the preprocessor encounters a manifest constant while scanning a source line, it replaces it with the specified replacement text.

Although you can accomplish this by defining a variable, there are several advantages to using a manifest constant: the compiler generates faster and more compact code for constants than for variables; and variables have memory overhead where manifest constants have no runtime overhead, thus saving memory and increasing execution speed. Furthermore, using a variable to represent a constant value is conceptually inconsistent. A variable by nature changes and a constant does not.

Use a manifest constant instead of a constant for several reasons. First, it increases readability. In the example above, the manifest constant indicates more clearly the key being represented than does the INKEY() code itself. Second, manifest constants localize the definition of constant values, thereby making changes easier to make, and increasing reliability. Third, and a side effect of the second reason, is that manifest constants isolate implementation or environment specifics when they are represented by constant values.

To further isolate the effects of change, manifest constants and other identifiers can be grouped together into header files allowing you to share identifiers between program (.prg) files, applications, and groups of programmers. Using this methodology, definitions can be standardized for use throughout a development organization. Merge header files into the current program file by using the #include directive.

For examples of header files, refer to the supplied header files.

Compiler Pseudo-functions :

In addition to defining constants as values, the #define directive can also define pseudofunctions that are resolved at compile time. A pseudofunction definition is an identifier immediately followed by an argument list, delimited by parentheses, and the replacement expression.

For example:

#define AREA(nLength, nWidth) (nLength * nWidth)
#define SETVAR(x, y) (x := y)
#define MAX(x, y) (IF(x > y, x, y))

Pseudofunctions differ from manifest constants by supporting arguments. Whenever the preprocessor scans a source line and encounters a function call that matches the pseudofunction definition, it substitutes the function call with the replacement expression. The arguments of the function call are transported into the replacement expression by the names specified in the argument list of the identifier definition. When the replacement expression is substituted for the pseudofunction, names in the replacement expression are replaced with argument text. For example, the following invocations,

? AREA(10, 12)
SETVAR(nValue, 10)
? MAX(10, 9)

are replaced by :

? (10 * 12)
nValue := 10
? (IF(10 > 9, 10, 9)

It is important when defining pseudofunctions, that you enclose the result expression in parentheses to enforce the proper order of evaluation. This is particularly important for numeric expressions. In pseudofunctions, you must specify all arguments. If the arguments are not specified, the function call is not expanded as a pseudofunction and exits the preprocessor to the compiler as encountered.

Pseudofunctions do not entail the overhead of a function call and are, therefore, generally faster. They also use less memory. Pseudofunctions, however, are more difficult to debug within the debugger, have a scope different from declared functions and procedures, do not allow skipped arguments, and are case-sensitive.

You can avoid some of these deficiencies by defining a pseudofunction using the #translate directive. #translate pseudofunctions are not case- sensitive, allow optional arguments, and obey the dBASE four-letter rule. See the #translate directive reference in this chapter for more information.

Examples :

. In this example a manifest constant conditionally controls the compilation of debugging code:

 #define DEBUG
 .
 . <statements>
 .
 #ifdef DEBUG
     Assert(FILE("System.dbf"))
 #endif

. This example defines a manifest constant and substitutes it for an INKEY() value:

 #define K_ESC 27
 .
 . <statements>
 .
 IF INKEY() != K_ESC
    DoIt()
 ELSE
    StopIt()
 ENDIF

. This example defines pseudofunctions for the standard functions, MAX() and ALLTRIM():

 #define MAX(arg1, arg2) (IF(arg1 > arg2, arg1, arg2))
 #define ALLTRIM(cString) (RTRIM(LTRIM(cString)))
 .
 . <statements>
 .
 ? MAX(1, 2)
 ? ALLTRIM(" Hello ")
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#undef : Remove a #define macro definition

Syntax :

#undef <identifier>

Arguments :

<identifier> is the name of the manifest constant or pseudofunction to remove.

Description :

#undef removes an identifier defined with the #define directive. After an #undef, the specified identifier becomes undefined. Use #undef to remove an identifier before you redefine it with #define, preventing the compiler warning that occurs when an existing identifier is redefined. Also, use #undef to make conditional compilation specific to certain sections of a program.

Examples :

. To define and then undefine a manifest constant and a pseudofunction:

 #define K_ESC 27
 #define MAX(x, y) IF(x > y, x, y)
 .
 . <statements>
 .
 #undef K_ESC
 #undef MAX

. To use #undef to undefine an identifier before redefining it:

 #define DEBUG
 .
 . <statements>
 .
 #undef DEBUG
 #define DEBUG .T.

. To undefine an identifier if it exists, and otherwise define it for later portions of the program file:

 #ifdef TEST
    #undef TEST
 #else
    #define TEST
 #endif

			

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.