shin@sgtp.apple.juice (Shinichirou Sugou) (04/25/89)
Dear FSF people: I think it maybe bug, but not sure which causes this bug, gdb or g++. For the present, I report to 'gdb'. My system is, gdb-3.1, g++-1.32, Sun3/60 with OS3.4. Whole program is appended at the last of this letter as shar-format. (0) Please use Sun if possible because this program uses special malloc.o file which is pecurial to Sun. Also, please use GNU's make. Sun's make will result in Makefile error. (1) Make a directory and rebuild whole sources. You know the way how to rebuild the program from shar-file, don't you? :-) (2) Type 'make'. Finally, the object named 'p' will be produced. (3) Type 'gdb p' to invoke gdb. (4) Set break point at grafPort::getPortRect by typing 'b grafPort::getPortRect'. (5) Run the program. (6) This function returns the 'portRect' (see grafPort.h and rect.h about its definition), its value must be... portRect = {left = 0, top = 0, right = 80, bottom = 24} (7) Type 'finish' to get what is retuned. You will see the incorrect return value, Value returned is $2 = {left = 0, top = 152880, right = 80, bottom = 0} What is wrong? Yours sincerely. CAUTION: Reply-command supplied by your mail system may NOT generate my address correctly. Please use the following address instead. shin%sgtp.apple.juice%lkbreth.foretune.junet@uunet.uu.net --- Shinichirou Sugou shin%sgtp.apple.juice%lkbreth.foretune.junet@uunet.uu.net Program sources (as shar format) follows... #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # ch.cc # terminal.cc # grafPort.cc # charMap.cc # bitMatrix.cc # misc.cc # region.cc # point.cc # rect.cc # quickDraw.cc # ch.h # terminal.h # grafPort.h # charMap.h # bitMatrix.h # misc.h # region.h # point.h # rect.h # quickDraw.h # global.h # Makefile # .gdbinit # dlist # This archive created: Tue Apr 25 14:16:34 1989 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'ch.cc' then echo shar: "will not over-write existing file 'ch.cc'" else cat << \SHAR_EOF > 'ch.cc' #include <stream.h> #include <ctype.h> #include "global.h" #include "quickDraw.h" #include "ch.h" /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ void ch::setOrdinary() /* Clear all shape flag FALSE and set it ordinary character. */ { reverse = underline = blink = doubleBright = halfBright = FALSE; } void ch::setC(uchar c1) { c = c1; } uchar ch::getC() { return c; } bool ch::isReverse() { return reverse; } bool ch::isUnderline() { return underline; } bool ch::isBlink() { return blink; } bool ch::isDoubleBright() { return doubleBright; } bool ch::isHalfBright() { return halfBright; } bool ch::isOrdinary() { return !(this->isReverse() || this->isUnderline() || this->isBlink() || this->isDoubleBright() || this->isHalfBright()); } void ch::setReverse(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); reverse = v; } void ch::setUnderline(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); underline = v; } void ch::setBlink(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); blink = v; } void ch::setDoubleBright(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); doubleBright = v; } void ch::setHalfBright(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); halfBright = v; } ch::ch(uchar c1) { c = c1; reverse = underline = blink = doubleBright = halfBright = FALSE; } bool ch::isAscii() /* Return TRUE if character is ordinary ascii character (not kanji or hiragana). */ { return isascii(c); } void ch::fprint(ostream& s) /* debugging tool */ { s << ((c != 0) ? form("%c", c) : form("^@")); char *shape; if (this->isOrdinary()) shape = "ordinary"; else if (this->isReverse()) shape = "reverse"; else if (this->isUnderline()) shape = "underline"; else if (this->isBlink()) shape = "blink"; else if (this->isDoubleBright()) shape = "doubleBright"; else if (this->isHalfBright()) shape = "halfBright"; else fatal("can't happen"); if (this->isAscii()) s << form("(%s)", shape); } ostream& operator<<(ostream& s, ch c) /* debugging tool */ { c.fprint(s); return s; } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'terminal.cc' then echo shar: "will not over-write existing file 'terminal.cc'" else cat << \SHAR_EOF > 'terminal.cc' #include <stream.h> #include <sgtty.h> #include "global.h" #include "quickDraw.h" static int ScrWidth, ScrHeight; char PC; /* for tputs() */ char *BC; /* for tgoto */ char *UP; short ospeed; /* for tputs() */ static const int speed[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400 }; /**/ /* Private -top- */ /**/ static fv initScreenSize(int *widthp, int *heightp) /* OK ERROR */ { *widthp = tgetnum("co"); *heightp = tgetnum("li"); return (*widthp >0 && *heightp >0) ? OK : ERROR; } static void initBaudRate(short *ospeedp) { sgttyb sg; ioctl(1, TIOCGETP, (char *)&sg); if (sg.sg_ospeed >= sizeof(speed)/sizeof(speed[0])) /* over the vector range */ fatal("termcap can't get valid baud-rate"); *ospeedp = short(speed[sg.sg_ospeed]); } /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ getScrHeight() { return ScrHeight; } getScrWidth() { return ScrWidth; } void initTermData() { static bool firstTime = TRUE; if (firstTime) firstTime = FALSE; else fatal("don't call initTermData() twice"); char *termType = getenv("TERM"); if (termType == NIL) fatal("specify a terminal type with 'setenv TERM <yourtype>'"); /* get terminal type */ static char termBuf[2048]; int success = tgetent(termBuf, termType); if (success < 0) fatal("could not access the termcap data base"); else if (success == 0) fatal("terminal type '%s' is not defined", termType); /* extract information that termcap functions use */ static char *buf; buf = new char[strlen(termBuf)]; char *tmp = tgetstr("pc", &buf); PC = tmp ? *tmp : 0; BC = tgetstr("le", &buf); UP = tgetstr("up", &buf); initBaudRate(&ospeed); /* extract various terminal information */ if (initScreenSize(&ScrWidth, &ScrHeight) != OK) fatal("terminal type '%s' is not powerful", termType); } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ extern fv initScreenSize(int*, int*); SHAR_EOF fi if test -f 'grafPort.cc' then echo shar: "will not over-write existing file 'grafPort.cc'" else cat << \SHAR_EOF > 'grafPort.cc' #include <stream.h> #include "global.h" #include "quickDraw.h" #include "point.h" #include "rect.h" #include "bitMatrix.h" #include "region.h" #include "ch.h" #include "charMap.h" #include "grafPort.h" /* Can't define 'static global' as g++ bug. */ pattern White; pattern Black; pattern Gray; pattern LtGray; pattern DkGray; cursor Arrow; ch *Screen; /* screen bit image */ charMap ScreenBits; long RandSeed; /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ point grafPort::globalToLocal(const point pt) /* grafPort::globalToLocal takes a point expressed in global coordinates (with the top left corner of the charMap as coordinate (0,0)) and converts it into the local coordinates of 'my' grafPort. The global point can be obtained with the grafPort::localToGlobal call. */ { point res = pt; res.add(portBits.getBounds().getTopLeft()); return res; } point grafPort::localToGlobal(const point pt) /* Convert the given point from 'my' grafPort's local coordinate system into a global coordinate system with the origin (0,0) at the top left corner of the port's bit image (such as the screen). This global point can then be compared to other global points, or be changed into the local coordinates of another grafPort. Since a rectangle is defined by two points, you can convert a rectangle into global coordinates by performing two LocalToGlobal calls. You can also convert a rectangle, region, or polygon into global coordinates by calling rect::offset, region::offset, or poly::offset (the last is not implemented yet). */ { point res = pt; res.sub(portBits.getBounds().getTopLeft()); return res; } void grafPort::init() /* Reinitialize the fields of the grafPort. Mac's initPort() does the same thing, and also it make the argument the current port. But because N-window's style is OOPS, the image 'current port' is not supported. */ { grafPort tmp; *this = tmp; } void grafPort::setPortBits(charMap cm) /* Set portBits of 'me' (note that this function deffers from Mac as Mac's function changes the device of 'thePort')to any reviously defined charMap. This allows you to perform all normal drawing and calculations on a buffer other than the screen -- for example, a 640-by-7 output buffer for a C. Itoh printer, or a small off-screen image for later "stamping" onto the screen. Remember to prepare all fields of the charMap before you call grafPort::setPortBits(). */ { portBits = cm; } void grafPort::setDevice(int dv) /* Set device of 'me' (note that this function deffers from Mac as Mac's function changes the device of 'thePort'), which identifies the logical output device for 'me'. The Font Manager uses this information. The initial device number is 0, which represents the screen. */ { device = dv; } void grafPort::portSize(uint w, uint h) /* Change the size of portRect. THIS DOES NOT AFFECT THE SCREEN; it merely changes the size of the "active area" of 'me'. The top left corner of the portRect remains at its same location; the width and height of the portRect are set to the given width and height. In other words, this function moves the bottom right corner of the portRect to a position relative to the top left corner. grafPort::portSize() does not change the clipRgn or the visRgn, nor does it affect the local coordinate system of the grafPort: it changes only the portRect's width and height. Remember that all drawing occurs only in the intersection of the portBits.bounds and the portRect, clipped to the visRgn and the clipRgn. */ { portRect.set(portRect.getLeft(), portRect.getTop(), portRect.getLeft()+w, portRect.getTop()+h); } grafPort::~grafPort() { /* empty body */ } grafPort::grafPort(const grafPort& g) { if (this == &g) fatal("syntax error"); *this = g; } void grafPort::operator=(const grafPort& g) { if (this == &g) /* beware of g=g */ return; device = g.device; portBits = g.portBits; portRect = g.portRect; visRgn = g.visRgn; clipRgn = g.clipRgn; bkPat = g.bkPat; fillPat = g.fillPat; pnLoc = g.pnLoc; pnSize = g.pnSize; pnMode = g.pnMode; pnPat = g.pnPat; pnVis = g.pnVis; txFont = g.txFont; txFace = g.txFace; txMode = g.txMode; txSize = g.txSize; spExtra = g.spExtra; fgColor = g.fgColor; bkColor = g.bkColor; colrbit = g.colrbit; patStretch = g.patStretch; picSave = g.picSave; rgnSave = g.rgnSave; polySave = g.polySave; grafProcs = g.grafProcs; } grafPort::grafPort() { device = 0; /* screen */ portBits = ScreenBits; portRect = ScreenBits.getBounds(); visRgn.rects(ScreenBits.getBounds()); clipRgn.setRect(-300, -300, 300, 300); /* smaller region than Mac library */ // clipRgn.setRect(-30, -30, 30, 30); /* smaller region than Mac library */ bkPat = White; fillPat = Black; pnLoc.set(0, 0); pnSize.set(1, 1); pnMode = PatCopy; pnPat = Black; pnVis = 0; txFont = 0; txFace = NORMAL; txMode = SrcOr; txSize = 0; spExtra = 0; fgColor = BlackColor; bkColor = WhiteColor; colrbit = 0; patStretch = 0; picSave = NIL; rgnSave = NIL; polySave = NIL; grafProcs = NIL; } void initGraf() /* Call initGraf() once and only once at the beginning of your program to initialize QuickDraw. Also, you must call initTermData() preceding initGraf() because two functions in initTermData(), getScrWidth() and getScrHeight(), are used. It initializes the QuickDraw global variables llistd below. ------------------------------------------------------------------------ variable type initial-setting ------------------------------------------------------------------------ White pattern all-white pattern Black pattern all-black pattern Gray pattern 50% gray pattern LtGray pattern 25% gray pattern DkGray pattern 75% gray pattern Arrow cursor inversed space (black square) Screen ch* screen bit image ScreenBits charMap screen, (0, 0, getScrWidth(), getScrHeight()) RandSeed long 1 */ { static bool firstTime = TRUE; if (firstTime) firstTime = FALSE; else fatal("don't call initGraf() twice"); White.setC(SPACE); White.setOrdinary(); Black.setC(SPACE); Black.resetShape(); Black.setReverse(TRUE); Gray.setC(SPACE); Gray.resetShape(); Gray.setReverse(TRUE); /* no suitable char! */ LtGray.setC(SPACE); LtGray.resetShape(); LtGray.setReverse(TRUE); /* no suitable char! */ DkGray.setC(SPACE); DkGray.resetShape(); DkGray.setReverse(TRUE); /* no suitable char! */ Arrow.setC(CARET); Arrow.setOrdinary(); /* no suitable char! */ assert((getScrWidth() > 0 && getScrHeight() > 0), "invoke initTermData()"); Screen = new ch[getScrWidth() * getScrHeight()]; ScreenBits = charMap(Screen, getScrWidth(), rect(0,0,getScrWidth(), getScrHeight())); RandSeed = 1; } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ void grafPort::movePortTo(int leftGlobal, int topGlobal) /* Change the position of my grafPort's portRect. THIS DOES NOT AFFECT THE SCREEN; it merely changes the location at which subsequent drawing inside the port will appear. The leftGlobal and topGlobal parameters set the distance between the top left corner of portBits.bounds and the top left corner of the new portRect. For example, g.movePortTo(256,171); will move the top left corner of the portRect to the center of the screen (if portBits is the Macintosh screen) regardless of the local coordinate system. Like PortSize, movePortTo does not change the clipRgn or the visRgn, nor does it affect the local coordinate system of the grafPort. */ { point localPt = this->globalToLocal(point(leftGlobal, topGlobal)); portRect.moveTo(localPt.getH(), localPt.getV()); } mainn() /* grafPort::movePortTo() Use gdb to examine the portRect's coordinates */ { malloc_debug(2); initTermData(); initGraf(); grafPort g1; while (1) { point pt; cin >> pt; g1.movePortTo(pt.getH(), pt.getV()); cout << g1.getPortBits().getBounds() NLN; cout << g1.getPortRect() NLN NLN; } } main() /* grafPort::getPortRect() */ { malloc_debug(2); initTermData(); initGraf(); grafPort g1; g1.getPortRect(); cout << "end" NLN; } SHAR_EOF fi if test -f 'charMap.cc' then echo shar: "will not over-write existing file 'charMap.cc'" else cat << \SHAR_EOF > 'charMap.cc' #include <stream.h> #include "global.h" #include "quickDraw.h" #include "point.h" #include "rect.h" #include "bitMatrix.h" #include "region.h" #include "ch.h" #include "charMap.h" /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ charMap::~charMap() { /* empty body */ } void charMap::operator=(const charMap& cm) { if (this == &cm) /* beware of cm = cm */ return; baseAddr = cm.baseAddr; rowBytes = cm.rowBytes; bounds = cm.bounds; updateRgn = cm.updateRgn; } charMap::charMap(const charMap& cm) { if (this == &cm) fatal("syntax error"); baseAddr = cm.baseAddr; rowBytes = cm.rowBytes; bounds = cm.bounds; updateRgn = cm.updateRgn; } charMap::charMap(ch *addr, int row, rect bnd) /* It is user's responsibility to prepare suffifient character-image (bit-image) area. 'ch' vector size of at least 'row*bnd.getHeight()' is needed. 'updateRgn' is initialized to the same size of 'bounds'. */ { assert((addr != NIL && row >= 0), "illegal argument"); assert(row >= bnd.getWidth(), "too large bounds"); baseAddr = addr; rowBytes = row; bounds = bnd; updateRgn.rects(bounds); } charMap::charMap() /* This constructor assigns dummy value. Don't use vanilla. */ { baseAddr = NIL; rowBytes = 0; } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'bitMatrix.cc' then echo shar: "will not over-write existing file 'bitMatrix.cc'" else cat << \SHAR_EOF > 'bitMatrix.cc' #include <stream.h> #include "global.h" #include "quickDraw.h" #include "bitMatrix.h" #include "misc.h" /**/ /* Global -top- */ /**/ bool bitMatrix::colBitIsClear(uint col) /* Return TRUE if all the bits of specified column (scanning vertically) are CLEAR. The empty matrix always returns TRUE. */ { assert((col == 0 || col < width), "lllegal argument"); for (uint i = 0; i < height; i++) if (get(col, i) == SET) return FALSE; return TRUE; } bool bitMatrix::lineBitIsClear(uint line) /* Return TRUE if all the bits of specified line (scanning horizontally) are CLEAR. The empty matrix always returns TRUE. */ { assert((line == 0 || line < height), "lllegal argument"); for (uint i = 0; i < width; i++) if (get(i, line) == SET) return FALSE; return TRUE; } bool bitMatrix::equal(bitMatrix bm) /* Return TRUE if two bitMatrix 'me' and 'bm' are equal or FALSE if not. The two bitMatrixs must have identical sizes and bit status to be considered to be equal. */ { if (width != bm.width || height != bm.height) return FALSE; for (uint w = 0; w < width; w++) for (uint h = 0; h < height; h++) if (mtrx[w][h] != bm.mtrx[w][h]) return FALSE; return TRUE; } istream& operator>>(istream& s, bitMatrix& bm) /* "3 5" will bm.resize(3,5). */ /* For debugging. */ { cout << "bitMatrix size: h v: "; int h = 0, v = 0; s >> h >> v; if (s) bm.resize(h, v); cout << "bit contents: "; for (uint col = 0; col < v; col++) for (uint line = 0; line < h; line++) { int bit; cin >> bit; bit ? bm.set(line, col) : bm.clear(line, col); } return s; } ostream& operator<<(ostream& s, const bitMatrix& m) /* For debugging. */ { return m.fprint(s); } void bitMatrix::print() /* For debugging. */ { if (width == 0 && height == 0) cout << "empty bitMatrix\n"; else for (uint j = 0; j < height; j++) { for (uint i = 0; i < width; i++) cout << mtrx[i][j]; cout << "\n"; } } ostream& bitMatrix::fprint(ostream& s) /* For debugging. */ { if (width == 0 && height == 0) s << "empty bitMatrix\n"; else for (uint j = 0; j < height; j++) { for (uint i = 0; i < width; i++) s << mtrx[i][j]; s << "\n"; } return s; } bitMatrix::bitMatrix(uint w, uint h, bit val) /* Zero sized matrix is also legal. */ { assert((val == CLEAR || val == SET), "Illegal val"); width = w; height = h; mtrx = new bit*[width]; for (uint i = 0; i < width; i++) mtrx[i] = new bit[height]; (val == SET) ? this->set() : this->clear(); } void bitMatrix::resize(uint w, uint h, bit val) { assert((val == CLEAR || val == SET), "Illegal val"); if (width != w || height != h) { /* de-allocate free space */ for (uint i = 0; i < width; i++) delete mtrx[i]; delete mtrx; /* re-initialize; reallocate */ width = w; height = h; mtrx = new bit*[width]; for (i = 0; i < width; i++) mtrx[i] = new bit[height]; } (val == SET) ? this->set() : this->clear(); } bit bitMatrix::get(uint col, uint line) /* Return the bit of 'col/line'. */ { if (col >= width || line >= height) fatal("illegal coordinate"); return mtrx[col][line]; } void bitMatrix::set(uint col, uint line) /* Set bit of 'col/line'. */ { if (col >= width || line >= height) fatal("illegal coordinate"); mtrx[col][line] = SET; } void bitMatrix::clear(uint col, uint line) /* Clear bit of 'col/line'. */ { if (col >= width || line >= height) fatal("illegal coordinate"); mtrx[col][line] = CLEAR; } void bitMatrix::set() /* Set all bits. */ { for (uint i = 0; i < width; i++) for (uint j = 0; j < height; j++) mtrx[i][j] = SET; } void bitMatrix::clear() /* Clear all bits. */ { for (uint i = 0; i < width; i++) for (uint j = 0; j < height; j++) mtrx[i][j] = CLEAR; } void bitMatrix::operator=(bitMatrix& m) { if (this == &m) /* beware of m=m */ return; if (width != m.width || height != m.height) fatal("can't assign different size matrix"); for (uint i = 0; i < width; i++) for (uint j = 0; j < height; j++) mtrx[i][j] = m.mtrx[i][j]; } bitMatrix::bitMatrix(const bitMatrix& m) { if (this == &m) fatal("syntax error"); width = m.width; height =m.height; mtrx = new bit*[width]; for (uint i = 0; i < width; i++) mtrx[i] = new bit[height]; *this = m; /* copy bits */ } bitMatrix::~bitMatrix() { for (uint i = 0; i < width; i++) delete mtrx[i]; delete mtrx; } /**/ /* Global -bottom- */ /**/ /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'misc.cc' then echo shar: "will not over-write existing file 'misc.cc'" else cat << \SHAR_EOF > 'misc.cc' #include <stream.h> #include <stdio.h> #include <stdarg.h> #include "global.h" #include "quickDraw.h" const MaxCoordinate = 32767; const MinCoordinate = -32768; /**/ /* Global -top- */ /**/ void fatal(char *fmt...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "fatal error: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); abort(); } bool validCoordinate(int i) /* Return TRUE if 'i' is valid. coordinate valid range is between 'MinCoordinate' and 'MaxCoordinate' inclusive. */ { return MinCoordinate <= i && i <= MaxCoordinate; } bool emptyRect(int left, int top, int right, int bottom) /* Return TRUE if the specified rectangle is empty. */ { assert((validCoordinate(left) && validCoordinate(top) && validCoordinate(right) && validCoordinate(bottom)), "illegal argument"); return bottom <= top || right <= left; } bit and(bit a, bit b) /* Return the and of 'a' and 'b'. */ { assert(((a == SET || a == CLEAR) && (b == SET || b == CLEAR)), "illegal argument"); return (a == SET && b == SET) ? SET : CLEAR; } bit or(bit a, bit b) /* Return the or of 'a' and 'b'. */ { assert(((a == SET || a == CLEAR) && (b == SET || b == CLEAR)), "illegal argument"); return (a == SET || b == SET) ? SET : CLEAR; } /**/ /* Global -bottom- */ /**/ /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'region.cc' then echo shar: "will not over-write existing file 'region.cc'" else cat << \SHAR_EOF > 'region.cc' #include <stream.h> #include "global.h" #include "quickDraw.h" #include "misc.h" #include "point.h" #include "rect.h" #include "bitMatrix.h" #include "region.h" /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ region::~region() { /* empty body */ } void region::sect(region a, region b) /* Calculate the intersection of two regions and places the intersection in 'me'. The dstRgn ('me') can be one of the source regions, if desired. If the regions do not intersect, or one of the regions is empty, the destination is set to the empty region (0,0,0,0). */ { bBox.sect(a.bBox, b.bBox); uint w = bBox.getWidth(), h = bBox.getHeight(); bMap.resize(w, h); uint dha = bBox.getLeft() - a.bBox.getLeft(); /* obscure */ uint dva = bBox.getTop() - a.bBox.getTop(); /* obscure */ uint dhb = bBox.getLeft() - b.bBox.getLeft(); /* obscure */ uint dvb = bBox.getTop() - b.bBox.getTop(); /* obscure */ for (int col = 0; col < w; col++) for (int line = 0; line < h; line++) (and(a.bMap.get(col+dha, line+dva), b.bMap.get(col+dhb, line+dvb)) == SET) ? bMap.set(col, line) : bMap.clear(col, line); this->compress(); } void region::unions(region a, region b) /* Calculate the union of two rgions and places the union in 'me'. The dstRgn 'me' can be one of the source regions, if desired. If both regions are empty, the destination 'me' is set to the empty region (0,0,0,0). */ { bBox.unions(a.bBox, b.bBox); bMap.resize(bBox.getWidth(), bBox.getHeight(), CLEAR); /* transfer bits in 'a' as or-mode */ uint dh = a.bBox.getLeft() - bBox.getLeft(); /* obscure */ uint dv = a.bBox.getTop() - bBox.getTop(); /* obscure */ uint w = a.bBox.getWidth(); uint h = a.bBox.getHeight(); for (int col = 0; col < w; col++) for (int line = 0; line < h; line++) (or(bMap.get(col+dh, line+dv), a.bMap.get(col, line)) == SET) ? bMap.set(col+dh, line+dv) : bMap.clear(col+dh, line+dv); /* transfer bits in 'b' as or-mode */ dh = b.bBox.getLeft() - bBox.getLeft(); /* obscure */ dv = b.bBox.getTop() - bBox.getTop(); /* obscure */ w = b.bBox.getWidth(); h = b.bBox.getHeight(); for (col = 0; col < w; col++) for (line = 0; line < h; line++) (or(bMap.get(col+dh, line+dv), b.bMap.get(col, line)) == SET) ? bMap.set(col+dh, line+dv) : bMap.clear(col+dh, line+dv); /* settle */ this->compress(); } void region::diff(region a, region b) /* Subtract srcRgn b from a and place the dirrerence in 'me'. The 'me' can be one of the source regions, if desired. If the first source region is empty, the destination is set to the empty region (0,0,0,0). */ { /* it suffices to re-calculate bits of 'a' restricted to the area of sRect. calculation table follows... -------------+--------- a b | result -------------+--------- SET SET | CLEAR SET CLEAR | SET CLEAR SET | CLEAR CLEAR CLEAR | CLEAR -------------+--------- */ if (a == b) { /* special case */ this->setEmpty(); return; } *this = a; rect sRect; sRect.sect(a.bBox, b.bBox); uint w = sRect.getWidth(); uint h = sRect.getHeight(); uint dha = sRect.getLeft() - a.bBox.getLeft(); uint dva = sRect.getTop() - a.bBox.getTop(); uint dhb = sRect.getLeft() - b.bBox.getLeft(); uint dvb = sRect.getTop() - b.bBox.getTop(); for (uint col = 0; col < w; col++) for (uint line = 0; line < h; line++) if (a.bMap.get(col+dha, line+dva) == SET && b.bMap.get(col+dhb, line+dvb) == SET) bMap.clear(col+dha, line+dva); this->compress(); } void region::xor(region a, region b) /* Calculate the difference between the union and the intersection of two regions and places the result in 'me'. The dstRgn 'me' can be one of the source regions, if desired. If the regions are coincident, the destination is set to the empty region (0,0,0,0). */ { region unions; unions.unions(a, b); region sect; sect.sect(a, b); this->diff(unions, sect); } void region::inset(int dh, int dv) /* Shrink or expand the region. All points on the resion boundary are moved inwards a distance of dv vertically and dh horizontally; if dh or dv is negative, the points are moved outwards in that direction. region::inset() leaves the region "centered" at the same position, but moves the outline in (for positive values of dh and dv) or out (for negative values of dh and dv). region::inset() of a rectangular region works just like rect::inset(). */ { region tmp = *this; /* resize */ this->bBox.inset(dh, dv); this->bMap.resize(bBox.getWidth(), bBox.getHeight(), SET); /* clear the bit within intersection rectangle 'r' where original's bit was clear */ rect r; r.sect(tmp.bBox, bBox); uint w = r.getWidth(); uint h = r.getHeight(); for (uint i = 0; i < w; i++) for (uint j = 0; j < h; j++) if (tmp.bMap.get(i+max(dh,0), j+max(dv,0)) == CLEAR) /* obscure */ bMap.clear(i-min(dh,0), j-min(dv,0)); /* obscure */ this->compress(); } void region::compress() /* Compress region data. Suppose the region is defined like this... (0, 0, 6, 6) 000000 001100 001100 001100 001100 000000 As stripping outerward zeroz doesn't change the region object, region::compress() will redefine the region data like this... (2, 1, 3, 4) 11 11 11 11 */ { if (this->empty()) { if (!bBox.empty()) this->setEmpty(); return; } else if (bMap.lineBitIsClear(0) && bMap.lineBitIsClear(bBox.getHeight() - 1)) { this->inset(0, 1); this->compress(); } else if (bMap.colBitIsClear(0) && bMap.colBitIsClear(bBox.getWidth() - 1)) { this->inset(1, 0); this->compress(); } } istream& operator>>(istream& s, region& rgn) /* For debugging. */ { s >> rgn.bBox; rgn.bMap.resize(rgn.bBox.getWidth(), rgn.bBox.getHeight()); cout << form("bit contents (hor = %u ver = %u): \n", rgn.bBox.getWidth(), rgn.bBox.getHeight()); for (uint col = 0; col < rgn.bBox.getHeight(); col++) for (uint line = 0; line < rgn.bBox.getWidth(); line++) { int bit; cin >> bit; bit ? rgn.bMap.set(line, col) : rgn.bMap.clear(line, col); } return s; } bool region::rectIn(rect r) /* Check whether the given rectangle intersects 'me', and return TRUE if the intersection encloses at least one bit or FALSE if not. */ { region rgn; rgn.rects(r); rgn.sect(rgn, *this); return !rgn.empty(); } bool region::empty() /* Return TRUE if the region is an empty region or FALSE if not. Some of the circumstances in which an empty region can be created are: a region::new() call; a region::copy() of an empty region; a region::setRect() or region::rect() with an empty rectangle as an argument; region::open(); region::offset() of an empty region; region::inset() with an empty region or too large an inset; region::sect() of nonintersecting regions; region::unions() of two empty regions; and region::diff() or region::xor() of two identical or nonintersecting regions. */ { uint w = bBox.getWidth(); uint h = bBox.getHeight(); for (uint i = 0; i < w; i++) for (uint j = 0; j < h; j++) if (bMap.get(i, j) == SET) return FALSE; return TRUE; } bool region::ptIn(point pt) /* Check whether the pixel below and to the right of the given coordinate point is within 'me', and return TRUE if so or FALSE if not. */ { return bBox.ptIn(pt) && bMap.get(pt.getH(), pt.getV()) == SET; } bool operator==(region a, region b) { return a.equal(b); } bool region::equal(region rgn) /* Compare the two regions, 'me' and 'rgn', and return TRUE if they are equal or FALSE if not. The two regions must have identical sizes, shapes, and locations to be considered equal. Any two empty regions are always equal. */ { return bBox.equal(rgn.bBox) && bMap.equal(rgn.bMap); } void region::print() /* For debugging. */ { cout << this->bBox NLN << this->bMap; } ostream& region::fprint(ostream& s) /* For debugging. */ { return s << this->bBox NLN << this->bMap; } ostream& operator<<(ostream& s, const region& rgn) /* For debugging. */ { return rgn.fprint(s); } void region::offset(int dh, int dv) /* Move the region on the coordinate plane, a distance of dh horizontally and dv vertically. This does not affect the screen unless you subsequently call a routine to draw the region. If dh and dv are positive, the movement is to the right and down; if either is negative, the corresponding movement is in the opposite direction. The region retain its size and shape. */ { bBox.offset(dh, dv); } void region::rects(rect r) /* Destroys the previous structure, then set the new structure to the rectangle specified by 'r'. This is operationally synonymous with region::setRect(), except the input rectangle is defined by a rectangle rather than by four boundary coordinates. */ { this->setRect(r.getLeft(), r.getTop(), r.getRight(), r.getBottom()); } void region::setEmpty() /* Destroy the previous structure, then set 'me' to the empty region (0,0,0,0). */ { this->setRect(0,0,0,0); } void region::copy(region rgn) /* Copy the mathematical structure of 'rgn'. */ { *this = rgn; } void region::operator=(const region& rgn) { if (this == &rgn) /* beware of rgn=rgn */ return; if (bBox.getWidth() != rgn.bBox.getWidth() || bBox.getHeight() != rgn.bBox.getHeight()) bMap.resize(rgn.bBox.getWidth(), rgn.bBox.getHeight()); bBox = rgn.bBox; bMap = rgn.bMap; } region::region(const region& rgn) : bBox(0, 0, 0, 0), bMap(0, 0, SET) { if (this == &rgn) fatal("syntax error"); bBox = rgn.bBox; bMap.resize(rgn.bMap.getWidth(), rgn.bMap.getHeight()); bMap = rgn.bMap; } void region::setRect(int left, int top, int right, int bottom) /* Destroy the previous structure of 'me', then sets the the new structure to the rectangle specified by left, top, right, and bottom. If the specified rectangle is empty (i.e., left>=right or top>=bottom), the rgion is set to the empty region (0,0,0,0). */ { assert((validCoordinate(left) && validCoordinate(top) && validCoordinate(right) && validCoordinate(bottom)), "illegal argument"); if (emptyRect(left, top, right, bottom)) left = top = right = bottom = 0; bBox.set(left, top, right, bottom); bMap.resize(right-left, bottom-top, SET); } region::region() : bBox(0, 0, 0, 0), bMap(0, 0, SET) /* Create the empty region (0, 0, 0, 0). This function corresponds to NewRgn() in Mac. */ { /* empty body */ } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'point.cc' then echo shar: "will not over-write existing file 'point.cc'" else cat << \SHAR_EOF > 'point.cc' #include <stream.h> #include "global.h" #include "quickDraw.h" #include "point.h" #include "misc.h" /**/ /* Global -top- */ /**/ point::point() { h = v = 0; } point::point(int hc, int vc) { assert((validCoordinate(hc) && validCoordinate(vc)), "Illegal argument"); h = hc; v = vc; } istream& operator>>(istream& s, point& p) /* "3 5" will p.set(3,5). */ { cout << "point: h v: "; int h = 0, v = 0; s >> h >> v; if (s) p.set(h, v); return s; } ostream& operator<<(ostream& s, point p) { return s << form("(%d,%d)", p.h, p.v); } bool point::ok() { return validCoordinate(h) && validCoordinate(v); } void point::add(point pt) /* Add the coordinates of 'pt'. */ { assert(pt.ok(), "Illegal argument"); h += pt.h; v += pt.v; assert(this->ok(), "Illegal result"); } void point::sub(point pt) /* Subtract the coordinates of 'pt'. */ { assert(pt.ok(), "Illegal argument"); h -= pt.h; v -= pt.v; assert(this->ok(), "Illegal result"); } void point::set(int hc, int vc) /* Assign two integer coordinates. */ { assert((validCoordinate(hc) && validCoordinate(vc)), "Illegal argument"); h = hc; v = vc; } bool point::equal(point pt) /* Compare the 'pt' with 'this' and return TRUE if they are equal or FALSE if not. */ { assert(pt.ok(), "Illegal argument"); return h == pt.h && v == pt.v; } /**/ /* Global -bottom- */ /**/ /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'rect.cc' then echo shar: "will not over-write existing file 'rect.cc'" else cat << \SHAR_EOF > 'rect.cc' #include <stream.h> #include "global.h" #include "quickDraw.h" #include "point.h" #include "rect.h" #include "misc.h" /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ void rect::moveTo(int left, int top) /* Move the top left cornet to the point (left,top). This function merely moves the rect posion, but not its shape. */ { this->offset(left - this->getLeft(), top - this->getTop()); } bool rect::sect(rect a, rect b) /* Calculate the rectangle that is the intersection of the two input input rectangles, and returns TRUE if they indeed intersect or FALSE if they do not. Rectangles that "touch" at a line or a point are not considered intersecting, because their intersection rectangle (really, in this case, an intersection line or point) does not enclose any bits on the bitMap. If the rectangles do not intersect, the destination rectangle is set to (0,0,0,0). This function works correctly even if one of the source rectangles (argument) is also 'me'. */ { if (a.empty() || b.empty() || a.bottom <= b.top || b.bottom <= a.top || a.right <= b.left || b.right <= a.left) { /* not intersect */ this->set(0, 0, 0, 0); return FALSE; } left = max(a.left, b.left); top = max(a.top, b.top); right = min(a.right, b.right); bottom = min(a.bottom, b.bottom); return TRUE; } bool rect::equal(rect r) /* Compare 'r' with 'me' and return TRUE if they are equal or FALSE if not. The two rectangles must have identical boundary coordinates to be considered equal. */ { return left == r.left && top == r.top && right == r.right && bottom == r.bottom; } void rect::pt2(point a, point b) /* Set 'me' the smallest rectangle which encloses the two input points. */ { int ah = a.getH(), av = a.getV(), bh = b.getH(), bv = b.getV(); left = min(ah, bh); right = max(ah, bh); top = min(av, bv); bottom = max(av, bv); } bool rect::ptIn(point pt) /* Determine whether the pixel below and to the right of the given coordinate point is enclosed in the specified rectangle 'me', and return TRUE if so or FALSE if not. */ { if (this->empty()) return FALSE; int h = pt.getH(); int v = pt.getV(); return left <= h && h < right && top <= v && v < bottom; } void rect::unions(rect a, rect b) /* Calculate the smallest rectangle which encloses both input rectangles. It works correctly even if one of the source rectangles is also 'me'. */ { left = min(a.left, b.left); top = min(a.top, b.top); right = max(a.right, b.right); bottom = max(a.bottom, b.bottom); } istream& operator>>(istream& s, rect& r) /* "3 5 2 9" will r.set(3,5,2,9). */ { cout << "rect: left top right bottom: "; int left = 0, top = 0, right = 0, bottom = 0; s >> left >> top >> right >> bottom; if (s) r.set(left, top, right, bottom); return s; } bool rect::empty() /* Return TRUE if 'me' is an empty rectangle. A rectangle is considered empty if the bottom coordinate is equal to or less than the top or the right coordinate is equal to or less than the left. */ { return bottom <= top || right <= left; } void rect::inset(int dh, int dv) /* Shrink or expand the rectangle (me). The left and right sides are moved in by the amount specified by 'dh'; the top and bottom are moved towards the center by the amount specified by 'dv'. If 'dh' or 'dv' is negative, the appropriate pair of sides is moved outwards instead of inwards. If the resulting width or height becomes less than 1, the rectangle is set to the empty rectangle (0,0,0,0). */ { left += dh; top += dv; right -= dh; bottom -= dv; if (top >= bottom || left >= right) top = bottom = left = right = 0; assert(this->ok(), "Illegal rectangle data"); } ostream& operator<<(ostream& s, rect r) { return s << form("(%d,%d,%d,%d)", r.left, r.top, r.right, r.bottom); } void rect::offset(int dh, int dv) /* Move the rectangle (me) by adding 'dh' to each horizontal coordinate and 'dv' to each vertical coordinate. If 'dh' and 'dv' are positive, the movement is to the right and down; if either is negative, the corresponding movement is in the opposite direction. The rectangle retains its shape and size; it's merely moved on the coordinate plane. */ { left += dh; right += dh; top += dv; bottom += dv; assert(this->ok(), "Illegal coordinate"); } void rect::set(int left, int top, int right, int bottom) /* Assign four boundary coordinates. */ { assert(rect::ok(top, left, bottom, right), "Illegal argument"); this->left = left; this->top = top; this->right = right; this->bottom = bottom; } bool rect::ok() { return validCoordinate(this->top) && validCoordinate(this->left) && validCoordinate(this->bottom) && validCoordinate(this->right); } rect::rect() /* Generate empty rectangle. See the comment of 'rect.h' about empty rectangle. */ { this->left = this->top = this->right = this->bottom = 0; } rect::rect(int left, int top, int right, int bottom) /* See the comment of 'rect.h' about empty rectangle. Assign the four boundary coordinates. */ { assert(rect::ok(left, top, right, bottom), "Illegal argument"); this->left = left; this->top = top; this->right = right; this->bottom = bottom; } bool rect::ok(int left, int top, int right, int bottom) { return validCoordinate(left) && validCoordinate(top) && validCoordinate(right) && validCoordinate(bottom); } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'quickDraw.cc' then echo shar: "will not over-write existing file 'quickDraw.cc'" else cat << \SHAR_EOF > 'quickDraw.cc' #include <stream.h> #include "global.h" #include "quickDraw.h" const SrcCopy = 0; const SrcOr = 1; const SrcXor = 2; const SrcBic = 3; const NotSrcCopy = 4; const NotSrcOr = 5; const NotSrcxor = 6; const NotSrcbic = 7; const PatCopy = 8; const PatOr = 9; const PatXor = 10; const PatBic = 11; const NotPatCopy = 12; const NotPatOr = 13; const NotPatXor = 14; const NotPatBic = 15; const BlackColor = 33; const WhiteColor = 30; const RedColor = 205; const GreenColor = 341; const BlueColor = 409; const CyanColor = 273; const MagentaColor = 137; const YellowColor = 69; const PicLParen = 0; const PicRParen = -1; /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ mainxz() {} /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'ch.h' then echo shar: "will not over-write existing file 'ch.h'" else cat << \SHAR_EOF > 'ch.h' class ch { uchar c; /* shape */ bool reverse; bool underline; bool blink; bool doubleBright; bool halfBright; public: /* constructor etc */ ch(uchar c = 0); /* general */ uchar getC(); void setC(uchar); void setOrdinary(); void setReverse(bool); void setUnderline(bool); void setBlink(bool); void setDoubleBright(bool); void setHalfBright(bool); void resetShape() { this->setOrdinary(); } bool isOrdinary(); bool isReverse(); bool isUnderline(); bool isBlink(); bool isDoubleBright(); bool isHalfBright(); bool isAscii(); /* for debugging */ friend ostream& operator<<(ostream&, ch); void fprint(ostream&); }; SHAR_EOF fi if test -f 'terminal.h' then echo shar: "will not over-write existing file 'terminal.h'" else cat << \SHAR_EOF > 'terminal.h' extern void initTermData(); extern getScrWidth(); extern getScrHeight(); extern char PC; extern char *BC; extern char *UP; extern short ospeed; SHAR_EOF fi if test -f 'grafPort.h' then echo shar: "will not over-write existing file 'grafPort.h'" else cat << \SHAR_EOF > 'grafPort.h' typedef ch pattern; typedef ch cursor; extern void initGraf(); /* different from Mac; void argument */ /* Macintosh 'thePort' variable is not need in N-window. */ /* Can't define 'static global' as g++ bug. */ extern pattern White; extern pattern Black; extern pattern Gray; extern pattern LtGray; extern pattern DkGray; extern cursor Arrow; extern charMap ScreenBits; extern long RandSeed; class grafPort { int device; charMap portBits; rect portRect; region visRgn; region clipRgn; pattern bkPat; pattern fillPat; point pnLoc; point pnSize; int pnMode; pattern pnPat; int pnVis; int txFont; style txFace; int txMode; int txSize; int spExtra; long fgColor; long bkColor; int colrbit; int patStretch; void *picSave; void *rgnSave; void *polySave; void *grafProcs; public: /* constructor etc */ grafPort(); /* initial value is the same as Mac library OpenPort() */ grafPort(const grafPort&); ~grafPort(); void operator=(const grafPort&); /* Mac library */ void init(); void open(); /* not implemented */ void close(); /* not implemented */ void setPort(grafPort gp); /* not implemented */ void getPort(grafPort &gpp); /* not implemented */ void setDevice(int); void setPortBits(charMap); void portSize(uint w, uint h); point localToGlobal(const point pt); point globalToLocal(const point pt); void movePortTo(int leftGlobal, int topGlobal); /* general */ charMap getPortBits() { return portBits; }; rect getPortRect() { return portRect; }; }; SHAR_EOF fi if test -f 'charMap.h' then echo shar: "will not over-write existing file 'charMap.h'" else cat << \SHAR_EOF > 'charMap.h' class charMap { ch *baseAddr; int rowBytes; rect bounds; region updateRgn; /* peculiar to N-window;show newly described region since last updated */ public: /* constructor etc */ charMap(ch *baseAddr, int rowBytes, rect bounds); charMap(); charMap(const charMap&); ~charMap(); void operator=(const charMap&); /* general */ rect getBounds() { return bounds; }; }; SHAR_EOF fi if test -f 'bitMatrix.h' then echo shar: "will not over-write existing file 'bitMatrix.h'" else cat << \SHAR_EOF > 'bitMatrix.h' class bitMatrix { uint width; uint height; bit **mtrx; /* matrix size is 'mtrx[width][height]' */ public: /* constructer etc */ bitMatrix(uint width, uint height, bit val=CLEAR); bitMatrix(const bitMatrix&); ~bitMatrix(); void operator=(bitMatrix&); /* general */ void set(); void set(uint col, uint line); void clear(); void clear(uint col, uint line); bit get(uint col, uint line); void resize(uint width, uint height, bit val=CLEAR); uint getWidth() { return width; } uint getHeight() { return height; } bool equal(bitMatrix); bool lineBitIsClear(uint line); bool colBitIsClear(uint col); /* for debugging */ friend istream& operator>>(istream&, bitMatrix&); friend ostream& operator<<(ostream&, const bitMatrix&); ostream& fprint(ostream&); void print(); }; SHAR_EOF fi if test -f 'misc.h' then echo shar: "will not over-write existing file 'misc.h'" else cat << \SHAR_EOF > 'misc.h' extern void fatal(char*...); extern bool validCoordinate(int); extern bool emptyRect(int, int, int, int); extern bit or(bit, bit); extern bit and(bit, bit); SHAR_EOF fi if test -f 'region.h' then echo shar: "will not over-write existing file 'region.h'" else cat << \SHAR_EOF > 'region.h' /* NewRgn() and DisposeRgn() in Mac are not supported because constructor and destructor play role. */ class region { rect bBox; /* boundary */ bitMatrix bMap; /* CLEAR bit represents the hole */ public: /* constructor etc */ region(); region(const region&); ~region(); void operator=(const region&); /* Mac library */ void copy(region); void setEmpty(); void setRect(int left, int top, int right, int bottom); void rects(rect); /* modify name to overcome g++ bug */ void open(); /* not implemented */ void close(); /* not implemented */ void offset(int dh, int dv); void inset(int dh, int dv); void sect(region a, region b); void unions(region a, region b); void diff(region a, region b); void xor(region a, region b); bool ptIn(point); bool rectIn(rect); bool equal(region); bool empty(); void frame(); void paint(); void erase(); void invert(); void fill(); /* general */ void compress(); friend bool operator==(region, region); /* for debugging */ friend ostream& operator<<(ostream&, const region&); friend istream& operator>>(istream&, region&); ostream& fprint(ostream&); void print(); }; SHAR_EOF fi if test -f 'point.h' then echo shar: "will not over-write existing file 'point.h'" else cat << \SHAR_EOF > 'point.h' /* Both horizontal and vertical coordinate reside in MaxCoordinate and MinCoordinate inclusive. */ class point { int h; /* horizontal coordinate */ int v; /* vertical coordinate */ public: /* constructor etc */ point(int h, int v); point(); /* general */ getH() { return h; } getV() { return v; } bool ok(); /* Mac library */ void add(point); void sub(point); void set(int h, int v); bool equal(point); /* for debugging */ friend ostream& operator<<(ostream&, point); friend istream& operator>>(istream&, point&); }; SHAR_EOF fi if test -f 'rect.h' then echo shar: "will not over-write existing file 'rect.h'" else cat << \SHAR_EOF > 'rect.h' /* Following four coordinate value must be 'validCoordinate(int)'. If the bottom coordinate of a rectangle is equal to or less than the top, or the right coordinate is equal to or less than the left, the rectangle is an empty rectangle (i.e., one that contains no bits). */ class rect { int left; int top; int right; int bottom; public: /* constructor etc */ rect(int left, int top, int right, int bottom); rect(); /* Mac library */ void set(int left, int top, int right, int bottom); void offset(int dh, int dv); void inset(int dh, int dv); bool sect(rect a, rect b); void unions(rect a, rect b); bool ptIn(point); void pt2(point, point); void ptToAngle(point, int*); /* not implemented */ bool equal(rect); bool empty(); void frame(); void paint(); void erase(); void invert(); void fill(); /* general */ bool ok(); bool ok(int left, int top, int right, int bottom); uint getWidth() { return max(0, right-left); }; uint getHeight() { return max(0, bottom-top); }; int getLeft() { return left; }; int getTop() { return top; }; int getRight() { return right; }; int getBottom() { return bottom; }; point getTopLeft() { point pt(left, top); return pt; }; void moveTo(int left, int top); /* for debugging */ friend ostream& operator<<(ostream&, rect); friend istream& operator>>(istream&, rect&); }; SHAR_EOF fi if test -f 'quickDraw.h' then echo shar: "will not over-write existing file 'quickDraw.h'" else cat << \SHAR_EOF > 'quickDraw.h' extern const SrcCopy; extern const SrcOr; extern const SrcXor; extern const SrcBic; extern const NotSrcCopy; extern const NotSrcOr; extern const NotSrcxor; extern const NotSrcbic; extern const PatCopy; extern const PatOr; extern const PatXor; extern const PatBic; extern const NotPatCopy; extern const NotPatOr; extern const NotPatXor; extern const NotPatBic; extern const BlackColor; extern const WhiteColor; extern const RedColor; extern const GreenColor; extern const BlueColor; extern const CyanColor; extern const MagentaColor; extern const YellowColor; extern const PicLParen; extern const PicRParen; enum bit { CLEAR = 0, SET = 1 }; enum style { NORMAL, BOLD, ITALIC, UNDERLINE, OUTLINE, SHADOW, CONDENSE, EXTEND }; SHAR_EOF fi if test -f 'global.h' then echo shar: "will not over-write existing file 'global.h'" else cat << \SHAR_EOF > 'global.h' #define max(A,B) ((A)>(B) ? (A):(B)) #define min(A,B) ((A)<(B) ? (A):(B)) #define until(A) while (!(A)) #define forever() while (1) #ifndef NO_DEBUG # define _assert(ex,msg) {if (!(ex)) fatal(msg);} # define assert(ex,msg) {if (!(ex)) fatal(msg);} #else # define _assert(ex,msg) ; # define assert(ex,msg) ; #endif NDEBUG #define NLN << "\n" #define NIL 0 #define SPACE ' ' #define CARET '^' typedef unsigned int uint; typedef unsigned char uchar; enum fv { OK, ERROR }; extern const MaxCoordinate; extern const MinCoordinate; /* make lint silent */ void malloc_debug(int); SHAR_EOF fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else cat << \SHAR_EOF > 'Makefile' C++ = g++ C++FLAGS = -g CPPFLAGS = LDFLAGS = LINT = /usr/bin/lint LINTFLAGS = -h LIBS = /usr/lib/debug/malloc.o -ltermlib -lm SRC =\ ch.cc\ terminal.cc\ grafPort.cc\ charMap.cc\ bitMatrix.cc\ misc.cc\ region.cc\ point.cc\ rect.cc\ quickDraw.cc OBJ := $(subst .cc,.o, $(SRC)) HDR = $(subst .cc,.h, $(SRC)) global.h PRG = p $(PRG): $(OBJ) $(C++) $(C++FLAGS) $(OBJ) -o $(PRG) $(LIBS) clean: \rm -rf $(OBJ) core mon.out gmon.out tags: $(SRC) Makefile etags -et $(HDR) $(SRC) main.cc dbg.cc trash.cc touch tags dlist: $(HDR) $(C++) -MM $(SRC) > dlist shar: shar $(SRC) $(HDR) Makefile .gdbinit dlist > shar.file # # implicit rules # .cc .o: $(C++) $(C++FLAGS) -o $@ $< $(LIBS) %:%.sh cp $< $@ chmod +x $@ # # misc # .PRECIOUS: tags # # dependency-list. # include dlist SHAR_EOF fi if test -f '.gdbinit' then echo shar: "will not over-write existing file '.gdbinit'" else cat << \SHAR_EOF > '.gdbinit' # Initialization for N-window unset env TERMCAP set env TERM vt100 printf "Caution: environment TERM is set to vt100. Modify '.gdbinit' as you wish.\n" # Switch to the file 'p' define dbgp exec p sym p core end document dbgp Switchs to the file 'p'. Core infomation is discarded, too. end # Print the next node define nn p $->next end document nn Print the next node of linear list. end # Print the previous node define pn p $->prev end document pn Print the previous node of linear list. end # Print the next track define nt p $->littleBr end document nt Print the next track. end # Print the previous track define pt p $->bigBr end document pt Print the previous track. end # Print the current node define cn p $ end document cn Print the current node of linear list. end # Print the content of the next node define nc p *$->next end document nc Print the content of the next node end # Print the content of the previous node define pc p *$->prev end document pc Print the content of the previous node end # Print the content of the current node define cc p *$ end document cc Print the content of the current node end # Lpr Cell and SymTable data. define prall set $tmp = lprCellAll() set $tmp = lprNl(5) set $tmp = lprSymTable() set $tmp = lprPage() end document prall Lpr Cell and SymTable data. end # Lpr Cell. define prcell set $tmp = lprCellAll() set $tmp = lprNl(5) end document prcell Lpr Cell data. end # Lpr Symtable. define prsym set $tmp = lprSymTable() set $tmp = lprPage() end document prsym Lpr all Symtable data. end SHAR_EOF fi if test -f 'dlist' then echo shar: "will not over-write existing file 'dlist'" else cat << \SHAR_EOF > 'dlist' ch.o : ch.cc global.h quickDraw.h ch.h terminal.o : terminal.cc global.h quickDraw.h grafPort.o : grafPort.cc global.h quickDraw.h point.h \ rect.h bitMatrix.h region.h ch.h charMap.h grafPort.h charMap.o : charMap.cc global.h quickDraw.h point.h \ rect.h bitMatrix.h region.h ch.h charMap.h bitMatrix.o : bitMatrix.cc global.h quickDraw.h bitMatrix.h \ misc.h misc.o : misc.cc global.h quickDraw.h region.o : region.cc global.h quickDraw.h misc.h point.h \ rect.h bitMatrix.h region.h point.o : point.cc global.h quickDraw.h point.h misc.h rect.o : rect.cc global.h quickDraw.h point.h rect.h \ misc.h quickDraw.o : quickDraw.cc global.h quickDraw.h SHAR_EOF fi exit 0 # End of shell archive
shin@sgtp.apple.juice (Shinichirou Sugou) (04/28/89)
Dear FSF people: I think this is bug in gdb-3.1. My system is Sun3/60 with OS3.4, gcc-3.4, and gdb-3.1. Whole source program (as shar-format) is appended to the last. Please unshar sources and type 'make' to generate executable code named 'p' (please use GNU make if possible, also use Sun if possible because special malloc.o file pecurial to Sun is used here). Type foo% gdb p to invoke gdb-3.1. Type (gdb) run to run the program 'p'. 'p' will require four integers (coordinates of a rectangle). left top right bottom: Type four values like these delimiting with space (value itself is not important in this case). 1 2 3 4 <CR> Again, 'p' will require two more integers (coordinates of a point). h v: Here, type Control-C to interrupt program. The screen looks like this. Program received signal 2, Interrupt 0x5e40 in read () (gdb) Type 'bt' to examine the backtracks of entire stack. Gdb-3.1 can't print the correct stack information. (gdb) bt #0 0x5e40 in read () #1 0x3 in ?? () While gdb-2.8 does without problem. (gdb-2.8) bt #0 0x5e40 in read () #1 0x3f10 in _doscan () #2 0x3e12 in _doscan () #3 0x3b4c in scanf () #4 0x29f4 in readPt (ptp=(struct point *) 0xefffd50) (point.c line 87) #5 0x2762 in main () (rect.c line 239) CAUTION: Reply-command supplied by your mail system may NOT generate my address correctly. Please use the following address instead. shin%sgtp.apple.juice%lkbreth.foretune.junet@uunet.uu.net --- Shinichirou Sugou shin%sgtp.apple.juice%lkbreth.foretune.junet@uunet.uu.net Sources follows... #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # rect.c # misc.c # point.c # rect.h # misc.h # point.h # global.h # Makefile # dlist # .gdbinit # This archive created: Fri Apr 28 14:54:22 1989 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'rect.c' then echo shar: "will not over-write existing file 'rect.c'" else cat << \SHAR_EOF > 'rect.c' #include <stdio.h> #include "global.h" #include "misc.h" #include "point.h" #include "rect.h" static void setEmptyRect(); /**/ /* Global -top- */ /**/ bool okRect(rp) Rect *rp; { return rp != NIL && okHLoc(rp->left) && okHLoc(rp->right) && okVLoc(rp->top) && okVLoc(rp->bottom); } bool EqualRect(ap, bp) Rect *ap; Rect *bp; /* EqualRect compares the two rectangles and returns TRUE if they are equal or FALSE if not. The two rectangles must have identical boundary coordinates to be cons idered equal. */ { assert((okRect(ap) && okRect(bp)), "invalid rect"); return ap->left == bp->left && ap->top == bp->top && ap->right == bp->right && ap->bottom == bp->bottom; } void UnionRect(srcAp, srcBp, dstp) Rect *srcAp; Rect *srcBp; Rect *dstp; /* UnionRect calculates the smallest rectangle which encloses both input rectan gles. It works correctly even if one of the source rectangles is also the destination . */ { if (EmptyRect(srcAp) && EmptyRect(srcBp)) setEmptyRect(dstp); else if (EmptyRect(srcAp)) copyRect(srcBp, dstp); else if (EmptyRect(srcBp)) copyRect(srcAp, dstp); else { dstp->left = min(srcAp->left, srcBp->left); dstp->right = max(srcAp->right, srcBp->right); dstp->top = min(srcAp->top, srcBp->top); dstp->bottom = max(srcAp->bottom, srcBp->bottom); } } void copyRect(srcp, dstp) Rect *srcp; Rect *dstp; /* result */ /* This is not the funtion of Mac toolbox. copyRect copies the coordinates of srcp into dstp. */ { assert(okRect(srcp), "invalid rect"); dstp->left = srcp->left; dstp->top = srcp->top; dstp->right = srcp->right; dstp->bottom = srcp->bottom; } bool SectRect(srcRectAp, srcRectBp, dstRectp) Rect *srcRectAp; Rect *srcRectBp; Rect *dstRectp; /* SectRect calculates the rectangle that is the intersection of the two input rectangles, and returns TRUE if they indeed intersect or FALSE if they do no t. Rectangles that "touch" at a line or a point are not considered intersecting , because their intersection rectangle (really, in this case, an intersection line or point) does not enclose any bits on the bitMap. If the rectangles do not intersect, the destination rectangle is set to (0,0 ,0,0). SectRect works correctly even if one of the source rectangles is also the de stination. */ { dstRectp->left = max(srcRectAp->left, srcRectBp->left); dstRectp->right = min(srcRectAp->right, srcRectBp->right); dstRectp->top = max(srcRectAp->top, srcRectBp->top); dstRectp->bottom = min(srcRectAp->bottom, srcRectBp->bottom); if (EmptyRect(dstRectp)) setEmptyRect(dstRectp); return !EmptyRect(dstRectp); } void InsetRect(rp, dh, dv) Rect *rp; int dh; int dv; /* InsetRect shrinks or expands the rectangle. The left and right sides are mo ved in by the amount specified by dh; the top and bottom are moved towards the center by the amount specified by dv. If dh or dv is negative, the appropriate pair of si des is moved outwards instead of inwards. The effect is to alter the size by 2*dh horizontally and 2*dv vertically, with the rectangle remaining centered in t he same place on the coordinate plane. If the resulting width or height becomes less than 1, the rectangle is set t o the empty rectangle (0,0,0,0). */ { assert(okRect(rp), "invalid rect"); rp->left += dh; rp->right -= dh; rp->top += dv; rp->bottom -= dv; if (EmptyRect(rp)) setEmptyRect(rp); } bool EmptyRect(rp) Rect *rp; /* EmptyRect returns TRUE if the given rectangle is an empty rectangle or FALSE if not. A rectangle is considered empty if the bottom coordinate is equal to or less than the top or the right coordinate is equal to or less than the left. */ { assert(okRect(rp), "invalid rect"); return rp->bottom <= rp->top || rp->right <= rp->left; } void OffsetRect(rp, dh, dv) Rect *rp; /* result */ int dh; int dv; /* OffsetRect moves the rectangle by adding dh to each horizontal coordinate an d dv to each vertical coordinate. If dh and dv are positive, the movement is to the right and down; if either is negative, the corresponding movement is in the opposite d irection. The rectangle retains its shape and size; it's merely moved on the coordinat e plane. This does not affect the screen unless you subsequently call a routine to dr aw within the rectangle. */ { assert((okRect(rp) && okHLoc(dh) && okVLoc(dv)), "illegal argument"); rp->left += dh; rp->right += dh; rp->top += dv; rp->bottom += dv; } void SetRect(rp, left, top, right, bottom) Rect *rp; /* result */ int left; int top; int right; int bottom; /* SetRect assigns the four boundary coordinates to the rectangle. The result is a rectangle with coordinates (left,top,right,bottom). This procedure is supplied as a utility to help you shorten your program tex t. If you want a more readable text at the expense of length, you can assign integers (or points) directly into the rectangle's fields. There is not significant code size of execution speed advantage to either method; one's just easier to write, and the other's easier to read. */ { rp->left = left; rp->top = top; rp->right = right; rp->bottom = bottom; assert(okRect(rp), "invalid rect"); } /**/ /* Global -bottom- */ /**/ /**/ /* Private -top- */ /**/ static void setEmptyRect(rp) Rect *rp; /* This is not the function of Mac toolbox. Set the rectangle empty (0,0,0,0). */ { /* Don't invoke okRect(rp) because setEmptyRect is sometimes called with uni nitialized variable. */ SetRect(rp, 0, 0, 0, 0); } /**/ /* Private -bottom- */ /**/ /**/ /* Debug -top- */ /**/ void readRect(rp) Rect *rp; /* result */ /* Debugging. */ { xprintf("left top right bottom: "); xscanf("%d%d%d%d", &rp->left, &rp->top, &rp->right, &rp->bottom); assert(okRect(rp), "invalid rect"); } void printRect(rp) Rect *rp; /* Debugging. */ { assert(okRect(rp), "invalid rect"); xprintf("(%d,%d,%d,%d)", rp->left, rp->top, rp->right, rp->bottom); } /**/ /* Debug -bottom- */ /**/ bool PtInRect(ptp, rp) Point *ptp; Rect *rp; /* PtInRect determines whether the pixel below and to the right of the given co ordinate point is enclosed in the specified rectangle, and returns TRUE if so or FALS E if not. */ { assert((okPt(ptp) && okRect(rp)), "invalid argument"); return rp->left <= ptp->h && ptp->h < rp->right && rp->top <= ptp->v && ptp->v < rp->bottom; } void main() /* PtInRect() */ { Rect r; Point pt; malloc_debug(MALLOC_LEVEL); readRect(&r); forever() { readPt(&pt); xprintf("%s\n\n", PtInRect(&pt, &r) ? "within" : "no, not"); } } SHAR_EOF fi if test -f 'misc.c' then echo shar: "will not over-write existing file 'misc.c'" else cat << \SHAR_EOF > 'misc.c' #include <stdio.h> #include "global.h" /**/ /* Global -top- */ /**/ void fatal(msg) char *msg; /* Print error message and dumps core. */ { xfprintf(stderr, "fatal error: %s\n", msg); (void)abort(); } bool okVLoc(v) int v; /* Return TRUE if vertical coordinate is valid. */ { return MIN_V <= v && v <= MAX_V; } bool okHLoc(h) int h; /* Return TRUE if horizontal coordinate is valid. */ { return MIN_H <= h && h <= MAX_H; } /**/ /* Global -bottom- */ /**/ /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'point.c' then echo shar: "will not over-write existing file 'point.c'" else cat << \SHAR_EOF > 'point.c' #include <stdio.h> #include "global.h" #include "misc.h" #include "point.h" /**/ /* Global -top- */ /**/ bool okPt(ptp) Point *ptp; /* Return TRUE if coordinates are valid. */ { return ptp != NIL && okHLoc(ptp->h) && okVLoc(ptp->v); } void SubPt(srcPtp, dstPtp) Point *srcPtp; Point *dstPtp; /* result */ /* SubPt subtracts the coordinates of srcPt to the coordiantes of dstPt, and re turn the result in dstPt. */ { assert((okPt(srcPtp) && okPt(dstPtp)), "invalid point"); dstPtp->h -= srcPtp->h; dstPtp->v -= srcPtp->v; } void AddPt(srcPtp, dstPtp) Point *srcPtp; Point *dstPtp; /* result */ /* AddPt adds the coordinates of srcPt to the coordiantes of dstPt, and return the result in dstPt. */ { assert((okPt(srcPtp) && okPt(dstPtp)), "invalid point"); dstPtp->h += srcPtp->h; dstPtp->v += srcPtp->v; } bool EqualPt(ptAp, ptBp) Point *ptAp; Point *ptBp; /* EqualPt compares the two points and returns TRUE if they are equal or FALSE if not. */ { assert((okPt(ptAp) && okPt(ptBp)), "invalid point"); return ptAp->h == ptBp->h && ptAp->v == ptBp->v; } void SetPt(ptp, h, v) Point *ptp; /* result */ int h; int v; /* SetPt assigns two integer coordinates to a variable of type Point*. */ { ptp->h = h; ptp->v = v; assert(okPt(ptp), "invalid point"); } /**/ /* Global -bottom- */ /**/ /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Debug -top- */ /**/ void readPt(ptp) Point *ptp; /* result */ /* Debugging. */ { xprintf("h v: "); if (scanf("%d%d", &ptp->h, &ptp->v) != 2) fatal("scanf error"); assert(okPt(ptp), "invalid point"); } void printPt(ptp) Point *ptp; /* Debugging tool. */ { assert(okPt(ptp), "invalid point"); fprintPt(stdout, ptp); } void fprintPt(stream, ptp) FILE *stream; Point *ptp; /* Debugging tool. */ { assert(okPt(ptp), "invalid point"); (void)fprintf(stream, "(%d,%d)", ptp->h, ptp->v); (void)fflush(stream); } /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'rect.h' then echo shar: "will not over-write existing file 'rect.h'" else cat << \SHAR_EOF > 'rect.h' /* Mac toolbox. */ extern void SetRect(); extern bool EmptyRect(); extern void OffsetRect(); extern void InsetRect(); extern bool SectRect(); extern void UnionRect(); extern bool EqualRect(); /* General. */ extern void copyRect(); extern bool okRect(); /* Debugging. */ extern void readRect(); SHAR_EOF fi if test -f 'misc.h' then echo shar: "will not over-write existing file 'misc.h'" else cat << \SHAR_EOF > 'misc.h' extern void fatal(); extern bool okVLoc(); extern bool okHLoc(); SHAR_EOF fi if test -f 'point.h' then echo shar: "will not over-write existing file 'point.h'" else cat << \SHAR_EOF > 'point.h' /* Mac toolbox. */ extern void SetPt(); extern void AddPt(); /* General. */ extern bool okPt(); /* Debugging. */ extern void fprintPt(); extern void printPt(); extern void readPt(); SHAR_EOF fi if test -f 'global.h' then echo shar: "will not over-write existing file 'global.h'" else cat << \SHAR_EOF > 'global.h' #define NLN (void)printf("\n") #define TRUE 1 #define FALSE 0 #define NIL 0 #define xprintf (void)printf #define xfprintf (void)fprintf #define xscanf (void)scanf #define xfscanf (void)fscanf #define until(A) while (!(A)) #define forever() while (TRUE) /* Horizontal coordinates range from -32768 to +32767, and vertical coordinates have the same range. */ #define MAX_H 32767 #define MAX_V 32767 #define MIN_H -32768 #define MIN_V -32768 #define max(A,B) ((A)>(B) ? (A):(B)) #define min(A,B) ((A)<(B) ? (A):(B)) #ifndef NO_DEBUG # define _assert(ex,msg) {if (!(ex)) fatal(msg);} # define assert(ex,msg) {if (!(ex)) fatal(msg);} #else # define _assert(ex,msg) ; # define assert(ex,msg) ; #endif NDEBUG struct point { int h; /* Horizontal coordinate. */ int v; /* Vertical coordinate. */ }; typedef struct point Point; struct rect { int left; int top; int right; int bottom; }; typedef struct rect Rect; typedef int bool; /* UNIX library definition. */ extern int printf(); extern int fprintf(); extern int fflush(); extern int malloc_debug(); extern int scanf(); extern int abort(); SHAR_EOF fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else cat << \SHAR_EOF > 'Makefile' # # Makefile for Neuron-Toolbox by S.Sugou 4/27 1989 # # 'make debug' generates debug version. # 'make lint' invokes lint. But, you should invoke 'lint.rc' instead of 'make l int'. # 'make tags' creates TAGS. # 'make clean' removes some files. # 'make shar' creates shar file. # CFLAGS = $(GNU_CFLAGS) -g -DMALLOC_LEVEL=2 CPPFLAGS = LDFLAGS = LINTFLAGS = -abchux -DMALLOC_LEVEL LIBS = /usr/lib/debug/malloc.o -lm -lmp PRG = p GNU_CFLAGS = -traditional -Wall SUN_CFLAGS = -fswitch #debug := CC = cc.GNU #debug := CFLAGS = $(GNU_CFLAGS) -g -DMALLOC_LEVEL=2 #debug := CC = cc.Sun #debug := CFLAGS = $(SUN_CFLAGS) -g -DMALLOC_LEVEL=2 SRC =\ rect.c\ misc.c\ point.c HDR = $(SRC:.c=.h) global.h OBJ = $(SRC:.c=.o) LINTFILES = $(SRC:.c=.ln) debug: $(PRG) $(PRG): $(OBJ) $(CC) $(CFLAGS) $(OBJ) $(LIBS) -o $(PRG) @make lint tags: $(SRC) Makefile etags -et $(SRC) $(HDR) main.c dbg.c trash.c touch tags clean: -\rm -f $(OBJ) $(LINTFILES) core mon.out gmon.out dlist: $(SRC) $(CC) -MM $(SRC) > dlist lint: $(LINTFILES) lint $(LINTFLAGS) $(LINTFILES) @touch lint shar: shar $(SRC) $(HDR) Makefile dlist .gdbinit > shar.file .PRECIOUS: lint tags # # dependency-list. # include dlist # # implict rule. # %:%.sh cp $< $@ chmod +x $@ %.ln:%.c lint $(LINTFLAGS) -i $< SHAR_EOF fi if test -f 'dlist' then echo shar: "will not over-write existing file 'dlist'" else cat << \SHAR_EOF > 'dlist' rect.o : rect.c global.h misc.h point.h rect.h misc.o : misc.c global.h point.o : point.c global.h misc.h point.h SHAR_EOF fi if test -f '.gdbinit' then echo shar: "will not over-write existing file '.gdbinit'" else cat << \SHAR_EOF > '.gdbinit' # Initialization for Neuron-Toolbox unset env TERMCAP set env TERM vt100 printf "Caution: environment TERM is set to vt100. Modify '.gdbinit' as you wi sh.\n" # Switch to the file 'p' define dbgp exec p sym p core end document dbgp Switchs to the file 'p'. Core infomation is discarded, too. end # Print the next node define nn p $->next end document nn Print the next node of linear list. end # Print the previous node define pn p $->prev end document pn Print the previous node of linear list. end # Print the next track define nt p $->littleBr end document nt Print the next track. end # Print the previous track define pt p $->bigBr end document pt Print the previous track. end # Print the current node define cn p $ end document cn Print the current node of linear list. end # Print the content of the next node define nc p *$->next end document nc Print the content of the next node end # Print the content of the previous node define pc p *$->prev end document pc Print the content of the previous node end # Print the content of the current node define cc p *$ end document cc Print the content of the current node end # Lpr Cell and SymTable data. define prall set $tmp = lprCellAll() set $tmp = lprNl(5) set $tmp = lprSymTable() set $tmp = lprPage() end document prall Lpr Cell and SymTable data. end # Lpr Cell. define prcell set $tmp = lprCellAll() set $tmp = lprNl(5) end document prcell Lpr Cell data. end # Lpr Symtable. define prsym set $tmp = lprSymTable() set $tmp = lprPage() end document prsym Lpr all Symtable data. end SHAR_EOF fi exit 0 # End of shell archive