Article View: comp.sys.atari.st
Article #37249A Lesson Learned
From: Charles S. [Chip] Roberson
Date: Mon, 20 Mar 1989 22:54
Date: Mon, 20 Mar 1989 22:54
75 lines
3771 bytes
3771 bytes
Greetings fellow psycho-programmers! Well, I just learned a lesson today
and I thought I pass it on to any others who haven't learned this, yet.
It only blew a day and a half of my time.
Below is a pretty slick fprintf() statement from some of the UUPC/ST code
munged enough to simplify this example. Looking at it, I was sure that it
should work. I mean, why not? It's pretty straight forward -- pass
fprintf() 3 arguments: stderr, the appropriate format string, and finally
the desired value to print. Then once the value is passed, increment.
Right? Wrong!
--------------------------------------------------------------------------
#include <stdio.h>
#include <ctype.h>
unsigned char charlie = 'I';
void oops() {
unsigned char *cp;
cp = charlie;
fprintf( stderr, isprint(*cp)? "[%c]":"[%02x]", *cp++ );
}
--------------------------------------------------------------------------
MWC passes parameters in reverse order. That means that the "*cp++"
gets evaluated BEFORE the "isprint(*cp)..." stuff. So, everytime
fprintf will get passed the approprate character, but isprint is going
to look at whatever is in the next data location. [In my case that was
usually garbage in an unused portion of a character buffer!]
For those of you who need to see the nasty stuff, here is a segment of the
MWC assembly code. It should explain everything. Especially, note the
lines that I marked with an '*'. [Thanks to MWC's db pgm!]
--------------------------------------------------------------------------
movea.l -8(a6), a0 ;; move *cp into a0 for passing to fprintf()
* addq.l $1, -8(a6) ;; increment cp as specified in fprintf arg
clr.w d0 ;; clean out cruft in d0
move.b (a0), d0 ;; load value destined for passing to fprintf()
move d0, -(a7) ;; push it on the stack
* movea.l -8(a6), a0 ;; move *cp into a0 for isprint() check
clr.w d0 ;; clean out some more cruft
move.b (a0), d0 ;; stash *cp in d0 for testing
swap.w d0 ;; toss it into the upper word
clr.w d0 ;; clean out the lower word
swap.w d0 ;; move *cp value back into lower word
movea.l d0, a0 ;; prep for isprint()
adda.l $_ctype_+1, a0 ;; mung it a little
move.b (a0), d0 ;; mung it some more
ext.w d0 ;; ok, it's munged
andi $171, d0 ;; does it map to printable set?
beq.s L10006 ;; nope, go print it in hex
pea L37 ;; yes, use character format in fprintf
bra.s L10007 ;; go finish pushing args
L10006:
pea L38 ;; use, hexidecimal format in fprintf
L10007:
pea _stderr_ ;; finally, pass 1st arg to fprintf
jsr fprintf_ ;; go do it!
--------------------------------------------------------------------------
The moral of this story? Well, as my Theory of Prog. Lang prof would
say, "That's just another insecurity of C!"; to which he would add
"Ada is a much better language." Well, I guess I would say
"Hey! Be careful out there."
Seriously, this is one side-effect that I hadn't thought about. How
do other ST compiler's pass their parameters? So much for portability,
eh? Does anybody know how the dpANS standard would affect this, if at
all? I can't seem to remember anything in it that would.
oh well.
cheers,
-c
Technical Details
Message-ID:
<8903202254.AA00303@icase.edu>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!ICASE.EDU!csrobeShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!ICASE.EDU!csrobe From: csrobe@ICASE.EDU (Charles S. [Chip] Roberson) Newsgroups: comp.sys.atari.st Subject: A Lesson Learned Message-ID: <8903202254.AA00303@icase.edu> Date: 20 Mar 89 22:54:30 GMT Sender: daemon@ucbvax.BERKELEY.EDU Organization: The Internet Lines: 75