On Tue, 2002-07-09 at 00:12, Michael Richardson wrote: > Can some explain why the constructs: > > #define __xINIT_CIPHER_BLKOPS(name) INIT_CIPHER_BLKOPS(name) > #define __xINIT_CIPHER_OPS(name) INIT_CIPHER_OPS(name) > > ... > > #define __STR(x) # x > #define __xSTR(x) __STR(x) > > #define __CAT(x,y) x ## y > #define __xCAT(x,y) __CAT(x,y) > > Why have __xCAT(x,y) at all? Why not just call __CAT() directly? > Ditto for INIT_CIPHER_BLKOPS(). I'm glad you asked, since it's actually a quite interesting---but little known---issue :-) it has to do with cpp's behaviour, when the macro argument is used as an operand of ## or # in the macro body; usually when a macro call is encountered, it's arguments are 'prescanned' and macro-expanded if necessary; then the result is substituted in the macro body; and after that another scan on the expanded body is performed; thus scanning takes place twice; but when arguments of the macro are used as operands to ## or # they are not prescanned, but are taken literally, as they were passed to the macro; some example; the fragments above are typically used by the following macro: #define CIPHER_SYMBOL(x) __xCAT(CIPHER_ID,x) which in turn is used in the cipher implementations the following way (it's just a simplified case; essentially this macro template stuff allows to let the preprocessor "instantiate" some other symbols and protoype-declarations (which all follow the same scheme) in a batch, which would otherwise need to be typed out by hand...) #define CIPHER_ID twofish /* imagine the macro #defines written above to be in scope here */ /* the following simplified prototypes are #included from a gen(eric) c header */ int CIPHER_SYMBOL(_encrypt) (...); int CIPHER_SYMBOL(_decrypt) (...); int CIPHER_SYMBOL(_setkey) (...); the last 3 lines above would be expanded to int twofish_encrypt (...); int twofish_decrypt (...); int twofish_setkey (...); ...hope I could make it clear a bit (in case it wasn't), why this is a killer feature IMHO... now back to the reason, why the construct above needs those additional "x-layers": imagine we had CIPHER_SYMBOL2 using __CAT directly, instead of __xCAT: #define CIPHER_SYMBOL2(x) __CAT(CIPHER_ID,x) then int CIPHER_SYMBOL2(_encrypt) (...); would evaluate to (pass by pass): int CIPHER_SYMBOL2(_encrypt) (...); int __CAT(CIPHER_ID,_encrypt) (...); /* prescan not used for ##'s operands */ int CIPHER_ID ## _encrypt (...); /* post-scan doesn't change anything */ int CIPHER_ID_encrypt (...); /* since operands to ## are taken as is */ and now compare this to the x-version: int CIPHER_SYMBOL(_encrypt) (...); int __xCAT(CIPHER_ID,_encrypt) (...); /* prescanning takes place */ int __CAT(twofish,_encrypt) (...); /* pre-expanded args filled in, 2nd scan doesn't change anything */ int twofish ## _encrypt (...); /* __CAT got expanded */ int twofish_encrypt (...); /* just what we wanted! */ well, guess that's already off-topic enough for now... :-) regards, -- Herbert Valerio Riedel / Phone: (EUROPE) +43-1-58801-18840 Email: hvr@hvrlab.org / Finger hvr@gnu.org for GnuPG Public Key GnuPG Key Fingerprint: 7BB9 2D6C D485 CE64 4748 5F65 4981 E064 883F 4142
Attachment:
signature.asc
Description: This is a digitally signed message part