************* BACK AND FORTH PAGING SUBROUTINE ************

PAGEFLOP

If they want to quit, do so
 If They want to quit subsession, Do SO!
  Decrement LOCAL and GLOBAL Page Counters

FORWARD

  Increment LOCAL and GLOBAL Page Counters
   *************** END PAGEFLOP *********************
  ****** CHAPTER INTERNAL SELECTOR ALGORITHM ******

SELECTOR

   Reset Local Page Counter

SELAGAIN

 CHECK IF ONLY A <CR>

WRONGSEL

YOUR SELECTION IS NOT IN THE 0 - #SELIMIT  RANGE  Please try again

AANVANG

Copyright CourseWare Technologies Inc., 1985-88


Lesson - 5


 THE C MACRO PREPROCESSOR 

P1

The Macro Preprocessor|Topics to Learn|5-0|11,56
  #                     Topic
 ---                   -------
  1   -   Macro Definitions
  2   -   How to Include Files into Your Program
  3   -   Defining and Undefining Constants
  4   -   First Review
  5   -   Conditional Compilation Commands
  6   -   More Conditional Compilation Commands
  7   -   Debugging Feature of the Macro Preprocessor
  8   -   Second Review
  0   -   Return to the Main Menu

P2

The Macro Preprocessor|Macro Definitions|5-1.1|11,54
     The C macro preprocessor is a language extension 
that provides:

           *  constant definition capability
           *  macro definitions
           *  file inclusion capability
           *  conditional compilation


     Macro preprocessor commands begin with a  #  in 
the first column and require no  ;  at the end of line.

P3

The Macro Preprocessor|Macro Definitions|5-1.2|14,60
The following example demonstrates the use of the C macro 
preprocessor for initializing integer and character string
constants.  A good way to verify the value of the constants 
is to print them using the appropriate format specifier and 
use the constant name as an argument.


/* constant definitions */

          #define BELL    7
          #define YES     1
          #define TRUE    1
          #define FALSE   0
          #define FAIL    (-1)
          #define ERR_MESSAGE  "no match found\n"

P4

The Macro Preprocessor|Macro Definitions|5-1.3|2,50
     Macros provide excellent readability without 
the time penalty involved in executing a function.

P5

The Macro Preprocessor|Macro Definitions|5-1.4|16,60
/* Macro substitution */

      #define square(x)     ((x) * (x))
      #define min(a,b)      ((a) < (b) ? (a) : (b))
      #define ASSERT(expr)  if (!(expr)) \
              printf("ERROR\n");


     A line of the form ASSERT(a > b); will be replaced 
with:

if (!(a > b)) printf("ERROR\n");


     Similarly, x = min (a+b, c-d); will be replaced with:

x = ((a+b) < (c-d) ? (a+b) : (c-d));

P6

The Macro Preprocessor|Including Files in Programs|5-2.1|12,54
     A command such as #include filename will be
replaced with the contents of filename.


     The most often included file is the standard 
I/O file stdio.h which contains definitions for the 
standard input and output, functions, macros, and
constants.  This file is located in /usr/include 
(the default UNIX include directory) and may be 
included with the line:

#include  <stdio.h>

P7

The Macro Preprocessor|Including Files in Programs|5-2.2|10,52
     If the file to be included does not reside in 
the default include directory, the file name should be 
enclosed in double quotes.  For example:

#include "/usr/george/include/common.h"


     If a macro preprocessor command is to be 
continued on the next line, a backslash (\) must be 
placed at the end of the line to be continued.

P8

The Macro Preprocessor|Defining and Undefining Constants|5-3.1|7,50
     A constant may be defined through a compilation 
command string like:

-DCLEAR=12

where -D is the define option, CLEAR is the constant's
name, and 12 is the constant's initial value.

P9

The Macro Preprocessor|Defining and Undefining Constants|5-3.2|12,50
     Another way to define a constant is with the 
macro preprocessor command:

#define  name  value

For example:

