-- TexScan.mesa -- last written by Doug Wyatt, January 19, 1980 12:20 AM DIRECTORY TexDefs: FROM "TexDefs" USING[Char,Font,Dimn,nilDimn,HangSpec,Digit,NumberStyle], TexErrorDefs: FROM "TexErrorDefs", TexFileDefs: FROM "TexFileDefs", TexFontDefs: FROM "TexFontDefs", TexGlueDefs: FROM "TexGlueDefs", TexMathDefs: FROM "TexMathDefs", TexStringDefs: FROM "TexStringDefs", TexSynDefs: FROM "TexSynDefs", TexTableDefs: FROM "TexTableDefs", TexTokenDefs: FROM "TexTokenDefs", InlineDefs: FROM "InlineDefs"; TexScan: PROGRAM IMPORTS TexErrorDefs,TexFileDefs,TexFontDefs,TexStringDefs,TexSynDefs, TexTableDefs,TexTokenDefs,InlineDefs EXPORTS TexSynDefs = BEGIN OPEN TexErrorDefs,TexSynDefs,TexGlueDefs,TexDefs; nbrlength: INTEGER←0; nbrsign: CHARACTER←'+; ScanSpacer: PUBLIC PROCEDURE = --INLINE-- BEGIN GetNCTok[]; IF curcmd#spacer THEN BackInput; END; ScanNonSpacer: PUBLIC PROCEDURE = --INLINE-- BEGIN DO GetNCTok[]; IF curcmd#spacer THEN EXIT ENDLOOP; END; ScanDigit: PUBLIC PROCEDURE RETURNS[Digit] = BEGIN d: CHARACTER; GetNCTok[]; WITH curtok SELECT FROM otherchar => d←char; ENDCASE => d←0C; IF d NOT IN ['0..'9] THEN BEGIN BackError["Missing digit (0 to 9), 0 inserted"L]; d←'0; END; ScanSpacer[]; RETURN[d-'0]; END -- of ScanDigit --; ScanLB: PUBLIC PROCEDURE = BEGIN ScanNonSpacer; IF curcmd#lbrace THEN BackError["Missing { inserted"L]; END; ScanString: PUBLIC PROCEDURE[s: STRING] RETURNS[BOOLEAN] = BEGIN OPEN TexTokenDefs; q: TokenPtr; i,j: CARDINAL; temphead: TokenLEntry←nilTokenLEntry; FOR i IN [0..s.length) DO GetNCTok[]; IF NOT CurCharMatches[s[i]] THEN BEGIN q←@temphead; FOR j IN [0..i) DO StoreTok[@q,MakeCharTok[s[j]]] ENDLOOP; StoreTok[@q,curtok]; InsList[temphead.link]; RETURN[FALSE]; END; ENDLOOP; RETURN[TRUE]; END -- of ScanString --; MakeCharTok: PROCEDURE[c: Char] RETURNS[t: TexTokenDefs.Token] = BEGIN SELECT TexTableDefs.ChType[c] FROM macprm => t←[macprm[c]]; mathbr => t←[mathbr[c]]; tabmrk => t←[tabmrk[c]]; supmrk => t←[supmrk[c]]; submrk => t←[submrk[c]]; spacer => t←[spacer[c]]; letter => t←[letter[c]]; otherchar => t←[otherchar[c]]; ENDCASE => ERROR Confusion; RETURN[t]; END; CurCharMatches: PROCEDURE[c: Char] RETURNS[BOOLEAN] = BEGIN WITH cc:curchar SELECT curcmd FROM macprm,lbrace,rbrace,mathbr,tabmrk, supmrk,submrk,spacer,letter,otherchar => RETURN[cc.char=c]; ENDCASE; RETURN[FALSE]; END; ScanLongNumber: PROCEDURE RETURNS[LONG CARDINAL] = BEGIN bign: LONG CARDINAL; nbrlength←0; nbrsign←'+; ScanNonSpacer; SELECT curtok FROM [otherchar['-]] => BEGIN nbrsign←'-; ScanNonSpacer END; [otherchar['+]] => ScanNonSpacer; ENDCASE; WITH cc:curchar SELECT curcmd FROM count => BEGIN bign←TexTableDefs.Kount[ScanDigit[]]; GetNCTok END; letter => BEGIN bign←LOOPHOLE[cc.char,CARDINAL]; GetNCTok END; ENDCASE => BEGIN digit: BOOLEAN; d: CARDINAL; radix: CARDINAL←10; IF curtok=[otherchar['']] THEN BEGIN radix←8; GetNCTok END; bign←0; DO [digit,d]←CurDigit[]; IF NOT digit THEN EXIT; bign←radix*bign+d; nbrlength←nbrlength+1; GetNCTok; ENDLOOP; END; IF curcmd#spacer THEN BackInput; RETURN[bign]; END; ScanNumber: PUBLIC PROCEDURE RETURNS[n: CARDINAL] = BEGIN bign: LONG CARDINAL←ScanLongNumber[]; IF InlineDefs.HighHalf[bign]>0 THEN BEGIN Error["Number bigger than 65535"L]; bign←LAST[CARDINAL] END; RETURN[InlineDefs.LowHalf[bign]]; END; CurDigit: PROCEDURE RETURNS[isdigit: BOOLEAN, d: [0..9]] = BEGIN WITH cc:curchar SELECT curcmd FROM otherchar => IF cc.char IN['0..'9] THEN RETURN[TRUE,cc.char-'0]; ENDCASE; RETURN[FALSE,0]; END; ScanFrac: PROCEDURE RETURNS[n: CARDINAL] = BEGIN OPEN InlineDefs; pofTen: CARDINAL←1; longn: LongNumber; digit: BOOLEAN; d: CARDINAL; n←0; ScanNonSpacer[]; DO [digit,d]←CurDigit[]; IF NOT digit THEN EXIT; IF pofTen<=1000 THEN BEGIN n←10*n+d; pofTen←pofTen*10 END; GetNCTok[]; ENDLOOP; IF curcmd#spacer THEN BackInput; longn←LongNumber[num[0,n]]; RETURN[LongDiv[longn.lc,pofTen]]; END -- of ScanFrac --; ScanLongLength: PROCEDURE RETURNS[LONG CARDINAL] = BEGIN magnify: BOOLEAN←TRUE; x: LONG CARDINAL; f: CARDINAL←0; Scale: PROCEDURE [int,frac: CARDINAL] = BEGIN OPEN InlineDefs; t2,t3,t4: LongNumber; t2.lc←x*frac; t3.lc←LongMult[f,int]; t4.lc←LongMult[f,frac]; t4.lc←t2.lowbits+t3.lowbits+t4.highbits+LONG[0]; x←x*int+t2.highbits+t3.highbits+t4.highbits +(IF t4.lowbits>77777B THEN 1 ELSE 0); END; x←ScanNumber[]; GetNCTok[]; IF curtok=[otherchar['.]] THEN f←ScanFrac[] ELSE BackInput; IF ScanString["true"L] THEN magnify←FALSE; SELECT TRUE FROM ScanString["mc"L] => Scale[1,0]; ScanString["pt"L] => Scale[35,9567]; -- 35.14598 ScanString["in"L] => Scale[2540,0]; ScanString["pc"L] => Scale[421,49267]; --421.75176 ScanString["cm"L] => Scale[1000,0]; ScanString["mm"L] => Scale[100,0]; ScanString["dd"L] => Scale[37,38927]; --37.59398496 ScanString["vu"L] => Scale[TexTableDefs.DimnParam[varunit],0]; ScanString["em"L] => BEGIN curfont: Font←TexTableDefs.CurFont[]; Scale[TexFontDefs.FontPar[curfont,quad],0]; END; ENDCASE => BEGIN Scale[35,9567]; Error["Illegal unit of measure (pt inserted)"L]; END; ScanSpacer[]; -- *** for debugging, introduce rfudge IF magnify THEN Scale[1,14632B]; -- 1.1 RETURN[x]; END -- of ScanLongLength --; ScanLength: PUBLIC PROCEDURE RETURNS[n: Dimn] = BEGIN x: LONG CARDINAL←ScanLongLength[]; IF x<=77777B THEN n←InlineDefs.LowHalf[x] ELSE BEGIN Error["Length greater than 32767 micas"L]; n←LAST[Dimn]; END; RETURN[IF nbrsign='+ THEN n ELSE -n]; END -- of ScanLength --; epsilonDimn: Dimn=1; ScanPosLength: PUBLIC PROCEDURE RETURNS[Dimn] = BEGIN r: Dimn←ScanLength[]; IF r>0 THEN RETURN[r]; IF r<0 THEN Error["This dimension shouldn't be negative"L]; RETURN[epsilonDimn]; END -- of ScanPosLength --; ScanFlex: PUBLIC PROCEDURE RETURNS[f: Flex] = BEGIN x: LONG CARDINAL; n: Dimn; ScanSpacer[]; f.order←(SELECT TRUE FROM ScanString["regular"L] => regular, ScanString["lowerfill"L] => lowerfill, ScanString["fill"L] => fill, ENDCASE => regular); x←ScanLongLength[]; IF x>77777B THEN BEGIN x←LongRShift[x,15]; f.order←fill END; n←InlineDefs.LowHalf[x]; f.val←IF nbrsign='+ THEN n ELSE -n; RETURN[f]; END -- of ScanFlex --; ScanGlue: PUBLIC PROCEDURE[g: GluePtr] = BEGIN g.space←ScanLength[]; g.flex←[zeroFlex,zeroFlex]; IF ScanString["plus"L] THEN g.flex[str]←ScanFlex[]; IF ScanString["minus"L] THEN g.flex[shr]←ScanFlex[]; END -- of ScanGlue --; ScanSpec: PUBLIC PROCEDURE[parok: BOOLEAN, size: Dimn] RETURNS[len: Dimn, xpand, break: BOOLEAN] = BEGIN break←FALSE; IF ScanString["to"L] OR (break←(parok AND ScanString["par"L])) THEN BEGIN xpand←FALSE; ScanSpacer; len←IF ScanString["size"L] THEN size ELSE ScanLength[]; END ELSE BEGIN xpand←TRUE; len←IF ScanString["expand"L] THEN ScanLength[] ELSE 0; END; ScanLB; END -- of ScanSpec --; ScanHang: PUBLIC PROCEDURE RETURNS[HangSpec] = BEGIN hang: HangSpec; hang.width←ScanLength[]; SELECT TRUE FROM ScanString["for"L] => BEGIN hang.begin←ScanNumber[]; hang.first←TRUE END; ScanString["after"L] => BEGIN hang.begin←ScanNumber[]; hang.first←FALSE END; ENDCASE => BEGIN hang.begin←1; hang.first←FALSE END; RETURN[hang]; END; ScanFileName: PUBLIC PROCEDURE [filename: STRING] = BEGIN OPEN TexStringDefs; c: Char; filename.length←0; DO GetNCTok[]; WITH cc:curchar SELECT curcmd FROM spacer => EXIT; macprm,lbrace,rbrace,mathbr,tabmrk,supmrk,submrk,letter,otherchar => c←cc.char; ENDCASE => BEGIN BackError["Blank space should follow file name"L]; EXIT END; AppendChar[filename,c]; ENDLOOP; END -- of ScanFileName --; ScanFont: PUBLIC PROCEDURE RETURNS[Font] = BEGIN OPEN TexFontDefs; f: Font; DO GetNCTok; IF curtok.cmd=ctrlseq THEN BackError["Illegal Font Code"L] ELSE EXIT; ENDLOOP; f←LOOPHOLE[InlineDefs.BITAND[curchar,37B]]; GetNCTok; IF FontDefined[f] THEN BEGIN IF curcmd#spacer THEN BackInput END ELSE BEGIN c: Char; DO c←TexTokenDefs.TokChar[curtok]; IF c='= OR c='← THEN EXIT; BackError["First use of font must define it"L]; GetNCTok; ENDLOOP; DefineFont[f]; END; RETURN[f]; END -- of ScanFont --; DefineFont: PROCEDURE[f: TexDefs.Font] = BEGIN filename: STRING←[TexFileDefs.filenamesize]; ScanFileName[filename]; TexFileDefs.StripExtension[filename]; TexFontDefs.ReadFontInfo[filename,f]; END; NumToMChar: PROCEDURE[n: CARDINAL] RETURNS[TexMathDefs.MChar] = BEGIN mfontmap: ARRAY [0..3] OF TexMathDefs.MFont = [rm,it,sy,ex]; Bits: TYPE = MACHINE DEPENDENT RECORD[x:[0..177B], f:[0..3B], c:[0..177B]]; bits: Bits=LOOPHOLE[n]; RETURN[[mfont: mfontmap[bits.f], char: LOOPHOLE[bits.c,Char]]]; END; ScanMChar: PUBLIC PROCEDURE RETURNS[TexMathDefs.MChar] = BEGIN RETURN[NumToMChar[ScanNumber[]]] END; LongRShift: PROCEDURE[n: LONG CARDINAL, shift: [0..15]] RETURNS[LONG CARDINAL] = BEGIN OPEN InlineDefs; hi,lo: CARDINAL; result: LongNumber; hi←HighHalf[n]; lo←LowHalf[n]; result.highbits←BITSHIFT[hi,-shift]; result.lowbits←BITOR[BITSHIFT[hi,16-shift],BITSHIFT[lo,-shift]]; RETURN[result.lc]; END; ScanDelim: PUBLIC PROCEDURE RETURNS[TexMathDefs.Delimiter] = BEGIN OPEN TexMathDefs; GetNCTok; WITH cc:curchar SELECT curcmd FROM otherchar => BEGIN defined: BOOLEAN; delim: Delimiter; [defined,delim]←TexTableDefs.DelimLookup[cc.char]; IF defined THEN RETURN[delim]; END; mathonly => BEGIN mch: MChar←cc.tmchar.mchar; IF mch.mfont=sy AND mch.char IN Char[142C..153C] THEN BEGIN largechar: MChar←[ex,mch.char-(142B-4B)]; -- *** Note the built-in dependency on the relationship -- between the symbol and mathex fonts! RETURN[[small: [TRUE,mch], large: [TRUE,largechar]]]; END; END; ascii => BEGIN OPEN InlineDefs; DChar: PROCEDURE[n: CARDINAL] RETURNS[DelimChar] = BEGIN IF n=0 THEN RETURN[nullDelimChar] ELSE RETURN[[TRUE,NumToMChar[n]]] END; nsm,nlg: CARDINAL; bign: LONG CARDINAL←ScanLongNumber[]; nsm←BITAND[LowHalf[LongRShift[bign,9]],777B]; nlg←BITAND[LowHalf[bign],777B]; RETURN[[small: DChar[nsm], large: DChar[nlg]]]; END; ENDCASE; BackError["Unknown Delimiter"L]; RETURN[nullDelimiter]; END -- of ScanDelim --; defaultRuleDimn: Dimn=14; -- approximately 0.4 points ScanRuleSpec: PUBLIC PROCEDURE RETURNS[width,height,depth: Dimn] = BEGIN IF curcmd=hrule THEN BEGIN width←nilDimn; height←defaultRuleDimn; depth←0; END ELSE BEGIN width←defaultRuleDimn; height←nilDimn; depth←nilDimn; END; DO SELECT TRUE FROM ScanString["width"L] => width←ScanPosLength[]; ScanString["height"L] => height←ScanPosLength[]; ScanString["depth"L] => depth←ScanPosLength[]; ENDCASE => EXIT; ENDLOOP; RETURN[width,height,depth]; END -- of ScanRuleSpec --; PassBlock: PUBLIC PROCEDURE = BEGIN unbal: INTEGER←0; DO -- ScanToks with no StoreItems GetTok[]; SELECT curcmd FROM lbrace => unbal←unbal+1; rbrace => IF (unbal←unbal-1)<=0 THEN EXIT; ENDCASE; ENDLOOP; IF unbal<0 THEN Error["Missing { inserted"L]; ScanSpacer[]; END -- of PassBlock --; InsNum: PUBLIC PROCEDURE[n: CARDINAL, style: NumberStyle] = BEGIN OPEN TexTokenDefs; p,q: TokenPtr; j,k: INTEGER; SELECT style FROM decimal => BEGIN p←NIL; DO q←MakeTokenLEntry[[otherchar[(n MOD 10)+'0]]]; q.link←p; p←q; n←n/10; IF n=0 THEN EXIT; ENDLOOP; END; roman => BEGIN romval: ARRAY [1..7] OF CARDINAL ← [1000,500,100,50,10,5,1]; romtok: ARRAY [1..7] OF CHARACTER ← ['m,'d,'c,'l,'x,'v,'i]; temphead: TokenLEntry←nilTokenLEntry; q←@temphead; j←1; DO WHILE n>=romval[j] DO StoreTok[@q,[letter[romtok[j]]]]; n←n-romval[j]; ENDLOOP; IF n=0 THEN EXIT; k←j+1+(IF (j MOD 2)=0 THEN 0 ELSE 1); IF n+romval[k]>=romval[j] THEN BEGIN StoreTok[@q,[letter[romtok[j]]]]; n←n+romval[k]; END ELSE j←j+1; ENDLOOP; p←temphead.link; END; ENDCASE; InsList[p]; END -- of InsNum --; ScanInteger: PUBLIC PROCEDURE RETURNS[INTEGER] = BEGIN n: INTEGER←ScanNumber[]; RETURN[IF nbrsign='- THEN -n ELSE n]; -- *** will do for now END; ScanAscii: PUBLIC PROCEDURE RETURNS[Char] = BEGIN n: CARDINAL←ScanNumber[]; RETURN[LOOPHOLE[n MOD 200B]]; END; END -- of TexScan --.