You are on page 1of 4

Conditional Macro Expansion

• Most macro processors can modify the


sequence of statements generated for a
macro expension, depending on the
arguments supplied in the macro invocation
Systems Programming – great power and flexibility
• Implementation is easy : macro processor
Chapter 4 maintains a symbol table that contains the
current values of all macro variables
Macro Processors processed. This table is used to look up the
current value of a macro variable whenever
it is required.
1 4

Macro (Instruction) ANSI C Macro Language


• a macro represents a commonly used group of • Definitions and invocations of macros
statements in the source programming
are handled by a preprocessor
language
– simply a notational convenience for the programmer – not integrated with the rest of the
• expanding the macros: the macro processor compiler
replaces each macro instruction with the
corresponding group of source language
statements Preprocessor Compiler
– Ex: On SIC/XE, it is necessary to save the contents
of all registers before calling a subprogram and
restore them on return: source object
• corresponding instructions can be made two macros: code code
LOADREGS and SAVEREGS.
2 5

#include preprocessor directive


• The functions of a macro processor • causes a copy of a specified file to be
essentially involve the substitution of one included in place of the directive
group of characters of lines for another.
• Two versions:
– Except in a few specialized cases, the macro
performs no analysis of the text it handles – #include “filename”
• looks at the form, not the meaning of statements preprocessor searches in the same directory as
• Most common use of macro processor is in the file being compiled for the file to be
assembler language programming, but included
macro processors can be used with high- – #include <filename>
level programming languages, O/S command used for standard library header files, the
languages, etc. search normally performed through pre-
designated directories
Macro processors usually work in one pass and not
directly related to the machine architecture. 3 6

1
Uses of Conditonal
#define preprocessor directive
Compilation
• creates symbolic constants and • To make sure that a macro is defined at
least and at most once.
macros
#ifndef NULL or #if !defined(NULL)
#define PI 3.14159 #define NULL 0
#endif
identifier replacement-text
• to control the inclusion of debugging
statements
replaces all subsequent occurrences of the
#define DEBUG 1
symbolic constant PI with the numeric #if DEBUG == 1 or #ifdef DEBUG
constant 3.14159. code prevented from compiling
#endif

7 10

#define preprocessor directive #error and #pragma


• A macro is an operation defined in a #define #error tokens
preprocessor directive • prints an implementation dependent
– without arguments – processed like a symbolic message including tokens specified in the
constant directive
– with arguments – arguments are substituted in the #error 1 – out of range error
replacement text, then the macro is expanded

#define ABSDIFF(X,Y) ( (X) > (Y) ? (X) – (Y) : (Y) – (X) ) #pragma tokens
• causes an implementation defined action
ABSDIFF(I+1, J-5) • A pragma not recognized by an
implementation is ignored
Common programming error: Forgetting to enclose macro
arguments in parentheses in the replacement text. – Borland c++ recognizes several pragmas that
enable the programmer to take full advantage
8 of the Borland’s compiler 11

Predefined Symbolic
Conditional Compilation
Constants
• enables the programmer to control • __LINE__ line number of current source code line
the execution of preprocessor • __FILE__ presumed name of source file
directives and the compilation of • __DATE__ compilation date as Mmm dd yyyy
program code
• __TIME__ compilation time as hh:mm:ss
– Each of the conditional preprocessor
directives evaluates a constant integer • __STDC__ int constant 1, to indicate that
expression implementation is ANSI compliant

9 12

2
Assertions Recursive Macro Expansion
• assert macro is defined in assert.h • Invocation of one macro by another
– tests the value of an expression
– if value of expr is 0, becomes false
• prints an error message and calls abort • It is not difficult if the macro
function of stdlib.h to terminate program processor is being written in a
execution programming language that allows
assert (R != 0); recursive calls
x = y / R; – macro processor recursively processes
• if symbolic constant NDEBUF is defined the macros until all are resolved.
subsequent asserts will be ignored. Try:
– Use #define NDEBUG when assert is no longer DISPLAY(ABSDIFF(3,8))
needed
13 16

General-Purpose Macro
# and ##
Processors
• # stringizing operator • not dependent on any particular
– argument substitution is performed in the usual programming language, but can be
way, but the resulting string is enclosed in used with a variety of different
quotes
#define DISPLAY(EXPR) printf(#EXPR ”= %d\n”,EXPR) languages
vs. – Advantages:
#define DISPLAY(EXPR) printf(#EXPR ”= %d\n”,EXPR) • programmer does not need to learn about a
TRY: DISPLAY(I*J+1) different macro facility for each compiler or
assembler language
• costs involved in producing a different macro
• ## concats two tokens processor for each language is not needed
#define TOKENCONCAT( x, y) x##y
TRY: TOKENCONCAT(O, K) 14 17

MACRO PROCESSOR General-Purpose macro


DESIGN OPTIONS processors are not common
• Recursive macro extension • large number of details that must be
• General-purpose macro processors dealt with in a real programming
• Macro processing within language language
• a special-purpose macro processor can have
translators these details built into its logic and
– Line-by-line macro processor structure
– Integrated macro processor • a general-purpose facility on the other hand,
must provide some way for a user to define
the specific set of rules to be followed.

15 18

3
• Implementation problems related to the • Integrated macro processor: instead
differences among langauges of passing information macro-
– There are several situations in which normal processor and translator, they are
macro parameter substitution should not occur
• e.g., different comment styles: /* */ or // combined as one unit.
– Grouping statements in languages highly differ – can potentially make use of any
• e.g., { }, begin end information about the source program
– Tokens and rules for forming tokens differ that is extracted by the language
• e.g., = and := translator
– syntax used for macro definitions and macro • special rules of the language are handled by
invocation statements should be similar to the translator
language to make it more readable and – ex: If macro involved substituting for the variable
writeable. name I in the FORTRAN statement DO 100 I = 1

19 22

Macro Processing within Disadvantages of integrated and


Language Translators line-by-line macro processors
• The macro processors that we have
discussed so far are preprocessors. • must be specially designed and
written to work with a particular
• A line-by-line macro processor: combines implementation of an assembler or
macro processing functions with the compiler
language translator itself. • the costs of macro processor
– macro processor reads the source program development must be added to the
statements and performs all of its functions as cost of the language translator
previously described
– However, the output lines are passed to the • the assembler or compiler will be
language translator as they are generated considerably larger and more complex
20 23

• Advantages:
+ avoids making an extra pass over the
source program
+ more efficient – some of the data structures
can be combined
+ makes it easier to give diagnostic messages
related to the source statement containing
the error

21

You might also like