Re: questions about gen-cipher.h

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Kernel]     [Linux Crypto]     [Gnu Crypto]     [Gnu Classpath]     [Netfilter]     [Bugtraq]
  Powered by Linux