[comp.unix.questions] need cpp macros to concatenate names

clark@calma.UUCP (Al Clark) (05/05/87)

*** IS THERE REALLY A LINE EATER ??? ***

Has anyone had any success using a macro to concatenate two words; eg:
concat(one, word)  to generate the the single word 'oneword', as in the
following code segment.

#define prefix my

#define concat(x,y) x\
y

main()
{
	long *concat(prefix,file);
}

The above works on some preprocessors, not others.  In all cases, the escaped 
new line provides token separation.  On the Sequent ucb universe, and on the
IBM RT the two words endup concatenated; on the Sequent att universe, they
are separated by a space.  Our intent is to be portable to any System
V machine with a minimum of changes.

Anybody have a suggestion? (We know about m4 and sed, but we can't afford to
add another step to the compilation of many thousands of lines of code, which
are all compiled together on a major build of an executable module.)
manual page,  

Any help will be appreciated. Please mail responses, unless you think they are
of general interest.
 
-- 
Al Clark - {ucbvax,sun,...}calma!clark
NOTE: This is a courtesy account; I am not employed by calma.

guy%gorodish@Sun.COM (Guy Harris) (05/05/87)

> The above works on some preprocessors, not others.

Yup.  Somewhere between System III and System V, I think, the
preprocessor was changed to turn escaped newlines, in the case you
mention, into blanks.  This is, in fact, incorrect, as I read the
ANSI C draft of October 1, 1986, since escaped newlines are to be
thrown out fairly early in the processing of the source code.

> In all cases, the escaped new line provides token separation.

Which is also incorrect, as I read the ANSI C draft.

> Our intent is to be portable to any System V machine with a minimum of
> changes.
> 
> Anybody have a suggestion? (We know about m4 and sed, but we can't afford to
> add another step to the compilation of many thousands of lines of code, which
> are all compiled together on a major build of an executable module.)

If you really intend to be portable to any conceivable S5-compatible
implementation, I suggest you use "m4" and/or "sed", since there's no
*documented* way of gluing tokens together in pre-ANSI C.

The following trick works on the versions of the "Reiser" preprocessor
that are distributed with AT&T UNIX releases, but somebody may have
changed things so as to make it not work (unlikely - I know of nobody
who has - but not impossible):

	#define concat(x,y) x/**/y

Note, BTW, that you MUST NOT call "concat" as

	concat(foo, bar)

and expect it to glue "foo" and "bar" together - it will glue "foo"
and " bar" (note the blank) together.

kurt@hi.UUCP (Kurt Zeilenga) (05/05/87)

In article <634@calma.UUCP> clark@calma.UUCP (Al Clark) writes:
>Has anyone had any success using a macro to concatenate two words; eg:
>concat(one, word)  to generate the the single word 'oneword', as in the
>following code segment.

Yes.

>#define prefix my

This makes it very hard! 

>#define concat(x,y) x\
>y
>
>main()
>{
>	long *concat(prefix,file);
>}
>

I've used in the pass (on a SUN3/160C with Rel. 3.3):

#define cat(x,y)	x/**/y
cat(a,b);

You get:

ab

But if you try to #define a or b, it don't work.
A friend (bret@hi.uucp) showed me:

#define prefix my
#define zz **
#define concat(x,y)	x/zz/y

	long *concat(prefix,file)

So, what does your compiler do with "long * my/**/file;"?  Ours
turns comments into "white space" . . . as in K&R.  Doesn't do
you any good, but it has its (ab)uses.

Well, I tried....

-- 
	Kurt Zeilenga	 (zeilenga@hc.dspo.gov)		I want my talk.flame!

	"So long, Mom, I'm off to drop the bomb..."

kurt@hi.UUCP (Kurt Zeilenga) (05/05/87)

In article <18010@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
   . . .
>The following trick works on the versions of the "Reiser" preprocessor
>that are distributed with AT&T UNIX releases, but somebody may have
>changed things so as to make it not work (unlikely - I know of nobody
>who has - but not impossible):
>
>	#define concat(x,y) x/**/y
>
>Note, BTW, that you MUST NOT call "concat" as
>
>	concat(foo, bar)
>
>and expect it to glue "foo" and "bar" together - it will glue "foo"
>and " bar" (note the blank) together.

It don't work that way on BSD releases.  The comment gets
stripped before either foo or bar get replaced by any other macros.

Hence:

#define foo	kay
#define bar	o
#define concat(x,y)	x/**/y
concat(foo,bar)

Returns: " foobar" (as Guy noted, the space)...

