whm@arizona.UUCP (Bill Mitchell) (06/26/84)
I need a way to form variable names using cpp macros. For example, I'd like a macro X(y), which might expand X(foo) into Xfoo. It so happens that #define X(y) X/**/y X(foo) works on 4.xbsd and on V7. This apparently because cpp considers int z/**/z; to be int zz; Is there some proper way to achieve the same effect without relying on this "feature" of cpp and thus retain some hope of portability? Thanks, Bill Mitchell whm.arizona@csnet-relay {noao,mcnc,utah-cs}!arizona!whm
gwyn@BRL-VLD.ARPA (06/28/84)
From: Doug Gwyn (VLD/VMB) <gwyn@BRL-VLD.ARPA> At USENIX, the word was that there really is no way to concatenate strings using the C preprocessor in a portable way, but the ANSI committee is considering how this might be done. The tricks that work with the Reiser preprocessor do not necessarily work elsewhere.
ron@brl-vgr.ARPA (Ron Natalie <ron>) (06/28/84)
The behaviour is wrong. According to the manual a comment is supposed to be syntactically like white space. The C standards people are suggesting that a new character ('#') be used by the preprocessor to do the same thing that /**/ is used for. -Ron
marcus@pyuxt.UUCP (M. G. Hand) (06/29/84)
Distasteful as it may be, the X/**/y feature is well documented in the source of cpp by John Reiser, and is portable at least as far as System V. Marcus Hand (pyuxt!marcus)
jpl@allegra.UUCP (John P. Linderman) (06/29/84)
I expected to see a hail of responses to this item, but since a few days have gone by, and the only response has been in support of X/**/y, the following ought to see the light of day: #define QUOTE(X) X #define MAKENAME(Y) QUOTE(X)Y #define CAT(X,Y) QUOTE(X)Y MAKENAME(lax) CAT(X,pertsystems) As long as macros are supported, this mechanism will work; no tricky stuff. To give credit where it is due, I think I first saw the QUOTE macro used by Mike Bianchi, for quite different reasons. It's a useful addition to one's bag of tricks. John P. Linderman Department of Macro Biology allegra!jpl
rgh@inmet.UUCP (06/30/84)
#R:arizona:-1236100:inmet:5000019:000:403 inmet!rgh Jun 28 14:01:00 1984 There's no portable way to use C #define's to introduce new tokens into a program, since macro replacement is defined in terms of token strings in K&R [C RefMan 12.1]. This issue -- character string vs. token string macros -- came up at the most recent C ANSI standards committee meeting, and the token string viewpoint prevailed. Randy Hudson {harpo, ihnp4, decvax!cca!ima} !inmet!rgh
henry@utzoo.UUCP (Henry Spencer) (07/01/84)
> Distasteful as it may be, the X/**/y feature is well documented in the > source of cpp by John Reiser, and is portable at least as far as System V. Since it's documented in the source, that means it's effectively entirely undocumented as far as binary licensees are concerned. Furthermore, one finds the documentation in the source only by accident, since that's not exactly the first place one looks for documentation. And it is *not* portable to most non-Bell-derived compilers, since most of their authors didn't have access to the cpp sources. The ANSI C standards effort is standardizing the preprocessor facilities as part of the language. "X/**/y" is *not* allowed in the standard. "If you want a general-purpose macro processor, use m4!" -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
bet@ecsvax.UUCP (07/02/84)
Someone made a comment earlier that seems to have been ignored by many, that efforts like X/**/Y and the QUOTE macro *aren't* guaranteed to be portable, and further that *no* mechanism is guaranteed to be portable, since in theory the cpp functionality is defined in terms of *tokens*. That is to say, the standard, *required* behavior of cpp could be produced by code between the lexical analyzer and the parser. Composite token creation can only really be expected to show up when cpp is a distinct pass of the compiler, producing "clear", preprocessed C as an intermediate step, which then undergoes another lexical analysis. In fact this is not the only way that compilers are created -- small, fast single pass compilers for micros, to keep the amount of overlaying required down, sometimes build the functionality of cpp *into* the compiler. A second lexical analysis is legitimately considered an unnecessary waste of time and space. Let us keep in mind that one of the strongest aspects of C is how good a language it is for small systems. Bennett Todd ...{decvax,ihnp4,akgua}!mcnc!ecsvax!bet
ado@elsie.UUCP (07/11/84)
> For concatenating strings at preprocessor time, try this: > > #define Ident(xxx) xxx > > #define concat(a,b) Ident(a)b > > It should always work. . . "Always"? How about if either "a" or "b" is "__LINE__"? Try typing this to see what happens: cc -E - #define Ident(xxx) xxx #define concat(a,b) Ident(a)b __LINE__ concat(__LINE__,__LINE__) -- ...decvax!allegra!umcp-cs!elsie!ado (301) 496-5688 (the DEC and VAX in decvax are Digital Equipment Corporation trademarks)
jwp@sdchema.UUCP (07/13/84)
...!elsie!ado: >Try typing this to see what happens: > cc -E - > #define Ident(xxx) xxx > #define concat(a,b) Ident(a)b > __LINE__ > concat(__LINE__,__LINE__) "concat(__LINE__,__LINE__)" gives "__LINE____LINE__" "concat(__LINE__, __LINE__)" gives, e.g., "3 3" For that matter: "concat(this,that)" results in "thisthat" "concat(this, that)" results in "this that" Defining "concat(a, b)" instead of "concat(a,b)" doesn't, however, seem to make a difference. It *is* interesting behavior. And also reinforces my general feelings that: (a) relying on the preprocessor to do too much for you is foolish, and (b) being very clever is a really fun way to screw up those that follow you (or yourself when you have to go back to the miserable thing two years later and have forgotten how terribly clever you were), especially when you follow the customary C commenting conventions. John Pierce, Chemistry, UC San Diego sdcsvax!sdchema!jwp
jim@ism780b.UUCP (08/02/84)
#R:elsie:-101400:ism780b:25500010:000:1888 ism780b!jim Jul 17 21:58:00 1984 > > >Try typing this to see what happens: > > cc -E - > > #define Ident(xxx) xxx > > #define concat(a,b) Ident(a)b > > __LINE__ > > concat(__LINE__,__LINE__) > > "concat(__LINE__,__LINE__)" gives "__LINE____LINE__" > "concat(__LINE__, __LINE__)" gives, e.g., "3 3" Not with a Reiser cpp (this is just one of the hundreds of bugs; I too rolled my own). >For that matter: "concat(this,that)" results in "thisthat" > "concat(this, that)" results in "this that" Easy to explain: the arguments to a macro consist of the text between parens and commas (not nested within parens), including any white space. Thus, you concatenated "this" with " that". The problem is that there is no formal documentation of cpp. > Defining "concat(a, b)" instead of "concat(a,b)" doesn't, however, seem to > make a difference. Of course, since "a" and "b" are just tokens to be replaced in the replacement text. > It *is* interesting behavior. Not very. > And also reinforces my > general feelings that: (a) relying on the preprocessor to do too much for you > is foolish, and (b) being very clever is a really fun way to screw up those that follow you (or yourself when you have to go back to the miserable thing two years later and have forgotten how terribly clever you were), especially when you follow the customary C commenting conventions. Definitely true given that it is undocumented, although understandable when the only alternative is m4. When defining a macro which can be tucked away in a common include file with plenty of comments can allow you to write far more readable and modifiable code elsewhere, then it may not be so foolish. However, if it is just used to support another favorite hack, then the cause is lost anyway. -- Jim Balter, INTERACTIVE Systems (ima!jim)