Back to index

tetex-bin  3.0
pprescan.c
Go to the documentation of this file.
00001 /*
00002  *   This is the main routine for the first (prescanning) pass.
00003  */
00004 #include "dvips.h" /* The copyright notice in that file is included too! */
00005 
00006 /*
00007  *   These are all the external routines it calls:
00008  */
00009 #include "protos.h"
00010 
00011 /*
00012  *   These are the globals it accesses.
00013  */
00014 #ifdef DEBUG
00015 extern integer debug_flag;
00016 #endif  /* DEBUG */
00017 extern fontdesctype *fonthead ;
00018 extern integer firstpage, lastpage ;
00019 extern integer firstseq, lastseq ;
00020 extern Boolean notfirst, notlast ;
00021 extern Boolean evenpages, oddpages, pagelist ;
00022 extern integer maxpages ;
00023 extern Boolean abspage ;
00024 extern FILE *dvifile ;
00025 extern fontdesctype *curfnt ;
00026 extern fontmaptype *ffont ;
00027 extern quarterword *curpos, *curlim ;
00028 extern integer pagenum ;
00029 extern char errbuf[] ;
00030 extern frametype frames[] ;
00031 extern Boolean noomega ;
00032 /*
00033  *  We declare this to tell everyone we are prescanning early.
00034  */
00035 Boolean pprescan ;
00036 /*
00037  * When a font is selected during the pre-prescan, this routine makes sure
00038  * that the tfm or vf (but not pk) file is loaded.
00039  */
00040 static void
00041 ppreselectfont P1C(fontdesctype *, f)
00042 {
00043    int i ;
00044 
00045    curfnt = f ;
00046    if (curfnt->loaded == 0) {
00047       if (!residentfont(curfnt))
00048          if (!virtualfont(curfnt)) {
00049             for (i=0; i<256; i++)
00050                curfnt->chardesc[i].flags = 0 ;
00051             curfnt->loaded = 3 ; /* we're scanning for sizes */
00052          }
00053    }
00054 }
00055 /*
00056  *   Now our scanpage routine.
00057  */
00058 static void
00059 pscanpage P1H(void)
00060 {
00061    register shalfword cmd ;
00062    register chardesctype *cd ;
00063    register fontmaptype *cfnt = 0 ;
00064    integer fnt ;
00065    integer mychar ;
00066    register frametype *frp = frames ;
00067 
00068 #ifdef DEBUG
00069    if (dd(D_PAGE))
00070 #ifdef SHORTINT
00071    (void)fprintf(stderr,"PPrescanning page %ld\n", pagenum) ;
00072 #else   /* ~SHORTINT */
00073    (void)fprintf(stderr,"PPrescanning page %d\n", pagenum) ;
00074 #endif  /* ~SHORTINT */
00075 #endif  /* DEBUG */
00076    curfnt = NULL ;
00077    curpos = NULL ;
00078    bopcolor(0) ;
00079    while (1) {
00080       switch (cmd=dvibyte()) {
00081 case 130: case 131: case 135: case 136: case 139:
00082 case 247: case 248: case 249: case 250: case 251: case 252: case 253:
00083 case 254: case 255: /* unimplemented or illegal commands */
00084          (void)sprintf(errbuf,
00085             "! DVI file contains unexpected command (%d)",cmd) ;
00086          error(errbuf) ;
00087 case 132: case 137: /* eight-byte commands setrule, putrule */
00088          (void)dvibyte() ;
00089          (void)dvibyte() ;
00090          (void)dvibyte() ;
00091          (void)dvibyte() ;
00092 case 146: case 151: case 156: case 160: case 165: case 170:
00093    /* four-byte commands right4, w4, x4, down4, y4, z4 */
00094          (void)dvibyte() ;
00095 case 145: case 150: case 155: case 159: case 164: case 169:
00096    /* three-byte commands right3, w3, x3, down3, y3, z3 */
00097          (void)dvibyte() ;
00098 case 144: case 149: case 154: case 158: case 163: case 168:
00099    /* two-byte commands right2, w2, x2, down2, y2, z2 */
00100          (void)dvibyte() ;
00101 case 143: case 148: case 153: case 157: case 162: case 167:
00102    /* one-byte commands right1, w1, x1, down1, y1, z1 */
00103          (void)dvibyte() ;
00104 case 147: case 152: case 161: case 166: /* w0, x0, y0, z0 */
00105 case 138: case 141: case 142: /* nop, push, pop */
00106          break ;
00107 case 134: case 129: /* set2, put2 */
00108          if (noomega) {
00109             (void)sprintf(errbuf,
00110                "! DVI file contains unexpected Omega command (%d)",cmd) ;
00111             error(errbuf) ;
00112          }
00113          mychar = dvibyte() ; mychar = (mychar << 8) + dvibyte() ;
00114          goto dochar ;
00115 case 133: case 128: cmd = dvibyte() ; /* set1, put1 commands drops through */
00116 default:    /* these are commands 0 (setchar0) thru 127 (setchar 127) */
00117         mychar = cmd ;
00118 dochar:
00119          if (curfnt==NULL)
00120             error("! Bad DVI file: no font selected") ;
00121          if (mychar>=curfnt->maxchars) {
00122             (void)sprintf(errbuf,"! invalid char %d from font %s", mychar, curfnt->name) ;
00123             error(errbuf) ;
00124          }
00125          if (curfnt->loaded == 2) { /* scanning a virtual font character */
00126             frp->curp = curpos ;
00127             frp->curl = curlim ;
00128             frp->ff = ffont ;
00129             frp->curf = curfnt ;
00130             if (++frp == &frames[MAXFRAME] )
00131                error("! virtual recursion stack overflow") ;
00132             cd = curfnt->chardesc + mychar;
00133             if (cd->packptr == 0)
00134     error("! a non-existent virtual char is being used; check vf/tfm files") ;
00135             curpos = cd->packptr + 2 ;
00136             curlim = curpos + (256*(long)(*cd->packptr)+(*(cd->packptr+1))) ;
00137             ffont = curfnt->localfonts ;
00138             if (ffont==NULL)
00139                curfnt = NULL ;
00140             else
00141                ppreselectfont(ffont->desc) ;
00142          } else if (curfnt->loaded == 3)
00143             curfnt->chardesc[mychar].flags = EXISTS ;
00144          break ;
00145 case 171: case 172: case 173: case 174: case 175: case 176: case 177:
00146 case 178: case 179: case 180: case 181: case 182: case 183: case 184:
00147 case 185: case 186: case 187: case 188: case 189: case 190: case 191:
00148 case 192: case 193: case 194: case 195: case 196: case 197: case 198:
00149 case 199: case 200: case 201: case 202: case 203: case 204: case 205:
00150 case 206: case 207: case 208: case 209: case 210: case 211: case 212:
00151 case 213: case 214: case 215: case 216: case 217: case 218: case 219:
00152 case 220: case 221: case 222: case 223: case 224: case 225: case 226:
00153 case 227: case 228: case 229: case 230: case 231: case 232: case 233:
00154 case 234: case 235: case 236: case 237: case 238: /* font selection commands */
00155          if (cmd < 235) fnt = cmd - 171 ; /* fntnum0 thru fntnum63 */
00156          else {
00157             fnt = dvibyte() ; /* fnt1 */
00158             while (cmd-- > 235)
00159                fnt = (fnt << 8) + dvibyte() ;
00160          }
00161          for (cfnt=ffont; cfnt; cfnt = cfnt->next)
00162             if (cfnt->fontnum == fnt) goto fontfound ;
00163          error("! no font selected") ;
00164 fontfound:  curfnt = cfnt->desc ;
00165          ppreselectfont(curfnt) ;
00166          break ;
00167 case 239: predospecial((integer)dvibyte(), 1) ; break ; /* xxx1 */
00168 case 240: predospecial((integer)twobytes(), 1) ; break ; /* xxx2 */
00169 case 241: predospecial(threebytes(), 1) ; break ; /* xxx3 */
00170 case 242: predospecial(signedquad(), 1) ; break ; /* xxx4 */
00171 case 243: case 244: case 245: case 246: fontdef(cmd-242) ; break ; /* fntdef1 */
00172 case 140: /* eop or end of virtual char */
00173          if (curpos) {
00174             --frp ;
00175             curfnt = frp->curf ;
00176             ffont = frp->ff ;
00177             curlim = frp->curl ;
00178             curpos = frp->curp ;
00179             break ;
00180          }
00181          return ;
00182       }
00183    }
00184 }
00185 /*
00186  *   Finally, here's our main pprescan routine.
00187  */
00188 static integer firstmatch = -1, lastmatch = -1 ;
00189 void
00190 pprescanpages P1H(void)
00191 {
00192    register int cmd ;
00193    integer lmaxpages = maxpages ;
00194    integer mpagenum ;
00195    integer pageseq = 0 ;
00196    int ntfirst = notfirst ;
00197 
00198    pprescan = 1 ;
00199    readpreamble() ;
00200 /*
00201  *   Now we look for the first page to process.  If we get to the end of
00202  *   the file before the page, we complain (fatally).
00203  *   Incidentally, we don't use the DVI file's bop backpointer to skip
00204  *   over pages at high speed, because we want to look to for special
00205  *   header that might be in skipped pages.
00206  */
00207    while (1) {
00208       cmd = skipnop() ;
00209       if (cmd==248)
00210          error("! End of document before first specified page") ;
00211       if (cmd!=139)
00212          error("! Bad DVI file: expected bop") ;
00213       pagenum = signedquad() ;
00214       pageseq++ ;
00215       mpagenum = abspage ? pageseq : pagenum ;
00216       if (mpagenum == firstpage && ntfirst)
00217          firstmatch++ ;
00218       if (mpagenum == lastpage && notlast)
00219          lastmatch++ ;
00220       if (ntfirst && mpagenum == firstpage && firstmatch == firstseq)
00221          ntfirst = 0 ;
00222       if (ntfirst ||
00223          ((evenpages && (pagenum & 1)) || (oddpages && (pagenum & 1)==0) ||
00224           (pagelist && !InPageList(pagenum)))) {
00225          skipover(40) ;
00226          skippage() ;
00227       } else {
00228          if (notlast && mpagenum == lastpage)
00229             lastmatch-- ;
00230          break ;
00231       }
00232    }
00233 /*
00234  *   Here we scan for each of the sections.  First we initialize some of
00235  *   the variables we need.  We don't have to be as smart as before in
00236  *   skipping pages.
00237  */
00238    skipover(40) ;
00239    while (lmaxpages > 0) {
00240       if (!(evenpages && (pagenum & 1)) &&
00241          !(oddpages && (pagenum & 1)==0) &&
00242          !(pagelist && !InPageList(pagenum))) {
00243          pscanpage() ;
00244          lmaxpages-- ;
00245       } else
00246          skippage() ;
00247       mpagenum = abspage ? pageseq : pagenum ;
00248       if (mpagenum == lastpage && notlast)
00249          lastmatch++ ;
00250       if (notlast && mpagenum == lastpage && lastmatch == lastseq)
00251          lmaxpages = -1 ; /* we are done after this page. */
00252       cmd=skipnop() ;
00253       if (cmd==248) break ;
00254       if (cmd!=139)
00255          error("! Bad DVI file: expected bop") ;
00256       pagenum = signedquad() ;
00257       skipover(40) ;
00258       pageseq++ ;
00259    }
00260    fseek(dvifile, 0L, 0) ;
00261    pprescan = 0 ;
00262 }