-- TexMain.mesa -- Mesa 6 version -- Last changed by Doug Wyatt, September 23, 1980 5:32 PM DIRECTORY TexAlignDefs: FROM "TexAlignDefs", TexDebugDefs: FROM "TexDebugDefs", TexDefs: FROM "TexDefs", TexErrorDefs: FROM "TexErrorDefs", TexGlueDefs: FROM "TexGlueDefs", TexIODefs: FROM "TexIODefs", TexJustifyDefs: FROM "TexJustifyDefs", TexMainDefs: FROM "TexMainDefs", TexMathDefs: FROM "TexMathDefs", TexNodeDefs: FROM "TexNodeDefs", TexOutputDefs: FROM "TexOutputDefs", TexPackDefs: FROM "TexPackDefs", TexSynDefs: FROM "TexSynDefs", TexTableDefs: FROM "TexTableDefs", TexTokenDefs: FROM "TexTokenDefs", ImageDefs: FROM "ImageDefs", TimeDefs: FROM "TimeDefs"; TexMain: PROGRAM IMPORTS TexAlignDefs,TexDebugDefs,TexErrorDefs,TexGlueDefs, TexIODefs,TexJustifyDefs,TexMainDefs,TexMathDefs,TexNodeDefs, TexOutputDefs,TexPackDefs,TexSynDefs,TexTableDefs, ImageDefs,TimeDefs EXPORTS TexMainDefs = BEGIN OPEN TexMainDefs,TexTableDefs,TexNodeDefs,TexSynDefs,TexDefs; CursorArray: TYPE = ARRAY [0..16) OF CARDINAL; -- here's the TEX cursor texCursor: CursorArray = [ 000000B, 176167B, 132062B, 030074B, 037734B, 033130B, 033014B, 033234B, 033636B, 033246B, 077167B, 003000B, 003100B, 007700B, 000000B, 000000B ]; cursorLoc: POINTER TO CursorArray = LOOPHOLE[431B]; Unimplemented: PUBLIC SIGNAL = CODE; Continue: PUBLIC SIGNAL = CODE; Reswitch: PUBLIC SIGNAL = CODE; FallThru: PUBLIC SIGNAL = CODE; Undefined: PUBLIC SIGNAL = CODE; CantDoThat: PUBLIC SIGNAL[mode: ModeType, restricted: BOOLEAN] = CODE; Herald: PROCEDURE = BEGIN OPEN TexIODefs,TimeDefs; time: STRING_[20]; AppendDayTime[time,UnpackDT[ImageDefs.BcdTime[]]]; Cr; Ws["Mesa\TEX of "L]; Ws[time]; Cr; END; MainControl: PUBLIC PROCEDURE = BEGIN OPEN TexIODefs,TexErrorDefs; page: CARDINAL_0; cursorLoc^ _ texCursor; TexDebugDefs.ShowMem["entering MainControl"]; TexOutputDefs.InitOut; Herald; BEGIN ENABLE BEGIN EndOfTex => CONTINUE; PageEnd => RESUME; Undefined => BEGIN Error["Undefined control sequence"L]; RESUME END; Unimplemented => BEGIN Error["This case not implemented"L]; RESUME END; CantDoThat => BEGIN BeginError; Ws["You can't do that in "L]; WMode[mode, restricted]; Ws[" mode"L]; Error[EndError[]]; RESUME; END; UndefinedFont => BEGIN PausingOnErrors[FALSE]; Error["Whoa--you have to define a font first"L]; CONTINUE; END; TexPackDefs.OverfullBox => BEGIN IF CurTracing[].reportoverfull THEN BEGIN OPEN TexIODefs; Ps["Overfull box, "L]; Wn[excess]; Ws[" micas too "L]; Ws[SELECT box.dir FROM hlist=>"wide"L, vlist=>"high"L, ENDCASE=>ERROR]; Wc[':]; -- *** then display the box END; RESUME; END; END; mainvlist: NodeListPtr _ InitNodeList[]; mainvhead: VHead_[mainvlist,pflag]; PausingOnErrors[TRUE]; VMode[@mainvhead, FALSE !EndOfTex => CONTINUE]; -- call the page builder END; TexOutputDefs.CloseOut[1]; TexDebugDefs.ShowMem["leaving MainControl"]; END; -- **************************** -- mode-independent commands -- **************************** Ddt: SIGNAL = CODE; CommonCmd: PUBLIC PROCEDURE = BEGIN WITH cc:curchar SELECT curcmd FROM undefined => SIGNAL Undefined; tabmrk,carret => SIGNAL Unimplemented; call => MacroCall[]; assignreal => { t: DimnParamType=cc.dimnparam; SetDimnParam[t, ScanLength[]]; }; assignglue => { t: GlueParamType=cc.glueparam; SetGlueParam[t, ScanGlueSpec[]]; }; def => MacroDef[cc.deftype]; output => SetOutputRoutine[ScanToks[output]]; ddt => SIGNAL Ddt; chcode => DoChng[cc.chngtype]; setcount => DoSetCount[]; advcount => DoAdvCount[]; count => DoCount[]; ifeven => DoIfEven[cc.iftype]; ifT => DoIfT[]; save => DoSave[]; topbotmark => DoTopBotMark[cc.marktype]; newaccent => SIGNAL Unimplemented; ENDCASE => SIGNAL FallThru; -- couldn't handle curcmd END; DoChng: PUBLIC PROCEDURE[type: ChngType] = BEGIN a,b: CARDINAL; a_ScanNumber[]; -- which parameter or character code GetNCTok; -- this token is ignored, it might be space or = or _, etc. IF curcmd=endv THEN TexErrorDefs.BackError["Missing } inserted"L]; b_ScanNumber[]; -- new value *** can this be negative? SELECT type FROM code => ChangeCode[a, b]; par => ChangePar[a, b]; ENDCASE => ERROR; -- bad ChngType END; savedbox: ARRAY Digit OF BoxNodePtr _ ALL[NIL]; nCharTypes: CARDINAL=13; CharTypeIndex: TYPE = [0..nCharTypes); mapCharType: ARRAY CharTypeIndex OF CharType = [escape,lbrace,rbrace,mathbr,tabmrk,carret,macprm, supmrk,submrk,ignore,spacer,letter,otherchar]; ChangeCode: PROCEDURE[char, val: CARDINAL] = BEGIN CharRange: TYPE = CARDINAL[LOOPHOLE[FIRST[Char]]..LOOPHOLE[LAST[Char]]]; IF char NOT IN CharRange THEN BEGIN TexErrorDefs.Error["bad character code"L]; RETURN END; IF val NOT IN CharTypeIndex THEN BEGIN TexErrorDefs.Error["bad character type"L]; RETURN END; SetChType[LOOPHOLE[char,Char], mapCharType[val]]; END; nTexPars: CARDINAL=10; TexParIndex: TYPE = [0..nTexPars); mapTexParType: ARRAY TexParIndex OF TexParamType = [tracing,jpar,hpen,penpen,wpen,bpen,mbpen,mrpen,ragged,disppen]; ChangePar: PROCEDURE[par, val: CARDINAL] = BEGIN typ: TexParamType; texpar: TexPar; IF par NOT IN TexParIndex THEN BEGIN TexErrorDefs.Error["bad texpar code"L]; RETURN END; typ_mapTexParType[par]; WITH tp:texpar SELECT typ FROM jpar,hpen,penpen,wpen,bpen,mbpen,mrpen,disppen => tp.penalty_val; ragged => tp.ragged_val; tracing => tp.tracing_LOOPHOLE[val,TraceInfo]; ENDCASE => ERROR; -- bad TexParamType SetTexParam[typ, texpar]; END; DoSetCount: PUBLIC PROCEDURE = BEGIN d: Digit_ScanDigit[]; SetKount[d,ScanInteger[]]; END; DoAdvCount: PUBLIC PROCEDURE = BEGIN d: Digit_ScanDigit[]; inc: INTEGER; oldkount: INTEGER_Kount[d]; IF ScanString["by"L] THEN inc_ScanInteger[] ELSE inc_(IF oldkount<0 THEN -1 ELSE 1); SetKount[d,oldkount+inc]; END; DoCount: PUBLIC PROCEDURE = BEGIN d: Digit_ScanDigit[]; InsNum[Kount[d], decimal]; END; DoIfEven: PUBLIC PROCEDURE[t: IfType] = BEGIN d: Digit_ScanDigit[]; SELECT t FROM even => ScanCond[(Kount[d] MOD 2)=0]; pos => ScanCond[Kount[d]>0]; ENDCASE => ERROR; -- bad IfType END; DoIfT: PUBLIC PROCEDURE = BEGIN t: TexTokenDefs.Token; GetNCTok; t_curtok; GetNCTok; ScanCond[curtok=t]; -- *** several tests for endv have been omitted here -- Although an endv code is unlikely here, it is best to make sure that -- endv can't be gobbled up under any circumstances END; ScanCond: PROCEDURE[b: BOOLEAN] = BEGIN IF b THEN BEGIN ScanLB; NewSaveLevel[trueend] END ELSE BEGIN PassBlock; -- skip the true part GetNCTok; IF curcmd#elsecode THEN TexErrorDefs.BackError["\else required here"L]; ScanLB; NewSaveLevel[falseend]; END; END; TrueEnd: PUBLIC PROCEDURE = BEGIN UnSave[trueend]; -- unwind the savestack ScanNonSpacer; -- find the next non-spacer, which should be \else IF curcmd#elsecode THEN TexErrorDefs.BackError["Missing \else inserted"L]; PassBlock; -- bypass the else clause END; FalseEnd: PUBLIC PROCEDURE = BEGIN UnSave[falseend]; -- just unwind the savestack ScanSpacer; -- and ignore any spacers after } END; DoSave: PUBLIC PROCEDURE = BEGIN d: Digit_ScanDigit[]; oldbox, newbox: BoxNodePtr; newbox_ScanBox[]; -- may SIGNAL Reswitch IF (oldbox_savedbox[d])#NIL THEN DsNode[oldbox]; savedbox[d]_newbox; END; DoTopBotMark: PUBLIC PROCEDURE[t: MarkType] = BEGIN p: TexTokenDefs.TokenListPtr_Mark[t]; IF p#NIL THEN BEGIN InsRCList[p]; NewSaveLevel[simpleblock] END; END; DoFntFam: PUBLIC PROCEDURE[mfont: TexMathDefs.MFont] = BEGIN OPEN TexMathDefs; msize: MathSize; f: Font; IF mfont=ex THEN BEGIN f_ScanFont[]; FOR msize IN MathSize DO TexTableDefs.SetMathFont[MFTIndex[mfont,msize],f]; ENDLOOP; END ELSE BEGIN FOR msize IN MathSize DO f_ScanFont[]; TexTableDefs.SetMathFont[MFTIndex[mfont,msize],f]; ENDLOOP; END; END; ScanPenltyNode: PUBLIC PROCEDURE RETURNS[NodePtr] = BEGIN n: Penalty_ScanInteger[]; -- ***** test for overflow/underflow? RETURN[MakePenaltyNode[n]]; END; -- ***** miscellaneous procedures InterLineGlue: PUBLIC PROCEDURE[delta: Dimn, p: TexGlueDefs.GluePtr] RETURNS[TexGlueDefs.GluePtr] = BEGIN OPEN TexGlueDefs; -- returns a pointer to glue specification that makes up for -- baseline distance deficiency of delta, when p points to the -- \baselineskip glue q: GluePtr; IF delta>=DimnParam[lineskiplimit] THEN BEGIN -- the normal baseline spacing was not exceeded q_MakeGlue[]; q.space_delta; q.flex_p.flex; END ELSE -- use lineskip glue if baseline distance is already large q_GlueParam[lineskip]; RETURN[q]; END; ScanRuleNode: PUBLIC PROCEDURE RETURNS[NodePtr] = BEGIN w,h,d: Dimn; [width: w, height: h, depth: d]_ScanRuleSpec[]; RETURN[MakeRuleNode[width: w, height: h, depth: d]]; END; ScanGlueSpec: PUBLIC PROCEDURE RETURNS[TexGlueDefs.GluePtr] = BEGIN OPEN TexGlueDefs; p: GluePtr_MakeGlue[]; ScanGlue[p]; RETURN[p]; END; ScanMovedBox: PUBLIC PROCEDURE[neg: BOOLEAN] RETURNS[BoxNodePtr] = BEGIN shft: Dimn_ScanLength[]; box: BoxNodePtr_ScanBox[]; IF neg THEN shft_-shft; box.shiftamt_shft; RETURN[box]; END; SkipGlue: PUBLIC PROCEDURE[gluetype: TexGlueDefs.GlueType] RETURNS[NodePtr] = BEGIN OPEN TexGlueDefs; p: GluePtr; IF gluetype=skip THEN p_ScanGlueSpec[] ELSE p_CommonGlue[gluetype]; RETURN[MakeGlueNode[p]]; END; DoTopBotIns: PUBLIC PROCEDURE[tb: TopBotType, dir: Direction, Store: PROCEDURE[NodePtr]] = BEGIN OPEN TexGlueDefs; ec: EndingCode_SELECT tb FROM top=>topinsend,bot=>botinsend,ENDCASE=>ERROR; inslist: NodeListPtr_InitNodeList[]; vhead: VHead_[inslist,pflag]; p: InsNodePtr; b: BoxNodePtr; q: GluePtr; flexsums: FlexSums; TotalFlex: PROCEDURE[sums: FlexSumsPtr] RETURNS[f: ARRAY FlexDir OF Flex] = BEGIN dir: FlexDir; FOR dir IN FlexDir DO f[dir]_DominantFlex[@sums[dir]] ENDLOOP; END; ScanLB; -- *** perhaps this should not skip spacers NewSaveLevel[ec]; VMode[@vhead, TRUE]; UnSave[ec]; SELECT tb FROM top => -- append topskip glue at end of vlist BEGIN p: NodePtr_MakeGlueNode[GlueParam[topskip]]; StoreNode[inslist, p]; END; bot => -- insert botskip glue at beginning of vlist BEGIN p: NodePtr_MakeGlueNode[GlueParam[botskip]]; p.link_inslist.link; inslist.link_p; END; ENDCASE => ERROR; -- bad TopBotType b_TexPackDefs.VPackage[list: inslist, desiredheight: 0, xpand: TRUE, page: FALSE, flexsums: @flexsums]; q_MakeGlue[]; AddGlueLink[q]; q.space_b.height+b.depth; q.flex_TotalFlex[@flexsums]; p_MakeInsNode[tb, dir, b.head, q]; b.head_NIL; DsNode[b]; Store[p]; END; ScanLeaders: PUBLIC PROCEDURE RETURNS[NodePtr] = BEGIN p: NodePtr; GetNCNext[]; WITH cc:curchar SELECT curcmd FROM hrule,vrule => p_ScanRuleNode[]; box => p_GetBox[cc.boxtype]; ENDCASE => BEGIN TexErrorDefs.Error["A box or rule specification was supposed to be here"L]; ERROR Reswitch; END; RETURN[MakeLeaderNode[p]]; END; ScanBox: PROCEDURE RETURNS[BoxNodePtr] = BEGIN GetNCNext[]; WITH cc:curchar SELECT curcmd FROM box => RETURN[GetBox[cc.boxtype]]; ENDCASE; TexErrorDefs.Error["A box specification was supposed to be here"L]; ERROR Reswitch; END; GetBox: PUBLIC PROCEDURE[type: BoxType] RETURNS[p: BoxNodePtr] = BEGIN SELECT type FROM hbox,vbox => BEGIN len: Dimn; xpand, break: BOOLEAN; list: NodeListPtr_InitNodeList[]; size: Dimn_DimnParam[IF type=vbox THEN vsize ELSE hsize]; [len,xpand,break]_ScanSpec[type=hbox, size]; IF break THEN SetHangIndent[nullHang]; -- reset hanging indent NewSaveLevel[justend]; SELECT type FROM vbox => BEGIN vhead: VHead_[list,pflag]; VMode[@vhead, TRUE]; p_TexPackDefs.VPack[list,len,xpand]; END; hbox => BEGIN hhead: HHead_[list,sfOne]; HMode[@hhead, TRUE]; IF break THEN p_Justify[list,len] ELSE p_TexPackDefs.HPack[list,len,xpand]; END; ENDCASE => ERROR; -- bad BoxType UnSave[justend]; -- box shifting to be done by caller END; box => BEGIN d: Digit_ScanDigit[]; p_savedbox[d]; IF p=NIL THEN p_NullBox[]; savedbox[d]_NIL; END; page => p_Page[]; ENDCASE => ERROR; -- bad BoxType END; Justify: PROCEDURE[q: NodeListPtr, width: Dimn] RETURNS[BoxNodePtr] = BEGIN OPEN TexGlueDefs,TexJustifyDefs; pflag: Dimn=FIRST[Dimn]; prevdepth: Dimn_pflag; begin: CARDINAL; width0,width1,indent0,indent1: Dimn; blskip: GluePtr_GlueParam[baselineskip]; nlines: CARDINAL_0; vlist: NodeListPtr_InitNodeList[]; LineWidth: LineWidthProc = BEGIN RETURN[IF line MissingMathbr; mathleft => MissingRight; ENDCASE => MissingRB; END; MissingMathbr: PUBLIC PROCEDURE = BEGIN TexErrorDefs.BackError["Missing $ inserted"]; curcmd_mathbr; curchar_[mathbr['$]]; curtok_[undefined[]]; ERROR Reswitch; END; MissingRight: PUBLIC PROCEDURE = BEGIN TexErrorDefs.BackError["Missing \right. inserted"]; InsToken[[otherchar['.]]]; curcmd_leftright; curchar_[leftright[right]]; curtok_[undefined[]]; ERROR Reswitch; END; MissingRB: PUBLIC PROCEDURE = BEGIN TexErrorDefs.BackError["Missing } inserted"]; curcmd_rbrace; curchar_[rbrace['}]]; curtok_[undefined[]]; ERROR Reswitch; END; -- write the name of the specified mode on the current output stream WMode: PROCEDURE[m: ModeType, r: BOOLEAN] = BEGIN OPEN TexIODefs; SELECT m FROM v,h => IF r THEN Ws["restricted "L]; m => IF NOT r THEN Ws["display "L]; ENDCASE; SELECT m FROM v => Ws["vertical"L]; h => Ws["horizontal"L]; m => Ws["math"L]; ENDCASE; END; END.(670)