jbaker@ee.UCLA.EDU (Joe Baker) (02/18/88)
I am a C neophyte and am looking for a solution to the following problem: I am attempting to port the latest version of the public domain spreadsheet calculator, sc 5.1, to an IBM PC. I am using Microsoft C 5.0. The code uses the following macro to produce control characters for comparison to input characters in case statements and the like: #define ctl(c) ('c'&037) This requires parameter substitution within a character constant, which is not allowed in MSC5.0 (My reading of Kernighan & Ritchie pg. 207 seems to indicate that they don't allow it either. However, the program compiles and runs on lots of systems.) The Microsoft manual suggests use of the 'stringizing' operator, #, but this produces a string literal instead of a character constant. I have come up with some ugly fixes, but would like to know: what is the Right Way to do this? Thanks, - Joe Baker, Dept. of Electrical Engineering 6731 Boelter Hall, UCLA, L.A., CA 90024 (213) 825-7079, 825-2327 ARPA: jbaker@ee.ucla.edu UUCP: {ihnp4|randvax|ucbvax}!ucla-cs!uclaee!jbaker "Presumptions that the church should be trying to improve housing for the poor...that the church should be small and impoverished...are hidden presumptions that I see all the time. Are _you_ housing the homeless in your home? What's the Empire State Building doing to help the homeless...? Why should people just pick on the churches? There's a fairness element here." - Pastor of the Fifth Avenue Presbyterian Church in NYC
karl@haddock.ISC.COM (Karl Heuer) (02/19/88)
In article <11879@brl-adm.ARPA> jbaker@ee.UCLA.EDU (Joe Baker) writes: > #define ctl(c) ('c'&037) >... is not allowed in MSC5.0 Nor in ANSI C. >What is the Right Way to do this? Change the definition to "#define ctl(c) ((c)&037)" and write "ctl('P')" rather than "ctl(P)". You may also want to change the name, in case you overlook some references. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/19/88)
In article <11879@brl-adm.ARPA> jbaker@ee.UCLA.EDU (Joe Baker) writes: >#define ctl(c) ('c'&037) Yes, whoever did this was deliberately violating the K&R rules, because they knew that their C preprocessor (probably based on Reiser's) would allow it. This particular macro and Berkeley's _IOR etc. ioctl macros are the most common cases of this nonportable construct. Neither was necessary, since the desired effect could have been achieved portably. The correct way to have done this would have been: #define ctl(c) ((c)&037) and include the '' in its invocation: case ctl('G'): With ANSI C, or any C preprocessor that includes the stringizing feature, you can make the original usage work by #define ctl(c) (#c[0]&037) which would cause case ctl(G): to expand to case ("G"[0]&037): which is equivalent to case ('G'&037): Personally, I prefer the other way I described, because it also works with pre-ANSI C preprocessors.
edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (02/19/88)
> > #define ctl(c) ('c'&037) > >... is not allowed in MSC5.0 > > Nor in ANSI C. Does this imply that a macro parameter will nolonger be expanded in strings too? #define DEBUG_CALL(xxx) if ((xxx) != OK) { \ (void) printf("xxx\n"); \ (void) printf("%s %d\n\n",__FILE__,__LINE__);\ clearline(); } -- Eddie Wyatt e-mail: edw@ius1.cs.cmu.edu
scjones@sdrc.UUCP (Larry Jones) (02/19/88)
In article <11879@brl-adm.ARPA>, jbaker@ee.UCLA.EDU (Joe Baker) writes:
< #define ctl(c) ('c'&037)
<
< This requires parameter substitution within a character constant, which
< is not allowed in MSC5.0 (My reading of Kernighan & Ritchie pg. 207
< seems to indicate that they don't allow it either. However, the
< program compiles and runs on lots of systems.)
<
< The Microsoft manual suggests use of the 'stringizing' operator, #,
< but this produces a string literal instead of a character constant.
Just stringize and then pick the character you want out of the string:
#define ctl(c) (#c[0]&037)
A sufficiently clever compiler will just compile this into a character
constant.
--
----
Larry Jones UUCP: uunet!sdrc!scjones
SDRC MAIL: 2000 Eastman Dr., Milford, OH 45150
AT&T: (513) 576-2070
"When all else fails, read the directions."
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/19/88)
In article <898@PT.CS.CMU.EDU> edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes: > Does this imply that a macro parameter will nolonger be expanded in >strings too? Yes -- it never was supposed to be expanded, according to K&R specs. The Reiser C preprocessor did anyway, though -- that's a bug.
kulik@xyzzy.UUCP (Al Kulik) (02/20/88)
>In article <898@PT.CS.CMU.EDU> edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes: > Does this imply that a macro parameter will nolonger be expanded in >strings too? That's right. You have to use the '#' operator, e.g. #define str(s) # s . . . char *p = str(somestring); which results in char *p = "somestring"; -- Al Kulik, Data General. Uucp: ...!mcnc!rti!xyzzy!kulik Arpa/Csnet: kulik@dg-rtp.DG.COM
karl@haddock.ISC.COM (Karl Heuer) (02/20/88)
In article <7277@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <11879@brl-adm.ARPA> jbaker@ee.UCLA.EDU (Joe Baker) writes: >>#define ctl(c) ('c'&037) > >Yes, whoever did this was deliberately violating the K&R rules I looked it up when I first saw this hack, and I concluded that K&R didn't establish an unambiguous rule. The book says that macros are not expanded inside strings, but I don't think it specifies whether macro *arguments* are expanded inside strings within the macro. >With ANSI C, or any C preprocessor that includes the stringizing >feature, you can make the original usage work by > #define ctl(c) (#c[0]&037) >which would cause > case ctl(G): >to expand to > case ("G"[0]&037): Umm, I believe that according to the C rules, that's a non-constant expression (and hence illegal as a case label). Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
flaps@csri.toronto.edu (Alan J Rosenthal) (02/21/88)
In article <11879@brl-adm.ARPA> jbaker@ee.UCLA.EDU (Joe Baker) writes: >#define ctl(c) ('c'&037) ... >I have come up with some ugly fixes, but would like to know: what is >the Right Way to do this? how about #define ctl(c)((c) & 31) and call it as ctl('a') -- "noalias considered sailaon"
gnu@hoptoad.uucp (John Gilmore) (02/21/88)
jbaker@ee.UCLA.EDU (Joe Baker) wrote: > #define ctl(c) ('c'&037) > I have come up with some ugly fixes, but would like to know: what is > the Right Way to do this? The Right Way is to send in a comment to the ANSI C committee, complaining that there is no Right Way to do this. This change caused us to have to fix more than 50 files in Berkeley Unix. We wouldn't have minded changing all the macro definitions -- we know that substitution inside strings is a hack -- it's that we had to change all the CALLERS too that bugged us! [Responses of the form: "Well, you already fixed your code, so why should we make the standard reasonable?" are bogus. A useful capability was removed, and replaced with a less capable set of features.] > However, the > program compiles and runs on lots of systems. Something like 99% of the Unix systems, I'd guess, since they all seem to use John Reiser's cpp -- it works, why rewrite it? -- {pyramid,ptsfa,amdahl,sun,ihnp4}!hoptoad!gnu gnu@toad.com "Watch me change my world..." -- Liquid Theatre
gnu@l nptoad.uucp (John Gilmore) (02/21/88)
jbaker@ee.UCLA.EDU (Joe Baker) wrote: > #define ctl(c) ('c'&037) > I have come up with some ugly fixes, but would like to know: what is > the Right Way to do this? The Right Way is to send in a comment to the ANSI C committee, complaining that there is no Right Way to do this. This change caused us to have to fix more than 50 files in Berkeley Unix. We wouldn't have minded changing all the macro definitions -- we know that substitution inside strings is a hack -- it's that we had to change all the CALLERS too that bugged us! [Responses of the form: "Well, you already fixed your code, so why should we make the standard reasonable?" are bogus. A useful capability was removed, and replaced with a less capable set of features.] > However, the > program compiles and runs on lots of systems. Something like 99% of the Unix systems, I'd guess, since they all seem to use John Reiser's cpp -- it works, why rewrite it? -- {pyramid,ptsfa,amdahl,sun,ihnp4}!loptoad!gnu gnu@toad.com "Watch me change my world..." -- Liquid Theatre
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/22/88)
In article <4099@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes: >jbaker@ee.UCLA.EDU (Joe Baker) wrote: >> #define ctl(c) ('c'&037) >This change caused us to have to fix more than 50 files in Berkeley >Unix. We wouldn't have minded changing all the macro definitions -- we >know that substitution inside strings is a hack -- it's that we had to >change all the CALLERS too that bugged us! >[Responses of the form: "Well, you already fixed your code, so why should >we make the standard reasonable?" are bogus. A useful capability was removed, >and replaced with a less capable set of features.] First, this was NOT a change to the C language. K&R already guaranteed that macro substitution would not occur inside string and character literals (section 12.1 of Appendix A). I daresay there are more instances of C compilers currently that do not do such substitution than those that do; generally only compilers adapted from AT&T's source (the Reiser C preprocessor in particular) have this bug. X3J11, realizing that the facility was nevertheless useful, designed an alternative approach that was compatible with the K&R definition. To see what is wrong with the Reiser method, try the following program: #include <stdio.h> #define TEST(a,b) ((void)fprintf(stderr,"This is a test: 0x%x\n",(a)^(b))) main() { TEST(0xFF<<4,0xFFFF>>4); return 0; }
bts@sas.UUCP (Brian T. Schellenberger) (02/28/88)
In article <11879@brl-adm.ARPA> jbaker@ee.UCLA.EDU (Joe Baker) writes: |#define ctl(c) ('c'&037) |what is the Right Way to do this? (under dpANS) #define ctl(c) ((* #c) & 037)) -- --Brian. (Brian T. Schellenberger) ...!mcnc!rti!sas!bts DISCLAIMER: Whereas Brian Schellenberger (hereinafter "the party of the first
ado@elsie.UUCP (Arthur David Olson) (02/29/88)
> > #define ctl(c) ('c'&037) > > what is the Right Way to do this? (under dpANS) > > #define ctl(c) ((* #c) & 037)) Not if you plan to use code such as switch (value) { case ctl(a): ... -- ado@vax2.nlm.nih.gov ADO, VAX, and NIH are Ampex and DEC trademarks
fox@alice.marlow.reuters.co.uk (Paul Fox) (03/03/88)
In article <898@PT.CS.CMU.EDU> edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes: >> > #define ctl(c) ('c'&037) >> >... is not allowed in MSC5.0 >> >> Nor in ANSI C. > > Does this imply that a macro parameter will nolonger be expanded in >strings too? > >#define DEBUG_CALL(xxx) if ((xxx) != OK) { \ > (void) printf("xxx\n"); \ > (void) printf("%s %d\n\n",__FILE__,__LINE__);\ > clearline(); } >-- ANSI gets around this via the '#' and '##' operators -- available within the preprocessor phase only. As I read it # define CTRL(x) #x & 037 CTRL(A); gives: "A" & 037 # define CTRL(x) '##x##' & 037 CTRL(A); gives: 'A' & 037
kulik@xyzzy.UUCP (Al Kulik) (03/05/88)
In article <290@alice.marlow.reuters.co.uk> fox@alice.marlow.reuters.co.uk (Paul Fox) writes: >ANSI gets around this [macro argument substitution in string literals] via the >'#' and '##' operators -- available within the preprocessor phase only. As I >read it > ># define CTRL(x) #x & 037 > CTRL(A); > >gives: "A" & 037 > ># define CTRL(x) '##x##' & 037 > CTRL(A); ^^^^^^^ > >gives: 'A' & 037 > I don't know about this. It seems to me that this would result in '##x##' & 037. '##x##' is a character constant which is a preprocessor token; the preprocessor will not recognize the ##s within the token, they're just part of the constant. In the first case above, "A" & 037 results in the address of the literal "A" being ANDed bitwise with the constant 037, which may not be what you want. To obtain something like the second case: #define CTRL(x) #x[0] & 037. -- Al Kulik, Data General. Uucp: ...!mcnc!rti!xyzzy!kulik Arpa/Csnet: kulik@dg-rtp.DG.COM
mouse@mcgill-vision.UUCP (der Mouse) (03/10/88)
In article <7309@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes: > In article <4099@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes: >> jbaker@ee.UCLA.EDU (Joe Baker) wrote: >>> #define ctl(c) ('c'&037) >> This change caused us to have to fix more than 50 files in Berkeley >> Unix. [...A useful capability was removed, and replaced with a less >> capable set of features.] > First, this was NOT a change to the C language. K&R already > guaranteed that macro substitution would not occur inside string and > character literals (section 12.1 of Appendix A). So? Macro arguments aren't macros. I looked for a statement in K&R that said that Reiser behavior was forbidden and failed to find anything clear-cut. The statement in 12.1 of Appendix A says that "Text inside a string or a character constant is not subject to replacement.", but they don't make it clear whether they mean replacement of macros with their expansions or all replacement arising from the preprocessor. > I daresay there are more instances of C compilers currently that do > not do such substitution than those that do; [most that do are > derived from AT&T's Reiser cpp]. Are you sure? I would have guessed the other way. I have no idea where to look to obtain statistics to settle this; can anyone cite any reference to such numbers? > To see what is wrong with the Reiser method, try [...]: > #define TEST(a,b) ((void)fprintf(stderr,"This is a test: 0x%x\n",(a)^(b))) Yeah, and to see what's wrong with the ++ operator, try: main() { int i,j; i = 7; j = i++ + i++ + i++; printf("i = %d, j = %d\n",i,j); } The behavior exhibited by Reiser preprocessors is "wrong" only in that it isn't how you believe it ought to work. I see nothing wrong with it. The cited piece of K&R arguably supports you, but it arguably does not support you. And I claim that history supports me, because the Reiser cpp is closer to the original cpp, the one used back when K&R was written, than anything else around. (Or at least so I believe, but on trying I find I can't provide a source for this claim. Can anyone cite a source to support or demolish it?) der Mouse uucp: mouse@mcgill-vision.uucp arpa: mouse@larry.mcrcim.mcgill.edu
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/24/88)
In article <983@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse) writes: >The statement in 12.1 of Appendix A says that "Text inside a string or >a character constant is not subject to replacement.", but they don't >make it clear whether they mean replacement of macros with their >expansions or all replacement arising from the preprocessor. You're the first person I've encountered who doesn't take that sentence IN CONTEXT to mean what I said. Every AT&T compiler person I've consulted (which is several) have agreed that the Reiser CPP incorrectly implements this aspect of K&R. Certainly X3J11 thinks so.