[comp.lang.c] Macros that wrap

dano@ssc-vax.UUCP (Dan Olson) (12/01/89)

[ MACROS that Rap (Run D.M.C.) ]


One feature I really love from the lisp world is the ability to use
macros that wrap around a piece of code.  This lets the macro set up
an environment just during a given block of code.  Some examples of this
from the lisp world are:

	(with-open-file (f "some.file")
	    ;; Automatically closes the file when the block is exited.
	    )

	(without-interrupts
	    ;; Disables interrupts during a block of code.
	    )

Actually, most of lisp's control structures are not built in, but
are instead macros.

Anyhowz, this is a feature I miss in C and it's macro processor.  Does
anybody know of any work toward this feature?  I have found one way
of doing wraps using for(;;), but its often ugly and doesn't work
for all tasks.

(Example)

#include <stdio.h>

typedef char Bool;
#define TRUE 1
#define FALSE 0

#define WITH_FILE(f,n,o,e) \
	  for((f = fopen(n,o)) || (e = TRUE); f; fclose(f), f = NULL)

#define WITH_ARRAY(a,s) \
	  for(a = calloc(sizeof(*a),s); a; free(a), a = NULL)
void *calloc();

main()
{
  FILE *f;
  long *array;
  Bool error = FALSE;

  /* File is closed when the following block exits */
  WITH_FILE (f, "some.file", "r", error) {  
    /* read, read, read ... */
    }
  if (error) puts("Hey, you blew it.");

  /* Memory is free'ed when the following block exits */
  WITH_ARRAY (array, 10000) {
    puts("Got it!");
    /* Do something with all that memory */
    }

  return 0;
}


Ideally, if this feature exisited it would allow you to put any
arbitrary code before and after a given block including local
variable declarations, or operate on multiple blocks like the 
if {} else {} construct.


-- Side note --

I often "typedef char Bool" (and I think many others do too.), but
until recently I never got hit by the "1 out of 256" problem.  This
is when you begin to think of Bool as a real type and do things like:

status(ok_flag)
  Bool ok_flag;
{
  puts( ok_flag ? "Ok" : "Not Ok");
}


ptr = malloc(sizeof(*ptr));
status((Bool)ptr);		/* Not so good */

Instead of...

status((Bool)(ptr != NULL));	/* GOOD */


It's "1 out of 256", because the not so good method works only
when the lower byte of the pointer is non zero.


Dano
...!uw-beaver!ssc-vax (I think)