From 5f1cf8e6fb130fd48d6f016d13baf5408b3181f8 Mon Sep 17 00:00:00 2001 From: wkj Date: Sun, 16 May 2004 07:56:41 +0000 Subject: Checkpoint: pull in mpm; merge pic from Taj's version of the world --- src/cmd/mpm/range.h | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 src/cmd/mpm/range.h (limited to 'src/cmd/mpm/range.h') diff --git a/src/cmd/mpm/range.h b/src/cmd/mpm/range.h new file mode 100644 index 00000000..401035a5 --- /dev/null +++ b/src/cmd/mpm/range.h @@ -0,0 +1,334 @@ +const int NOGOAL = -1; + +class stream; + +enum primeflush { NO, YES, EXPECTED, UNEXPECTED }; // mergestream::prime() + +// Ranges do two things. They interpose a layer between slugs and the rest +// of the program; this is important because of the grossness of the slug +// data structure (made necessary by its origins in troff output). Ranges also +// group together other ranges into meaningful chunks like unbreakable stream +// objects, floatable objects, and page headers and footers. +// Member function height() returns a range's height as of the latest composition. +// Member function rawht() returns the range's original height in the input. +class range { + protected: + slug *first; // earliest slug in range + int accumV; // accumulated V to this point + public: + range() { first = 0; accumV = 0; } + range(slug *p) { first = p; accumV = 0; } + char *headstr() { + return first ? first->headstr() : (char*)""; } + char *typename() { return first->typename(); } + int serialno() { return first->serialno(); } + int lineno() { return first->lineno(); } + virtual void dump() { first->dump(); } + virtual void rdump() { dump(); } + virtual int print(int cv, int col) { + first->slugout(col); return cv; } + virtual int floatable() { return 0; } + virtual int brkafter() { return 1; } + virtual int isnested() { return 0; } + virtual int issp() { return 0; } + virtual int isvbox() { return 0; } + virtual int isneed() { return 0; } + virtual int iscmd() { return 0; } + virtual int cmdtype() { return -1; } + virtual int isparm() { return 0; } + virtual int parmtype() { return -1; } + virtual int parm() { return -1; } + virtual int breakable() { return 0; } + virtual int forceflush() { return UNEXPECTED; } + virtual int pn() { return 0; } + virtual stream *children() { return 0; } // see page::peeloff() + virtual void killkids() { } + virtual void enqueue(int = 0); + virtual int height() { return 0; } + virtual int rawht() { return 0; } + virtual int needht() { return 0; } + virtual void reheight(int *, int *) { } + virtual void rerawht(int *, int *) { } + virtual void setheight(int) { } + virtual void restore() { } // goals of floatables + virtual int goal() { return NOGOAL; } + int accum() { return accumV; } + void setaccum(int n) { accumV = n; } + virtual void setgoal(int) { } + virtual void pickgoal(int, double) { } + virtual int numcol() { return first->numcol(); } + virtual int issentinel() { return 0; } + virtual range *clone() { return 0; } + virtual int breaking() { return 0; } + virtual void setbreaking() { } +}; + +class vboxrange : public range { + int dv; // inherited from slug + int base; // inherited from slug + int brk; // 0 => ok to break after, 1 => no break + public: + vboxrange(slug *p) : range(p) { dv = p->dv; base = p->base; brk = p->parm; } + void dump() { + printf("#### VBOX brk? %d dv %d ht %d\n", brk, dv, dv+base); } + int print(int cv, int col) { + printf("V%d\n", cv += dv); first->slugout(col); return cv+base; } + int brkafter() { return !brk; } + int isvbox() { return 1; } + int forceflush() { return NO; } + int height() { return dv + base; } + int rawht() { return first->dv + first->base; } + void reheight(int *cv, int *mv) { + *cv += dv+base; *mv = max(*mv, *cv); } + void rerawht(int *cv, int *mv) { + *cv += rawht(); *mv = max(*mv, *cv); } +}; + +class sprange : public range { + int dv; + public: + sprange(slug *p) : range(p) { dv = first->dv; } + void dump() { + printf("#### SP dv %d (originally %d)\n", dv, first->dv); } + int print(int cv, int col) { + first->slugout(col); return cv + dv; } + int issp() { return 1; } + int forceflush() { return YES; } + int height() { return dv; } + int rawht() { return first->dv; } + void reheight(int *, int *); + void rerawht(int *, int *); + void setheight(int n) { dv = n; } +}; + +class tmrange : public range { + public: + tmrange(slug *p) : range(p) { } + int forceflush() { return NO; } + int print(int cv, int col) { first->slugout(col); return cv; } +}; + +class coordrange : public range { + public: + coordrange(slug *p) : range(p) { } + int forceflush() { return NO; } + int print(int cv, int col) + { first->slugout(col); printf(" Y %d\n", cv); return cv; } +}; + +class nerange : public range { + public: + nerange(slug *p) : range(p) { } + int isneed() { return 1; } + int forceflush() { return YES; } + int needht() { return first->dv; } +}; + +class mcrange : public range { + public: + mcrange(slug *p) : range(p) { } + int forceflush() { return YES; } +}; + +class cmdrange : public range { + public: + cmdrange(slug *p) : range(p) { } + int iscmd() { return 1; } + int forceflush() { return YES; } + int cmdtype() { return first->parm; } +}; + +class parmrange : public range { + public: + parmrange(slug *p) : range(p) { } + int isparm() { return 1; } + int forceflush() { return YES; } + int parmtype() { return first->parm; } + int parm() { return first->parm2; } +}; + +class bsrange : public range { + public: + bsrange(slug *p) : range(p) { } + int forceflush() { return NO; } + int print(int cv, int col) { first->slugout(col); return cv; } +}; + +class endrange : public range { + public: + endrange(slug *p) : range(p) { } + int forceflush() { return UNEXPECTED; } +}; + +class eofrange : public range { + public: + eofrange(slug *p) : range(p) { } + int forceflush() { return UNEXPECTED; } +}; + +extern eofrange *lastrange; // the EOF block (trailer, etc.) goes here + +int measure(stream *); +int rawmeasure(stream *); + +// A nestrange packages together a sequence of ranges, its subrange. +// Other parts of the program reach in and alter the dimensions of +// some of these ranges, so when the height of a range is requested +// it is computed completely afresh. +// (Note: the alternative, of keeping around many copies of ranges +// with different dimensions, was abandoned because of the difficulty +// of ensuring that exactly one copy of each original range would be +// output.) +class nestrange : public range { + protected: + stream *subrange; + int isbreaking; + int rawdv; + public: + nestrange() : range() { subrange = 0; isbreaking = 0; rawdv = -1; } + nestrange(slug *p, stream *s) : range(p) + { subrange = s; isbreaking = 0; rawdv = -1; } + void rdump(); + virtual void restore(); + stream *children() { return subrange; } + void killkids(); + int height() { return measure(subrange); } + int rawht() { if (rawdv < 0 || isbreaking) rawdv = rawmeasure(subrange); + return rawdv; } + void reheight(int *cv, int *mv) { + *mv += measure(subrange); *cv = max(*mv, *cv); } + void rerawht(int *cv, int *mv) { + *mv += rawht(); *cv = max(*mv, *cv); } + int isnested() { return 1; } + int forceflush() { return EXPECTED; } + int print(int cv, int col); + int breaking() { return isbreaking; } + void setbreaking() { isbreaking++; } +}; + +class usrange : public nestrange { + public: + usrange() { } + usrange(slug *p, stream *s) : nestrange(p, s) {} + void dump() { printf("#### US dv %d\n", height()); } + range *clone(); +}; + +class ufrange : public nestrange { + int goalV, goal2; + public: + ufrange() { } + ufrange(slug *p, stream *s) : nestrange(p, s) { + goalV = p->parm; goal2 = p->parm2; } + void dump() { printf("#### UF dv %d goal %d goal2 %d\n", + height(), goalV, goal2); } + int floatable() { return 1; } + void enqueue(int = 0); + range *clone(); + int goal() { return goalV; } + void setgoal(int n) { goalV = goal2 = n; } + void pickgoal(int acv, double scale); + void restore() { goalV = first->parm; goal2 = first->ht; } +}; + +class bfrange : public nestrange { + int goalV, goal2; + public: + bfrange() { } + bfrange(slug *p, stream *s) : nestrange(p, s) { + goalV = p->parm; goal2 = p->parm2; } + void dump() { printf("#### BF dv %d goal %d goal2 %d\n", + height(), goalV, goal2); } + int floatable() { return 1; } + void enqueue(int = 0); + range *clone(); + int goal() { return goalV; } + void setgoal(int n) { goalV = goal2 = n; } + void pickgoal(int acv, double scale); + void restore() { goalV = first->parm; goal2 = first->parm2; } + int breakable() { return 1; } // can be broken +}; + +class ptrange : public nestrange { + int pgno; + public: + int pn() { return pgno; } + ptrange(slug *p, stream *s) : nestrange(p, s) { pgno = p->parm; } + void dump() { printf("#### PT pgno %d dv %d\n", pgno, height()); } +}; + +class btrange : public nestrange { + int pgno; + public: + btrange(slug *p, stream *s) : nestrange(p, s) { pgno = p->parm; } + void dump() { printf("#### BT pgno %d dv %d\n", pgno, height()); } +}; + +// A stream is a sequence of ranges; we use this data structure a lot +// to traverse various sequences that crop up in page-making. +class stream { + protected: +public: + struct strblk { // ranges are linked by these blocks + strblk *next; + range *rp; + }; + strblk *first; + strblk *last; + strblk *curr; + public: + stream() { curr = last = first = 0; } + stream(range *r) { curr = last = first = new strblk; + last->rp = r; last->next = 0; } + void freeall(); // note: not a destructor + void dump(); // top level + void rdump(); // recursive + int restoreall(); + range *current() { return curr->rp; } + range *next() { return curr && curr->next ? curr->next->rp : 0; } + void advance() { curr = curr->next; } + range *append(range *r); + void split(); + int more() { return curr && curr->rp; } + int height(); + int rawht(); +}; + +// A generator iterates through all the ranges of a stream +// (not just the root ranges of nestranges). +class generator { + stream s; + generator *child; + public: + generator() { child = 0; } + generator(stream *sp) { s = *sp; child = 0; } + range *next(); +}; + +extern stream ptlist, btlist; // page titles + +#define INFINITY 1000001 + +// A queue is a distinguished kind of stream. +// It keeps its contents in order by the serial numbers of the ranges. +// A queue can be blocked from dequeuing something to indicate +// that it's not worth considering the queue again on a given page. +class queue : public stream { + strblk *newguy; + protected: + int blocked; + void check(char *); + public: + queue() : blocked(0) { } + range *enqueue(range *r); + range *dequeue(); + void block() { blocked = 1; } + void unblock() { blocked = 0; } + int more() { return !blocked && stream::more(); } + int empty() { return !stream::more(); } + int serialno() { return empty() ? INFINITY : current()->serialno(); } +}; + +// functions in range.c +void checkout(); +void startup(FILE *); -- cgit v1.2.3