Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!uwm.edu!zaphod.mps.ohio-state.edu!samsung!cs.utexas.edu!rice!uw-beaver!fluke!ssc-vax!dano From: dano@ssc-vax.UUCP (Dan Olson) Newsgroups: comp.lang.c Subject: Macros that wrap Message-ID: <3015@ssc-vax.UUCP> Date: 30 Nov 89 20:03:17 GMT Organization: Boeing Aerospace & Electronics, Seattle WA Lines: 94 [ 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 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)