[comp.lang.c] Clever C Preprocessor Definitions Sought

mjones@stdc01.UUCP (Michael Jones) (08/30/89)

I am interested in collecting popular pre-processor definitions. The
"semi-extensibility" which C offers via CPP provides an example set
for those curious about common usage, missing language features, etc.

Some ideas that I have seen or which seem useful to me would include:

    1. Each of the high-precision numerical constants from the
       back of Knuth's Art of Computer Programming, in appropriate
       float/double real precision. In fact, since some compilers
       fail slightly on floating input conversion, it might be
       nice to see these numbers as "*(float *)" and "*(double *)"
       indirections to explicit binary values stored as character
       arrays of proper length, where "proper" rounding had been 
       used to construct them.

       Definitions for ANSI Terminal control sequences and ASCII
       control characters would also be useful. I use something like
       this when writing for the IBM-PC to decode "keyboard scan-
       codes":

       #define SCAN_left_shift_key	0xNN	(don't remember now)
       #define SCAN_keypad_plus		0xNN

    2. Variable and or type definitions. I have found explicit size
       definitions to be handy:

       #define ordinal_8	unsigned char
       #define integer_8	char
	 :
	 :
       #define ordinal_32	unsigned long
       #define integer_32	long

    3. Syntactic type definitions, ranging from the simple/suave to
       the "ambitious". I have seen several versions of "improved"
       selection statements, unbounded loops, sequential iterators,
       and so on. Examples of this nature include:

       a. IF/THEN/ELSE constructs:

       #define IF       if (
       #define THEN     ) {
       #define ELSE     } else {
       #define ELSEIF   } else if (
       #define ENDIF    }

       IF a == b THEN
           x = 1;
           b = 2;
       ELSE
           y = 3;
       ENDIF

       (If this example shocks you, arrange to view the S.R. Bourne "SH" 
       source code! Almost anyone would think it was in algol-60.)

       b. SELECTION constructs:

       #define when         break; case
       #define also         case
       #define otherwise    break; default

       switch (expression)
           {
	   when value-1:
	   also value-2:
	       code;
	   when value-3:
	       code;
	   otherwise:
	       code;
	   }


       c. UNBOUNDED ITERATION constructs:

       #define ever	1

       for (ever)
	   code;

       #define repeat	for (;;)

       repeat
	   code;

    4. Macro "pseudo-functions" from the simple and common min/max/abs:

       #define min(a,b)	((a) > (b) ? (b) : (a))

       to the more extreme "quick-sort generator given base data type"
       which I have seen recently.

If you have anything like this which you would like to contribute to the
"C-Preprocessor Library", I would like to hear from you! Just think, that
handy little definition could be remembered for posterity as:

    "... well son, back when *I* was a programmer, we used something
    known as Galt's Device, a really nifty CPP definition that came
    across the net. Of course, back then we had to ..."

where for Galt read *your name here*. I promise to share the full results
with everyone who submits something interesting. Or will post if there is
sufficient activity.

-- 
-- Michael T. Jones          Email:            ...!mcnc!rti!stdc01!mjones --
-- The wise man will pursue  Paper: 3101-H Aileen Drive, Raleigh NC 27606 --
-- excellence in all things  Voice: W:(919)361-3800  and  H:(919)851-7979 --

hascall@atanasoff.cs.iastate.edu (John Hascall) (09/01/89)

In article <555@stdc01.UUCP> mjones@stdc01.UUCP (Michael Jones) writes:
}I am interested in collecting popular pre-processor definitions.
 
   Probably everyone has re-invented some variation on:

      #define  ALLOC(type)  ((type *) malloc(sizeof(type)))

   As well as various constants:

      #define K_PI             3.141592653589793238462643
      #define K_E              2.718281828459045235360287

      #define K_PI_2           1.570796326794896619231322
      #define K_PI_4           0.785398163397448309615661
      #define K_PI_8           0.39269908169872415480783
      #define K_PI_180         0.0174532925199432957692369
      #define K_1_PI           0.3183098861837906715377675
      #define K_2PI            6.283185307179586476925287

      #define K_LN_2           0.693147180559945309417232
      #define K_LN_3           1.098912288668109691395245
      #define K_LN_10          2.302585092994045684017991

      #define K_180_PI        57.295779513082320876798155
      #define K_PI_180         0.017453292519943295769237
      #define K_ARC_MINUTE     0.000290888208665721596154
      #define K_ARC_SECOND     0.000004848136811095359936

   Here is one I use on VMS where system calls return odd values for OK
   and even values for various errors (but which has a couple of ideas
   which could be applied elsewhere):

      #define ODD(x)             ((x)&1)
      #define EVEN(x)            (!ODD(x))
      #define ERROR(cond)        EVEN(cond)
      #define FATAL(str, val)    exit((fprintf(stderr, "[%4d] 0x0%x <- %s\n", \
				       __LINE__, val, str), val))
      #define SYSCALL(v, func)   if (ERROR(v = func)) FATAL("func", v)

      Used like this for example:

         register int cond;
         SYSCALL(cond, SYS$ASSIGN(&device, &channel, 0, 0));

         which gives error messages like:

	     [  17] 0x0908 <- SYS$ASSIGN(&device, &channel, 0, 0)
	     No such device available

         (assuming the SYSCALL is on line 17)

scs@hstbme.mit.edu (Steve Summit) (09/03/89)

In article <1424@atanasoff.cs.iastate.edu> hascall@atanasoff.cs.iastate.edu.UUCP (John Hascall) writes:
>   Here is one I use on VMS where system calls return odd values for OK
>   and even values for various errors:
>      #define ODD(x)             ((x)&1)
>      #define EVEN(x)            (!ODD(x))
>      #define ERROR(cond)        EVEN(cond)

If you do these right (I forget the exact form I used, but at
least John's ODD macro would probably work) you can get the VAXC
compiler to generate a single BLBS or BLBC instruction, those
being two of the instructions (so the story goes) that the VAX
hardware designers put in specifically at the request of the VMS
software developers.  (I try not to worry about such machine-
level optimizations, but it's nice to know that, since the
instructions are there, they're being used as intended.)

henry@utzoo.uucp (Henry Spencer) (09/06/89)

In article <555@stdc01.UUCP> mjones@stdc01.UUCP (Michael Jones) writes:
>       (If this example shocks you, arrange to view the S.R. Bourne "SH" 
>       source code! Almost anyone would think it was in algol-60.)

Modern versions of the Bourne shell have been fixed to get rid of those
silly macros, which made the code a little bit harder to read and noticeably
harder to use automatic tools on.
-- 
V7 /bin/mail source: 554 lines.|     Henry Spencer at U of Toronto Zoology
1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu