[comp.lang.c] Preprocessor macro to quote its argument

adrian@mti.mti.com (Adrian McCarthy) (08/18/90)

Ever needed a preprocessor macro that could quote its argument?  I did for
my own version of assert().  The obvious first try is:

	#define Q1(x)	" x "

but the argument isn't expanded because it's in quotes.  Solution follows...

	#define Q	"
	#define Q1(x)	Q x "

It introduces a few spaces, but fortunately that doesn't conflict with my
needs.

Note that:

	#define Q1(x)	Q x Q

does *not* work.  The second Q won't be translated.

I think my solution is portable.  It seems to comply with the ANSI
preprocessing notes in K&R/2.  In addition, it works on the non-ANSI
Sun and VAX/VMS compilers.

In case the motivation isn't clear, I wanted something along the lines of:

	ASSERT((x > 0))

to produce:

	assert((x > 0), " (x > 0) ")

so that the assert() function could print the assertion if the condition
fails.

Aid.  (adrian@gonzo.mti.com)

vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) (08/18/90)

In article <1112@mti.mti.com> adrian@mti.UUCP (Adrian McCarthy) writes:
>Ever needed a preprocessor macro that could quote its argument?  I did for
\\\
>	#define Q	"
>	#define Q1(x)	Q x "


Whatever happened to

#define	Q(x)	#x

?

-Kym Horsell

fpb@ittc.wec.com (Frank P. Bresz) (08/19/90)

In article <1112@mti.mti.com> adrian@mti.mti.com (Adrian McCarthy) writes:

>Ever needed a preprocessor macro that could quote its argument?  I did for
>my own version of assert().  The obvious first try is:

>	#define Q1(x)	" x "

>but the argument isn't expanded because it's in quotes.  Solution follows...
>
>	#define Q	"
>	#define Q1(x)	Q x "

>It introduces a few spaces, but fortunately that doesn't conflict with my
>needs.

>Note that:

>	#define Q1(x)	Q x Q

>does *not* work.  The second Q won't be translated.

>I think my solution is portable.  It seems to comply with the ANSI
>preprocessing notes in K&R/2.  In addition, it works on the non-ANSI
>Sun and VAX/VMS compilers.

>In case the motivation isn't clear, I wanted something along the lines of:

>	ASSERT((x > 0))

>to produce:

>	assert((x > 0), " (x > 0) ")

>so that the assert() function could print the assertion if the condition
>fails.

	Funny I have been using the following debug.h for years without
much problem.  I use the argument a inside quotes and it expands exactly as
I want it to.   You have to be carefull about side effects because it
evaluates twice.  Once for the printing and once to get the result this
allows 
	a = dbgdec(x);

	to work correctly.  I use the dbgmsg[n] to print out informational
messages to stderr.  I name everything dbg so I can quickly nuke them when
I am done debugging.

	BTW This is on SunOS I have also done it on an INTEL 310 system
running some XENIXy kind of unix.


debug.h 

#define dbgflt(a) (fprintf(stderr,"a = %f\n",a),fflush(stderr),(a))
#define dbghex(a) (fprintf(stderr,"a = %08lx\n",a),fflush(stderr),(a))
#define dbghexs(a) (fprintf(stderr,"a = %04x\n",a),fflush(stderr),(a))
#define dbghexc(a) (fprintf(stderr,"a = %02x\n",(unsigned char) a),fflush(stderr),(a))
#define dbgdec(a) (fprintf(stderr,"a = %12ld\n",a),fflush(stderr),(a))
#define dbgdecs(a) (fprintf(stderr,"a = %6d\n",a),fflush(stderr),(a))
#define dbgdecc(a) (fprintf(stderr,"a = %3d\n",(unsigned char) a),fflush(stderr),(a))
#define dbgmsg(a) (fprintf(stderr,"%s\n",a),fflush(stderr),(a))
#define dbgmsgn(a) (fprintf(stderr,"%s",a),fflush(stderr),(a))
#define dbgsev(a) (fprintf(stderr,"a = '%s'\n",a),fflush(stderr),(a))
#define dbgfile	(fprintf(stderr,"%s:%d",__FILE__,__LINE__),fflush(stderr))

	It allows me to put the following in my C code and I will get
results below:

...

int foo;
char *str;

dbgdec(foo);
....
dbghex(str);
dbgsev(str);

....

Execution is 

...
foo = 15
...
str = 0x00049812
str = 'This is a test'
--
+--------------------+
|fbresz@ittc.wec.com |  My opinions are my own, I'm not paid
|uunet!ittc!fbresz   |  enough to make an official statement  
|(412)733-6749       |  +-----------------------------------+
|Fax: (412)733-6444  |  |      THIS SPACE FOR SALE!!!       |
+--------------------+  +-----------------------------------+

adrian@mti.mti.com (Adrian McCarthy) (08/20/90)

In article <1112@mti.mti.com> adrian@mti.UUCP I wrote:
>Ever needed a preprocessor macro that could quote its argument?  [...]
>	#define Q	"
>	#define Q1(x)	Q x "

It has been pointed out by several kind folks that this is *not*
ANSI-compliant.  ANSI preprocessors do the tokenization of the input for
the rest of the compiler (thus ``preprocessor'' is arguably a misnomer),
so the #define lines would generate errors since the unpaired double-quote
is an incomplete token.

For ANSI preprocessors, use:
	#define Q1(x)	#x
For pre-ANSI preprocessors, the original solution *may* work.  Reportedly,
	#define Q1(x)	" x "
may even work with many pre-ANSI preprocessors, though not VAX C.

OK, so I was wrong,
Aid.  (adrian@gonzo.mti.com)

unhd (Anthony Lapadula) (08/20/90)

In article <3857@bingvaxu.cc.binghamton.edu> vu0310@bingvaxu.cc.binghamton.edu.cc.binghamton.edu (R. Kym Horsell) writes:
>In article <1112@mti.mti.com> adrian@mti.UUCP (Adrian McCarthy) writes:
>>Ever needed a preprocessor macro that could quote its argument?  I did for
>\\\
>>	#define Q	"
>>	#define Q1(x)	Q x "
>
>
>Whatever happened to
>
>#define	Q(x)	#x
>
>?
>
>-Kym Horsell

What happens if Q is ``invoked'' with another macro as its argument, as in:
	#define M1 100
	#define M2 func()
	:
	puts (Q(M1));
	puts (Q(M2));

What should the output be?  The two compilers available to me disagree.
   gcc version 1.37.1   --->   outputs "M1" and "M2"
   cc                   --->   CPP error ("#100 undefined [in puts(#100)])

These results are for a DECstation 5000.


-- Anthony (uunet!unhd!al, al@unh.edu) Lapadula

// Wanted: catchy .sig.

henry@zoo.toronto.edu (Henry Spencer) (08/20/90)

In article <1114@mti.mti.com> adrian@mti.UUCP (Adrian McCarthy) writes:
>It has been pointed out by several kind folks that this is *not*
>ANSI-compliant.  ANSI preprocessors do the tokenization of the input for
>the rest of the compiler (thus ``preprocessor'' is arguably a misnomer)...

Actually, a good many pre-ANSI preprocessors do this too; X3J11 did not
invent this approach.
-- 
Committees do harm merely by existing. | Henry Spencer at U of Toronto Zoology
                       -Freeman Dyson  |  henry@zoo.toronto.edu   utzoo!henry

rankin@eql.caltech.edu (08/20/90)

[ He wants to turn a macro argument into a quoted string, which is done
significantly differently in ANSI C than in 'traditional' C. ]

In article <1114@mti.mti.com>, adrian@mti.mti.com (Adrian McCarthy) writes:
>[text deleted]
> For ANSI preprocessors, use:
> 	#define Q1(x)	#x
> For pre-ANSI preprocessors, the original solution *may* work.  Reportedly,
> 	#define Q1(x)	" x "
> may even work with many pre-ANSI preprocessors, though not VAX C.

     The second method works fine in VAX C (which is not [yet?] ANSI
compliant).  The preprocessor is just an internal phase of the integrated
compiler, but that doesn't make any difference in a case like this.

$  type t.c   			!t.c is a trivial test file
#define Q1(x) " x "
char *string = Q1(xyzzy);
$  cc/preprocess_only t		!read t.c, write t.i
$  type t.i			!display the result
# 1 "USER:[RANKIN]T.C;1"

char *string = " xyzzy ";

     Older versions of the compiler didn't support an explicit preprocess-
only option, but they still did the macro substitution this way.

		Pat Rankin, rankin@eql.caltech.edu

vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) (08/20/90)

