Fuel for your flames: Things I would like in CPP
Kevin Martin
kpmartin at watmath.UUCP
Mon Oct 1 04:03:27 AEST 1984
There are several things which I would like in CPP, but before I describe
them, I would like to stifle the obvious flame:
*USING M4 IS NOT A SUITABLE SOLUTION*
1) Not every system has m4 (e.g. non-unix systems)
2) Having to manually use a pre-processor which is not well-integrated
into the language is a pain; ask anyone who uses Troff+Eqn+Tbl how
much fun it is to find the original input line which caused Troff
to issue an error message
3) m4 can't use CPP macros, nor vice versa. For instance, m4 can't use
names such as NOFILE (in <sys/types.h>), since the include file
is brought in by CPP's #include directive (which m4 doesn't understand),
and even if m4 understood #include, it wouldn't understand #define.
Now, on to things I would like to see:
1) The ability to define a token to be the result of an expression:
e.g.
#eval XXX 1+2
would define 'XXX' to have the value 3, just as if I had typed
#define XXX 3
The expression would be macro-expanded just as it is for #if
This is useful for two purposes: Any defined constants within the
expression can be re-defined without changing the new constant, e.g.
/* Define offsets */
#define X 1
#define Y 2
#define Z 3
/* Define first group */
#define BASE 10
#eval XX BASE+X
#eval YY BASE+Y
#eval ZZ BASE+Z
/* Define second group */
#define BASE 20
... /* the value of XX, when expanded, remaine unchanged */
The other use is to generate new identifiers. This requires some form
of token concatenation to work:
#eval NUM NUM+1
#define NAME tempvar/**/NUM
/* (or however token concatenation works) */
2) The ability to put newlines in a macro definition, in order that
the macro, when expanded, can perform other #directives
This should probably use a directive other than #define, since
escaping the newline for #define already has meaning. Perhaps:
#macro name(formals)
/* put macro body here */
#endm name
(The 'name' on the #endm would be optional, and default to the macro
which is currently being defined; it is there so that the invokation
of a macro can define other macros)
3) The ability to temporarily send output to another file, to be later
included by a form of the #include directive. This is similar to the
diversion facility in m4.
This facility, combined with macros (as in (2) above), allows the
generation of parallel tables, since the macro can put the entry
into the first table, switch to another diversion, and put the entry
for the second table, then switch back.
4) Given proper macros, it is now useful to have the ability to
issue error messages, perhaps including a severity (warning --
the compile can continue, error -- CPP can continue, but the compiler
should not be called up, fatal -- force CPP to give up immediately).
#message 0 "Warning: NUM < 0"
Maybe the quotes aren't needed...
The combination of the first three features allows generation of ragged
initialized arrays: Each row is given a name using #eval and token
concatanation, the row is given storage class 'static', and, by switching
to another diversion, the row pointer in the edge vector can be
initialized to point to the row.
Note that none of these changes will harm existing C programs.
And with a well-written CPP, none of these changes are terribly difficult
to implement.
Kevin Martin, UofW Software Development Group
More information about the Comp.lang.c
mailing list