home *** CD-ROM | disk | FTP | other *** search
- -*- Mode:Text -*-
-
- Summary of CPP Macro Support
-
- This is a summary of the defmacro language extension, its syntax and
- capabilities, and examples of usage. I have composed this in an attempt to
- provide a gentler introduction than that available in the man page. Note that
- the following implementation details are *NOT* standard C++, but rather
- extensions that we have added via an enhanced, portable preprocessor. This
- preprocessor has been brought up on Sun OS, SCO XENIX, OS/2, and MVS.
-
- There are lots of pieces to the macro facilities. Some were patterned after
- LISP features such as LOOP and REST: arguments, while others such as the
- parameterized types support are implementations of design papers published by
- Stroustrup. Together, they provide significant language features and enhanced
- power for the programmer. However, it is important to note that once any
- given macro is expanded, the resulting code is plain-old vanilla C++ syntax
- acceptable to any C++ translator or compiler.
-
- The basic cpp extension mechanism utilized to implement all macro
- functionality is provided by a #pragma statement. Common macros are defined
- in this manner. The "defmacro" keyword follows and provides a way to execute
- arbitrary filter programs (macros expanders) on code fragments. The syntax
- for defmacro is:
-
- #pragma defmacro name <file> options
- or #pragma defmacro name "file" options
- or #pragma defmacro name program options
-
- where "name" is the name of the filter, <file> and "file" are the name of a
- source file containing a macro definition, "program" is the name of a program
- implementing a macro, and options is a series of of optional modifiers for the
- defmacro explained below. The implementation of a defmacro may be either
- external to the preprocessor (as in the case of files and programs) or
- internal to the preprocessor. For example, the template macro implementing
- parameterized types is internal to the preprocessor to provide a more
- efficient, performance tuned implementation. Cpp will first search for a file
- or program in the same search path as that used for include files. If a match
- is not found, it then searches an internal preprocessor table. If a match is
- still not found, cpp prints "Error: Cannot open macro file [xxx]", where "xxx"
- is the name as it appears in the source code.
-
- The defmacro syntax also supports a series of options. Zero or more of the
- following options may be included in any order:
-
- recursive - when present, the macro may be recursively expanded.
-
- expanding - when present, input to the macro is expanded.
-
- delimiter=x - the default delimiter (semicolon) is replaced with 'x'.
-
- other - unknown options are passed as arguments to the macro
- expander.
-
- When a defmacro style macro is encountered by the preprocessor, the name and
- everything until the terminating character -- including all matching and
- nested levels of {} [] () <> "" '' and comments found along the way -- is
- piped into the macro procedure's standard-input. The procedure's standard
- output is scanned by CPP for further processing. The resulting expansion
- replaces the macro input in the source.
-
-
- The defmacro implementation is used to declare the MACRO (all uppercase)
- keyword. This is essentially an enhanced #define syntax that supports
- multiline, arbitrary length, nested macros and cpp-directives, with optional,
- keyword, and body parameters. To use it include the line:
-
- #pragma defmacro MACRO "macro" delimiter=}
-
- thus declaring the MACRO keyword whose implementation is a cpp internal
- routine named "macro". The terminating delimiter for a MACRO is the closing
- brace character. The syntax for MACRO is:
-
- MACRO name (arglist) { body }
-
- where "name" is the name of the macro, "arglist" is a list of argument
- specifiers separated by commas, and "body" is what is substituted on a call to
- the macro. The "arglist" may specify positional, optional, optional keyword,
- required keyword, rest and body arguments. When KEY: is specified, the macro
- takes all following arguments to be keyword arguments that allow the user to
- specify a particular value. Default values are support by use of an equal
- sign and value and may be applied to both regular and keyword arguments. The
- REST: modifier indicates that there is some number of arguments, all of which
- are referenced by use of the one named identifier. An optional equal sign and
- identifier will contain the number of arguments remaining. Finally, BODY:
- indicates that when used, the parameter will be expanded to include all the
- text within the braces after the macro call. This is useful for identifying a
- section of code that implements some part of the macro or should be passed to
- other nested macros. The following examples show some of the power and
- flexibility of the COOL MACRO capability:
-
- MACRO set_val (size, value=NULL, KEY: low = 0, high) {
- init (size, value, low, high-low)
- }
-
- In this example, "set_val" is the name of the macro that the programmer refers
- to, "size" is a required positional argument, "val" is an optional positional
- argument that if not specified in a particular call has a default value of
- NULL, "low" is an on optional keyword parameter, and "high" is a required
- keyword parameter. In this example, the macro simple calls the function
- init() with four arguments. The following show several legal invocations of
- the macro along with the resulting call to the function init():
-
- set_val (0, high=20) ----> init (0, NULL, 0, 20);
- set_val (0, low=5, high=15) ----> init (0, NULL, 5, 10);
- set_val (1, 2, high=25) ----> init (1, 2, 0, 25);
-
- See the files "macro-sample.c" and "macro-sample.i" for an example usage of
- this capability and the corresponding expansion.
-
-
- One of the main uses of the defmacro facility is the implementation of
- templates to support parameterized types. The syntax of the template grammar
- is that as specified by Stroustrup in his paper "Parameterized types for C++"
- in the 1988 USENIX C++ Conference Proceedings. Cpp implements this
- functionality such that there will be minimal source code conversion necessary
- when this feature is finally implemented in the C++ language.
-
- A class programmer who wishes to implement a vector class object wants to make
- design and implementation decisions in such a way as to facilitate a simple
- and consistent interface for the application programmer, no matter what type
- of thing is to be stored in the vector. In addition, replication of code for
- each specific type should be avoided if at all possible. To accomplish this,
- the class programmer implements a vector template, with the type selection
- left to the application programmer. The following example is for a Vector
- header file:
-
- template<class Type> class Vector { // Parameterized Vector class
- private:
- Type* v; // Data of type pointer to Type
- int size; // Size of vector object
- public:
- Vector (); // Empty constructor
- Vector (int); // Constructor with size
- Vector (Vector&); // Constructor with reference
- ~Vector (); // Destructor
- Type& operator[](int n); // Operator[] overload for Type
- Type& element (int n); // Return element of type Type
- ... // ... other methods ...
- };
-
- An application programmer would include this header file in the appropriate
- source file. In addition, common header file must be included to provide the
- #pragma statement declaring the defmacro template shown below. This must
- occur before the inclusion of the Vector header file and so is done within
- Vector.h if it has not already been included.
-
- #pragma defmacro template "template" delimiter=}
-
- An application programmer also places the following lines in his/her source
- code to use the parameterized Vector class for a specific type:
-
- DECLARE Vector<double>;
- IMPLEMENT Vector<double>;
- Vector<double> vs(30);
-
- The DECLARE macro implements a series of #define preprocessor statements that
- will declare and define code for a Vector of doubles. Together with the
- template macro expander. A class definition with its associated methods is
- created ready to be compiled, all performed invisibly to the user.
-
- The common header file must include the #pragma statements that allow DECLARE
- and IMPLEMENT to work also. They are as follows:
-
- #pragma defmacro MACRO "macro" delimiter=} recursive
- #pragma defmacro DECLARE "declare" delimiter=> recursive lines
- #pragma defmacro IMPLEMENT "implement" delimiter=> recursive lines
-
- See the files "template-sample.c" and "template-sample.i" for an example usage
- of this capability and the corresponding expansion.
-
- There are several other internal macros included with cpp that we have
- experimented with. These can safely be ignored. For the interested parties
- who want to delve more we refer you to the comments in the source files.
-