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