In article <1990Aug19.200440.8534@uunet!unhd> al@unhd.UUCP (Anthony Lapadula) writes:
\\\
>What happens if Q is ``invoked'' with another macro as its argument, as in:
>	#define M1 100
>	#define M2 func()
>	:
>	puts (Q(M1));
>	puts (Q(M2));
>
>What should the output be?  The two compilers available to me disagree.
>   gcc version 1.37.1   --->   outputs "M1" and "M2"
>   cc                   --->   CPP error ("#100 undefined [in puts(#100)])

The #x in a macro is supposed to produce an ascii string if its 
argument "x".

Since rescanning occurs *after* this process and ANSII C isn't
*supposed* to look inside strings you should get what gcc gave
you. 

It sounds like your cc dosn't comply with the std.

-Kym Horsell

vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) (08/20/90)

Sorry about the bandwidth, but... If you *want* to quote something
*after* is has been expanded try this:

#define	Q2(x)	#x
#define	Q(x)	Q2(x)
#define	foo	bar

main(){
	puts(Q(foo));
	}

Ugly?  But it works (if you've an ansii comp).

-Kym Horsell

schaefer@ogicse.ogi.edu (Barton E. Schaefer) (08/20/90)

In article <1114@mti.mti.com> adrian@mti.UUCP (Adrian McCarthy) writes:
} In article <1112@mti.mti.com> adrian@mti.UUCP I wrote:
} >Ever needed a preprocessor macro that could quote its argument?  [...]
} >	#define Q	"
} >	#define Q1(x)	Q x "
} 
} It has been pointed out by several kind folks that this is *not*
} ANSI-compliant.  ANSI preprocessors do the tokenization of the input for
} the rest of the compiler (thus ``preprocessor'' is arguably a misnomer),
} so the #define lines would generate errors since the unpaired double-quote
} is an incomplete token.

In article <1990Aug20.012839.3545@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
} 
} Actually, a good many pre-ANSI preprocessors do this too; X3J11 did not
} invent this approach.

Now wait a minute here -- is it really true that the "right hand side"
of a #define constant must be a valid token sequence?  I was under the
impression that only the result after expansion had to be a valid sequence.

I believe that someone once suggested quoting a single character by

#define C1(x) 'x
#define C2(x) x'
#define CHAR(x) C2(C1(x))

and I don't recall any complaints about 'x and x' not being tokens coming
up at that point.  That was in a discussion of how to repair macros that
(in Reiser cpp) use stuff like

#define CTRL(x) ('x' & 037)
char eof = CTRL(D);

by using instead

#define CTRL(x) (CHAR(x) & 037)

for an ANSI preprocessor.  Yes, I know the preferred method would be
either ( #x [0] & 037) or global replacement to use CTRL('D').  The
question is, is   #define C1 'x   an error at time of definition?
-- 
Bart Schaefer						schaefer@cse.ogi.edu

nol2321@dsacg4.dsac.dla.mil (Jim Dunn) (08/20/90)

Greetings NetLanders...

I've currently been working on a version of CURSES for our PCs that is
uses "direct screen writes" and "many many #defines".  I've been told
about PcCurses v1.4 and v1.5, but they use the BIOS screen write
approach.  That is fine, but we need our EGA screens to refresh faster.

I have a 20K C source file (we're doing it all in C) and all seems to
be fine, except we find that our PCs lock up ever to often, or after
you execute the program many times, etc.

If anyone would be interested in taking a look at the source/debugging
some for us, please send me some e-mail and I'd be glad to send you
the source!

Thanks!
Jim, jdunn@dsac.dla.mil

 ------------------------------------------------------------------------------
 Jim Dunn:  jdunn@dsac.dla.mil; AV 850-9713; ATT 614-238-9713; FAX 614-238-9936
 "He Cared the Most, He Gave It All; Know it & Live, or Ignore it & Die." JD :)
 ------------------------------------------------------------------------------

steve@taumet.com (Stephen Clamage) (08/21/90)

schaefer@ogicse.ogi.edu (Barton E. Schaefer) writes:

>Now wait a minute here -- is it really true that the "right hand side"
>of a #define constant must be a valid token sequence?  I was under the
>impression that only the result after expansion had to be a valid sequence.

The #define must consist of valid *pre-processor* tokens, which are not
quite identical to C language tokens.  In particular, partial string
constants and partial character constants are not allowed.  That is,
your examples such as of
	#define w	"
	#define x	abc"
	#define y	'
	#define z	d'
are all illegal in ANSI C.  (Preprocessor tokens include fragments of
file names in unexpanded #include directives, and fragments of
numbers in macro definitions.)

The "stringizing" and "token concatenation" preprocessor operators are
sufficient to do what the nonportable earlier constructs did, except
for building a character constant.  There are now no legal tricks in an
ANSI-compliant program which allow you to build a character constant
from parts.  You could write to the ANSI committee and suggest that the
next C standard (1995?) include "character-constant pasting" :-)
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

