URI:
       tqueue.cc - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tqueue.cc (5717B)
       ---
            1 #include        "misc.h"
            2 #include        "slug.h"
            3 #include        "range.h"
            4 #include        "page.h"
            5 
            6 queue        squeue;
            7 queue        bfqueue;
            8 queue        ufqueue;
            9 
           10 // We use the stream function current() to access a queue's head.
           11 // Thus, queue member curr should always point to its first range.
           12 void queue::check(char *whence)
           13 {
           14         if (dbg & 8) {
           15                 char *p;
           16                 if (this == &squeue)
           17                         p = "squeue";
           18                 else if (this == &bfqueue)
           19                         p = "bfqueue";
           20                 else if (this == &ufqueue)
           21                         p = "ufqueue";
           22                 else
           23                         p = "weird queue";
           24                 printf("#checking %s\n", p);
           25         }
           26         if (first != curr)
           27                 ERROR "check(%s): first != curr, line %d\n", whence, curr->rp->lineno() FATAL;
           28 }
           29 
           30 // When ranges are told to enqueue themselves, they are being rejected from the
           31 // stage back onto their original queues.
           32 // They reset any parameters that may have been altered by staging or trial
           33 // composition.
           34 
           35 void        range::enqueue(int block)
           36 {
           37         squeue.enqueue(this);
           38         if (block)
           39                 squeue.block();
           40 }
           41 
           42 void        ufrange::enqueue(int block)
           43 {
           44         restore();                        // both goal positions
           45         ufqueue.enqueue(this);
           46         if (block)
           47                 ufqueue.block();
           48 }
           49 
           50 void        bfrange::enqueue(int block)
           51 {
           52         restore();                        // both goal positions
           53         bfqueue.enqueue(this);
           54         if (block)
           55                 bfqueue.block();
           56 }
           57 
           58 int anymore()
           59 {
           60         return !(squeue.empty() && ufqueue.empty() && bfqueue.empty());
           61 }
           62 
           63 void mergestream::unblock()
           64 {
           65         squeue.unblock();
           66         bfqueue.unblock();
           67         ufqueue.unblock();
           68 }
           69 
           70 // Fill the staging area with a minimal chunk of input ranges.
           71 int mergestream::prime()
           72 {
           73         if (dbg & 4)
           74                 printf("#entering mergestream::prime()\n");
           75         if (!empty())
           76                 return 1;
           77         int brkok = 1;                        // is it OK to break after the last
           78                                         // VBOX that was added to the stage?
           79         int needheight = -1;                // minimum acceptable height of the
           80                                         // chunk being constructed on stage
           81         // If the range at the head of any queue is breaking,
           82         // deal with it first.
           83         if (squeue.more() && squeue.current()->breaking())
           84                 enqueue(squeue.dequeue());
           85         else if (bfqueue.more() && (bfqueue.current()->breaking() ||
           86                 (bfqueue.serialno() < squeue.serialno())))
           87                 enqueue(bfqueue.dequeue());
           88         else if (ufqueue.more() && (ufqueue.current()->breaking() ||
           89                 (ufqueue.serialno() < squeue.serialno())))
           90                 enqueue(ufqueue.dequeue());
           91         else while (squeue.more()) {
           92                 // Fill the stage with enough ranges to be a valid chunk.
           93                 range *r = squeue.dequeue();
           94                 if (r->isvbox()) {        // VBOX
           95                         if (dbg & 16)
           96                                 printf("#VBOX: !empty: %d; brkok: %d; vsince: %d\n",
           97                                         !empty(), brkok, currpage->vsince);
           98                         if (!empty()        // there's something there
           99                                 && brkok
          100                                         // it's OK to break here
          101                                 && currpage->vsince >= 2
          102                                         // enough stream has gone onto this page
          103                                 && rawht() >= needheight
          104                                         // current need has been satisfied
          105                                 ) {
          106                                         // the stage already contains enough
          107                                         // ranges, so this one can wait
          108                                 r->enqueue();
          109                                 break;
          110                         } else {
          111                                 if (r->rawht() > 0) {
          112                                         ++currpage->vsince;
          113                                         brkok = r->brkafter();
          114                                 }
          115                                 enqueue(r);
          116                         }
          117                 } else if (r->isnested() || r->issp()) {        // US, SP
          118                         if (!empty() && rawht() >= needheight) {
          119                                         // enough already, wait
          120                                 r->enqueue();
          121                                 break;
          122                         }
          123                         currpage->vsince = 0;
          124                         enqueue(r);
          125                         if (height() >= needheight)
          126                                 break;
          127                 } else if (r->isneed()) {        // NE
          128                         if (!empty() && rawht() >= needheight) {
          129                                         // not currently working on an unsatisfied NEed 
          130                                 r->enqueue();
          131                                 break;
          132                         }
          133                                         // deal with overlapping NEeds
          134                         needheight = rawht() + max(needheight - rawht(), r->needht());
          135                         enqueue(r);
          136                 } else if (r->forceflush() == NO) {
          137                         enqueue(r);
          138                 } else if (r->forceflush() == YES) {
          139                         currpage->vsince = 0;
          140                         if (!empty()) {
          141                                         // ready or not, r must wait
          142                                 r->enqueue();
          143                                 break;
          144                         }
          145                         enqueue(r);
          146                         break;
          147                 } else
          148                         ERROR "unexpected  %s[%s] in prime(), line %d\n",
          149                                 r->typename(), r->headstr(), r->lineno() FATAL;
          150         }
          151         return more();                        // 0 if nothing was staged
          152 }
          153 
          154 void page::cmdproc()
          155 {
          156         if (stage->next())
          157                 ERROR "more than a single command on bsqueue\n" FATAL;
          158         switch (stage->current()->cmdtype()) {
          159         case FC:        // freeze the current 2-column range and start a new one
          160                 adddef(stage->dequeue());
          161                 twocol->compose(FINAL);
          162                 adddef(twocol);
          163                 twocol = new multicol(this);
          164                 break;
          165         case BP:        // force a page break
          166                 adddef(stage->dequeue());
          167                 squeue.block();
          168                 break;
          169         case FL:        // flush out all floatables that precede this range:
          170                         // no more stream input allowed until they're past
          171                 if (stage->serialno() > ufqueue.serialno() ||
          172                         stage->serialno() > bfqueue.serialno()) {
          173                         range *r = stage->dequeue();
          174                         r->enqueue(ANDBLOCK);
          175                 } else
          176                         adddef(stage->dequeue());
          177                 break;
          178         default:
          179                 stage->current()->dump();
          180                 ERROR "unknown command\n" FATAL;
          181         }
          182 }
          183 
          184 void page::parmproc()
          185 {
          186         if (stage->next())
          187                 ERROR "more than a single parameter on bsqueue\n" FATAL;
          188         switch (stage->current()->parmtype()) {
          189         case NP:        // page top margin
          190                 if (blank())
          191                         pagetop = stage->current()->parm();
          192                 pagesize = pagebot - pagetop;
          193                 break;
          194         case FO:
          195                 if (blank())
          196                         pagebot = stage->current()->parm();
          197                 pagesize = pagebot - pagetop;
          198                 break;
          199         case PL:
          200                 if (blank())
          201                         physbot = stage->current()->parm();
          202                 break;
          203         case MF:
          204                 minfull = 0.01*stage->current()->parm();
          205                 break;
          206         case CT:
          207                 coltol = 0.01*stage->current()->parm();
          208                 break;
          209         case WARN:
          210                 wantwarn = stage->current()->parm();
          211                 break;
          212         case DBG:
          213                 dbg = stage->current()->parm();
          214                 break;
          215         default:
          216                 stage->current()->dump();
          217                 ERROR "unknown parameter\n" FATAL;
          218         }
          219         adddef(stage->dequeue());
          220 }
          221 
          222 // Process the contents of the staging area; a relic that used to do more.
          223 void mergestream::pend()
          224 {
          225         if (dbg & 4)
          226                 printf("#entering mergestream::pend()\n");
          227         if (!more())
          228                 return;
          229         if (current()->iscmd())
          230                 currpage->cmdproc();
          231         else if (current()->isparm())
          232                 currpage->parmproc();
          233         else
          234                 currpage->tryout();
          235 }