-- 
	Kurt Zeilenga	 (zeilenga@hc.dspo.gov)		I want my talk.flame!

	"So long, Mom, I'm off to drop the bomb..."

brent@terra.UUCP (05/05/87)

In article <634@calma.UUCP>, clark@calma.UUCP (Al Clark) writes:
> 
> Has anyone had any success using a macro to concatenate two words; eg:
> concat(one, word)  to generate the the single word 'oneword', as in the
> following code segment.
> 
> #define prefix my
> 
> #define concat(x,y) x\
> y
> 
> main()
> {
> 	long *concat(prefix,file);
> }

Have you tried using a null comment ?  It works OK on the
Sun compiler e.g.

	#define concat(x,y)	x/**/y

Made in New Zealand -->  Brent Callaghan  @ Sun Microsystems
			 uucp: sun!bcallaghan
			 phone: (415) 691 6188

guy@gorodish.UUCP (05/06/87)

> It don't work that way on BSD releases.

Umm, the "cpp" distributed with 4.3BSD isn't, as I remember, that
violently different (as determined by "diff") from that distributed
with V7.  (Differences exist, but nothing as fundamental as the order
in which things are done changed.  Even the S5 one isn't violently
different once you run it and a V7/S3/4BSD one through something like
"indent" - the S5 one was reformatted to eliminate the original's
somewhat, umm, idiosyncratic formatting.)  Moreover, I'm not sure
what "it don't work that way" refers to, except to the warning about

	concat(foo, bar)

I just built the 4.3BSD "cpp" here and it does, in fact, expand
"concat(foo, bar)" to " foo bar".

> The comment gets stripped before either foo or bar get replaced by any
> other macros.

Did I say it didn't get so replaced in the "cpp" as distributed with
other releases?  No.  In fact, I just tried your example with what is
basically an S5R3 "cpp", and it returns "foobar"; the only difference
is that the white space between the "concat(x,y)" and the "x/**/y" in
the definition isn't considered part of the definition of the macro.

So what "don't work that way on BSD releases" but "works that way" on
other releases?  The "x/**/y" stuff seems to work the same way on all
versions of the Reiser preprocessor; the question is whether it works
the same way in compilers not using the Reiser preprocessor (the
answer is "maybe yes, maybe no, don't expect it to").

ado@elsie.UUCP (05/06/87)

> > Our intent is to be portable to any System V machine with a minimum of
> > changes.
> > 
> > Anybody have a suggestion? (We know about m4 and sed, but we can't afford to
> > add another step to the compilation of many thousands of lines of code. . .)
> 
> . . .I suggest you use "m4" and/or "sed", since there's no
> *documented* way of gluing tokens together in pre-ANSI C.
> 
> The following trick works on the versions of the "Reiser" preprocessor
> that are distributed with AT&T UNIX releases. . .
> 
> 	#define concat(x,y) x/**/y

And if you think the code will have a good long lifetime, think about using

	#ifdef __STDC__
	#define concat(x,y) x ## y
	#else
	#define concat(x,y) x/**/y
	#endif

--
UNIX is a registered trademark of AT&T.
-- 
	UUCP: ..seismo!elsie!ado	   ARPA: elsie!ado@seismo.CSS.GOV
	     Elsie and Ado are trademarks of Borden, Inc. and Ampex.

bret@hi.UUCP (Bret K. Thaeler) (05/06/87)

> #define prefix my
> 
> #define concat(x,y) x\
> y
> 
> main()
> {
> 	long *concat(prefix,file);
> }
> 

This is our attempt. This was done on a Sun running 3.3.

#define pre()my
#define prefix pre()
#define concat(x,y)x//**/**/y

main()
{
	long *concat(prefix,file);
}

----------------- producing -----------------
main()
{
	long *myfile;
}

=============================================


Now for the hard one.... What if you want BOTH of the concat() args
to be #define's??? 

#define  prefix my
#define  post()file
#define  postfix post()
#define concat(x,y)x//**/**/y

main()
{
	long *concat(prefix,postfix);
}

----------------- producing -----------------

main()
{
	long *myfile;
}

=============================================

Brought to you by the minds of ... 
	--Bret

Who said hackers were no good bums?
	--Josh

Who needs m4?
	--Kurt


-- 
--------------------------------------------------------------------------------
Bret K. Thaeler		     ARPA: thaeler@hc.dspo.gov  |          /// Amiga
College of Enginering, UNM   UUCP: hc!thaeler           |         /// user
Professional Student                                    |   \\\  ///
Of: (505) 277-1611    Ho: (505) 277-4497		|    \\\///  And dam
I instinctively used the Vulcan death grip.             |     \///  proud,
 ofak