henry@zoo.toronto.edu (Henry Spencer) (08/22/90)

In article <11517@ogicse.ogi.edu> schaefer@ogicse.ogi.edu (Barton E. Schaefer) writes:
>Now wait a minute here -- is it really true that the "right hand side"
>of a #define constant must be a valid token sequence?  I was under the
>impression that only the result after expansion had to be a valid sequence.

Your impression is wrong; the RHS of a #define constant must be a sequence
of valid preprocessor tokens (which are somewhat less restrictive than
"real" tokens).  In particular, mismatched quotes have undefined effects.

The right way to fix the notorious `CTRL(D)' problem is to quote the D.
There is no portable way for the macro to supply the (single) quotes.
This has been true for a long time; tokenizing preprocessors existed
well before the ANSI C effort started.
-- 
Committees do harm merely by existing. | Henry Spencer at U of Toronto Zoology
                       -Freeman Dyson  |  henry@zoo.toronto.edu   utzoo!henry

ckp@grebyn.com (Checkpoint Technologies) (08/25/90)

In article <1990Aug21.175138.24633@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>The right way to fix the notorious `CTRL(D)' problem is to quote the D.
>There is no portable way for the macro to supply the (single) quotes.
>This has been true for a long time; tokenizing preprocessors existed
>well before the ANSI C effort started.

(This is just off the top of my head, so please be gentle...)

Why can't this work?

#define CTRL(ch) ((* #ch) - 64)

It's ANSI only. The single # places it's arg in double quotes, making a
string, and the * returns the first byte of the string.

Now, I know this *could* be a constant expression. In ANSI, should
a compiler treat this as a constant expression, which is allowed in
static initializers etc?
-- 
First comes the logo: C H E C K P O I N T  T E C H N O L O G I E S      / /  
                                                                    \\ / /    
Then, the disclaimer:  All expressed opinions are, indeed, opinions. \  / o
Now for the witty part:    I'm pink, therefore, I'm spam!             \/

vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) (08/26/90)

In article <21594@grebyn.com> ckp@grebyn.UUCP (Checkpoint Technologies) writes:
\\\
>(This is just off the top of my head, so please be gentle...)
>
>Why can't this work?
>
>#define CTRL(ch) ((* #ch) - 64)
>
>It's ANSI only. The single # places it's arg in double quotes, making a
>string, and the * returns the first byte of the string.

This is fine (and I think has been pointed out recently on this
newsgroup). A slight improvement may be

#define	CTRL(c)	((*#c)&037)

'though.

-Kym Horsell

henry@zoo.toronto.edu (Henry Spencer) (08/26/90)

In article <21594@grebyn.com> ckp@grebyn.UUCP (Checkpoint Technologies) writes:
>Why can't this work?
>#define CTRL(ch) ((* #ch) - 64)
>Now, I know this *could* be a constant expression...

3.4 says that the value of an object may not be accessed by a `*' operator
in a constant expression, so this isn't a constant expression in a portable
sense.  However, it is not a constraint violation, so the compiler is not
*required* to complain about it, and 3.4 does explicitly authorize compilers
to accept "other forms" of constant expression.  So your comment is correct:
it *could be* a constant expression, but isn't dependably one.  Alas, one
use of the `CTRL(D)' hack is in case labels, where constant expressions are
required.
-- 
Committees do harm merely by existing. | Henry Spencer at U of Toronto Zoology
                       -Freeman Dyson  |  henry@zoo.toronto.edu   utzoo!henry

peter@ficc.ferranti.com (Peter da Silva) (08/26/90)

In article <3891@bingvaxu.cc.binghamton.edu> vu0310@bingvaxu.cc.binghamton.edu.cc.binghamton.edu (R. Kym Horsell) writes:
> #define	CTRL(c)	((*#c)&037)

If you define CTRL(c) ((*#c)^('\177'^'?')) it'll handle '^?' for delete as
well, at the expense of producing gibberish for CTRL(a).
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
peter@ferranti.com

vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) (08/27/90)

In article <GJG5YDA@ggpc2.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
\\\
>If you define CTRL(c) ((*#c)^('\177'^'?')) it'll handle '^?' for delete as
>well, at the expense of producing gibberish for CTRL(a).

I think the original

#define	CTRL(c)	((*#c)-64)

did this correctly anyway. It just makes me nervous that it also didn't
handle lower-case; I came across a nasty bug once involving the
programmer's misunderstanding of what CTRL(x) would match!

-Kym Horsell