#define   CLEAR   12


     NOTE:  If the constant's value is not specified, 
it is set to 1 by default. 

P10

The Macro Preprocessor|Defining and Undefining Constants|5-3.3|14,56
     Conversely, one may undefine a constant.  This is  
done by using the -U flag.  For example:

-UCLEAR

will remove the initial definition of the constant CLEAR.


     Inside your program you may undefine a constant with
the macro preprocessor command #undef.  For example:

#undef   CLEAR

will remove the definition of CLEAR from that point on.

P11

The Macro Preprocessor|Conditional Compilation Commands|5-5.1|15,51
     Since C was designed to be a portable language, it 
provides the capability to alter the program compilation 
depending on the environment, function libraries, and 
various other conditions represented by compilation 
keywords:

                         #if
                         #ifdef
                         #ifndef
                         #endif


     Like other macro preprocessor commands,the
conditional compilation commands are preceeded by a 
sharp (or pound) sign: #.

P12

The Macro Preprocessor|Conditional Compilation Commands|5-5.2|17,60
Syntax:

                 #if   constant_expression
                     statement
                 [#else  /* optional part  */
                     statement ]
                 #endif


     If the constant expression evaluates to non-zero, the 
lines following the #if condition up to any existing #else
or #endif are compiled.  If the constant expression 
evaluates to 0, the lines following any existing #else
are compiled.


     Conditional compilation constructs may be nested.

P13

The Macro Preprocessor|Conditional Compilation Commands|5-5.3|12,60
The next example shows the conditional compilation constructs 
if, else and endif.  The code examines the constant REGNUM,
the number of registers.  If it finds that REGNUM is smaller 
than 32, then the variable maxvalis set to 16 and the variable
stacksizeis set to 256.  On the other hand, if REGNUM is 
greater than 32, then maxval is set to 32 and stacksize to 1024.

NOTE:  With conditional compilation constructs, no braces 
are used for compound statements; therefore, one has to be 
more careful with nested constructs.  Nevertheless, the 
construct #endif makes the code more structured.

P14

The Macro Preprocessor|Conditional Compilation Commands|5-5.4|11,35
/*  Conditional compilation  */

      #if   regnum < 32
          maxval = 16;
          stacksize = 256;
       
      #else
           maxval = 32;
           stacksize = 1024;
      
      #endif

P15

The Macro Preprocessor|Conditional Compilation Commands|5-5.5|15,49
     Syntax:

              #ifdef/ifndef  name
                   statement
              [#else]            /* optional */
                   statement
              #endif


     These constructs have the same logic as the
#if - #else - #endif constructs, however, they check 
whether the constant is defined or not defined.


     NOTE:  The constant value of 0 implies defined.

P16

The Macro Preprocessor|More Conditional Commands|5-6.1| 10 , 63
The following example demonstrates another set of conditional 
compilation constructs: #ifdef, #ifndef, #else and #endif.
Tests are performed to determine whether a certain construct 
is defined or undefined.  Note that we have nested conditional 
compilation constructs.  In nested situations, the #else will 
always refer to the preceding if(def/ndef).

P17

The Macro Preprocessor|More Conditional Compilation Commands|5-6.2|16,54
/* #ifdef/ifndef - #endif conditional compilation */

            #ifdef VAX
                 wordsize = 32;
            #else
                 wordsize = 16;
            
            #ifndef MC68000
                 clib = "/usr/lib/common";
            
            #else                /* for #ifndef */
                 clib = "/usr/lib/mc68";
            
            #endif               /* for #ifndef */
            #endif                /* for #ifdef */

P18

The Macro Preprocessor|Debugging Feature|5-7.1|13,59
     C has a debugging feature called line, which 
operates during error detection to force the compiler 
to believe that the line number of the following source 
line is set to value.  For example, if value is 20 and
it actually occurs on line 1020, then all errors occurring 
on the actual source lines > 1020 will be referred with 
the line number of 1000 less than the actual line number.
This is particularly useful in a file with many lines.


Syntax:

#line    value