| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273 |
- // Code generated by '[/tmp/go-build3521972418/b001/exe/generate]', DO NOT EDIT.
- // % This program is copyright (C) 1982 by D. E. Knuth; all rights are reserved.
- // % Unlimited copying and redistribution of this file are permitted as long
- // % as this file is not modified. Modifications are permitted, but only if
- // % the resulting file is not named tex.web. (The WEB system provides
- // % for alterations via an auxiliary file; the master file should stay intact.)
- // % See Appendix H of the WEB manual for hints on how to install this program.
- // % And see Appendix A of the TRIP manual for details about how to validate it.
- //
- // % TeX is a trademark of the American Mathematical Society.
- // % METAFONT is a trademark of Addison-Wesley Publishing Company.
- //
- // % Version 0 was released in September 1982 after it passed a variety of tests.
- // % Version 1 was released in November 1983 after thorough testing.
- // % Version 1.1 fixed ``disappearing font identifiers'' et alia (July 1984).
- // % Version 1.2 allowed `0' in response to an error, et alia (October 1984).
- // % Version 1.3 made memory allocation more flexible and local (November 1984).
- // % Version 1.4 fixed accents right after line breaks, et alia (April 1985).
- // % Version 1.5 fixed \the\toks after other expansion in \edefs (August 1985).
- // % Version 2.0 (almost identical to 1.5) corresponds to "Volume B" (April 1986).
- // % Version 2.1 corrected anomalies in discretionary breaks (January 1987).
- // % Version 2.2 corrected "(Please type...)" with null \endlinechar (April 1987).
- // % Version 2.3 avoided incomplete page in premature termination (August 1987).
- // % Version 2.4 fixed \noaligned rules in indented displays (August 1987).
- // % Version 2.5 saved cur_order when expanding tokens (September 1987).
- // % Version 2.6 added 10sp slop when shipping leaders (November 1987).
- // % Version 2.7 improved rounding of negative-width characters (November 1987).
- // % Version 2.8 fixed weird bug if no \patterns are used (December 1987).
- // % Version 2.9 made \csname\endcsname's "relax" local (December 1987).
- // % Version 2.91 fixed \outer\def\a0[]\a\a bug (April 1988).
- // % Version 2.92 fixed \patterns, also file names with complex macros (May 1988).
- // % Version 2.93 fixed negative halving in allocator when mem_min<0 (June 1988).
- // % Version 2.94 kept open_log_file from calling fatal_error (November 1988).
- // % Version 2.95 solved that problem a better way (December 1988).
- // % Version 2.96 corrected bug in "Infinite shrinkage" recovery (January 1989).
- // % Version 2.97 corrected blunder in creating 2.95 (February 1989).
- // % Version 2.98 omitted save_for_after at outer level (March 1989).
- // % Version 2.99 caught $$\begingroup\halign..$$ (June 1989).
- // % Version 2.991 caught .5\ifdim.6... (June 1989).
- // % Version 2.992 introduced major changes for 8-bit extensions (September 1989).
- // % Version 2.993 fixed a save_stack synchronization bug et alia (December 1989).
- // % Version 3.0 fixed unusual displays; was more \output robust (March 1990).
- // % Version 3.1 fixed nullfont, disabled \write[\the\prevgraf] (September 1990).
- // % Version 3.14 fixed unprintable font names and corrected typos (March 1991).
- // % Version 3.141 more of same; reconstituted ligatures better (March 1992).
- // % Version 3.1415 preserved nonexplicit kerns, tidied up (February 1993).
- // % Version 3.14159 allowed fontmemsize to change; bulletproofing (March 1995).
- // % Version 3.141592 fixed \xleaders, glueset, weird alignments (December 2002).
- // % Version 3.1415926 was a general cleanup with minor fixes (February 2008).
- // % Version 3.14159265 was similar (January 2014).
- // % Version 3.141592653 was similar but more extensive (January 2021).
- //
- // % A reward of $327.68 will be paid to the first finder of any remaining bug.
- //
- // % Although considerable effort has been expended to make the TeX program
- // % correct and reliable, no warranty is implied; the author disclaims any
- // % obligation or liability for damages, including but not limited to
- // % special, indirect, or consequential damages arising out of or in
- // % connection with the use or performance of this software. This work has
- // % been a ``labor of love'' and the author hopes that users enjoy it.
- //
- // % Here is TeX material that gets inserted after \input webmac
- // \def\hang[\hangindent 3em\noindent\ignorespaces]
- // \def\hangg#1 [\hang\hbox[#1 ]]
- // \def\textindent#1[\hangindent2.5em\noindent\hbox to2.5em[\hss#1 ]\ignorespaces]
- // \font\ninerm=cmr9
- // \let\mc=\ninerm % medium caps for names like SAIL
- // \def\PASCAL[Pascal]
- // \def\ph[\hbox[Pascal-H]]
- // \def\pct![[\char`\%]] % percent sign in ordinary text
- // \font\logo=logo10 % font used for the METAFONT logo
- // \def\MF[[\logo META]\-[\logo FONT]]
- // \def\<#1>[$\langle#1\rangle$]
- // \def\section[\mathhexbox278]
- //
- // \def\(#1)[] % this is used to make section names sort themselves better
- // \def\9#1[] % this is used for sort keys in the index via @:sort key][entry@>
- //
- // \outer\def\N#1. \[#2]#3.[\MN#1.\vfil\eject % begin starred section
- // \def\rhead[PART #2:\uppercase[#3]] % define running headline
- // \message[*\modno] % progress report
- // \edef\next[\write\cont[\Z[\?#2]#3][\modno][\the\pageno]]]\next
- // \ifon\startsection[\bf\ignorespaces#3.\quad]\ignorespaces]
- // \let\?=\relax % we want to be able to \write a \?
- //
- // \def\title[\TeX82]
- // \def\topofcontents[\hsize 5.5in
- // \vglue 0pt plus 1fil minus 1.5in
- // \def\?##1][\hbox to 1in[\hfil##1.\ ]]
- // ]
- // \def\botofcontents[\vskip 0pt plus 1fil minus 1.5in]
- // \pageno=3
- // \def\glob[13] % this should be the section number of "<Global...>"
- // \def\gglob[20, 26] % this should be the next two sections of "<Global...>"
- //
- //
- // 1. \[1] Introduction
- // tangle:pos tex.web:95:22:
- // This is \TeX, a document compiler intended to produce typesetting of high
- // quality.
- // The \PASCAL\ program that follows is the definition of \TeX82, a standard
- // \xref[PASCAL][\PASCAL]
- // \xref[TeX82][\TeX82]
- // version of \TeX\ that is designed to be highly portable so that identical output
- // will be obtainable on a great variety of computers.
- //
- // The main purpose of the following program is to explain the algorithms of \TeX\
- // as clearly as possible. As a result, the program will not necessarily be very
- // efficient when a particular \PASCAL\ compiler has translated it into a
- // particular machine language. However, the program has been written so that it
- // can be tuned to run efficiently in a wide variety of operating environments
- // by making comparatively few changes. Such flexibility is possible because
- // the documentation that follows is written in the \.[WEB] language, which is
- // at a higher level than \PASCAL; the preprocessing step that converts \.[WEB]
- // to \PASCAL\ is able to introduce most of the necessary refinements.
- // Semi-automatic translation to other languages is also feasible, because the
- // program below does not make extensive use of features that are peculiar to
- // \PASCAL.
- //
- // A large piece of software like \TeX\ has inherent complexity that cannot
- // be reduced below a certain level of difficulty, although each individual
- // part is fairly simple by itself. The \.[WEB] language is intended to make
- // the algorithms as readable as possible, by reflecting the way the
- // individual program pieces fit together and by providing the
- // cross-references that connect different parts. Detailed comments about
- // what is going on, and about why things were done in certain ways, have
- // been liberally sprinkled throughout the program. These comments explain
- // features of the implementation, but they rarely attempt to explain the
- // \TeX\ language itself, since the reader is supposed to be familiar with
- // [\sl The \TeX book].
- // \xref[WEB]
- // \xref[TeXbook][\sl The \TeX book]
- // 2.
- // tangle:pos tex.web:131:3:
- // The present implementation has a long ancestry, beginning in the summer
- // of~1977, when Michael~F. Plass and Frank~M. Liang designed and coded
- // a prototype
- // \xref[Plass, Michael Frederick]
- // \xref[Liang, Franklin Mark]
- // \xref[Knuth, Donald Ervin]
- // based on some specifications that the author had made in May of that year.
- // This original proto\TeX\ included macro definitions and elementary
- // manipulations on boxes and glue, but it did not have line-breaking,
- // page-breaking, mathematical formulas, alignment routines, error recovery,
- // or the present semantic nest; furthermore,
- // it used character lists instead of token lists, so that a control sequence
- // like \.[\\halign] was represented by a list of seven characters. A
- // complete version of \TeX\ was designed and coded by the author in late
- // 1977 and early 1978; that program, like its prototype, was written in the
- // [\mc SAIL] language, for which an excellent debugging system was
- // available. Preliminary plans to convert the [\mc SAIL] code into a form
- // somewhat like the present ``web'' were developed by Luis Trabb~Pardo and
- // \xref[Trabb Pardo, Luis Isidoro]
- // the author at the beginning of 1979, and a complete implementation was
- // created by Ignacio~A. Zabala in 1979 and 1980. The \TeX82 program, which
- // \xref[Zabala Salelles, Ignacio Andr\'es]
- // was written by the author during the latter part of 1981 and the early
- // part of 1982, also incorporates ideas from the 1979 implementation of
- // \xref[Guibas, Leonidas Ioannis]
- // \xref[Sedgewick, Robert]
- // \xref[Wyatt, Douglas Kirk]
- // \TeX\ in [\mc MESA] that was written by Leonidas Guibas, Robert Sedgewick,
- // and Douglas Wyatt at the Xerox Palo Alto Research Center. Several hundred
- // refinements were introduced into \TeX82 based on the experiences gained with
- // the original implementations, so that essentially every part of the system
- // has been substantially improved. After the appearance of ``Version 0'' in
- // September 1982, this program benefited greatly from the comments of
- // many other people, notably David~R. Fuchs and Howard~W. Trickey.
- // A final revision in September 1989 extended the input character set to
- // eight-bit codes and introduced the ability to hyphenate words from
- // different languages, based on some ideas of Michael~J. Ferguson.
- // \xref[Fuchs, David Raymond]
- // \xref[Trickey, Howard Wellington]
- // \xref[Ferguson, Michael John]
- //
- // No doubt there still is plenty of room for improvement, but the author
- // is firmly committed to keeping \TeX82 ``frozen'' from now on; stability
- // and reliability are to be its main virtues.
- //
- // On the other hand, the \.[WEB] description can be extended without changing
- // the core of \TeX82 itself, and the program has been designed so that such
- // extensions are not extremely difficult to make.
- // The |banner| string defined here should be changed whenever \TeX\
- // undergoes any modifications, so that it will be clear which version of
- // \TeX\ might be the guilty party when a problem arises.
- // \xref[extensions to \TeX]
- // \xref[system dependencies]
- //
- // If this program is changed, the resulting system should not be called
- // `\TeX'; the official name `\TeX' by itself is reserved
- // for software systems that are fully compatible with each other.
- // A special test suite called the ``\.[TRIP] test'' is available for
- // helping to determine whether a particular implementation deserves to be
- // known as `\TeX' [cf.~Stanford Computer Science report CS1027,
- // November 1984].
- // 3.
- // tangle:pos tex.web:195:3:
- // Different \PASCAL s have slightly different conventions, and the present
- // \xref[PASCAL H][\ph]
- // program expresses \TeX\ in terms of the \PASCAL\ that was
- // available to the author in 1982. Constructions that apply to
- // this particular compiler, which we shall call \ph, should help the
- // reader see how to make an appropriate interface for other systems
- // if necessary. (\ph\ is Charles Hedrick's modification of a compiler
- // \xref[Hedrick, Charles Locke]
- // for the DECsystem-10 that was originally developed at the University of
- // Hamburg; cf.\ [\sl Software---Practice and Experience \bf6] (1976),
- // 29--42. The \TeX\ program below is intended to be adaptable, without
- // extensive changes, to most other versions of \PASCAL, so it does not fully
- // use the admirable features of \ph. Indeed, a conscious effort has been
- // made here to avoid using several idiosyncratic features of standard
- // \PASCAL\ itself, so that most of the code can be translated mechanically
- // into other high-level languages. For example, the `\&[with]' and `\\[new]'
- // features are not used, nor are pointer types, set types, or enumerated
- // scalar types; there are no `\&[var]' parameters, except in the case of files;
- // there are no tag fields on variant records; there are no assignments
- // |real:=integer|; no procedures are declared local to other procedures.)
- //
- // The portions of this program that involve system-dependent code, where
- // changes might be necessary because of differences between \PASCAL\ compilers
- // and/or differences between
- // operating systems, can be identified by looking at the sections whose
- // numbers are listed under `system dependencies' in the index. Furthermore,
- // the index entries for `dirty \PASCAL' list all places where the restrictions
- // of \PASCAL\ have not been followed perfectly, for one reason or another.
- // \xref[system dependencies]
- // \xref[dirty \PASCAL]
- //
- // Incidentally, \PASCAL's standard |round| function can be problematical,
- // because it disagrees with the IEEE floating-point standard.
- // Many implementors have
- // therefore chosen to substitute their own home-grown rounding procedure.
- // 4.
- // tangle:pos tex.web:231:3:
- // The program begins with a normal \PASCAL\ program heading, whose
- // components will be filled in later, using the conventions of \.[WEB].
- // \xref[WEB]
- // For example, the portion of the program called `\X\glob:Global
- // variables\X' below will be replaced by a sequence of variable declarations
- // that starts in $\section\glob$ of this documentation. In this way, we are able
- // to define each individual global variable when we are prepared to
- // understand what it means; we do not have to define all of the globals at
- // once. Cross references in $\section\glob$, where it says ``See also
- // sections \gglob, \dots,'' also make it possible to look at the set of
- // all global variables, if desired. Similar remarks apply to the other
- // portions of the program heading.
- //
- // Actually the heading shown here is not quite normal: The |program| line
- // does not mention any |output| file, because \ph\ would ask the \TeX\ user
- // to specify a file name if |output| were specified here.
- // \xref[PASCAL H][\ph]
- // \xref[system dependencies]
- // \4
- // Compiler directives
- // $C-,A+,D-
- // no range check, catch arithmetic overflow, no debug overhead
- // [$C+,D+] [ ]
- // but turn everything on when debugging
- package tex
- import (
- "math"
- "unsafe"
- "modernc.org/knuth"
- )
- var (
- _ = math.MaxInt32
- _ unsafe.Pointer
- )
- type (
- char = byte
- signal int
- )
- func strcopy(dst []char, src string) {
- for i := 0; i < len(dst) && i < len(src); i++ {
- dst[i] = src[i]
- }
- }
- func arraystr(a []char) string {
- b := make([]byte, len(a))
- for i, c := range a {
- b[i] = c
- }
- return string(b)
- }
- func abs(n int32) int32 {
- if n >= 0 {
- return n
- }
- return -n
- }
- func fabs(f float64) float64 {
- if f >= 0 {
- return f
- }
- return -f
- }
- func round(f float64) int32 {
- if f >= 0 {
- return int32(f + 0.5)
- }
- return int32(f - 0.5)
- }
- // key control points
- const (
- startOfTex = 1 /* go here when \TeX's variables are initialized */
- endOfTex = 9998 /* go here to close files and terminate gracefully */
- finalEnd = 9999 /* this label marks the ending of the program */
- memBot = 0 // smallest index in the |mem| array dumped by \.[INITEX];
- // must not be less than |mem_min|
- fontBase = 0 // smallest internal font number; must not be less
- // than |min_quarterword|
- hashSize = 2100 // maximum number of control sequences; it should be at most
- // about |(mem_max-mem_min)/10|
- hashPrime = 1777 /* a prime number equal to about 85\pct! of |hash_size| */
- hyphSize = 307 // another prime; the number of \.[\\hyphenation] exceptions
- // \xref[system dependencies]
- exit = 10 /* go here to leave a procedure */
- restart = 20 /* go here to start a procedure again */
- reswitch = 21 /* go here to start a case statement again */
- continue1 = 22 /* go here to resume a loop */
- done = 30 /* go here to exit a loop */
- done1 = 31 /* like |done|, when there is more than one loop */
- done2 = 32 /* for exiting the second loop in a long block */
- done3 = 33 /* for exiting the third loop in a very long block */
- done4 = 34 /* for exiting the fourth loop in an extremely long block */
- done5 = 35 /* for exiting the fifth loop in an immense block */
- done6 = 36 /* for exiting the sixth loop in a block */
- found = 40 /* go here when you've found it */
- found1 = 41 /* like |found|, when there's more than one per routine */
- found2 = 42 /* like |found|, when there's more than two per routine */
- notFound = 45 /* go here when you've found nothing */
- commonEnding = 50 /* go here when you want to merge with another branch */
- empty = 0 /* symbolic name for a null constant */
- firstTextChar = 0 /* ordinal number of the smallest element of |text_char| */
- lastTextChar = 255 /* ordinal number of the largest element of |text_char| */
- nullCode = 0 /* ASCII code that might disappear */
- carriageReturn = 015 /* ASCII code used at end of line */
- invalidCode = 0177 /* ASCII code that many systems prohibit in text files */
- noPrint = 16 /* |selector| setting that makes data disappear */
- termOnly = 17 /* printing is destined for the terminal only */
- logOnly = 18 /* printing is destined for the transcript file only */
- termAndLog = 19 /* normal |selector| setting */
- pseudo = 20 /* special |selector| setting for |show_context| */
- newString = 21 /* printing is deflected to the string pool */
- maxSelector = 21 /* highest selector setting */
- batchMode = 0 /* omits all stops and omits terminal output */
- nonstopMode = 1 /* omits all stops */
- scrollMode = 2 /* omits error stops */
- errorStopMode = 3 /* stops at every opportunity to interact */
- spotless = 0 /* |history| value when nothing has been amiss yet */
- warningIssued = 1 /* |history| value when |begin_diagnostic| has been called */
- errorMessageIssued = 2 /* |history| value when |error| has been called */
- fatalErrorStop = 3 /* |history| value when termination was premature */
- infBad = 10000 /* infinitely bad value */
- minQuarterword = 0 /* smallest allowable value in a |quarterword| */
- maxQuarterword = 255 /* largest allowable value in a |quarterword| */
- hlistNode = 0 /* |type| of hlist nodes */
- boxNodeSize = 7 /* number of words to allocate for a box node */
- widthOffset = 1 /* position of |width| field in a box node */
- depthOffset = 2 /* position of |depth| field in a box node */
- heightOffset = 3 /* position of |height| field in a box node */
- listOffset = 5 /* position of |list_ptr| field in a box node */
- normal = 0 /* the most common case when several cases are named */
- stretching = 1 /* glue setting applies to the stretch components */
- shrinking = 2 /* glue setting applies to the shrink components */
- glueOffset = 6 /* position of |glue_set| in a box node */
- vlistNode = 1 /* |type| of vlist nodes */
- ruleNode = 2 /* |type| of rule nodes */
- ruleNodeSize = 4 /* number of words to allocate for a rule node */
- insNode = 3 /* |type| of insertion nodes */
- insNodeSize = 5 /* number of words to allocate for an insertion */
- markNode = 4 /* |type| of a mark node */
- smallNodeSize = 2 /* number of words to allocate for most node types */
- adjustNode = 5 /* |type| of an adjust node */
- ligatureNode = 6 /* |type| of a ligature node */
- discNode = 7 /* |type| of a discretionary node */
- whatsitNode = 8 /* |type| of special extension nodes */
- mathNode = 9 /* |type| of a math node */
- before = 0 /* |subtype| for math node that introduces a formula */
- after = 1 /* |subtype| for math node that winds up a formula */
- glueNode = 10 /* |type| of node that points to a glue specification */
- condMathGlue = 98 /* special |subtype| to suppress glue in the next node */
- muGlue = 99 /* |subtype| for math glue */
- aLeaders = 100 /* |subtype| for aligned leaders */
- cLeaders = 101 /* |subtype| for centered leaders */
- xLeaders = 102 /* |subtype| for expanded leaders */
- glueSpecSize = 4 /* number of words to allocate for a glue specification */
- fil = 1 /* first-order infinity */
- fill = 2 /* second-order infinity */
- filll = 3 /* third-order infinity */
- kernNode = 11 /* |type| of a kern node */
- explicit = 1 /* |subtype| of kern nodes from \.[\\kern] and \.[\\/] */
- accKern = 2 /* |subtype| of kern nodes from accents */
- penaltyNode = 12 /* |type| of a penalty node */
- infPenalty = infBad /* ``infinite'' penalty value */
- ejectPenalty = -infPenalty /* ``negatively infinite'' penalty value */
- unsetNode = 13 /* |type| for an unset node */
- hiMemStatUsage = 14 /* the number of one-word nodes always present */
- escape = 0 // escape delimiter (called \.\\ in [\sl The \TeX book\/])
- // \xref[TeXbook][\sl The \TeX book]
- relax = 0 /* do nothing ( \.[\\relax] ) */
- leftBrace = 1 /* beginning of a group ( \.\[ ) */
- rightBrace = 2 /* ending of a group ( \.\] ) */
- mathShift = 3 /* mathematics shift character ( \.\$ ) */
- tabMark = 4 /* alignment delimiter ( \.\&, \.[\\span] ) */
- carRet = 5 /* end of line ( |carriage_return|, \.[\\cr], \.[\\crcr] ) */
- outParam = 5 /* output a macro parameter */
- macParam = 6 /* macro parameter symbol ( \.\# ) */
- supMark = 7 /* superscript ( \.[\char'136] ) */
- subMark = 8 /* subscript ( \.[\char'137] ) */
- ignore = 9 /* characters to ignore ( \.[\^\^@] ) */
- endv = 9 /* end of \<v_j> list in alignment template */
- spacer = 10 /* characters equivalent to blank space ( \.[\ ] ) */
- letter = 11 /* characters regarded as letters ( \.[A..Z], \.[a..z] ) */
- otherChar = 12 /* none of the special character types */
- activeChar = 13 /* characters that invoke macros ( \.[\char`\~] ) */
- parEnd = 13 /* end of paragraph ( \.[\\par] ) */
- match = 13 /* match a macro parameter */
- comment = 14 /* characters that introduce comments ( \.\% ) */
- endMatch = 14 /* end of parameters to macro */
- stop = 14 /* end of job ( \.[\\end], \.[\\dump] ) */
- invalidChar = 15 /* characters that shouldn't appear ( \.[\^\^?] ) */
- delimNum = 15 /* specify delimiter numerically ( \.[\\delimiter] ) */
- maxCharCode = 15 /* largest catcode for individual characters */
- charNum = 16 /* character specified numerically ( \.[\\char] ) */
- mathCharNum = 17 /* explicit math code ( \.[\\mathchar] ) */
- mark = 18 /* mark definition ( \.[\\mark] ) */
- xray = 19 /* peek inside of \TeX\ ( \.[\\show], \.[\\showbox], etc.~) */
- makeBox = 20 /* make a box ( \.[\\box], \.[\\copy], \.[\\hbox], etc.~) */
- hmove = 21 /* horizontal motion ( \.[\\moveleft], \.[\\moveright] ) */
- vmove = 22 /* vertical motion ( \.[\\raise], \.[\\lower] ) */
- unHbox = 23 /* unglue a box ( \.[\\unhbox], \.[\\unhcopy] ) */
- unVbox = 24 /* unglue a box ( \.[\\unvbox], \.[\\unvcopy] ) */
- removeItem = 25 // nullify last item ( \.[\\unpenalty],
- // \.[\\unkern], \.[\\unskip] )
- hskip = 26 /* horizontal glue ( \.[\\hskip], \.[\\hfil], etc.~) */
- vskip = 27 /* vertical glue ( \.[\\vskip], \.[\\vfil], etc.~) */
- mskip = 28 /* math glue ( \.[\\mskip] ) */
- kern = 29 /* fixed space ( \.[\\kern] ) */
- mkern = 30 /* math kern ( \.[\\mkern] ) */
- leaderShip = 31 /* use a box ( \.[\\shipout], \.[\\leaders], etc.~) */
- halign = 32 /* horizontal table alignment ( \.[\\halign] ) */
- valign = 33 /* vertical table alignment ( \.[\\valign] ) */
- noAlign = 34 /* temporary escape from alignment ( \.[\\noalign] ) */
- vrule = 35 /* vertical rule ( \.[\\vrule] ) */
- hrule = 36 /* horizontal rule ( \.[\\hrule] ) */
- insert = 37 /* vlist inserted in box ( \.[\\insert] ) */
- vadjust = 38 /* vlist inserted in enclosing paragraph ( \.[\\vadjust] ) */
- ignoreSpaces = 39 /* gobble |spacer| tokens ( \.[\\ignorespaces] ) */
- afterAssignment = 40 /* save till assignment is done ( \.[\\afterassignment] ) */
- afterGroup = 41 /* save till group is done ( \.[\\aftergroup] ) */
- breakPenalty = 42 /* additional badness ( \.[\\penalty] ) */
- startPar = 43 /* begin paragraph ( \.[\\indent], \.[\\noindent] ) */
- italCorr = 44 /* italic correction ( \.[\\/] ) */
- accent = 45 /* attach accent in text ( \.[\\accent] ) */
- mathAccent = 46 /* attach accent in math ( \.[\\mathaccent] ) */
- discretionary = 47 /* discretionary texts ( \.[\\-], \.[\\discretionary] ) */
- eqNo = 48 /* equation number ( \.[\\eqno], \.[\\leqno] ) */
- leftRight = 49 /* variable delimiter ( \.[\\left], \.[\\right] ) */
- mathComp = 50 /* component of formula ( \.[\\mathbin], etc.~) */
- limitSwitch = 51 /* diddle limit conventions ( \.[\\displaylimits], etc.~) */
- above = 52 /* generalized fraction ( \.[\\above], \.[\\atop], etc.~) */
- mathStyle = 53 /* style specification ( \.[\\displaystyle], etc.~) */
- mathChoice = 54 /* choice specification ( \.[\\mathchoice] ) */
- nonScript = 55 /* conditional math glue ( \.[\\nonscript] ) */
- vcenter = 56 /* vertically center a vbox ( \.[\\vcenter] ) */
- caseShift = 57 /* force specific case ( \.[\\lowercase], \.[\\uppercase]~) */
- message = 58 /* send to user ( \.[\\message], \.[\\errmessage] ) */
- extension = 59 /* extensions to \TeX\ ( \.[\\write], \.[\\special], etc.~) */
- inStream = 60 /* files for reading ( \.[\\openin], \.[\\closein] ) */
- beginGroup = 61 /* begin local grouping ( \.[\\begingroup] ) */
- endGroup = 62 /* end local grouping ( \.[\\endgroup] ) */
- omit = 63 /* omit alignment template ( \.[\\omit] ) */
- exSpace = 64 /* explicit space ( \.[\\\ ] ) */
- noBoundary = 65 /* suppress boundary ligatures ( \.[\\noboundary] ) */
- radical = 66 /* square root and similar signs ( \.[\\radical] ) */
- endCsName = 67 /* end control sequence ( \.[\\endcsname] ) */
- minInternal = 68 /* the smallest code that can follow \.[\\the] */
- charGiven = 68 /* character code defined by \.[\\chardef] */
- mathGiven = 69 /* math code defined by \.[\\mathchardef] */
- lastItem = 70 // most recent item ( \.[\\lastpenalty],
- // \.[\\lastkern], \.[\\lastskip] )
- maxNonPrefixedCommand = 70 /* largest command code that can't be \.[\\global] */
- toksRegister = 71 /* token list register ( \.[\\toks] ) */
- assignToks = 72 /* special token list ( \.[\\output], \.[\\everypar], etc.~) */
- assignInt = 73 /* user-defined integer ( \.[\\tolerance], \.[\\day], etc.~) */
- assignDimen = 74 /* user-defined length ( \.[\\hsize], etc.~) */
- assignGlue = 75 /* user-defined glue ( \.[\\baselineskip], etc.~) */
- assignMuGlue = 76 /* user-defined muglue ( \.[\\thinmuskip], etc.~) */
- assignFontDimen = 77 /* user-defined font dimension ( \.[\\fontdimen] ) */
- assignFontInt = 78 // user-defined font integer ( \.[\\hyphenchar],
- // \.[\\skewchar] )
- setAux = 79 /* specify state info ( \.[\\spacefactor], \.[\\prevdepth] ) */
- setPrevGraf = 80 /* specify state info ( \.[\\prevgraf] ) */
- setPageDimen = 81 /* specify state info ( \.[\\pagegoal], etc.~) */
- setPageInt = 82 // specify state info ( \.[\\deadcycles],
- // \.[\\insertpenalties] )
- setBoxDimen = 83 /* change dimension of box ( \.[\\wd], \.[\\ht], \.[\\dp] ) */
- setShape = 84 /* specify fancy paragraph shape ( \.[\\parshape] ) */
- defCode = 85 /* define a character code ( \.[\\catcode], etc.~) */
- defFamily = 86 /* declare math fonts ( \.[\\textfont], etc.~) */
- setFont = 87 /* set current font ( font identifiers ) */
- defFont = 88 /* define a font file ( \.[\\font] ) */
- register = 89 /* internal register ( \.[\\count], \.[\\dimen], etc.~) */
- maxInternal = 89 /* the largest code that can follow \.[\\the] */
- advance = 90 /* advance a register or parameter ( \.[\\advance] ) */
- multiply = 91 /* multiply a register or parameter ( \.[\\multiply] ) */
- divide = 92 /* divide a register or parameter ( \.[\\divide] ) */
- prefix = 93 /* qualify a definition ( \.[\\global], \.[\\long], \.[\\outer] ) */
- let = 94 /* assign a command code ( \.[\\let], \.[\\futurelet] ) */
- shorthandDef = 95 /* code definition ( \.[\\chardef], \.[\\countdef], etc.~) */
- readToCs = 96 /* read into a control sequence ( \.[\\read] ) */
- def = 97 /* macro definition ( \.[\\def], \.[\\gdef], \.[\\xdef], \.[\\edef] ) */
- setBox = 98 /* set a box ( \.[\\setbox] ) */
- hyphData = 99 /* hyphenation data ( \.[\\hyphenation], \.[\\patterns] ) */
- setInteraction = 100 /* define level of interaction ( \.[\\batchmode], etc.~) */
- maxCommand = 100 /* the largest command code seen at |big_switch| */
- undefinedCs = maxCommand + 1 /* initial state of most |eq_type| fields */
- expandAfter = maxCommand + 2 /* special expansion ( \.[\\expandafter] ) */
- noExpand = maxCommand + 3 /* special nonexpansion ( \.[\\noexpand] ) */
- input = maxCommand + 4 /* input a source file ( \.[\\input], \.[\\endinput] ) */
- ifTest = maxCommand + 5 /* conditional text ( \.[\\if], \.[\\ifcase], etc.~) */
- fiOrElse = maxCommand + 6 /* delimiters for conditionals ( \.[\\else], etc.~) */
- csName = maxCommand + 7 /* make a control sequence from tokens ( \.[\\csname] ) */
- convert = maxCommand + 8 /* convert to text ( \.[\\number], \.[\\string], etc.~) */
- the = maxCommand + 9 /* expand an internal quantity ( \.[\\the] ) */
- topBotMark = maxCommand + 10 /* inserted mark ( \.[\\topmark], etc.~) */
- call = maxCommand + 11 /* non-long, non-outer control sequence */
- longCall = maxCommand + 12 /* long, non-outer control sequence */
- outerCall = maxCommand + 13 /* non-long, outer control sequence */
- longOuterCall = maxCommand + 14 /* long, outer control sequence */
- endTemplate = maxCommand + 15 /* end of an alignment template */
- dontExpand = maxCommand + 16 /* the following token was marked by \.[\\noexpand] */
- glueRef = maxCommand + 17 /* the equivalent points to a glue specification */
- shapeRef = maxCommand + 18 /* the equivalent points to a parshape specification */
- boxRef = maxCommand + 19 /* the equivalent points to a box node, or is |null| */
- data = maxCommand + 20 /* the equivalent is simply a halfword number */
- vmode = 1 /* vertical mode */
- hmode = vmode + maxCommand + 1 /* horizontal mode */
- mmode = hmode + maxCommand + 1 /* math mode */
- levelZero = minQuarterword /* level for undefined quantities */
- levelOne = levelZero + 1 /* outermost level for defined quantities */
- activeBase = 1 /* beginning of region 1, for active character equivalents */
- singleBase = activeBase + 256 /* equivalents of one-character control sequences */
- nullCs = singleBase + 256 /* equivalent of \.[\\csname\\endcsname] */
- hashBase = nullCs + 1 /* beginning of region 2, for the hash table */
- frozenControlSequence = hashBase + hashSize /* for error recovery */
- frozenProtection = frozenControlSequence /* inaccessible but definable */
- frozenCr = frozenControlSequence + 1 /* permanent `\.[\\cr]' */
- frozenEndGroup = frozenControlSequence + 2 /* permanent `\.[\\endgroup]' */
- frozenRight = frozenControlSequence + 3 /* permanent `\.[\\right]' */
- frozenFi = frozenControlSequence + 4 /* permanent `\.[\\fi]' */
- frozenEndTemplate = frozenControlSequence + 5 /* permanent `\.[\\endtemplate]' */
- frozenEndv = frozenControlSequence + 6 /* second permanent `\.[\\endtemplate]' */
- frozenRelax = frozenControlSequence + 7 /* permanent `\.[\\relax]' */
- endWrite = frozenControlSequence + 8 /* permanent `\.[\\endwrite]' */
- frozenDontExpand = frozenControlSequence + 9
- /* permanent `\.[\\notexpanded:]' */
- frozenNullFont = frozenControlSequence + 10
- /* permanent `\.[\\nullfont]' */
- fontIdBase = frozenNullFont - fontBase
- /* begins table of 257 permanent font identifiers */
- undefinedControlSequence = frozenNullFont + 257 /* dummy location */
- glueBase = undefinedControlSequence + 1 /* beginning of region 3 */
- lineSkipCode = 0 /* interline glue if |baseline_skip| is infeasible */
- baselineSkipCode = 1 /* desired glue between baselines */
- parSkipCode = 2 /* extra glue just above a paragraph */
- aboveDisplaySkipCode = 3 /* extra glue just above displayed math */
- belowDisplaySkipCode = 4 /* extra glue just below displayed math */
- aboveDisplayShortSkipCode = 5
- /* glue above displayed math following short lines */
- belowDisplayShortSkipCode = 6
- /* glue below displayed math following short lines */
- leftSkipCode = 7 /* glue at left of justified lines */
- rightSkipCode = 8 /* glue at right of justified lines */
- topSkipCode = 9 /* glue at top of main pages */
- splitTopSkipCode = 10 /* glue at top of split pages */
- tabSkipCode = 11 /* glue between aligned entries */
- spaceSkipCode = 12 /* glue between words (if not |zero_glue|) */
- xspaceSkipCode = 13 /* glue after sentences (if not |zero_glue|) */
- parFillSkipCode = 14 /* glue on last line of paragraph */
- thinMuSkipCode = 15 /* thin space in math formula */
- medMuSkipCode = 16 /* medium space in math formula */
- thickMuSkipCode = 17 /* thick space in math formula */
- gluePars = 18 /* total number of glue parameters */
- skipBase = glueBase + gluePars /* table of 256 ``skip'' registers */
- muSkipBase = skipBase + 256 /* table of 256 ``muskip'' registers */
- localBase = muSkipBase + 256 /* beginning of region 4 */
- parShapeLoc = localBase /* specifies paragraph shape */
- outputRoutineLoc = localBase + 1 /* points to token list for \.[\\output] */
- everyParLoc = localBase + 2 /* points to token list for \.[\\everypar] */
- everyMathLoc = localBase + 3 /* points to token list for \.[\\everymath] */
- everyDisplayLoc = localBase + 4 /* points to token list for \.[\\everydisplay] */
- everyHboxLoc = localBase + 5 /* points to token list for \.[\\everyhbox] */
- everyVboxLoc = localBase + 6 /* points to token list for \.[\\everyvbox] */
- everyJobLoc = localBase + 7 /* points to token list for \.[\\everyjob] */
- everyCrLoc = localBase + 8 /* points to token list for \.[\\everycr] */
- errHelpLoc = localBase + 9 /* points to token list for \.[\\errhelp] */
- toksBase = localBase + 10 /* table of 256 token list registers */
- boxBase = toksBase + 256 /* table of 256 box registers */
- curFontLoc = boxBase + 256 /* internal font number outside math mode */
- mathFontBase = curFontLoc + 1 /* table of 48 math font numbers */
- catCodeBase = mathFontBase + 48
- /* table of 256 command codes (the ``catcodes'') */
- lcCodeBase = catCodeBase + 256 /* table of 256 lowercase mappings */
- ucCodeBase = lcCodeBase + 256 /* table of 256 uppercase mappings */
- sfCodeBase = ucCodeBase + 256 /* table of 256 spacefactor mappings */
- mathCodeBase = sfCodeBase + 256 /* table of 256 math mode mappings */
- intBase = mathCodeBase + 256 /* beginning of region 5 */
- pretoleranceCode = 0 /* badness tolerance before hyphenation */
- toleranceCode = 1 /* badness tolerance after hyphenation */
- linePenaltyCode = 2 /* added to the badness of every line */
- hyphenPenaltyCode = 3 /* penalty for break after discretionary hyphen */
- exHyphenPenaltyCode = 4 /* penalty for break after explicit hyphen */
- clubPenaltyCode = 5 /* penalty for creating a club line */
- widowPenaltyCode = 6 /* penalty for creating a widow line */
- displayWidowPenaltyCode = 7 /* ditto, just before a display */
- brokenPenaltyCode = 8 /* penalty for breaking a page at a broken line */
- binOpPenaltyCode = 9 /* penalty for breaking after a binary operation */
- relPenaltyCode = 10 /* penalty for breaking after a relation */
- preDisplayPenaltyCode = 11
- /* penalty for breaking just before a displayed formula */
- postDisplayPenaltyCode = 12
- /* penalty for breaking just after a displayed formula */
- interLinePenaltyCode = 13 /* additional penalty between lines */
- doubleHyphenDemeritsCode = 14 /* demerits for double hyphen break */
- finalHyphenDemeritsCode = 15 /* demerits for final hyphen break */
- adjDemeritsCode = 16 /* demerits for adjacent incompatible lines */
- magCode = 17 /* magnification ratio */
- delimiterFactorCode = 18 /* ratio for variable-size delimiters */
- loosenessCode = 19 /* change in number of lines for a paragraph */
- timeCode = 20 /* current time of day */
- dayCode = 21 /* current day of the month */
- monthCode = 22 /* current month of the year */
- yearCode = 23 /* current year of our Lord */
- showBoxBreadthCode = 24 /* nodes per level in |show_box| */
- showBoxDepthCode = 25 /* maximum level in |show_box| */
- hbadnessCode = 26 /* hboxes exceeding this badness will be shown by |hpack| */
- vbadnessCode = 27 /* vboxes exceeding this badness will be shown by |vpack| */
- pausingCode = 28 /* pause after each line is read from a file */
- tracingOnlineCode = 29 /* show diagnostic output on terminal */
- tracingMacrosCode = 30 /* show macros as they are being expanded */
- tracingStatsCode = 31 /* show memory usage if \TeX\ knows it */
- tracingParagraphsCode = 32 /* show line-break calculations */
- tracingPagesCode = 33 /* show page-break calculations */
- tracingOutputCode = 34 /* show boxes when they are shipped out */
- tracingLostCharsCode = 35 /* show characters that aren't in the font */
- tracingCommandsCode = 36 /* show command codes at |big_switch| */
- tracingRestoresCode = 37 /* show equivalents when they are restored */
- ucHyphCode = 38 /* hyphenate words beginning with a capital letter */
- outputPenaltyCode = 39 /* penalty found at current page break */
- maxDeadCyclesCode = 40 /* bound on consecutive dead cycles of output */
- hangAfterCode = 41 /* hanging indentation changes after this many lines */
- floatingPenaltyCode = 42 /* penalty for insertions held over after a split */
- globalDefsCode = 43 /* override \.[\\global] specifications */
- curFamCode = 44 /* current family */
- escapeCharCode = 45 /* escape character for token output */
- defaultHyphenCharCode = 46 /* value of \.[\\hyphenchar] when a font is loaded */
- defaultSkewCharCode = 47 /* value of \.[\\skewchar] when a font is loaded */
- endLineCharCode = 48 /* character placed at the right end of the buffer */
- newLineCharCode = 49 /* character that prints as |print_ln| */
- languageCode = 50 /* current hyphenation table */
- leftHyphenMinCode = 51 /* minimum left hyphenation fragment size */
- rightHyphenMinCode = 52 /* minimum right hyphenation fragment size */
- holdingInsertsCode = 53 /* do not remove insertion nodes from \.[\\box255] */
- errorContextLinesCode = 54 /* maximum intermediate line pairs shown */
- intPars = 55 /* total number of integer parameters */
- countBase = intBase + intPars /* 256 user \.[\\count] registers */
- delCodeBase = countBase + 256 /* 256 delimiter code mappings */
- dimenBase = delCodeBase + 256 /* beginning of region 6 */
- parIndentCode = 0 /* indentation of paragraphs */
- mathSurroundCode = 1 /* space around math in text */
- lineSkipLimitCode = 2 /* threshold for |line_skip| instead of |baseline_skip| */
- hsizeCode = 3 /* line width in horizontal mode */
- vsizeCode = 4 /* page height in vertical mode */
- maxDepthCode = 5 /* maximum depth of boxes on main pages */
- splitMaxDepthCode = 6 /* maximum depth of boxes on split pages */
- boxMaxDepthCode = 7 /* maximum depth of explicit vboxes */
- hfuzzCode = 8 /* tolerance for overfull hbox messages */
- vfuzzCode = 9 /* tolerance for overfull vbox messages */
- delimiterShortfallCode = 10 /* maximum amount uncovered by variable delimiters */
- nullDelimiterSpaceCode = 11 /* blank space in null delimiters */
- scriptSpaceCode = 12 /* extra space after subscript or superscript */
- preDisplaySizeCode = 13 /* length of text preceding a display */
- displayWidthCode = 14 /* length of line for displayed equation */
- displayIndentCode = 15 /* indentation of line for displayed equation */
- overfullRuleCode = 16 /* width of rule that identifies overfull hboxes */
- hangIndentCode = 17 /* amount of hanging indentation */
- hOffsetCode = 18 /* amount of horizontal offset when shipping pages out */
- vOffsetCode = 19 /* amount of vertical offset when shipping pages out */
- emergencyStretchCode = 20 /* reduces badnesses on final pass of line-breaking */
- dimenPars = 21 /* total number of dimension parameters */
- scaledBase = dimenBase + dimenPars
- /* table of 256 user-defined \.[\\dimen] registers */
- eqtbSize = scaledBase + 255 /* largest subscript of |eqtb| */
- restoreOldValue = 0 /* |save_type| when a value should be restored later */
- restoreZero = 1 /* |save_type| when an undefined entry should be restored */
- insertToken = 2 /* |save_type| when a token is being saved for later use */
- levelBoundary = 3 /* |save_type| corresponding to beginning of group */
- bottomLevel = 0 /* group code for the outside world */
- simpleGroup = 1 /* group code for local structure only */
- hboxGroup = 2 /* code for `\.[\\hbox]\grp' */
- adjustedHboxGroup = 3 /* code for `\.[\\hbox]\grp' in vertical mode */
- vboxGroup = 4 /* code for `\.[\\vbox]\grp' */
- vtopGroup = 5 /* code for `\.[\\vtop]\grp' */
- alignGroup = 6 /* code for `\.[\\halign]\grp', `\.[\\valign]\grp' */
- noAlignGroup = 7 /* code for `\.[\\noalign]\grp' */
- outputGroup = 8 /* code for output routine */
- mathGroup = 9 /* code for, e.g., `\.[\char'136]\grp' */
- discGroup = 10 /* code for `\.[\\discretionary]\grp\grp\grp' */
- insertGroup = 11 /* code for `\.[\\insert]\grp', `\.[\\vadjust]\grp' */
- vcenterGroup = 12 /* code for `\.[\\vcenter]\grp' */
- mathChoiceGroup = 13 /* code for `\.[\\mathchoice]\grp\grp\grp\grp' */
- semiSimpleGroup = 14 /* code for `\.[\\begingroup...\\endgroup]' */
- mathShiftGroup = 15 /* code for `\.[\$...\$]' */
- mathLeftGroup = 16 /* code for `\.[\\left...\\right]' */
- maxGroupCode = 16
- leftBraceToken = 0400 /* $2^8\cdot|left_brace|$ */
- leftBraceLimit = 01000 /* $2^8\cdot(|left_brace|+1)$ */
- rightBraceToken = 01000 /* $2^8\cdot|right_brace|$ */
- rightBraceLimit = 01400 /* $2^8\cdot(|right_brace|+1)$ */
- mathShiftToken = 01400 /* $2^8\cdot|math_shift|$ */
- tabToken = 02000 /* $2^8\cdot|tab_mark|$ */
- outParamToken = 02400 /* $2^8\cdot|out_param|$ */
- spaceToken = 05040 /* $2^8\cdot|spacer|+|" "|$ */
- letterToken = 05400 /* $2^8\cdot|letter|$ */
- otherToken = 06000 /* $2^8\cdot|other_char|$ */
- matchToken = 06400 /* $2^8\cdot|match|$ */
- endMatchToken = 07000 /* $2^8\cdot|end_match|$ */
- midLine = 1 /* |state| code when scanning a line of characters */
- skipBlanks = 2 + maxCharCode /* |state| code when ignoring blanks */
- newLine = 3 + maxCharCode + maxCharCode /* |state| code at start of line */
- skipping = 1 /* |scanner_status| when passing conditional text */
- defining = 2 /* |scanner_status| when reading a macro definition */
- matching = 3 /* |scanner_status| when reading macro arguments */
- aligning = 4 /* |scanner_status| when reading an alignment preamble */
- absorbing = 5 /* |scanner_status| when reading a balanced text */
- tokenList = 0 /* |state| code when scanning a token list */
- parameter = 0 /* |token_type| code for parameter */
- uTemplate = 1 /* |token_type| code for \<u_j> template */
- vTemplate = 2 /* |token_type| code for \<v_j> template */
- backedUp = 3 /* |token_type| code for text to be reread */
- inserted = 4 /* |token_type| code for inserted texts */
- macro = 5 /* |token_type| code for defined control sequences */
- outputText = 6 /* |token_type| code for output routines */
- everyParText = 7 /* |token_type| code for \.[\\everypar] */
- everyMathText = 8 /* |token_type| code for \.[\\everymath] */
- everyDisplayText = 9 /* |token_type| code for \.[\\everydisplay] */
- everyHboxText = 10 /* |token_type| code for \.[\\everyhbox] */
- everyVboxText = 11 /* |token_type| code for \.[\\everyvbox] */
- everyJobText = 12 /* |token_type| code for \.[\\everyjob] */
- everyCrText = 13 /* |token_type| code for \.[\\everycr] */
- markText = 14 /* |token_type| code for \.[\\topmark], etc. */
- writeText = 15 /* |token_type| code for \.[\\write] */
- switch1 = 25 /* a label in |get_next| */
- startCs = 26 /* another */
- noExpandFlag = 257 /* this characterizes a special variant of |relax| */
- topMarkCode = 0 /* the mark in effect at the previous page break */
- firstMarkCode = 1 /* the first mark between |top_mark| and |bot_mark| */
- botMarkCode = 2 /* the mark in effect at the current page break */
- splitFirstMarkCode = 3 /* the first mark found by \.[\\vsplit] */
- splitBotMarkCode = 4 /* the last mark found by \.[\\vsplit] */
- intVal = 0 /* integer values */
- dimenVal = 1 /* dimension values */
- glueVal = 2 /* glue specifications */
- muVal = 3 /* math glue specifications */
- identVal = 4 /* font identifier */
- tokVal = 5 /* token lists */
- inputLineNoCode = glueVal + 1 /* code for \.[\\inputlineno] */
- badnessCode = glueVal + 2 /* code for \.[\\badness] */
- octalToken = otherToken + '\'' /* apostrophe, indicates an octal constant */
- hexToken = otherToken + '"' /* double quote, indicates a hex constant */
- alphaToken = otherToken + '`' /* reverse apostrophe, precedes alpha constants */
- pointToken = otherToken + '.' /* decimal point */
- continentalPointToken = otherToken + ',' /* decimal point, Eurostyle */
- zeroToken = otherToken + '0' /* zero, the smallest digit */
- aToken = letterToken + 'A' /* the smallest special hex digit */
- otherAToken = otherToken + 'A' /* special hex digit of type |other_char| */
- attachFraction = 88 /* go here to pack |cur_val| and |f| into |cur_val| */
- attachSign = 89 /* go here when |cur_val| is correct except perhaps for sign */
- defaultRule = 26214 /* 0.4\thinspace pt */
- numberCode = 0 /* command code for \.[\\number] */
- romanNumeralCode = 1 /* command code for \.[\\romannumeral] */
- stringCode = 2 /* command code for \.[\\string] */
- meaningCode = 3 /* command code for \.[\\meaning] */
- fontNameCode = 4 /* command code for \.[\\fontname] */
- jobNameCode = 5 /* command code for \.[\\jobname] */
- closed = 2 /* not open, or at end of file */
- justOpen = 1 /* newly opened, first line not yet read */
- ifCharCode = 0 /* `\.[\\if]' */
- ifCatCode = 1 /* `\.[\\ifcat]' */
- ifIntCode = 2 /* `\.[\\ifnum]' */
- ifDimCode = 3 /* `\.[\\ifdim]' */
- ifOddCode = 4 /* `\.[\\ifodd]' */
- ifVmodeCode = 5 /* `\.[\\ifvmode]' */
- ifHmodeCode = 6 /* `\.[\\ifhmode]' */
- ifMmodeCode = 7 /* `\.[\\ifmmode]' */
- ifInnerCode = 8 /* `\.[\\ifinner]' */
- ifVoidCode = 9 /* `\.[\\ifvoid]' */
- ifHboxCode = 10 /* `\.[\\ifhbox]' */
- ifVboxCode = 11 /* `\.[\\ifvbox]' */
- ifxCode = 12 /* `\.[\\ifx]' */
- ifEofCode = 13 /* `\.[\\ifeof]' */
- ifTrueCode = 14 /* `\.[\\iftrue]' */
- ifFalseCode = 15 /* `\.[\\iffalse]' */
- ifCaseCode = 16 /* `\.[\\ifcase]' */
- ifNodeSize = 2 /* number of words in stack entry for conditionals */
- ifCode = 1 /* code for \.[\\if...] being evaluated */
- fiCode = 2 /* code for \.[\\fi] */
- elseCode = 3 /* code for \.[\\else] */
- orCode = 4 /* code for \.[\\or] */
- formatDefaultLength = 20 /* length of the |TEX_format_default| string */
- formatAreaLength = 11 /* length of its area part */
- formatExtLength = 4 /* length of its `\.[.fmt]' part */
- formatExtension = /* ".fmt" */ 786 /* the extension, as a \.[WEB] constant */
- noTag = 0 /* vanilla character */
- ligTag = 1 /* character has a ligature/kerning program */
- listTag = 2 /* character has a successor in a charlist */
- extTag = 3 /* character is extensible */
- slantCode = 1
- spaceCode = 2
- spaceStretchCode = 3
- spaceShrinkCode = 4
- xHeightCode = 5
- quadCode = 6
- extraSpaceCode = 7
- nonAddress = 0 /* a spurious |bchar_label| */
- badTfm = 11 /* label for |read_font_info| */
- setChar0 = 0 /* typeset character 0 and move right */
- set1 = 128 /* typeset a character and move right */
- setRule = 132 /* typeset a rule and move right */
- putRule = 137 /* typeset a rule */
- nop = 138 /* no operation */
- bop = 139 /* beginning of page */
- eop = 140 /* ending of page */
- push = 141 /* save the current positions */
- pop = 142 /* restore previous positions */
- right1 = 143 /* move right */
- w0 = 147 /* move right by |w| */
- w1 = 148 /* move right and set |w| */
- x0 = 152 /* move right by |x| */
- x1 = 153 /* move right and set |x| */
- down1 = 157 /* move down */
- y0 = 161 /* move down by |y| */
- y1 = 162 /* move down and set |y| */
- z0 = 166 /* move down by |z| */
- z1 = 167 /* move down and set |z| */
- fntNum0 = 171 /* set current font to 0 */
- fnt1 = 235 /* set current font */
- xxx1 = 239 /* extension to \.[DVI] primitives */
- xxx4 = 242 /* potentially long extension to \.[DVI] primitives */
- fntDef1 = 243 /* define the meaning of a font number */
- pre = 247 /* preamble */
- post = 248 /* postamble beginning */
- postPost = 249 /* postamble ending */
- idByte = 2 /* identifies the kind of \.[DVI] files described here */
- movementNodeSize = 3 /* number of words per entry in the down and right stacks */
- yHere = 1 /* |info| when the movement entry points to a |y| command */
- zHere = 2 /* |info| when the movement entry points to a |z| command */
- yzOk = 3 /* |info| corresponding to an unconstrained \\[down] command */
- yOk = 4 /* |info| corresponding to a \\[down] that can't become a |z| */
- zOk = 5 /* |info| corresponding to a \\[down] that can't become a |y| */
- dFixed = 6 /* |info| corresponding to a \\[down] that can't change */
- noneSeen = 0 /* no |y_here| or |z_here| nodes have been encountered yet */
- ySeen = 6 /* we have seen |y_here| but not |z_here| */
- zSeen = 12 /* we have seen |z_here| but not |y_here| */
- movePast = 13 /* go to this label when advancing past glue or a rule */
- finRule = 14 /* go to this label to finish processing a rule */
- nextP = 15 /* go to this label when finished with node |p| */
- exactly = 0 /* a box dimension is pre-specified */
- additional = 1 /* a box dimension is increased from the natural one */
- noadSize = 4 /* number of words in a normal noad */
- mathChar = 1 /* |math_type| when the attribute is simple */
- subBox = 2 /* |math_type| when the attribute is a box */
- subMlist = 3 /* |math_type| when the attribute is a formula */
- mathTextChar = 4 /* |math_type| when italic correction is dubious */
- ordNoad = unsetNode + 3 /* |type| of a noad classified Ord */
- opNoad = ordNoad + 1 /* |type| of a noad classified Op */
- binNoad = ordNoad + 2 /* |type| of a noad classified Bin */
- relNoad = ordNoad + 3 /* |type| of a noad classified Rel */
- openNoad = ordNoad + 4 /* |type| of a noad classified Open */
- closeNoad = ordNoad + 5 /* |type| of a noad classified Close */
- punctNoad = ordNoad + 6 /* |type| of a noad classified Punct */
- innerNoad = ordNoad + 7 /* |type| of a noad classified Inner */
- limits = 1 /* |subtype| of |op_noad| whose scripts are to be above, below */
- noLimits = 2 /* |subtype| of |op_noad| whose scripts are to be normal */
- radicalNoad = innerNoad + 1 /* |type| of a noad for square roots */
- radicalNoadSize = 5 /* number of |mem| words in a radical noad */
- fractionNoad = radicalNoad + 1 /* |type| of a noad for generalized fractions */
- fractionNoadSize = 6 /* number of |mem| words in a fraction noad */
- underNoad = fractionNoad + 1 /* |type| of a noad for underlining */
- overNoad = underNoad + 1 /* |type| of a noad for overlining */
- accentNoad = overNoad + 1 /* |type| of a noad for accented subformulas */
- accentNoadSize = 5 /* number of |mem| words in an accent noad */
- vcenterNoad = accentNoad + 1 /* |type| of a noad for \.[\\vcenter] */
- leftNoad = vcenterNoad + 1 /* |type| of a noad for \.[\\left] */
- rightNoad = leftNoad + 1 /* |type| of a noad for \.[\\right] */
- styleNode = unsetNode + 1 /* |type| of a style node */
- styleNodeSize = 3 /* number of words in a style node */
- displayStyle = 0 /* |subtype| for \.[\\displaystyle] */
- textStyle = 2 /* |subtype| for \.[\\textstyle] */
- scriptStyle = 4 /* |subtype| for \.[\\scriptstyle] */
- scriptScriptStyle = 6 /* |subtype| for \.[\\scriptscriptstyle] */
- cramped = 1 /* add this to an uncramped style if you want to cramp it */
- choiceNode = unsetNode + 2 /* |type| of a choice node */
- textSize = 0 /* size code for the largest size in a family */
- scriptSize = 16 /* size code for the medium size in a family */
- scriptScriptSize = 32 /* size code for the smallest size in a family */
- totalMathsyParams = 22
- totalMathexParams = 13
- doneWithNoad = 80 /* go here when a noad has been fully translated */
- doneWithNode = 81 /* go here when a node has been fully converted */
- checkDimensions = 82 /* go here to update |max_h| and |max_d| */
- deleteQ = 83 /* go here to delete |q| and move to the next node */
- mathSpacing =
- // \hskip-35pt
- /* "0234000122*4000133**3**344*0400400*000000234000111*1111112341011" */ 892
- /* $ \hskip-35pt$ */
- alignStackNodeSize = 5 /* number of |mem| words to save alignment states */
- spanCode = 256 /* distinct from any character */
- crCode = 257 /* distinct from |span_code| and from any character */
- crCrCode = crCode + 1 /* this distinguishes \.[\\crcr] from \.[\\cr] */
- spanNodeSize = 2 /* number of |mem| words for a span node */
- tightFit = 3 // fitness classification for lines shrinking 0.5 to 1.0 of their
- // shrinkability
- looseFit = 1 // fitness classification for lines stretching 0.5 to 1.0 of their
- // stretchability
- veryLooseFit = 0 // fitness classification for lines stretching more than
- // their stretchability
- decentFit = 2 /* fitness classification for all other lines */
- activeNodeSize = 3 /* number of words in active nodes */
- unhyphenated = 0 /* the |type| of a normal active break node */
- hyphenated = 1 /* the |type| of an active node that breaks at a |disc_node| */
- passiveNodeSize = 2 /* number of words in passive nodes */
- deltaNodeSize = 7 /* number of words in a delta node */
- deltaNode = 2 /* |type| field in a delta node */
- deactivate = 60 /* go here when node |r| should be deactivated */
- updateHeights = 90 /* go here to record glue in the |active_height| table */
- insertsOnly = 1
- /* |page_contents| when an insert node has been contributed, but no boxes */
- boxThere = 2 /* |page_contents| when a box or rule has been contributed */
- pageInsNodeSize = 4 /* number of words for a page insertion node */
- inserting = 0 /* an insertion class that has not yet overflowed */
- splitUp = 1 /* an overflowed insertion class */
- contribute = 80 /* go here to link a node into the current page */
- bigSwitch = 60 /* go here to branch on the next token of input */
- mainLoop = 70 /* go here to typeset a string of consecutive characters */
- mainLoopWrapup = 80 /* go here to finish a character or ligature */
- mainLoopMove = 90 /* go here to advance the ligature cursor */
- mainLoopMoveLig = 95 /* same, when advancing past a generated ligature */
- mainLoopLookahead = 100 /* go here to bring in another character, if any */
- mainLigLoop = 110 /* go here to check for ligatures or kerning */
- appendNormalSpace = 120 /* go here to append a normal space between words */
- filCode = 0 /* identifies \.[\\hfil] and \.[\\vfil] */
- fillCode = 1 /* identifies \.[\\hfill] and \.[\\vfill] */
- ssCode = 2 /* identifies \.[\\hss] and \.[\\vss] */
- filNegCode = 3 /* identifies \.[\\hfilneg] and \.[\\vfilneg] */
- skipCode = 4 /* identifies \.[\\hskip] and \.[\\vskip] */
- mskipCode = 5 /* identifies \.[\\mskip] */
- boxCode = 0 /* |chr_code| for `\.[\\box]' */
- copyCode = 1 /* |chr_code| for `\.[\\copy]' */
- lastBoxCode = 2 /* |chr_code| for `\.[\\lastbox]' */
- vsplitCode = 3 /* |chr_code| for `\.[\\vsplit]' */
- vtopCode = 4 /* |chr_code| for `\.[\\vtop]' */
- aboveCode = 0 /* `\.[\\above]' */
- overCode = 1 /* `\.[\\over]' */
- atopCode = 2 /* `\.[\\atop]' */
- delimitedCode = 3 /* `\.[\\abovewithdelims]', etc. */
- charDefCode = 0 /* |shorthand_def| for \.[\\chardef] */
- mathCharDefCode = 1 /* |shorthand_def| for \.[\\mathchardef] */
- countDefCode = 2 /* |shorthand_def| for \.[\\countdef] */
- dimenDefCode = 3 /* |shorthand_def| for \.[\\dimendef] */
- skipDefCode = 4 /* |shorthand_def| for \.[\\skipdef] */
- muSkipDefCode = 5 /* |shorthand_def| for \.[\\muskipdef] */
- toksDefCode = 6 /* |shorthand_def| for \.[\\toksdef] */
- showCode = 0 /* \.[\\show] */
- showBoxCode = 1 /* \.[\\showbox] */
- showTheCode = 2 /* \.[\\showthe] */
- showListsCode = 3 /* \.[\\showlists] */
- badFmt = 6666 /* go here if the format file is unacceptable */
- breakpoint = 888 /* place where a breakpoint is desirable */
- writeNodeSize = 2 /* number of words in a write/whatsit node */
- openNodeSize = 3 /* number of words in an open/whatsit node */
- openNode = 0 /* |subtype| in whatsits that represent files to \.[\\openout] */
- writeNode = 1 /* |subtype| in whatsits that represent things to \.[\\write] */
- closeNode = 2 /* |subtype| in whatsits that represent streams to \.[\\closeout] */
- specialNode = 3 /* |subtype| in whatsits that represent \.[\\special] things */
- languageNode = 4 /* |subtype| in whatsits that change the current language */
- immediateCode = 4 /* command modifier for \.[\\immediate] */
- setLanguageCode = 5 /* command modifier for \.[\\setlanguage] */
- // Constants in the outer block
- memMax = 30000 // greatest index in \TeX's internal |mem| array;
- // must be strictly less than |max_halfword|;
- // must be equal to |mem_top| in \.[INITEX], otherwise |>=mem_top|
- memMin = 0 // smallest index in \TeX's internal |mem| array;
- // must be |min_halfword| or more;
- // must be equal to |mem_bot| in \.[INITEX], otherwise |<=mem_bot|
- bufSize = 500 // maximum number of characters simultaneously present in
- // current lines of open files and in control sequences between
- // \.[\\csname] and \.[\\endcsname]; must not exceed |max_halfword|
- errorLine = 72 // width of context lines on terminal error messages
- halfErrorLine = 42 // width of first lines of contexts in terminal
- // error messages; should be between 30 and |error_line-15|
- maxPrintLine = 79 // width of longest text lines output; should be at least 60
- stackSize = 200 // maximum number of simultaneous input sources
- maxInOpen = 6 // maximum number of input files and error insertions that
- // can be going on simultaneously
- fontMax = 75 // maximum internal font number; must not exceed |max_quarterword|
- // and must be at most |font_base+256|
- fontMemSize = 20000 // number of words of |font_info| for all fonts
- paramSize = 60 // maximum number of simultaneous macro parameters
- nestSize = 40 // maximum number of semantic levels simultaneously active
- maxStrings = 3000 // maximum number of strings; must not exceed |max_halfword|
- stringVacancies = 8000 // the minimum number of characters that should be
- // available for the user's control sequences and font names,
- // after \TeX's own error messages are stored
- poolSize = 32000 // maximum number of characters in strings, including all
- // error messages and help texts, and the names of all fonts and
- // control sequences; must exceed |string_vacancies| by the total
- // length of \TeX's own strings, which is currently about 23000
- saveSize = 600 // space for saving values outside of current group; must be
- // at most |max_halfword|
- trieSize = 8000 // space for hyphenation patterns; should be larger for
- // \.[INITEX] than it is in production versions of \TeX
- trieOpSize = 500 // space for ``opcodes'' in the hyphenation patterns
- dviBufSize = 800 // size of the output buffer; must be a multiple of 8
- fileNameSize = 40 // file names shouldn't be longer than this
- poolName = "TeXformats:TEX.POOL "
- // string of length |file_name_size|; tells where the string pool appears
- // \xref[TeXformats]
- )
- type (
- // Types in the outer block
- asciiCode = /* 0..255 */ byte // eight-bit numbers
- eightBits = /* 0..255 */ byte // unsigned one-byte quantity
- alphaFile = knuth.File // files that contain textual data
- byteFile = knuth.File // files that contain binary data
- poolPointer = /* 0..poolSize */ uint16 // for variables that point into |str_pool|
- strNumber = /* 0..maxStrings */ uint16 // for variables that point into |str_start|
- packedAsciiCode = /* 0..255 */ byte // elements of |str_pool| array
- scaled = int32 // this type is used for scaled integers
- nonnegativeInteger = /* 0..017777777777 */ uint32 // $0\L x<2^[31]$
- smallNumber = /* 0..63 */ byte // this type is self-explanatory
- glueRatio = float64 // one-word representation of a glue expansion factor
- quarterword = /* minQuarterword..maxQuarterword */ byte // 1/4 of a word
- halfword = /* 0..65535 */ uint16 // 1/2 of a word
- twoChoices = /* 1..2 */ byte // used when there are two variants in a record
- fourChoices = /* 1..4 */ byte // used when there are four variants in a record
- twoHalves struct{ data uint32 }
- fourQuarters = struct {
- b0 quarterword
- b1 quarterword
- b2 quarterword
- b3 quarterword
- }
- memoryWord struct{ data uint32 }
- wordFile = knuth.File
- glueOrd = /* normal..filll */ byte // infinity to the 0, 1, 2, or 3 power
- listStateRecord = struct {
- modeField int16
- headField, tailField halfword
- pgField, mlField int32
- auxField memoryWord
- }
- groupCode = /* 0..maxGroupCode */ byte // |save_level| for a level boundary
- inStateRecord = struct {
- stateField, indexField quarterword
- startField, locField, limitField, nameField halfword
- }
- internalFontNumber = /* fontBase..fontMax */ byte // |font| in a |char_node|
- fontIndex = /* 0..fontMemSize */ uint16 // index into |font_info|
- dviIndex = /* 0..dviBufSize */ uint16 // an index into the output buffer
- triePointer = /* 0..trieSize */ uint16 // an index into |trie|
- hyphPointer = /* 0..hyphSize */ uint16 // an index into the ordered hash table
- )
- func (r *memoryWord) gr() *float32 {
- return (*float32)(unsafe.Add(unsafe.Pointer(&r.data), 0))
- }
- func (r *memoryWord) hh() *twoHalves {
- return (*twoHalves)(unsafe.Add(unsafe.Pointer(&r.data), 0))
- }
- func (r *memoryWord) int() *int32 {
- return (*int32)(unsafe.Add(unsafe.Pointer(&r.data), 0))
- }
- func (r *memoryWord) qqqq() *fourQuarters {
- return (*fourQuarters)(unsafe.Add(unsafe.Pointer(&r.data), 0))
- }
- func (r *twoHalves) b0() *quarterword {
- return (*quarterword)(unsafe.Add(unsafe.Pointer(&r.data), 2))
- }
- func (r *twoHalves) b1() *quarterword {
- return (*quarterword)(unsafe.Add(unsafe.Pointer(&r.data), 3))
- }
- func (r *twoHalves) lh() *halfword {
- return (*halfword)(unsafe.Add(unsafe.Pointer(&r.data), 2))
- }
- func (r *twoHalves) rh() *halfword {
- return (*halfword)(unsafe.Add(unsafe.Pointer(&r.data), 0))
- }
- type prg struct {
- stdin, stdout, stderr knuth.File
- // Global variables
- bad int32 // is some ``constant'' wrong?
- xord [256]asciiCode
- // specifies conversion of input characters
- xchr [256]char
- // specifies conversion of output characters
- nameOfFile [40]char
- // on some systems this may be a \&[record] variable
- nameLength/* 0..fileNameSize */ byte
- // this many characters are actually
- // relevant in |name_of_file| (the rest are blank)
- buffer [501]asciiCode // lines of characters being read
- first/* 0..bufSize */ uint16 // the first unused position in |buffer|
- last/* 0..bufSize */ uint16 // end of the line just input to |buffer|
- maxBufStack/* 0..bufSize */ uint16 // largest index used in |buffer|
- termIn alphaFile // the terminal as an input file
- termOut alphaFile // the terminal as an output file
- strPool [32001]packedAsciiCode // the characters
- strStart [3001]poolPointer // the starting pointers
- poolPtr poolPointer // first unused position in |str_pool|
- strPtr strNumber // number of the current string being created
- initPoolPtr poolPointer // the starting value of |pool_ptr|
- initStrPtr strNumber // the starting value of |str_ptr|
- poolFile alphaFile // the string-pool file output by \.[TANGLE]
- logFile alphaFile // transcript of \TeX\ session
- selector/* 0..maxSelector */ byte // where to print a message
- dig [23] /* 0..15 */ byte // digits in a number being output
- tally int32 // the number of characters recently printed
- termOffset/* 0..maxPrintLine */ byte
- // the number of characters on the current terminal line
- fileOffset/* 0..maxPrintLine */ byte
- // the number of characters on the current file line
- trickBuf [73]asciiCode // circular buffer for
- // pseudoprinting
- trickCount int32 // threshold for pseudoprinting, explained later
- firstCount int32 // another variable for pseudoprinting
- interaction/* batchMode..errorStopMode */ byte // current level of interaction
- deletionsAllowed bool // is it safe for |error| to call |get_token|?
- setBoxAllowed bool // is it safe to do a \.[\\setbox] assignment?
- history/* spotless..fatalErrorStop */ byte // has the source input been clean so far?
- errorCount/* -1..100 */ int8 // the number of scrolled errors since the
- // last paragraph ended
- helpLine [6]strNumber // helps for the next |error|
- helpPtr/* 0..6 */ byte // the number of help lines present
- useErrHelp bool // should the |err_help| list be shown?
- interrupt int32 // should \TeX\ pause for instructions?
- okToInterrupt bool // should interrupts be observed?
- arithError bool // has arithmetic overflow occurred recently?
- remainder scaled // amount subtracted to get an exact division
- tempPtr halfword // a pointer variable for occasional emergency use
- mem [30001]memoryWord // the big dynamic storage area
- loMemMax halfword // the largest location of variable-size memory in use
- hiMemMin halfword // the smallest location of one-word memory in use
- varUsed, dynUsed int32 // how much memory is in use
- avail halfword // head of the list of available one-word nodes
- memEnd halfword // the last one-word node used in |mem|
- rover halfword // points to some node in the list of empties
- // free: packed array [mem_min..mem_max] of boolean; [free cells]
- // [ \hskip10pt ] was_free: packed array [mem_min..mem_max] of boolean;
- // [previously free cells]
- // [ \hskip10pt ] was_mem_end, was_lo_max, was_hi_min: halfword ;
- // [previous |mem_end|, |lo_mem_max|, and |hi_mem_min|]
- // [ \hskip10pt ] panicking:boolean; [do we want to check memory constantly?]
- // [ ]
- fontInShortDisplay int32 // an internal font number
- depthThreshold int32 // maximum nesting depth in box displays
- breadthMax int32 // maximum number of items shown at the same list level
- nest [41]listStateRecord
- nestPtr/* 0..nestSize */ byte // first unused location of |nest|
- maxNestStack/* 0..nestSize */ byte // maximum of |nest_ptr| when pushing
- curList listStateRecord // the ``top'' semantic state
- shownMode/* -mmode..mmode */ int16 // most recent mode shown by \.[\\tracingcommands]
- oldSetting/* 0..maxSelector */ byte
- sysTime, sysDay, sysMonth, sysYear int32
- // date and time supplied by external system
- eqtb [6106]memoryWord
- xeqLevel [844]quarterword
- hash [2367]twoHalves
- // the hash table
- hashUsed halfword // allocation pointer for |hash|
- noNewControlSequence bool // are new identifiers legal?
- csCount int32 // total number of known identifiers
- saveStack [601]memoryWord
- savePtr/* 0..saveSize */ uint16 // first unused entry on |save_stack|
- maxSaveStack/* 0..saveSize */ uint16 // maximum usage of save stack
- curLevel quarterword // current nesting level for groups
- curGroup groupCode // current group type
- curBoundary/* 0..saveSize */ uint16 // where the current level begins
- magSet int32 // if nonzero, this magnification should be used henceforth
- curCmd eightBits // current command set by |get_next|
- curChr halfword // operand of current command
- curCs halfword // control sequence found here, zero if none found
- curTok halfword // packed representative of |cur_cmd| and |cur_chr|
- inputStack [201]inStateRecord
- inputPtr/* 0..stackSize */ byte // first unused location of |input_stack|
- maxInStack/* 0..stackSize */ byte // largest value of |input_ptr| when pushing
- curInput inStateRecord
- // the ``top'' input state, according to convention (1)
- inOpen/* 0..maxInOpen */ byte // the number of lines in the buffer, less one
- openParens/* 0..maxInOpen */ byte // the number of open text files
- inputFile [6]alphaFile
- line int32 // current line number in the current source file
- lineStack [6]int32
- scannerStatus/* normal..absorbing */ byte // can a subfile end now?
- warningIndex halfword // identifier relevant to non-|normal| scanner status
- defRef halfword // reference count of token list being defined
- paramStack [61]halfword
- // token list pointers for parameters
- paramPtr/* 0..paramSize */ byte // first unused entry in |param_stack|
- maxParamStack int32
- // largest value of |param_ptr|, will be |<=param_size+9|
- alignState int32 // group level with respect to current alignment
- basePtr/* 0..stackSize */ byte // shallowest level shown by |show_context|
- parLoc halfword // location of `\.[\\par]' in |eqtb|
- parToken halfword // token representing `\.[\\par]'
- forceEof bool // should the next \.[\\input] be aborted early?
- curMark [5]halfword
- // token lists for marks
- longState/* call..longOuterCall */ byte // governs the acceptance of \.[\\par]
- pstack [9]halfword // arguments supplied to a macro
- curVal int32 // value returned by numeric scanners
- curValLevel/* intVal..tokVal */ byte // the ``level'' of this value
- radix smallNumber // |scan_int| sets this to 8, 10, 16, or zero
- curOrder glueOrd // order of infinity found by |scan_dimen|
- readFile [16]alphaFile // used for \.[\\read]
- readOpen [17] /* normal..closed */ byte // state of |read_file[n]|
- condPtr halfword // top of the condition stack
- ifLimit/* normal..orCode */ byte // upper bound on |fi_or_else| codes
- curIf smallNumber // type of conditional being worked on
- ifLine int32 // line where that conditional began
- skipLine int32 // skipping began here
- curName strNumber // name of file just scanned
- curArea strNumber // file area just scanned, or \.[""]
- curExt strNumber // file extension just scanned, or \.[""]
- areaDelimiter poolPointer // the most recent `\.>' or `\.:', if any
- extDelimiter poolPointer // the relevant `\..', if any
- texFormatDefault [20]char
- nameInProgress bool // is a file name being scanned?
- jobName strNumber // principal file name
- logOpened bool // has the transcript file been opened?
- dviFile byteFile // the device-independent output goes here
- outputFileName strNumber // full name of the output file
- logName strNumber // full name of the log file
- tfmFile byteFile
- buf eightBits
- fontInfo [20001]memoryWord
- // the big collection of font data
- fmemPtr fontIndex // first unused word of |font_info|
- fontPtr internalFontNumber // largest internal font number in use
- fontCheck [76]fourQuarters // check sum
- fontSize [76]scaled // ``at'' size
- fontDsize [76]scaled // ``design'' size
- fontParams [76]fontIndex // how many font
- // parameters are present
- fontName [76]strNumber // name of the font
- fontArea [76]strNumber // area of the font
- fontBc [76]eightBits
- // beginning (smallest) character code
- fontEc [76]eightBits
- // ending (largest) character code
- fontGlue [76]halfword
- // glue specification for interword space, |null| if not allocated
- fontUsed [76]bool
- // has a character from this font actually appeared in the output?
- hyphenChar [76]int32
- // current \.[\\hyphenchar] values
- skewChar [76]int32
- // current \.[\\skewchar] values
- bcharLabel [76]fontIndex
- // start of |lig_kern| program for left boundary character,
- // |non_address| if there is none
- fontBchar [76] /* minQuarterword..256+minQuarterword */ uint16
- // boundary character, |non_char| if there is none
- fontFalseBchar [76] /* minQuarterword..256+minQuarterword */ uint16
- // |font_bchar| if it doesn't exist in the font, otherwise |non_char|
- charBase [76]int32
- // base addresses for |char_info|
- widthBase [76]int32
- // base addresses for widths
- heightBase [76]int32
- // base addresses for heights
- depthBase [76]int32
- // base addresses for depths
- italicBase [76]int32
- // base addresses for italic corrections
- ligKernBase [76]int32
- // base addresses for ligature/kerning programs
- kernBase [76]int32
- // base addresses for kerns
- extenBase [76]int32
- // base addresses for extensible recipes
- paramBase [76]int32
- // base addresses for font parameters
- nullCharacter fourQuarters // nonexistent character information
- totalPages int32 // the number of pages that have been shipped out
- maxV scaled // maximum height-plus-depth of pages shipped so far
- maxH scaled // maximum width of pages shipped so far
- maxPush int32 // deepest nesting of |push| commands encountered so far
- lastBop int32 // location of previous |bop| in the \.[DVI] output
- deadCycles int32 // recent outputs that didn't ship anything out
- doingLeaders bool // are we inside a leader box?
- c, f quarterword // character and font in current |char_node|
- ruleHt, ruleDp, ruleWd scaled // size of current rule being output
- g halfword // current glue specification
- lq, lr int32 // quantities used in calculations for leaders
- dviBuf [801]eightBits // buffer for \.[DVI] output
- halfBuf dviIndex // half of |dvi_buf_size|
- dviLimit dviIndex // end of the current half buffer
- dviPtr dviIndex // the next available buffer address
- dviOffset int32 // |dvi_buf_size| times the number of times the
- // output buffer has been fully emptied
- dviGone int32 // the number of bytes already output to |dvi_file|
- downPtr, rightPtr halfword // heads of the down and right stacks
- dviH, dviV scaled // a \.[DVI] reader program thinks we are here
- curH, curV scaled // \TeX\ thinks we are here
- dviF internalFontNumber // the current font
- curS int32 // current depth of output box nesting, initially $-1$
- totalStretch, totalShrink [4]scaled
- // glue found by |hpack| or |vpack|
- lastBadness int32 // badness of the most recently packaged box
- adjustTail halfword // tail of adjustment list
- packBeginLine int32 // source file line where the current paragraph
- // or alignment began; a negative value denotes alignment
- emptyField twoHalves
- nullDelimiter fourQuarters
- curMlist halfword // beginning of mlist to be translated
- curStyle smallNumber // style code at current place in the list
- curSize smallNumber // size code corresponding to |cur_style|
- curMu scaled // the math unit width corresponding to |cur_size|
- mlistPenalties bool // should |mlist_to_hlist| insert penalties?
- curF internalFontNumber // the |font| field of a |math_char|
- curC quarterword // the |character| field of a |math_char|
- curI fourQuarters // the |char_info| of a |math_char|,
- // or a lig/kern instruction
- magicOffset int32 // used to find inter-element spacing
- curAlign halfword // current position in preamble list
- curSpan halfword // start of currently spanned columns in preamble list
- curLoop halfword // place to copy when extending a periodic preamble
- alignPtr halfword // most recently pushed-down alignment stack node
- curHead, curTail halfword // adjustment list pointers
- justBox halfword // the |hlist_node| for the last line of the new paragraph
- passive halfword // most recent node on passive list
- printedNode halfword // most recent node that has been printed
- passNumber halfword // the number of passive nodes allocated on this pass
- activeWidth [6]scaled
- // distance from first active node to~|cur_p|
- curActiveWidth [6]scaled // distance from current active node
- background [6]scaled // length of an ``empty'' line
- breakWidth [6]scaled // length being computed after current break
- noShrinkErrorYet bool // have we complained about infinite shrinkage?
- curP halfword // the current breakpoint under consideration
- secondPass bool // is this our second attempt to break this paragraph?
- finalPass bool // is this our final attempt to break this paragraph?
- threshold int32 // maximum badness on feasible lines
- minimalDemerits [4]int32 // best total
- // demerits known for current line class and position, given the fitness
- minimumDemerits int32 // best total demerits known for current line class
- // and position
- bestPlace [4]halfword // how to achieve
- // |minimal_demerits|
- bestPlLine [4]halfword // corresponding
- // line number
- discWidth scaled // the length of discretionary material preceding a break
- easyLine halfword // line numbers |>easy_line| are equivalent in break nodes
- lastSpecialLine halfword // line numbers |>last_special_line| all have
- // the same width
- firstWidth scaled // the width of all lines |<=last_special_line|, if
- // no \.[\\parshape] has been specified
- secondWidth scaled // the width of all lines |>last_special_line|
- firstIndent scaled // left margin to go with |first_width|
- secondIndent scaled // left margin to go with |second_width|
- bestBet halfword // use this passive node and its predecessors
- fewestDemerits int32 // the demerits associated with |best_bet|
- bestLine halfword // line number following the last line of the new paragraph
- actualLooseness int32 // the difference between |line_number(best_bet)|
- // and the optimum |best_line|
- lineDiff int32 // the difference between the current line number and
- // the optimum |best_line|
- hc [66] /* 0..256 */ uint16 // word to be hyphenated
- hn/* 0..64 */ byte // the number of positions occupied in |hc|;
- // not always a |small_number|
- ha, hb halfword // nodes |ha..hb| should be replaced by the hyphenated result
- hf internalFontNumber // font number of the letters in |hc|
- hu [64] /* 0..256 */ uint16 // like |hc|, before conversion to lowercase
- hyfChar int32 // hyphen character of the relevant font
- curLang, initCurLang asciiCode // current hyphenation table of interest
- lHyf, rHyf, initLHyf, initRHyf int32 // limits on fragment sizes
- hyfBchar halfword // boundary character after $c_n$
- hyf [65] /* 0..9 */ byte // odd values indicate discretionary hyphens
- initList halfword // list of punctuation characters preceding the word
- initLig bool // does |init_list| represent a ligature?
- initLft bool // if so, did the ligature involve a left boundary?
- hyphenPassed smallNumber // first hyphen in a ligature, if any
- curL, curR halfword // characters before and after the cursor
- curQ halfword // where a ligature should be detached
- ligStack halfword // unfinished business to the right of the cursor
- ligaturePresent bool // should a ligature node be made for |cur_l|?
- lftHit, rtHit bool // did we hit a ligature with a boundary character?
- trie [8001]twoHalves // |trie_link|, |trie_char|, |trie_op|
- hyfDistance [500]smallNumber // position |k-j| of $n_j$
- hyfNum [500]smallNumber // value of $n_j$
- hyfNext [500]quarterword // continuation code
- opStart [256] /* 0..trieOpSize */ uint16 // offset for current language
- hyphWord [308]strNumber // exception words
- hyphList [308]halfword // lists of hyphen positions
- hyphCount hyphPointer // the number of words in the exception dictionary
- trieOpHash [1001] /* 0..trieOpSize */ uint16
- // trie op codes for quadruples
- trieUsed [256]quarterword
- // largest opcode used so far for this language
- trieOpLang [500]asciiCode
- // language part of a hashed quadruple
- trieOpVal [500]quarterword
- // opcode corresponding to a hashed quadruple
- trieOpPtr/* 0..trieOpSize */ uint16 // number of stored ops so far
- trieC [8001]packedAsciiCode
- // characters to match
- // \hskip10pt
- trieO [8001]quarterword
- // operations to perform
- // \hskip10pt
- trieL [8001]triePointer
- // left subtrie links
- // \hskip10pt
- trieR [8001]triePointer
- // right subtrie links
- // \hskip10pt
- triePtr triePointer // the number of nodes in the trie
- // \hskip10pt
- trieHash [8001]triePointer
- // used to identify equivalent subtries
- trieTaken [8000]bool
- // does a family start here?
- // \hskip10pt
- trieMin [256]triePointer
- // the first possible slot for each character
- // \hskip10pt
- trieMax triePointer // largest location used in |trie|
- // \hskip10pt
- trieNotReady bool // is the trie still in linked form?
- bestHeightPlusDepth scaled // height of the best box, without stretching or
- // shrinking
- pageTail halfword // the final node on the current page
- pageContents/* empty..boxThere */ byte // what is on the current page so far?
- pageMaxDepth scaled // maximum box depth on page being built
- bestPageBreak halfword // break here to get the best page known so far
- leastPageCost int32 // the score for this currently best page
- bestSize scaled // its |page_goal|
- pageSoFar [8]scaled // height and glue of the current page
- lastGlue halfword // used to implement \.[\\lastskip]
- lastPenalty int32 // used to implement \.[\\lastpenalty]
- lastKern scaled // used to implement \.[\\lastkern]
- insertPenalties int32 // sum of the penalties for insertions
- // that were held over
- outputActive bool // are we in the midst of an output routine?
- mainF internalFontNumber // the current font
- mainI fourQuarters // character information bytes for |cur_l|
- mainJ fourQuarters // ligature/kern command
- mainK fontIndex // index into |font_info|
- mainP halfword // temporary register for list manipulation
- mainS int32 // space factor value
- bchar halfword // boundary character of current font, or |non_char|
- falseBchar halfword // nonexistent character matching |bchar|, or |non_char|
- cancelBoundary bool // should the left boundary be ignored?
- insDisc bool // should we insert a discretionary node?
- curBox halfword // box to be placed into its context
- afterToken halfword // zero, or a saved token
- longHelpSeen bool // has the long \.[\\errmessage] help been used?
- formatIdent strNumber
- fmtFile wordFile // for input or output of format information
- readyAlready int32 // a sacrifice of purity for economy
- writeFile [16]alphaFile
- writeOpen [18]bool
- writeLoc halfword // |eqtb| address of \.[\\write]
- }
- func (prg *prg) initialize() { // this procedure gets things started properly
- var (
- // Local variables for initialization
- i int32
- k int32 // index into |mem|, |eqtb|, etc.
- z hyphPointer // runs through the exception dictionary
- )
- prg.xchr[040] = ' '
- prg.xchr[041] = '!'
- prg.xchr[042] = '"'
- prg.xchr[043] = '#'
- prg.xchr[044] = '$'
- prg.xchr[045] = '%'
- prg.xchr[046] = '&'
- prg.xchr[047] = '\''
- prg.xchr[050] = '('
- prg.xchr[051] = ')'
- prg.xchr[052] = '*'
- prg.xchr[053] = '+'
- prg.xchr[054] = ','
- prg.xchr[055] = '-'
- prg.xchr[056] = '.'
- prg.xchr[057] = '/'
- prg.xchr[060] = '0'
- prg.xchr[061] = '1'
- prg.xchr[062] = '2'
- prg.xchr[063] = '3'
- prg.xchr[064] = '4'
- prg.xchr[065] = '5'
- prg.xchr[066] = '6'
- prg.xchr[067] = '7'
- prg.xchr[070] = '8'
- prg.xchr[071] = '9'
- prg.xchr[072] = ':'
- prg.xchr[073] = ';'
- prg.xchr[074] = '<'
- prg.xchr[075] = '='
- prg.xchr[076] = '>'
- prg.xchr[077] = '?'
- prg.xchr[0100] = '@'
- prg.xchr[0101] = 'A'
- prg.xchr[0102] = 'B'
- prg.xchr[0103] = 'C'
- prg.xchr[0104] = 'D'
- prg.xchr[0105] = 'E'
- prg.xchr[0106] = 'F'
- prg.xchr[0107] = 'G'
- prg.xchr[0110] = 'H'
- prg.xchr[0111] = 'I'
- prg.xchr[0112] = 'J'
- prg.xchr[0113] = 'K'
- prg.xchr[0114] = 'L'
- prg.xchr[0115] = 'M'
- prg.xchr[0116] = 'N'
- prg.xchr[0117] = 'O'
- prg.xchr[0120] = 'P'
- prg.xchr[0121] = 'Q'
- prg.xchr[0122] = 'R'
- prg.xchr[0123] = 'S'
- prg.xchr[0124] = 'T'
- prg.xchr[0125] = 'U'
- prg.xchr[0126] = 'V'
- prg.xchr[0127] = 'W'
- prg.xchr[0130] = 'X'
- prg.xchr[0131] = 'Y'
- prg.xchr[0132] = 'Z'
- prg.xchr[0133] = '['
- prg.xchr[0134] = '\\'
- prg.xchr[0135] = ']'
- prg.xchr[0136] = '^'
- prg.xchr[0137] = '_'
- prg.xchr[0140] = '`'
- prg.xchr[0141] = 'a'
- prg.xchr[0142] = 'b'
- prg.xchr[0143] = 'c'
- prg.xchr[0144] = 'd'
- prg.xchr[0145] = 'e'
- prg.xchr[0146] = 'f'
- prg.xchr[0147] = 'g'
- prg.xchr[0150] = 'h'
- prg.xchr[0151] = 'i'
- prg.xchr[0152] = 'j'
- prg.xchr[0153] = 'k'
- prg.xchr[0154] = 'l'
- prg.xchr[0155] = 'm'
- prg.xchr[0156] = 'n'
- prg.xchr[0157] = 'o'
- prg.xchr[0160] = 'p'
- prg.xchr[0161] = 'q'
- prg.xchr[0162] = 'r'
- prg.xchr[0163] = 's'
- prg.xchr[0164] = 't'
- prg.xchr[0165] = 'u'
- prg.xchr[0166] = 'v'
- prg.xchr[0167] = 'w'
- prg.xchr[0170] = 'x'
- prg.xchr[0171] = 'y'
- prg.xchr[0172] = 'z'
- prg.xchr[0173] = '{'
- prg.xchr[0174] = '|'
- prg.xchr[0175] = '}'
- prg.xchr[0176] = '~'
- for ii := int32(0); ii <= 037; ii++ {
- i = ii
- _ = i
- prg.xchr[i] = ' '
- }
- for ii := int32(0177); ii <= 0377; ii++ {
- i = ii
- _ = i
- prg.xchr[i] = ' '
- }
- for ii := int32(firstTextChar); ii <= lastTextChar; ii++ {
- i = ii
- _ = i
- prg.xord[char(i)] = byte(invalidCode)
- }
- for ii := int32(0200); ii <= 0377; ii++ {
- i = ii
- _ = i
- prg.xord[prg.xchr[i]] = byte(i)
- }
- for ii := int32(0); ii <= 0176; ii++ {
- i = ii
- _ = i
- prg.xord[prg.xchr[i]] = byte(i)
- }
- prg.interaction = byte(errorStopMode)
- prg.deletionsAllowed = true
- prg.setBoxAllowed = true
- prg.errorCount = 0 // |history| is initialized elsewhere
- prg.helpPtr = 0
- prg.useErrHelp = false
- prg.interrupt = 0
- prg.okToInterrupt = true
- // was_mem_end:=mem_min; [indicate that everything was previously free]
- // was_lo_max:=mem_min; was_hi_min:=mem_max;
- // panicking:=false;
- // [ ]
- prg.nestPtr = 0
- prg.maxNestStack = 0
- prg.curList.modeField = int16(vmode)
- prg.curList.headField = uint16(30000 - 1)
- prg.curList.tailField = uint16(30000 - 1)
- *prg.curList.auxField.int() = -65536000
- prg.curList.mlField = 0
- prg.curList.pgField = 0
- prg.shownMode = 0
- // Start a new current page
- prg.pageContents = byte(empty)
- prg.pageTail = uint16(30000 - 2)
- *(*prg.mem[30000-2].hh()).rh() = 0
- prg.lastGlue = 65535
- prg.lastPenalty = 0
- prg.lastKern = 0
- prg.pageSoFar[7] = 0
- prg.pageMaxDepth = 0
- for ii := int32(intBase); ii <= eqtbSize; ii++ {
- k = ii
- _ = k
- prg.xeqLevel[k-5263] = byte(levelOne)
- }
- prg.noNewControlSequence = true // new identifiers are usually forbidden
- *prg.hash[hashBase-514].lh() = 0
- *prg.hash[hashBase-514].rh() = 0
- for ii := int32(hashBase + 1); ii <= undefinedControlSequence-1; ii++ {
- k = ii
- _ = k
- prg.hash[k-514] = prg.hash[hashBase-514]
- }
- prg.savePtr = 0
- prg.curLevel = byte(levelOne)
- prg.curGroup = byte(bottomLevel)
- prg.curBoundary = 0
- prg.maxSaveStack = 0
- prg.magSet = 0
- prg.curMark[topMarkCode] = 0
- prg.curMark[firstMarkCode] = 0
- prg.curMark[botMarkCode] = 0
- prg.curMark[splitFirstMarkCode] = 0
- prg.curMark[splitBotMarkCode] = 0
- prg.curVal = 0
- prg.curValLevel = byte(intVal)
- prg.radix = 0
- prg.curOrder = byte(normal)
- for ii := int32(0); ii <= 16; ii++ {
- k = ii
- _ = k
- prg.readOpen[k] = byte(closed)
- }
- prg.condPtr = 0
- prg.ifLimit = byte(normal)
- prg.curIf = 0
- prg.ifLine = 0
- strcopy(prg.texFormatDefault[:], "TeXformats:plain.fmt")
- // \xref[TeXformats]
- // \xref[plain]
- // \xref[system dependencies]
- for ii := int32(fontBase); ii <= fontMax; ii++ {
- k = ii
- _ = k
- prg.fontUsed[k] = false
- }
- prg.nullCharacter.b0 = byte(minQuarterword)
- prg.nullCharacter.b1 = byte(minQuarterword)
- prg.nullCharacter.b2 = byte(minQuarterword)
- prg.nullCharacter.b3 = byte(minQuarterword)
- prg.totalPages = 0
- prg.maxV = 0
- prg.maxH = 0
- prg.maxPush = 0
- prg.lastBop = -1
- prg.doingLeaders = false
- prg.deadCycles = 0
- prg.curS = -1
- prg.halfBuf = uint16(dviBufSize / 2)
- prg.dviLimit = uint16(dviBufSize)
- prg.dviPtr = 0
- prg.dviOffset = 0
- prg.dviGone = 0
- prg.downPtr = 0
- prg.rightPtr = 0
- prg.adjustTail = 0
- prg.lastBadness = 0
- prg.packBeginLine = 0
- *prg.emptyField.rh() = uint16(empty)
- *prg.emptyField.lh() = 0
- prg.nullDelimiter.b0 = 0
- prg.nullDelimiter.b1 = byte(minQuarterword)
- prg.nullDelimiter.b2 = 0
- prg.nullDelimiter.b3 = byte(minQuarterword)
- prg.alignPtr = 0
- prg.curAlign = 0
- prg.curSpan = 0
- prg.curLoop = 0
- prg.curHead = 0
- prg.curTail = 0
- for ii := int32(0); ii <= hyphSize; ii++ {
- z = hyphPointer(ii)
- _ = z
- prg.hyphWord[z] = 0
- prg.hyphList[z] = 0
- }
- prg.hyphCount = 0
- prg.outputActive = false
- prg.insertPenalties = 0
- prg.ligaturePresent = false
- prg.cancelBoundary = false
- prg.lftHit = false
- prg.rtHit = false
- prg.insDisc = false
- prg.afterToken = 0
- prg.longHelpSeen = false
- prg.formatIdent = 0
- for ii := int32(0); ii <= 17; ii++ {
- k = ii
- _ = k
- prg.writeOpen[k] = false
- }
- // Initialize table entries (done by \.[INITEX] only)
- for ii := int32(memBot + 1); ii <= memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize-1; ii++ {
- k = ii
- _ = k
- *prg.mem[k].int() = 0
- }
- // all glue dimensions are zeroed
- // \xref[data structure assumptions]
- k = memBot
- for k <= memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize-1 {
- // set first words of glue specifications
- *(*prg.mem[k].hh()).rh() = uint16(0 + 1)
- *(*prg.mem[k].hh()).b0() = byte(normal)
- *(*prg.mem[k].hh()).b1() = byte(normal)
- k = k + glueSpecSize
- }
- *prg.mem[memBot+glueSpecSize+2].int() = 0200000
- *(*prg.mem[memBot+glueSpecSize].hh()).b0() = byte(fil)
- *prg.mem[memBot+glueSpecSize+glueSpecSize+2].int() = 0200000
- *(*prg.mem[memBot+glueSpecSize+glueSpecSize].hh()).b0() = byte(fill)
- *prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize+2].int() = 0200000
- *(*prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize].hh()).b0() = byte(fil)
- *prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize+3].int() = 0200000
- *(*prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize].hh()).b1() = byte(fil)
- *prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+2].int() = -0200000
- *(*prg.mem[memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize].hh()).b0() = byte(fil)
- prg.rover = uint16(memBot + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize - 1 + 1)
- *(*prg.mem[prg.rover].hh()).rh() = 65535 // now initialize the dynamic memory
- *(*prg.mem[prg.rover].hh()).lh() = 1000 // which is a 1000-word available node
- *(*prg.mem[int32(prg.rover)+1].hh()).lh() = prg.rover
- *(*prg.mem[int32(prg.rover)+1].hh()).rh() = prg.rover
- prg.loMemMax = uint16(int32(prg.rover) + 1000)
- *(*prg.mem[prg.loMemMax].hh()).rh() = 0
- *(*prg.mem[prg.loMemMax].hh()).lh() = 0
- for ii := int32(30000 - 13); ii <= 30000; ii++ {
- k = ii
- _ = k
- prg.mem[k] = prg.mem[prg.loMemMax]
- } // clear list heads
- // Initialize the special list heads and constant nodes
- *(*prg.mem[30000-10].hh()).lh() = uint16(07777 + frozenEndTemplate) // |link(omit_template)=null|
- *(*prg.mem[30000-9].hh()).rh() = uint16(maxQuarterword + 1)
- *(*prg.mem[30000-9].hh()).lh() = 0
- *(*prg.mem[30000-7].hh()).b0() = byte(hyphenated)
- *(*prg.mem[30000-7+1].hh()).lh() = 65535
- *(*prg.mem[30000-7].hh()).b1() = 0 // the |subtype| is never examined by the algorithm
- *(*prg.mem[30000].hh()).b1() = byte(255 + minQuarterword)
- *(*prg.mem[30000].hh()).b0() = byte(splitUp)
- *(*prg.mem[30000].hh()).rh() = 30000
- *(*prg.mem[30000-2].hh()).b0() = byte(glueNode)
- *(*prg.mem[30000-2].hh()).b1() = byte(normal)
- prg.avail = 0
- prg.memEnd = 30000
- prg.hiMemMin = uint16(30000 - 13) // initialize the one-word memory
- prg.varUsed = memBot + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize - 1 + 1 - memBot
- prg.dynUsed = hiMemStatUsage
- // initialize statistics
- *(*prg.eqtb[undefinedControlSequence-1].hh()).b0() = byte(undefinedCs)
- *(*prg.eqtb[undefinedControlSequence-1].hh()).rh() = 0
- *(*prg.eqtb[undefinedControlSequence-1].hh()).b1() = byte(levelZero)
- for ii := int32(activeBase); ii <= undefinedControlSequence-1; ii++ {
- k = ii
- _ = k
- prg.eqtb[k-1] = prg.eqtb[undefinedControlSequence-1]
- }
- *(*prg.eqtb[glueBase-1].hh()).rh() = uint16(memBot)
- *(*prg.eqtb[glueBase-1].hh()).b1() = byte(levelOne)
- *(*prg.eqtb[glueBase-1].hh()).b0() = byte(glueRef)
- for ii := int32(glueBase + 1); ii <= localBase-1; ii++ {
- k = ii
- _ = k
- prg.eqtb[k-1] = prg.eqtb[glueBase-1]
- }
- *(*prg.mem[memBot].hh()).rh() = uint16(int32(*(*prg.mem[memBot].hh()).rh()) + localBase - glueBase)
- *(*prg.eqtb[parShapeLoc-1].hh()).rh() = 0
- *(*prg.eqtb[parShapeLoc-1].hh()).b0() = byte(shapeRef)
- *(*prg.eqtb[parShapeLoc-1].hh()).b1() = byte(levelOne)
- for ii := int32(outputRoutineLoc); ii <= toksBase+255; ii++ {
- k = ii
- _ = k
- prg.eqtb[k-1] = prg.eqtb[undefinedControlSequence-1]
- }
- *(*prg.eqtb[boxBase+0-1].hh()).rh() = 0
- *(*prg.eqtb[boxBase-1].hh()).b0() = byte(boxRef)
- *(*prg.eqtb[boxBase-1].hh()).b1() = byte(levelOne)
- for ii := int32(boxBase + 1); ii <= boxBase+255; ii++ {
- k = ii
- _ = k
- prg.eqtb[k-1] = prg.eqtb[boxBase-1]
- }
- *(*prg.eqtb[curFontLoc-1].hh()).rh() = uint16(fontBase)
- *(*prg.eqtb[curFontLoc-1].hh()).b0() = byte(data)
- *(*prg.eqtb[curFontLoc-1].hh()).b1() = byte(levelOne)
- for ii := int32(mathFontBase); ii <= mathFontBase+47; ii++ {
- k = ii
- _ = k
- prg.eqtb[k-1] = prg.eqtb[curFontLoc-1]
- }
- *(*prg.eqtb[catCodeBase-1].hh()).rh() = 0
- *(*prg.eqtb[catCodeBase-1].hh()).b0() = byte(data)
- *(*prg.eqtb[catCodeBase-1].hh()).b1() = byte(levelOne)
- for ii := int32(catCodeBase + 1); ii <= intBase-1; ii++ {
- k = ii
- _ = k
- prg.eqtb[k-1] = prg.eqtb[catCodeBase-1]
- }
- for ii := int32(0); ii <= 255; ii++ {
- k = ii
- _ = k
- *(*prg.eqtb[catCodeBase+k-1].hh()).rh() = uint16(otherChar)
- *(*prg.eqtb[mathCodeBase+k-1].hh()).rh() = uint16(k + 0)
- *(*prg.eqtb[sfCodeBase+k-1].hh()).rh() = 1000
- }
- *(*prg.eqtb[catCodeBase+carriageReturn-1].hh()).rh() = uint16(carRet)
- *(*prg.eqtb[catCodeBase+' '-1].hh()).rh() = uint16(spacer)
- *(*prg.eqtb[catCodeBase+'\\'-1].hh()).rh() = uint16(escape)
- *(*prg.eqtb[catCodeBase+'%'-1].hh()).rh() = uint16(comment)
- *(*prg.eqtb[catCodeBase+invalidCode-1].hh()).rh() = uint16(invalidChar)
- *(*prg.eqtb[catCodeBase+nullCode-1].hh()).rh() = uint16(ignore)
- for ii := int32('0'); ii <= '9'; ii++ {
- k = ii
- _ = k
- *(*prg.eqtb[mathCodeBase+k-1].hh()).rh() = uint16(k + 070000 + 0)
- }
- for ii := int32('A'); ii <= 'Z'; ii++ {
- k = ii
- _ = k
- *(*prg.eqtb[catCodeBase+k-1].hh()).rh() = uint16(letter)
- *(*prg.eqtb[catCodeBase+k+'a'-'A'-1].hh()).rh() = uint16(letter)
- *(*prg.eqtb[mathCodeBase+k-1].hh()).rh() = uint16(k + 070000 + 0400 + 0)
- *(*prg.eqtb[mathCodeBase+k+'a'-'A'-1].hh()).rh() = uint16(k + 'a' - 'A' + 070000 + 0400 + 0)
- *(*prg.eqtb[lcCodeBase+k-1].hh()).rh() = uint16(k + 'a' - 'A')
- *(*prg.eqtb[lcCodeBase+k+'a'-'A'-1].hh()).rh() = uint16(k + 'a' - 'A')
- *(*prg.eqtb[ucCodeBase+k-1].hh()).rh() = uint16(k)
- *(*prg.eqtb[ucCodeBase+k+'a'-'A'-1].hh()).rh() = uint16(k)
- *(*prg.eqtb[sfCodeBase+k-1].hh()).rh() = 999
- }
- for ii := int32(intBase); ii <= delCodeBase-1; ii++ {
- k = ii
- _ = k
- *prg.eqtb[k-1].int() = 0
- }
- *prg.eqtb[intBase+magCode-1].int() = 1000
- *prg.eqtb[intBase+toleranceCode-1].int() = 10000
- *prg.eqtb[intBase+hangAfterCode-1].int() = 1
- *prg.eqtb[intBase+maxDeadCyclesCode-1].int() = 25
- *prg.eqtb[intBase+escapeCharCode-1].int() = '\\'
- *prg.eqtb[intBase+endLineCharCode-1].int() = carriageReturn
- for ii := int32(0); ii <= 255; ii++ {
- k = ii
- _ = k
- *prg.eqtb[delCodeBase+k-1].int() = -1
- }
- *prg.eqtb[delCodeBase+'.'-1].int() = 0 // this null delimiter is used in error recovery
- for ii := int32(dimenBase); ii <= eqtbSize; ii++ {
- k = ii
- _ = k
- *prg.eqtb[k-1].int() = 0
- }
- prg.hashUsed = uint16(frozenControlSequence) // nothing is used
- prg.csCount = 0
- *(*prg.eqtb[frozenDontExpand-1].hh()).b0() = byte(dontExpand)
- *prg.hash[frozenDontExpand-514].rh() = 502
- // \xref[notexpanded:]
- prg.fontPtr = byte(fontBase)
- prg.fmemPtr = 7
- prg.fontName[fontBase] = /* "nullfont" */ 801
- prg.fontArea[fontBase] = /* "" */ 338
- prg.hyphenChar[fontBase] = '-'
- prg.skewChar[fontBase] = -1
- prg.bcharLabel[fontBase] = uint16(nonAddress)
- prg.fontBchar[fontBase] = uint16(256 + minQuarterword)
- prg.fontFalseBchar[fontBase] = uint16(256 + minQuarterword)
- prg.fontBc[fontBase] = 1
- prg.fontEc[fontBase] = 0
- prg.fontSize[fontBase] = 0
- prg.fontDsize[fontBase] = 0
- prg.charBase[fontBase] = 0
- prg.widthBase[fontBase] = 0
- prg.heightBase[fontBase] = 0
- prg.depthBase[fontBase] = 0
- prg.italicBase[fontBase] = 0
- prg.ligKernBase[fontBase] = 0
- prg.kernBase[fontBase] = 0
- prg.extenBase[fontBase] = 0
- prg.fontGlue[fontBase] = 0
- prg.fontParams[fontBase] = 7
- prg.paramBase[fontBase] = -1
- for ii := int32(0); ii <= 6; ii++ {
- k = ii
- _ = k
- *prg.fontInfo[k].int() = 0
- }
- for ii := int32(-trieOpSize); ii <= trieOpSize; ii++ {
- k = ii
- _ = k
- prg.trieOpHash[k+500] = 0
- }
- for ii := int32(0); ii <= 255; ii++ {
- k = ii
- _ = k
- prg.trieUsed[k] = byte(minQuarterword)
- }
- prg.trieOpPtr = 0
- prg.trieNotReady = true
- prg.trieL[0] = 0
- prg.trieC[0] = 0
- prg.triePtr = 0
- *prg.hash[frozenProtection-514].rh() = 1190
- // \xref[inaccessible]
- prg.formatIdent = /* " (INITEX)" */ 1257
- *prg.hash[endWrite-514].rh() = 1296
- *(*prg.eqtb[endWrite-1].hh()).b1() = byte(levelOne)
- *(*prg.eqtb[endWrite-1].hh()).b0() = byte(outerCall)
- *(*prg.eqtb[endWrite-1].hh()).rh() = 0
- }
- // \4
- // Basic printing procedures
- func (prg *prg) printLn() {
- switch prg.selector {
- case termAndLog:
- prg.termOut.Writeln()
- prg.logFile.Writeln()
- prg.termOffset = 0
- prg.fileOffset = 0
- case logOnly:
- prg.logFile.Writeln()
- prg.fileOffset = 0
- case termOnly:
- prg.termOut.Writeln()
- prg.termOffset = 0
- case noPrint, pseudo, newString:
- default:
- prg.writeFile[prg.selector].Writeln()
- }
- } // |tally| is not affected
- func (prg *prg) printChar(s asciiCode) {
- if int32(s) == *prg.eqtb[intBase+newLineCharCode-1].int() {
- // Character |s| is the current new-line character
- if int32(prg.selector) < pseudo {
- prg.printLn()
- goto exit
- }
- }
- switch prg.selector {
- case termAndLog:
- prg.termOut.Write(string(rune(prg.xchr[s])))
- prg.logFile.Write(string(rune(prg.xchr[s])))
- prg.termOffset = byte(int32(prg.termOffset) + 1)
- prg.fileOffset = byte(int32(prg.fileOffset) + 1)
- if int32(prg.termOffset) == maxPrintLine {
- prg.termOut.Writeln()
- prg.termOffset = 0
- }
- if int32(prg.fileOffset) == maxPrintLine {
- prg.logFile.Writeln()
- prg.fileOffset = 0
- }
- case logOnly:
- prg.logFile.Write(string(rune(prg.xchr[s])))
- prg.fileOffset = byte(int32(prg.fileOffset) + 1)
- if int32(prg.fileOffset) == maxPrintLine {
- prg.printLn()
- }
- case termOnly:
- prg.termOut.Write(string(rune(prg.xchr[s])))
- prg.termOffset = byte(int32(prg.termOffset) + 1)
- if int32(prg.termOffset) == maxPrintLine {
- prg.printLn()
- }
- case noPrint:
- case pseudo:
- if prg.tally < prg.trickCount {
- prg.trickBuf[prg.tally%errorLine] = s
- }
- case newString:
- if int32(prg.poolPtr) < poolSize {
- prg.strPool[prg.poolPtr] = s
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- // we drop characters if the string space is full
- default:
- prg.writeFile[prg.selector].Write(string(rune(prg.xchr[s])))
- }
- prg.tally = prg.tally + 1
- exit:
- }
- func (prg *prg) print(s int32) {
- var (
- j poolPointer // current character code position
- nl int32 // new-line character to restore
- )
- if s >= int32(prg.strPtr) {
- s = /* "???" */ 259
- } else if s < 256 {
- if s < 0 {
- s = /* "???" */ 259
- } else {
- if int32(prg.selector) > pseudo {
- prg.printChar(asciiCode(s))
- goto exit // internal strings are not expanded
- }
- if s == *prg.eqtb[intBase+newLineCharCode-1].int() {
- if int32(prg.selector) < pseudo {
- prg.printLn()
- goto exit
- }
- }
- nl = *prg.eqtb[intBase+newLineCharCode-1].int()
- *prg.eqtb[intBase+newLineCharCode-1].int() = -1
- // temporarily disable new-line character
- j = prg.strStart[s]
- for int32(j) < int32(prg.strStart[s+1]) {
- prg.printChar(prg.strPool[j])
- j = uint16(int32(j) + 1)
- }
- *prg.eqtb[intBase+newLineCharCode-1].int() = nl
- goto exit
- }
- }
- j = prg.strStart[s]
- for int32(j) < int32(prg.strStart[s+1]) {
- prg.printChar(prg.strPool[j])
- j = uint16(int32(j) + 1)
- }
- exit:
- }
- func (prg *prg) slowPrint(s int32) { // prints string |s|
- var (
- j poolPointer // current character code position
- )
- if s >= int32(prg.strPtr) || s < 256 {
- prg.print(s)
- } else {
- j = prg.strStart[s]
- for int32(j) < int32(prg.strStart[s+1]) {
- prg.print(int32(prg.strPool[j]))
- j = uint16(int32(j) + 1)
- }
- }
- }
- func (prg *prg) printNl(s strNumber) {
- if int32(prg.termOffset) > 0 && prg.selector&1 != 0 || int32(prg.fileOffset) > 0 && int32(prg.selector) >= logOnly {
- prg.printLn()
- }
- prg.print(int32(s))
- }
- func (prg *prg) printEsc(s strNumber) { // prints escape character, then |s|
- var (
- c int32 // the escape character code
- )
- c = *prg.eqtb[intBase+escapeCharCode-1].int()
- if c >= 0 {
- if c < 256 {
- prg.print(c)
- }
- }
- prg.slowPrint(int32(s))
- }
- func (prg *prg) printTheDigs(k eightBits) {
- for int32(k) > 0 {
- k = byte(int32(k) - 1)
- if int32(prg.dig[k]) < 10 {
- prg.printChar(asciiCode('0' + int32(prg.dig[k])))
- } else {
- prg.printChar(asciiCode('A' - 10 + int32(prg.dig[k])))
- }
- }
- }
- func (prg *prg) printInt(n int32) { // prints an integer in decimal form
- var (
- k/* 0..23 */ byte // index to current digit; we assume that $\vert n\vert<10^[23]$
- m int32 // used to negate |n| in possibly dangerous cases
- )
- k = 0
- if n < 0 {
- prg.printChar(asciiCode('-'))
- if n > -100000000 {
- n = -n
- } else {
- m = -1 - n
- n = m / 10
- m = m%10 + 1
- k = 1
- if m < 10 {
- prg.dig[0] = byte(m)
- } else {
- prg.dig[0] = 0
- n = n + 1
- }
- }
- }
- for {
- prg.dig[k] = byte(n % 10)
- n = n / 10
- k = byte(int32(k) + 1)
- if n == 0 {
- break
- }
- }
- prg.printTheDigs(k)
- }
- func (prg *prg) printCs(p int32) {
- if p < hashBase {
- if p >= singleBase {
- if p == nullCs {
- prg.printEsc(strNumber( /* "csname" */ 504))
- prg.printEsc(strNumber( /* "endcsname" */ 505))
- prg.printChar(asciiCode(' '))
- } else {
- prg.printEsc(strNumber(p - singleBase))
- if int32(*(*prg.eqtb[catCodeBase+p-singleBase-1].hh()).rh()) == letter {
- prg.printChar(asciiCode(' '))
- }
- }
- } else if p < activeBase {
- prg.printEsc(strNumber( /* "IMPOSSIBLE." */ 506))
- } else {
- prg.print(p - activeBase)
- }
- } else if p >= undefinedControlSequence {
- prg.printEsc(strNumber( /* "IMPOSSIBLE." */ 506))
- } else if int32(*prg.hash[p-514].rh()) < 0 || int32(*prg.hash[p-514].rh()) >= int32(prg.strPtr) {
- prg.printEsc(strNumber( /* "NONEXISTENT." */ 507))
- } else {
- prg.printEsc(*prg.hash[p-514].rh())
- prg.printChar(asciiCode(' '))
- }
- }
- func (prg *prg) sprintCs(p halfword) {
- if int32(p) < hashBase {
- if int32(p) < singleBase {
- prg.print(int32(p) - activeBase)
- } else if int32(p) < nullCs {
- prg.printEsc(strNumber(int32(p) - singleBase))
- } else {
- prg.printEsc(strNumber( /* "csname" */ 504))
- prg.printEsc(strNumber( /* "endcsname" */ 505))
- }
- } else {
- prg.printEsc(*prg.hash[p-514].rh())
- }
- }
- func (prg *prg) printFileName(n, a, e int32) {
- prg.slowPrint(a)
- prg.slowPrint(n)
- prg.slowPrint(e)
- }
- func (prg *prg) printSize(s int32) {
- if s == textSize {
- prg.printEsc(strNumber( /* "textfont" */ 412))
- } else if s == scriptSize {
- prg.printEsc(strNumber( /* "scriptfont" */ 413))
- } else {
- prg.printEsc(strNumber( /* "scriptscriptfont" */ 414))
- }
- }
- func (prg *prg) printWriteWhatsit(s strNumber, p halfword) {
- prg.printEsc(s)
- if int32(*(*prg.mem[int32(p)+1].hh()).lh()) < 16 {
- prg.printInt(int32(*(*prg.mem[int32(p)+1].hh()).lh()))
- } else if int32(*(*prg.mem[int32(p)+1].hh()).lh()) == 16 {
- prg.printChar(asciiCode('*'))
- } else {
- prg.printChar(asciiCode('-'))
- }
- } // \2
- // \4\hskip-\fontdimen2\font
- // procedure debug_help;
- // forward; [ ]
- func (prg *prg) jumpOut() {
- panic(signal(endOfTex))
- }
- func (prg *prg) error1() {
- var (
- c asciiCode // what the user types
- s1, s2, s3, s4 int32
- // used to save global variables when deleting tokens
- )
- if int32(prg.history) < errorMessageIssued {
- prg.history = byte(errorMessageIssued)
- }
- prg.printChar(asciiCode('.'))
- prg.showContext()
- if int32(prg.interaction) == errorStopMode {
- for true {
- continue1:
- if int32(prg.interaction) != errorStopMode {
- goto exit
- }
- prg.clearForErrorPrompt()
- {
- prg.print( /* "? " */ 264)
- prg.termInput()
- }
- // \xref[?\relax]
- if int32(prg.last) == int32(prg.first) {
- goto exit
- }
- c = prg.buffer[prg.first]
- if int32(c) >= 'a' {
- c = byte(int32(c) + 'A' - 'a')
- } // convert to uppercase
- // Interpret code |c| and |return| if done
- switch c {
- case '0', '1', '2', '3',
- '4', '5', '6', '7',
- '8', '9':
- if prg.deletionsAllowed {
- s1 = int32(prg.curTok)
- s2 = int32(prg.curCmd)
- s3 = int32(prg.curChr)
- s4 = prg.alignState
- prg.alignState = 1000000
- prg.okToInterrupt = false
- if int32(prg.last) > int32(prg.first)+1 && int32(prg.buffer[int32(prg.first)+1]) >= '0' && int32(prg.buffer[int32(prg.first)+1]) <= '9' {
- c = byte(int32(c)*10 + int32(prg.buffer[int32(prg.first)+1]) - '0'*11)
- } else {
- c = byte(int32(c) - '0')
- }
- for int32(c) > 0 {
- prg.getToken() // one-level recursive call of |error| is possible
- c = byte(int32(c) - 1)
- }
- prg.curTok = uint16(s1)
- prg.curCmd = byte(s2)
- prg.curChr = uint16(s3)
- prg.alignState = s4
- prg.okToInterrupt = true
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I have just deleted some text, as you asked." */ 279
- prg.helpLine[0] = /* "You can now delete more, or insert, or whatever." */ 280
- }
- prg.showContext()
- goto continue1
- }
- // \4\4
- // ["D"=]68: begin debug_help; goto continue; end; [ ]
- // "E"=
- case 'E':
- if int32(prg.basePtr) > 0 {
- if int32(prg.inputStack[prg.basePtr].nameField) >= 256 {
- prg.printNl(strNumber( /* "You want to edit file " */ 265))
- // \xref[You want to edit file x]
- prg.slowPrint(int32(prg.inputStack[prg.basePtr].nameField))
- prg.print( /* " at line " */ 266)
- prg.printInt(prg.line)
- prg.interaction = byte(scrollMode)
- prg.jumpOut()
- }
- }
- // "H"=
- case 'H':
- // Print the help information and |goto continue|
- if prg.useErrHelp {
- prg.giveErrHelp()
- prg.useErrHelp = false
- } else {
- if int32(prg.helpPtr) == 0 {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Sorry, I don't know how to help in this situation." */ 281
- prg.helpLine[0] = /* "Maybe you should try asking a human?" */ 282
- }
- for {
- prg.helpPtr = byte(int32(prg.helpPtr) - 1)
- prg.print(int32(prg.helpLine[prg.helpPtr]))
- prg.printLn()
- if int32(prg.helpPtr) == 0 {
- break
- }
- }
- }
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "Sorry, I already gave what help I could..." */ 283
- prg.helpLine[2] = /* "Maybe you should try asking a human?" */ 282
- prg.helpLine[1] = /* "An error might have occurred before I noticed any problems." */ 284
- prg.helpLine[0] = /* "``If all else fails, read the instructions.''" */ 285
- }
- goto continue1
- // "I"=
- case 'I':
- // Introduce new material from the terminal and |return|
- prg.beginFileReading() // enter a new syntactic level for terminal input
- // now |state=mid_line|, so an initial blank space will count as a blank
- if int32(prg.last) > int32(prg.first)+1 {
- prg.curInput.locField = uint16(int32(prg.first) + 1)
- prg.buffer[prg.first] = ' '
- } else {
- {
- prg.print( /* "insert>" */ 278)
- prg.termInput()
- }
- prg.curInput.locField = prg.first
- // \xref[insert>]
- }
- prg.first = prg.last
- prg.curInput.limitField = uint16(int32(prg.last) - 1) // no |end_line_char| ends this line
- // no |end_line_char| ends this line
- goto exit
- // "Q"=
- case 'Q', 'R', 'S':
- // Change the interaction level and |return|
- prg.errorCount = 0
- prg.interaction = byte(batchMode + int32(c) - 'Q')
- prg.print( /* "OK, entering " */ 273)
- switch c {
- case 'Q':
- prg.printEsc(strNumber( /* "batchmode" */ 274))
- prg.selector = byte(int32(prg.selector) - 1)
- // "R"=
- case 'R':
- prg.printEsc(strNumber( /* "nonstopmode" */ 275))
- // "S"=
- case 'S':
- prg.printEsc(strNumber( /* "scrollmode" */ 276))
- } // there are no other cases
- prg.print( /* "..." */ 277)
- prg.printLn()
- goto exit
- // "X"=
- case 'X':
- prg.interaction = byte(scrollMode)
- prg.jumpOut()
- default:
- }
- // Print the menu of available options
- {
- prg.print( /* "Type <return> to proceed, S to scroll future error messages," */ 267)
- // \xref[Type <return> to proceed...]
- prg.printNl(strNumber( /* "R to run without stopping, Q to run quietly," */ 268))
- prg.printNl(strNumber( /* "I to insert something, " */ 269))
- if int32(prg.basePtr) > 0 {
- if int32(prg.inputStack[prg.basePtr].nameField) >= 256 {
- prg.print( /* "E to edit your file," */ 270)
- }
- }
- if prg.deletionsAllowed {
- prg.printNl(strNumber( /* "1 or ... or 9 to ignore the next 1 to 9 tokens of input," */ 271))
- }
- prg.printNl(strNumber( /* "H for help, X to quit." */ 272))
- }
- }
- }
- prg.errorCount = int8(int32(prg.errorCount) + 1)
- if int32(prg.errorCount) == 100 {
- prg.printNl(strNumber( /* "(That makes 100 errors; please try again.)" */ 263))
- // \xref[That makes 100 errors...]
- prg.history = byte(fatalErrorStop)
- prg.jumpOut()
- }
- // Put help message on the transcript file
- if int32(prg.interaction) > batchMode {
- prg.selector = byte(int32(prg.selector) - 1)
- } // avoid terminal output
- if prg.useErrHelp {
- prg.printLn()
- prg.giveErrHelp()
- } else {
- for int32(prg.helpPtr) > 0 {
- prg.helpPtr = byte(int32(prg.helpPtr) - 1)
- prg.printNl(prg.helpLine[prg.helpPtr])
- }
- }
- prg.printLn()
- if int32(prg.interaction) > batchMode {
- prg.selector = byte(int32(prg.selector) + 1)
- } // re-enable terminal output
- prg.printLn()
- exit:
- }
- func (prg *prg) fatalError(s strNumber) {
- prg.normalizeSelector()
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Emergency stop" */ 287)
- }
- {
- prg.helpPtr = 1
- prg.helpLine[0] = s
- }
- {
- if int32(prg.interaction) == errorStopMode {
- prg.interaction = byte(scrollMode)
- }
- if prg.logOpened {
- prg.error1()
- } /* if interaction>batch_mode then debug_help; [ ] */
- prg.history = byte(fatalErrorStop)
- prg.jumpOut()
- }
- // \xref[Emergency stop]
- }
- func (prg *prg) overflow(s strNumber, n int32) {
- prg.normalizeSelector()
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "TeX capacity exceeded, sorry [" */ 288)
- }
- // \xref[TeX capacity exceeded ...]
- prg.print(int32(s))
- prg.printChar(asciiCode('='))
- prg.printInt(n)
- prg.printChar(asciiCode(']'))
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "If you really absolutely need more capacity," */ 289
- prg.helpLine[0] = /* "you can ask a wizard to enlarge me." */ 290
- }
- {
- if int32(prg.interaction) == errorStopMode {
- prg.interaction = byte(scrollMode)
- }
- if prg.logOpened {
- prg.error1()
- } /* if interaction>batch_mode then debug_help; [ ] */
- prg.history = byte(fatalErrorStop)
- prg.jumpOut()
- }
- }
- func (prg *prg) confusion(s strNumber) {
- prg.normalizeSelector()
- if int32(prg.history) < errorMessageIssued {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "This can't happen (" */ 291)
- }
- prg.print(int32(s))
- prg.printChar(asciiCode(')'))
- // \xref[This can't happen]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm broken. Please show this to someone who can fix can fix" */ 292
- }
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "I can't go on meeting you like this" */ 293)
- }
- // \xref[I can't go on...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "One of your faux pas seems to have wounded me deeply..." */ 294
- prg.helpLine[0] = /* "in fact, I'm barely conscious. Please fix it and try again." */ 295
- }
- }
- {
- if int32(prg.interaction) == errorStopMode {
- prg.interaction = byte(scrollMode)
- }
- if prg.logOpened {
- prg.error1()
- } /* if interaction>batch_mode then debug_help; [ ] */
- prg.history = byte(fatalErrorStop)
- prg.jumpOut()
- }
- }
- // 5.
- // tangle:pos tex.web:268:3:
- // The overall \TeX\ program begins with the heading just shown, after which
- // comes a bunch of procedure declarations and function declarations.
- // Finally we will get to the main program, which begins with the
- // comment `|start_here|'. If you want to skip down to the
- // main program now, you can look up `|start_here|' in the index.
- // But the author suggests that the best way to understand this program
- // is to follow pretty much the order of \TeX's components as they appear in the
- // \.[WEB] description you are now reading, since the present ordering is
- // intended to combine the advantages of the ``bottom up'' and ``top down''
- // approaches to the problem of understanding a somewhat complicated system.
- // 7.
- // tangle:pos tex.web:290:3:
- // Some of the code below is intended to be used only when diagnosing the
- // strange behavior that sometimes occurs when \TeX\ is being installed or
- // when system wizards are fooling around with \TeX\ without quite knowing
- // what they are doing. Such code will not normally be compiled; it is
- // delimited by the codewords `$|debug|\ldots|gubed|$', with apologies
- // to people who wish to preserve the purity of English.
- //
- // Similarly, there is some conditional code delimited by
- // `$|stat|\ldots|tats|$' that is intended for use when statistics are to be
- // kept about \TeX's memory usage. The |stat| $\ldots$ |tats| code also
- // implements diagnostic information for \.[\\tracingparagraphs],
- // \.[\\tracingpages], and \.[\\tracingrestores].
- // \xref[debugging]
- // 10.
- // tangle:pos tex.web:348:3:
- // This \TeX\ implementation conforms to the rules of the [\sl Pascal User
- // \xref[PASCAL][\PASCAL]
- // \xref[system dependencies]
- // Manual] published by Jensen and Wirth in 1975, except where system-dependent
- // \xref[Wirth, Niklaus]
- // \xref[Jensen, Kathleen]
- // code is necessary to make a useful system program, and except in another
- // respect where such conformity would unnecessarily obscure the meaning
- // and clutter up the code: We assume that |case| statements may include a
- // default case that applies if no matching label is found. Thus, we shall use
- // constructions like
- // $$\vbox[\halign[\ignorespaces#\hfil\cr
- // |case x of|\cr
- // 1: $\langle\,$code for $x=1\,\rangle$;\cr
- // 3: $\langle\,$code for $x=3\,\rangle$;\cr
- // |othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
- // |endcases|\cr]]$$
- // since most \PASCAL\ compilers have plugged this hole in the language by
- // incorporating some sort of default mechanism. For example, the \ph\
- // compiler allows `|others|:' as a default label, and other \PASCAL s allow
- // syntaxes like `\&[else]' or `\&[otherwise]' or `\\[otherwise]:', etc. The
- // definitions of |othercases| and |endcases| should be changed to agree with
- // local conventions. Note that no semicolon appears before |endcases| in
- // this program, so the definition of |endcases| should include a semicolon
- // if the compiler wants one. (Of course, if no default mechanism is
- // available, the |case| statements of \TeX\ will have to be laboriously
- // extended by listing all remaining cases. People who are stuck with such
- // \PASCAL s have, in fact, done this, successfully but not happily!)
- // \xref[PASCAL H][\ph]
- // 12.
- // tangle:pos tex.web:430:3:
- // Like the preceding parameters, the following quantities can be changed
- // at compile time to extend or reduce \TeX's capacity. But if they are changed,
- // it is necessary to rerun the initialization program \.[INITEX]
- // \xref[INITEX]
- // to generate new tables for the production \TeX\ program.
- // One can't simply make helter-skelter changes to the following constants,
- // since certain rather complex initialization
- // numbers are computed from them. They are defined here using
- // \.[WEB] macros, instead of being put into \PASCAL's |const| list, in order to
- // emphasize this distinction.
- // 15.
- // tangle:pos tex.web:476:3:
- // Labels are given symbolic names by the following definitions, so that
- // occasional |goto| statements will be meaningful. We insert the label
- // `|exit|' just before the `\ignorespaces|end|\unskip' of a procedure in
- // which we have used the `|return|' statement defined below; the label
- // `|restart|' is occasionally used at the very beginning of a procedure; and
- // the label `|reswitch|' is occasionally used just prior to a |case|
- // statement in which some cases change the conditions and we wish to branch
- // to the newly applicable case. Loops that are set up with the |loop|
- // construction defined below are commonly exited by going to `|done|' or to
- // `|found|' or to `|not_found|', and they are sometimes repeated by going to
- // `|continue|'. If two or more parts of a subroutine start differently but
- // end up the same, the shared code may be gathered together at
- // `|common_ending|'.
- //
- // Incidentally, this program never declares a label that isn't actually used,
- // because some fussy \PASCAL\ compilers will complain about redundant labels.
- // 16.
- // tangle:pos tex.web:510:3:
- // Here are some macros for common programming idioms.
- // 17. \[2] The character set
- // tangle:pos tex.web:523:27:
- // In order to make \TeX\ readily portable to a wide variety of
- // computers, all of its input text is converted to an internal eight-bit
- // code that includes standard ASCII, the ``American Standard Code for
- // Information Interchange.'' This conversion is done immediately when each
- // character is read in. Conversely, characters are converted from ASCII to
- // the user's external representation just before they are output to a
- // text file.
- //
- // Such an internal code is relevant to users of \TeX\ primarily because it
- // governs the positions of characters in the fonts. For example, the
- // character `\.A' has ASCII code $65=@'101$, and when \TeX\ typesets
- // this letter it specifies character number 65 in the current font.
- // If that font actually has `\.A' in a different position, \TeX\ doesn't
- // know what the real position is; the program that does the actual printing from
- // \TeX's device-independent files is responsible for converting from ASCII to
- // a particular font encoding.
- // \xref[ASCII code]
- //
- // \TeX's internal code also defines the value of constants
- // that begin with a reverse apostrophe; and it provides an index to the
- // \.[\\catcode], \.[\\mathcode], \.[\\uccode], \.[\\lccode], and \.[\\delcode]
- // tables.
- // 22.
- // tangle:pos tex.web:702:3:
- // Some of the ASCII codes without visible characters have been given symbolic
- // names in this program because they are used with a special meaning.
- // 27.
- // tangle:pos tex.web:808:3:
- // The \ph\ compiler with which the present version of \TeX\ was prepared has
- // extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
- // we can write
- // $$\vbox[\halign[#\hfil\qquad&#\hfil\cr
- // |reset(f,\\[name],'/O')|&for input;\cr
- // |rewrite(f,\\[name],'/O')|&for output.\cr]]$$
- // The `\\[name]' parameter, which is of type `[\bf packed array
- // $[\langle\\[any]\rangle]$ of \\[char]]', stands for the name of
- // the external file that is being opened for input or output.
- // Blank spaces that might appear in \\[name] are ignored.
- //
- // The `\.[/O]' parameter tells the operating system not to issue its own
- // error messages if something goes wrong. If a file of the specified name
- // cannot be found, or if such a file cannot be opened for some other reason
- // (e.g., someone may already be trying to write the same file), we will have
- // | erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows
- // \TeX\ to undertake appropriate corrective action.
- // \xref[PASCAL H][\ph]
- // \xref[system dependencies]
- //
- // \TeX's file-opening procedures return |false| if no file identified by
- // |name_of_file| could be opened.
- func (prg *prg) aOpenIn(f alphaFile) (r bool) {
- f.Reset(arraystr(prg.nameOfFile[:]), "/O")
- r = f.ErStat() == 0
- return r
- }
- func (prg *prg) aOpenOut(f alphaFile) (r bool) {
- f.Rewrite(arraystr(prg.nameOfFile[:]), "/O")
- r = f.ErStat() == 0
- return r
- }
- func (prg *prg) bOpenIn(f byteFile) (r bool) {
- f.Reset(arraystr(prg.nameOfFile[:]), "/O")
- r = f.ErStat() == 0
- return r
- }
- func (prg *prg) bOpenOut(f byteFile) (r bool) {
- f.Rewrite(arraystr(prg.nameOfFile[:]), "/O")
- r = f.ErStat() == 0
- return r
- }
- func (prg *prg) wOpenIn(f wordFile) (r bool) {
- f.Reset(arraystr(prg.nameOfFile[:]), "/O")
- r = f.ErStat() == 0
- return r
- }
- func (prg *prg) wOpenOut(f wordFile) (r bool) {
- f.Rewrite(arraystr(prg.nameOfFile[:]), "/O")
- r = f.ErStat() == 0
- return r
- }
- // 28.
- // tangle:pos tex.web:864:3:
- // Files can be closed with the \ph\ routine `|close(f)|', which
- // \xref[PASCAL H][\ph]
- // \xref[system dependencies]
- // should be used when all input or output with respect to |f| has been completed.
- // This makes |f| available to be opened again, if desired; and if |f| was used for
- // output, the |close| operation makes the corresponding external file appear
- // on the user's area, ready to be read.
- //
- // These procedures should not generate error messages if a file is
- // being closed before it has been successfully opened.
- func (prg *prg) aClose(f alphaFile) {
- f.Close()
- }
- func (prg *prg) bClose(f byteFile) {
- f.Close()
- }
- func (prg *prg) wClose(f wordFile) {
- f.Close()
- }
- // 29.
- // tangle:pos tex.web:887:3:
- // Binary input and output are done with \PASCAL's ordinary |get| and |put|
- // procedures, so we don't have to make any other special arrangements for
- // binary~I/O. Text output is also easy to do with standard \PASCAL\ routines.
- // The treatment of text input is more difficult, however, because
- // of the necessary translation to |ASCII_code| values.
- // \TeX's conventions should be efficient, and they should
- // blend nicely with the user's operating environment.
- // 31.
- // tangle:pos tex.web:908:3:
- // The |input_ln| function brings the next line of input from the specified
- // file into available positions of the buffer array and returns the value
- // |true|, unless the file has already been entirely read, in which case it
- // returns |false| and sets |last:=first|. In general, the |ASCII_code|
- // numbers that represent the next line of the file are input into
- // |buffer[first]|, |buffer[first+1]|, \dots, |buffer[last-1]|; and the
- // global variable |last| is set equal to |first| plus the length of the
- // line. Trailing blanks are removed from the line; thus, either |last=first|
- // (in which case the line was entirely blank) or |buffer[last-1]<>" "|.
- //
- // An overflow error is given, however, if the normal actions of |input_ln|
- // would make |last>=buf_size|; this is done so that other parts of \TeX\
- // can safely look at the contents of |buffer[last+1]| without overstepping
- // the bounds of the |buffer| array. Upon entry to |input_ln|, the condition
- // |first<buf_size| will always hold, so that there is always room for an
- // “empty” line.
- //
- // The variable |max_buf_stack|, which is used to keep track of how large
- // the |buf_size| parameter must be to accommodate the present job, is
- // also kept up to date by |input_ln|.
- //
- // If the |bypass_eoln| parameter is |true|, |input_ln| will do a |get|
- // before looking at the first character of the line; this skips over
- // an |eoln| that was in |f^|. The procedure does not do a |get| when it
- // reaches the end of the line; therefore it can be used to acquire input
- // from the user's terminal as well as from ordinary text files.
- //
- // Standard \PASCAL\ says that a file should have |eoln| immediately
- // before |eof|, but \TeX\ needs only a weaker restriction: If |eof|
- // occurs in the middle of a line, the system function |eoln| should return
- // a |true| result (even though |f^| will be undefined).
- //
- // Since the inner loop of |input_ln| is part of \TeX's “inner loop”---each
- // character of input comes in at this place---it is wise to reduce system
- // overhead by making use of special routines that read in an entire array
- // of characters at once, if such routines are available. The following
- // code uses standard \PASCAL\ to illustrate what needs to be done, but
- // finer tuning is often possible at well-developed \PASCAL\ sites.
- // \xref[inner loop]
- func (prg *prg) inputLn(f alphaFile, bypassEoln bool) (r bool) {
- // inputs the next line or returns |false|
- var (
- lastNonblank /* 0..bufSize */ uint16 // |last| with trailing blanks removed
- )
- if bypassEoln {
- if !f.EOF() && f.EOLN() {
- f.Get()
- }
- }
- // input the first character of the line into |f^|
- prg.last = prg.first // cf.\ Matthew 19\thinspace:\thinspace30
- if f.EOF() {
- r = false
- } else {
- lastNonblank = prg.first
- for !f.EOLN() {
- if int32(prg.last) >= int32(prg.maxBufStack) {
- prg.maxBufStack = uint16(int32(prg.last) + 1)
- if int32(prg.maxBufStack) == bufSize {
- if int32(prg.formatIdent) == 0 {
- prg.termOut.Writeln("Buffer size exceeded!")
- panic(signal(finalEnd))
- // \xref[Buffer size exceeded]
- } else {
- prg.curInput.locField = prg.first
- prg.curInput.limitField = uint16(int32(prg.last) - 1)
- prg.overflow(strNumber( /* "buffer size" */ 256), bufSize)
- // \xref[TeX capacity exceeded buffer size][\quad buffer size]
- }
- }
- }
- prg.buffer[prg.last] = prg.xord[*f.ByteP()]
- f.Get()
- prg.last = uint16(int32(prg.last) + 1)
- if int32(prg.buffer[int32(prg.last)-1]) != ' ' {
- lastNonblank = prg.last
- }
- }
- prg.last = lastNonblank
- r = true
- }
- return r
- }
- // 33.
- // tangle:pos tex.web:979:3:
- // Here is how to open the terminal files
- // in \ph. The `\.[/I]' switch suppresses the first |get|.
- // \xref[PASCAL H][\ph]
- // \xref[system dependencies]
- // 34.
- // tangle:pos tex.web:987:3:
- // Sometimes it is necessary to synchronize the input/output mixture that
- // happens on the user's terminal, and three system-dependent
- // procedures are used for this
- // purpose. The first of these, |update_terminal|, is called when we want
- // to make sure that everything we have output to the terminal so far has
- // actually left the computer's internal buffers and been sent.
- // The second, |clear_terminal|, is called when we wish to cancel any
- // input that the user may have typed ahead (since we are about to
- // issue an unexpected error message). The third, |wake_up_terminal|,
- // is supposed to revive the terminal if the user has disabled it by
- // some instruction to the operating system. The following macros show how
- // these operations can be specified in \ph:
- // \xref[PASCAL H][\ph]
- // \xref[system dependencies]
- // 36.
- // tangle:pos tex.web:1044:3:
- // Different systems have different ways to get started. But regardless of
- // what conventions are adopted, the routine that initializes the terminal
- // should satisfy the following specifications:
- //
- // \yskip\textindent[1)]It should open file |term_in| for input from the
- // terminal. (The file |term_out| will already be open for output to the
- // terminal.)
- //
- // \textindent[2)]If the user has given a command line, this line should be
- // considered the first line of terminal input. Otherwise the
- // user should be prompted with `\.[**]', and the first line of input
- // should be whatever is typed in response.
- //
- // \textindent[3)]The first line of input, which might or might not be a
- // command line, should appear in locations |first| to |last-1| of the
- // |buffer| array.
- //
- // \textindent[4)]The global variable |loc| should be set so that the
- // character to be read next by \TeX\ is in |buffer[loc]|. This
- // character should not be blank, and we should have |loc<last|.
- //
- // \yskip\noindent(It may be necessary to prompt the user several times
- // before a non-blank line comes in. The prompt is `\.[**]' instead of the
- // later `\.*' because the meaning is slightly different: `\.[\\input]' need
- // not be typed immediately after~`\.[**]'.)
- // 37.
- // tangle:pos tex.web:1072:3:
- // The following program does the required initialization
- // without retrieving a possible command line.
- // It should be clear how to modify this routine to deal with command lines,
- // if the system permits them.
- // \xref[system dependencies]
- func (prg *prg) initTerminal() (r bool) {
- prg.termIn.Reset("TTY:", "/O/I")
- for true {
- prg.termOut.Write("**")
- // \xref[**]
- if !prg.inputLn(prg.termIn, true) {
- prg.termOut.Writeln()
- prg.termOut.Writeln("! End of file on the terminal... why?")
- // \xref[End of file on the terminal]
- r = false
- goto exit
- }
- prg.curInput.locField = prg.first
- for int32(prg.curInput.locField) < int32(prg.last) && int32(prg.buffer[prg.curInput.locField]) == ' ' {
- prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
- }
- if int32(prg.curInput.locField) < int32(prg.last) {
- r = true
- goto exit // return unless the line was all blank
- }
- prg.termOut.Writeln("Please type the name of your input file.")
- }
- exit:
- ;
- return r
- }
- // 40.
- // tangle:pos tex.web:1156:3:
- // Several of the elementary string operations are performed using \.[WEB]
- // macros instead of \PASCAL\ procedures, because many of the
- // operations are done quite frequently and we want to avoid the
- // overhead of procedure calls. For example, here is
- // a simple macro that computes the length of a string.
- // \xref[WEB]
- // 41.
- // tangle:pos tex.web:1166:3:
- // The length of the current string is called |cur_length|:
- // 42.
- // tangle:pos tex.web:1170:3:
- // Strings are created by appending character codes to |str_pool|.
- // The |append_char| macro, defined here, does not check to see if the
- // value of |pool_ptr| has gotten too high; this test is supposed to be
- // made before |append_char| is used. There is also a |flush_char|
- // macro, which erases the last character appended.
- //
- // To test if there is room to append |l| more characters to |str_pool|,
- // we shall write |str_room(l)|, which aborts \TeX\ and gives an
- // apologetic error message if there isn't enough room.
- // 43.
- // tangle:pos tex.web:1190:3:
- // Once a sequence of characters has been appended to |str_pool|, it
- // officially becomes a string when the function |make_string| is called.
- // This function returns the identification number of the new string as its
- // value.
- func (prg *prg) makeString() (r strNumber) {
- if int32(prg.strPtr) == maxStrings {
- prg.overflow(strNumber( /* "number of strings" */ 258), maxStrings-int32(prg.initStrPtr))
- }
- // \xref[TeX capacity exceeded number of strings][\quad number of strings]
- prg.strPtr = uint16(int32(prg.strPtr) + 1)
- prg.strStart[prg.strPtr] = prg.poolPtr
- r = uint16(int32(prg.strPtr) - 1)
- return r
- }
- // 44.
- // tangle:pos tex.web:1203:3:
- // To destroy the most recently made string, we say |flush_string|.
- // 45.
- // tangle:pos tex.web:1208:3:
- // The following subroutine compares string |s| with another string of the
- // same length that appears in |buffer| starting at position |k|;
- // the result is |true| if and only if the strings are equal.
- // Empirical tests indicate that |str_eq_buf| is used in such a way that
- // it tends to return |true| about 80 percent of the time.
- func (prg *prg) strEqBuf(s strNumber, k int32) (r bool) { // loop exit
- var (
- j poolPointer // running index
- result bool // result of comparison
- )
- j = prg.strStart[s]
- for int32(j) < int32(prg.strStart[int32(s)+1]) {
- if int32(prg.strPool[j]) != int32(prg.buffer[k]) {
- result = false
- goto notFound
- }
- j = uint16(int32(j) + 1)
- k = k + 1
- }
- result = true
- notFound:
- r = result
- return r
- }
- // 46.
- // tangle:pos tex.web:1230:3:
- // Here is a similar routine, but it compares two strings in the string pool,
- // and it does not assume that they have the same length.
- func (prg *prg) strEqStr(s, t strNumber) (r bool) { // loop exit
- var (
- j, k poolPointer // running indices
- result bool // result of comparison
- )
- result = false
- if int32(prg.strStart[int32(s)+1])-int32(prg.strStart[s]) != int32(prg.strStart[int32(t)+1])-int32(prg.strStart[t]) {
- goto notFound
- }
- j = prg.strStart[s]
- k = prg.strStart[t]
- for int32(j) < int32(prg.strStart[int32(s)+1]) {
- if int32(prg.strPool[j]) != int32(prg.strPool[k]) {
- goto notFound
- }
- j = uint16(int32(j) + 1)
- k = uint16(int32(k) + 1)
- }
- result = true
- notFound:
- r = result
- return r
- }
- // 47.
- // tangle:pos tex.web:1249:3:
- // The initial values of |str_pool|, |str_start|, |pool_ptr|,
- // and |str_ptr| are computed by the \.[INITEX] program, based in part
- // on the information that \.[WEB] has output while processing \TeX.
- // \xref[INITEX]
- // \xref[string pool]
- func (prg *prg) getStringsStarted() (r bool) {
- var (
- k, l/* 0..255 */ byte // small indices or counters
- m, n char // characters input from |pool_file|
- g strNumber // garbage
- a int32 // accumulator for check sum
- c bool // check sum has been checked
- )
- if int32(g) == 0 {
- }
- prg.poolPtr = 0
- prg.strPtr = 0
- prg.strStart[0] = 0
- // Make the first 256 strings
- for ii := int32(0); ii <= 255; ii++ {
- k = byte(ii)
- _ = k
- if int32(k) < ' ' || int32(k) > '~' {
- {
- prg.strPool[prg.poolPtr] = '^'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- {
- prg.strPool[prg.poolPtr] = '^'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- if int32(k) < 0100 {
- prg.strPool[prg.poolPtr] = byte(int32(k) + 0100)
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- } else if int32(k) < 0200 {
- prg.strPool[prg.poolPtr] = byte(int32(k) - 0100)
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- } else {
- l = byte(int32(k) / 16)
- if int32(l) < 10 {
- prg.strPool[prg.poolPtr] = byte(int32(l) + '0')
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- } else {
- prg.strPool[prg.poolPtr] = byte(int32(l) - 10 + 'a')
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- l = byte(int32(k) % 16)
- if int32(l) < 10 {
- prg.strPool[prg.poolPtr] = byte(int32(l) + '0')
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- } else {
- prg.strPool[prg.poolPtr] = byte(int32(l) - 10 + 'a')
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- }
- } else {
- prg.strPool[prg.poolPtr] = k
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- g = prg.makeString()
- }
- // Read the other strings from the \.[TEX.POOL] file and return |true|, or give an error message and return |false|
- strcopy(prg.nameOfFile[:], "TeXformats:TEX.POOL ") // we needn't set |name_length|
- if prg.aOpenIn(prg.poolFile) {
- c = false
- for {
- // Read one string, but return |false| if the string memory space is getting too tight for comfort
- {
- if prg.poolFile.EOF() {
- prg.termOut.Writeln("! TEX.POOL has no check sum.")
- prg.aClose(prg.poolFile)
- r = false
- goto exit
- }
- // \xref[TEX.POOL has no check sum]
- prg.poolFile.Read(&m, &n) // read two digits of string length
- if int32(m) == '*' {
- a = 0
- k = 1
- for true {
- if int32(prg.xord[n]) < '0' || int32(prg.xord[n]) > '9' {
- prg.termOut.Writeln("! TEX.POOL check sum doesn't have nine digits.")
- prg.aClose(prg.poolFile)
- r = false
- goto exit
- }
- // \xref[TEX.POOL check sum...]
- a = 10*a + int32(prg.xord[n]) - '0'
- if int32(k) == 9 {
- goto done
- }
- k = byte(int32(k) + 1)
- prg.poolFile.Read(&n)
- }
- done:
- if a != 504454778 {
- prg.termOut.Writeln("! TEX.POOL doesn't match; TANGLE me again.")
- prg.aClose(prg.poolFile)
- r = false
- goto exit
- }
- // \xref[TEX.POOL doesn't match]
- c = true
- } else {
- if int32(prg.xord[m]) < '0' || int32(prg.xord[m]) > '9' || int32(prg.xord[n]) < '0' || int32(prg.xord[n]) > '9' {
- prg.termOut.Writeln("! TEX.POOL line doesn't begin with two digits.")
- prg.aClose(prg.poolFile)
- r = false
- goto exit
- }
- // \xref[TEX.POOL line doesn't...]
- l = byte(int32(prg.xord[m])*10 + int32(prg.xord[n]) - '0'*11) // compute the length
- if int32(prg.poolPtr)+int32(l)+stringVacancies > poolSize {
- prg.termOut.Writeln("! You have to increase POOLSIZE.")
- prg.aClose(prg.poolFile)
- r = false
- goto exit
- }
- // \xref[You have to increase POOLSIZE]
- for ii := int32(1); ii <= int32(l); ii++ {
- k = byte(ii)
- _ = k
- if prg.poolFile.EOLN() {
- m = ' '
- } else {
- prg.poolFile.Read(&m)
- }
- {
- prg.strPool[prg.poolPtr] = prg.xord[m]
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- }
- prg.poolFile.Readln()
- g = prg.makeString()
- }
- }
- if c {
- break
- }
- }
- prg.aClose(prg.poolFile)
- r = true
- } else {
- prg.termOut.Writeln("! I can't read TEX.POOL.")
- prg.aClose(prg.poolFile)
- r = false
- goto exit
- }
- exit:
- ;
- return r
- }
- // 56.
- // tangle:pos tex.web:1448:3:
- // Macro abbreviations for output to the terminal and to the log file are
- // defined here for convenience. Some systems need special conventions
- // for terminal output, and it is possible to adhere to those conventions
- // by changing |wterm|, |wterm_ln|, and |wterm_cr| in this section.
- // \xref[system dependencies]
- // 66.
- // tangle:pos tex.web:1638:3:
- // Here is a trivial procedure to print two digits; it is usually called with
- // a parameter in the range |0<=n<=99|.
- func (prg *prg) printTwo(n int32) {
- n = abs(n) % 100
- prg.printChar(asciiCode('0' + n/10))
- prg.printChar(asciiCode('0' + n%10))
- }
- // 67.
- // tangle:pos tex.web:1646:3:
- // Hexadecimal printing of nonnegative integers is accomplished by |print_hex|.
- func (prg *prg) printHex(n int32) {
- // prints a positive integer in hexadecimal form
- var (
- k /* 0..22 */ byte // index to current digit; we assume that $0\L n<16^[22]$
- )
- k = 0
- prg.printChar(asciiCode('"'))
- for {
- prg.dig[k] = byte(n % 16)
- n = n / 16
- k = byte(int32(k) + 1)
- if n == 0 {
- break
- }
- }
- prg.printTheDigs(k)
- }
- // 68.
- // tangle:pos tex.web:1657:3:
- // Old versions of \TeX\ needed a procedure called |print_ASCII| whose function
- // is now subsumed by |print|. We retain the old name here as a possible aid to
- // future software arch\ae ologists.
- // 69.
- // tangle:pos tex.web:1663:3:
- // Roman numerals are produced by the |print_roman_int| routine. Readers
- // who like puzzles might enjoy trying to figure out how this tricky code
- // works; therefore no explanation will be given. Notice that 1990 yields
- // \.[mcmxc], not \.[mxm].
- func (prg *prg) printRomanInt(n int32) {
- var (
- j, k poolPointer // mysterious indices into |str_pool|
- u, v nonnegativeInteger // mysterious numbers
- )
- j = prg.strStart[ /* "m2d5c2l5x2v5i" */ 260]
- v = 1000
- for true {
- for n >= int32(v) {
- prg.printChar(prg.strPool[j])
- n = n - int32(v)
- }
- if n <= 0 {
- goto exit
- } // nonpositive input produces no output
- k = uint16(int32(j) + 2)
- u = uint32(int32(v) / (int32(prg.strPool[int32(k)-1]) - '0'))
- if int32(prg.strPool[int32(k)-1]) == '2' {
- k = uint16(int32(k) + 2)
- u = uint32(int32(u) / (int32(prg.strPool[int32(k)-1]) - '0'))
- }
- if n+int32(u) >= int32(v) {
- prg.printChar(prg.strPool[k])
- n = n + int32(u)
- } else {
- j = uint16(int32(j) + 2)
- v = uint32(int32(v) / (int32(prg.strPool[int32(j)-1]) - '0'))
- }
- }
- exit:
- }
- // 70.
- // tangle:pos tex.web:1689:3:
- // The |print| subroutine will not print a string that is still being
- // created. The following procedure will.
- func (prg *prg) printCurrentString() { // prints a yet-unmade string
- var (
- j poolPointer // points to current character code
- )
- j = prg.strStart[prg.strPtr]
- for int32(j) < int32(prg.poolPtr) {
- prg.printChar(prg.strPool[j])
- j = uint16(int32(j) + 1)
- }
- } // \2
- func (prg *prg) termInput() { // gets a line from the terminal
- var (
- k /* 0..bufSize */ uint16 // index into |buffer|
- ) // now the user sees the prompt for sure
- if !prg.inputLn(prg.termIn, true) {
- prg.fatalError(strNumber( /* "End of file on the terminal!" */ 261))
- }
- // \xref[End of file on the terminal]
- prg.termOffset = 0 // the user's line ended with \<\rm return>
- prg.selector = byte(int32(prg.selector) - 1) // prepare to echo the input
- if int32(prg.last) != int32(prg.first) {
- for ii := int32(prg.first); ii <= int32(prg.last)-1; ii++ {
- k = uint16(ii)
- _ = k
- prg.print(int32(prg.buffer[k]))
- }
- }
- prg.printLn()
- prg.selector = byte(int32(prg.selector) + 1) // restore previous status
- }
- // 72. \[6] Reporting errors
- // tangle:pos tex.web:1721:26:
- // When something anomalous is detected, \TeX\ typically does something like this:
- // $$\vbox[\halign[#\hfil\cr
- // |print_err("Something anomalous has been detected");|\cr
- // |help3("This is the first line of my offer to help.")|\cr
- // |("This is the second line. I'm trying to")|\cr
- // |("explain the best way for you to proceed.");|\cr
- // |error;|\cr]]$$
- // A two-line help message would be given using |help2|, etc.; these informal
- // helps should use simple vocabulary that complements the words used in the
- // official error message that was printed. (Outside the U.S.A., the help
- // messages should preferably be translated into the local vernacular. Each
- // line of help is at most 60 characters long, in the present implementation,
- // so that |max_print_line| will not be exceeded.)
- //
- // The |print_err| procedure supplies a `\.!' before the official message,
- // and makes sure that the terminal is awake if a stop is going to occur.
- // The |error| procedure supplies a `\..' after the official message, then it
- // shows the location of the error; and if |interaction=error_stop_mode|,
- // it also enters into a dialog with the user, during which time the help
- // message may be printed.
- // \xref[system dependencies]
- // 91.
- // tangle:pos tex.web:2034:3:
- // A dozen or so error messages end with a parenthesized integer, so we
- // save a teeny bit of program space by declaring the following procedure:
- func (prg *prg) intError(n int32) {
- prg.print( /* " (" */ 286)
- prg.printInt(n)
- prg.printChar(asciiCode(')'))
- prg.error1()
- }
- // \4
- // Error handling procedures
- func (prg *prg) normalizeSelector() {
- if prg.logOpened {
- prg.selector = byte(termAndLog)
- } else {
- prg.selector = byte(termOnly)
- }
- if int32(prg.jobName) == 0 {
- prg.openLogFile()
- }
- if int32(prg.interaction) == batchMode {
- prg.selector = byte(int32(prg.selector) - 1)
- }
- }
- // 98.
- // tangle:pos tex.web:2124:3:
- // When an interrupt has been detected, the program goes into its
- // highest interaction level and lets the user have nearly the full flexibility of
- // the |error| routine. \TeX\ checks for interrupts only at times when it is
- // safe to do this.
- func (prg *prg) pauseForInstructions() {
- if prg.okToInterrupt {
- prg.interaction = byte(errorStopMode)
- if int32(prg.selector) == logOnly || int32(prg.selector) == noPrint {
- prg.selector = byte(int32(prg.selector) + 1)
- }
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Interruption" */ 296)
- }
- // \xref[Interruption]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "You rang?" */ 297
- prg.helpLine[1] = /* "Try to insert an instruction for me (e.g., `I\\showlists')," */ 298
- prg.helpLine[0] = /* "unless you just want to quit by typing `X'." */ 299
- }
- prg.deletionsAllowed = false
- prg.error1()
- prg.deletionsAllowed = true
- prg.interrupt = 0
- }
- }
- // 99. \[7] Arithmetic with scaled dimensions
- // tangle:pos tex.web:2144:43:
- // The principal computations performed by \TeX\ are done entirely in terms of
- // integers less than $2^[31]$ in magnitude; and divisions are done only when both
- // dividend and divisor are nonnegative. Thus, the arithmetic specified in this
- // program can be carried out in exactly the same way on a wide variety of
- // computers, including some small ones. Why? Because the arithmetic
- // calculations need to be spelled out precisely in order to guarantee that
- // \TeX\ will produce identical output on different machines. If some
- // quantities were rounded differently in different implementations, we would
- // find that line breaks and even page breaks might occur in different places.
- // Hence the arithmetic of \TeX\ has been designed with care, and systems that
- // claim to be implementations of \TeX82 should follow precisely the
- // \xref[TeX82][\TeX82]
- // calculations as they appear in the present program.
- //
- // (Actually there are three places where \TeX\ uses |div| with a possibly negative
- // numerator. These are harmless; see |div| in the index. Also if the user
- // sets the \.[\\time] or the \.[\\year] to a negative value, some diagnostic
- // information will involve negative-numerator division. The same remarks
- // apply for |mod| as well as for |div|.)
- // 100.
- // tangle:pos tex.web:2165:3:
- // Here is a routine that calculates half of an integer, using an
- // unambiguous convention with respect to signed odd numbers.
- func (prg *prg) half(x int32) (r int32) {
- if x&1 != 0 {
- r = (x + 1) / 2
- } else {
- r = x / 2
- }
- return r
- }
- // 102.
- // tangle:pos tex.web:2185:3:
- // The following function is used to create a scaled integer from a given decimal
- // fraction $(.d_0d_1\ldots d_[k-1])$, where |0<=k<=17|. The digit $d_i$ is
- // given in |dig[i]|, and the calculation produces a correctly rounded result.
- func (prg *prg) roundDecimals(k smallNumber) (r scaled) {
- // converts a decimal fraction
- var (
- a int32 // the accumulator
- )
- a = 0
- for int32(k) > 0 {
- k = byte(int32(k) - 1)
- a = (a + int32(prg.dig[k])*0400000) / 10
- }
- r = (a + 1) / 2
- return r
- }
- // 103.
- // tangle:pos tex.web:2199:3:
- // Conversely, here is a procedure analogous to |print_int|. If the output
- // of this procedure is subsequently read by \TeX\ and converted by the
- // |round_decimals| routine above, it turns out that the original value will
- // be reproduced exactly; the “simplest” such decimal number is output,
- // but there is always at least one digit following the decimal point.
- //
- // The invariant relation in the \&[repeat] loop is that a sequence of
- // decimal digits yet to be printed will yield the original number if and only if
- // they form a fraction~$f$ in the range $s-\delta\L10\cdot2^[16]f<s$.
- // We can stop if and only if $f=0$ satisfies this condition; the loop will
- // terminate before $s$ can possibly become zero.
- func (prg *prg) printScaled(s scaled) { // prints scaled real, rounded to five
- // digits
- var (
- delta scaled // amount of allowable inaccuracy
- )
- if s < 0 {
- prg.printChar(asciiCode('-'))
- s = -s // print the sign, if negative
- }
- prg.printInt(s / 0200000) // print the integer part
- prg.printChar(asciiCode('.'))
- s = 10*(s%0200000) + 5
- delta = 10
- for {
- if delta > 0200000 {
- s = s + 0100000 - 50000
- } // round the last digit
- prg.printChar(asciiCode('0' + s/0200000))
- s = 10 * (s % 0200000)
- delta = delta * 10
- if s <= delta {
- break
- }
- }
- }
- // 105.
- // tangle:pos tex.web:2254:3:
- // The first arithmetical subroutine we need computes $nx+y$, where |x|
- // and~|y| are |scaled| and |n| is an integer. We will also use it to
- // multiply integers.
- func (prg *prg) multAndAdd(n int32, x, y, maxAnswer scaled) (r scaled) {
- if n < 0 {
- x = -x
- n = -n
- }
- if n == 0 {
- r = y
- } else if x <= (maxAnswer-y)/n && -x <= (maxAnswer+y)/n {
- r = n*x + y
- } else {
- prg.arithError = true
- r = 0
- }
- return r
- }
- // 106.
- // tangle:pos tex.web:2272:3:
- // We also need to divide scaled dimensions by integers.
- func (prg *prg) xOverN(x scaled, n int32) (r scaled) {
- var (
- negative bool // should |remainder| be negated?
- )
- negative = false
- if n == 0 {
- prg.arithError = true
- r = 0
- prg.remainder = x
- } else {
- if n < 0 {
- x = -x
- n = -n
- negative = true
- }
- if x >= 0 {
- r = x / n
- prg.remainder = x % n
- } else {
- r = -(-x / n)
- prg.remainder = -(-x % n)
- }
- }
- if negative {
- prg.remainder = -prg.remainder
- }
- return r
- }
- // 107.
- // tangle:pos tex.web:2292:3:
- // Then comes the multiplication of a scaled number by a fraction |n/d|,
- // where |n| and |d| are nonnegative integers |<=$2^[16]$| and |d| is
- // positive. It would be too dangerous to multiply by~|n| and then divide
- // by~|d|, in separate operations, since overflow might well occur; and it
- // would be too inaccurate to divide by |d| and then multiply by |n|. Hence
- // this subroutine simulates 1.5-precision arithmetic.
- func (prg *prg) xnOverD(x scaled, n, d int32) (r scaled) {
- var (
- positive bool // was |x>=0|?
- t, u, v nonnegativeInteger // intermediate quantities
- )
- if x >= 0 {
- positive = true
- } else {
- x = -x
- positive = false
- }
- t = uint32(x % 0100000 * n)
- u = uint32(x/0100000*n + int32(t)/0100000)
- v = uint32(int32(u)%d*0100000 + int32(t)%0100000)
- if int32(u)/d >= 0100000 {
- prg.arithError = true
- } else {
- u = uint32(0100000*(int32(u)/d) + int32(v)/d)
- }
- if positive {
- r = int32(u)
- prg.remainder = int32(v) % d
- } else {
- r = -int32(u)
- prg.remainder = -(int32(v) % d)
- }
- return r
- }
- // 108.
- // tangle:pos tex.web:2317:3:
- // The next subroutine is used to compute the “badness” of glue, when a
- // total~|t| is supposed to be made from amounts that sum to~|s|. According
- // to [\sl The \TeX book], the badness of this situation is $100(t/s)^3$;
- // however, badness is simply a heuristic, so we need not squeeze out the
- // last drop of accuracy when computing it. All we really want is an
- // approximation that has similar properties.
- // \xref[TeXbook][\sl The \TeX book]
- //
- // The actual method used to compute the badness is easier to read from the
- // program than to describe in words. It produces an integer value that is a
- // reasonably close approximation to $100(t/s)^3$, and all implementations
- // of \TeX\ should use precisely this method. Any badness of $2^[13]$ or more is
- // treated as infinitely bad, and represented by 10000.
- //
- // It is not difficult to prove that $$\hbox[|badness(t+1,s)>=badness(t,s)
- // >=badness(t,s+1)|].$$ The badness function defined here is capable of
- // computing at most 1095 distinct values, but that is plenty.
- func (prg *prg) badness(t, s scaled) (r halfword) { // compute badness, given |t>=0|
- var (
- r1 int32 // approximation to $\alpha t/s$, where $\alpha^3\approx
- // 100\cdot2^[18]$
- )
- if t == 0 {
- r = 0
- } else if s <= 0 {
- r = uint16(infBad)
- } else {
- if t <= 7230584 {
- r1 = t * 297 / s
- } else if s >= 1663497 {
- r1 = t / (s / 297)
- } else {
- r1 = t
- }
- if r1 > 1290 {
- r = uint16(infBad)
- } else {
- r = uint16((r1*r1*r1 + 0400000) / 01000000)
- }
- } // that was $r^3/2^[18]$, rounded to the nearest integer
- return r
- }
- // 110. \[8] Packed data
- // tangle:pos tex.web:2375:21:
- // In order to make efficient use of storage space, \TeX\ bases its major data
- // structures on a |memory_word|, which contains either a (signed) integer,
- // possibly scaled, or a (signed) |glue_ratio|, or a small number of
- // fields that are one half or one quarter of the size used for storing
- // integers.
- //
- // If |x| is a variable of type |memory_word|, it contains up to four
- // fields that can be referred to as follows:
- // $$\vbox[\halign[\hfil#&#\hfil&#\hfil\cr
- // |x|&.|int|&(an |integer|)\cr
- // |x|&.|sc|\qquad&(a |scaled| integer)\cr
- // |x|&.|gr|&(a |glue_ratio|)\cr
- // |x.hh.lh|, |x.hh|&.|rh|&(two halfword fields)\cr
- // |x.hh.b0|, |x.hh.b1|, |x.hh|&.|rh|&(two quarterword fields, one halfword
- // field)\cr
- // |x.qqqq.b0|, |x.qqqq.b1|, |x.qqqq|&.|b2|, |x.qqqq.b3|\hskip-100pt
- // &\qquad\qquad\qquad(four quarterword fields)\cr]]$$
- // This is somewhat cumbersome to write, and not very readable either, but
- // macros will be used to make the notation shorter and more transparent.
- // The \PASCAL\ code below gives a formal definition of |memory_word| and
- // its subsidiary types, using packed variant records. \TeX\ makes no
- // assumptions about the relative positions of the fields within a word.
- //
- // Since we are assuming 32-bit integers, a halfword must contain at least
- // 16 bits, and a quarterword must contain at least 8 bits.
- // \xref[system dependencies]
- // But it doesn't hurt to have more bits; for example, with enough 36-bit
- // words you might be able to have |mem_max| as large as 262142, which is
- // eight times as much memory as anybody had during the first four years of
- // \TeX's existence.
- //
- // N.B.: Valuable memory space will be dreadfully wasted unless \TeX\ is compiled
- // by a \PASCAL\ that packs all of the |memory_word| variants into
- // the space of a single integer. This means, for example, that |glue_ratio|
- // words should be |short_real| instead of |real| on some computers. Some
- // \PASCAL\ compilers will pack an integer whose subrange is `|0..255|' into
- // an eight-bit field, but others insist on allocating space for an additional
- // sign bit; on such systems you can get 256 values into a quarterword only
- // if the subrange is `|-128..127|'.
- //
- // The present implementation tries to accommodate as many variations as possible,
- // so it makes few assumptions. If integers having the subrange
- // `|min_quarterword..max_quarterword|' can be packed into a quarterword,
- // and if integers having the subrange `|min_halfword..max_halfword|'
- // can be packed into a halfword, everything should work satisfactorily.
- //
- // It is usually most efficient to have |min_quarterword=min_halfword=0|,
- // so one should try to achieve this unless it causes a severe problem.
- // The values defined here are recommended for most 32-bit computers.
- // 112.
- // tangle:pos tex.web:2449:3:
- // The operation of adding or subtracting |min_quarterword| occurs quite
- // frequently in \TeX, so it is convenient to abbreviate this operation
- // by using the macros |qi| and |qo| for input and output to and from
- // quarterword format.
- //
- // The inner loop of \TeX\ will run faster with respect to compilers
- // that don't optimize expressions like `|x+0|' and `|x-0|', if these
- // macros are simplified in the obvious way when |min_quarterword=0|.
- // \xref[inner loop]\xref[system dependencies]
- // 114.
- // tangle:pos tex.web:2499:3:
- // When debugging, we may want to print a |memory_word| without knowing
- // what type it is; so we print it in all modes.
- // \xref[dirty \PASCAL]\xref[debugging]
- // procedure print_word( w:memory_word);
- // [prints |w| in all ways]
- // begin print_int(w.int); print_char([" "=]32);
- //
- // print_scaled(w.int ); print_char([" "=]32);
- //
- // print_scaled(round( [0200000=]65536 * w. gr )); print_ln;
- //
- // [ \xref[real multiplication] ]
- // print_int(w.hh.lh); print_char(["="=]61); print_int(w.hh.b0); print_char([":"=]58);
- // print_int(w.hh.b1); print_char([";"=]59); print_int(w.hh.rh); print_char([" "=]32);
- //
- // print_int(w.qqqq.b0); print_char([":"=]58); print_int(w.qqqq.b1); print_char([":"=]58);
- // print_int(w.qqqq.b2); print_char([":"=]58); print_int(w.qqqq.b3);
- // end;
- // [ ]
- // 119.
- // tangle:pos tex.web:2596:3:
- // If memory is exhausted, it might mean that the user has forgotten
- // a right brace. We will define some procedures later that try to help
- // pinpoint the trouble.
- // Declare the procedure called |show_token_list|
- func (prg *prg) showTokenList(p, q int32, l int32) {
- var (
- m, c int32 // pieces of a token
- matchChr asciiCode // character used in a `|match|'
- n asciiCode // the highest parameter number, as an ASCII digit
- )
- matchChr = '#'
- n = '0'
- prg.tally = 0
- for p != 0 && prg.tally < l {
- if p == q {
- prg.firstCount = prg.tally
- prg.trickCount = prg.tally + 1 + errorLine - halfErrorLine
- if prg.trickCount < errorLine {
- prg.trickCount = errorLine
- }
- }
- // Display token |p|, and |return| if there are problems
- if p < int32(prg.hiMemMin) || p > int32(prg.memEnd) {
- prg.printEsc(strNumber( /* "CLOBBERED." */ 309))
- goto exit
- // \xref[CLOBBERED]
- }
- if int32(*(*prg.mem[p].hh()).lh()) >= 07777 {
- prg.printCs(int32(*(*prg.mem[p].hh()).lh()) - 07777)
- } else {
- m = int32(*(*prg.mem[p].hh()).lh()) / 0400
- c = int32(*(*prg.mem[p].hh()).lh()) % 0400
- if int32(*(*prg.mem[p].hh()).lh()) < 0 {
- prg.printEsc(strNumber( /* "BAD." */ 555))
- } else {
- // Display the token $(|m|,|c|)$
- switch m {
- case leftBrace, rightBrace, mathShift, tabMark,
- supMark, subMark, spacer, letter,
- otherChar:
- prg.print(c)
- case macParam:
- prg.print(c)
- prg.print(c)
- case outParam:
- prg.print(int32(matchChr))
- if c <= 9 {
- prg.printChar(asciiCode(c + '0'))
- } else {
- prg.printChar(asciiCode('!'))
- goto exit
- }
- case match:
- matchChr = byte(c)
- prg.print(c)
- n = byte(int32(n) + 1)
- prg.printChar(n)
- if int32(n) > '9' {
- goto exit
- }
- case endMatch:
- prg.print( /* "->" */ 556)
- // \xref[->]
- default:
- prg.printEsc(strNumber( /* "BAD." */ 555))
- // \xref[BAD]
- }
- }
- }
- p = int32(*(*prg.mem[p].hh()).rh())
- }
- if p != 0 {
- prg.printEsc(strNumber( /* "ETC." */ 554))
- }
- // \xref[ETC]
- // \xref[ETC]
- exit:
- }
- // Declare the procedure called |runaway|
- func (prg *prg) runaway() {
- var (
- p halfword // head of runaway list
- )
- if int32(prg.scannerStatus) > skipping {
- prg.printNl(strNumber( /* "Runaway " */ 569))
- // \xref[Runaway...]
- switch prg.scannerStatus {
- case defining:
- prg.print( /* "definition" */ 570)
- p = prg.defRef
- case matching:
- prg.print( /* "argument" */ 571)
- p = uint16(30000 - 3)
- case aligning:
- prg.print( /* "preamble" */ 572)
- p = uint16(30000 - 4)
- case absorbing:
- prg.print( /* "text" */ 573)
- p = prg.defRef
- } // there are no other cases
- prg.printChar(asciiCode('?'))
- prg.printLn()
- prg.showTokenList(int32(*(*prg.mem[p].hh()).rh()), 0, errorLine-10)
- }
- }
- // 120.
- // tangle:pos tex.web:2603:3:
- // The function |get_avail| returns a pointer to a new one-word node whose
- // |link| field is null. However, \TeX\ will halt if there is no more room left.
- // \xref[inner loop]
- //
- // If the available-space list is empty, i.e., if |avail=null|,
- // we try first to increase |mem_end|. If that cannot be done, i.e., if
- // |mem_end=mem_max|, we try to decrease |hi_mem_min|. If that cannot be
- // done, i.e., if |hi_mem_min=lo_mem_max+1|, we have to quit.
- func (prg *prg) getAvail() (r halfword) { // single-word node allocation
- var (
- p halfword // the new node being got
- )
- p = prg.avail // get top location in the |avail| stack
- if int32(p) != 0 {
- prg.avail = *(*prg.mem[prg.avail].hh()).rh()
- } else if int32(prg.memEnd) < memMax {
- prg.memEnd = uint16(int32(prg.memEnd) + 1)
- p = prg.memEnd
- } else {
- prg.hiMemMin = uint16(int32(prg.hiMemMin) - 1)
- p = prg.hiMemMin
- if int32(prg.hiMemMin) <= int32(prg.loMemMax) {
- prg.runaway() // if memory is exhausted, display possible runaway text
- prg.overflow(strNumber( /* "main memory size" */ 300), memMax+1-memMin)
- // quit; all one-word nodes are busy
- // \xref[TeX capacity exceeded main memory size][\quad main memory size]
- }
- }
- *(*prg.mem[p].hh()).rh() = 0 // provide an oft-desired initialization of the new node
- // dyn_used:= dyn_used+1 ; [ ]
- //
- // maintain statistics
- r = p
- return r
- }
- // 121.
- // tangle:pos tex.web:2632:3:
- // Conversely, a one-word node is recycled by calling |free_avail|.
- // This routine is part of \TeX's ``inner loop,'' so we want it to be fast.
- // \xref[inner loop]
- // 122.
- // tangle:pos tex.web:2641:3:
- // There's also a |fast_get_avail| routine, which saves the procedure-call
- // overhead at the expense of extra programming. This routine is used in
- // the places that would otherwise account for the most calls of |get_avail|.
- // \xref[inner loop]
- // 123.
- // tangle:pos tex.web:2654:3:
- // The procedure |flush_list(p)| frees an entire linked list of
- // one-word nodes that starts at position |p|.
- // \xref[inner loop]
- func (prg *prg) flushList(p halfword) { // makes list of single-word nodes
- // available
- var (
- q, r1 halfword // list traversers
- )
- if int32(p) != 0 {
- r1 = p
- for {
- q = r1
- r1 = *(*prg.mem[r1].hh()).rh() // dyn_used:= dyn_used-1 ; [ ]
- if int32(r1) == 0 {
- break
- }
- } // now |q| is the last node on the list
- *(*prg.mem[q].hh()).rh() = prg.avail
- prg.avail = p
- }
- }
- // 125.
- // tangle:pos tex.web:2694:3:
- // A call to |get_node| with argument |s| returns a pointer to a new node
- // of size~|s|, which must be 2~or more. The |link| field of the first word
- // of this new node is set to null. An overflow stop occurs if no suitable
- // space exists.
- //
- // If |get_node| is called with $s=2^[30]$, it simply merges adjacent free
- // areas and returns the value |max_halfword|.
- func (prg *prg) getNode(s int32) (r halfword) {
- var (
- p halfword // the node currently under inspection
- q halfword // the node physically after node |p|
- r1 int32 // the newly allocated node, or a candidate for this honor
- t int32 // temporary register
- )
- restart:
- p = prg.rover // start at some free node in the ring
- for {
- // Try to allocate within node |p| and its physical successors, and |goto found| if allocation was possible
- q = uint16(int32(p) + int32(*(*prg.mem[p].hh()).lh())) // find the physical successor
- // \xref[inner loop]
- for int32(*(*prg.mem[q].hh()).rh()) == 65535 { // merge node |p| with node |q|
- t = int32(*(*prg.mem[int32(q)+1].hh()).rh())
- if int32(q) == int32(prg.rover) {
- prg.rover = uint16(t)
- }
- *(*prg.mem[t+1].hh()).lh() = *(*prg.mem[int32(q)+1].hh()).lh()
- *(*prg.mem[int32(*(*prg.mem[int32(q)+1].hh()).lh())+1].hh()).rh() = uint16(t)
- q = uint16(int32(q) + int32(*(*prg.mem[q].hh()).lh()))
- }
- r1 = int32(q) - s
- if r1 > int32(p)+1 {
- *(*prg.mem[p].hh()).lh() = uint16(r1 - int32(p)) // store the remaining size
- // \xref[inner loop]
- prg.rover = p // start searching here next time
- // start searching here next time
- goto found
- }
- if r1 == int32(p) {
- if int32(*(*prg.mem[int32(p)+1].hh()).rh()) != int32(p) {
- prg.rover = *(*prg.mem[int32(p)+1].hh()).rh()
- t = int32(*(*prg.mem[int32(p)+1].hh()).lh())
- *(*prg.mem[int32(prg.rover)+1].hh()).lh() = uint16(t)
- *(*prg.mem[t+1].hh()).rh() = prg.rover
- goto found
- }
- }
- *(*prg.mem[p].hh()).lh() = uint16(int32(q) - int32(p))
- // \xref[inner loop]
- p = *(*prg.mem[int32(p)+1].hh()).rh() // move to the next node in the ring
- if int32(p) == int32(prg.rover) {
- break
- }
- } // repeat until the whole list has been traversed
- if s == 010000000000 {
- r = 65535
- goto exit
- }
- if int32(prg.loMemMax)+2 < int32(prg.hiMemMin) {
- if int32(prg.loMemMax)+2 <= memBot+65535 {
- if int32(prg.hiMemMin)-int32(prg.loMemMax) >= 1998 {
- t = int32(prg.loMemMax) + 1000
- } else {
- t = int32(prg.loMemMax) + 1 + (int32(prg.hiMemMin)-int32(prg.loMemMax))/2
- }
- // |lo_mem_max+2<=t<hi_mem_min|
- p = *(*prg.mem[int32(prg.rover)+1].hh()).lh()
- q = prg.loMemMax
- *(*prg.mem[int32(p)+1].hh()).rh() = q
- *(*prg.mem[int32(prg.rover)+1].hh()).lh() = q
- if t > memBot+65535 {
- t = memBot + 65535
- }
- *(*prg.mem[int32(q)+1].hh()).rh() = prg.rover
- *(*prg.mem[int32(q)+1].hh()).lh() = p
- *(*prg.mem[q].hh()).rh() = 65535
- *(*prg.mem[q].hh()).lh() = uint16(t - int32(prg.loMemMax))
- prg.loMemMax = uint16(t)
- *(*prg.mem[prg.loMemMax].hh()).rh() = 0
- *(*prg.mem[prg.loMemMax].hh()).lh() = 0
- prg.rover = q
- goto restart
- }
- }
- prg.overflow(strNumber( /* "main memory size" */ 300), memMax+1-memMin)
- // sorry, nothing satisfactory is left
- // \xref[TeX capacity exceeded main memory size][\quad main memory size]
- // sorry, nothing satisfactory is left
- // \xref[TeX capacity exceeded main memory size][\quad main memory size]
- found:
- *(*prg.mem[r1].hh()).rh() = 0 // this node is now nonempty
- // var_used:=var_used+s; [maintain usage statistics]
- // [ ]
- r = uint16(r1)
- exit:
- ;
- return r
- }
- // 130.
- // tangle:pos tex.web:2780:3:
- // Conversely, when some variable-size node |p| of size |s| is no longer needed,
- // the operation |free_node(p,s)| will make its words available, by inserting
- // |p| as a new empty node just before where |rover| now points.
- // \xref[inner loop]
- func (prg *prg) freeNode(p halfword, s halfword) { // variable-size node
- // liberation
- var (
- q halfword // |llink(rover)|
- )
- *(*prg.mem[p].hh()).lh() = s
- *(*prg.mem[p].hh()).rh() = 65535
- q = *(*prg.mem[int32(prg.rover)+1].hh()).lh()
- *(*prg.mem[int32(p)+1].hh()).lh() = q
- *(*prg.mem[int32(p)+1].hh()).rh() = prg.rover // set both links
- *(*prg.mem[int32(prg.rover)+1].hh()).lh() = p
- *(*prg.mem[int32(q)+1].hh()).rh() = p // insert |p| into the ring
- // var_used:=var_used-s; [ ]
- // maintain statistics
- }
- // 131.
- // tangle:pos tex.web:2794:3:
- // Just before \.[INITEX] writes out the memory, it sorts the doubly linked
- // available space list. The list is probably very short at such times, so a
- // simple insertion sort is used. The smallest available location will be
- // pointed to by |rover|, the next-smallest by |rlink(rover)|, etc.
- func (prg *prg) sortAvail() { // sorts the available variable-size nodes
- // by location
- var (
- p, q, r1 halfword // indices into |mem|
- oldRover halfword // initial |rover| setting
- )
- p = prg.getNode(010000000000) // merge adjacent free areas
- p = *(*prg.mem[int32(prg.rover)+1].hh()).rh()
- *(*prg.mem[int32(prg.rover)+1].hh()).rh() = 65535
- oldRover = prg.rover
- for int32(p) != int32(oldRover) {
- // Sort \(p)|p| into the list starting at |rover| and advance |p| to |rlink(p)|
- if int32(p) < int32(prg.rover) {
- q = p
- p = *(*prg.mem[int32(q)+1].hh()).rh()
- *(*prg.mem[int32(q)+1].hh()).rh() = prg.rover
- prg.rover = q
- } else {
- q = prg.rover
- for int32(*(*prg.mem[int32(q)+1].hh()).rh()) < int32(p) {
- q = *(*prg.mem[int32(q)+1].hh()).rh()
- }
- r1 = *(*prg.mem[int32(p)+1].hh()).rh()
- *(*prg.mem[int32(p)+1].hh()).rh() = *(*prg.mem[int32(q)+1].hh()).rh()
- *(*prg.mem[int32(q)+1].hh()).rh() = p
- p = r1
- }
- }
- p = prg.rover
- for int32(*(*prg.mem[int32(p)+1].hh()).rh()) != 65535 {
- *(*prg.mem[int32(*(*prg.mem[int32(p)+1].hh()).rh())+1].hh()).lh() = p
- p = *(*prg.mem[int32(p)+1].hh()).rh()
- }
- *(*prg.mem[int32(p)+1].hh()).rh() = prg.rover
- *(*prg.mem[int32(prg.rover)+1].hh()).lh() = p
- }
- // 133. \[10] Data structures for boxes and their friends
- // tangle:pos tex.web:2828:54:
- // From the computer's standpoint, \TeX's chief mission is to create
- // horizontal and vertical lists. We shall now investigate how the elements
- // of these lists are represented internally as nodes in the dynamic memory.
- //
- // A horizontal or vertical list is linked together by |link| fields in
- // the first word of each node. Individual nodes represent boxes, glue,
- // penalties, or special things like discretionary hyphens; because of this
- // variety, some nodes are longer than others, and we must distinguish different
- // kinds of nodes. We do this by putting a `|type|' field in the first word,
- // together with the link and an optional `|subtype|'.
- // 134.
- // tangle:pos tex.web:2843:3:
- // A | char_node|, which represents a single character, is the most important
- // kind of node because it accounts for the vast majority of all boxes.
- // Special precautions are therefore taken to ensure that a |char_node| does
- // not take up much memory space. Every such node is one word long, and in fact
- // it is identifiable by this property, since other kinds of nodes have at least
- // two words, and they appear in |mem| locations less than |hi_mem_min|.
- // This makes it possible to omit the |type| field in a |char_node|, leaving
- // us room for two bytes that identify a |font| and a |character| within
- // that font.
- //
- // Note that the format of a |char_node| allows for up to 256 different
- // fonts and up to 256 characters per font; but most implementations will
- // probably limit the total number of fonts to fewer than 75 per job,
- // and most fonts will stick to characters whose codes are
- // less than 128 (since higher codes
- // are more difficult to access on most keyboards).
- //
- // Extensions of \TeX\ intended for oriental languages will need even more
- // than $256\times256$ possible characters, when we consider different sizes
- // \xref[oriental characters]\xref[Chinese characters]\xref[Japanese characters]
- // and styles of type. It is suggested that Chinese and Japanese fonts be
- // handled by representing such characters in two consecutive |char_node|
- // entries: The first of these has |font=font_base|, and its |link| points
- // to the second;
- // the second identifies the font and the character dimensions.
- // The saving feature about oriental characters is that most of them have
- // the same box dimensions. The |character| field of the first |char_node|
- // is a ``\\[charext]'' that distinguishes between graphic symbols whose
- // dimensions are identical for typesetting purposes. (See the \MF\ manual.)
- // Such an extension of \TeX\ would not be difficult; further details are
- // left to the reader.
- //
- // In order to make sure that the |character| code fits in a quarterword,
- // \TeX\ adds the quantity |min_quarterword| to the actual code.
- //
- // Character nodes appear only in horizontal lists, never in vertical lists.
- // 135.
- // tangle:pos tex.web:2885:3:
- // An |hlist_node| stands for a box that was made from a horizontal list.
- // Each |hlist_node| is seven words long, and contains the following fields
- // (in addition to the mandatory |type| and |link|, which we shall not
- // mention explicitly when discussing the other node types): The |height| and
- // |width| and |depth| are scaled integers denoting the dimensions of the
- // box. There is also a |shift_amount| field, a scaled integer indicating
- // how much this box should be lowered (if it appears in a horizontal list),
- // or how much it should be moved to the right (if it appears in a vertical
- // list). There is a |list_ptr| field, which points to the beginning of the
- // list from which this box was fabricated; if |list_ptr| is |null|, the box
- // is empty. Finally, there are three fields that represent the setting of
- // the glue: |glue_set(p)| is a word of type |glue_ratio| that represents
- // the proportionality constant for glue setting; |glue_sign(p)| is
- // |stretching| or |shrinking| or |normal| depending on whether or not the
- // glue should stretch or shrink or remain rigid; and |glue_order(p)|
- // specifies the order of infinity to which glue setting applies (|normal|,
- // |fil|, |fill|, or |filll|). The |subtype| field is not used.
- // 136.
- // tangle:pos tex.web:2923:3:
- // The |new_null_box| function returns a pointer to an |hlist_node| in
- // which all subfields have the values corresponding to `\.[\\hbox\[\]]'.
- // (The |subtype| field is set to |min_quarterword|, for historic reasons
- // that are no longer relevant.)
- func (prg *prg) newNullBox() (r halfword) { // creates a new box node
- var (
- p halfword // the new node
- )
- p = prg.getNode(boxNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(hlistNode)
- *(*prg.mem[p].hh()).b1() = byte(minQuarterword)
- *prg.mem[int32(p)+widthOffset].int() = 0
- *prg.mem[int32(p)+depthOffset].int() = 0
- *prg.mem[int32(p)+heightOffset].int() = 0
- *prg.mem[int32(p)+4].int() = 0
- *(*prg.mem[int32(p)+listOffset].hh()).rh() = 0
- *(*prg.mem[int32(p)+listOffset].hh()).b0() = byte(normal)
- *(*prg.mem[int32(p)+listOffset].hh()).b1() = byte(normal)
- *prg.mem[int32(p)+glueOffset].gr() = float32(0.0)
- r = p
- return r
- }
- // 137.
- // tangle:pos tex.web:2937:3:
- // A |vlist_node| is like an |hlist_node| in all respects except that it
- // contains a vertical list.
- // 138.
- // tangle:pos tex.web:2942:3:
- // A |rule_node| stands for a solid black rectangle; it has |width|,
- // |depth|, and |height| fields just as in an |hlist_node|. However, if
- // any of these dimensions is $-2^[30]$, the actual value will be determined
- // by running the rule up to the boundary of the innermost enclosing box.
- // This is called a ``running dimension.'' The |width| is never running in
- // an hlist; the |height| and |depth| are never running in a~vlist.
- // 139.
- // tangle:pos tex.web:2954:3:
- // A new rule node is delivered by the |new_rule| function. It
- // makes all the dimensions “running,” so you have to change the
- // ones that are not allowed to run.
- func (prg *prg) newRule() (r halfword) {
- var (
- p halfword // the new node
- )
- p = prg.getNode(ruleNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(ruleNode)
- *(*prg.mem[p].hh()).b1() = 0 // the |subtype| is not used
- *prg.mem[int32(p)+widthOffset].int() = -010000000000
- *prg.mem[int32(p)+depthOffset].int() = -010000000000
- *prg.mem[int32(p)+heightOffset].int() = -010000000000
- r = p
- return r
- }
- // 140.
- // tangle:pos tex.web:2966:3:
- // Insertions are represented by |ins_node| records, where the |subtype|
- // indicates the corresponding box number. For example, `\.[\\insert 250]'
- // leads to an |ins_node| whose |subtype| is |250+min_quarterword|.
- // The |height| field of an |ins_node| is slightly misnamed; it actually holds
- // the natural height plus depth of the vertical list being inserted.
- // The |depth| field holds the |split_max_depth| to be used in case this
- // insertion is split, and the |split_top_ptr| points to the corresponding
- // |split_top_skip|. The |float_cost| field holds the |floating_penalty| that
- // will be used if this insertion floats to a subsequent page after a
- // split insertion of the same class. There is one more field, the
- // |ins_ptr|, which points to the beginning of the vlist for the insertion.
- // 141.
- // tangle:pos tex.web:2984:3:
- // A |mark_node| has a |mark_ptr| field that points to the reference count
- // of a token list that contains the user's \.[\\mark] text.
- // This field occupies a full word instead of a halfword, because
- // there's nothing to put in the other halfword; it is easier in \PASCAL\ to
- // use the full word than to risk leaving garbage in the unused half.
- // 142.
- // tangle:pos tex.web:2994:3:
- // An |adjust_node|, which occurs only in horizontal lists,
- // specifies material that will be moved out into the surrounding
- // vertical list; i.e., it is used to implement \TeX's `\.[\\vadjust]'
- // operation. The |adjust_ptr| field points to the vlist containing this
- // material.
- // 143.
- // tangle:pos tex.web:3003:3:
- // A |ligature_node|, which occurs only in horizontal lists, specifies
- // a character that was fabricated from the interaction of two or more
- // actual characters. The second word of the node, which is called the
- // |lig_char| word, contains |font| and |character| fields just as in a
- // |char_node|. The characters that generated the ligature have not been
- // forgotten, since they are needed for diagnostic messages and for
- // hyphenation; the |lig_ptr| field points to a linked list of character
- // nodes for all original characters that have been deleted. (This list
- // might be empty if the characters that generated the ligature were
- // retained in other nodes.)
- //
- // The |subtype| field is 0, plus 2 and/or 1 if the original source of the
- // ligature included implicit left and/or right boundaries.
- // 144.
- // tangle:pos tex.web:3021:3:
- // The |new_ligature| function creates a ligature node having given
- // contents of the |font|, |character|, and |lig_ptr| fields. We also have
- // a |new_lig_item| function, which returns a two-word node having a given
- // |character| field. Such nodes are used for temporary processing as ligatures
- // are being created.
- func (prg *prg) newLigature(f, c quarterword, q halfword) (r halfword) {
- var (
- p halfword // the new node
- )
- p = prg.getNode(smallNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(ligatureNode)
- *(*prg.mem[int32(p)+1].hh()).b0() = f
- *(*prg.mem[int32(p)+1].hh()).b1() = c
- *(*prg.mem[int32(p)+1].hh()).rh() = q
- *(*prg.mem[p].hh()).b1() = 0
- r = p
- return r
- }
- func (prg *prg) newLigItem(c quarterword) (r halfword) {
- var (
- p halfword // the new node
- )
- p = prg.getNode(smallNodeSize)
- *(*prg.mem[p].hh()).b1() = c
- *(*prg.mem[int32(p)+1].hh()).rh() = 0
- r = p
- return r
- }
- // 145.
- // tangle:pos tex.web:3040:3:
- // A |disc_node|, which occurs only in horizontal lists, specifies a
- // “dis\-cretion\-ary” line break. If such a break occurs at node |p|, the text
- // that starts at |pre_break(p)| will precede the break, the text that starts at
- // |post_break(p)| will follow the break, and text that appears in the next
- // |replace_count(p)| nodes will be ignored. For example, an ordinary
- // discretionary hyphen, indicated by `\.[\\-]', yields a |disc_node| with
- // |pre_break| pointing to a |char_node| containing a hyphen, |post_break=null|,
- // and |replace_count=0|. All three of the discretionary texts must be
- // lists that consist entirely of character, kern, box, rule, and ligature nodes.
- //
- // If |pre_break(p)=null|, the |ex_hyphen_penalty| will be charged for this
- // break. Otherwise the |hyphen_penalty| will be charged. The texts will
- // actually be substituted into the list by the line-breaking algorithm if it
- // decides to make the break, and the discretionary node will disappear at
- // that time; thus, the output routine sees only discretionaries that were
- // not chosen.
- func (prg *prg) newDisc() (r halfword) { // creates an empty |disc_node|
- var (
- p halfword // the new node
- )
- p = prg.getNode(smallNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(discNode)
- *(*prg.mem[p].hh()).b1() = 0
- *(*prg.mem[int32(p)+1].hh()).lh() = 0
- *(*prg.mem[int32(p)+1].hh()).rh() = 0
- r = p
- return r
- }
- // 146.
- // tangle:pos tex.web:3069:3:
- // A |whatsit_node| is a wild card reserved for extensions to \TeX. The
- // |subtype| field in its first word says what `\\[whatsit]' it is, and
- // implicitly determines the node size (which must be 2 or more) and the
- // format of the remaining words. When a |whatsit_node| is encountered
- // in a list, special actions are invoked; knowledgeable people who are
- // careful not to mess up the rest of \TeX\ are able to make \TeX\ do new
- // things by adding code at the end of the program. For example, there
- // might be a `\TeX nicolor' extension to specify different colors of ink,
- // \xref[extensions to \TeX]
- // and the whatsit node might contain the desired parameters.
- //
- // The present implementation of \TeX\ treats the features associated with
- // `\.[\\write]' and `\.[\\special]' as if they were extensions, in order to
- // illustrate how such routines might be coded. We shall defer further
- // discussion of extensions until the end of this program.
- // 147.
- // tangle:pos tex.web:3087:3:
- // A |math_node|, which occurs only in horizontal lists, appears before and
- // after mathematical formulas. The |subtype| field is |before| before the
- // formula and |after| after it. There is a |width| field, which represents
- // the amount of surrounding space inserted by \.[\\mathsurround].
- func (prg *prg) newMath(w scaled, s smallNumber) (r halfword) {
- var (
- p halfword // the new node
- )
- p = prg.getNode(smallNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(mathNode)
- *(*prg.mem[p].hh()).b1() = s
- *prg.mem[int32(p)+widthOffset].int() = w
- r = p
- return r
- }
- // 148.
- // tangle:pos tex.web:3102:3:
- // \TeX\ makes use of the fact that |hlist_node|, |vlist_node|,
- // |rule_node|, |ins_node|, |mark_node|, |adjust_node|, |ligature_node|,
- // |disc_node|, |whatsit_node|, and |math_node| are at the low end of the
- // type codes, by permitting a break at glue in a list if and only if the
- // |type| of the previous node is less than |math_node|. Furthermore, a
- // node is discarded after a break if its type is |math_node| or~more.
- // 149.
- // tangle:pos tex.web:3112:3:
- // A |glue_node| represents glue in a list. However, it is really only
- // a pointer to a separate glue specification, since \TeX\ makes use of the
- // fact that many essentially identical nodes of glue are usually present.
- // If |p| points to a |glue_node|, |glue_ptr(p)| points to
- // another packet of words that specify the stretch and shrink components, etc.
- //
- // Glue nodes also serve to represent leaders; the |subtype| is used to
- // distinguish between ordinary glue (which is called |normal|) and the three
- // kinds of leaders (which are called |a_leaders|, |c_leaders|, and |x_leaders|).
- // The |leader_ptr| field points to a rule node or to a box node containing the
- // leaders; it is set to |null| in ordinary glue nodes.
- //
- // Many kinds of glue are computed from \TeX's ``skip'' parameters, and
- // it is helpful to know which parameter has led to a particular glue node.
- // Therefore the |subtype| is set to indicate the source of glue, whenever
- // it originated as a parameter. We will be defining symbolic names for the
- // parameter numbers later (e.g., |line_skip_code=0|, |baseline_skip_code=1|,
- // etc.); it suffices for now to say that the |subtype| of parametric glue
- // will be the same as the parameter number, plus~one.
- //
- // In math formulas there are two more possibilities for the |subtype| in a
- // glue node: |mu_glue| denotes an \.[\\mskip] (where the units are scaled \.[mu]
- // instead of scaled \.[pt]); and |cond_math_glue| denotes the `\.[\\nonscript]'
- // feature that cancels the glue node immediately following if it appears
- // in a subscript.
- // 151.
- // tangle:pos tex.web:3174:3:
- // Here is a function that returns a pointer to a copy of a glue spec.
- // The reference count in the copy is |null|, because there is assumed
- // to be exactly one reference to the new specification.
- func (prg *prg) newSpec(p halfword) (r halfword) { // duplicates a glue specification
- var (
- q halfword // the new spec
- )
- q = prg.getNode(glueSpecSize)
- prg.mem[q] = prg.mem[p]
- *(*prg.mem[q].hh()).rh() = 0
- *prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(p)+widthOffset].int()
- *prg.mem[int32(q)+2].int() = *prg.mem[int32(p)+2].int()
- *prg.mem[int32(q)+3].int() = *prg.mem[int32(p)+3].int()
- r = q
- return r
- }
- // 152.
- // tangle:pos tex.web:3186:3:
- // And here's a function that creates a glue node for a given parameter
- // identified by its code number; for example,
- // |new_param_glue(line_skip_code)| returns a pointer to a glue node for the
- // current \.[\\lineskip].
- func (prg *prg) newParamGlue(n smallNumber) (r halfword) {
- var (
- p halfword // the new node
- q halfword // the glue specification
- )
- p = prg.getNode(smallNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(glueNode)
- *(*prg.mem[p].hh()).b1() = byte(int32(n) + 1)
- *(*prg.mem[int32(p)+1].hh()).rh() = 0
- q = *(*prg.eqtb[glueBase+int32(n)-1].hh()).rh()
- *(*prg.mem[int32(p)+1].hh()).lh() = q
- *(*prg.mem[q].hh()).rh() = uint16(int32(*(*prg.mem[q].hh()).rh()) + 1)
- r = p
- return r
- }
- // 153.
- // tangle:pos tex.web:3201:3:
- // Glue nodes that are more or less anonymous are created by |new_glue|,
- // whose argument points to a glue specification.
- func (prg *prg) newGlue(q halfword) (r halfword) {
- var (
- p halfword // the new node
- )
- p = prg.getNode(smallNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(glueNode)
- *(*prg.mem[p].hh()).b1() = byte(normal)
- *(*prg.mem[int32(p)+1].hh()).rh() = 0
- *(*prg.mem[int32(p)+1].hh()).lh() = q
- *(*prg.mem[q].hh()).rh() = uint16(int32(*(*prg.mem[q].hh()).rh()) + 1)
- r = p
- return r
- }
- // 154.
- // tangle:pos tex.web:3211:3:
- // Still another subroutine is needed: This one is sort of a combination
- // of |new_param_glue| and |new_glue|. It creates a glue node for one of
- // the current glue parameters, but it makes a fresh copy of the glue
- // specification, since that specification will probably be subject to change,
- // while the parameter will stay put. The global variable |temp_ptr| is
- // set to the address of the new spec.
- func (prg *prg) newSkipParam(n smallNumber) (r halfword) {
- var (
- p halfword // the new node
- )
- prg.tempPtr = prg.newSpec(*(*prg.eqtb[glueBase+int32(n)-1].hh()).rh())
- p = prg.newGlue(prg.tempPtr)
- *(*prg.mem[prg.tempPtr].hh()).rh() = 0
- *(*prg.mem[p].hh()).b1() = byte(int32(n) + 1)
- r = p
- return r
- }
- // 155.
- // tangle:pos tex.web:3225:3:
- // A |kern_node| has a |width| field to specify a (normally negative)
- // amount of spacing. This spacing correction appears in horizontal lists
- // between letters like A and V when the font designer said that it looks
- // better to move them closer together or further apart. A kern node can
- // also appear in a vertical list, when its `|width|' denotes additional
- // spacing in the vertical direction. The |subtype| is either |normal| (for
- // kerns inserted from font information or math mode calculations) or |explicit|
- // (for kerns inserted from \.[\\kern] and \.[\\/] commands) or |acc_kern|
- // (for kerns inserted from non-math accents) or |mu_glue| (for kerns
- // inserted from \.[\\mkern] specifications in math formulas).
- // 156.
- // tangle:pos tex.web:3240:3:
- // The |new_kern| function creates a kern node having a given width.
- func (prg *prg) newKern(w scaled) (r halfword) {
- var (
- p halfword // the new node
- )
- p = prg.getNode(smallNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(kernNode)
- *(*prg.mem[p].hh()).b1() = byte(normal)
- *prg.mem[int32(p)+widthOffset].int() = w
- r = p
- return r
- }
- // 157.
- // tangle:pos tex.web:3250:3:
- // A |penalty_node| specifies the penalty associated with line or page
- // breaking, in its |penalty| field. This field is a fullword integer, but
- // the full range of integer values is not used: Any penalty |>=10000| is
- // treated as infinity, and no break will be allowed for such high values.
- // Similarly, any penalty |<=-10000| is treated as negative infinity, and a
- // break will be forced.
- // 158.
- // tangle:pos tex.web:3262:3:
- // Anyone who has been reading the last few sections of the program will
- // be able to guess what comes next.
- func (prg *prg) newPenalty(m int32) (r halfword) {
- var (
- p halfword // the new node
- )
- p = prg.getNode(smallNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(penaltyNode)
- *(*prg.mem[p].hh()).b1() = 0 // the |subtype| is not used
- *prg.mem[int32(p)+1].int() = m
- r = p
- return r
- }
- // 159.
- // tangle:pos tex.web:3272:3:
- // You might think that we have introduced enough node types by now. Well,
- // almost, but there is one more: An |unset_node| has nearly the same format
- // as an |hlist_node| or |vlist_node|; it is used for entries in \.[\\halign]
- // or \.[\\valign] that are not yet in their final form, since the box
- // dimensions are their ``natural'' sizes before any glue adjustment has been
- // made. The |glue_set| word is not present; instead, we have a |glue_stretch|
- // field, which contains the total stretch of order |glue_order| that is
- // present in the hlist or vlist being boxed.
- // Similarly, the |shift_amount| field is replaced by a |glue_shrink| field,
- // containing the total shrink of order |glue_sign| that is present.
- // The |subtype| field is called |span_count|; an unset box typically
- // contains the data for |qo(span_count)+1| columns.
- // Unset nodes will be changed to box nodes when alignment is completed.
- // 160.
- // tangle:pos tex.web:3291:3:
- // In fact, there are still more types coming. When we get to math formula
- // processing we will see that a |style_node| has |type=14|; and a number
- // of larger type codes will also be defined, for use in math mode only.
- // 161.
- // tangle:pos tex.web:3295:3:
- // Warning: If any changes are made to these data structure layouts, such as
- // changing any of the node sizes or even reordering the words of nodes,
- // the |copy_node_list| procedure and the memory initialization code
- // below may have to be changed. Such potentially dangerous parts of the
- // program are listed in the index under `data structure assumptions'.
- // \xref[data structure assumptions]
- // However, other references to the nodes are made symbolically in terms of
- // the \.[WEB] macro definitions above, so that format changes will leave
- // \TeX's other algorithms intact.
- // \xref[system dependencies]
- // 162. \[11] Memory layout
- // tangle:pos tex.web:3306:24:
- // Some areas of |mem| are dedicated to fixed usage, since static allocation is
- // more efficient than dynamic allocation when we can get away with it. For
- // example, locations |mem_bot| to |mem_bot+3| are always used to store the
- // specification for glue that is `\.[0pt plus 0pt minus 0pt]'. The
- // following macro definitions accomplish the static allocation by giving
- // symbolic names to the fixed positions. Static variable-size nodes appear
- // in locations |mem_bot| through |lo_mem_stat_max|, and static single-word nodes
- // appear in locations |hi_mem_stat_min| through |mem_top|, inclusive. It is
- // harmless to let |lig_trick| and |garbage| share the same location of |mem|.
- // 167.
- // tangle:pos tex.web:3402:3:
- // Procedure |check_mem| makes sure that the available space lists of
- // |mem| are well formed, and it optionally prints out all locations
- // that are reserved now but were free the last time this procedure was called.
- // procedure check_mem( print_locs : boolean);
- // label done1,done2; [loop exits]
- // var p, q:halfword ; [current locations of interest in |mem|]
- // clobbered:boolean; [is something amiss?]
- // begin for p:=mem_min to lo_mem_max do free[p]:=false; [you can probably
- // do this faster]
- // for p:=hi_mem_min to mem_end do free[p]:=false; [ditto]
- //
- // [ Check single-word |avail| list ]
- // p:=avail; q:=0 ; clobbered:=false;
- // while p<>0 do
- // begin if (p>mem_end)or(p<hi_mem_min) then clobbered:=true
- // else if free[p] then clobbered:=true;
- // if clobbered then
- // begin print_nl(["AVAIL list clobbered at "=]301);
- // [ \xref[AVAIL list clobbered...] ]
- // print_int(q); goto done1;
- // end;
- // free[p]:=true; q:=p; p:= mem[ q].hh.rh ;
- // end;
- // done1:
- //
- // ;
- //
- // [ Check variable-size |avail| list ]
- // p:=rover; q:=0 ; clobbered:=false;
- // repeat if (p>=lo_mem_max)or(p<mem_min) then clobbered:=true
- // else if ( mem[ p+ 1].hh.rh >=lo_mem_max)or( mem[ p+ 1].hh.rh <mem_min) then clobbered:=true
- // else if not( ( mem[ p].hh.rh = 65535 ) )or( mem[ p].hh.lh <2)or
- // (p+ mem[ p].hh.lh >lo_mem_max)or ( mem[ mem[ p+ 1].hh.rh + 1].hh.lh <>p) then clobbered:=true;
- // if clobbered then
- // begin print_nl(["Double-AVAIL list clobbered at "=]302);
- // print_int(q); goto done2;
- // end;
- // for q:=p to p+ mem[ p].hh.lh -1 do [mark all locations free]
- // begin if free[q] then
- // begin print_nl(["Doubly free location at "=]303);
- // [ \xref[Doubly free location...] ]
- // print_int(q); goto done2;
- // end;
- // free[q]:=true;
- // end;
- // q:=p; p:= mem[ p+ 1].hh.rh ;
- // until p=rover;
- // done2:
- //
- // ;
- //
- // [ Check flags of unavailable nodes ]
- // p:=mem_min;
- // while p<=lo_mem_max do [node |p| should not be empty]
- // begin if ( mem[ p].hh.rh = 65535 ) then
- // begin print_nl(["Bad flag at "=]304); print_int(p);
- // [ \xref[Bad flag...] ]
- // end;
- // while (p<=lo_mem_max) and not free[p] do p:= p+1 ;
- // while (p<=lo_mem_max) and free[p] do p:= p+1 ;
- // end
- //
- // ;
- // if print_locs then
- // [ Print newly busy locations ]
- // begin print_nl(["New busy locs:"=]305);
- // for p:=mem_min to lo_mem_max do
- // if not free[p] and ((p>was_lo_max) or was_free[p]) then
- // begin print_char([" "=]32); print_int(p);
- // end;
- // for p:=hi_mem_min to mem_end do
- // if not free[p] and
- // ((p<was_hi_min) or (p>was_mem_end) or was_free[p]) then
- // begin print_char([" "=]32); print_int(p);
- // end;
- // end
- //
- // ;
- // for p:=mem_min to lo_mem_max do was_free[p]:=free[p];
- // for p:=hi_mem_min to mem_end do was_free[p]:=free[p];
- // [|was_free:=free| might be faster]
- // was_mem_end:=mem_end; was_lo_max:=lo_mem_max; was_hi_min:=hi_mem_min;
- // end;
- // [ ]
- // 172.
- // tangle:pos tex.web:3484:3:
- // The |search_mem| procedure attempts to answer the question ``Who points
- // to node~|p|?'' In doing so, it fetches |link| and |info| fields of |mem|
- // that might not be of type |two_halves|. Strictly speaking, this is
- // \xref[dirty \PASCAL]
- // undefined in \PASCAL, and it can lead to ``false drops'' (words that seem to
- // point to |p| purely by coincidence). But for debugging purposes, we want
- // to rule out the places that do [\sl not\/] point to |p|, so a few false
- // drops are tolerable.
- // procedure search_mem( p:halfword ); [look for pointers to |p|]
- // var q:integer; [current position being searched]
- // begin for q:=mem_min to lo_mem_max do
- // begin if mem[ q].hh.rh =p then
- // begin print_nl(["LINK("=]306); print_int(q); print_char([")"=]41);
- // end;
- // if mem[ q].hh.lh =p then
- // begin print_nl(["INFO("=]307); print_int(q); print_char([")"=]41);
- // end;
- // end;
- // for q:=hi_mem_min to mem_end do
- // begin if mem[ q].hh.rh =p then
- // begin print_nl(["LINK("=]306); print_int(q); print_char([")"=]41);
- // end;
- // if mem[ q].hh.lh =p then
- // begin print_nl(["INFO("=]307); print_int(q); print_char([")"=]41);
- // end;
- // end;
- //
- // [ Search |eqtb| for equivalents equal to |p| ]
- // for q:=active_base to box_base+255 do
- // begin if eqtb[ q].hh.rh =p then
- // begin print_nl(["EQUIV("=]501); print_int(q); print_char([")"=]41);
- // end;
- // end
- //
- // ;
- //
- // [ Search |save_stack| for equivalents that point to |p| ]
- // if save_ptr>0 then for q:=0 to save_ptr-1 do
- // begin if save_stack[ q].hh.rh =p then
- // begin print_nl(["SAVE("=]546); print_int(q); print_char([")"=]41);
- // end;
- // end
- //
- // ;
- //
- // [ Search |hyph_list| for pointers to |p| ]
- // for q:=0 to hyph_size do
- // begin if hyph_list[q]=p then
- // begin print_nl(["HYPH("=]940); print_int(q); print_char([")"=]41);
- // end;
- // end
- //
- // ;
- // end;
- // [ ]
- // 174.
- // tangle:pos tex.web:3538:3:
- // Boxes, rules, inserts, whatsits, marks, and things in general that are
- // sort of “complicated” are indicated only by printing `\.[[]]'.
- func (prg *prg) shortDisplay(p int32) { // prints highlights of list |p|
- var (
- n int32 // for replacement counts
- )
- for p > memMin {
- if p >= int32(prg.hiMemMin) {
- if p <= int32(prg.memEnd) {
- if int32(*(*prg.mem[p].hh()).b0()) != prg.fontInShortDisplay {
- if int32(*(*prg.mem[p].hh()).b0()) < fontBase || int32(*(*prg.mem[p].hh()).b0()) > fontMax {
- prg.printChar(asciiCode('*'))
- } else {
- // Print the font identifier for |font(p)|
- prg.printEsc(*prg.hash[fontIdBase+int32(*(*prg.mem[p].hh()).b0())-514].rh())
- }
- prg.printChar(asciiCode(' '))
- prg.fontInShortDisplay = int32(*(*prg.mem[p].hh()).b0())
- }
- prg.print(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword)
- }
- } else {
- // Print a short indication of the contents of node |p|
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, insNode, whatsitNode,
- markNode, adjustNode, unsetNode:
- prg.print( /* "[]" */ 308)
- case ruleNode:
- prg.printChar(asciiCode('|'))
- case glueNode:
- if int32(*(*prg.mem[p+1].hh()).lh()) != memBot {
- prg.printChar(asciiCode(' '))
- }
- case mathNode:
- prg.printChar(asciiCode('$'))
- case ligatureNode:
- prg.shortDisplay(int32(*(*prg.mem[p+1].hh()).rh()))
- case discNode:
- prg.shortDisplay(int32(*(*prg.mem[p+1].hh()).lh()))
- prg.shortDisplay(int32(*(*prg.mem[p+1].hh()).rh()))
- n = int32(*(*prg.mem[p].hh()).b1())
- for n > 0 {
- if int32(*(*prg.mem[p].hh()).rh()) != 0 {
- p = int32(*(*prg.mem[p].hh()).rh())
- }
- n = n - 1
- }
- default:
- }
- }
- p = int32(*(*prg.mem[p].hh()).rh())
- }
- }
- // 176.
- // tangle:pos tex.web:3580:3:
- // The |show_node_list| routine requires some auxiliary subroutines: one to
- // print a font-and-character combination, one to print a token list without
- // its reference count, and one to print a rule dimension.
- func (prg *prg) printFontAndChar(p int32) {
- if p > int32(prg.memEnd) {
- prg.printEsc(strNumber( /* "CLOBBERED." */ 309))
- } else {
- if int32(*(*prg.mem[p].hh()).b0()) < fontBase || int32(*(*prg.mem[p].hh()).b0()) > fontMax {
- prg.printChar(asciiCode('*'))
- } else {
- // Print the font identifier for |font(p)|
- prg.printEsc(*prg.hash[fontIdBase+int32(*(*prg.mem[p].hh()).b0())-514].rh())
- }
- prg.printChar(asciiCode(' '))
- prg.print(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword)
- }
- }
- func (prg *prg) printMark(p int32) {
- prg.printChar(asciiCode('{'))
- if p < int32(prg.hiMemMin) || p > int32(prg.memEnd) {
- prg.printEsc(strNumber( /* "CLOBBERED." */ 309))
- } else {
- prg.showTokenList(int32(*(*prg.mem[p].hh()).rh()), 0, maxPrintLine-10)
- }
- prg.printChar(asciiCode('}'))
- }
- func (prg *prg) printRuleDimen(d scaled) {
- if d == -010000000000 {
- prg.printChar(asciiCode('*'))
- } else {
- prg.printScaled(d)
- }
- // \xref[*\relax]
- }
- // 177.
- // tangle:pos tex.web:3605:3:
- // Then there is a subroutine that prints glue stretch and shrink, possibly
- // followed by the name of finite units:
- func (prg *prg) printGlue(d scaled, order int32, s strNumber) {
- prg.printScaled(d)
- if order < normal || order > filll {
- prg.print( /* "foul" */ 310)
- } else if order > normal {
- prg.print( /* "fil" */ 311)
- for order > fil {
- prg.printChar(asciiCode('l'))
- order = order - 1
- }
- } else if int32(s) != 0 {
- prg.print(int32(s))
- }
- }
- // 178.
- // tangle:pos tex.web:3621:3:
- // The next subroutine prints a whole glue specification.
- func (prg *prg) printSpec(p int32, s strNumber) {
- if p < memMin || p >= int32(prg.loMemMax) {
- prg.printChar(asciiCode('*'))
- } else {
- prg.printScaled(*prg.mem[p+widthOffset].int())
- if int32(s) != 0 {
- prg.print(int32(s))
- }
- if *prg.mem[p+2].int() != 0 {
- prg.print( /* " plus " */ 312)
- prg.printGlue(*prg.mem[p+2].int(), int32(*(*prg.mem[p].hh()).b0()), s)
- }
- if *prg.mem[p+3].int() != 0 {
- prg.print( /* " minus " */ 313)
- prg.printGlue(*prg.mem[p+3].int(), int32(*(*prg.mem[p].hh()).b1()), s)
- }
- }
- }
- // 179.
- // tangle:pos tex.web:3638:3:
- // We also need to declare some procedures that appear later in this
- // documentation.
- // Declare procedures needed for displaying the elements of mlists
- func (prg *prg) printFamAndChar(p halfword) {
- prg.printEsc(strNumber( /* "fam" */ 464))
- prg.printInt(int32(*(*prg.mem[p].hh()).b0()))
- prg.printChar(asciiCode(' '))
- prg.print(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword)
- }
- func (prg *prg) printDelimiter(p halfword) { // prints a delimiter as 24-bit hex value
- var (
- a int32 // accumulator
- )
- a = int32((*prg.mem[p].qqqq()).b0)*256 + int32((*prg.mem[p].qqqq()).b1) - minQuarterword
- a = a*010000 + int32((*prg.mem[p].qqqq()).b2)*256 + int32((*prg.mem[p].qqqq()).b3) - minQuarterword
- if a < 0 {
- prg.printInt(a)
- } else {
- prg.printHex(a)
- }
- } // \2
- // |show_node_list(info(temp_ptr))|
- func (prg *prg) printSubsidiaryData(p halfword, c asciiCode) {
- if int32(prg.poolPtr)-int32(prg.strStart[prg.strPtr]) >= prg.depthThreshold {
- if int32(*(*prg.mem[p].hh()).rh()) != empty {
- prg.print( /* " []" */ 314)
- }
- } else {
- {
- prg.strPool[prg.poolPtr] = c
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- } // include |c| in the recursion history
- prg.tempPtr = p // prepare for |show_info| if recursion is needed
- switch *(*prg.mem[p].hh()).rh() {
- case mathChar:
- prg.printLn()
- prg.printCurrentString()
- prg.printFamAndChar(p)
- case subBox:
- prg.showInfo() // recursive call
- case subMlist:
- if int32(*(*prg.mem[p].hh()).lh()) == 0 {
- prg.printLn()
- prg.printCurrentString()
- prg.print( /* "[]" */ 860)
- } else {
- prg.showInfo()
- }
- // recursive call
- default: // |empty|
- }
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1) // remove |c| from the recursion history
- }
- }
- func (prg *prg) printStyle(c int32) {
- switch c / 2 {
- case 0:
- prg.printEsc(strNumber( /* "displaystyle" */ 861)) // |display_style=0|
- case 1:
- prg.printEsc(strNumber( /* "textstyle" */ 862)) // |text_style=2|
- case 2:
- prg.printEsc(strNumber( /* "scriptstyle" */ 863)) // |script_style=4|
- case 3:
- prg.printEsc(strNumber( /* "scriptscriptstyle" */ 864))
- // |script_script_style=6|
- default:
- prg.print( /* "Unknown style!" */ 865)
- }
- }
- // Declare the procedure called |print_skip_param|
- func (prg *prg) printSkipParam(n int32) {
- switch n {
- case lineSkipCode:
- prg.printEsc(strNumber( /* "lineskip" */ 376))
- case baselineSkipCode:
- prg.printEsc(strNumber( /* "baselineskip" */ 377))
- case parSkipCode:
- prg.printEsc(strNumber( /* "parskip" */ 378))
- case aboveDisplaySkipCode:
- prg.printEsc(strNumber( /* "abovedisplayskip" */ 379))
- case belowDisplaySkipCode:
- prg.printEsc(strNumber( /* "belowdisplayskip" */ 380))
- case aboveDisplayShortSkipCode:
- prg.printEsc(strNumber( /* "abovedisplayshortskip" */ 381))
- case belowDisplayShortSkipCode:
- prg.printEsc(strNumber( /* "belowdisplayshortskip" */ 382))
- case leftSkipCode:
- prg.printEsc(strNumber( /* "leftskip" */ 383))
- case rightSkipCode:
- prg.printEsc(strNumber( /* "rightskip" */ 384))
- case topSkipCode:
- prg.printEsc(strNumber( /* "topskip" */ 385))
- case splitTopSkipCode:
- prg.printEsc(strNumber( /* "splittopskip" */ 386))
- case tabSkipCode:
- prg.printEsc(strNumber( /* "tabskip" */ 387))
- case spaceSkipCode:
- prg.printEsc(strNumber( /* "spaceskip" */ 388))
- case xspaceSkipCode:
- prg.printEsc(strNumber( /* "xspaceskip" */ 389))
- case parFillSkipCode:
- prg.printEsc(strNumber( /* "parfillskip" */ 390))
- case thinMuSkipCode:
- prg.printEsc(strNumber( /* "thinmuskip" */ 391))
- case medMuSkipCode:
- prg.printEsc(strNumber( /* "medmuskip" */ 392))
- case thickMuSkipCode:
- prg.printEsc(strNumber( /* "thickmuskip" */ 393))
- default:
- prg.print( /* "[unknown glue parameter!]" */ 394)
- }
- }
- // 180.
- // tangle:pos tex.web:3644:3:
- // Since boxes can be inside of boxes, |show_node_list| is inherently recursive,
- // \xref[recursion]
- // up to a given maximum number of levels. The history of nesting is indicated
- // by the current string, which will be printed at the beginning of each line;
- // the length of this string, namely |cur_length|, is the depth of nesting.
- //
- // Recursive calls on |show_node_list| therefore use the following pattern:
- // 182.
- // tangle:pos tex.web:3667:3:
- // Now we are ready for |show_node_list| itself. This procedure has been
- // written to be “extra robust” in the sense that it should not crash or get
- // into a loop even if the data structures have been messed up by bugs in
- // the rest of the program. You can safely call its parent routine
- // |show_box(p)| for arbitrary values of |p| when you are debugging \TeX.
- // However, in the presence of bad data, the procedure may
- // \xref[dirty \PASCAL]\xref[debugging]
- // fetch a |memory_word| whose variant is different from the way it was stored;
- // for example, it might try to read |mem[p].hh| when |mem[p]|
- // contains a scaled integer, if |p| is a pointer that has been
- // clobbered or chosen at random.
- func (prg *prg) showNodeList(p int32) {
- var (
- n int32 // the number of items already printed at this level
- g float64 // a glue ratio, as a floating point number
- )
- if int32(prg.poolPtr)-int32(prg.strStart[prg.strPtr]) > prg.depthThreshold {
- if p > 0 {
- prg.print( /* " []" */ 314)
- }
- // indicate that there's been some truncation
- // indicate that there's been some truncation
- goto exit
- }
- n = 0
- for p > memMin {
- prg.printLn()
- prg.printCurrentString() // display the nesting history
- if p > int32(prg.memEnd) {
- prg.print( /* "Bad link, display aborted." */ 315)
- goto exit
- // \xref[Bad link...]
- }
- n = n + 1
- if n > prg.breadthMax {
- prg.print( /* "etc." */ 316)
- goto exit
- // \xref[etc]
- }
- // Display node |p|
- if p >= int32(prg.hiMemMin) {
- prg.printFontAndChar(p)
- } else {
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, unsetNode:
- // Display box |p|
- if int32(*(*prg.mem[p].hh()).b0()) == hlistNode {
- prg.printEsc(strNumber('h'))
- } else if int32(*(*prg.mem[p].hh()).b0()) == vlistNode {
- prg.printEsc(strNumber('v'))
- } else {
- prg.printEsc(strNumber( /* "unset" */ 318))
- }
- prg.print( /* "box(" */ 319)
- prg.printScaled(*prg.mem[p+heightOffset].int())
- prg.printChar(asciiCode('+'))
- prg.printScaled(*prg.mem[p+depthOffset].int())
- prg.print( /* ")x" */ 320)
- prg.printScaled(*prg.mem[p+widthOffset].int())
- if int32(*(*prg.mem[p].hh()).b0()) == unsetNode {
- if int32(*(*prg.mem[p].hh()).b1()) != minQuarterword {
- prg.print( /* " (" */ 286)
- prg.printInt(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword + 1)
- prg.print( /* " columns)" */ 322)
- }
- if *prg.mem[p+glueOffset].int() != 0 {
- prg.print( /* ", stretch " */ 323)
- prg.printGlue(*prg.mem[p+glueOffset].int(), int32(*(*prg.mem[p+listOffset].hh()).b1()), strNumber(0))
- }
- if *prg.mem[p+4].int() != 0 {
- prg.print( /* ", shrink " */ 324)
- prg.printGlue(*prg.mem[p+4].int(), int32(*(*prg.mem[p+listOffset].hh()).b0()), strNumber(0))
- }
- } else {
- g = float64(*prg.mem[p+glueOffset].gr())
- if g != 0.0 && int32(*(*prg.mem[p+listOffset].hh()).b0()) != normal {
- prg.print( /* ", glue set " */ 325)
- if int32(*(*prg.mem[p+listOffset].hh()).b0()) == shrinking {
- prg.print( /* "- " */ 326)
- }
- if abs(*prg.mem[p+glueOffset].int()) < 04000000 {
- prg.print( /* "?.?" */ 327)
- } else if fabs(g) > 20000.0 {
- if g > 0.0 {
- prg.printChar(asciiCode('>'))
- } else {
- prg.print( /* "< -" */ 328)
- }
- prg.printGlue(20000*0200000, int32(*(*prg.mem[p+listOffset].hh()).b1()), strNumber(0))
- } else {
- prg.printGlue(round(float64(0200000)*g), int32(*(*prg.mem[p+listOffset].hh()).b1()), strNumber(0))
- }
- // \xref[real multiplication]
- }
- if *prg.mem[p+4].int() != 0 {
- prg.print( /* ", shifted " */ 321)
- prg.printScaled(*prg.mem[p+4].int())
- }
- }
- {
- {
- prg.strPool[prg.poolPtr] = '.'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(int32(*(*prg.mem[p+listOffset].hh()).rh()))
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- } // recursive call
- case ruleNode:
- // Display rule |p|
- prg.printEsc(strNumber( /* "rule(" */ 329))
- prg.printRuleDimen(*prg.mem[p+heightOffset].int())
- prg.printChar(asciiCode('+'))
- prg.printRuleDimen(*prg.mem[p+depthOffset].int())
- prg.print( /* ")x" */ 320)
- prg.printRuleDimen(*prg.mem[p+widthOffset].int())
- case insNode:
- // Display insertion |p|
- prg.printEsc(strNumber( /* "insert" */ 330))
- prg.printInt(int32(*(*prg.mem[p].hh()).b1()) - minQuarterword)
- prg.print( /* ", natural size " */ 331)
- prg.printScaled(*prg.mem[p+heightOffset].int())
- prg.print( /* "; split(" */ 332)
- prg.printSpec(int32(*(*prg.mem[p+4].hh()).rh()), strNumber(0))
- prg.printChar(asciiCode(','))
- prg.printScaled(*prg.mem[p+depthOffset].int())
- prg.print( /* "); float cost " */ 333)
- prg.printInt(*prg.mem[p+1].int())
- {
- {
- prg.strPool[prg.poolPtr] = '.'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(int32(*(*prg.mem[p+4].hh()).lh()))
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- } // recursive call
- case whatsitNode:
- // Display the whatsit node |p|
- switch *(*prg.mem[p].hh()).b1() {
- case openNode:
- prg.printWriteWhatsit(strNumber( /* "openout" */ 1285), halfword(p))
- prg.printChar(asciiCode('='))
- prg.printFileName(int32(*(*prg.mem[p+1].hh()).rh()), int32(*(*prg.mem[p+2].hh()).lh()), int32(*(*prg.mem[p+2].hh()).rh()))
- case writeNode:
- prg.printWriteWhatsit(strNumber( /* "write" */ 594), halfword(p))
- prg.printMark(int32(*(*prg.mem[p+1].hh()).rh()))
- case closeNode:
- prg.printWriteWhatsit(strNumber( /* "closeout" */ 1286), halfword(p))
- case specialNode:
- prg.printEsc(strNumber( /* "special" */ 1287))
- prg.printMark(int32(*(*prg.mem[p+1].hh()).rh()))
- case languageNode:
- prg.printEsc(strNumber( /* "setlanguage" */ 1289))
- prg.printInt(int32(*(*prg.mem[p+1].hh()).rh()))
- prg.print( /* " (hyphenmin " */ 1292)
- prg.printInt(int32(*(*prg.mem[p+1].hh()).b0()))
- prg.printChar(asciiCode(','))
- prg.printInt(int32(*(*prg.mem[p+1].hh()).b1()))
- prg.printChar(asciiCode(')'))
- default:
- prg.print( /* "whatsit?" */ 1293)
- }
- case glueNode:
- // Display glue |p|
- if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
- prg.printEsc(strNumber( /* "" */ 338))
- if int32(*(*prg.mem[p].hh()).b1()) == cLeaders {
- prg.printChar(asciiCode('c'))
- } else if int32(*(*prg.mem[p].hh()).b1()) == xLeaders {
- prg.printChar(asciiCode('x'))
- }
- prg.print( /* "leaders " */ 339)
- prg.printSpec(int32(*(*prg.mem[p+1].hh()).lh()), strNumber(0))
- {
- {
- prg.strPool[prg.poolPtr] = '.'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(int32(*(*prg.mem[p+1].hh()).rh()))
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- } // recursive call
- } else {
- prg.printEsc(strNumber( /* "glue" */ 334))
- if int32(*(*prg.mem[p].hh()).b1()) != normal {
- prg.printChar(asciiCode('('))
- if int32(*(*prg.mem[p].hh()).b1()) < condMathGlue {
- prg.printSkipParam(int32(*(*prg.mem[p].hh()).b1()) - 1)
- } else if int32(*(*prg.mem[p].hh()).b1()) == condMathGlue {
- prg.printEsc(strNumber( /* "nonscript" */ 335))
- } else {
- prg.printEsc(strNumber( /* "mskip" */ 336))
- }
- prg.printChar(asciiCode(')'))
- }
- if int32(*(*prg.mem[p].hh()).b1()) != condMathGlue {
- prg.printChar(asciiCode(' '))
- if int32(*(*prg.mem[p].hh()).b1()) < condMathGlue {
- prg.printSpec(int32(*(*prg.mem[p+1].hh()).lh()), strNumber(0))
- } else {
- prg.printSpec(int32(*(*prg.mem[p+1].hh()).lh()), strNumber( /* "mu" */ 337))
- }
- }
- }
- case kernNode:
- // Display kern |p|
- if int32(*(*prg.mem[p].hh()).b1()) != muGlue {
- prg.printEsc(strNumber( /* "kern" */ 340))
- if int32(*(*prg.mem[p].hh()).b1()) != normal {
- prg.printChar(asciiCode(' '))
- }
- prg.printScaled(*prg.mem[p+widthOffset].int())
- if int32(*(*prg.mem[p].hh()).b1()) == accKern {
- prg.print( /* " (for accent)" */ 341)
- }
- // \xref[for accent]
- } else {
- prg.printEsc(strNumber( /* "mkern" */ 342))
- prg.printScaled(*prg.mem[p+widthOffset].int())
- prg.print( /* "mu" */ 337)
- }
- case mathNode:
- // Display math node |p|
- prg.printEsc(strNumber( /* "math" */ 343))
- if int32(*(*prg.mem[p].hh()).b1()) == before {
- prg.print( /* "on" */ 344)
- } else {
- prg.print( /* "off" */ 345)
- }
- if *prg.mem[p+widthOffset].int() != 0 {
- prg.print( /* ", surrounded " */ 346)
- prg.printScaled(*prg.mem[p+widthOffset].int())
- }
- case ligatureNode:
- // Display ligature |p|
- prg.printFontAndChar(p + 1)
- prg.print( /* " (ligature " */ 347)
- if int32(*(*prg.mem[p].hh()).b1()) > 1 {
- prg.printChar(asciiCode('|'))
- }
- prg.fontInShortDisplay = int32(*(*prg.mem[p+1].hh()).b0())
- prg.shortDisplay(int32(*(*prg.mem[p+1].hh()).rh()))
- if *(*prg.mem[p].hh()).b1()&1 != 0 {
- prg.printChar(asciiCode('|'))
- }
- prg.printChar(asciiCode(')'))
- case penaltyNode:
- // Display penalty |p|
- prg.printEsc(strNumber( /* "penalty " */ 348))
- prg.printInt(*prg.mem[p+1].int())
- case discNode:
- // Display discretionary |p|
- prg.printEsc(strNumber( /* "discretionary" */ 349))
- if int32(*(*prg.mem[p].hh()).b1()) > 0 {
- prg.print( /* " replacing " */ 350)
- prg.printInt(int32(*(*prg.mem[p].hh()).b1()))
- }
- {
- {
- prg.strPool[prg.poolPtr] = '.'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(int32(*(*prg.mem[p+1].hh()).lh()))
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- } // recursive call
- {
- prg.strPool[prg.poolPtr] = '|'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(int32(*(*prg.mem[p+1].hh()).rh()))
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1) // recursive call
- case markNode:
- // Display mark |p|
- prg.printEsc(strNumber( /* "mark" */ 351))
- prg.printMark(*prg.mem[p+1].int())
- case adjustNode:
- // Display adjustment |p|
- prg.printEsc(strNumber( /* "vadjust" */ 352))
- {
- {
- prg.strPool[prg.poolPtr] = '.'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(*prg.mem[p+1].int())
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- } // recursive call
- // \4
- // Cases of |show_node_list| that arise in mlists only
- case styleNode:
- prg.printStyle(int32(*(*prg.mem[p].hh()).b1()))
- case choiceNode:
- // Display choice node |p|
- prg.printEsc(strNumber( /* "mathchoice" */ 525))
- {
- prg.strPool[prg.poolPtr] = 'D'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(int32(*(*prg.mem[p+1].hh()).lh()))
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- {
- prg.strPool[prg.poolPtr] = 'T'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(int32(*(*prg.mem[p+1].hh()).rh()))
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- {
- prg.strPool[prg.poolPtr] = 'S'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(int32(*(*prg.mem[p+2].hh()).lh()))
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- {
- prg.strPool[prg.poolPtr] = 's'
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- prg.showNodeList(int32(*(*prg.mem[p+2].hh()).rh()))
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- case ordNoad, opNoad, binNoad, relNoad,
- openNoad, closeNoad, punctNoad, innerNoad,
- radicalNoad, overNoad, underNoad, vcenterNoad,
- accentNoad, leftNoad, rightNoad:
- // Display normal noad |p|
- switch *(*prg.mem[p].hh()).b0() {
- case ordNoad:
- prg.printEsc(strNumber( /* "mathord" */ 866))
- case opNoad:
- prg.printEsc(strNumber( /* "mathop" */ 867))
- case binNoad:
- prg.printEsc(strNumber( /* "mathbin" */ 868))
- case relNoad:
- prg.printEsc(strNumber( /* "mathrel" */ 869))
- case openNoad:
- prg.printEsc(strNumber( /* "mathopen" */ 870))
- case closeNoad:
- prg.printEsc(strNumber( /* "mathclose" */ 871))
- case punctNoad:
- prg.printEsc(strNumber( /* "mathpunct" */ 872))
- case innerNoad:
- prg.printEsc(strNumber( /* "mathinner" */ 873))
- case overNoad:
- prg.printEsc(strNumber( /* "overline" */ 874))
- case underNoad:
- prg.printEsc(strNumber( /* "underline" */ 875))
- case vcenterNoad:
- prg.printEsc(strNumber( /* "vcenter" */ 539))
- case radicalNoad:
- prg.printEsc(strNumber( /* "radical" */ 533))
- prg.printDelimiter(halfword(p + 4))
- case accentNoad:
- prg.printEsc(strNumber( /* "accent" */ 508))
- prg.printFamAndChar(halfword(p + 4))
- case leftNoad:
- prg.printEsc(strNumber( /* "left" */ 876))
- prg.printDelimiter(halfword(p + 1))
- case rightNoad:
- prg.printEsc(strNumber( /* "right" */ 877))
- prg.printDelimiter(halfword(p + 1))
- }
- if int32(*(*prg.mem[p].hh()).b1()) != normal {
- if int32(*(*prg.mem[p].hh()).b1()) == limits {
- prg.printEsc(strNumber( /* "limits" */ 878))
- } else {
- prg.printEsc(strNumber( /* "nolimits" */ 879))
- }
- }
- if int32(*(*prg.mem[p].hh()).b0()) < leftNoad {
- prg.printSubsidiaryData(halfword(p+1), asciiCode('.'))
- }
- prg.printSubsidiaryData(halfword(p+2), asciiCode('^'))
- prg.printSubsidiaryData(halfword(p+3), asciiCode('_'))
- case fractionNoad:
- // Display fraction noad |p|
- prg.printEsc(strNumber( /* "fraction, thickness " */ 880))
- if *prg.mem[p+widthOffset].int() == 010000000000 {
- prg.print( /* "= default" */ 881)
- } else {
- prg.printScaled(*prg.mem[p+widthOffset].int())
- }
- if int32((*prg.mem[p+4].qqqq()).b0) != 0 || int32((*prg.mem[p+4].qqqq()).b1) != minQuarterword || int32((*prg.mem[p+4].qqqq()).b2) != 0 || int32((*prg.mem[p+4].qqqq()).b3) != minQuarterword {
- prg.print( /* ", left-delimiter " */ 882)
- prg.printDelimiter(halfword(p + 4))
- }
- if int32((*prg.mem[p+5].qqqq()).b0) != 0 || int32((*prg.mem[p+5].qqqq()).b1) != minQuarterword || int32((*prg.mem[p+5].qqqq()).b2) != 0 || int32((*prg.mem[p+5].qqqq()).b3) != minQuarterword {
- prg.print( /* ", right-delimiter " */ 883)
- prg.printDelimiter(halfword(p + 5))
- }
- prg.printSubsidiaryData(halfword(p+2), asciiCode('\\'))
- prg.printSubsidiaryData(halfword(p+3), asciiCode('/'))
- default:
- prg.print( /* "Unknown node type!" */ 317)
- }
- }
- p = int32(*(*prg.mem[p].hh()).rh())
- }
- exit:
- }
- // 198.
- // tangle:pos tex.web:3872:3:
- // The recursive machinery is started by calling |show_box|.
- // \xref[recursion]
- func (prg *prg) showBox(p halfword) {
- prg.depthThreshold = *prg.eqtb[intBase+showBoxDepthCode-1].int()
- prg.breadthMax = *prg.eqtb[intBase+showBoxBreadthCode-1].int()
- if prg.breadthMax <= 0 {
- prg.breadthMax = 5
- }
- if int32(prg.poolPtr)+prg.depthThreshold >= poolSize {
- prg.depthThreshold = poolSize - int32(prg.poolPtr) - 1
- }
- // now there's enough room for prefix string
- prg.showNodeList(int32(p)) // the show starts at |p|
- prg.printLn()
- }
- // 199. \[13] Destroying boxes
- // tangle:pos tex.web:3886:27:
- // When we are done with a node list, we are obliged to return it to free
- // storage, including all of its sublists. The recursive procedure
- // |flush_node_list| does this for us.
- // 200.
- // tangle:pos tex.web:3891:3:
- // First, however, we shall consider two non-recursive procedures that do
- // simpler tasks. The first of these, |delete_token_ref|, is called when
- // a pointer to a token list's reference count is being removed. This means
- // that the token list should disappear if the reference count was |null|,
- // otherwise the count should be decreased by one.
- // \xref[reference counts]
- func (prg *prg) deleteTokenRef(p halfword) {
- if int32(*(*prg.mem[p].hh()).lh()) == 0 {
- prg.flushList(p)
- } else {
- *(*prg.mem[p].hh()).lh() = uint16(int32(*(*prg.mem[p].hh()).lh()) - 1)
- }
- }
- // 201.
- // tangle:pos tex.web:3906:3:
- // Similarly, |delete_glue_ref| is called when a pointer to a glue
- // specification is being withdrawn.
- // \xref[reference counts]
- func (prg *prg) deleteGlueRef(p halfword) {
- if int32(*(*prg.mem[p].hh()).rh()) == 0 {
- prg.freeNode(p, halfword(glueSpecSize))
- } else {
- *(*prg.mem[p].hh()).rh() = uint16(int32(*(*prg.mem[p].hh()).rh()) - 1)
- }
- }
- // 202.
- // tangle:pos tex.web:3917:3:
- // Now we are ready to delete any node list, recursively.
- // In practice, the nodes deleted are usually charnodes (about 2/3 of the time),
- // and they are glue nodes in about half of the remaining cases.
- // \xref[recursion]
- func (prg *prg) flushNodeList(p halfword) { // go here when node |p| has been freed
- var (
- q halfword // successor to node |p|
- )
- for int32(p) != 0 {
- // \xref[inner loop]
- q = *(*prg.mem[p].hh()).rh()
- if int32(p) >= int32(prg.hiMemMin) {
- *(*prg.mem[p].hh()).rh() = prg.avail
- prg.avail = p /* dyn_used:= dyn_used-1 ; [ ] */
- } else {
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, unsetNode:
- prg.flushNodeList(*(*prg.mem[int32(p)+listOffset].hh()).rh())
- prg.freeNode(p, halfword(boxNodeSize))
- goto done
- case ruleNode:
- prg.freeNode(p, halfword(ruleNodeSize))
- goto done
- case insNode:
- prg.flushNodeList(*(*prg.mem[int32(p)+4].hh()).lh())
- prg.deleteGlueRef(*(*prg.mem[int32(p)+4].hh()).rh())
- prg.freeNode(p, halfword(insNodeSize))
- goto done
- case whatsitNode:
- // Wipe out the whatsit node |p| and |goto done|
- switch *(*prg.mem[p].hh()).b1() {
- case openNode:
- prg.freeNode(p, halfword(openNodeSize))
- case writeNode, specialNode:
- prg.deleteTokenRef(*(*prg.mem[int32(p)+1].hh()).rh())
- prg.freeNode(p, halfword(writeNodeSize))
- goto done
- case closeNode, languageNode:
- prg.freeNode(p, halfword(smallNodeSize))
- default:
- prg.confusion(strNumber( /* "ext3" */ 1295))
- // \xref[this can't happen ext3][\quad ext3]
- }
- goto done
- case glueNode:
- {
- if int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh()) == 0 {
- prg.freeNode(*(*prg.mem[int32(p)+1].hh()).lh(), halfword(glueSpecSize))
- } else {
- *(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh() = uint16(int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh()) - 1)
- }
- }
- if int32(*(*prg.mem[int32(p)+1].hh()).rh()) != 0 {
- prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
- }
- case kernNode, mathNode, penaltyNode:
- case ligatureNode:
- prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
- case markNode:
- prg.deleteTokenRef(halfword(*prg.mem[int32(p)+1].int()))
- case discNode:
- prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).lh())
- prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
- case adjustNode:
- prg.flushNodeList(halfword(*prg.mem[int32(p)+1].int()))
- // \4
- // Cases of |flush_node_list| that arise in mlists only
- case styleNode:
- prg.freeNode(p, halfword(styleNodeSize))
- goto done
- case choiceNode:
- prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).lh())
- prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
- prg.flushNodeList(*(*prg.mem[int32(p)+2].hh()).lh())
- prg.flushNodeList(*(*prg.mem[int32(p)+2].hh()).rh())
- prg.freeNode(p, halfword(styleNodeSize))
- goto done
- case ordNoad, opNoad, binNoad, relNoad,
- openNoad, closeNoad, punctNoad, innerNoad,
- radicalNoad, overNoad, underNoad, vcenterNoad,
- accentNoad: //
- if int32(*(*prg.mem[int32(p)+1].hh()).rh()) >= subBox {
- prg.flushNodeList(*(*prg.mem[int32(p)+1].hh()).lh())
- }
- if int32(*(*prg.mem[int32(p)+2].hh()).rh()) >= subBox {
- prg.flushNodeList(*(*prg.mem[int32(p)+2].hh()).lh())
- }
- if int32(*(*prg.mem[int32(p)+3].hh()).rh()) >= subBox {
- prg.flushNodeList(*(*prg.mem[int32(p)+3].hh()).lh())
- }
- if int32(*(*prg.mem[p].hh()).b0()) == radicalNoad {
- prg.freeNode(p, halfword(radicalNoadSize))
- } else if int32(*(*prg.mem[p].hh()).b0()) == accentNoad {
- prg.freeNode(p, halfword(accentNoadSize))
- } else {
- prg.freeNode(p, halfword(noadSize))
- }
- goto done
- case leftNoad, rightNoad:
- prg.freeNode(p, halfword(noadSize))
- goto done
- case fractionNoad:
- prg.flushNodeList(*(*prg.mem[int32(p)+2].hh()).lh())
- prg.flushNodeList(*(*prg.mem[int32(p)+3].hh()).lh())
- prg.freeNode(p, halfword(fractionNoadSize))
- goto done
- default:
- prg.confusion(strNumber( /* "flushing" */ 353))
- // \xref[this can't happen flushing][\quad flushing]
- }
- prg.freeNode(p, halfword(smallNodeSize))
- done:
- }
- p = q
- }
- }
- // 203. \[14] Copying boxes
- // tangle:pos tex.web:3960:24:
- // Another recursive operation that acts on boxes is sometimes needed: The
- // procedure |copy_node_list| returns a pointer to another node list that has
- // the same structure and meaning as the original. Note that since glue
- // specifications and token lists have reference counts, we need not make
- // copies of them. Reference counts can never get too large to fit in a
- // halfword, since each pointer to a node is in a different memory address,
- // and the total number of memory addresses fits in a halfword.
- // \xref[recursion]
- // \xref[reference counts]
- //
- // (Well, there actually are also references from outside |mem|; if the
- // |save_stack| is made arbitrarily large, it would theoretically be possible
- // to break \TeX\ by overflowing a reference count. But who would want to do that?)
- // 204.
- // tangle:pos tex.web:3978:3:
- // The copying procedure copies words en masse without bothering
- // to look at their individual fields. If the node format changes---for
- // example, if the size is altered, or if some link field is moved to another
- // relative position---then this code may need to be changed too.
- // \xref[data structure assumptions]
- func (prg *prg) copyNodeList(p halfword) (r halfword) { // makes a duplicate of the
- // node list that starts at |p| and returns a pointer to the new list
- var (
- h halfword // temporary head of copied list
- q halfword // previous position in new list
- r1 halfword // current node being fabricated for new list
- words/* 0..5 */ byte // number of words remaining to be copied
- )
- h = prg.getAvail()
- q = h
- for int32(p) != 0 {
- words = 1 // this setting occurs in more branches than any other
- if int32(p) >= int32(prg.hiMemMin) {
- r1 = prg.getAvail()
- } else {
- // Case statement to copy different types and set |words| to the number of initial words not yet copied
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, unsetNode:
- r1 = prg.getNode(boxNodeSize)
- prg.mem[int32(r1)+6] = prg.mem[int32(p)+6]
- prg.mem[int32(r1)+5] = prg.mem[int32(p)+5] // copy the last two words
- *(*prg.mem[int32(r1)+listOffset].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+listOffset].hh()).rh()) // this affects |mem[r+5]|
- words = 5
- case ruleNode:
- r1 = prg.getNode(ruleNodeSize)
- words = byte(ruleNodeSize)
- case insNode:
- r1 = prg.getNode(insNodeSize)
- prg.mem[int32(r1)+4] = prg.mem[int32(p)+4]
- *(*prg.mem[*(*prg.mem[int32(p)+4].hh()).rh()].hh()).rh() = uint16(int32(*(*prg.mem[*(*prg.mem[int32(p)+4].hh()).rh()].hh()).rh()) + 1)
- *(*prg.mem[int32(r1)+4].hh()).lh() = prg.copyNodeList(*(*prg.mem[int32(p)+4].hh()).lh()) // this affects |mem[r+4]|
- words = byte(insNodeSize - 1)
- case whatsitNode:
- // Make a partial copy of the whatsit node |p| and make |r| point to it; set |words| to the number of initial words not yet copied
- switch *(*prg.mem[p].hh()).b1() {
- case openNode:
- r1 = prg.getNode(openNodeSize)
- words = byte(openNodeSize)
- case writeNode, specialNode:
- r1 = prg.getNode(writeNodeSize)
- *(*prg.mem[*(*prg.mem[int32(p)+1].hh()).rh()].hh()).lh() = uint16(int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).rh()].hh()).lh()) + 1)
- words = byte(writeNodeSize)
- case closeNode, languageNode:
- r1 = prg.getNode(smallNodeSize)
- words = byte(smallNodeSize)
- default:
- prg.confusion(strNumber( /* "ext2" */ 1294))
- // \xref[this can't happen ext2][\quad ext2]
- }
- case glueNode:
- r1 = prg.getNode(smallNodeSize)
- *(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh() = uint16(int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).lh()].hh()).rh()) + 1)
- *(*prg.mem[int32(r1)+1].hh()).lh() = *(*prg.mem[int32(p)+1].hh()).lh()
- *(*prg.mem[int32(r1)+1].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
- case kernNode, mathNode, penaltyNode:
- r1 = prg.getNode(smallNodeSize)
- words = byte(smallNodeSize)
- case ligatureNode:
- r1 = prg.getNode(smallNodeSize)
- prg.mem[int32(r1)+1] = prg.mem[int32(p)+1] // copy |font| and |character|
- *(*prg.mem[int32(r1)+1].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
- case discNode:
- r1 = prg.getNode(smallNodeSize)
- *(*prg.mem[int32(r1)+1].hh()).lh() = prg.copyNodeList(*(*prg.mem[int32(p)+1].hh()).lh())
- *(*prg.mem[int32(r1)+1].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+1].hh()).rh())
- case markNode:
- r1 = prg.getNode(smallNodeSize)
- *(*prg.mem[*prg.mem[int32(p)+1].int()].hh()).lh() = uint16(int32(*(*prg.mem[*prg.mem[int32(p)+1].int()].hh()).lh()) + 1)
- words = byte(smallNodeSize)
- case adjustNode:
- r1 = prg.getNode(smallNodeSize)
- *prg.mem[int32(r1)+1].int() = int32(prg.copyNodeList(halfword(*prg.mem[int32(p)+1].int())))
- // |words=1=small_node_size-1|
- default:
- prg.confusion(strNumber( /* "copying" */ 354))
- // \xref[this can't happen copying][\quad copying]
- }
- }
- for int32(words) > 0 {
- words = byte(int32(words) - 1)
- prg.mem[int32(r1)+int32(words)] = prg.mem[int32(p)+int32(words)]
- }
- *(*prg.mem[q].hh()).rh() = r1
- q = r1
- p = *(*prg.mem[p].hh()).rh()
- }
- *(*prg.mem[q].hh()).rh() = 0
- q = *(*prg.mem[h].hh()).rh()
- {
- *(*prg.mem[h].hh()).rh() = prg.avail
- prg.avail = h /* dyn_used:= dyn_used-1 ; [ ] */
- }
- r = q
- return r
- }
- // 207. \[15] The command codes
- // tangle:pos tex.web:4048:28:
- // Before we can go any further, we need to define symbolic names for the internal
- // code numbers that represent the various commands obeyed by \TeX. These codes
- // are somewhat arbitrary, but not completely so. For example, the command
- // codes for character types are fixed by the language, since a user says,
- // e.g., `\.[\\catcode \`\\\$[] = 3]' to make \.[\char'44] a math delimiter,
- // and the command code |math_shift| is equal to~3. Some other codes have
- // been made adjacent so that |case| statements in the program need not consider
- // cases that are widely spaced, or so that |case| statements can be replaced
- // by |if| statements.
- //
- // At any rate, here is the list, for future reference. First come the
- // ``catcode'' commands, several of which share their numeric codes with
- // ordinary commands when the catcode cannot emerge from \TeX's scanning routine.
- // 208.
- // tangle:pos tex.web:4090:3:
- // Next are the ordinary run-of-the-mill command codes. Codes that are
- // |min_internal| or more represent internal quantities that might be
- // expanded by `\.[\\the]'.
- // 209.
- // tangle:pos tex.web:4154:3:
- // The next codes are special; they all relate to mode-independent
- // assignment of values to \TeX's internal registers or tables.
- // Codes that are |max_internal| or less represent internal quantities
- // that might be expanded by `\.[\\the]'.
- // 210.
- // tangle:pos tex.web:4194:3:
- // The remaining command codes are extra special, since they cannot get through
- // \TeX's scanner to the main control routine. They have been given values higher
- // than |max_command| so that their special nature is easily discernible.
- // The ``expandable'' commands come first.
- // 211. \[16] The semantic nest
- // tangle:pos tex.web:4220:28:
- // \TeX\ is typically in the midst of building many lists at once. For example,
- // when a math formula is being processed, \TeX\ is in math mode and
- // working on an mlist; this formula has temporarily interrupted \TeX\ from
- // being in horizontal mode and building the hlist of a paragraph; and this
- // paragraph has temporarily interrupted \TeX\ from being in vertical mode
- // and building the vlist for the next page of a document. Similarly, when a
- // \.[\\vbox] occurs inside of an \.[\\hbox], \TeX\ is temporarily
- // interrupted from working in restricted horizontal mode, and it enters
- // internal vertical mode. The “semantic nest” is a stack that
- // keeps track of what lists and modes are currently suspended.
- //
- // At each level of processing we are in one of six modes:
- //
- // \yskip\hang|vmode| stands for vertical mode (the page builder);
- //
- // \hang|hmode| stands for horizontal mode (the paragraph builder);
- //
- // \hang|mmode| stands for displayed formula mode;
- //
- // \hang|-vmode| stands for internal vertical mode (e.g., in a \.[\\vbox]);
- //
- // \hang|-hmode| stands for restricted horizontal mode (e.g., in an \.[\\hbox]);
- //
- // \hang|-mmode| stands for math formula mode (not displayed).
- //
- // \yskip\noindent The mode is temporarily set to zero while processing \.[\\write]
- // texts.
- //
- // Numeric values are assigned to |vmode|, |hmode|, and |mmode| so that
- // \TeX's “big semantic switch” can select the appropriate thing to
- // do by computing the value |abs(mode)+cur_cmd|, where |mode| is the current
- // mode and |cur_cmd| is the current command code.
- func (prg *prg) printMode(m int32) {
- if m > 0 {
- switch m / (maxCommand + 1) {
- case 0:
- prg.print( /* "vertical" */ 355)
- case 1:
- prg.print( /* "horizontal" */ 356)
- case 2:
- prg.print( /* "display math" */ 357)
- }
- } else if m == 0 {
- prg.print( /* "no" */ 358)
- } else {
- switch -m / (maxCommand + 1) {
- case 0:
- prg.print( /* "internal vertical" */ 359)
- case 1:
- prg.print( /* "restricted horizontal" */ 360)
- case 2:
- prg.print( /* "math" */ 343)
- }
- }
- prg.print( /* " mode" */ 361)
- }
- // 214.
- // tangle:pos tex.web:4348:3:
- // Here is a common way to make the current list grow:
- // 216.
- // tangle:pos tex.web:4368:3:
- // When \TeX's work on one level is interrupted, the state is saved by
- // calling |push_nest|. This routine changes |head| and |tail| so that
- // a new (empty) list is begun; it does not change |mode| or |aux|.
- func (prg *prg) pushNest() {
- if int32(prg.nestPtr) > int32(prg.maxNestStack) {
- prg.maxNestStack = prg.nestPtr
- if int32(prg.nestPtr) == nestSize {
- prg.overflow(strNumber( /* "semantic nest size" */ 362), nestSize)
- }
- // \xref[TeX capacity exceeded semantic nest size][\quad semantic nest size]
- }
- prg.nest[prg.nestPtr] = prg.curList // stack the record
- prg.nestPtr = byte(int32(prg.nestPtr) + 1)
- prg.curList.headField = prg.getAvail()
- prg.curList.tailField = prg.curList.headField
- prg.curList.pgField = 0
- prg.curList.mlField = prg.line
- }
- // 217.
- // tangle:pos tex.web:4382:3:
- // Conversely, when \TeX\ is finished on the current level, the former
- // state is restored by calling |pop_nest|. This routine will never be
- // called at the lowest semantic level, nor will it be called unless |head|
- // is a node that should be returned to free memory.
- func (prg *prg) popNest() {
- {
- *(*prg.mem[prg.curList.headField].hh()).rh() = prg.avail
- prg.avail = prg.curList.headField /* dyn_used:= dyn_used-1 ; [ ] */
- }
- prg.nestPtr = byte(int32(prg.nestPtr) - 1)
- prg.curList = prg.nest[prg.nestPtr]
- } // \2
- func (prg *prg) showActivities() {
- var (
- p/* 0..nestSize */ byte // index into |nest|
- m/* -mmode..mmode */ int16 // mode
- a memoryWord // auxiliary
- q, r1 halfword // for showing the current page
- t int32 // ditto
- )
- prg.nest[prg.nestPtr] = prg.curList // put the top level into the array
- prg.printNl(strNumber( /* "" */ 338))
- prg.printLn()
- for ii := int32(prg.nestPtr); ii >= 0; ii-- {
- p = byte(ii)
- _ = p
- m = prg.nest[p].modeField
- a = prg.nest[p].auxField
- prg.printNl(strNumber( /* "### " */ 363))
- prg.printMode(int32(m))
- prg.print( /* " entered at line " */ 364)
- prg.printInt(abs(prg.nest[p].mlField))
- if int32(m) == hmode {
- if prg.nest[p].pgField != 040600000 {
- prg.print( /* " (language" */ 365)
- prg.printInt(prg.nest[p].pgField % 0200000)
- prg.print( /* ":hyphenmin" */ 366)
- prg.printInt(prg.nest[p].pgField / 020000000)
- prg.printChar(asciiCode(','))
- prg.printInt(prg.nest[p].pgField / 0200000 % 0100)
- prg.printChar(asciiCode(')'))
- }
- }
- if prg.nest[p].mlField < 0 {
- prg.print( /* " (\\output routine)" */ 367)
- }
- if int32(p) == 0 {
- if 30000-2 != int32(prg.pageTail) {
- prg.printNl(strNumber( /* "### current page:" */ 980))
- if prg.outputActive {
- prg.print( /* " (held over for next output)" */ 981)
- }
- // \xref[held over for next output]
- prg.showBox(*(*prg.mem[30000-2].hh()).rh())
- if int32(prg.pageContents) > empty {
- prg.printNl(strNumber( /* "total height " */ 982))
- prg.printTotals()
- // \xref[total_height][\.[total height]]
- prg.printNl(strNumber( /* " goal height " */ 983))
- prg.printScaled(prg.pageSoFar[0])
- // \xref[goal height]
- r1 = *(*prg.mem[30000].hh()).rh()
- for int32(r1) != 30000 {
- prg.printLn()
- prg.printEsc(strNumber( /* "insert" */ 330))
- t = int32(*(*prg.mem[r1].hh()).b1()) - minQuarterword
- prg.printInt(t)
- prg.print( /* " adds " */ 984)
- if *prg.eqtb[countBase+t-1].int() == 1000 {
- t = *prg.mem[int32(r1)+heightOffset].int()
- } else {
- t = prg.xOverN(*prg.mem[int32(r1)+heightOffset].int(), 1000) * *prg.eqtb[countBase+t-1].int()
- }
- prg.printScaled(t)
- if int32(*(*prg.mem[r1].hh()).b0()) == splitUp {
- q = uint16(30000 - 2)
- t = 0
- for {
- q = *(*prg.mem[q].hh()).rh()
- if int32(*(*prg.mem[q].hh()).b0()) == insNode && int32(*(*prg.mem[q].hh()).b1()) == int32(*(*prg.mem[r1].hh()).b1()) {
- t = t + 1
- }
- if int32(q) == int32(*(*prg.mem[int32(r1)+1].hh()).lh()) {
- break
- }
- }
- prg.print( /* ", #" */ 985)
- prg.printInt(t)
- prg.print( /* " might split" */ 986)
- }
- r1 = *(*prg.mem[r1].hh()).rh()
- }
- }
- }
- if int32(*(*prg.mem[30000-1].hh()).rh()) != 0 {
- prg.printNl(strNumber( /* "### recent contributions:" */ 368))
- }
- }
- prg.showBox(*(*prg.mem[prg.nest[p].headField].hh()).rh())
- // Show the auxiliary field, |a|
- switch abs(int32(m)) / (maxCommand + 1) {
- case 0:
- prg.printNl(strNumber( /* "prevdepth " */ 369))
- if *a.int() <= -65536000 {
- prg.print( /* "ignored" */ 370)
- } else {
- prg.printScaled(*a.int())
- }
- if prg.nest[p].pgField != 0 {
- prg.print( /* ", prevgraf " */ 371)
- prg.printInt(prg.nest[p].pgField)
- prg.print( /* " line" */ 372)
- if prg.nest[p].pgField != 1 {
- prg.printChar(asciiCode('s'))
- }
- }
- case 1:
- prg.printNl(strNumber( /* "spacefactor " */ 373))
- prg.printInt(int32(*(*a.hh()).lh()))
- if int32(m) > 0 {
- if int32(*(*a.hh()).rh()) > 0 {
- prg.print( /* ", current language " */ 374)
- prg.printInt(int32(*(*a.hh()).rh()))
- }
- }
- case 2:
- if *a.int() != 0 {
- prg.print( /* "this will begin denominator of:" */ 375)
- prg.showBox(halfword(*a.int()))
- }
- }
- }
- }
- // 220. \[17] The table of equivalents
- // tangle:pos tex.web:4444:35:
- // Now that we have studied the data structures for \TeX's semantic routines,
- // we ought to consider the data structures used by its syntactic routines. In
- // other words, our next concern will be
- // the tables that \TeX\ looks at when it is scanning
- // what the user has written.
- //
- // The biggest and most important such table is called |eqtb|. It holds the
- // current ``equivalents'' of things; i.e., it explains what things mean
- // or what their current values are, for all quantities that are subject to
- // the nesting structure provided by \TeX's grouping mechanism. There are six
- // parts to |eqtb|:
- //
- // \yskip\hangg 1) |eqtb[active_base..(hash_base-1)]| holds the current
- // equivalents of single-character control sequences.
- //
- // \yskip\hangg 2) |eqtb[hash_base..(glue_base-1)]| holds the current
- // equivalents of multiletter control sequences.
- //
- // \yskip\hangg 3) |eqtb[glue_base..(local_base-1)]| holds the current
- // equivalents of glue parameters like the current baselineskip.
- //
- // \yskip\hangg 4) |eqtb[local_base..(int_base-1)]| holds the current
- // equivalents of local halfword quantities like the current box registers,
- // the current ``catcodes,'' the current font, and a pointer to the current
- // paragraph shape.
- //
- // \yskip\hangg 5) |eqtb[int_base..(dimen_base-1)]| holds the current
- // equivalents of fullword integer parameters like the current hyphenation
- // penalty.
- //
- // \yskip\hangg 6) |eqtb[dimen_base..eqtb_size]| holds the current equivalents
- // of fullword dimension parameters like the current hsize or amount of
- // hanging indentation.
- //
- // \yskip\noindent Note that, for example, the current amount of
- // baselineskip glue is determined by the setting of a particular location
- // in region~3 of |eqtb|, while the current meaning of the control sequence
- // `\.[\\baselineskip]' (which might have been changed by \.[\\def] or
- // \.[\\let]) appears in region~2.
- // 221.
- // tangle:pos tex.web:4485:3:
- // Each entry in |eqtb| is a |memory_word|. Most of these words are of type
- // |two_halves|, and subdivided into three fields:
- //
- // \yskip\hangg 1) The |eq_level| (a quarterword) is the level of grouping at
- // which this equivalent was defined. If the level is |level_zero|, the
- // equivalent has never been defined; |level_one| refers to the outer level
- // (outside of all groups), and this level is also used for global
- // definitions that never go away. Higher levels are for equivalents that
- // will disappear at the end of their group. \xref[global definitions]
- //
- // \yskip\hangg 2) The |eq_type| (another quarterword) specifies what kind of
- // entry this is. There are many types, since each \TeX\ primitive like
- // \.[\\hbox], \.[\\def], etc., has its own special code. The list of
- // command codes above includes all possible settings of the |eq_type| field.
- //
- // \yskip\hangg 3) The |equiv| (a halfword) is the current equivalent value.
- // This may be a font number, a pointer into |mem|, or a variety of other
- // things.
- // 237.
- // tangle:pos tex.web:5043:3:
- // We can print the symbolic name of an integer parameter as follows.
- func (prg *prg) printParam(n int32) {
- switch n {
- case pretoleranceCode:
- prg.printEsc(strNumber( /* "pretolerance" */ 420))
- case toleranceCode:
- prg.printEsc(strNumber( /* "tolerance" */ 421))
- case linePenaltyCode:
- prg.printEsc(strNumber( /* "linepenalty" */ 422))
- case hyphenPenaltyCode:
- prg.printEsc(strNumber( /* "hyphenpenalty" */ 423))
- case exHyphenPenaltyCode:
- prg.printEsc(strNumber( /* "exhyphenpenalty" */ 424))
- case clubPenaltyCode:
- prg.printEsc(strNumber( /* "clubpenalty" */ 425))
- case widowPenaltyCode:
- prg.printEsc(strNumber( /* "widowpenalty" */ 426))
- case displayWidowPenaltyCode:
- prg.printEsc(strNumber( /* "displaywidowpenalty" */ 427))
- case brokenPenaltyCode:
- prg.printEsc(strNumber( /* "brokenpenalty" */ 428))
- case binOpPenaltyCode:
- prg.printEsc(strNumber( /* "binoppenalty" */ 429))
- case relPenaltyCode:
- prg.printEsc(strNumber( /* "relpenalty" */ 430))
- case preDisplayPenaltyCode:
- prg.printEsc(strNumber( /* "predisplaypenalty" */ 431))
- case postDisplayPenaltyCode:
- prg.printEsc(strNumber( /* "postdisplaypenalty" */ 432))
- case interLinePenaltyCode:
- prg.printEsc(strNumber( /* "interlinepenalty" */ 433))
- case doubleHyphenDemeritsCode:
- prg.printEsc(strNumber( /* "doublehyphendemerits" */ 434))
- case finalHyphenDemeritsCode:
- prg.printEsc(strNumber( /* "finalhyphendemerits" */ 435))
- case adjDemeritsCode:
- prg.printEsc(strNumber( /* "adjdemerits" */ 436))
- case magCode:
- prg.printEsc(strNumber( /* "mag" */ 437))
- case delimiterFactorCode:
- prg.printEsc(strNumber( /* "delimiterfactor" */ 438))
- case loosenessCode:
- prg.printEsc(strNumber( /* "looseness" */ 439))
- case timeCode:
- prg.printEsc(strNumber( /* "time" */ 440))
- case dayCode:
- prg.printEsc(strNumber( /* "day" */ 441))
- case monthCode:
- prg.printEsc(strNumber( /* "month" */ 442))
- case yearCode:
- prg.printEsc(strNumber( /* "year" */ 443))
- case showBoxBreadthCode:
- prg.printEsc(strNumber( /* "showboxbreadth" */ 444))
- case showBoxDepthCode:
- prg.printEsc(strNumber( /* "showboxdepth" */ 445))
- case hbadnessCode:
- prg.printEsc(strNumber( /* "hbadness" */ 446))
- case vbadnessCode:
- prg.printEsc(strNumber( /* "vbadness" */ 447))
- case pausingCode:
- prg.printEsc(strNumber( /* "pausing" */ 448))
- case tracingOnlineCode:
- prg.printEsc(strNumber( /* "tracingonline" */ 449))
- case tracingMacrosCode:
- prg.printEsc(strNumber( /* "tracingmacros" */ 450))
- case tracingStatsCode:
- prg.printEsc(strNumber( /* "tracingstats" */ 451))
- case tracingParagraphsCode:
- prg.printEsc(strNumber( /* "tracingparagraphs" */ 452))
- case tracingPagesCode:
- prg.printEsc(strNumber( /* "tracingpages" */ 453))
- case tracingOutputCode:
- prg.printEsc(strNumber( /* "tracingoutput" */ 454))
- case tracingLostCharsCode:
- prg.printEsc(strNumber( /* "tracinglostchars" */ 455))
- case tracingCommandsCode:
- prg.printEsc(strNumber( /* "tracingcommands" */ 456))
- case tracingRestoresCode:
- prg.printEsc(strNumber( /* "tracingrestores" */ 457))
- case ucHyphCode:
- prg.printEsc(strNumber( /* "uchyph" */ 458))
- case outputPenaltyCode:
- prg.printEsc(strNumber( /* "outputpenalty" */ 459))
- case maxDeadCyclesCode:
- prg.printEsc(strNumber( /* "maxdeadcycles" */ 460))
- case hangAfterCode:
- prg.printEsc(strNumber( /* "hangafter" */ 461))
- case floatingPenaltyCode:
- prg.printEsc(strNumber( /* "floatingpenalty" */ 462))
- case globalDefsCode:
- prg.printEsc(strNumber( /* "globaldefs" */ 463))
- case curFamCode:
- prg.printEsc(strNumber( /* "fam" */ 464))
- case escapeCharCode:
- prg.printEsc(strNumber( /* "escapechar" */ 465))
- case defaultHyphenCharCode:
- prg.printEsc(strNumber( /* "defaulthyphenchar" */ 466))
- case defaultSkewCharCode:
- prg.printEsc(strNumber( /* "defaultskewchar" */ 467))
- case endLineCharCode:
- prg.printEsc(strNumber( /* "endlinechar" */ 468))
- case newLineCharCode:
- prg.printEsc(strNumber( /* "newlinechar" */ 469))
- case languageCode:
- prg.printEsc(strNumber( /* "language" */ 470))
- case leftHyphenMinCode:
- prg.printEsc(strNumber( /* "lefthyphenmin" */ 471))
- case rightHyphenMinCode:
- prg.printEsc(strNumber( /* "righthyphenmin" */ 472))
- case holdingInsertsCode:
- prg.printEsc(strNumber( /* "holdinginserts" */ 473))
- case errorContextLinesCode:
- prg.printEsc(strNumber( /* "errorcontextlines" */ 474))
- default:
- prg.print( /* "[unknown integer parameter!]" */ 475)
- }
- }
- // 241.
- // tangle:pos tex.web:5240:3:
- // The following procedure, which is called just before \TeX\ initializes its
- // input and output, establishes the initial values of the date and time.
- // \xref[system dependencies]
- // Since standard \PASCAL\ cannot provide such information, something special
- // is needed. The program here simply assumes that suitable values appear in
- // the global variables \\[sys\_time], \\[sys\_day], \\[sys\_month], and
- // \\[sys\_year] (which are initialized to noon on 4 July 1776,
- // in case the implementor is careless).
- func (prg *prg) fixDateAndTime() {
- prg.sysTime = 12 * 60
- prg.sysDay = 4
- prg.sysMonth = 7
- prg.sysYear = 1776 // self-evident truths
- *prg.eqtb[intBase+timeCode-1].int() = prg.sysTime // minutes since midnight
- *prg.eqtb[intBase+dayCode-1].int() = prg.sysDay // day of the month
- *prg.eqtb[intBase+monthCode-1].int() = prg.sysMonth // month of the year
- *prg.eqtb[intBase+yearCode-1].int() = prg.sysYear // Anno Domini
- }
- // 245.
- // tangle:pos tex.web:5272:3:
- // \TeX\ is occasionally supposed to print diagnostic information that
- // goes only into the transcript file, unless |tracing_online| is positive.
- // Here are two routines that adjust the destination of print commands:
- func (prg *prg) beginDiagnostic() {
- prg.oldSetting = prg.selector
- if *prg.eqtb[intBase+tracingOnlineCode-1].int() <= 0 && int32(prg.selector) == termAndLog {
- prg.selector = byte(int32(prg.selector) - 1)
- if int32(prg.history) == spotless {
- prg.history = byte(warningIssued)
- }
- }
- }
- func (prg *prg) endDiagnostic(blankLine bool) {
- prg.printNl(strNumber( /* "" */ 338))
- if blankLine {
- prg.printLn()
- }
- prg.selector = prg.oldSetting
- }
- // 247.
- // tangle:pos tex.web:5299:3:
- // The final region of |eqtb| contains the dimension parameters defined
- // here, and the 256 \.[\\dimen] registers.
- func (prg *prg) printLengthParam(n int32) {
- switch n {
- case parIndentCode:
- prg.printEsc(strNumber( /* "parindent" */ 478))
- case mathSurroundCode:
- prg.printEsc(strNumber( /* "mathsurround" */ 479))
- case lineSkipLimitCode:
- prg.printEsc(strNumber( /* "lineskiplimit" */ 480))
- case hsizeCode:
- prg.printEsc(strNumber( /* "hsize" */ 481))
- case vsizeCode:
- prg.printEsc(strNumber( /* "vsize" */ 482))
- case maxDepthCode:
- prg.printEsc(strNumber( /* "maxdepth" */ 483))
- case splitMaxDepthCode:
- prg.printEsc(strNumber( /* "splitmaxdepth" */ 484))
- case boxMaxDepthCode:
- prg.printEsc(strNumber( /* "boxmaxdepth" */ 485))
- case hfuzzCode:
- prg.printEsc(strNumber( /* "hfuzz" */ 486))
- case vfuzzCode:
- prg.printEsc(strNumber( /* "vfuzz" */ 487))
- case delimiterShortfallCode:
- prg.printEsc(strNumber( /* "delimitershortfall" */ 488))
- case nullDelimiterSpaceCode:
- prg.printEsc(strNumber( /* "nulldelimiterspace" */ 489))
- case scriptSpaceCode:
- prg.printEsc(strNumber( /* "scriptspace" */ 490))
- case preDisplaySizeCode:
- prg.printEsc(strNumber( /* "predisplaysize" */ 491))
- case displayWidthCode:
- prg.printEsc(strNumber( /* "displaywidth" */ 492))
- case displayIndentCode:
- prg.printEsc(strNumber( /* "displayindent" */ 493))
- case overfullRuleCode:
- prg.printEsc(strNumber( /* "overfullrule" */ 494))
- case hangIndentCode:
- prg.printEsc(strNumber( /* "hangindent" */ 495))
- case hOffsetCode:
- prg.printEsc(strNumber( /* "hoffset" */ 496))
- case vOffsetCode:
- prg.printEsc(strNumber( /* "voffset" */ 497))
- case emergencyStretchCode:
- prg.printEsc(strNumber( /* "emergencystretch" */ 498))
- default:
- prg.print( /* "[unknown dimen parameter!]" */ 499)
- }
- }
- // 252.
- // tangle:pos tex.web:5441:3:
- // Here is a procedure that displays the contents of |eqtb[n]|
- // symbolically.
- // \4
- // Declare the procedure called |print_cmd_chr|
- func (prg *prg) printCmdChr(cmd quarterword, chrCode halfword) {
- switch cmd {
- case leftBrace:
- prg.print( /* "begin-group character " */ 557)
- prg.print(int32(chrCode))
- case rightBrace:
- prg.print( /* "end-group character " */ 558)
- prg.print(int32(chrCode))
- case mathShift:
- prg.print( /* "math shift character " */ 559)
- prg.print(int32(chrCode))
- case macParam:
- prg.print( /* "macro parameter character " */ 560)
- prg.print(int32(chrCode))
- case supMark:
- prg.print( /* "superscript character " */ 561)
- prg.print(int32(chrCode))
- case subMark:
- prg.print( /* "subscript character " */ 562)
- prg.print(int32(chrCode))
- case endv:
- prg.print( /* "end of alignment template" */ 563)
- case spacer:
- prg.print( /* "blank space " */ 564)
- prg.print(int32(chrCode))
- case letter:
- prg.print( /* "the letter " */ 565)
- prg.print(int32(chrCode))
- case otherChar:
- prg.print( /* "the character " */ 566)
- prg.print(int32(chrCode))
- // \4
- // Cases of |print_cmd_chr| for symbolic printing of primitives
- case assignGlue, assignMuGlue:
- if int32(chrCode) < skipBase {
- prg.printSkipParam(int32(chrCode) - glueBase)
- } else if int32(chrCode) < muSkipBase {
- prg.printEsc(strNumber( /* "skip" */ 395))
- prg.printInt(int32(chrCode) - skipBase)
- } else {
- prg.printEsc(strNumber( /* "muskip" */ 396))
- prg.printInt(int32(chrCode) - muSkipBase)
- }
- case assignToks:
- if int32(chrCode) >= toksBase {
- prg.printEsc(strNumber( /* "toks" */ 407))
- prg.printInt(int32(chrCode) - toksBase)
- } else {
- switch chrCode {
- case outputRoutineLoc:
- prg.printEsc(strNumber( /* "output" */ 398))
- case everyParLoc:
- prg.printEsc(strNumber( /* "everypar" */ 399))
- case everyMathLoc:
- prg.printEsc(strNumber( /* "everymath" */ 400))
- case everyDisplayLoc:
- prg.printEsc(strNumber( /* "everydisplay" */ 401))
- case everyHboxLoc:
- prg.printEsc(strNumber( /* "everyhbox" */ 402))
- case everyVboxLoc:
- prg.printEsc(strNumber( /* "everyvbox" */ 403))
- case everyJobLoc:
- prg.printEsc(strNumber( /* "everyjob" */ 404))
- case everyCrLoc:
- prg.printEsc(strNumber( /* "everycr" */ 405))
- default:
- prg.printEsc(strNumber( /* "errhelp" */ 406))
- }
- }
- case assignInt:
- if int32(chrCode) < countBase {
- prg.printParam(int32(chrCode) - intBase)
- } else {
- prg.printEsc(strNumber( /* "count" */ 476))
- prg.printInt(int32(chrCode) - countBase)
- }
- case assignDimen:
- if int32(chrCode) < scaledBase {
- prg.printLengthParam(int32(chrCode) - dimenBase)
- } else {
- prg.printEsc(strNumber( /* "dimen" */ 500))
- prg.printInt(int32(chrCode) - scaledBase)
- }
- case accent:
- prg.printEsc(strNumber( /* "accent" */ 508))
- case advance:
- prg.printEsc(strNumber( /* "advance" */ 509))
- case afterAssignment:
- prg.printEsc(strNumber( /* "afterassignment" */ 510))
- case afterGroup:
- prg.printEsc(strNumber( /* "aftergroup" */ 511))
- case assignFontDimen:
- prg.printEsc(strNumber( /* "fontdimen" */ 519))
- case beginGroup:
- prg.printEsc(strNumber( /* "begingroup" */ 512))
- case breakPenalty:
- prg.printEsc(strNumber( /* "penalty" */ 531))
- case charNum:
- prg.printEsc(strNumber( /* "char" */ 513))
- case csName:
- prg.printEsc(strNumber( /* "csname" */ 504))
- case defFont:
- prg.printEsc(strNumber( /* "font" */ 518))
- case delimNum:
- prg.printEsc(strNumber( /* "delimiter" */ 514))
- case divide:
- prg.printEsc(strNumber( /* "divide" */ 515))
- case endCsName:
- prg.printEsc(strNumber( /* "endcsname" */ 505))
- case endGroup:
- prg.printEsc(strNumber( /* "endgroup" */ 516))
- case exSpace:
- prg.printEsc(strNumber(' '))
- case expandAfter:
- prg.printEsc(strNumber( /* "expandafter" */ 517))
- case halign:
- prg.printEsc(strNumber( /* "halign" */ 520))
- case hrule:
- prg.printEsc(strNumber( /* "hrule" */ 521))
- case ignoreSpaces:
- prg.printEsc(strNumber( /* "ignorespaces" */ 522))
- case insert:
- prg.printEsc(strNumber( /* "insert" */ 330))
- case italCorr:
- prg.printEsc(strNumber('/'))
- case mark:
- prg.printEsc(strNumber( /* "mark" */ 351))
- case mathAccent:
- prg.printEsc(strNumber( /* "mathaccent" */ 523))
- case mathCharNum:
- prg.printEsc(strNumber( /* "mathchar" */ 524))
- case mathChoice:
- prg.printEsc(strNumber( /* "mathchoice" */ 525))
- case multiply:
- prg.printEsc(strNumber( /* "multiply" */ 526))
- case noAlign:
- prg.printEsc(strNumber( /* "noalign" */ 527))
- case noBoundary:
- prg.printEsc(strNumber( /* "noboundary" */ 528))
- case noExpand:
- prg.printEsc(strNumber( /* "noexpand" */ 529))
- case nonScript:
- prg.printEsc(strNumber( /* "nonscript" */ 335))
- case omit:
- prg.printEsc(strNumber( /* "omit" */ 530))
- case radical:
- prg.printEsc(strNumber( /* "radical" */ 533))
- case readToCs:
- prg.printEsc(strNumber( /* "read" */ 534))
- case relax:
- prg.printEsc(strNumber( /* "relax" */ 535))
- case setBox:
- prg.printEsc(strNumber( /* "setbox" */ 536))
- case setPrevGraf:
- prg.printEsc(strNumber( /* "prevgraf" */ 532))
- case setShape:
- prg.printEsc(strNumber( /* "parshape" */ 408))
- case the:
- prg.printEsc(strNumber( /* "the" */ 537))
- case toksRegister:
- prg.printEsc(strNumber( /* "toks" */ 407))
- case vadjust:
- prg.printEsc(strNumber( /* "vadjust" */ 352))
- case valign:
- prg.printEsc(strNumber( /* "valign" */ 538))
- case vcenter:
- prg.printEsc(strNumber( /* "vcenter" */ 539))
- case vrule:
- prg.printEsc(strNumber( /* "vrule" */ 540))
- case parEnd:
- prg.printEsc(strNumber( /* "par" */ 597))
- case input:
- if int32(chrCode) == 0 {
- prg.printEsc(strNumber( /* "input" */ 629))
- } else {
- prg.printEsc(strNumber( /* "endinput" */ 630))
- }
- case topBotMark:
- switch chrCode {
- case firstMarkCode:
- prg.printEsc(strNumber( /* "firstmark" */ 632))
- case botMarkCode:
- prg.printEsc(strNumber( /* "botmark" */ 633))
- case splitFirstMarkCode:
- prg.printEsc(strNumber( /* "splitfirstmark" */ 634))
- case splitBotMarkCode:
- prg.printEsc(strNumber( /* "splitbotmark" */ 635))
- default:
- prg.printEsc(strNumber( /* "topmark" */ 631))
- }
- case register:
- if int32(chrCode) == intVal {
- prg.printEsc(strNumber( /* "count" */ 476))
- } else if int32(chrCode) == dimenVal {
- prg.printEsc(strNumber( /* "dimen" */ 500))
- } else if int32(chrCode) == glueVal {
- prg.printEsc(strNumber( /* "skip" */ 395))
- } else {
- prg.printEsc(strNumber( /* "muskip" */ 396))
- }
- case setAux:
- if int32(chrCode) == vmode {
- prg.printEsc(strNumber( /* "prevdepth" */ 669))
- } else {
- prg.printEsc(strNumber( /* "spacefactor" */ 668))
- }
- case setPageInt:
- if int32(chrCode) == 0 {
- prg.printEsc(strNumber( /* "deadcycles" */ 670))
- } else {
- prg.printEsc(strNumber( /* "insertpenalties" */ 671))
- }
- case setBoxDimen:
- if int32(chrCode) == widthOffset {
- prg.printEsc(strNumber( /* "wd" */ 672))
- } else if int32(chrCode) == heightOffset {
- prg.printEsc(strNumber( /* "ht" */ 673))
- } else {
- prg.printEsc(strNumber( /* "dp" */ 674))
- }
- case lastItem:
- switch chrCode {
- case intVal:
- prg.printEsc(strNumber( /* "lastpenalty" */ 675))
- case dimenVal:
- prg.printEsc(strNumber( /* "lastkern" */ 676))
- case glueVal:
- prg.printEsc(strNumber( /* "lastskip" */ 677))
- case inputLineNoCode:
- prg.printEsc(strNumber( /* "inputlineno" */ 678))
- default:
- prg.printEsc(strNumber( /* "badness" */ 679))
- }
- case convert:
- switch chrCode {
- case numberCode:
- prg.printEsc(strNumber( /* "number" */ 735))
- case romanNumeralCode:
- prg.printEsc(strNumber( /* "romannumeral" */ 736))
- case stringCode:
- prg.printEsc(strNumber( /* "string" */ 737))
- case meaningCode:
- prg.printEsc(strNumber( /* "meaning" */ 738))
- case fontNameCode:
- prg.printEsc(strNumber( /* "fontname" */ 739))
- default:
- prg.printEsc(strNumber( /* "jobname" */ 740))
- }
- case ifTest:
- switch chrCode {
- case ifCatCode:
- prg.printEsc(strNumber( /* "ifcat" */ 758))
- case ifIntCode:
- prg.printEsc(strNumber( /* "ifnum" */ 759))
- case ifDimCode:
- prg.printEsc(strNumber( /* "ifdim" */ 760))
- case ifOddCode:
- prg.printEsc(strNumber( /* "ifodd" */ 761))
- case ifVmodeCode:
- prg.printEsc(strNumber( /* "ifvmode" */ 762))
- case ifHmodeCode:
- prg.printEsc(strNumber( /* "ifhmode" */ 763))
- case ifMmodeCode:
- prg.printEsc(strNumber( /* "ifmmode" */ 764))
- case ifInnerCode:
- prg.printEsc(strNumber( /* "ifinner" */ 765))
- case ifVoidCode:
- prg.printEsc(strNumber( /* "ifvoid" */ 766))
- case ifHboxCode:
- prg.printEsc(strNumber( /* "ifhbox" */ 767))
- case ifVboxCode:
- prg.printEsc(strNumber( /* "ifvbox" */ 768))
- case ifxCode:
- prg.printEsc(strNumber( /* "ifx" */ 769))
- case ifEofCode:
- prg.printEsc(strNumber( /* "ifeof" */ 770))
- case ifTrueCode:
- prg.printEsc(strNumber( /* "iftrue" */ 771))
- case ifFalseCode:
- prg.printEsc(strNumber( /* "iffalse" */ 772))
- case ifCaseCode:
- prg.printEsc(strNumber( /* "ifcase" */ 773))
- default:
- prg.printEsc(strNumber( /* "if" */ 757))
- }
- case fiOrElse:
- if int32(chrCode) == fiCode {
- prg.printEsc(strNumber( /* "fi" */ 774))
- } else if int32(chrCode) == orCode {
- prg.printEsc(strNumber( /* "or" */ 775))
- } else {
- prg.printEsc(strNumber( /* "else" */ 776))
- }
- case tabMark:
- if int32(chrCode) == spanCode {
- prg.printEsc(strNumber( /* "span" */ 898))
- } else {
- prg.print( /* "alignment tab character " */ 902)
- prg.print(int32(chrCode))
- }
- case carRet:
- if int32(chrCode) == crCode {
- prg.printEsc(strNumber( /* "cr" */ 899))
- } else {
- prg.printEsc(strNumber( /* "crcr" */ 900))
- }
- case setPageDimen:
- switch chrCode {
- case 0:
- prg.printEsc(strNumber( /* "pagegoal" */ 970))
- case 1:
- prg.printEsc(strNumber( /* "pagetotal" */ 971))
- case 2:
- prg.printEsc(strNumber( /* "pagestretch" */ 972))
- case 3:
- prg.printEsc(strNumber( /* "pagefilstretch" */ 973))
- case 4:
- prg.printEsc(strNumber( /* "pagefillstretch" */ 974))
- case 5:
- prg.printEsc(strNumber( /* "pagefilllstretch" */ 975))
- case 6:
- prg.printEsc(strNumber( /* "pageshrink" */ 976))
- default:
- prg.printEsc(strNumber( /* "pagedepth" */ 977))
- }
- case stop:
- if int32(chrCode) == 1 {
- prg.printEsc(strNumber( /* "dump" */ 1026))
- } else {
- prg.printEsc(strNumber( /* "end" */ 1025))
- }
- case hskip:
- switch chrCode {
- case skipCode:
- prg.printEsc(strNumber( /* "hskip" */ 1027))
- case filCode:
- prg.printEsc(strNumber( /* "hfil" */ 1028))
- case fillCode:
- prg.printEsc(strNumber( /* "hfill" */ 1029))
- case ssCode:
- prg.printEsc(strNumber( /* "hss" */ 1030))
- default:
- prg.printEsc(strNumber( /* "hfilneg" */ 1031))
- }
- case vskip:
- switch chrCode {
- case skipCode:
- prg.printEsc(strNumber( /* "vskip" */ 1032))
- case filCode:
- prg.printEsc(strNumber( /* "vfil" */ 1033))
- case fillCode:
- prg.printEsc(strNumber( /* "vfill" */ 1034))
- case ssCode:
- prg.printEsc(strNumber( /* "vss" */ 1035))
- default:
- prg.printEsc(strNumber( /* "vfilneg" */ 1036))
- }
- case mskip:
- prg.printEsc(strNumber( /* "mskip" */ 336))
- case kern:
- prg.printEsc(strNumber( /* "kern" */ 340))
- case mkern:
- prg.printEsc(strNumber( /* "mkern" */ 342))
- case hmove:
- if int32(chrCode) == 1 {
- prg.printEsc(strNumber( /* "moveleft" */ 1054))
- } else {
- prg.printEsc(strNumber( /* "moveright" */ 1055))
- }
- case vmove:
- if int32(chrCode) == 1 {
- prg.printEsc(strNumber( /* "raise" */ 1056))
- } else {
- prg.printEsc(strNumber( /* "lower" */ 1057))
- }
- case makeBox:
- switch chrCode {
- case boxCode:
- prg.printEsc(strNumber( /* "box" */ 409))
- case copyCode:
- prg.printEsc(strNumber( /* "copy" */ 1058))
- case lastBoxCode:
- prg.printEsc(strNumber( /* "lastbox" */ 1059))
- case vsplitCode:
- prg.printEsc(strNumber( /* "vsplit" */ 965))
- case vtopCode:
- prg.printEsc(strNumber( /* "vtop" */ 1060))
- case vtopCode + 1:
- prg.printEsc(strNumber( /* "vbox" */ 967))
- default:
- prg.printEsc(strNumber( /* "hbox" */ 1061))
- }
- case leaderShip:
- if int32(chrCode) == aLeaders {
- prg.printEsc(strNumber( /* "leaders" */ 1063))
- } else if int32(chrCode) == cLeaders {
- prg.printEsc(strNumber( /* "cleaders" */ 1064))
- } else if int32(chrCode) == xLeaders {
- prg.printEsc(strNumber( /* "xleaders" */ 1065))
- } else {
- prg.printEsc(strNumber( /* "shipout" */ 1062))
- }
- case startPar:
- if int32(chrCode) == 0 {
- prg.printEsc(strNumber( /* "noindent" */ 1081))
- } else {
- prg.printEsc(strNumber( /* "indent" */ 1080))
- }
- case removeItem:
- if int32(chrCode) == glueNode {
- prg.printEsc(strNumber( /* "unskip" */ 1092))
- } else if int32(chrCode) == kernNode {
- prg.printEsc(strNumber( /* "unkern" */ 1091))
- } else {
- prg.printEsc(strNumber( /* "unpenalty" */ 1090))
- }
- case unHbox:
- if int32(chrCode) == copyCode {
- prg.printEsc(strNumber( /* "unhcopy" */ 1094))
- } else {
- prg.printEsc(strNumber( /* "unhbox" */ 1093))
- }
- case unVbox:
- if int32(chrCode) == copyCode {
- prg.printEsc(strNumber( /* "unvcopy" */ 1096))
- } else {
- prg.printEsc(strNumber( /* "unvbox" */ 1095))
- }
- case discretionary:
- if int32(chrCode) == 1 {
- prg.printEsc(strNumber('-'))
- } else {
- prg.printEsc(strNumber( /* "discretionary" */ 349))
- }
- case eqNo:
- if int32(chrCode) == 1 {
- prg.printEsc(strNumber( /* "leqno" */ 1128))
- } else {
- prg.printEsc(strNumber( /* "eqno" */ 1127))
- }
- case mathComp:
- switch chrCode {
- case ordNoad:
- prg.printEsc(strNumber( /* "mathord" */ 866))
- case opNoad:
- prg.printEsc(strNumber( /* "mathop" */ 867))
- case binNoad:
- prg.printEsc(strNumber( /* "mathbin" */ 868))
- case relNoad:
- prg.printEsc(strNumber( /* "mathrel" */ 869))
- case openNoad:
- prg.printEsc(strNumber( /* "mathopen" */ 870))
- case closeNoad:
- prg.printEsc(strNumber( /* "mathclose" */ 871))
- case punctNoad:
- prg.printEsc(strNumber( /* "mathpunct" */ 872))
- case innerNoad:
- prg.printEsc(strNumber( /* "mathinner" */ 873))
- case underNoad:
- prg.printEsc(strNumber( /* "underline" */ 875))
- default:
- prg.printEsc(strNumber( /* "overline" */ 874))
- }
- case limitSwitch:
- if int32(chrCode) == limits {
- prg.printEsc(strNumber( /* "limits" */ 878))
- } else if int32(chrCode) == noLimits {
- prg.printEsc(strNumber( /* "nolimits" */ 879))
- } else {
- prg.printEsc(strNumber( /* "displaylimits" */ 1129))
- }
- case mathStyle:
- prg.printStyle(int32(chrCode))
- case above:
- switch chrCode {
- case overCode:
- prg.printEsc(strNumber( /* "over" */ 1148))
- case atopCode:
- prg.printEsc(strNumber( /* "atop" */ 1149))
- case delimitedCode + 0:
- prg.printEsc(strNumber( /* "abovewithdelims" */ 1150))
- case delimitedCode + 1:
- prg.printEsc(strNumber( /* "overwithdelims" */ 1151))
- case delimitedCode + 2:
- prg.printEsc(strNumber( /* "atopwithdelims" */ 1152))
- default:
- prg.printEsc(strNumber( /* "above" */ 1147))
- }
- case leftRight:
- if int32(chrCode) == leftNoad {
- prg.printEsc(strNumber( /* "left" */ 876))
- } else {
- prg.printEsc(strNumber( /* "right" */ 877))
- }
- case prefix:
- if int32(chrCode) == 1 {
- prg.printEsc(strNumber( /* "long" */ 1171))
- } else if int32(chrCode) == 2 {
- prg.printEsc(strNumber( /* "outer" */ 1172))
- } else {
- prg.printEsc(strNumber( /* "global" */ 1173))
- }
- case def:
- if int32(chrCode) == 0 {
- prg.printEsc(strNumber( /* "def" */ 1174))
- } else if int32(chrCode) == 1 {
- prg.printEsc(strNumber( /* "gdef" */ 1175))
- } else if int32(chrCode) == 2 {
- prg.printEsc(strNumber( /* "edef" */ 1176))
- } else {
- prg.printEsc(strNumber( /* "xdef" */ 1177))
- }
- case let:
- if int32(chrCode) != normal {
- prg.printEsc(strNumber( /* "futurelet" */ 1192))
- } else {
- prg.printEsc(strNumber( /* "let" */ 1191))
- }
- case shorthandDef:
- switch chrCode {
- case charDefCode:
- prg.printEsc(strNumber( /* "chardef" */ 1193))
- case mathCharDefCode:
- prg.printEsc(strNumber( /* "mathchardef" */ 1194))
- case countDefCode:
- prg.printEsc(strNumber( /* "countdef" */ 1195))
- case dimenDefCode:
- prg.printEsc(strNumber( /* "dimendef" */ 1196))
- case skipDefCode:
- prg.printEsc(strNumber( /* "skipdef" */ 1197))
- case muSkipDefCode:
- prg.printEsc(strNumber( /* "muskipdef" */ 1198))
- default:
- prg.printEsc(strNumber( /* "toksdef" */ 1199))
- }
- case charGiven:
- prg.printEsc(strNumber( /* "char" */ 513))
- prg.printHex(int32(chrCode))
- case mathGiven:
- prg.printEsc(strNumber( /* "mathchar" */ 524))
- prg.printHex(int32(chrCode))
- case defCode:
- if int32(chrCode) == catCodeBase {
- prg.printEsc(strNumber( /* "catcode" */ 415))
- } else if int32(chrCode) == mathCodeBase {
- prg.printEsc(strNumber( /* "mathcode" */ 419))
- } else if int32(chrCode) == lcCodeBase {
- prg.printEsc(strNumber( /* "lccode" */ 416))
- } else if int32(chrCode) == ucCodeBase {
- prg.printEsc(strNumber( /* "uccode" */ 417))
- } else if int32(chrCode) == sfCodeBase {
- prg.printEsc(strNumber( /* "sfcode" */ 418))
- } else {
- prg.printEsc(strNumber( /* "delcode" */ 477))
- }
- case defFamily:
- prg.printSize(int32(chrCode) - mathFontBase)
- case hyphData:
- if int32(chrCode) == 1 {
- prg.printEsc(strNumber( /* "patterns" */ 953))
- } else {
- prg.printEsc(strNumber( /* "hyphenation" */ 941))
- }
- case assignFontInt:
- if int32(chrCode) == 0 {
- prg.printEsc(strNumber( /* "hyphenchar" */ 1217))
- } else {
- prg.printEsc(strNumber( /* "skewchar" */ 1218))
- }
- case setFont:
- prg.print( /* "select font " */ 1226)
- prg.slowPrint(int32(prg.fontName[chrCode]))
- if prg.fontSize[chrCode] != prg.fontDsize[chrCode] {
- prg.print( /* " at " */ 741)
- prg.printScaled(prg.fontSize[chrCode])
- prg.print( /* "pt" */ 397)
- }
- case setInteraction:
- switch chrCode {
- case batchMode:
- prg.printEsc(strNumber( /* "batchmode" */ 274))
- case nonstopMode:
- prg.printEsc(strNumber( /* "nonstopmode" */ 275))
- case scrollMode:
- prg.printEsc(strNumber( /* "scrollmode" */ 276))
- default:
- prg.printEsc(strNumber( /* "errorstopmode" */ 1227))
- }
- case inStream:
- if int32(chrCode) == 0 {
- prg.printEsc(strNumber( /* "closein" */ 1229))
- } else {
- prg.printEsc(strNumber( /* "openin" */ 1228))
- }
- case message:
- if int32(chrCode) == 0 {
- prg.printEsc(strNumber( /* "message" */ 1230))
- } else {
- prg.printEsc(strNumber( /* "errmessage" */ 1231))
- }
- case caseShift:
- if int32(chrCode) == lcCodeBase {
- prg.printEsc(strNumber( /* "lowercase" */ 1237))
- } else {
- prg.printEsc(strNumber( /* "uppercase" */ 1238))
- }
- case xray:
- switch chrCode {
- case showBoxCode:
- prg.printEsc(strNumber( /* "showbox" */ 1240))
- case showTheCode:
- prg.printEsc(strNumber( /* "showthe" */ 1241))
- case showListsCode:
- prg.printEsc(strNumber( /* "showlists" */ 1242))
- default:
- prg.printEsc(strNumber( /* "show" */ 1239))
- }
- case undefinedCs:
- prg.print( /* "undefined" */ 1249)
- case call:
- prg.print( /* "macro" */ 1250)
- case longCall:
- prg.printEsc(strNumber( /* "long macro" */ 1251))
- case outerCall:
- prg.printEsc(strNumber( /* "outer macro" */ 1252))
- case longOuterCall:
- prg.printEsc(strNumber( /* "long" */ 1171))
- prg.printEsc(strNumber( /* "outer macro" */ 1252))
- case endTemplate:
- prg.printEsc(strNumber( /* "outer endtemplate" */ 1253))
- case extension:
- switch chrCode {
- case openNode:
- prg.printEsc(strNumber( /* "openout" */ 1285))
- case writeNode:
- prg.printEsc(strNumber( /* "write" */ 594))
- case closeNode:
- prg.printEsc(strNumber( /* "closeout" */ 1286))
- case specialNode:
- prg.printEsc(strNumber( /* "special" */ 1287))
- case immediateCode:
- prg.printEsc(strNumber( /* "immediate" */ 1288))
- case setLanguageCode:
- prg.printEsc(strNumber( /* "setlanguage" */ 1289))
- default:
- prg.print( /* "[unknown extension!]" */ 1290)
- }
- default:
- prg.print( /* "[unknown command code!]" */ 567)
- }
- }
- // procedure show_eqtb( n:halfword );
- // begin if n<active_base then print_char(["?"=]63) [this can't happen]
- // else if n<glue_base then
- // [ Show equivalent |n|, in region 1 or 2 ]
- // begin sprint_cs(n); print_char(["="=]61); print_cmd_chr( eqtb[ n].hh.b0 , eqtb[ n].hh.rh );
- // if eqtb[ n].hh.b0 >=call then
- // begin print_char([":"=]58); show_token_list( mem[ eqtb[ n].hh.rh ].hh.rh ,0 ,32);
- // end;
- // end
- //
- // else if n<local_base then
- // [ Show equivalent |n|, in region 3 ]
- // if n<skip_base then
- // begin print_skip_param(n-glue_base); print_char(["="=]61);
- // if n<glue_base+thin_mu_skip_code then print_spec( eqtb[ n].hh.rh ,["pt"=]397)
- // else print_spec( eqtb[ n].hh.rh ,["mu"=]337);
- // end
- // else if n<mu_skip_base then
- // begin print_esc(["skip"=]395); print_int(n-skip_base); print_char(["="=]61);
- // print_spec( eqtb[ n].hh.rh ,["pt"=]397);
- // end
- // else begin print_esc(["muskip"=]396); print_int(n-mu_skip_base); print_char(["="=]61);
- // print_spec( eqtb[ n].hh.rh ,["mu"=]337);
- // end
- //
- // else if n<int_base then
- // [ Show equivalent |n|, in region 4 ]
- // if n=par_shape_loc then
- // begin print_esc(["parshape"=]408); print_char(["="=]61);
- // if eqtb[ par_shape_loc].hh.rh =0 then print_char(["0"=]48)
- // else print_int( mem[ eqtb[ par_shape_loc].hh.rh ].hh.lh );
- // end
- // else if n<toks_base then
- // begin print_cmd_chr(assign_toks,n); print_char(["="=]61);
- // if eqtb[ n].hh.rh <>0 then show_token_list( mem[ eqtb[ n].hh.rh ].hh.rh ,0 ,32);
- // end
- // else if n<box_base then
- // begin print_esc(["toks"=]407); print_int(n-toks_base); print_char(["="=]61);
- // if eqtb[ n].hh.rh <>0 then show_token_list( mem[ eqtb[ n].hh.rh ].hh.rh ,0 ,32);
- // end
- // else if n<cur_font_loc then
- // begin print_esc(["box"=]409); print_int(n-box_base); print_char(["="=]61);
- // if eqtb[ n].hh.rh =0 then print(["void"=]410)
- // else begin depth_threshold:=0; breadth_max:=1; show_node_list( eqtb[ n].hh.rh );
- // end;
- // end
- // else if n<cat_code_base then
- // [ Show the font identifier in |eqtb[n]| ]
- // begin if n=cur_font_loc then print(["current font"=]411)
- // else if n<math_font_base+16 then
- // begin print_esc(["textfont"=]412); print_int(n-math_font_base);
- // end
- // else if n<math_font_base+32 then
- // begin print_esc(["scriptfont"=]413); print_int(n-math_font_base-16);
- // end
- // else begin print_esc(["scriptscriptfont"=]414); print_int(n-math_font_base-32);
- // end;
- // print_char(["="=]61);
- //
- // print_esc(hash[font_id_base+ eqtb[ n].hh.rh ].rh);
- // [that's |font_id_text(equiv(n))|]
- // end
- //
- // else
- // [ Show the halfword code in |eqtb[n]| ]
- // if n<math_code_base then
- // begin if n<lc_code_base then
- // begin print_esc(["catcode"=]415); print_int(n-cat_code_base);
- // end
- // else if n<uc_code_base then
- // begin print_esc(["lccode"=]416); print_int(n-lc_code_base);
- // end
- // else if n<sf_code_base then
- // begin print_esc(["uccode"=]417); print_int(n-uc_code_base);
- // end
- // else begin print_esc(["sfcode"=]418); print_int(n-sf_code_base);
- // end;
- // print_char(["="=]61); print_int( eqtb[ n].hh.rh );
- // end
- // else begin print_esc(["mathcode"=]419); print_int(n-math_code_base);
- // print_char(["="=]61); print_int( eqtb[ n].hh.rh -0 );
- // end
- //
- // else if n<dimen_base then
- // [ Show equivalent |n|, in region 5 ]
- // begin if n<count_base then print_param(n-int_base)
- // else if n<del_code_base then
- // begin print_esc(["count"=]476); print_int(n-count_base);
- // end
- // else begin print_esc(["delcode"=]477); print_int(n-del_code_base);
- // end;
- // print_char(["="=]61); print_int(eqtb[n].int);
- // end
- //
- // else if n<=eqtb_size then
- // [ Show equivalent |n|, in region 6 ]
- // begin if n<scaled_base then print_length_param(n-dimen_base)
- // else begin print_esc(["dimen"=]500); print_int(n-scaled_base);
- // end;
- // print_char(["="=]61); print_scaled(eqtb[n].int ); print(["pt"=]397);
- // end
- //
- // else print_char(["?"=]63); [this can't happen either]
- // end;
- // [ ]
- // 259.
- // tangle:pos tex.web:5528:3:
- // Here is the subroutine that searches the hash table for an identifier
- // that matches a given string of length |l>1| appearing in |buffer[j..
- // (j+l-1)]|. If the identifier is found, the corresponding hash table address
- // is returned. Otherwise, if the global variable |no_new_control_sequence|
- // is |true|, the dummy address |undefined_control_sequence| is returned.
- // Otherwise the identifier is inserted into the hash table and its location
- // is returned.
- func (prg *prg) idLookup(j, l int32) (r halfword) { // go here if you found it
- var (
- h int32 // hash code
- d int32 // number of characters in incomplete current string
- p halfword // index in |hash| array
- k halfword // index in |buffer| array
- )
- h = int32(prg.buffer[j])
- for ii := j + 1; ii <= j+l-1; ii++ {
- k = halfword(ii)
- _ = k
- h = h + h + int32(prg.buffer[k])
- for h >= hashPrime {
- h = h - hashPrime
- }
- }
- p = uint16(h + hashBase) // we start searching here; note that |0<=h<hash_prime|
- for true {
- if int32(*prg.hash[p-514].rh()) > 0 {
- if int32(prg.strStart[int32(*prg.hash[p-514].rh())+1])-int32(prg.strStart[*prg.hash[p-514].rh()]) == l {
- if prg.strEqBuf(*prg.hash[p-514].rh(), j) {
- goto found
- }
- }
- }
- if int32(*prg.hash[p-514].lh()) == 0 {
- if prg.noNewControlSequence {
- p = uint16(undefinedControlSequence)
- } else {
- // Insert a new control sequence after |p|, then make |p| point to it
- if int32(*prg.hash[p-514].rh()) > 0 {
- for {
- if int32(prg.hashUsed) == hashBase {
- prg.overflow(strNumber( /* "hash size" */ 503), hashSize)
- }
- // \xref[TeX capacity exceeded hash size][\quad hash size]
- prg.hashUsed = uint16(int32(prg.hashUsed) - 1)
- if int32(*prg.hash[prg.hashUsed-514].rh()) == 0 {
- break
- }
- } // search for an empty location in |hash|
- *prg.hash[p-514].lh() = prg.hashUsed
- p = prg.hashUsed
- }
- {
- if int32(prg.poolPtr)+l > poolSize {
- prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
- } /* \xref[TeX capacity exceeded pool size][\quad pool size] */
- }
- d = int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr])
- for int32(prg.poolPtr) > int32(prg.strStart[prg.strPtr]) {
- prg.poolPtr = uint16(int32(prg.poolPtr) - 1)
- prg.strPool[int32(prg.poolPtr)+l] = prg.strPool[prg.poolPtr]
- } // move current string up to make room for another
- for ii := j; ii <= j+l-1; ii++ {
- k = halfword(ii)
- _ = k
- prg.strPool[prg.poolPtr] = prg.buffer[k]
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- *prg.hash[p-514].rh() = prg.makeString()
- prg.poolPtr = uint16(int32(prg.poolPtr) + d)
- // cs_count:= cs_count+1 ; [ ]
- }
- goto found
- }
- p = *prg.hash[p-514].lh()
- }
- found:
- r = p
- return r
- }
- // 264.
- // tangle:pos tex.web:5631:3:
- // We need to put \TeX's “primitive” control sequences into the hash
- // table, together with their command code (which will be the |eq_type|)
- // and an operand (which will be the |equiv|). The |primitive| procedure
- // does this, in a way that no \TeX\ user can. The global value |cur_val|
- // contains the new |eqtb| pointer after |primitive| has acted.
- func (prg *prg) primitive(s strNumber, c quarterword, o halfword) {
- var (
- k poolPointer // index into |str_pool|
- j smallNumber // index into |buffer|
- l smallNumber // length of the string
- )
- if int32(s) < 256 {
- prg.curVal = int32(s) + singleBase
- } else {
- k = prg.strStart[s]
- l = byte(int32(prg.strStart[int32(s)+1]) - int32(k))
- // we will move |s| into the (empty) |buffer|
- for ii := int32(0); ii <= int32(l)-1; ii++ {
- j = smallNumber(ii)
- _ = j
- prg.buffer[j] = prg.strPool[int32(k)+int32(j)]
- }
- prg.curVal = int32(prg.idLookup(0, int32(l))) // |no_new_control_sequence| is |false|
- {
- prg.strPtr = uint16(int32(prg.strPtr) - 1)
- prg.poolPtr = prg.strStart[prg.strPtr]
- }
- *prg.hash[prg.curVal-514].rh() = s // we don't want to have the string twice
- }
- *(*prg.eqtb[prg.curVal-1].hh()).b1() = byte(levelOne)
- *(*prg.eqtb[prg.curVal-1].hh()).b0() = c
- *(*prg.eqtb[prg.curVal-1].hh()).rh() = o
- }
- // 268. \[19] Saving and restoring equivalents
- // tangle:pos tex.web:5813:43:
- // The nested structure provided by `$\.[\char'173]\ldots\.[\char'175]$' groups
- // in \TeX\ means that |eqtb| entries valid in outer groups should be saved
- // and restored later if they are overridden inside the braces. When a new |eqtb|
- // value is being assigned, the program therefore checks to see if the previous
- // entry belongs to an outer level. In such a case, the old value is placed
- // on the |save_stack| just before the new value enters |eqtb|. At the
- // end of a grouping level, i.e., when the right brace is sensed, the
- // |save_stack| is used to restore the outer values, and the inner ones are
- // destroyed.
- //
- // Entries on the |save_stack| are of type |memory_word|. The top item on
- // this stack is |save_stack[p]|, where |p=save_ptr-1|; it contains three
- // fields called |save_type|, |save_level|, and |save_index|, and it is
- // interpreted in one of four ways:
- //
- // \yskip\hangg 1) If |save_type(p)=restore_old_value|, then
- // |save_index(p)| is a location in |eqtb| whose current value should
- // be destroyed at the end of the current group and replaced by |save_stack[p-1]|.
- // Furthermore if |save_index(p)>=int_base|, then |save_level(p)|
- // should replace the corresponding entry in |xeq_level|.
- //
- // \yskip\hangg 2) If |save_type(p)=restore_zero|, then |save_index(p)|
- // is a location in |eqtb| whose current value should be destroyed at the end
- // of the current group, when it should be
- // replaced by the value of |eqtb[undefined_control_sequence]|.
- //
- // \yskip\hangg 3) If |save_type(p)=insert_token|, then |save_index(p)|
- // is a token that should be inserted into \TeX's input when the current
- // group ends.
- //
- // \yskip\hangg 4) If |save_type(p)=level_boundary|, then |save_level(p)|
- // is a code explaining what kind of group we were previously in, and
- // |save_index(p)| points to the level boundary word at the bottom of
- // the entries for that group.
- // 270.
- // tangle:pos tex.web:5892:3:
- // The global variable |cur_group| keeps track of what sort of group we are
- // currently in. Another global variable, |cur_boundary|, points to the
- // topmost |level_boundary| word. And |cur_level| is the current depth of
- // nesting. The routines are designed to preserve the condition that no entry
- // in the |save_stack| or in |eqtb| ever has a level greater than |cur_level|.
- // 273.
- // tangle:pos tex.web:5915:3:
- // The following macro is used to test if there is room for up to six more
- // entries on |save_stack|. By making a conservative test like this, we can
- // get by with testing for overflow in only a few places.
- // 274.
- // tangle:pos tex.web:5925:3:
- // Procedure |new_save_level| is called when a group begins. The
- // argument is a group identification code like `|hbox_group|'. After
- // calling this routine, it is safe to put five more entries on |save_stack|.
- //
- // In some cases integer-valued items are placed onto the
- // |save_stack| just below a |level_boundary| word, because this is a
- // convenient place to keep information that is supposed to “pop up” just
- // when the group has finished.
- // For example, when `\.[\\hbox to 100pt]\grp' is being treated, the 100pt
- // dimension is stored on |save_stack| just before |new_save_level| is
- // called.
- //
- // We use the notation |saved(k)| to stand for an integer item that
- // appears in location |save_ptr+k| of the save stack.
- func (prg *prg) newSaveLevel(c groupCode) {
- if int32(prg.savePtr) > int32(prg.maxSaveStack) {
- prg.maxSaveStack = prg.savePtr
- if int32(prg.maxSaveStack) > saveSize-6 {
- prg.overflow(strNumber( /* "save size" */ 541), saveSize)
- } /* \xref[TeX capacity exceeded save size][\quad save size] */
- }
- *(*prg.saveStack[prg.savePtr].hh()).b0() = byte(levelBoundary)
- *(*prg.saveStack[prg.savePtr].hh()).b1() = prg.curGroup
- *(*prg.saveStack[prg.savePtr].hh()).rh() = prg.curBoundary
- if int32(prg.curLevel) == maxQuarterword {
- prg.overflow(strNumber( /* "grouping levels" */ 542), maxQuarterword-minQuarterword)
- }
- // quit if |(cur_level+1)| is too big to be stored in |eqtb|
- prg.curBoundary = prg.savePtr
- prg.curLevel = byte(int32(prg.curLevel) + 1)
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- prg.curGroup = c
- }
- // 275.
- // tangle:pos tex.web:5953:3:
- // Just before an entry of |eqtb| is changed, the following procedure should
- // be called to update the other data structures properly. It is important
- // to keep in mind that reference counts in |mem| include references from
- // within |save_stack|, so these counts must be handled carefully.
- // \xref[reference counts]
- func (prg *prg) eqDestroy(w memoryWord) { // gets ready to forget |w|
- var (
- q halfword // |equiv| field of |w|
- )
- switch *(*w.hh()).b0() {
- case call, longCall, outerCall, longOuterCall:
- prg.deleteTokenRef(*(*w.hh()).rh())
- case glueRef:
- prg.deleteGlueRef(*(*w.hh()).rh())
- case shapeRef:
- q = *(*w.hh()).rh() // we need to free a \.[\\parshape] block
- if int32(q) != 0 {
- prg.freeNode(q, halfword(int32(*(*prg.mem[q].hh()).lh())+int32(*(*prg.mem[q].hh()).lh())+1))
- }
- // such a block is |2n+1| words long, where |n=info(q)|
- case boxRef:
- prg.flushNodeList(*(*w.hh()).rh())
- default:
- }
- }
- // 276.
- // tangle:pos tex.web:5972:3:
- // To save a value of |eqtb[p]| that was established at level |l|, we
- // can use the following subroutine.
- func (prg *prg) eqSave(p halfword, l quarterword) {
- if int32(prg.savePtr) > int32(prg.maxSaveStack) {
- prg.maxSaveStack = prg.savePtr
- if int32(prg.maxSaveStack) > saveSize-6 {
- prg.overflow(strNumber( /* "save size" */ 541), saveSize)
- } /* \xref[TeX capacity exceeded save size][\quad save size] */
- }
- if int32(l) == levelZero {
- *(*prg.saveStack[prg.savePtr].hh()).b0() = byte(restoreZero)
- } else {
- prg.saveStack[prg.savePtr] = prg.eqtb[p-1]
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- *(*prg.saveStack[prg.savePtr].hh()).b0() = byte(restoreOldValue)
- }
- *(*prg.saveStack[prg.savePtr].hh()).b1() = l
- *(*prg.saveStack[prg.savePtr].hh()).rh() = p
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- }
- // 277.
- // tangle:pos tex.web:5984:3:
- // The procedure |eq_define| defines an |eqtb| entry having specified
- // |eq_type| and |equiv| fields, and saves the former value if appropriate.
- // This procedure is used only for entries in the first four regions of |eqtb|,
- // i.e., only for entries that have |eq_type| and |equiv| fields.
- // After calling this routine, it is safe to put four more entries on
- // |save_stack|, provided that there was room for four more entries before
- // the call, since |eq_save| makes the necessary test.
- func (prg *prg) eqDefine(p halfword, t quarterword, e halfword) {
- if int32(*(*prg.eqtb[p-1].hh()).b1()) == int32(prg.curLevel) {
- prg.eqDestroy(prg.eqtb[p-1])
- } else if int32(prg.curLevel) > levelOne {
- prg.eqSave(p, *(*prg.eqtb[p-1].hh()).b1())
- }
- *(*prg.eqtb[p-1].hh()).b1() = prg.curLevel
- *(*prg.eqtb[p-1].hh()).b0() = t
- *(*prg.eqtb[p-1].hh()).rh() = e
- }
- // 278.
- // tangle:pos tex.web:5999:3:
- // The counterpart of |eq_define| for the remaining (fullword) positions in
- // |eqtb| is called |eq_word_define|. Since |xeq_level[p]>=level_one| for all
- // |p|, a `|restore_zero|' will never be used in this case.
- func (prg *prg) eqWordDefine(p halfword, w int32) {
- if int32(prg.xeqLevel[p-5263]) != int32(prg.curLevel) {
- prg.eqSave(p, prg.xeqLevel[p-5263])
- prg.xeqLevel[p-5263] = prg.curLevel
- }
- *prg.eqtb[p-1].int() = w
- }
- // 279.
- // tangle:pos tex.web:6010:3:
- // The |eq_define| and |eq_word_define| routines take care of local definitions.
- // \xref[global definitions]
- // Global definitions are done in almost the same way, but there is no need
- // to save old values, and the new value is associated with |level_one|.
- func (prg *prg) geqDefine(p halfword, t quarterword, e halfword) {
- prg.eqDestroy(prg.eqtb[p-1])
- *(*prg.eqtb[p-1].hh()).b1() = byte(levelOne)
- *(*prg.eqtb[p-1].hh()).b0() = t
- *(*prg.eqtb[p-1].hh()).rh() = e
- }
- func (prg *prg) geqWordDefine(p halfword, w int32) {
- *prg.eqtb[p-1].int() = w
- prg.xeqLevel[p-5263] = byte(levelOne)
- }
- // 280.
- // tangle:pos tex.web:6025:3:
- // Subroutine |save_for_after| puts a token on the stack for save-keeping.
- func (prg *prg) saveForAfter(t halfword) {
- if int32(prg.curLevel) > levelOne {
- if int32(prg.savePtr) > int32(prg.maxSaveStack) {
- prg.maxSaveStack = prg.savePtr
- if int32(prg.maxSaveStack) > saveSize-6 {
- prg.overflow(strNumber( /* "save size" */ 541), saveSize)
- } /* \xref[TeX capacity exceeded save size][\quad save size] */
- }
- *(*prg.saveStack[prg.savePtr].hh()).b0() = byte(insertToken)
- *(*prg.saveStack[prg.savePtr].hh()).b1() = byte(levelZero)
- *(*prg.saveStack[prg.savePtr].hh()).rh() = t
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- }
- } // \2
- func (prg *prg) unsave() {
- var (
- p halfword // position to be restored
- l quarterword // saved level, if in fullword regions of |eqtb|
- t halfword // saved value of |cur_tok|
- )
- if int32(prg.curLevel) > levelOne {
- prg.curLevel = byte(int32(prg.curLevel) - 1)
- // Clear off top level from |save_stack|
- for true {
- prg.savePtr = uint16(int32(prg.savePtr) - 1)
- if int32(*(*prg.saveStack[prg.savePtr].hh()).b0()) == levelBoundary {
- goto done
- }
- p = *(*prg.saveStack[prg.savePtr].hh()).rh()
- if int32(*(*prg.saveStack[prg.savePtr].hh()).b0()) == insertToken {
- t = prg.curTok
- prg.curTok = p
- prg.backInput()
- prg.curTok = t
- } else {
- if int32(*(*prg.saveStack[prg.savePtr].hh()).b0()) == restoreOldValue {
- l = *(*prg.saveStack[prg.savePtr].hh()).b1()
- prg.savePtr = uint16(int32(prg.savePtr) - 1)
- } else {
- prg.saveStack[prg.savePtr] = prg.eqtb[undefinedControlSequence-1]
- }
- // Store \(s)|save_stack[save_ptr]| in |eqtb[p]|, unless |eqtb[p]| holds a global value
- if int32(p) < intBase {
- if int32(*(*prg.eqtb[p-1].hh()).b1()) == levelOne {
- prg.eqDestroy(prg.saveStack[prg.savePtr]) // destroy the saved value
- // if eqtb[int_base+ tracing_restores_code].int >0 then restore_trace(p,["retaining"=]544); [ ]
- } else {
- prg.eqDestroy(prg.eqtb[p-1]) // destroy the current value
- prg.eqtb[p-1] = prg.saveStack[prg.savePtr] // restore the saved value
- // if eqtb[int_base+ tracing_restores_code].int >0 then restore_trace(p,["restoring"=]545); [ ]
- }
- } else if int32(prg.xeqLevel[p-5263]) != levelOne {
- prg.eqtb[p-1] = prg.saveStack[prg.savePtr]
- prg.xeqLevel[p-5263] = l
- // if eqtb[int_base+ tracing_restores_code].int >0 then restore_trace(p,["restoring"=]545); [ ]
- } else {
- }
- }
- }
- done:
- prg.curGroup = *(*prg.saveStack[prg.savePtr].hh()).b1()
- prg.curBoundary = *(*prg.saveStack[prg.savePtr].hh()).rh()
- } else {
- prg.confusion(strNumber( /* "curlevel" */ 543))
- } // |unsave| is not used when |cur_group=bottom_level|
- // \xref[this can't happen curlevel][\quad curlevel]
- }
- // 288.
- // tangle:pos tex.web:6129:3:
- // The |prepare_mag| subroutine is called whenever \TeX\ wants to use |mag|
- // for magnification.
- func (prg *prg) prepareMag() {
- if prg.magSet > 0 && *prg.eqtb[intBase+magCode-1].int() != prg.magSet {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Incompatible magnification (" */ 547)
- }
- prg.printInt(*prg.eqtb[intBase+magCode-1].int())
- // \xref[Incompatible magnification]
- prg.print( /* ");" */ 548)
- prg.printNl(strNumber( /* " the previous value will be retained" */ 549))
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I can handle only one magnification ratio per job. So I've" */ 550
- prg.helpLine[0] = /* "reverted to the magnification you used earlier on this run." */ 551
- }
- prg.intError(prg.magSet)
- prg.geqWordDefine(halfword(intBase+magCode), prg.magSet) // |mag:=mag_set|
- }
- if *prg.eqtb[intBase+magCode-1].int() <= 0 || *prg.eqtb[intBase+magCode-1].int() > 32768 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Illegal magnification has been changed to 1000" */ 552)
- }
- // \xref[Illegal magnification...]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "The magnification ratio must be between 1 and 32768." */ 553
- }
- prg.intError(*prg.eqtb[intBase+magCode-1].int())
- prg.geqWordDefine(halfword(intBase+magCode), 1000)
- }
- prg.magSet = *prg.eqtb[intBase+magCode-1].int()
- }
- // 289. \[20] Token lists
- // tangle:pos tex.web:6151:22:
- // A \TeX\ token is either a character or a control sequence, and it is
- // \xref[token]
- // represented internally in one of two ways: (1)~A character whose ASCII
- // code number is |c| and whose command code is |m| is represented as the
- // number $2^8m+c$; the command code is in the range |1<=m<=14|. (2)~A control
- // sequence whose |eqtb| address is |p| is represented as the number
- // |cs_token_flag+p|. Here |cs_token_flag=$2^[12]-1$| is larger than
- // $2^8m+c$, yet it is small enough that |cs_token_flag+p< max_halfword|;
- // thus, a token fits comfortably in a halfword.
- //
- // A token |t| represents a |left_brace| command if and only if
- // |t<left_brace_limit|; it represents a |right_brace| command if and only if
- // we have |left_brace_limit<=t<right_brace_limit|; and it represents a |match| or
- // |end_match| command if and only if |match_token<=t<=end_match_token|.
- // The following definitions take care of these token-oriented constants
- // and a few others.
- // 291.
- // tangle:pos tex.web:6187:3:
- // A token list is a singly linked list of one-word nodes in |mem|, where
- // each word contains a token and a link. Macro definitions, output-routine
- // definitions, marks, \.[\\write] texts, and a few other things
- // are remembered by \TeX\ in the form
- // of token lists, usually preceded by a node with a reference count in its
- // |token_ref_count| field. The token stored in location |p| is called
- // |info(p)|.
- //
- // Three special commands appear in the token lists of macro definitions.
- // When |m=match|, it means that \TeX\ should scan a parameter
- // for the current macro; when |m=end_match|, it means that parameter
- // matching should end and \TeX\ should start reading the macro text; and
- // when |m=out_param|, it means that \TeX\ should insert parameter
- // number |c| into the text at this point.
- //
- // The enclosing \.[\char'173] and \.[\char'175] characters of a macro
- // definition are omitted, but an output routine
- // will be enclosed in braces.
- //
- // Here is an example macro definition that illustrates these conventions.
- // After \TeX\ processes the text
- // $$\.[\\def\\mac a\#1\#2 \\b \[\#1\\-a \#\#1\#2 \#2\]]$$
- // the definition of \.[\\mac] is represented as a token list containing
- // $$\def\,[\hskip2pt]
- // \vbox[\halign[\hfil#\hfil\cr
- // (reference count), |letter|\,\.a, |match|\,\#, |match|\,\#, |spacer|\,\.\ ,
- // \.[\\b], |end_match|,\cr
- // |out_param|\,1, \.[\\-], |letter|\,\.a, |spacer|\,\.\ , |mac_param|\,\#,
- // |other_char|\,\.1,\cr
- // |out_param|\,2, |spacer|\,\.\ , |out_param|\,2.\cr]]$$
- // The procedure |scan_toks| builds such token lists, and |macro_call|
- // does the parameter matching.
- // \xref[reference counts]
- //
- // Examples such as
- // $$\.[\\def\\m\[\\def\\m\[a\]\ b\]]$$
- // explain why reference counts would be needed even if \TeX\ had no \.[\\let]
- // operation: When the token list for \.[\\m] is being read, the redefinition of
- // \.[\\m] changes the |eqtb| entry before the token list has been fully
- // consumed, so we dare not simply destroy a token list when its
- // control sequence is being redefined.
- //
- // If the parameter-matching part of a definition ends with `\.[\#\[]',
- // the corresponding token list will have `\.\[' just before the `|end_match|'
- // and also at the very end. The first `\.\[' is used to delimit the parameter; the
- // second one keeps the first from disappearing.
- // 295.
- // tangle:pos tex.web:6313:3:
- // Here's the way we sometimes want to display a token list, given a pointer
- // to its reference count; the pointer may be null.
- func (prg *prg) tokenShow(p halfword) {
- if int32(p) != 0 {
- prg.showTokenList(int32(*(*prg.mem[p].hh()).rh()), 0, 10000000)
- }
- }
- // 296.
- // tangle:pos tex.web:6320:3:
- // The |print_meaning| subroutine displays |cur_cmd| and |cur_chr| in
- // symbolic form, including the expansion of a macro or mark.
- func (prg *prg) printMeaning() {
- prg.printCmdChr(prg.curCmd, prg.curChr)
- if int32(prg.curCmd) >= call {
- prg.printChar(asciiCode(':'))
- prg.printLn()
- prg.tokenShow(prg.curChr)
- } else if int32(prg.curCmd) == topBotMark {
- prg.printChar(asciiCode(':'))
- prg.printLn()
- prg.tokenShow(prg.curMark[prg.curChr])
- }
- }
- // 299.
- // tangle:pos tex.web:6419:3:
- // Here is a procedure that displays the current command.
- func (prg *prg) showCurCmdChr() {
- prg.beginDiagnostic()
- prg.printNl(strNumber('{'))
- if int32(prg.curList.modeField) != int32(prg.shownMode) {
- prg.printMode(int32(prg.curList.modeField))
- prg.print( /* ": " */ 568)
- prg.shownMode = prg.curList.modeField
- }
- prg.printCmdChr(prg.curCmd, prg.curChr)
- prg.printChar(asciiCode('}'))
- prg.endDiagnostic(false)
- } // \2
- func (prg *prg) showContext() {
- var (
- oldSetting/* 0..maxSelector */ byte // saved |selector| setting
- nn int32 // number of contexts shown so far, less one
- bottomLine bool // have we reached the final context to be shown?
- // Local variables for formatting calculations
- i/* 0..bufSize */ uint16 // index into |buffer|
- j/* 0..bufSize */ uint16 // end of current line in |buffer|
- l/* 0..halfErrorLine */ byte // length of descriptive information on line 1
- m int32 // context information gathered for line 2
- n/* 0..errorLine */ byte // length of line 1
- p int32 // starting or ending place in |trick_buf|
- q int32 // temporary index
- )
- prg.basePtr = prg.inputPtr
- prg.inputStack[prg.basePtr] = prg.curInput
- // store current state
- nn = -1
- bottomLine = false
- for true {
- prg.curInput = prg.inputStack[prg.basePtr] // enter into the context
- if int32(prg.curInput.stateField) != tokenList {
- if int32(prg.curInput.nameField) > 17 || int32(prg.basePtr) == 0 {
- bottomLine = true
- }
- }
- if int32(prg.basePtr) == int32(prg.inputPtr) || bottomLine || nn < *prg.eqtb[intBase+errorContextLinesCode-1].int() {
- if int32(prg.basePtr) == int32(prg.inputPtr) || int32(prg.curInput.stateField) != tokenList || int32(prg.curInput.indexField) != backedUp || int32(prg.curInput.locField) != 0 {
- prg.tally = 0 // get ready to count characters
- oldSetting = prg.selector
- if int32(prg.curInput.stateField) != tokenList {
- if int32(prg.curInput.nameField) <= 17 {
- if int32(prg.curInput.nameField) == 0 {
- if int32(prg.basePtr) == 0 {
- prg.printNl(strNumber( /* "<*>" */ 574))
- } else {
- prg.printNl(strNumber( /* "<insert> " */ 575))
- }
- } else {
- prg.printNl(strNumber( /* "<read " */ 576))
- if int32(prg.curInput.nameField) == 17 {
- prg.printChar(asciiCode('*'))
- } else {
- prg.printInt(int32(prg.curInput.nameField) - 1)
- }
- // \xref[*\relax]
- prg.printChar(asciiCode('>'))
- }
- } else {
- prg.printNl(strNumber( /* "l." */ 577))
- prg.printInt(prg.line)
- }
- prg.printChar(asciiCode(' '))
- // Pseudoprint the line
- {
- l = byte(prg.tally)
- prg.tally = 0
- prg.selector = byte(pseudo)
- prg.trickCount = 1000000
- }
- if int32(prg.buffer[prg.curInput.limitField]) == *prg.eqtb[intBase+endLineCharCode-1].int() {
- j = prg.curInput.limitField
- } else {
- j = uint16(int32(prg.curInput.limitField) + 1)
- } // determine the effective end of the line
- if int32(j) > 0 {
- for ii := int32(prg.curInput.startField); ii <= int32(j)-1; ii++ {
- i = uint16(ii)
- _ = i
- if int32(i) == int32(prg.curInput.locField) {
- prg.firstCount = prg.tally
- prg.trickCount = prg.tally + 1 + errorLine - halfErrorLine
- if prg.trickCount < errorLine {
- prg.trickCount = errorLine
- }
- }
- prg.print(int32(prg.buffer[i]))
- }
- }
- } else {
- switch prg.curInput.indexField {
- case parameter:
- prg.printNl(strNumber( /* "<argument> " */ 578))
- case uTemplate, vTemplate:
- prg.printNl(strNumber( /* "<template> " */ 579))
- case backedUp:
- if int32(prg.curInput.locField) == 0 {
- prg.printNl(strNumber( /* "<recently read> " */ 580))
- } else {
- prg.printNl(strNumber( /* "<to be read again> " */ 581))
- }
- case inserted:
- prg.printNl(strNumber( /* "<inserted text> " */ 582))
- case macro:
- prg.printLn()
- prg.printCs(int32(prg.curInput.nameField))
- case outputText:
- prg.printNl(strNumber( /* "<output> " */ 583))
- case everyParText:
- prg.printNl(strNumber( /* "<everypar> " */ 584))
- case everyMathText:
- prg.printNl(strNumber( /* "<everymath> " */ 585))
- case everyDisplayText:
- prg.printNl(strNumber( /* "<everydisplay> " */ 586))
- case everyHboxText:
- prg.printNl(strNumber( /* "<everyhbox> " */ 587))
- case everyVboxText:
- prg.printNl(strNumber( /* "<everyvbox> " */ 588))
- case everyJobText:
- prg.printNl(strNumber( /* "<everyjob> " */ 589))
- case everyCrText:
- prg.printNl(strNumber( /* "<everycr> " */ 590))
- case markText:
- prg.printNl(strNumber( /* "<mark> " */ 591))
- case writeText:
- prg.printNl(strNumber( /* "<write> " */ 592))
- default:
- prg.printNl(strNumber('?')) // this should never happen
- }
- // Pseudoprint the token list
- {
- l = byte(prg.tally)
- prg.tally = 0
- prg.selector = byte(pseudo)
- prg.trickCount = 1000000
- }
- if int32(prg.curInput.indexField) < macro {
- prg.showTokenList(int32(prg.curInput.startField), int32(prg.curInput.locField), 100000)
- } else {
- prg.showTokenList(int32(*(*prg.mem[prg.curInput.startField].hh()).rh()), int32(prg.curInput.locField), 100000)
- }
- }
- prg.selector = oldSetting // stop pseudoprinting
- // Print two lines using the tricky pseudoprinted information
- if prg.trickCount == 1000000 {
- prg.firstCount = prg.tally
- prg.trickCount = prg.tally + 1 + errorLine - halfErrorLine
- if prg.trickCount < errorLine {
- prg.trickCount = errorLine
- }
- }
- // |set_trick_count| must be performed
- if prg.tally < prg.trickCount {
- m = prg.tally - prg.firstCount
- } else {
- m = prg.trickCount - prg.firstCount
- } // context on line 2
- if int32(l)+prg.firstCount <= halfErrorLine {
- p = 0
- n = byte(int32(l) + prg.firstCount)
- } else {
- prg.print( /* "..." */ 277)
- p = int32(l) + prg.firstCount - halfErrorLine + 3
- n = byte(halfErrorLine)
- }
- for ii := p; ii <= prg.firstCount-1; ii++ {
- q = ii
- _ = q
- prg.printChar(prg.trickBuf[q%errorLine])
- }
- prg.printLn()
- for ii := int32(1); ii <= int32(n); ii++ {
- q = ii
- _ = q
- prg.printChar(asciiCode(' '))
- } // print |n| spaces to begin line~2
- if m+int32(n) <= errorLine {
- p = prg.firstCount + m
- } else {
- p = prg.firstCount + (errorLine - int32(n) - 3)
- }
- for ii := prg.firstCount; ii <= p-1; ii++ {
- q = ii
- _ = q
- prg.printChar(prg.trickBuf[q%errorLine])
- }
- if m+int32(n) > errorLine {
- prg.print( /* "..." */ 277)
- }
- nn = nn + 1
- }
- } else if nn == *prg.eqtb[intBase+errorContextLinesCode-1].int() {
- prg.printNl(strNumber( /* "..." */ 277))
- nn = nn + 1 // omitted if |error_context_lines<0|
- }
- if bottomLine {
- goto done
- }
- prg.basePtr = byte(int32(prg.basePtr) - 1)
- }
- done:
- prg.curInput = prg.inputStack[prg.inputPtr] // restore original state
- }
- // 316.
- // tangle:pos tex.web:6886:3:
- // The following code sets up the print routines so that they will gather
- // the desired information.
- // 321. \[23] Maintaining the input stacks
- // tangle:pos tex.web:6942:39:
- // The following subroutines change the input status in commonly needed ways.
- //
- // First comes |push_input|, which stores the current state and creates a
- // new level (having, initially, the same properties as the old).
- // 322.
- // tangle:pos tex.web:6958:3:
- // And of course what goes up must come down.
- // 323.
- // tangle:pos tex.web:6964:3:
- // Here is a procedure that starts a new level of token-list input, given
- // a token list |p| and its type |t|. If |t=macro|, the calling routine should
- // set |name| and |loc|.
- func (prg *prg) beginTokenList(p halfword, t quarterword) {
- {
- if int32(prg.inputPtr) > int32(prg.maxInStack) {
- prg.maxInStack = prg.inputPtr
- if int32(prg.inputPtr) == stackSize {
- prg.overflow(strNumber( /* "input stack size" */ 593), stackSize)
- } /* \xref[TeX capacity exceeded input stack size][\quad input stack size] */
- }
- prg.inputStack[prg.inputPtr] = prg.curInput
- prg.inputPtr = byte(int32(prg.inputPtr) + 1)
- }
- prg.curInput.stateField = byte(tokenList)
- prg.curInput.startField = p
- prg.curInput.indexField = t
- if int32(t) >= macro {
- *(*prg.mem[p].hh()).lh() = uint16(int32(*(*prg.mem[p].hh()).lh()) + 1)
- if int32(t) == macro {
- prg.curInput.limitField = uint16(prg.paramPtr)
- } else {
- prg.curInput.locField = *(*prg.mem[p].hh()).rh()
- if *prg.eqtb[intBase+tracingMacrosCode-1].int() > 1 {
- prg.beginDiagnostic()
- prg.printNl(strNumber( /* "" */ 338))
- switch t {
- case markText:
- prg.printEsc(strNumber( /* "mark" */ 351))
- case writeText:
- prg.printEsc(strNumber( /* "write" */ 594))
- default:
- prg.printCmdChr(quarterword(assignToks), halfword(int32(t)-outputText+outputRoutineLoc))
- }
- prg.print( /* "->" */ 556)
- prg.tokenShow(p)
- prg.endDiagnostic(false)
- }
- }
- } else {
- prg.curInput.locField = p
- }
- }
- // 324.
- // tangle:pos tex.web:6991:3:
- // When a token list has been fully scanned, the following computations
- // should be done as we leave that level of input. The |token_type| tends
- // to be equal to either |backed_up| or |inserted| about 2/3 of the time.
- // \xref[inner loop]
- func (prg *prg) endTokenList() {
- if int32(prg.curInput.indexField) >= backedUp {
- if int32(prg.curInput.indexField) <= inserted {
- prg.flushList(prg.curInput.startField)
- } else {
- prg.deleteTokenRef(prg.curInput.startField) // update reference count
- if int32(prg.curInput.indexField) == macro {
- for int32(prg.paramPtr) > int32(prg.curInput.limitField) {
- prg.paramPtr = byte(int32(prg.paramPtr) - 1)
- prg.flushList(prg.paramStack[prg.paramPtr])
- }
- }
- }
- } else if int32(prg.curInput.indexField) == uTemplate {
- if prg.alignState > 500000 {
- prg.alignState = 0
- } else {
- prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
- }
- }
- // \xref[interwoven alignment preambles...]
- //
- {
- prg.inputPtr = byte(int32(prg.inputPtr) - 1)
- prg.curInput = prg.inputStack[prg.inputPtr]
- }
- {
- if prg.interrupt != 0 {
- prg.pauseForInstructions()
- }
- }
- }
- // 281.
- // tangle:pos tex.web:6035:3:
- // The |unsave| routine goes the other way, taking items off of |save_stack|.
- // This routine takes care of restoration when a level ends; everything
- // belonging to the topmost group is cleared off of the save stack.
- // \4
- // Declare the procedure called |restore_trace|
- // procedure restore_trace( p:halfword ; s:str_number);
- // [|eqtb[p]| has just been restored or retained]
- // begin begin_diagnostic; print_char(["["=]123); print(s); print_char([" "=]32);
- // show_eqtb(p); print_char(["]"=]125);
- // end_diagnostic(false);
- // end;
- // [ ]
- func (prg *prg) backInput() { // undoes one token of input
- var (
- p halfword // a token list of length one
- )
- for int32(prg.curInput.stateField) == tokenList && int32(prg.curInput.locField) == 0 && int32(prg.curInput.indexField) != vTemplate {
- prg.endTokenList()
- } // conserve stack space
- p = prg.getAvail()
- *(*prg.mem[p].hh()).lh() = prg.curTok
- if int32(prg.curTok) < rightBraceLimit {
- if int32(prg.curTok) < leftBraceLimit {
- prg.alignState = prg.alignState - 1
- } else {
- prg.alignState = prg.alignState + 1
- }
- }
- /* */ {
- if int32(prg.inputPtr) > int32(prg.maxInStack) {
- prg.maxInStack = prg.inputPtr
- if int32(prg.inputPtr) == stackSize {
- prg.overflow(strNumber( /* "input stack size" */ 593), stackSize)
- } /* \xref[TeX capacity exceeded input stack size][\quad input stack size] */
- }
- prg.inputStack[prg.inputPtr] = prg.curInput
- prg.inputPtr = byte(int32(prg.inputPtr) + 1)
- }
- prg.curInput.stateField = byte(tokenList)
- prg.curInput.startField = p
- prg.curInput.indexField = byte(backedUp)
- prg.curInput.locField = p // that was |back_list(p)|, without procedure overhead
- }
- // 327.
- // tangle:pos tex.web:7039:3:
- // The |back_error| routine is used when we want to replace an offending token
- // just before issuing an error message. This routine, like |back_input|,
- // requires that |cur_tok| has been set. We disable interrupts during the
- // call of |back_input| so that the help message won't be lost.
- func (prg *prg) backError() {
- prg.okToInterrupt = false
- prg.backInput()
- prg.okToInterrupt = true
- prg.error1()
- }
- func (prg *prg) insError() {
- prg.okToInterrupt = false
- prg.backInput()
- prg.curInput.indexField = byte(inserted)
- prg.okToInterrupt = true
- prg.error1()
- } // \2
- func (prg *prg) beginFileReading() {
- if int32(prg.inOpen) == maxInOpen {
- prg.overflow(strNumber( /* "text input levels" */ 596), maxInOpen)
- }
- // \xref[TeX capacity exceeded text input levels][\quad text input levels]
- if int32(prg.first) == bufSize {
- prg.overflow(strNumber( /* "buffer size" */ 256), bufSize)
- }
- // \xref[TeX capacity exceeded buffer size][\quad buffer size]
- prg.inOpen = byte(int32(prg.inOpen) + 1) /* */
- {
- if int32(prg.inputPtr) > int32(prg.maxInStack) {
- prg.maxInStack = prg.inputPtr
- if int32(prg.inputPtr) == stackSize {
- prg.overflow(strNumber( /* "input stack size" */ 593), stackSize)
- } /* \xref[TeX capacity exceeded input stack size][\quad input stack size] */
- }
- prg.inputStack[prg.inputPtr] = prg.curInput
- prg.inputPtr = byte(int32(prg.inputPtr) + 1)
- }
- prg.curInput.indexField = prg.inOpen
- prg.lineStack[prg.curInput.indexField-1] = prg.line
- prg.curInput.startField = prg.first
- prg.curInput.stateField = byte(midLine)
- prg.curInput.nameField = 0 // |terminal_input| is now |true|
- }
- // 329.
- // tangle:pos tex.web:7069:3:
- // Conversely, the variables must be downdated when such a level of input
- // is finished:
- func (prg *prg) endFileReading() {
- prg.first = prg.curInput.startField
- prg.line = prg.lineStack[prg.curInput.indexField-1]
- if int32(prg.curInput.nameField) > 17 {
- prg.aClose(prg.inputFile[prg.curInput.indexField-1])
- } // forget it
- //
- {
- prg.inputPtr = byte(int32(prg.inputPtr) - 1)
- prg.curInput = prg.inputStack[prg.inputPtr]
- }
- prg.inOpen = byte(int32(prg.inOpen) - 1)
- } // \2
- func (prg *prg) clearForErrorPrompt() {
- for int32(prg.curInput.stateField) != tokenList && int32(prg.curInput.nameField) == 0 && int32(prg.inputPtr) > 0 && int32(prg.curInput.locField) > int32(prg.curInput.limitField) {
- prg.endFileReading()
- }
- prg.printLn()
- }
- // 332. \[24] Getting the next token
- // tangle:pos tex.web:7104:33:
- // The heart of \TeX's input mechanism is the |get_next| procedure, which
- // we shall develop in the next few sections of the program. Perhaps we
- // shouldn't actually call it the ``heart,'' however, because it really acts
- // as \TeX's eyes and mouth, reading the source files and gobbling them up.
- // And it also helps \TeX\ to regurgitate stored token lists that are to be
- // processed again.
- // \xref[eyes and mouth]
- //
- // The main duty of |get_next| is to input one token and to set |cur_cmd|
- // and |cur_chr| to that token's command code and modifier. Furthermore, if
- // the input token is a control sequence, the |eqtb| location of that control
- // sequence is stored in |cur_cs|; otherwise |cur_cs| is set to zero.
- //
- // Underlying this simple description is a certain amount of complexity
- // because of all the cases that need to be handled.
- // However, the inner loop of |get_next| is reasonably short and fast.
- //
- // When |get_next| is asked to get the next token of a \.[\\read] line,
- // it sets |cur_cmd=cur_chr=cur_cs=0| in the case that no more tokens
- // appear on that line. (There might not be any tokens at all, if the
- // |end_line_char| has |ignore| as its catcode.)
- // 336.
- // tangle:pos tex.web:7144:3:
- // Before getting into |get_next|, let's consider the subroutine that
- // is called when an `\.[\\outer]' control sequence has been scanned or
- // when the end of a file has been reached. These two cases are distinguished
- // by |cur_cs|, which is zero at the end of a file.
- func (prg *prg) checkOuterValidity() {
- var (
- p halfword // points to inserted token list
- q halfword // auxiliary pointer
- )
- if int32(prg.scannerStatus) != normal {
- prg.deletionsAllowed = false
- // Back up an outer control sequence so that it can be reread
- if int32(prg.curCs) != 0 {
- if int32(prg.curInput.stateField) == tokenList || int32(prg.curInput.nameField) < 1 || int32(prg.curInput.nameField) > 17 {
- p = prg.getAvail()
- *(*prg.mem[p].hh()).lh() = uint16(07777 + int32(prg.curCs))
- prg.beginTokenList(p, quarterword(backedUp)) // prepare to read the control sequence again
- }
- prg.curCmd = byte(spacer)
- prg.curChr = ' ' // replace it by a space
- }
- if int32(prg.scannerStatus) > skipping {
- prg.runaway() // print a definition, argument, or preamble
- if int32(prg.curCs) == 0 {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "File ended" */ 604)
- } else {
- prg.curCs = 0
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Forbidden control sequence found" */ 605)
- }
- // \xref[Forbidden control sequence...]
- }
- prg.print( /* " while scanning " */ 606)
- // Print either `\.[definition]' or `\.[use]' or `\.[preamble]' or `\.[text]', and insert tokens that should lead to recovery
- p = prg.getAvail()
- switch prg.scannerStatus {
- case defining:
- prg.print( /* "definition" */ 570)
- *(*prg.mem[p].hh()).lh() = uint16(rightBraceToken + '}')
- case matching:
- prg.print( /* "use" */ 612)
- *(*prg.mem[p].hh()).lh() = prg.parToken
- prg.longState = byte(outerCall)
- case aligning:
- prg.print( /* "preamble" */ 572)
- *(*prg.mem[p].hh()).lh() = uint16(rightBraceToken + '}')
- q = p
- p = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[p].hh()).lh() = uint16(07777 + frozenCr)
- prg.alignState = -1000000
- case absorbing:
- prg.print( /* "text" */ 573)
- *(*prg.mem[p].hh()).lh() = uint16(rightBraceToken + '}')
- } // there are no other cases
- prg.beginTokenList(p, quarterword(inserted))
- prg.print( /* " of " */ 607)
- prg.sprintCs(prg.warningIndex)
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "I suspect you have forgotten a `]', causing me" */ 608
- prg.helpLine[2] = /* "to read past where you wanted me to stop." */ 609
- prg.helpLine[1] = /* "I'll try to recover; but if the error is serious," */ 610
- prg.helpLine[0] = /* "you'd better type `E' or `X' now and fix your file." */ 611
- }
- prg.error1()
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Incomplete " */ 598)
- }
- prg.printCmdChr(quarterword(ifTest), halfword(prg.curIf))
- // \xref[Incomplete \\if...]
- prg.print( /* "; all text was ignored after line " */ 599)
- prg.printInt(prg.skipLine)
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "A forbidden control sequence occurred in skipped text." */ 600
- prg.helpLine[1] = /* "This kind of error happens when you say `\\if...' and forget" */ 601
- prg.helpLine[0] = /* "the matching `\\fi'. I've inserted a `\\fi'; this might work." */ 602
- }
- if int32(prg.curCs) != 0 {
- prg.curCs = 0
- } else {
- prg.helpLine[2] =
- /* "The file ended while I was skipping conditional text." */ 603
- }
- prg.curTok = uint16(07777 + frozenFi)
- prg.insError()
- }
- prg.deletionsAllowed = true
- }
- }
- // 341.
- // tangle:pos tex.web:7230:3:
- // Now we're ready to take the plunge into |get_next| itself. Parts of
- // this routine are executed more often than any other instructions of \TeX.
- // \xref[mastication]\xref[inner loop]
- func (prg *prg) getNext() { // go here when the next input token has been got
- var (
- k/* 0..bufSize */ uint16 // an index into |buffer|
- t halfword // a token
- cat/* 0..maxCharCode */ byte // |cat_code(cur_chr)|, usually
- c, cc asciiCode // constituents of a possible expanded code
- d/* 2..3 */ byte // number of excess characters in an expanded code
- )
- restart:
- prg.curCs = 0
- if int32(prg.curInput.stateField) != tokenList {
- switch1:
- if int32(prg.curInput.locField) <= int32(prg.curInput.limitField) {
- prg.curChr = uint16(prg.buffer[prg.curInput.locField])
- prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
- reswitch:
- prg.curCmd = byte(*(*prg.eqtb[catCodeBase+int32(prg.curChr)-1].hh()).rh())
- // Change state if necessary, and |goto switch| if the current character should be ignored, or |goto reswitch| if the current character changes to another
- switch int32(prg.curInput.stateField) + int32(prg.curCmd) {
- case midLine + 9, skipBlanks + 9, newLine + 9, skipBlanks + 10,
- newLine + 10:
- goto switch1
- case midLine + 0, skipBlanks + 0, newLine + 0:
- // Scan a control sequence and set |state:=skip_blanks| or |mid_line|
- if int32(prg.curInput.locField) > int32(prg.curInput.limitField) {
- prg.curCs = uint16(nullCs)
- } else {
- startCs:
- k = prg.curInput.locField
- prg.curChr = uint16(prg.buffer[k])
- cat = byte(*(*prg.eqtb[catCodeBase+int32(prg.curChr)-1].hh()).rh())
- k = uint16(int32(k) + 1)
- if int32(cat) == letter {
- prg.curInput.stateField = byte(skipBlanks)
- } else if int32(cat) == spacer {
- prg.curInput.stateField = byte(skipBlanks)
- } else {
- prg.curInput.stateField = byte(midLine)
- }
- if int32(cat) == letter && int32(k) <= int32(prg.curInput.limitField) {
- for {
- prg.curChr = uint16(prg.buffer[k])
- cat = byte(*(*prg.eqtb[catCodeBase+int32(prg.curChr)-1].hh()).rh())
- k = uint16(int32(k) + 1)
- if int32(cat) != letter || int32(k) > int32(prg.curInput.limitField) {
- break
- }
- }
- // If an expanded...
- {
- if int32(prg.buffer[k]) == int32(prg.curChr) {
- if int32(cat) == supMark {
- if int32(k) < int32(prg.curInput.limitField) {
- c = prg.buffer[int32(k)+1]
- if int32(c) < 0200 {
- d = 2
- if int32(c) >= '0' && int32(c) <= '9' || int32(c) >= 'a' && int32(c) <= 'f' {
- if int32(k)+2 <= int32(prg.curInput.limitField) {
- cc = prg.buffer[int32(k)+2]
- if int32(cc) >= '0' && int32(cc) <= '9' || int32(cc) >= 'a' && int32(cc) <= 'f' {
- d = byte(int32(d) + 1)
- }
- }
- }
- if int32(d) > 2 {
- if int32(c) <= '9' {
- prg.curChr = uint16(int32(c) - '0')
- } else {
- prg.curChr = uint16(int32(c) - 'a' + 10)
- }
- if int32(cc) <= '9' {
- prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - '0')
- } else {
- prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - 'a' + 10)
- }
- prg.buffer[int32(k)-1] = byte(prg.curChr)
- } else if int32(c) < 0100 {
- prg.buffer[int32(k)-1] = byte(int32(c) + 0100)
- } else {
- prg.buffer[int32(k)-1] = byte(int32(c) - 0100)
- }
- prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - int32(d))
- prg.first = uint16(int32(prg.first) - int32(d))
- for int32(k) <= int32(prg.curInput.limitField) {
- prg.buffer[k] = prg.buffer[int32(k)+int32(d)]
- k = uint16(int32(k) + 1)
- }
- goto startCs
- }
- }
- }
- }
- }
- if int32(cat) != letter {
- k = uint16(int32(k) - 1)
- }
- // now |k| points to first nonletter
- if int32(k) > int32(prg.curInput.locField)+1 {
- prg.curCs = prg.idLookup(int32(prg.curInput.locField), int32(k)-int32(prg.curInput.locField))
- prg.curInput.locField = k
- goto found
- }
- } else {
- // If an expanded code is present, reduce it and |goto start_cs|
- if int32(prg.buffer[k]) == int32(prg.curChr) {
- if int32(cat) == supMark {
- if int32(k) < int32(prg.curInput.limitField) {
- c = prg.buffer[int32(k)+1]
- if int32(c) < 0200 {
- d = 2
- if int32(c) >= '0' && int32(c) <= '9' || int32(c) >= 'a' && int32(c) <= 'f' {
- if int32(k)+2 <= int32(prg.curInput.limitField) {
- cc = prg.buffer[int32(k)+2]
- if int32(cc) >= '0' && int32(cc) <= '9' || int32(cc) >= 'a' && int32(cc) <= 'f' {
- d = byte(int32(d) + 1)
- }
- }
- }
- if int32(d) > 2 {
- if int32(c) <= '9' {
- prg.curChr = uint16(int32(c) - '0')
- } else {
- prg.curChr = uint16(int32(c) - 'a' + 10)
- }
- if int32(cc) <= '9' {
- prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - '0')
- } else {
- prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - 'a' + 10)
- }
- prg.buffer[int32(k)-1] = byte(prg.curChr)
- } else if int32(c) < 0100 {
- prg.buffer[int32(k)-1] = byte(int32(c) + 0100)
- } else {
- prg.buffer[int32(k)-1] = byte(int32(c) - 0100)
- }
- prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - int32(d))
- prg.first = uint16(int32(prg.first) - int32(d))
- for int32(k) <= int32(prg.curInput.limitField) {
- prg.buffer[k] = prg.buffer[int32(k)+int32(d)]
- k = uint16(int32(k) + 1)
- }
- goto startCs
- }
- }
- }
- }
- }
- prg.curCs = uint16(singleBase + int32(prg.buffer[prg.curInput.locField]))
- prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
- }
- found:
- prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
- prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
- if int32(prg.curCmd) >= outerCall {
- prg.checkOuterValidity()
- }
- case midLine + 13, skipBlanks + 13, newLine + 13:
- // Process an active-character control sequence and set |state:=mid_line|
- prg.curCs = uint16(int32(prg.curChr) + activeBase)
- prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
- prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
- prg.curInput.stateField = byte(midLine)
- if int32(prg.curCmd) >= outerCall {
- prg.checkOuterValidity()
- }
- case midLine + 7, skipBlanks + 7, newLine + 7:
- // If this |sup_mark| starts an expanded character like~\.[\^\^A] or~\.[\^\^df], then |goto reswitch|, otherwise set |state:=mid_line|
- if int32(prg.curChr) == int32(prg.buffer[prg.curInput.locField]) {
- if int32(prg.curInput.locField) < int32(prg.curInput.limitField) {
- c = prg.buffer[int32(prg.curInput.locField)+1]
- if int32(c) < 0200 {
- prg.curInput.locField = uint16(int32(prg.curInput.locField) + 2)
- if int32(c) >= '0' && int32(c) <= '9' || int32(c) >= 'a' && int32(c) <= 'f' {
- if int32(prg.curInput.locField) <= int32(prg.curInput.limitField) {
- cc = prg.buffer[prg.curInput.locField]
- if int32(cc) >= '0' && int32(cc) <= '9' || int32(cc) >= 'a' && int32(cc) <= 'f' {
- prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
- if int32(c) <= '9' {
- prg.curChr = uint16(int32(c) - '0')
- } else {
- prg.curChr = uint16(int32(c) - 'a' + 10)
- }
- if int32(cc) <= '9' {
- prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - '0')
- } else {
- prg.curChr = uint16(16*int32(prg.curChr) + int32(cc) - 'a' + 10)
- }
- goto reswitch
- }
- }
- }
- if int32(c) < 0100 {
- prg.curChr = uint16(int32(c) + 0100)
- } else {
- prg.curChr = uint16(int32(c) - 0100)
- }
- goto reswitch
- }
- }
- }
- prg.curInput.stateField = byte(midLine)
- case midLine + 15, skipBlanks + 15, newLine + 15:
- // Decry the invalid character and |goto restart|
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Text line contains an invalid character" */ 613)
- }
- // \xref[Text line contains...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "A funny symbol that I can't read has just been input." */ 614
- prg.helpLine[0] = /* "Continue, and I'll forget that it ever happened." */ 615
- }
- prg.deletionsAllowed = false
- prg.error1()
- prg.deletionsAllowed = true
- goto restart
- // \4
- // Handle situations involving spaces, braces, changes of state
- case midLine + 10:
- // Enter |skip_blanks| state, emit a space
- prg.curInput.stateField = byte(skipBlanks)
- prg.curChr = ' '
- case midLine + 5:
- // Finish line, emit a space
- prg.curInput.locField = uint16(int32(prg.curInput.limitField) + 1)
- prg.curCmd = byte(spacer)
- prg.curChr = ' '
- case skipBlanks + 5, midLine + 14, skipBlanks + 14, newLine + 14:
- // Finish line, |goto switch|
- prg.curInput.locField = uint16(int32(prg.curInput.limitField) + 1)
- goto switch1
- case newLine + 5:
- // Finish line, emit a \.[\\par]
- prg.curInput.locField = uint16(int32(prg.curInput.limitField) + 1)
- prg.curCs = prg.parLoc
- prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
- prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
- if int32(prg.curCmd) >= outerCall {
- prg.checkOuterValidity()
- }
- case midLine + 1:
- prg.alignState = prg.alignState + 1
- case skipBlanks + 1, newLine + 1:
- prg.curInput.stateField = byte(midLine)
- prg.alignState = prg.alignState + 1
- case midLine + 2:
- prg.alignState = prg.alignState - 1
- case skipBlanks + 2, newLine + 2:
- prg.curInput.stateField = byte(midLine)
- prg.alignState = prg.alignState - 1
- case skipBlanks + 3, skipBlanks + 4, skipBlanks + 6, skipBlanks + 8,
- skipBlanks + 11, skipBlanks + 12, newLine + 3, newLine + 4,
- newLine + 6, newLine + 8, newLine + 11, newLine + 12:
- prg.curInput.stateField = byte(midLine)
- default:
- }
- } else {
- prg.curInput.stateField = byte(newLine)
- // Move to next line of file, or |goto restart| if there is no next line, or |return| if a \.[\\read] line has finished
- if int32(prg.curInput.nameField) > 17 {
- prg.line = prg.line + 1
- prg.first = prg.curInput.startField
- if !prg.forceEof {
- if prg.inputLn(prg.inputFile[prg.curInput.indexField-1], true) {
- prg.firmUpTheLine()
- } else {
- prg.forceEof = true
- }
- }
- if prg.forceEof {
- prg.printChar(asciiCode(')'))
- prg.openParens = byte(int32(prg.openParens) - 1)
- // show user that file has been read
- prg.forceEof = false
- prg.endFileReading() // resume previous level
- prg.checkOuterValidity()
- goto restart
- }
- if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
- prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
- } else {
- prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
- }
- prg.first = uint16(int32(prg.curInput.limitField) + 1)
- prg.curInput.locField = prg.curInput.startField // ready to read
- } else {
- if !(int32(prg.curInput.nameField) == 0) {
- prg.curCmd = 0
- prg.curChr = 0
- goto exit
- }
- if int32(prg.inputPtr) > 0 {
- prg.endFileReading()
- goto restart // resume previous level
- }
- if int32(prg.selector) < logOnly {
- prg.openLogFile()
- }
- if int32(prg.interaction) > nonstopMode {
- if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
- prg.curInput.limitField = uint16(int32(prg.curInput.limitField) + 1)
- }
- if int32(prg.curInput.limitField) == int32(prg.curInput.startField) {
- prg.printNl(strNumber( /* "(Please type a command or say `\\end')" */ 616))
- }
- // \xref[Please type...]
- prg.printLn()
- prg.first = prg.curInput.startField
- {
- prg.print('*')
- prg.termInput()
- } // input on-line into |buffer|
- // \xref[*\relax]
- prg.curInput.limitField = prg.last
- if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
- prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
- } else {
- prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
- }
- prg.first = uint16(int32(prg.curInput.limitField) + 1)
- prg.curInput.locField = prg.curInput.startField
- } else {
- prg.fatalError(strNumber( /* "*** (job aborted, no legal \\end found)" */ 617))
- }
- // \xref[job aborted]
- // nonstop mode, which is intended for overnight batch processing,
- // never waits for on-line input
- }
- {
- if prg.interrupt != 0 {
- prg.pauseForInstructions()
- }
- }
- goto switch1
- }
- } else if int32(prg.curInput.locField) != 0 {
- t = *(*prg.mem[prg.curInput.locField].hh()).lh()
- prg.curInput.locField = *(*prg.mem[prg.curInput.locField].hh()).rh() // move to next
- if int32(t) >= 07777 {
- prg.curCs = uint16(int32(t) - 07777)
- prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
- prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
- if int32(prg.curCmd) >= outerCall {
- if int32(prg.curCmd) == dontExpand {
- prg.curCs = uint16(int32(*(*prg.mem[prg.curInput.locField].hh()).lh()) - 07777)
- prg.curInput.locField = 0
- prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
- prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
- if int32(prg.curCmd) > maxCommand {
- prg.curCmd = byte(relax)
- prg.curChr = uint16(noExpandFlag)
- }
- } else {
- prg.checkOuterValidity()
- }
- }
- } else {
- prg.curCmd = byte(int32(t) / 0400)
- prg.curChr = uint16(int32(t) % 0400)
- switch prg.curCmd {
- case leftBrace:
- prg.alignState = prg.alignState + 1
- case rightBrace:
- prg.alignState = prg.alignState - 1
- case outParam:
- // Insert macro parameter and |goto restart|
- prg.beginTokenList(prg.paramStack[int32(prg.curInput.limitField)+int32(prg.curChr)-1], quarterword(parameter))
- goto restart
- default:
- }
- }
- } else {
- prg.endTokenList()
- goto restart // resume previous level
- }
- // If an alignment entry has just ended, take appropriate action
- if int32(prg.curCmd) <= carRet {
- if int32(prg.curCmd) >= tabMark {
- if prg.alignState == 0 {
- if int32(prg.scannerStatus) == aligning || int32(prg.curAlign) == 0 {
- prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
- }
- // \xref[interwoven alignment preambles...]
- prg.curCmd = byte(*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh())
- *(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh() = prg.curChr
- if int32(prg.curCmd) == omit {
- prg.beginTokenList(halfword(30000-10), quarterword(vTemplate))
- } else {
- prg.beginTokenList(halfword(*prg.mem[int32(prg.curAlign)+depthOffset].int()), quarterword(vTemplate))
- }
- prg.alignState = 1000000
- goto restart
- }
- }
- }
- exit:
- }
- // 340.
- // tangle:pos tex.web:7226:3:
- // We need to mention a procedure here that may be called by |get_next|.
- func (prg *prg) firmUpTheLine() {
- var (
- k /* 0..bufSize */ uint16 // an index into |buffer|
- )
- prg.curInput.limitField = prg.last
- if *prg.eqtb[intBase+pausingCode-1].int() > 0 {
- if int32(prg.interaction) > nonstopMode {
- prg.printLn()
- if int32(prg.curInput.startField) < int32(prg.curInput.limitField) {
- for ii := int32(prg.curInput.startField); ii <= int32(prg.curInput.limitField)-1; ii++ {
- k = uint16(ii)
- _ = k
- prg.print(int32(prg.buffer[k]))
- }
- }
- prg.first = prg.curInput.limitField
- {
- prg.print( /* "=>" */ 618)
- prg.termInput()
- } // wait for user response
- // \xref[=>]
- if int32(prg.last) > int32(prg.first) {
- for ii := int32(prg.first); ii <= int32(prg.last)-1; ii++ {
- k = uint16(ii)
- _ = k // move line down in buffer
- prg.buffer[int32(k)+int32(prg.curInput.startField)-int32(prg.first)] = prg.buffer[k]
- }
- prg.curInput.limitField = uint16(int32(prg.curInput.startField) + int32(prg.last) - int32(prg.first))
- }
- }
- }
- } // \2
- func (prg *prg) getToken() {
- prg.noNewControlSequence = false
- prg.getNext()
- prg.noNewControlSequence = true
- // \xref[inner loop]
- if int32(prg.curCs) == 0 {
- prg.curTok = uint16(int32(prg.curCmd)*0400 + int32(prg.curChr))
- } else {
- prg.curTok = uint16(07777 + int32(prg.curCs))
- }
- }
- // 366. \[25] Expanding the next token
- // tangle:pos tex.web:7636:33:
- // Only a dozen or so command codes |>max_command| can possibly be returned by
- // |get_next|; in increasing order, they are |undefined_cs|, |expand_after|,
- // |no_expand|, |input|, |if_test|, |fi_or_else|, |cs_name|, |convert|, |the|,
- // |top_bot_mark|, |call|, |long_call|, |outer_call|, |long_outer_call|, and
- // |end_template|.[\emergencystretch=40pt\par]
- //
- // The |expand| subroutine is used when |cur_cmd>max_command|. It removes a
- // “call” or a conditional or one of the other special operations just
- // listed. It follows that |expand| might invoke itself recursively. In all
- // cases, |expand| destroys the current token, but it sets things up so that
- // the next |get_next| will deliver the appropriate next token. The value of
- // |cur_tok| need not be known when |expand| is called.
- //
- // Since several of the basic scanning routines communicate via global variables,
- // their values are saved as local variables of |expand| so that
- // recursive calls don't invalidate them.
- // \xref[recursion]
- // \4
- // Declare the procedure called |macro_call|
- func (prg *prg) macroCall() {
- var (
- r1 halfword // current node in the macro's token list
- p halfword // current node in parameter token list being built
- q halfword // new node being put into the token list
- s halfword // backup pointer for parameter matching
- t halfword // cycle pointer for backup recovery
- u, v halfword // auxiliary pointers for backup recovery
- rbracePtr halfword // one step before the last |right_brace| token
- n smallNumber // the number of parameters scanned
- unbalance halfword // unmatched left braces in current parameter
- m halfword // the number of tokens or groups (usually)
- refCount halfword // start of the token list
- saveScannerStatus smallNumber // |scanner_status| upon entry
- saveWarningIndex halfword // |warning_index| upon entry
- matchChr asciiCode // character used in parameter
- )
- saveScannerStatus = prg.scannerStatus
- saveWarningIndex = prg.warningIndex
- prg.warningIndex = prg.curCs
- refCount = prg.curChr
- r1 = *(*prg.mem[refCount].hh()).rh()
- n = 0
- if *prg.eqtb[intBase+tracingMacrosCode-1].int() > 0 {
- prg.beginDiagnostic()
- prg.printLn()
- prg.printCs(int32(prg.warningIndex))
- prg.tokenShow(refCount)
- prg.endDiagnostic(false)
- }
- if int32(*(*prg.mem[r1].hh()).lh()) != endMatchToken {
- prg.scannerStatus = byte(matching)
- unbalance = 0
- prg.longState = *(*prg.eqtb[prg.curCs-1].hh()).b0()
- if int32(prg.longState) >= outerCall {
- prg.longState = byte(int32(prg.longState) - 2)
- }
- for {
- *(*prg.mem[30000-3].hh()).rh() = 0
- if int32(*(*prg.mem[r1].hh()).lh()) > matchToken+255 || int32(*(*prg.mem[r1].hh()).lh()) < matchToken {
- s = 0
- } else {
- matchChr = byte(int32(*(*prg.mem[r1].hh()).lh()) - matchToken)
- s = *(*prg.mem[r1].hh()).rh()
- r1 = s
- p = uint16(30000 - 3)
- m = 0
- }
- // Scan a parameter until its delimiter string has been found; or, if |s=null|, simply scan the delimiter string
- // Scan a parameter until its delimiter string has been found; or, if |s=null|, simply scan the delimiter string
- continue1:
- prg.getToken() // set |cur_tok| to the next token of input
- if int32(prg.curTok) == int32(*(*prg.mem[r1].hh()).lh()) {
- r1 = *(*prg.mem[r1].hh()).rh()
- if int32(*(*prg.mem[r1].hh()).lh()) >= matchToken && int32(*(*prg.mem[r1].hh()).lh()) <= endMatchToken {
- if int32(prg.curTok) < leftBraceLimit {
- prg.alignState = prg.alignState - 1
- }
- goto found
- } else {
- goto continue1
- }
- }
- // Contribute the recently matched tokens to the current parameter, and |goto continue| if a partial match is still in effect; but abort if |s=null|
- if int32(s) != int32(r1) {
- if int32(s) == 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Use of " */ 650)
- }
- prg.sprintCs(prg.warningIndex)
- // \xref[Use of x doesn't match...]
- prg.print( /* " doesn't match its definition" */ 651)
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "If you say, e.g., `\\def\\a1[...]', then you must always" */ 652
- prg.helpLine[2] = /* "put `1' after `\\a', since control sequence names are" */ 653
- prg.helpLine[1] = /* "made up of letters only. The macro here has not been" */ 654
- prg.helpLine[0] = /* "followed by the required stuff, so I'm ignoring it." */ 655
- }
- prg.error1()
- goto exit
- } else {
- t = s
- for {
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = *(*prg.mem[t].hh()).lh()
- p = q
- }
- m = uint16(int32(m) + 1)
- u = *(*prg.mem[t].hh()).rh()
- v = s
- for true {
- if int32(u) == int32(r1) {
- if int32(prg.curTok) != int32(*(*prg.mem[v].hh()).lh()) {
- goto done
- } else {
- r1 = *(*prg.mem[v].hh()).rh()
- goto continue1
- }
- }
- if int32(*(*prg.mem[u].hh()).lh()) != int32(*(*prg.mem[v].hh()).lh()) {
- goto done
- }
- u = *(*prg.mem[u].hh()).rh()
- v = *(*prg.mem[v].hh()).rh()
- }
- done:
- t = *(*prg.mem[t].hh()).rh()
- if int32(t) == int32(r1) {
- break
- }
- }
- r1 = s // at this point, no tokens are recently matched
- }
- }
- if int32(prg.curTok) == int32(prg.parToken) {
- if int32(prg.longState) != longCall {
- if int32(prg.longState) == call {
- prg.runaway()
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Paragraph ended before " */ 645)
- }
- // \xref[Paragraph ended before...]
- prg.sprintCs(prg.warningIndex)
- prg.print( /* " was complete" */ 646)
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "I suspect you've forgotten a `]', causing me to apply this" */ 647
- prg.helpLine[1] = /* "control sequence to too much text. How can we recover?" */ 648
- prg.helpLine[0] = /* "My plan is to forget the whole thing and hope for the best." */ 649
- }
- prg.backError()
- }
- prg.pstack[n] = *(*prg.mem[30000-3].hh()).rh()
- prg.alignState = prg.alignState - int32(unbalance)
- for ii := int32(0); ii <= int32(n); ii++ {
- m = halfword(ii)
- _ = m
- prg.flushList(prg.pstack[m])
- }
- goto exit
- }
- }
- if int32(prg.curTok) < rightBraceLimit {
- if int32(prg.curTok) < leftBraceLimit {
- unbalance = 1
- // \xref[inner loop]
- for true {
- {
- {
- q = prg.avail
- if int32(q) == 0 {
- q = prg.getAvail()
- } else {
- prg.avail = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = 0 /* dyn_used:= dyn_used+1 ; [ ] */
- }
- }
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = prg.curTok
- p = q
- }
- prg.getToken()
- if int32(prg.curTok) == int32(prg.parToken) {
- if int32(prg.longState) != longCall {
- if int32(prg.longState) == call {
- prg.runaway()
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Paragraph ended before " */ 645)
- }
- // \xref[Paragraph ended before...]
- prg.sprintCs(prg.warningIndex)
- prg.print( /* " was complete" */ 646)
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "I suspect you've forgotten a `]', causing me to apply this" */ 647
- prg.helpLine[1] = /* "control sequence to too much text. How can we recover?" */ 648
- prg.helpLine[0] = /* "My plan is to forget the whole thing and hope for the best." */ 649
- }
- prg.backError()
- }
- prg.pstack[n] = *(*prg.mem[30000-3].hh()).rh()
- prg.alignState = prg.alignState - int32(unbalance)
- for ii := int32(0); ii <= int32(n); ii++ {
- m = halfword(ii)
- _ = m
- prg.flushList(prg.pstack[m])
- }
- goto exit
- }
- }
- if int32(prg.curTok) < rightBraceLimit {
- if int32(prg.curTok) < leftBraceLimit {
- unbalance = uint16(int32(unbalance) + 1)
- } else {
- unbalance = uint16(int32(unbalance) - 1)
- if int32(unbalance) == 0 {
- goto done1
- }
- }
- }
- }
- done1:
- rbracePtr = p
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = prg.curTok
- p = q
- }
- } else {
- // Report an extra right brace and |goto continue|
- prg.backInput()
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Argument of " */ 637)
- }
- prg.sprintCs(prg.warningIndex)
- // \xref[Argument of \\x has...]
- prg.print( /* " has an extra ]" */ 638)
- {
- prg.helpPtr = 6
- prg.helpLine[5] = /* "I've run across a `]' that doesn't seem to match anything." */ 639
- prg.helpLine[4] = /* "For example, `\\def\\a#1[...]' and `\\a]' would produce" */ 640
- prg.helpLine[3] = /* "this error. If you simply proceed now, the `\\par' that" */ 641
- prg.helpLine[2] = /* "I've just inserted will cause me to report a runaway" */ 642
- prg.helpLine[1] = /* "argument that might be the root of the problem. But if" */ 643
- prg.helpLine[0] = /* "your `]' was spurious, just type `2' and it will go away." */ 644
- }
- prg.alignState = prg.alignState + 1
- prg.longState = byte(call)
- prg.curTok = prg.parToken
- prg.insError()
- goto continue1
- }
- } else {
- // Store the current token, but |goto continue| if it is a blank space that would become an undelimited parameter
- if int32(prg.curTok) == spaceToken {
- if int32(*(*prg.mem[r1].hh()).lh()) <= endMatchToken {
- if int32(*(*prg.mem[r1].hh()).lh()) >= matchToken {
- goto continue1
- }
- }
- }
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = prg.curTok
- p = q
- }
- }
- m = uint16(int32(m) + 1)
- if int32(*(*prg.mem[r1].hh()).lh()) > endMatchToken {
- goto continue1
- }
- if int32(*(*prg.mem[r1].hh()).lh()) < matchToken {
- goto continue1
- }
- found:
- if int32(s) != 0 {
- if int32(m) == 1 && int32(*(*prg.mem[p].hh()).lh()) < rightBraceLimit {
- *(*prg.mem[rbracePtr].hh()).rh() = 0
- {
- *(*prg.mem[p].hh()).rh() = prg.avail
- prg.avail = p /* dyn_used:= dyn_used-1 ; [ ] */
- }
- p = *(*prg.mem[30000-3].hh()).rh()
- prg.pstack[n] = *(*prg.mem[p].hh()).rh()
- {
- *(*prg.mem[p].hh()).rh() = prg.avail
- prg.avail = p /* dyn_used:= dyn_used-1 ; [ ] */
- }
- } else {
- prg.pstack[n] = *(*prg.mem[30000-3].hh()).rh()
- }
- n = byte(int32(n) + 1)
- if *prg.eqtb[intBase+tracingMacrosCode-1].int() > 0 {
- prg.beginDiagnostic()
- prg.printNl(strNumber(matchChr))
- prg.printInt(int32(n))
- prg.print( /* "<-" */ 656)
- prg.showTokenList(int32(prg.pstack[int32(n)-1]), 0, 1000)
- prg.endDiagnostic(false)
- }
- }
- // now |info(r)| is a token whose command code is either |match| or |end_match|
- if int32(*(*prg.mem[r1].hh()).lh()) == endMatchToken {
- break
- }
- }
- }
- // Feed the macro body and its parameters to the scanner
- for int32(prg.curInput.stateField) == tokenList && int32(prg.curInput.locField) == 0 && int32(prg.curInput.indexField) != vTemplate {
- prg.endTokenList()
- } // conserve stack space
- prg.beginTokenList(refCount, quarterword(macro))
- prg.curInput.nameField = prg.warningIndex
- prg.curInput.locField = *(*prg.mem[r1].hh()).rh()
- if int32(n) > 0 {
- if int32(prg.paramPtr)+int32(n) > prg.maxParamStack {
- prg.maxParamStack = int32(prg.paramPtr) + int32(n)
- if prg.maxParamStack > paramSize {
- prg.overflow(strNumber( /* "parameter stack size" */ 636), paramSize)
- }
- // \xref[TeX capacity exceeded parameter stack size][\quad parameter stack size]
- }
- for ii := int32(0); ii <= int32(n)-1; ii++ {
- m = halfword(ii)
- _ = m
- prg.paramStack[int32(prg.paramPtr)+int32(m)] = prg.pstack[m]
- }
- prg.paramPtr = byte(int32(prg.paramPtr) + int32(n))
- }
- exit:
- prg.scannerStatus = saveScannerStatus
- prg.warningIndex = saveWarningIndex
- }
- // \4
- // Declare the procedure called |insert_relax|
- func (prg *prg) insertRelax() {
- prg.curTok = uint16(07777 + int32(prg.curCs))
- prg.backInput()
- prg.curTok = uint16(07777 + frozenRelax)
- prg.backInput()
- prg.curInput.indexField = byte(inserted)
- } // \2
- func (prg *prg) expand() {
- var (
- t halfword // token that is being ``expanded after''
- p, q, r1 halfword // for list manipulation
- j/* 0..bufSize */ uint16 // index into |buffer|
- cvBackup int32 // to save the global quantity |cur_val|
- cvlBackup, radixBackup, coBackup smallNumber
- // to save |cur_val_level|, etc.
- backupBackup halfword // to save |link(backup_head)|
- saveScannerStatus smallNumber // temporary storage of |scanner_status|
- )
- cvBackup = prg.curVal
- cvlBackup = prg.curValLevel
- radixBackup = prg.radix
- coBackup = prg.curOrder
- backupBackup = *(*prg.mem[30000-13].hh()).rh()
- if int32(prg.curCmd) < call {
- if *prg.eqtb[intBase+tracingCommandsCode-1].int() > 1 {
- prg.showCurCmdChr()
- }
- switch prg.curCmd {
- case topBotMark:
- // Insert the \(a)appropriate mark text into the scanner
- if int32(prg.curMark[prg.curChr]) != 0 {
- prg.beginTokenList(prg.curMark[prg.curChr], quarterword(markText))
- }
- case expandAfter:
- // Expand the token after the next token
- prg.getToken()
- t = prg.curTok
- prg.getToken()
- if int32(prg.curCmd) > maxCommand {
- prg.expand()
- } else {
- prg.backInput()
- }
- prg.curTok = t
- prg.backInput()
- case noExpand:
- // Suppress expansion of the next token
- saveScannerStatus = prg.scannerStatus
- prg.scannerStatus = byte(normal)
- prg.getToken()
- prg.scannerStatus = saveScannerStatus
- t = prg.curTok
- prg.backInput() // now |start| and |loc| point to the backed-up token |t|
- if int32(t) >= 07777 {
- p = prg.getAvail()
- *(*prg.mem[p].hh()).lh() = uint16(07777 + frozenDontExpand)
- *(*prg.mem[p].hh()).rh() = prg.curInput.locField
- prg.curInput.startField = p
- prg.curInput.locField = p
- }
- case csName:
- // Manufacture a control sequence name
- r1 = prg.getAvail()
- p = r1 // head of the list of characters
- for {
- prg.getXToken()
- if int32(prg.curCs) == 0 {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = prg.curTok
- p = q
- }
- if int32(prg.curCs) != 0 {
- break
- }
- }
- if int32(prg.curCmd) != endCsName {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing " */ 625)
- }
- prg.printEsc(strNumber( /* "endcsname" */ 505))
- prg.print( /* " inserted" */ 626)
- // \xref[Missing \\endcsname...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "The control sequence marked <to be read again> should" */ 627
- prg.helpLine[0] = /* "not appear between \\csname and \\endcsname." */ 628
- }
- prg.backError()
- }
- // Look up the characters of list |r| in the hash table, and set |cur_cs|
- j = prg.first
- p = *(*prg.mem[r1].hh()).rh()
- for int32(p) != 0 {
- if int32(j) >= int32(prg.maxBufStack) {
- prg.maxBufStack = uint16(int32(j) + 1)
- if int32(prg.maxBufStack) == bufSize {
- prg.overflow(strNumber( /* "buffer size" */ 256), bufSize)
- }
- // \xref[TeX capacity exceeded buffer size][\quad buffer size]
- }
- prg.buffer[j] = byte(int32(*(*prg.mem[p].hh()).lh()) % 0400)
- j = uint16(int32(j) + 1)
- p = *(*prg.mem[p].hh()).rh()
- }
- if int32(j) > int32(prg.first)+1 {
- prg.noNewControlSequence = false
- prg.curCs = prg.idLookup(int32(prg.first), int32(j)-int32(prg.first))
- prg.noNewControlSequence = true
- } else if int32(j) == int32(prg.first) {
- prg.curCs = uint16(nullCs)
- } else {
- prg.curCs = uint16(singleBase + int32(prg.buffer[prg.first]))
- }
- prg.flushList(r1)
- if int32(*(*prg.eqtb[prg.curCs-1].hh()).b0()) == undefinedCs {
- prg.eqDefine(prg.curCs, quarterword(relax), halfword(256)) // N.B.: The |save_stack| might change
- } // the control sequence will now match `\.[\\relax]'
- prg.curTok = uint16(int32(prg.curCs) + 07777)
- prg.backInput()
- case convert:
- prg.convToks() // this procedure is discussed in Part 27 below
- case the:
- prg.insTheToks() // this procedure is discussed in Part 27 below
- case ifTest:
- prg.conditional() // this procedure is discussed in Part 28 below
- case fiOrElse:
- // Terminate the current conditional and skip to \.[\\fi]
- if int32(prg.curChr) > int32(prg.ifLimit) {
- if int32(prg.ifLimit) == ifCode {
- prg.insertRelax()
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Extra " */ 777)
- }
- prg.printCmdChr(quarterword(fiOrElse), prg.curChr)
- // \xref[Extra \\or]
- // \xref[Extra \\else]
- // \xref[Extra \\fi]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm ignoring this; it doesn't match any \\if." */ 778
- }
- prg.error1()
- }
- } else {
- for int32(prg.curChr) != fiCode {
- prg.passText()
- } // skip to \.[\\fi]
- // Pop the condition stack
- {
- p = prg.condPtr
- prg.ifLine = *prg.mem[int32(p)+1].int()
- prg.curIf = *(*prg.mem[p].hh()).b1()
- prg.ifLimit = *(*prg.mem[p].hh()).b0()
- prg.condPtr = *(*prg.mem[p].hh()).rh()
- prg.freeNode(p, halfword(ifNodeSize))
- }
- }
- case input:
- // Initiate or terminate input from a file
- if int32(prg.curChr) > 0 {
- prg.forceEof = true
- } else if prg.nameInProgress {
- prg.insertRelax()
- } else {
- prg.startInput()
- }
- default:
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Undefined control sequence" */ 619)
- }
- // \xref[Undefined control sequence]
- {
- prg.helpPtr = 5
- prg.helpLine[4] = /* "The control sequence at the end of the top line" */ 620
- prg.helpLine[3] = /* "of your error message was never \\def'ed. If you have" */ 621
- prg.helpLine[2] = /* "misspelled it (e.g., `\\hobx'), type `I' and the correct" */ 622
- prg.helpLine[1] = /* "spelling (e.g., `I\\hbox'). Otherwise just continue," */ 623
- prg.helpLine[0] = /* "and I'll forget about whatever was undefined." */ 624
- }
- prg.error1()
- }
- } else if int32(prg.curCmd) < endTemplate {
- prg.macroCall()
- } else {
- // Insert a token containing |frozen_endv|
- prg.curTok = uint16(07777 + frozenEndv)
- prg.backInput()
- }
- prg.curVal = cvBackup
- prg.curValLevel = cvlBackup
- prg.radix = radixBackup
- prg.curOrder = coBackup
- *(*prg.mem[30000-13].hh()).rh() = backupBackup
- } // \2
- func (prg *prg) getXToken() {
- restart:
- prg.getNext()
- // \xref[inner loop]
- if int32(prg.curCmd) <= maxCommand {
- goto done
- }
- if int32(prg.curCmd) >= call {
- if int32(prg.curCmd) < endTemplate {
- prg.macroCall()
- } else {
- prg.curCs = uint16(frozenEndv)
- prg.curCmd = byte(endv)
- goto done // |cur_chr=null_list|
- }
- } else {
- prg.expand()
- }
- goto restart
- done:
- if int32(prg.curCs) == 0 {
- prg.curTok = uint16(int32(prg.curCmd)*0400 + int32(prg.curChr))
- } else {
- prg.curTok = uint16(07777 + int32(prg.curCs))
- }
- }
- // 381.
- // tangle:pos tex.web:7842:1:
- // The |get_x_token| procedure is essentially equivalent to two consecutive
- // procedure calls: |get_next; x_token|.
- func (prg *prg) xToken() {
- for int32(prg.curCmd) > maxCommand {
- prg.expand()
- prg.getNext()
- }
- if int32(prg.curCs) == 0 {
- prg.curTok = uint16(int32(prg.curCmd)*0400 + int32(prg.curChr))
- } else {
- prg.curTok = uint16(07777 + int32(prg.curCs))
- }
- }
- // 402. \[26] Basic scanning subroutines
- // tangle:pos tex.web:8181:35:
- // Let's turn now to some procedures that \TeX\ calls upon frequently to digest
- // certain kinds of patterns in the input. Most of these are quite simple;
- // some are quite elaborate. Almost all of the routines call |get_x_token|,
- // which can cause them to be invoked recursively.
- // \xref[stomach]
- // \xref[recursion]
- // 403.
- // tangle:pos tex.web:8189:1:
- // The |scan_left_brace| routine is called when a left brace is supposed to be
- // the next non-blank token. (The term “left brace” means, more precisely,
- // a character whose catcode is |left_brace|.) \TeX\ allows \.[\\relax] to
- // appear before the |left_brace|.
- func (prg *prg) scanLeftBrace() {
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
- break
- }
- }
- if int32(prg.curCmd) != leftBrace {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing [ inserted" */ 657)
- }
- // \xref[Missing \[ inserted]
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "A left brace was mandatory here, so I've put one in." */ 658
- prg.helpLine[2] = /* "You might want to delete and/or insert some corrections" */ 659
- prg.helpLine[1] = /* "so that I will find a matching right brace soon." */ 660
- prg.helpLine[0] = /* "(If you're confused by all this, try typing `I]' now.)" */ 661
- }
- prg.backError()
- prg.curTok = uint16(leftBraceToken + '{')
- prg.curCmd = byte(leftBrace)
- prg.curChr = '{'
- prg.alignState = prg.alignState + 1
- }
- }
- // 405.
- // tangle:pos tex.web:8212:1:
- // The |scan_optional_equals| routine looks for an optional `\.=' sign preceded
- // by optional spaces; `\.[\\relax]' is not ignored here.
- func (prg *prg) scanOptionalEquals() {
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- if int32(prg.curTok) != otherToken+'=' {
- prg.backInput()
- }
- }
- // 407.
- // tangle:pos tex.web:8224:1:
- // In case you are getting bored, here is a slightly less trivial routine:
- // Given a string of lowercase letters, like `\.[pt]' or `\.[plus]' or
- // `\.[width]', the |scan_keyword| routine checks to see whether the next
- // tokens of input match this string. The match must be exact, except that
- // uppercase letters will match their lowercase counterparts; uppercase
- // equivalents are determined by subtracting |"a"-"A"|, rather than using the
- // |uc_code| table, since \TeX\ uses this routine only for its own limited
- // set of keywords.
- //
- // If a match is found, the characters are effectively removed from the input
- // and |true| is returned. Otherwise |false| is returned, and the input
- // is left essentially unchanged (except for the fact that some macros
- // may have been expanded, etc.).
- // \xref[inner loop]
- func (prg *prg) scanKeyword(s strNumber) (r bool) {
- var (
- p halfword // tail of the backup list
- q halfword // new node being added to the token list via |store_new_token|
- k poolPointer // index into |str_pool|
- )
- p = uint16(30000 - 13)
- *(*prg.mem[p].hh()).rh() = 0
- k = prg.strStart[s]
- for int32(k) < int32(prg.strStart[int32(s)+1]) {
- prg.getXToken() // recursion is possible here
- // \xref[recursion]
- if int32(prg.curCs) == 0 && (int32(prg.curChr) == int32(prg.strPool[k]) || int32(prg.curChr) == int32(prg.strPool[k])-'a'+'A') {
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = prg.curTok
- p = q
- }
- k = uint16(int32(k) + 1)
- } else if int32(prg.curCmd) != spacer || int32(p) != 30000-13 {
- prg.backInput()
- if int32(p) != 30000-13 {
- prg.beginTokenList(*(*prg.mem[30000-13].hh()).rh(), quarterword(backedUp))
- }
- r = false
- goto exit
- }
- }
- prg.flushList(*(*prg.mem[30000-13].hh()).rh())
- r = true
- exit:
- ;
- return r
- }
- // 408.
- // tangle:pos tex.web:8261:1:
- // Here is a procedure that sounds an alarm when mu and non-mu units
- // are being switched.
- func (prg *prg) muError() {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Incompatible glue units" */ 662)
- }
- // \xref[Incompatible glue units]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm going to assume that 1mu=1pt when they're mixed." */ 663
- }
- prg.error1()
- } // scans an integer value
- // \4\4
- // Declare procedures that scan restricted classes of integers
- func (prg *prg) scanEightBitInt() {
- prg.scanInt()
- if prg.curVal < 0 || prg.curVal > 255 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Bad register code" */ 687)
- }
- // \xref[Bad register code]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "A register number must be between 0 and 255." */ 688
- prg.helpLine[0] = /* "I changed this one to zero." */ 689
- }
- prg.intError(prg.curVal)
- prg.curVal = 0
- }
- }
- func (prg *prg) scanCharNum() {
- prg.scanInt()
- if prg.curVal < 0 || prg.curVal > 255 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Bad character code" */ 690)
- }
- // \xref[Bad character code]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "A character number must be between 0 and 255." */ 691
- prg.helpLine[0] = /* "I changed this one to zero." */ 689
- }
- prg.intError(prg.curVal)
- prg.curVal = 0
- }
- }
- func (prg *prg) scanFourBitInt() {
- prg.scanInt()
- if prg.curVal < 0 || prg.curVal > 15 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Bad number" */ 692)
- }
- // \xref[Bad number]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Since I expected to read a number between 0 and 15," */ 693
- prg.helpLine[0] = /* "I changed this one to zero." */ 689
- }
- prg.intError(prg.curVal)
- prg.curVal = 0
- }
- }
- func (prg *prg) scanFifteenBitInt() {
- prg.scanInt()
- if prg.curVal < 0 || prg.curVal > 077777 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Bad mathchar" */ 694)
- }
- // \xref[Bad mathchar]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "A mathchar number must be between 0 and 32767." */ 695
- prg.helpLine[0] = /* "I changed this one to zero." */ 689
- }
- prg.intError(prg.curVal)
- prg.curVal = 0
- }
- }
- func (prg *prg) scanTwentySevenBitInt() {
- prg.scanInt()
- if prg.curVal < 0 || prg.curVal > 0777777777 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Bad delimiter code" */ 696)
- }
- // \xref[Bad delimiter code]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "A numeric delimiter code must be between 0 and 2^[27]-1." */ 697
- prg.helpLine[0] = /* "I changed this one to zero." */ 689
- }
- prg.intError(prg.curVal)
- prg.curVal = 0
- }
- }
- // \4\4
- // Declare procedures that scan font-related stuff
- func (prg *prg) scanFontIdent() {
- var (
- f internalFontNumber
- m halfword
- )
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- if int32(prg.curCmd) == defFont {
- f = byte(*(*prg.eqtb[curFontLoc-1].hh()).rh())
- } else if int32(prg.curCmd) == setFont {
- f = byte(prg.curChr)
- } else if int32(prg.curCmd) == defFamily {
- m = prg.curChr
- prg.scanFourBitInt()
- f = byte(*(*prg.eqtb[int32(m)+prg.curVal-1].hh()).rh())
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing font identifier" */ 817)
- }
- // \xref[Missing font identifier]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I was looking for a control sequence whose" */ 818
- prg.helpLine[0] = /* "current meaning has been defined by \\font." */ 819
- }
- prg.backError()
- f = byte(fontBase)
- }
- prg.curVal = int32(f)
- }
- func (prg *prg) findFontDimen(writing bool) {
- // sets |cur_val| to |font_info| location
- var (
- f internalFontNumber
- n int32 // the parameter number
- )
- prg.scanInt()
- n = prg.curVal
- prg.scanFontIdent()
- f = byte(prg.curVal)
- if n <= 0 {
- prg.curVal = int32(prg.fmemPtr)
- } else {
- if writing && n <= spaceShrinkCode && n >= spaceCode && int32(prg.fontGlue[f]) != 0 {
- prg.deleteGlueRef(prg.fontGlue[f])
- prg.fontGlue[f] = 0
- }
- if n > int32(prg.fontParams[f]) {
- if int32(f) < int32(prg.fontPtr) {
- prg.curVal = int32(prg.fmemPtr)
- } else {
- // Increase the number of parameters in the last font
- for {
- if int32(prg.fmemPtr) == fontMemSize {
- prg.overflow(strNumber( /* "font memory" */ 824), fontMemSize)
- }
- // \xref[TeX capacity exceeded font memory][\quad font memory]
- *prg.fontInfo[prg.fmemPtr].int() = 0
- prg.fmemPtr = uint16(int32(prg.fmemPtr) + 1)
- prg.fontParams[f] = uint16(int32(prg.fontParams[f]) + 1)
- if n == int32(prg.fontParams[f]) {
- break
- }
- }
- prg.curVal = int32(prg.fmemPtr) - 1 // this equals |param_base[f]+font_params[f]|
- }
- } else {
- prg.curVal = n + prg.paramBase[f]
- }
- }
- // Issue an error message if |cur_val=fmem_ptr|
- if prg.curVal == int32(prg.fmemPtr) {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Font " */ 802)
- }
- prg.printEsc(*prg.hash[fontIdBase+int32(f)-514].rh())
- prg.print( /* " has only " */ 820)
- prg.printInt(int32(prg.fontParams[f]))
- prg.print( /* " fontdimen parameters" */ 821)
- // \xref[Font x has only...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "To increase the number of font parameters, you must" */ 822
- prg.helpLine[0] = /* "use \\fontdimen immediately after the \\font is loaded." */ 823
- }
- prg.error1()
- }
- }
- // 413.
- // tangle:pos tex.web:8345:1:
- // OK, we're ready for |scan_something_internal| itself. A second parameter,
- // |negative|, is set |true| if the value that is found should be negated.
- // It is assumed that |cur_cmd| and |cur_chr| represent the first token of
- // the internal quantity to be scanned; an error will be signalled if
- // |cur_cmd<min_internal| or |cur_cmd>max_internal|.
- func (prg *prg) scanSomethingInternal(level smallNumber, negative bool) {
- // fetch an internal parameter
- var (
- m halfword // |chr_code| part of the operand token
- p/* 0..nestSize */ byte // index into |nest|
- )
- m = prg.curChr
- switch prg.curCmd {
- case defCode:
- // Fetch a character code from some table
- prg.scanCharNum()
- if int32(m) == mathCodeBase {
- prg.curVal = int32(*(*prg.eqtb[mathCodeBase+prg.curVal-1].hh()).rh()) - 0
- prg.curValLevel = byte(intVal)
- } else if int32(m) < mathCodeBase {
- prg.curVal = int32(*(*prg.eqtb[int32(m)+prg.curVal-1].hh()).rh())
- prg.curValLevel = byte(intVal)
- } else {
- prg.curVal = *prg.eqtb[int32(m)+prg.curVal-1].int()
- prg.curValLevel = byte(intVal)
- }
- case toksRegister, assignToks, defFamily, setFont,
- defFont:
- // Fetch a token list or font identifier, provided that |level=tok_val|
- if int32(level) != tokVal {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing number, treated as zero" */ 664)
- }
- // \xref[Missing number...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "A number should have been here; I inserted `0'." */ 665
- prg.helpLine[1] = /* "(If you can't figure out why I needed to see a number," */ 666
- prg.helpLine[0] = /* "look up `weird error' in the index to The TeXbook.)" */ 667
- }
- // \xref[TeXbook][\sl The \TeX book]
- prg.backError()
- {
- prg.curVal = 0
- prg.curValLevel = byte(dimenVal)
- }
- } else if int32(prg.curCmd) <= assignToks {
- if int32(prg.curCmd) < assignToks {
- prg.scanEightBitInt()
- m = uint16(toksBase + prg.curVal)
- }
- {
- prg.curVal = int32(*(*prg.eqtb[m-1].hh()).rh())
- prg.curValLevel = byte(tokVal)
- }
- } else {
- prg.backInput()
- prg.scanFontIdent()
- {
- prg.curVal = fontIdBase + prg.curVal
- prg.curValLevel = byte(identVal)
- }
- }
- case assignInt:
- prg.curVal = *prg.eqtb[m-1].int()
- prg.curValLevel = byte(intVal)
- case assignDimen:
- prg.curVal = *prg.eqtb[m-1].int()
- prg.curValLevel = byte(dimenVal)
- case assignGlue:
- prg.curVal = int32(*(*prg.eqtb[m-1].hh()).rh())
- prg.curValLevel = byte(glueVal)
- case assignMuGlue:
- prg.curVal = int32(*(*prg.eqtb[m-1].hh()).rh())
- prg.curValLevel = byte(muVal)
- case setAux:
- // Fetch the |space_factor| or the |prev_depth|
- if abs(int32(prg.curList.modeField)) != int32(m) {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Improper " */ 680)
- }
- prg.printCmdChr(quarterword(setAux), m)
- // \xref[Improper \\spacefactor]
- // \xref[Improper \\prevdepth]
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "You can refer to \\spacefactor only in horizontal mode;" */ 681
- prg.helpLine[2] = /* "you can refer to \\prevdepth only in vertical mode; and" */ 682
- prg.helpLine[1] = /* "neither of these is meaningful inside \\write. So" */ 683
- prg.helpLine[0] = /* "I'm forgetting what you said and using zero instead." */ 684
- }
- prg.error1()
- if int32(level) != tokVal {
- prg.curVal = 0
- prg.curValLevel = byte(dimenVal)
- } else {
- prg.curVal = 0
- prg.curValLevel = byte(intVal)
- }
- } else if int32(m) == vmode {
- prg.curVal = *prg.curList.auxField.int()
- prg.curValLevel = byte(dimenVal)
- } else {
- prg.curVal = int32(*(*prg.curList.auxField.hh()).lh())
- prg.curValLevel = byte(intVal)
- }
- case setPrevGraf:
- // Fetch the |prev_graf|
- if int32(prg.curList.modeField) == 0 {
- prg.curVal = 0
- prg.curValLevel = byte(intVal)
- } else {
- prg.nest[prg.nestPtr] = prg.curList
- p = prg.nestPtr
- for abs(int32(prg.nest[p].modeField)) != vmode {
- p = byte(int32(p) - 1)
- }
- {
- prg.curVal = prg.nest[p].pgField
- prg.curValLevel = byte(intVal)
- }
- }
- case setPageInt:
- // Fetch the |dead_cycles| or the |insert_penalties|
- if int32(m) == 0 {
- prg.curVal = prg.deadCycles
- } else {
- prg.curVal = prg.insertPenalties
- }
- prg.curValLevel = byte(intVal)
- case setPageDimen:
- // Fetch something on the |page_so_far|
- if int32(prg.pageContents) == empty && !prg.outputActive {
- if int32(m) == 0 {
- prg.curVal = 07777777777
- } else {
- prg.curVal = 0
- }
- } else {
- prg.curVal = prg.pageSoFar[m]
- }
- prg.curValLevel = byte(dimenVal)
- case setShape:
- // Fetch the |par_shape| size
- if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
- prg.curVal = 0
- } else {
- prg.curVal = int32(*(*prg.mem[*(*prg.eqtb[parShapeLoc-1].hh()).rh()].hh()).lh())
- }
- prg.curValLevel = byte(intVal)
- case setBoxDimen:
- // Fetch a box dimension
- prg.scanEightBitInt()
- if int32(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()) == 0 {
- prg.curVal = 0
- } else {
- prg.curVal = *prg.mem[int32(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh())+int32(m)].int()
- }
- prg.curValLevel = byte(dimenVal)
- case charGiven, mathGiven:
- prg.curVal = int32(prg.curChr)
- prg.curValLevel = byte(intVal)
- case assignFontDimen:
- // Fetch a font dimension
- prg.findFontDimen(false)
- *prg.fontInfo[prg.fmemPtr].int() = 0
- {
- prg.curVal = *prg.fontInfo[prg.curVal].int()
- prg.curValLevel = byte(dimenVal)
- }
- case assignFontInt:
- // Fetch a font integer
- prg.scanFontIdent()
- if int32(m) == 0 {
- prg.curVal = prg.hyphenChar[prg.curVal]
- prg.curValLevel = byte(intVal)
- } else {
- prg.curVal = prg.skewChar[prg.curVal]
- prg.curValLevel = byte(intVal)
- }
- case register:
- // Fetch a register
- prg.scanEightBitInt()
- switch m {
- case intVal:
- prg.curVal = *prg.eqtb[countBase+prg.curVal-1].int()
- case dimenVal:
- prg.curVal = *prg.eqtb[scaledBase+prg.curVal-1].int()
- case glueVal:
- prg.curVal = int32(*(*prg.eqtb[skipBase+prg.curVal-1].hh()).rh())
- case muVal:
- prg.curVal = int32(*(*prg.eqtb[muSkipBase+prg.curVal-1].hh()).rh())
- } // there are no other cases
- prg.curValLevel = byte(m)
- case lastItem:
- // Fetch an item in the current node, if appropriate
- if int32(prg.curChr) > glueVal {
- if int32(prg.curChr) == inputLineNoCode {
- prg.curVal = prg.line
- } else {
- prg.curVal = prg.lastBadness
- } // |cur_chr=badness_code|
- prg.curValLevel = byte(intVal)
- } else {
- if int32(prg.curChr) == glueVal {
- prg.curVal = memBot
- } else {
- prg.curVal = 0
- }
- prg.curValLevel = byte(prg.curChr)
- if !(int32(prg.curList.tailField) >= int32(prg.hiMemMin)) && int32(prg.curList.modeField) != 0 {
- switch prg.curChr {
- case intVal:
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == penaltyNode {
- prg.curVal = *prg.mem[int32(prg.curList.tailField)+1].int()
- }
- case dimenVal:
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == kernNode {
- prg.curVal = *prg.mem[int32(prg.curList.tailField)+widthOffset].int()
- }
- case glueVal:
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == glueNode {
- prg.curVal = int32(*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh())
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b1()) == muGlue {
- prg.curValLevel = byte(muVal)
- }
- }
- }
- } else if int32(prg.curList.modeField) == vmode && int32(prg.curList.tailField) == int32(prg.curList.headField) {
- switch prg.curChr {
- case intVal:
- prg.curVal = prg.lastPenalty
- case dimenVal:
- prg.curVal = prg.lastKern
- case glueVal:
- if int32(prg.lastGlue) != 65535 {
- prg.curVal = int32(prg.lastGlue)
- }
- }
- } // there are no other cases
- }
- default:
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "You can't use `" */ 685)
- }
- prg.printCmdChr(prg.curCmd, prg.curChr)
- // \xref[You can't use x after ...]
- prg.print( /* "' after " */ 686)
- prg.printEsc(strNumber( /* "the" */ 537))
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm forgetting what you said and using zero instead." */ 684
- }
- prg.error1()
- if int32(level) != tokVal {
- prg.curVal = 0
- prg.curValLevel = byte(dimenVal)
- } else {
- prg.curVal = 0
- prg.curValLevel = byte(intVal)
- }
- }
- for int32(prg.curValLevel) > int32(level) {
- // Convert \(c)|cur_val| to a lower level
- if int32(prg.curValLevel) == glueVal {
- prg.curVal = *prg.mem[prg.curVal+widthOffset].int()
- } else if int32(prg.curValLevel) == muVal {
- prg.muError()
- }
- prg.curValLevel = byte(int32(prg.curValLevel) - 1)
- }
- // Fix the reference count, if any, and negate |cur_val| if |negative|
- if negative {
- if int32(prg.curValLevel) >= glueVal {
- prg.curVal = int32(prg.newSpec(halfword(prg.curVal)))
- // Negate all three glue components of |cur_val|
- {
- *prg.mem[prg.curVal+widthOffset].int() = -*prg.mem[prg.curVal+widthOffset].int()
- *prg.mem[prg.curVal+2].int() = -*prg.mem[prg.curVal+2].int()
- *prg.mem[prg.curVal+3].int() = -*prg.mem[prg.curVal+3].int()
- }
- } else {
- prg.curVal = -prg.curVal
- }
- } else if int32(prg.curValLevel) >= glueVal && int32(prg.curValLevel) <= muVal {
- *(*prg.mem[prg.curVal].hh()).rh() = uint16(int32(*(*prg.mem[prg.curVal].hh()).rh()) + 1)
- }
- }
- // 409.
- // tangle:pos tex.web:8271:1:
- // The next routine `|scan_something_internal|' is used to fetch internal
- // numeric quantities like `\.[\\hsize]', and also to handle the `\.[\\the]'
- // when expanding constructions like `\.[\\the\\toks0]' and
- // `\.[\\the\\baselineskip]'. Soon we will be considering the |scan_int|
- // procedure, which calls |scan_something_internal|; on the other hand,
- // |scan_something_internal| also calls |scan_int|, for constructions like
- // `\.[\\catcode\`\\\$]' or `\.[\\fontdimen] \.3 \.[\\ff]'. So we
- // have to declare |scan_int| as a |forward| procedure. A few other
- // procedures are also declared at this point.
- func (prg *prg) scanInt() {
- var (
- negative bool // should the answer be negated?
- m int32 // |$2^[31]$ div radix|, the threshold of danger
- d smallNumber // the digit just scanned
- vacuous bool // have no digits appeared?
- okSoFar bool // has an error message been issued?
- )
- prg.radix = 0
- okSoFar = true
- // Get the next non-blank non-sign token; set |negative| appropriately
- negative = false
- for {
- // Get the next non-blank non-call token
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- if int32(prg.curTok) == otherToken+'-' {
- negative = !negative
- prg.curTok = uint16(otherToken + '+')
- }
- if int32(prg.curTok) != otherToken+'+' {
- break
- }
- }
- if int32(prg.curTok) == alphaToken {
- prg.getToken() // suppress macro expansion
- if int32(prg.curTok) < 07777 {
- prg.curVal = int32(prg.curChr)
- if int32(prg.curCmd) <= rightBrace {
- if int32(prg.curCmd) == rightBrace {
- prg.alignState = prg.alignState + 1
- } else {
- prg.alignState = prg.alignState - 1
- }
- }
- } else if int32(prg.curTok) < 07777+singleBase {
- prg.curVal = int32(prg.curTok) - 07777 - activeBase
- } else {
- prg.curVal = int32(prg.curTok) - 07777 - singleBase
- }
- if prg.curVal > 255 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Improper alphabetic constant" */ 698)
- }
- // \xref[Improper alphabetic constant]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "A one-character control sequence belongs after a ` mark." */ 699
- prg.helpLine[0] = /* "So I'm essentially inserting \\0 here." */ 700
- }
- prg.curVal = '0'
- prg.backError()
- } else {
- // Scan an optional space
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- prg.backInput()
- }
- }
- } else if int32(prg.curCmd) >= minInternal && int32(prg.curCmd) <= maxInternal {
- prg.scanSomethingInternal(smallNumber(intVal), false)
- } else {
- // Scan a numeric constant
- prg.radix = 10
- m = 214748364
- if int32(prg.curTok) == octalToken {
- prg.radix = 8
- m = 02000000000
- prg.getXToken()
- } else if int32(prg.curTok) == hexToken {
- prg.radix = 16
- m = 01000000000
- prg.getXToken()
- }
- vacuous = true
- prg.curVal = 0
- // Accumulate the constant until |cur_tok| is not a suitable digit
- for true {
- if int32(prg.curTok) < zeroToken+int32(prg.radix) && int32(prg.curTok) >= zeroToken && int32(prg.curTok) <= zeroToken+9 {
- d = byte(int32(prg.curTok) - zeroToken)
- } else if int32(prg.radix) == 16 {
- if int32(prg.curTok) <= aToken+5 && int32(prg.curTok) >= aToken {
- d = byte(int32(prg.curTok) - aToken + 10)
- } else if int32(prg.curTok) <= otherAToken+5 && int32(prg.curTok) >= otherAToken {
- d = byte(int32(prg.curTok) - otherAToken + 10)
- } else {
- goto done
- }
- } else {
- goto done
- }
- vacuous = false
- if prg.curVal >= m && (prg.curVal > m || int32(d) > 7 || int32(prg.radix) != 10) {
- if okSoFar {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Number too big" */ 701)
- }
- // \xref[Number too big]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I can only go up to 2147483647='17777777777=\"7FFFFFFF," */ 702
- prg.helpLine[0] = /* "so I'm using that number instead of yours." */ 703
- }
- prg.error1()
- prg.curVal = 017777777777
- okSoFar = false
- }
- } else {
- prg.curVal = prg.curVal*int32(prg.radix) + int32(d)
- }
- prg.getXToken()
- }
- done:
- ;
- if vacuous {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing number, treated as zero" */ 664)
- }
- // \xref[Missing number...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "A number should have been here; I inserted `0'." */ 665
- prg.helpLine[1] = /* "(If you can't figure out why I needed to see a number," */ 666
- prg.helpLine[0] = /* "look up `weird error' in the index to The TeXbook.)" */ 667
- }
- // \xref[TeXbook][\sl The \TeX book]
- prg.backError()
- } else if int32(prg.curCmd) != spacer {
- prg.backInput()
- }
- }
- if negative {
- prg.curVal = -prg.curVal
- }
- }
- // 448.
- // tangle:pos tex.web:8829:1:
- // Constructions like `\.[-\'77 pt]' are legal dimensions, so |scan_dimen|
- // may begin with |scan_int|. This explains why it is convenient to use
- // |scan_int| also for the integer part of a decimal fraction.
- //
- // Several branches of |scan_dimen| work with |cur_val| as an integer and
- // with an auxiliary fraction |f|, so that the actual quantity of interest is
- // $|cur_val|+|f|/2^[16]$. At the end of the routine, this “unpacked”
- // representation is put into the single word |cur_val|, which suddenly
- // switches significance from |integer| to |scaled|.
- func (prg *prg) scanDimen(mu, inf, shortcut bool) {
- var (
- negative bool // should the answer be negated?
- f int32 // numerator of a fraction whose denominator is $2^[16]$
- // Local variables for dimension calculations
- num, denom/* 1..65536 */ uint32 // conversion ratio for the scanned units
- k, kk smallNumber // number of digits in a decimal fraction
- p, q halfword // top of decimal digit stack
- v scaled // an internal dimension
- saveCurVal int32 // temporary storage of |cur_val|
- )
- f = 0
- prg.arithError = false
- prg.curOrder = byte(normal)
- negative = false
- if !shortcut {
- negative = false
- for {
- // Get the next non-blank non-call token
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- if int32(prg.curTok) == otherToken+'-' {
- negative = !negative
- prg.curTok = uint16(otherToken + '+')
- }
- if int32(prg.curTok) != otherToken+'+' {
- break
- }
- }
- if int32(prg.curCmd) >= minInternal && int32(prg.curCmd) <= maxInternal {
- if mu {
- prg.scanSomethingInternal(smallNumber(muVal), false)
- // Coerce glue to a dimension
- if int32(prg.curValLevel) >= glueVal {
- v = *prg.mem[prg.curVal+widthOffset].int()
- prg.deleteGlueRef(halfword(prg.curVal))
- prg.curVal = v
- }
- if int32(prg.curValLevel) == muVal {
- goto attachSign
- }
- if int32(prg.curValLevel) != intVal {
- prg.muError()
- }
- } else {
- prg.scanSomethingInternal(smallNumber(dimenVal), false)
- if int32(prg.curValLevel) == dimenVal {
- goto attachSign
- }
- }
- } else {
- prg.backInput()
- if int32(prg.curTok) == continentalPointToken {
- prg.curTok = uint16(pointToken)
- }
- if int32(prg.curTok) != pointToken {
- prg.scanInt()
- } else {
- prg.radix = 10
- prg.curVal = 0
- }
- if int32(prg.curTok) == continentalPointToken {
- prg.curTok = uint16(pointToken)
- }
- if int32(prg.radix) == 10 && int32(prg.curTok) == pointToken {
- k = 0
- p = 0
- prg.getToken() // |point_token| is being re-scanned
- for true {
- prg.getXToken()
- if int32(prg.curTok) > zeroToken+9 || int32(prg.curTok) < zeroToken {
- goto done1
- }
- if int32(k) < 17 {
- q = prg.getAvail()
- *(*prg.mem[q].hh()).rh() = p
- *(*prg.mem[q].hh()).lh() = uint16(int32(prg.curTok) - zeroToken)
- p = q
- k = byte(int32(k) + 1)
- }
- }
- done1:
- for ii := int32(k); ii >= 1; ii-- {
- kk = smallNumber(ii)
- _ = kk
- prg.dig[int32(kk)-1] = byte(*(*prg.mem[p].hh()).lh())
- q = p
- p = *(*prg.mem[p].hh()).rh()
- {
- *(*prg.mem[q].hh()).rh() = prg.avail
- prg.avail = q /* dyn_used:= dyn_used-1 ; [ ] */
- }
- }
- f = prg.roundDecimals(k)
- if int32(prg.curCmd) != spacer {
- prg.backInput()
- }
- }
- }
- }
- if prg.curVal < 0 {
- negative = !negative
- prg.curVal = -prg.curVal
- }
- // Scan units and set |cur_val| to $x\cdot(|cur_val|+f/2^[16])$, where there are |x| sp per unit; |goto attach_sign| if the units are internal
- if inf {
- if prg.scanKeyword(strNumber( /* "fil" */ 311)) {
- prg.curOrder = byte(fil)
- for prg.scanKeyword(strNumber('l')) {
- if int32(prg.curOrder) == filll {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Illegal unit of measure (" */ 705)
- }
- // \xref[Illegal unit of measure]
- prg.print( /* "replaced by filll)" */ 706)
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I dddon't go any higher than filll." */ 707
- }
- prg.error1()
- } else {
- prg.curOrder = byte(int32(prg.curOrder) + 1)
- }
- }
- goto attachFraction
- }
- }
- // Scan for \(u)units that are internal dimensions; |goto attach_sign| with |cur_val| set if found
- saveCurVal = prg.curVal
- // Get the next non-blank non-call...
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- if int32(prg.curCmd) < minInternal || int32(prg.curCmd) > maxInternal {
- prg.backInput()
- } else {
- if mu {
- prg.scanSomethingInternal(smallNumber(muVal), false)
- // Coerce glue...
- if int32(prg.curValLevel) >= glueVal {
- v = *prg.mem[prg.curVal+widthOffset].int()
- prg.deleteGlueRef(halfword(prg.curVal))
- prg.curVal = v
- }
- if int32(prg.curValLevel) != muVal {
- prg.muError()
- }
- } else {
- prg.scanSomethingInternal(smallNumber(dimenVal), false)
- }
- v = prg.curVal
- goto found
- }
- if mu {
- goto notFound
- }
- if prg.scanKeyword(strNumber( /* "em" */ 708)) {
- v = *prg.fontInfo[quadCode+prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()]].int()
- } else if prg.scanKeyword(strNumber( /* "ex" */ 709)) {
- v = *prg.fontInfo[xHeightCode+prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()]].int()
- } else {
- goto notFound
- }
- // Scan an optional space
- {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- prg.backInput()
- }
- }
- found:
- prg.curVal = prg.multAndAdd(saveCurVal, v, prg.xnOverD(v, f, 0200000), scaled(07777777777))
- goto attachSign
- notFound:
- ;
- if mu {
- if prg.scanKeyword(strNumber( /* "mu" */ 337)) {
- goto attachFraction
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Illegal unit of measure (" */ 705)
- }
- prg.print( /* "mu inserted)" */ 710)
- // \xref[Illegal unit of measure]
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "The unit of measurement in math glue must be mu." */ 711
- prg.helpLine[2] = /* "To recover gracefully from this error, it's best to" */ 712
- prg.helpLine[1] = /* "delete the erroneous units; e.g., type `2' to delete" */ 713
- prg.helpLine[0] = /* "two letters. (See Chapter 27 of The TeXbook.)" */ 714
- }
- // \xref[TeXbook][\sl The \TeX book]
- prg.error1()
- goto attachFraction
- }
- }
- if prg.scanKeyword(strNumber( /* "true" */ 704)) {
- prg.prepareMag()
- if *prg.eqtb[intBase+magCode-1].int() != 1000 {
- prg.curVal = prg.xnOverD(prg.curVal, 1000, *prg.eqtb[intBase+magCode-1].int())
- f = (1000*f + 0200000*prg.remainder) / *prg.eqtb[intBase+magCode-1].int()
- prg.curVal = prg.curVal + f/0200000
- f = f % 0200000
- }
- }
- // \xref[true]
- if prg.scanKeyword(strNumber( /* "pt" */ 397)) {
- goto attachFraction
- } // the easy case
- // \xref[pt]
- // Scan for \(a)all other units and adjust |cur_val| and |f| accordingly; |goto done| in the case of scaled points
- if prg.scanKeyword(strNumber( /* "in" */ 715)) {
- num = 7227
- denom = 100
- } else if prg.scanKeyword(strNumber( /* "pc" */ 716)) {
- num = 12
- denom = 1
- } else if prg.scanKeyword(strNumber( /* "cm" */ 717)) {
- num = 7227
- denom = 254
- } else if prg.scanKeyword(strNumber( /* "mm" */ 718)) {
- num = 7227
- denom = 2540
- } else if prg.scanKeyword(strNumber( /* "bp" */ 719)) {
- num = 7227
- denom = 7200
- } else if prg.scanKeyword(strNumber( /* "dd" */ 720)) {
- num = 1238
- denom = 1157
- } else if prg.scanKeyword(strNumber( /* "cc" */ 721)) {
- num = 14856
- denom = 1157
- } else if prg.scanKeyword(strNumber( /* "sp" */ 722)) {
- goto done
- } else {
- // Complain about unknown unit and |goto done2|
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Illegal unit of measure (" */ 705)
- }
- prg.print( /* "pt inserted)" */ 723)
- // \xref[Illegal unit of measure]
- {
- prg.helpPtr = 6
- prg.helpLine[5] = /* "Dimensions can be in units of em, ex, in, pt, pc," */ 724
- prg.helpLine[4] = /* "cm, mm, dd, cc, bp, or sp; but yours is a new one!" */ 725
- prg.helpLine[3] = /* "I'll assume that you meant to say pt, for printer's points." */ 726
- prg.helpLine[2] = /* "To recover gracefully from this error, it's best to" */ 712
- prg.helpLine[1] = /* "delete the erroneous units; e.g., type `2' to delete" */ 713
- prg.helpLine[0] = /* "two letters. (See Chapter 27 of The TeXbook.)" */ 714
- }
- // \xref[TeXbook][\sl The \TeX book]
- prg.error1()
- goto done2
- }
- prg.curVal = prg.xnOverD(prg.curVal, int32(num), int32(denom))
- f = (int32(num)*f + 0200000*prg.remainder) / int32(denom)
- prg.curVal = prg.curVal + f/0200000
- f = f % 0200000
- done2:
- ;
- attachFraction:
- if prg.curVal >= 040000 {
- prg.arithError = true
- } else {
- prg.curVal = prg.curVal*0200000 + f
- }
- done:
- ;
- // Scan an optional space
- {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- prg.backInput()
- }
- }
- attachSign:
- if prg.arithError || abs(prg.curVal) >= 010000000000 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Dimension too large" */ 727)
- }
- // \xref[Dimension too large]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I can't work with sizes bigger than about 19 feet." */ 728
- prg.helpLine[0] = /* "Continue and I'll use the largest value I can." */ 729
- }
- prg.error1()
- prg.curVal = 07777777777
- prg.arithError = false
- }
- if negative {
- prg.curVal = -prg.curVal
- }
- }
- // 461.
- // tangle:pos tex.web:9064:1:
- // The final member of \TeX's value-scanning trio is |scan_glue|, which
- // makes |cur_val| point to a glue specification. The reference count of that
- // glue spec will take account of the fact that |cur_val| is pointing to~it.
- //
- // The |level| parameter should be either |glue_val| or |mu_val|.
- //
- // Since |scan_dimen| was so much more complex than |scan_int|, we might expect
- // |scan_glue| to be even worse. But fortunately, it is very simple, since
- // most of the work has already been done.
- func (prg *prg) scanGlue(level smallNumber) {
- var (
- negative bool // should the answer be negated?
- q halfword // new glue specification
- mu bool // does |level=mu_val|?
- )
- mu = int32(level) == muVal
- // Get the next non-blank non-sign...
- negative = false
- for {
- // Get the next non-blank non-call token
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- if int32(prg.curTok) == otherToken+'-' {
- negative = !negative
- prg.curTok = uint16(otherToken + '+')
- }
- if int32(prg.curTok) != otherToken+'+' {
- break
- }
- }
- if int32(prg.curCmd) >= minInternal && int32(prg.curCmd) <= maxInternal {
- prg.scanSomethingInternal(level, negative)
- if int32(prg.curValLevel) >= glueVal {
- if int32(prg.curValLevel) != int32(level) {
- prg.muError()
- }
- goto exit
- }
- if int32(prg.curValLevel) == intVal {
- prg.scanDimen(mu, false, true)
- } else if int32(level) == muVal {
- prg.muError()
- }
- } else {
- prg.backInput()
- prg.scanDimen(mu, false, false)
- if negative {
- prg.curVal = -prg.curVal
- }
- }
- // Create a new glue specification whose width is |cur_val|; scan for its stretch and shrink components
- q = prg.newSpec(halfword(memBot))
- *prg.mem[int32(q)+widthOffset].int() = prg.curVal
- if prg.scanKeyword(strNumber( /* "plus" */ 730)) {
- prg.scanDimen(mu, true, false)
- *prg.mem[int32(q)+2].int() = prg.curVal
- *(*prg.mem[q].hh()).b0() = prg.curOrder
- }
- if prg.scanKeyword(strNumber( /* "minus" */ 731)) {
- prg.scanDimen(mu, true, false)
- *prg.mem[int32(q)+3].int() = prg.curVal
- *(*prg.mem[q].hh()).b1() = prg.curOrder
- }
- prg.curVal = int32(q)
- exit:
- }
- // 463.
- // tangle:pos tex.web:9111:1:
- // Here's a similar procedure that returns a pointer to a rule node. This
- // routine is called just after \TeX\ has seen \.[\\hrule] or \.[\\vrule];
- // therefore |cur_cmd| will be either |hrule| or |vrule|. The idea is to store
- // the default rule dimensions in the node, then to override them if
- // `\.[height]' or `\.[width]' or `\.[depth]' specifications are
- // found (in any order).
- func (prg *prg) scanRuleSpec() (r halfword) {
- var (
- q halfword // the rule node being created
- )
- q = prg.newRule() // |width|, |depth|, and |height| all equal |null_flag| now
- if int32(prg.curCmd) == vrule {
- *prg.mem[int32(q)+widthOffset].int() = defaultRule
- } else {
- *prg.mem[int32(q)+heightOffset].int() = defaultRule
- *prg.mem[int32(q)+depthOffset].int() = 0
- }
- reswitch:
- if prg.scanKeyword(strNumber( /* "width" */ 732)) {
- prg.scanDimen(false, false, false)
- *prg.mem[int32(q)+widthOffset].int() = prg.curVal
- goto reswitch
- }
- if prg.scanKeyword(strNumber( /* "height" */ 733)) {
- prg.scanDimen(false, false, false)
- *prg.mem[int32(q)+heightOffset].int() = prg.curVal
- goto reswitch
- }
- if prg.scanKeyword(strNumber( /* "depth" */ 734)) {
- prg.scanDimen(false, false, false)
- *prg.mem[int32(q)+depthOffset].int() = prg.curVal
- goto reswitch
- }
- r = q
- return r
- }
- // 464. \[27] Building token lists
- // tangle:pos tex.web:9142:29:
- // The token lists for macros and for other things like \.[\\mark] and \.[\\output]
- // and \.[\\write] are produced by a procedure called |scan_toks|.
- //
- // Before we get into the details of |scan_toks|, let's consider a much
- // simpler task, that of converting the current string into a token list.
- // The |str_toks| function does this; it classifies spaces as type |spacer|
- // and everything else as type |other_char|.
- //
- // The token list created by |str_toks| begins at |link(temp_head)| and ends
- // at the value |p| that is returned. (If |p=temp_head|, the list is empty.)
- func (prg *prg) strToks(b poolPointer) (r halfword) {
- // converts |str_pool[b..pool_ptr-1]| to a token list
- var (
- p halfword // tail of the token list
- q halfword // new node being added to the token list via |store_new_token|
- t halfword // token being appended
- k poolPointer // index into |str_pool|
- )
- {
- if int32(prg.poolPtr)+1 > poolSize {
- prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
- } /* \xref[TeX capacity exceeded pool size][\quad pool size] */
- }
- p = uint16(30000 - 3)
- *(*prg.mem[p].hh()).rh() = 0
- k = b
- for int32(k) < int32(prg.poolPtr) {
- t = uint16(prg.strPool[k])
- if int32(t) == ' ' {
- t = uint16(spaceToken)
- } else {
- t = uint16(otherToken + int32(t))
- }
- {
- {
- q = prg.avail
- if int32(q) == 0 {
- q = prg.getAvail()
- } else {
- prg.avail = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = 0 /* dyn_used:= dyn_used+1 ; [ ] */
- }
- }
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = t
- p = q
- }
- k = uint16(int32(k) + 1)
- }
- prg.poolPtr = b
- r = p
- return r
- }
- // 465.
- // tangle:pos tex.web:9172:1:
- // The main reason for wanting |str_toks| is the next function,
- // |the_toks|, which has similar input/output characteristics.
- //
- // This procedure is supposed to scan something like `\.[\\skip\\count12]',
- // i.e., whatever can follow `\.[\\the]', and it constructs a token list
- // containing something like `\.[-3.0pt minus 0.5fill]'.
- func (prg *prg) theToks() (r halfword) {
- var (
- oldSetting/* 0..maxSelector */ byte // holds |selector| setting
- p, q, r1 halfword // used for copying a token list
- b poolPointer // base of temporary string
- )
- prg.getXToken()
- prg.scanSomethingInternal(smallNumber(tokVal), false)
- if int32(prg.curValLevel) >= identVal {
- p = uint16(30000 - 3)
- *(*prg.mem[p].hh()).rh() = 0
- if int32(prg.curValLevel) == identVal {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = uint16(07777 + prg.curVal)
- p = q
- } else if prg.curVal != 0 {
- r1 = *(*prg.mem[prg.curVal].hh()).rh() // do not copy the reference count
- for int32(r1) != 0 {
- {
- {
- q = prg.avail
- if int32(q) == 0 {
- q = prg.getAvail()
- } else {
- prg.avail = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = 0 /* dyn_used:= dyn_used+1 ; [ ] */
- }
- }
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = *(*prg.mem[r1].hh()).lh()
- p = q
- }
- r1 = *(*prg.mem[r1].hh()).rh()
- }
- }
- r = p
- } else {
- oldSetting = prg.selector
- prg.selector = byte(newString)
- b = prg.poolPtr
- switch prg.curValLevel {
- case intVal:
- prg.printInt(prg.curVal)
- case dimenVal:
- prg.printScaled(prg.curVal)
- prg.print( /* "pt" */ 397)
- case glueVal:
- prg.printSpec(prg.curVal, strNumber( /* "pt" */ 397))
- prg.deleteGlueRef(halfword(prg.curVal))
- case muVal:
- prg.printSpec(prg.curVal, strNumber( /* "mu" */ 337))
- prg.deleteGlueRef(halfword(prg.curVal))
- } // there are no other cases
- prg.selector = oldSetting
- r = prg.strToks(b)
- }
- return r
- } // \2
- func (prg *prg) insTheToks() {
- *(*prg.mem[30000-12].hh()).rh() = prg.theToks()
- prg.beginTokenList(*(*prg.mem[30000-3].hh()).rh(), quarterword(inserted))
- } // \2
- func (prg *prg) convToks() {
- var (
- oldSetting/* 0..maxSelector */ byte // holds |selector| setting
- c/* numberCode..jobNameCode */ byte // desired type of conversion
- saveScannerStatus smallNumber // |scanner_status| upon entry
- b poolPointer // base of temporary string
- )
- c = byte(prg.curChr)
- // Scan the argument for command |c|
- switch c {
- case numberCode, romanNumeralCode:
- prg.scanInt()
- case stringCode, meaningCode:
- saveScannerStatus = prg.scannerStatus
- prg.scannerStatus = byte(normal)
- prg.getToken()
- prg.scannerStatus = saveScannerStatus
- case fontNameCode:
- prg.scanFontIdent()
- case jobNameCode:
- if int32(prg.jobName) == 0 {
- prg.openLogFile()
- }
- }
- oldSetting = prg.selector
- prg.selector = byte(newString)
- b = prg.poolPtr
- // Print the result of command |c|
- switch c {
- case numberCode:
- prg.printInt(prg.curVal)
- case romanNumeralCode:
- prg.printRomanInt(prg.curVal)
- case stringCode:
- if int32(prg.curCs) != 0 {
- prg.sprintCs(prg.curCs)
- } else {
- prg.printChar(asciiCode(prg.curChr))
- }
- case meaningCode:
- prg.printMeaning()
- case fontNameCode:
- prg.print(int32(prg.fontName[prg.curVal]))
- if prg.fontSize[prg.curVal] != prg.fontDsize[prg.curVal] {
- prg.print( /* " at " */ 741)
- prg.printScaled(prg.fontSize[prg.curVal])
- prg.print( /* "pt" */ 397)
- }
- case jobNameCode:
- prg.print(int32(prg.jobName))
- }
- prg.selector = oldSetting
- *(*prg.mem[30000-12].hh()).rh() = prg.strToks(b)
- prg.beginTokenList(*(*prg.mem[30000-3].hh()).rh(), quarterword(inserted))
- }
- // 473.
- // tangle:pos tex.web:9292:1:
- // Now we can't postpone the difficulties any longer; we must bravely tackle
- // |scan_toks|. This function returns a pointer to the tail of a new token
- // list, and it also makes |def_ref| point to the reference count at the
- // head of that list.
- //
- // There are two boolean parameters, |macro_def| and |xpand|. If |macro_def|
- // is true, the goal is to create the token list for a macro definition;
- // otherwise the goal is to create the token list for some other \TeX\
- // primitive: \.[\\mark], \.[\\output], \.[\\everypar], \.[\\lowercase],
- // \.[\\uppercase], \.[\\message], \.[\\errmessage], \.[\\write], or
- // \.[\\special]. In the latter cases a left brace must be scanned next; this
- // left brace will not be part of the token list, nor will the matching right
- // brace that comes at the end. If |xpand| is false, the token list will
- // simply be copied from the input using |get_token|. Otherwise all expandable
- // tokens will be expanded until unexpandable tokens are left, except that
- // the results of expanding `\.[\\the]' are not expanded further.
- // If both |macro_def| and |xpand| are true, the expansion applies
- // only to the macro body (i.e., to the material following the first
- // |left_brace| character).
- //
- // The value of |cur_cs| when |scan_toks| begins should be the |eqtb|
- // address of the control sequence to display in “runaway” error
- // messages.
- func (prg *prg) scanToks(macroDef, xpand bool) (r halfword) {
- var (
- t halfword // token representing the highest parameter number
- s halfword // saved token
- p halfword // tail of the token list being built
- q halfword // new node being added to the token list via |store_new_token|
- unbalance halfword // number of unmatched left braces
- hashBrace halfword // possible `\.[\#\[]' token
- )
- if macroDef {
- prg.scannerStatus = byte(defining)
- } else {
- prg.scannerStatus = byte(absorbing)
- }
- prg.warningIndex = prg.curCs
- prg.defRef = prg.getAvail()
- *(*prg.mem[prg.defRef].hh()).lh() = 0
- p = prg.defRef
- hashBrace = 0
- t = uint16(zeroToken)
- if macroDef {
- for true {
- continue1:
- prg.getToken() // set |cur_cmd|, |cur_chr|, |cur_tok|
- if int32(prg.curTok) < rightBraceLimit {
- goto done1
- }
- if int32(prg.curCmd) == macParam {
- s = uint16(matchToken + int32(prg.curChr))
- prg.getToken()
- if int32(prg.curTok) < leftBraceLimit {
- hashBrace = prg.curTok
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = prg.curTok
- p = q
- }
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = uint16(endMatchToken)
- p = q
- }
- goto done
- }
- if int32(t) == zeroToken+9 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "You already have nine parameters" */ 744)
- }
- // \xref[You already have nine...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I'm going to ignore the # sign you just used," */ 745
- prg.helpLine[0] = /* "as well as the token that followed it." */ 746
- }
- prg.error1()
- goto continue1
- } else {
- t = uint16(int32(t) + 1)
- if int32(prg.curTok) != int32(t) {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Parameters must be numbered consecutively" */ 747)
- }
- // \xref[Parameters...consecutively]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I've inserted the digit you should have used after the #." */ 748
- prg.helpLine[0] = /* "Type `1' to delete what you did use." */ 749
- }
- prg.backError()
- }
- prg.curTok = s
- }
- }
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = prg.curTok
- p = q
- }
- }
- done1:
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = uint16(endMatchToken)
- p = q
- }
- if int32(prg.curCmd) == rightBrace {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing [ inserted" */ 657)
- }
- prg.alignState = prg.alignState + 1
- // \xref[Missing \[ inserted]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Where was the left brace? You said something like `\\def\\a]'," */ 742
- prg.helpLine[0] = /* "which I'm going to interpret as `\\def\\a[]'." */ 743
- }
- prg.error1()
- goto found
- }
- done:
- } else {
- prg.scanLeftBrace()
- } // remove the compulsory left brace
- // Scan and build the body of the token list; |goto found| when finished
- unbalance = 1
- for true {
- if xpand {
- for true {
- prg.getNext()
- if int32(prg.curCmd) <= maxCommand {
- goto done2
- }
- if int32(prg.curCmd) != the {
- prg.expand()
- } else {
- q = prg.theToks()
- if int32(*(*prg.mem[30000-3].hh()).rh()) != 0 {
- *(*prg.mem[p].hh()).rh() = *(*prg.mem[30000-3].hh()).rh()
- p = q
- }
- }
- }
- done2:
- prg.xToken()
- } else {
- prg.getToken()
- }
- if int32(prg.curTok) < rightBraceLimit {
- if int32(prg.curCmd) < rightBrace {
- unbalance = uint16(int32(unbalance) + 1)
- } else {
- unbalance = uint16(int32(unbalance) - 1)
- if int32(unbalance) == 0 {
- goto found
- }
- }
- } else if int32(prg.curCmd) == macParam {
- if macroDef {
- s = prg.curTok
- if xpand {
- prg.getXToken()
- } else {
- prg.getToken()
- }
- if int32(prg.curCmd) != macParam {
- if int32(prg.curTok) <= zeroToken || int32(prg.curTok) > int32(t) {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Illegal parameter number in definition of " */ 750)
- }
- // \xref[Illegal parameter number...]
- prg.sprintCs(prg.warningIndex)
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "You meant to type ## instead of #, right?" */ 751
- prg.helpLine[1] = /* "Or maybe a ] was forgotten somewhere earlier, and things" */ 752
- prg.helpLine[0] = /* "are all screwed up? I'm going to assume that you meant ##." */ 753
- }
- prg.backError()
- prg.curTok = s
- } else {
- prg.curTok = uint16(outParamToken - '0' + int32(prg.curChr))
- }
- }
- }
- }
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = prg.curTok
- p = q
- }
- }
- found:
- prg.scannerStatus = byte(normal)
- if int32(hashBrace) != 0 {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = hashBrace
- p = q
- }
- r = p
- return r
- }
- // 482.
- // tangle:pos tex.web:9444:1:
- // The |read_toks| procedure constructs a token list like that for any
- // macro definition, and makes |cur_val| point to it. Parameter |r| points
- // to the control sequence that will receive this token list.
- func (prg *prg) readToks(n int32, r1 halfword) {
- var (
- p halfword // tail of the token list
- q halfword // new node being added to the token list via |store_new_token|
- s int32 // saved value of |align_state|
- m smallNumber // stream number
- )
- prg.scannerStatus = byte(defining)
- prg.warningIndex = r1
- prg.defRef = prg.getAvail()
- *(*prg.mem[prg.defRef].hh()).lh() = 0
- p = prg.defRef // the reference count
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = uint16(endMatchToken)
- p = q
- }
- if n < 0 || n > 15 {
- m = 16
- } else {
- m = byte(n)
- }
- s = prg.alignState
- prg.alignState = 1000000 // disable tab marks, etc.
- for {
- // Input and store tokens from the next line of the file
- prg.beginFileReading()
- prg.curInput.nameField = uint16(int32(m) + 1)
- if int32(prg.readOpen[m]) == closed {
- if int32(prg.interaction) > nonstopMode {
- if n < 0 {
- prg.print( /* "" */ 338)
- prg.termInput()
- } else {
- prg.printLn()
- prg.sprintCs(r1)
- {
- prg.print('=')
- prg.termInput()
- }
- n = -1
- }
- } else {
- prg.fatalError(strNumber( /* "*** (cannot \\read from terminal in nonstop modes)" */ 754))
- }
- } else if int32(prg.readOpen[m]) == justOpen {
- if prg.inputLn(prg.readFile[m], false) {
- prg.readOpen[m] = byte(normal)
- } else {
- prg.aClose(prg.readFile[m])
- prg.readOpen[m] = byte(closed)
- }
- } else {
- // Input the next line of |read_file[m]|
- if !prg.inputLn(prg.readFile[m], true) {
- prg.aClose(prg.readFile[m])
- prg.readOpen[m] = byte(closed)
- if prg.alignState != 1000000 {
- prg.runaway()
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "File ended within " */ 755)
- }
- prg.printEsc(strNumber( /* "read" */ 534))
- // \xref[File ended within \\read]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "This \\read has unbalanced braces." */ 756
- }
- prg.alignState = 1000000
- prg.curInput.limitField = 0
- prg.error1()
- }
- }
- }
- prg.curInput.limitField = prg.last
- if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
- prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
- } else {
- prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
- }
- prg.first = uint16(int32(prg.curInput.limitField) + 1)
- prg.curInput.locField = prg.curInput.startField
- prg.curInput.stateField = byte(newLine)
- for true {
- prg.getToken()
- if int32(prg.curTok) == 0 {
- goto done
- }
- // |cur_cmd=cur_chr=0| will occur at the end of the line
- if prg.alignState < 1000000 {
- for {
- prg.getToken()
- if int32(prg.curTok) == 0 {
- break
- }
- }
- prg.alignState = 1000000
- goto done
- }
- {
- q = prg.getAvail()
- *(*prg.mem[p].hh()).rh() = q
- *(*prg.mem[q].hh()).lh() = prg.curTok
- p = q
- }
- }
- done:
- prg.endFileReading()
- if prg.alignState == 1000000 {
- break
- }
- }
- prg.curVal = int32(prg.defRef)
- prg.scannerStatus = byte(normal)
- prg.alignState = s
- }
- func (prg *prg) passText() {
- var (
- l int32 // level of $\.[\\if]\ldots\.[\\fi]$ nesting
- saveScannerStatus smallNumber // |scanner_status| upon entry
- )
- saveScannerStatus = prg.scannerStatus
- prg.scannerStatus = byte(skipping)
- l = 0
- prg.skipLine = prg.line
- for true {
- prg.getNext()
- if int32(prg.curCmd) == fiOrElse {
- if l == 0 {
- goto done
- }
- if int32(prg.curChr) == fiCode {
- l = l - 1
- }
- } else if int32(prg.curCmd) == ifTest {
- l = l + 1
- }
- }
- done:
- prg.scannerStatus = saveScannerStatus
- }
- // 497.
- // tangle:pos tex.web:9693:1:
- // Here's a procedure that changes the |if_limit| code corresponding to
- // a given value of |cond_ptr|.
- func (prg *prg) changeIfLimit(l smallNumber, p halfword) {
- var (
- q halfword
- )
- if int32(p) == int32(prg.condPtr) {
- prg.ifLimit = l
- } else {
- q = prg.condPtr
- for true {
- if int32(q) == 0 {
- prg.confusion(strNumber( /* "if" */ 757))
- }
- // \xref[this can't happen if][\quad if]
- if int32(*(*prg.mem[q].hh()).rh()) == int32(p) {
- *(*prg.mem[q].hh()).b0() = l
- goto exit
- }
- q = *(*prg.mem[q].hh()).rh()
- }
- }
- exit:
- } // \2
- func (prg *prg) conditional() {
- var (
- b bool // is the condition true?
- r1/* '<'..'>' */ byte // relation to be evaluated
- m, n int32 // to be tested against the second operand
- p, q halfword // for traversing token lists in \.[\\ifx] tests
- saveScannerStatus smallNumber // |scanner_status| upon entry
- saveCondPtr halfword // |cond_ptr| corresponding to this conditional
- thisIf smallNumber // type of this conditional
- )
- {
- p = prg.getNode(ifNodeSize)
- *(*prg.mem[p].hh()).rh() = prg.condPtr
- *(*prg.mem[p].hh()).b0() = prg.ifLimit
- *(*prg.mem[p].hh()).b1() = prg.curIf
- *prg.mem[int32(p)+1].int() = prg.ifLine
- prg.condPtr = p
- prg.curIf = byte(prg.curChr)
- prg.ifLimit = byte(ifCode)
- prg.ifLine = prg.line
- }
- saveCondPtr = prg.condPtr
- thisIf = byte(prg.curChr)
- // Either process \.[\\ifcase] or set |b| to the value of a boolean condition
- switch thisIf {
- case ifCharCode, ifCatCode:
- // Test if two characters match
- {
- prg.getXToken()
- if int32(prg.curCmd) == relax {
- if int32(prg.curChr) == noExpandFlag {
- prg.curCmd = byte(activeChar)
- prg.curChr = uint16(int32(prg.curTok) - 07777 - activeBase)
- }
- }
- }
- if int32(prg.curCmd) > activeChar || int32(prg.curChr) > 255 {
- m = relax
- n = 256
- } else {
- m = int32(prg.curCmd)
- n = int32(prg.curChr)
- }
- /* */ {
- prg.getXToken()
- if int32(prg.curCmd) == relax {
- if int32(prg.curChr) == noExpandFlag {
- prg.curCmd = byte(activeChar)
- prg.curChr = uint16(int32(prg.curTok) - 07777 - activeBase)
- }
- }
- }
- if int32(prg.curCmd) > activeChar || int32(prg.curChr) > 255 {
- prg.curCmd = byte(relax)
- prg.curChr = 256
- }
- if int32(thisIf) == ifCharCode {
- b = n == int32(prg.curChr)
- } else {
- b = m == int32(prg.curCmd)
- }
- case ifIntCode, ifDimCode:
- // Test relation between integers or dimensions
- if int32(thisIf) == ifIntCode {
- prg.scanInt()
- } else {
- prg.scanDimen(false, false, false)
- }
- n = prg.curVal
- // Get the next non-blank non-call...
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- if int32(prg.curTok) >= otherToken+'<' && int32(prg.curTok) <= otherToken+'>' {
- r1 = byte(int32(prg.curTok) - otherToken)
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing = inserted for " */ 781)
- }
- // \xref[Missing = inserted]
- prg.printCmdChr(quarterword(ifTest), halfword(thisIf))
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I was expecting to see `<', `=', or `>'. Didn't." */ 782
- }
- prg.backError()
- r1 = '='
- }
- if int32(thisIf) == ifIntCode {
- prg.scanInt()
- } else {
- prg.scanDimen(false, false, false)
- }
- switch r1 {
- case '<':
- b = n < prg.curVal
- // "="=
- case '=':
- b = n == prg.curVal
- // ">"=
- case '>':
- b = n > prg.curVal
- }
- case ifOddCode:
- // Test if an integer is odd
- prg.scanInt()
- b = prg.curVal&1 != 0
- case ifVmodeCode:
- b = abs(int32(prg.curList.modeField)) == vmode
- case ifHmodeCode:
- b = abs(int32(prg.curList.modeField)) == hmode
- case ifMmodeCode:
- b = abs(int32(prg.curList.modeField)) == mmode
- case ifInnerCode:
- b = int32(prg.curList.modeField) < 0
- case ifVoidCode, ifHboxCode, ifVboxCode:
- // Test box register status
- prg.scanEightBitInt()
- p = *(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()
- if int32(thisIf) == ifVoidCode {
- b = int32(p) == 0
- } else if int32(p) == 0 {
- b = false
- } else if int32(thisIf) == ifHboxCode {
- b = int32(*(*prg.mem[p].hh()).b0()) == hlistNode
- } else {
- b = int32(*(*prg.mem[p].hh()).b0()) == vlistNode
- }
- case ifxCode:
- // Test if two tokens match
- saveScannerStatus = prg.scannerStatus
- prg.scannerStatus = byte(normal)
- prg.getNext()
- n = int32(prg.curCs)
- p = uint16(prg.curCmd)
- q = prg.curChr
- prg.getNext()
- if int32(prg.curCmd) != int32(p) {
- b = false
- } else if int32(prg.curCmd) < call {
- b = int32(prg.curChr) == int32(q)
- } else {
- // Test if two macro texts match
- p = *(*prg.mem[prg.curChr].hh()).rh()
- q = *(*prg.mem[*(*prg.eqtb[n-1].hh()).rh()].hh()).rh() // omit reference counts
- if int32(p) == int32(q) {
- b = true
- } else {
- for int32(p) != 0 && int32(q) != 0 {
- if int32(*(*prg.mem[p].hh()).lh()) != int32(*(*prg.mem[q].hh()).lh()) {
- p = 0
- } else {
- p = *(*prg.mem[p].hh()).rh()
- q = *(*prg.mem[q].hh()).rh()
- }
- }
- b = int32(p) == 0 && int32(q) == 0
- }
- }
- prg.scannerStatus = saveScannerStatus
- case ifEofCode:
- prg.scanFourBitInt()
- b = int32(prg.readOpen[prg.curVal]) == closed
- case ifTrueCode:
- b = true
- case ifFalseCode:
- b = false
- case ifCaseCode:
- // Select the appropriate case and |return| or |goto common_ending|
- prg.scanInt()
- n = prg.curVal // |n| is the number of cases to pass
- if *prg.eqtb[intBase+tracingCommandsCode-1].int() > 1 {
- prg.beginDiagnostic()
- prg.print( /* "[case " */ 783)
- prg.printInt(n)
- prg.printChar(asciiCode('}'))
- prg.endDiagnostic(false)
- }
- for n != 0 {
- prg.passText()
- if int32(prg.condPtr) == int32(saveCondPtr) {
- if int32(prg.curChr) == orCode {
- n = n - 1
- } else {
- goto commonEnding
- }
- } else if int32(prg.curChr) == fiCode {
- p = prg.condPtr
- prg.ifLine = *prg.mem[int32(p)+1].int()
- prg.curIf = *(*prg.mem[p].hh()).b1()
- prg.ifLimit = *(*prg.mem[p].hh()).b0()
- prg.condPtr = *(*prg.mem[p].hh()).rh()
- prg.freeNode(p, halfword(ifNodeSize))
- }
- }
- prg.changeIfLimit(smallNumber(orCode), saveCondPtr)
- goto exit // wait for \.[\\or], \.[\\else], or \.[\\fi]
- }
- if *prg.eqtb[intBase+tracingCommandsCode-1].int() > 1 {
- prg.beginDiagnostic()
- if b {
- prg.print( /* "[true]" */ 779)
- } else {
- prg.print( /* "[false]" */ 780)
- }
- prg.endDiagnostic(false)
- }
- if b {
- prg.changeIfLimit(smallNumber(elseCode), saveCondPtr)
- goto exit // wait for \.[\\else] or \.[\\fi]
- }
- // Skip to \.[\\else] or \.[\\fi], then |goto common_ending|
- for true {
- prg.passText()
- if int32(prg.condPtr) == int32(saveCondPtr) {
- if int32(prg.curChr) != orCode {
- goto commonEnding
- }
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Extra " */ 777)
- }
- prg.printEsc(strNumber( /* "or" */ 775))
- // \xref[Extra \\or]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm ignoring this; it doesn't match any \\if." */ 778
- }
- prg.error1()
- } else if int32(prg.curChr) == fiCode {
- p = prg.condPtr
- prg.ifLine = *prg.mem[int32(p)+1].int()
- prg.curIf = *(*prg.mem[p].hh()).b1()
- prg.ifLimit = *(*prg.mem[p].hh()).b0()
- prg.condPtr = *(*prg.mem[p].hh()).rh()
- prg.freeNode(p, halfword(ifNodeSize))
- }
- }
- commonEnding:
- if int32(prg.curChr) == fiCode {
- p = prg.condPtr
- prg.ifLine = *prg.mem[int32(p)+1].int()
- prg.curIf = *(*prg.mem[p].hh()).b1()
- prg.ifLimit = *(*prg.mem[p].hh()).b0()
- prg.condPtr = *(*prg.mem[p].hh()).rh()
- prg.freeNode(p, halfword(ifNodeSize))
- } else {
- prg.ifLimit = byte(fiCode)
- } // wait for \.[\\fi]
- // wait for \.[\\fi]
- exit:
- }
- // 499.
- // tangle:pos tex.web:9737:1:
- // In a construction like `\.[\\if\\iftrue abc\\else d\\fi]', the first
- // \.[\\else] that we come to after learning that the \.[\\if] is false is
- // not the \.[\\else] we're looking for. Hence the following curious
- // logic is needed.
- // 511. \[29] File names
- // tangle:pos tex.web:9910:19:
- // It's time now to fret about file names. Besides the fact that different
- // operating systems treat files in different ways, we must cope with the
- // fact that completely different naming conventions are used by different
- // groups of people. The following programs show what is required for one
- // particular operating system; similar routines for other systems are not
- // difficult to devise.
- // \xref[fingers]
- // \xref[system dependencies]
- //
- // \TeX\ assumes that a file name has three parts: the name proper; its
- // ``extension''; and a ``file area'' where it is found in an external file
- // system. The extension of an input file or a write file is assumed to be
- // `\.[.tex]' unless otherwise specified; it is `\.[.log]' on the
- // transcript file that records each run of \TeX; it is `\.[.tfm]' on the font
- // metric files that describe characters in the fonts \TeX\ uses; it is
- // `\.[.dvi]' on the output files that specify typesetting information; and it
- // is `\.[.fmt]' on the format files written by \.[INITEX] to initialize \TeX.
- // The file area can be arbitrary on input files, but files are usually
- // output to the user's current area. If an input file cannot be
- // found on the specified area, \TeX\ will look for it on a special system
- // area; this special area is intended for commonly used input files like
- // \.[webmac.tex].
- //
- // Simple uses of \TeX\ refer only to file names that have no explicit
- // extension or area. For example, a person usually says `\.[\\input] \.[paper]'
- // or `\.[\\font\\tenrm] \.= \.[helvetica]' instead of `\.[\\input]
- // \.[paper.new]' or `\.[\\font\\tenrm] \.= \.[<csd.knuth>test]'. Simple file
- // names are best, because they make the \TeX\ source files portable;
- // whenever a file name consists entirely of letters and digits, it should be
- // treated in the same way by all implementations of \TeX. However, users
- // need the ability to refer to other files in their environment, especially
- // when responding to error messages concerning unopenable files; therefore
- // we want to let them use the syntax that appears in their favorite
- // operating system.
- //
- // The following procedures don't allow spaces to be part of
- // file names; but some users seem to like names that are spaced-out.
- // System-dependent changes to allow such things should probably
- // be made with reluctance, and only when an entire file name that
- // includes spaces is ``quoted'' somehow.
- // 514.
- // tangle:pos tex.web:9998:1:
- // Input files that can't be found in the user's area may appear in a standard
- // system area called |TEX_area|. Font metric files whose areas are not given
- // explicitly are assumed to appear in a standard system area called
- // |TEX_font_area|. These system area names will, of course, vary from place
- // to place.
- // \xref[system dependencies]
- // 515.
- // tangle:pos tex.web:10010:1:
- // Here now is the first of the system-dependent routines for file name scanning.
- // \xref[system dependencies]
- func (prg *prg) beginName() {
- prg.areaDelimiter = 0
- prg.extDelimiter = 0
- }
- // 516.
- // tangle:pos tex.web:10017:1:
- // And here's the second. The string pool might change as the file name is
- // being scanned, since a new \.[\\csname] might be entered; therefore we keep
- // |area_delimiter| and |ext_delimiter| relative to the beginning of the current
- // string, instead of assigning an absolute address like |pool_ptr| to them.
- // \xref[system dependencies]
- func (prg *prg) moreName(c asciiCode) (r bool) {
- if int32(c) == ' ' {
- r = false
- } else {
- {
- if int32(prg.poolPtr)+1 > poolSize {
- prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
- } /* \xref[TeX capacity exceeded pool size][\quad pool size] */
- }
- {
- prg.strPool[prg.poolPtr] = c
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- } // contribute |c| to the current string
- if int32(c) == '>' || int32(c) == ':' {
- prg.areaDelimiter = uint16(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
- prg.extDelimiter = 0
- } else if int32(c) == '.' && int32(prg.extDelimiter) == 0 {
- prg.extDelimiter = uint16(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
- }
- r = true
- }
- return r
- }
- // 517.
- // tangle:pos tex.web:10034:1:
- // The third.
- // \xref[system dependencies]
- func (prg *prg) endName() {
- if int32(prg.strPtr)+3 > maxStrings {
- prg.overflow(strNumber( /* "number of strings" */ 258), maxStrings-int32(prg.initStrPtr))
- }
- // \xref[TeX capacity exceeded number of strings][\quad number of strings]
- if int32(prg.areaDelimiter) == 0 {
- prg.curArea = /* "" */ 338
- } else {
- prg.curArea = prg.strPtr
- prg.strStart[int32(prg.strPtr)+1] = uint16(int32(prg.strStart[prg.strPtr]) + int32(prg.areaDelimiter))
- prg.strPtr = uint16(int32(prg.strPtr) + 1)
- }
- if int32(prg.extDelimiter) == 0 {
- prg.curExt = /* "" */ 338
- prg.curName = prg.makeString()
- } else {
- prg.curName = prg.strPtr
- prg.strStart[int32(prg.strPtr)+1] = uint16(int32(prg.strStart[prg.strPtr]) + int32(prg.extDelimiter) - int32(prg.areaDelimiter) - 1)
- prg.strPtr = uint16(int32(prg.strPtr) + 1)
- prg.curExt = prg.makeString()
- }
- }
- // 519.
- // tangle:pos tex.web:10064:1:
- // Another system-dependent routine is needed to convert three internal
- // \TeX\ strings
- // into the |name_of_file| value that is used to open files. The present code
- // allows both lowercase and uppercase letters in the file name.
- // \xref[system dependencies]
- func (prg *prg) packFileName(n, a, e strNumber) {
- var (
- k int32 // number of positions filled in |name_of_file|
- c asciiCode // character being packed
- j poolPointer // index into |str_pool|
- )
- k = 0
- for ii := int32(prg.strStart[a]); ii <= int32(prg.strStart[int32(a)+1])-1; ii++ {
- j = poolPointer(ii)
- _ = j
- c = prg.strPool[j]
- k = k + 1
- if k <= fileNameSize {
- prg.nameOfFile[k-1] = prg.xchr[c]
- }
- }
- for ii := int32(prg.strStart[n]); ii <= int32(prg.strStart[int32(n)+1])-1; ii++ {
- j = poolPointer(ii)
- _ = j
- c = prg.strPool[j]
- k = k + 1
- if k <= fileNameSize {
- prg.nameOfFile[k-1] = prg.xchr[c]
- }
- }
- for ii := int32(prg.strStart[e]); ii <= int32(prg.strStart[int32(e)+1])-1; ii++ {
- j = poolPointer(ii)
- _ = j
- c = prg.strPool[j]
- k = k + 1
- if k <= fileNameSize {
- prg.nameOfFile[k-1] = prg.xchr[c]
- }
- }
- if k <= fileNameSize {
- prg.nameLength = byte(k)
- } else {
- prg.nameLength = byte(fileNameSize)
- }
- for ii := int32(prg.nameLength) + 1; ii <= fileNameSize; ii++ {
- k = ii
- _ = k
- prg.nameOfFile[k-1] = ' '
- }
- }
- // 523.
- // tangle:pos tex.web:10109:1:
- // Here is the messy routine that was just mentioned. It sets |name_of_file|
- // from the first |n| characters of |TEX_format_default|, followed by
- // |buffer[a..b]|, followed by the last |format_ext_length| characters of
- // |TEX_format_default|.
- //
- // We dare not give error messages here, since \TeX\ calls this routine before
- // the |error| routine is ready to roll. Instead, we simply drop excess characters,
- // since the error will be detected in another way when a strange file name
- // isn't found.
- // \xref[system dependencies]
- func (prg *prg) packBufferedName(n smallNumber, a, b int32) {
- var (
- k int32 // number of positions filled in |name_of_file|
- c asciiCode // character being packed
- j int32 // index into |buffer| or |TEX_format_default|
- )
- if int32(n)+b-a+1+formatExtLength > fileNameSize {
- b = a + fileNameSize - int32(n) - 1 - formatExtLength
- }
- k = 0
- for ii := int32(1); ii <= int32(n); ii++ {
- j = ii
- _ = j
- c = prg.xord[prg.texFormatDefault[j-1]]
- k = k + 1
- if k <= fileNameSize {
- prg.nameOfFile[k-1] = prg.xchr[c]
- }
- }
- for ii := a; ii <= b; ii++ {
- j = ii
- _ = j
- c = prg.buffer[j]
- k = k + 1
- if k <= fileNameSize {
- prg.nameOfFile[k-1] = prg.xchr[c]
- }
- }
- for ii := int32(formatDefaultLength - formatExtLength + 1); ii <= formatDefaultLength; ii++ {
- j = ii
- _ = j
- c = prg.xord[prg.texFormatDefault[j-1]]
- k = k + 1
- if k <= fileNameSize {
- prg.nameOfFile[k-1] = prg.xchr[c]
- }
- }
- if k <= fileNameSize {
- prg.nameLength = byte(k)
- } else {
- prg.nameLength = byte(fileNameSize)
- }
- for ii := int32(prg.nameLength) + 1; ii <= fileNameSize; ii++ {
- k = ii
- _ = k
- prg.nameOfFile[k-1] = ' '
- }
- }
- // 525.
- // tangle:pos tex.web:10172:1:
- // Operating systems often make it possible to determine the exact name (and
- // possible version number) of a file that has been opened. The following routine,
- // which simply makes a \TeX\ string from the value of |name_of_file|, should
- // ideally be changed to deduce the full name of file~|f|, which is the file
- // most recently opened, if it is possible to do this in a \PASCAL\ program.
- // \xref[system dependencies]
- //
- // This routine might be called after string memory has overflowed, hence
- // we dare not use `|str_room|'.
- func (prg *prg) makeNameString() (r strNumber) {
- var (
- k /* 1..fileNameSize */ byte // index into |name_of_file|
- )
- if int32(prg.poolPtr)+int32(prg.nameLength) > poolSize || int32(prg.strPtr) == maxStrings || int32(prg.poolPtr)-int32(prg.strStart[prg.strPtr]) > 0 {
- r = '?'
- } else {
- for ii := int32(1); ii <= int32(prg.nameLength); ii++ {
- k = byte(ii)
- _ = k
- prg.strPool[prg.poolPtr] = prg.xord[prg.nameOfFile[k-1]]
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- r = prg.makeString()
- }
- return r
- }
- func (prg *prg) aMakeNameString(f alphaFile) (r strNumber) {
- r = prg.makeNameString()
- return r
- }
- func (prg *prg) bMakeNameString(f byteFile) (r strNumber) {
- r = prg.makeNameString()
- return r
- }
- func (prg *prg) wMakeNameString(f wordFile) (r strNumber) {
- r = prg.makeNameString()
- return r
- }
- // 526.
- // tangle:pos tex.web:10201:1:
- // Now let's consider the “driver”
- // routines by which \TeX\ deals with file names
- // in a system-independent manner. First comes a procedure that looks for a
- // file name in the input by calling |get_x_token| for the information.
- func (prg *prg) scanFileName() {
- prg.nameInProgress = true
- prg.beginName()
- // Get the next non-blank non-call...
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- for true {
- if int32(prg.curCmd) > otherChar || int32(prg.curChr) > 255 {
- prg.backInput()
- goto done
- }
- if !prg.moreName(asciiCode(prg.curChr)) {
- goto done
- }
- prg.getXToken()
- }
- done:
- prg.endName()
- prg.nameInProgress = false
- }
- // 529.
- // tangle:pos tex.web:10243:1:
- // Here is a routine that manufactures the output file names, assuming that
- // |job_name<>0|. It ignores and changes the current settings of |cur_area|
- // and |cur_ext|.
- func (prg *prg) packJobName(s strNumber) {
- prg.curArea = /* "" */ 338
- prg.curExt = s
- prg.curName = prg.jobName
- prg.packFileName(prg.curName, prg.curArea, prg.curExt)
- }
- // 530.
- // tangle:pos tex.web:10255:1:
- // If some trouble arises when \TeX\ tries to open a file, the following
- // routine calls upon the user to supply another file name. Parameter~|s|
- // is used in the error message to identify the type of file; parameter~|e|
- // is the default extension if none is given. Upon exit from the routine,
- // variables |cur_name|, |cur_area|, |cur_ext|, and |name_of_file| are
- // ready for another attempt at file opening.
- func (prg *prg) promptFileName(s, e strNumber) {
- var (
- k /* 0..bufSize */ uint16 // index into |buffer|
- )
- if int32(prg.interaction) == scrollMode {
- }
- if int32(s) == 787 {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "I can't find file `" */ 788)
- } else {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "I can't write on file `" */ 789)
- }
- // \xref[I can't write on file x]
- prg.printFileName(int32(prg.curName), int32(prg.curArea), int32(prg.curExt))
- prg.print( /* "'." */ 790)
- if int32(e) == 791 {
- prg.showContext()
- }
- prg.printNl(strNumber( /* "Please type another " */ 792))
- prg.print(int32(s))
- // \xref[Please type...]
- if int32(prg.interaction) < scrollMode {
- prg.fatalError(strNumber( /* "*** (job aborted, file error in nonstop mode)" */ 793))
- }
- // \xref[job aborted, file error...]
- {
- prg.print( /* ": " */ 568)
- prg.termInput()
- }
- // Scan file name in the buffer
- {
- prg.beginName()
- k = prg.first
- for int32(prg.buffer[k]) == ' ' && int32(k) < int32(prg.last) {
- k = uint16(int32(k) + 1)
- }
- for true {
- if int32(k) == int32(prg.last) {
- goto done
- }
- if !prg.moreName(prg.buffer[k]) {
- goto done
- }
- k = uint16(int32(k) + 1)
- }
- done:
- prg.endName()
- }
- if int32(prg.curExt) == 338 {
- prg.curExt = e
- }
- prg.packFileName(prg.curName, prg.curArea, prg.curExt)
- } // \2
- func (prg *prg) openLogFile() {
- var (
- oldSetting/* 0..maxSelector */ byte // previous |selector| setting
- k/* 0..bufSize */ uint16 // index into |months| and |buffer|
- l/* 0..bufSize */ uint16 // end of first input line
- months [36]char // abbreviations of month names
- )
- oldSetting = prg.selector
- if int32(prg.jobName) == 0 {
- prg.jobName = /* "texput" */ 796
- }
- // \xref[texput]
- prg.packJobName(strNumber( /* ".log" */ 797))
- for !prg.aOpenOut(prg.logFile) {
- // Try to get a different log file name
- prg.selector = byte(termOnly)
- prg.promptFileName(strNumber( /* "transcript file name" */ 799), strNumber( /* ".log" */ 797))
- }
- prg.logName = prg.aMakeNameString(prg.logFile)
- prg.selector = byte(logOnly)
- prg.logOpened = true
- // Print the banner line, including the date and time
- {
- prg.logFile.Write("This is TeX, Version 3.141592653 (gotex v0.0-prerelease)")
- prg.slowPrint(int32(prg.formatIdent))
- prg.print( /* " " */ 800)
- prg.printInt(prg.sysDay)
- prg.printChar(asciiCode(' '))
- strcopy(months[:], "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC")
- for ii := 3*prg.sysMonth - 2; ii <= 3*prg.sysMonth; ii++ {
- k = uint16(ii)
- _ = k
- prg.logFile.Write(string(rune(months[k-1])))
- }
- prg.printChar(asciiCode(' '))
- prg.printInt(prg.sysYear)
- prg.printChar(asciiCode(' '))
- prg.printTwo(prg.sysTime / 60)
- prg.printChar(asciiCode(':'))
- prg.printTwo(prg.sysTime % 60)
- }
- prg.inputStack[prg.inputPtr] = prg.curInput // make sure bottom level is in memory
- prg.printNl(strNumber( /* "**" */ 798))
- // \xref[**]
- l = prg.inputStack[0].limitField // last position of first line
- if int32(prg.buffer[l]) == *prg.eqtb[intBase+endLineCharCode-1].int() {
- l = uint16(int32(l) - 1)
- }
- for ii := int32(1); ii <= int32(l); ii++ {
- k = uint16(ii)
- _ = k
- prg.print(int32(prg.buffer[k]))
- }
- prg.printLn() // now the transcript file contains the first line of input
- prg.selector = byte(int32(oldSetting) + 2) // |log_only| or |term_and_log|
- } // \2
- func (prg *prg) startInput() {
- prg.scanFileName() // set |cur_name| to desired file name
- if int32(prg.curExt) == 338 {
- prg.curExt = /* ".tex" */ 791
- }
- prg.packFileName(prg.curName, prg.curArea, prg.curExt)
- for true {
- prg.beginFileReading() // set up |cur_file| and new level of input
- if prg.aOpenIn(prg.inputFile[prg.curInput.indexField-1]) {
- goto done
- }
- if int32(prg.curArea) == 338 {
- prg.packFileName(prg.curName, strNumber( /* "TeXinputs:" */ 784), prg.curExt)
- if prg.aOpenIn(prg.inputFile[prg.curInput.indexField-1]) {
- goto done
- }
- }
- prg.endFileReading() // remove the level that didn't work
- prg.promptFileName(strNumber( /* "input file name" */ 787), strNumber( /* ".tex" */ 791))
- }
- done:
- prg.curInput.nameField = prg.aMakeNameString(prg.inputFile[prg.curInput.indexField-1])
- if int32(prg.jobName) == 0 {
- prg.jobName = prg.curName
- prg.openLogFile()
- } // |open_log_file| doesn't |show_context|, so |limit|
- // and |loc| needn't be set to meaningful values yet
- if int32(prg.termOffset)+(int32(prg.strStart[int32(prg.curInput.nameField)+1])-int32(prg.strStart[prg.curInput.nameField])) > maxPrintLine-2 {
- prg.printLn()
- } else if int32(prg.termOffset) > 0 || int32(prg.fileOffset) > 0 {
- prg.printChar(asciiCode(' '))
- }
- prg.printChar(asciiCode('('))
- prg.openParens = byte(int32(prg.openParens) + 1)
- prg.slowPrint(int32(prg.curInput.nameField))
- prg.curInput.stateField = byte(newLine)
- if int32(prg.curInput.nameField) == int32(prg.strPtr)-1 {
- {
- prg.strPtr = uint16(int32(prg.strPtr) - 1)
- prg.poolPtr = prg.strStart[prg.strPtr]
- }
- prg.curInput.nameField = prg.curName
- }
- // Read the first line of the new file
- {
- prg.line = 1
- if prg.inputLn(prg.inputFile[prg.curInput.indexField-1], false) {
- }
- prg.firmUpTheLine()
- if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
- prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
- } else {
- prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
- }
- prg.first = uint16(int32(prg.curInput.limitField) + 1)
- prg.curInput.locField = prg.curInput.startField
- }
- }
- // 540.
- // tangle:pos tex.web:10433:1:
- // The first 24 bytes (6 words) of a \.[TFM] file contain twelve 16-bit
- // integers that give the lengths of the various subsequent portions
- // of the file. These twelve integers are, in order:
- // $$\vbox[\halign[\hfil#&$\null=\null$#\hfil\cr
- // |lf|&length of the entire file, in words;\cr
- // |lh|&length of the header data, in words;\cr
- // |bc|&smallest character code in the font;\cr
- // |ec|&largest character code in the font;\cr
- // |nw|&number of words in the width table;\cr
- // |nh|&number of words in the height table;\cr
- // |nd|&number of words in the depth table;\cr
- // |ni|&number of words in the italic correction table;\cr
- // |nl|&number of words in the lig/kern table;\cr
- // |nk|&number of words in the kern table;\cr
- // |ne|&number of words in the extensible character table;\cr
- // |np|&number of font parameter words.\cr]]$$
- // They are all nonnegative and less than $2^[15]$. We must have |bc-1<=ec<=255|,
- // and
- // $$\hbox[|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.]$$
- // Note that a font may contain as many as 256 characters (if |bc=0| and |ec=255|),
- // and as few as 0 characters (if |bc=ec+1|).
- //
- // Incidentally, when two or more 8-bit bytes are combined to form an integer of
- // 16 or more bits, the most significant bytes appear first in the file.
- // This is called BigEndian order.
- // \xref[BigEndian order]
- // 541.
- // tangle:pos tex.web:10460:1:
- // The rest of the \.[TFM] file may be regarded as a sequence of ten data
- // arrays having the informal specification
- // $$\def\arr$[#1]#2$[\&[array] $[#1]$ \&[of] #2]
- // \vbox[\halign[\hfil\\[#]&$\,:\,$\arr#\hfil\cr
- // header&|[0..lh-1]\\[stuff]|\cr
- // char\_info&|[bc..ec]char_info_word|\cr
- // width&|[0..nw-1]fix_word|\cr
- // height&|[0..nh-1]fix_word|\cr
- // depth&|[0..nd-1]fix_word|\cr
- // italic&|[0..ni-1]fix_word|\cr
- // lig\_kern&|[0..nl-1]lig_kern_command|\cr
- // kern&|[0..nk-1]fix_word|\cr
- // exten&|[0..ne-1]extensible_recipe|\cr
- // param&|[1..np]fix_word|\cr]]$$
- // The most important data type used here is a | fix_word|, which is
- // a 32-bit representation of a binary fraction. A |fix_word| is a signed
- // quantity, with the two's complement of the entire word used to represent
- // negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the
- // binary point; thus, the largest |fix_word| value is $2048-2^[-20]$, and
- // the smallest is $-2048$. We will see below, however, that all but two of
- // the |fix_word| values must lie between $-16$ and $+16$.
- // 542.
- // tangle:pos tex.web:10482:1:
- // The first data array is a block of header information, which contains
- // general facts about the font. The header must contain at least two words,
- // |header[0]| and |header[1]|, whose meaning is explained below.
- // Additional header information of use to other software routines might
- // also be included, but \TeX82 does not need to know about such details.
- // For example, 16 more words of header information are in use at the Xerox
- // Palo Alto Research Center; the first ten specify the character coding
- // scheme used (e.g., `\.[XEROX text]' or `\.[TeX math symbols]'), the next five
- // give the font identifier (e.g., `\.[HELVETICA]' or `\.[CMSY]'), and the
- // last gives the ``face byte.'' The program that converts \.[DVI] files
- // to Xerox printing format gets this information by looking at the \.[TFM]
- // file, which it needs to read anyway because of other information that
- // is not explicitly repeated in \.[DVI]~format.
- //
- // \yskip\hang|header[0]| is a 32-bit check sum that \TeX\ will copy into
- // the \.[DVI] output file. Later on when the \.[DVI] file is printed,
- // possibly on another computer, the actual font that gets used is supposed
- // to have a check sum that agrees with the one in the \.[TFM] file used by
- // \TeX. In this way, users will be warned about potential incompatibilities.
- // (However, if the check sum is zero in either the font file or the \.[TFM]
- // file, no check is made.) The actual relation between this check sum and
- // the rest of the \.[TFM] file is not important; the check sum is simply an
- // identification number with the property that incompatible fonts almost
- // always have distinct check sums.
- // \xref[check sum]
- //
- // \yskip\hang|header[1]| is a |fix_word| containing the design size of
- // the font, in units of \TeX\ points. This number must be at least 1.0; it is
- // fairly arbitrary, but usually the design size is 10.0 for a ``10 point''
- // font, i.e., a font that was designed to look best at a 10-point size,
- // whatever that really means. When a \TeX\ user asks for a font
- // `\.[at] $\delta$ \.[pt]', the effect is to override the design size
- // and replace it by $\delta$, and to multiply the $x$ and~$y$ coordinates
- // of the points in the font image by a factor of $\delta$ divided by the
- // design size. [\sl All other dimensions in the\/ \.[TFM] file are
- // |fix_word|\kern-1pt\ numbers in design-size units], with the exception of
- // |param[1]| (which denotes the slant ratio). Thus, for example, the value
- // of |param[6]|, which defines the \.[em] unit, is often the |fix_word| value
- // $2^[20]=1.0$, since many fonts have a design size equal to one em.
- // The other dimensions must be less than 16 design-size units in absolute
- // value; thus, |header[1]| and |param[1]| are the only |fix_word|
- // entries in the whole \.[TFM] file whose first byte might be something
- // besides 0 or 255.
- // 543.
- // tangle:pos tex.web:10526:1:
- // Next comes the |char_info| array, which contains one | char_info_word|
- // per character. Each word in this part of the file contains six fields
- // packed into four bytes as follows.
- //
- // \yskip\hang first byte: | width_index| (8 bits)\par
- // \hang second byte: | height_index| (4 bits) times 16, plus | depth_index|
- // (4~bits)\par
- // \hang third byte: | italic_index| (6 bits) times 4, plus | tag|
- // (2~bits)\par
- // \hang fourth byte: | remainder| (8 bits)\par
- // \yskip\noindent
- // The actual width of a character is \\[width]|[width_index]|, in design-size
- // units; this is a device for compressing information, since many characters
- // have the same width. Since it is quite common for many characters
- // to have the same height, depth, or italic correction, the \.[TFM] format
- // imposes a limit of 16 different heights, 16 different depths, and
- // 64 different italic corrections.
- //
- // \xref[italic correction]
- // The italic correction of a character has two different uses.
- // (a)~In ordinary text, the italic correction is added to the width only if
- // the \TeX\ user specifies `\.[\\/]' after the character.
- // (b)~In math formulas, the italic correction is always added to the width,
- // except with respect to the positioning of subscripts.
- //
- // Incidentally, the relation $\\[width][0]=\\[height][0]=\\[depth][0]=
- // \\[italic][0]=0$ should always hold, so that an index of zero implies a
- // value of zero. The |width_index| should never be zero unless the
- // character does not exist in the font, since a character is valid if and
- // only if it lies between |bc| and |ec| and has a nonzero |width_index|.
- // 544.
- // tangle:pos tex.web:10557:1:
- // The |tag| field in a |char_info_word| has four values that explain how to
- // interpret the |remainder| field.
- //
- // \yskip\hangg|tag=0| (|no_tag|) means that |remainder| is unused.\par
- // \hangg|tag=1| (|lig_tag|) means that this character has a ligature/kerning
- // program starting at position |remainder| in the |lig_kern| array.\par
- // \hangg|tag=2| (|list_tag|) means that this character is part of a chain of
- // characters of ascending sizes, and not the largest in the chain. The
- // |remainder| field gives the character code of the next larger character.\par
- // \hangg|tag=3| (|ext_tag|) means that this character code represents an
- // extensible character, i.e., a character that is built up of smaller pieces
- // so that it can be made arbitrarily large. The pieces are specified in
- // | exten[remainder]|.\par
- // \yskip\noindent
- // Characters with |tag=2| and |tag=3| are treated as characters with |tag=0|
- // unless they are used in special circumstances in math formulas. For example,
- // the \.[\\sum] operation looks for a |list_tag|, and the \.[\\left]
- // operation looks for both |list_tag| and |ext_tag|.
- // 545.
- // tangle:pos tex.web:10581:1:
- // The |lig_kern| array contains instructions in a simple programming language
- // that explains what to do for special letter pairs. Each word in this array is a
- // | lig_kern_command| of four bytes.
- //
- // \yskip\hang first byte: |skip_byte|, indicates that this is the final program
- // step if the byte is 128 or more, otherwise the next step is obtained by
- // skipping this number of intervening steps.\par
- // \hang second byte: |next_char|, ``if |next_char| follows the current character,
- // then perform the operation and stop, otherwise continue.''\par
- // \hang third byte: |op_byte|, indicates a ligature step if less than~128,
- // a kern step otherwise.\par
- // \hang fourth byte: |remainder|.\par
- // \yskip\noindent
- // In a kern step, an
- // additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
- // between the current character and |next_char|. This amount is
- // often negative, so that the characters are brought closer together
- // by kerning; but it might be positive.
- //
- // There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
- // $0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
- // |remainder| is inserted between the current character and |next_char|;
- // then the current character is deleted if $b=0$, and |next_char| is
- // deleted if $c=0$; then we pass over $a$~characters to reach the next
- // current character (which may have a ligature/kerning program of its own).
- //
- // If the very first instruction of the |lig_kern| array has |skip_byte=255|,
- // the |next_char| byte is the so-called boundary character of this font;
- // the value of |next_char| need not lie between |bc| and~|ec|.
- // If the very last instruction of the |lig_kern| array has |skip_byte=255|,
- // there is a special ligature/kerning program for a boundary character at the
- // left, beginning at location |256*op_byte+remainder|.
- // The interpretation is that \TeX\ puts implicit boundary characters
- // before and after each consecutive string of characters from the same font.
- // These implicit characters do not appear in the output, but they can affect
- // ligatures and kerning.
- //
- // If the very first instruction of a character's |lig_kern| program has
- // |skip_byte>128|, the program actually begins in location
- // |256*op_byte+remainder|. This feature allows access to large |lig_kern|
- // arrays, because the first instruction must otherwise
- // appear in a location |<=255|.
- //
- // Any instruction with |skip_byte>128| in the |lig_kern| array must satisfy
- // the condition
- // $$\hbox[|256*op_byte+remainder<nl|.]$$
- // If such an instruction is encountered during
- // normal program execution, it denotes an unconditional halt; no ligature
- // or kerning command is performed.
- // 546.
- // tangle:pos tex.web:10638:1:
- // Extensible characters are specified by an | extensible_recipe|, which
- // consists of four bytes called | top|, | mid|, | bot|, and | rep| (in this
- // order). These bytes are the character codes of individual pieces used to
- // build up a large symbol. If |top|, |mid|, or |bot| are zero, they are not
- // present in the built-up result. For example, an extensible vertical line is
- // like an extensible bracket, except that the top and bottom pieces are missing.
- //
- // Let $T$, $M$, $B$, and $R$ denote the respective pieces, or an empty box
- // if the piece isn't present. Then the extensible characters have the form
- // $TR^kMR^kB$ from top to bottom, for some |k>=0|, unless $M$ is absent;
- // in the latter case we can have $TR^kB$ for both even and odd values of~|k|.
- // The width of the extensible character is the width of $R$; and the
- // height-plus-depth is the sum of the individual height-plus-depths of the
- // components used, since the pieces are butted together in a vertical list.
- // 547.
- // tangle:pos tex.web:10658:1:
- // The final portion of a \.[TFM] file is the |param| array, which is another
- // sequence of |fix_word| values.
- //
- // \yskip\hang|param[1]=slant| is the amount of italic slant, which is used
- // to help position accents. For example, |slant=.25| means that when you go
- // up one unit, you also go .25 units to the right. The |slant| is a pure
- // number; it's the only |fix_word| other than the design size itself that is
- // not scaled by the design size.
- //
- // \hang|param[2]=space| is the normal spacing between words in text.
- // Note that character |" "| in the font need not have anything to do with
- // blank spaces.
- //
- // \hang|param[3]=space_stretch| is the amount of glue stretching between words.
- //
- // \hang|param[4]=space_shrink| is the amount of glue shrinking between words.
- //
- // \hang|param[5]=x_height| is the size of one ex in the font; it is also
- // the height of letters for which accents don't have to be raised or lowered.
- //
- // \hang|param[6]=quad| is the size of one em in the font.
- //
- // \hang|param[7]=extra_space| is the amount added to |param[2]| at the
- // ends of sentences.
- //
- // \yskip\noindent
- // If fewer than seven parameters are present, \TeX\ sets the missing parameters
- // to zero. Fonts used for math symbols are required to have
- // additional parameter information, which is explained later.
- // 554.
- // tangle:pos tex.web:10804:1:
- // Of course we want to define macros that suppress the detail of how font
- // information is actually packed, so that we don't have to write things like
- // $$\hbox[|font_info[width_base[f]+font_info[char_base[f]+c].qqqq.b0].sc|]$$
- // too often. The \.[WEB] definitions here make |char_info(f)(c)| the
- // |four_quarters| word of font information corresponding to character
- // |c| of font |f|. If |q| is such a word, |char_width(f)(q)| will be
- // the character's width; hence the long formula above is at least
- // abbreviated to
- // $$\hbox[|char_width(f)(char_info(f)(c))|.]$$
- // Usually, of course, we will fetch |q| first and look at several of its
- // fields at the same time.
- //
- // The italic correction of a character will be denoted by
- // |char_italic(f)(q)|, so it is analogous to |char_width|. But we will get
- // at the height and depth in a slightly different way, since we usually want
- // to compute both height and depth if we want either one. The value of
- // |height_depth(q)| will be the 8-bit quantity
- // $$b=|height_index|\times16+|depth_index|,$$ and if |b| is such a byte we
- // will write |char_height(f)(b)| and |char_depth(f)(b)| for the height and
- // depth of the character |c| for which |q=char_info(f)(c)|. Got that?
- //
- // The tag field will be called |char_tag(q)|; the remainder byte will be
- // called |rem_byte(q)|, using a macro that we have already defined above.
- //
- // Access to a character's |width|, |height|, |depth|, and |tag| fields is
- // part of \TeX's inner loop, so we want these macros to produce code that is
- // as fast as possible under the circumstances.
- // \xref[inner loop]
- // 557.
- // tangle:pos tex.web:10858:1:
- // Here are some macros that help process ligatures and kerns.
- // We write |char_kern(f)(j)| to find the amount of kerning specified by
- // kerning command~|j| in font~|f|. If |j| is the |char_info| for a character
- // with a ligature/kern program, the first instruction of that program is either
- // |i=font_info[lig_kern_start(f)(j)]| or |font_info[lig_kern_restart(f)(i)]|,
- // depending on whether or not |skip_byte(i)<=stop_flag|.
- //
- // The constant |kern_base_offset| should be simplified, for \PASCAL\ compilers
- // that do not do local optimization.
- // \xref[system dependencies]
- // 560.
- // tangle:pos tex.web:10892:1:
- // \TeX\ checks the information of a \.[TFM] file for validity as the
- // file is being read in, so that no further checks will be needed when
- // typesetting is going on. The somewhat tedious subroutine that does this
- // is called |read_font_info|. It has four parameters: the user font
- // identifier~|u|, the file name and area strings |nom| and |aire|, and the
- // “at” size~|s|. If |s|~is negative, it's the negative of a scale factor
- // to be applied to the design size; |s=-1000| is the normal case.
- // Otherwise |s| will be substituted for the design size; in this
- // case, |s| must be positive and less than $2048\rm\,pt$
- // (i.e., it must be less than $2^[27]$ when considered as an integer).
- //
- // The subroutine opens and closes a global file variable called |tfm_file|.
- // It returns the value of the internal font number that was just loaded.
- // If an error is detected, an error message is issued and no font
- // information is stored; |null_font| is returned in this case.
- func (prg *prg) readFontInfo(u halfword, nom, aire strNumber,
- s scaled) (r internalFontNumber) {
- var (
- k fontIndex // index into |font_info|
- fileOpened bool // was |tfm_file| successfully opened?
- lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np halfword
- // sizes of subfiles
- f internalFontNumber // the new font's number
- g internalFontNumber // the number to return
- a, b, c, d eightBits // byte variables
- qw fourQuarters
- sw scaled // accumulators
- bchLabel int32 // left boundary start location, or infinity
- bchar/* 0..256 */ uint16 // boundary character, or 256
- z scaled // the design size or the ``at'' size
- alpha int32
- beta/* 1..16 */ byte
- // auxiliary quantities used in fixed-point multiplication
- )
- g = byte(fontBase)
- // Read and check the font data; |abort| if the \.[TFM] file is malformed; if there's no room for this font, say so and |goto done|; otherwise |incr(font_ptr)| and |goto done|
- // Open |tfm_file| for input
- fileOpened = false
- if int32(aire) == 338 {
- prg.packFileName(nom, strNumber( /* "TeXfonts:" */ 785), strNumber( /* ".tfm" */ 811))
- } else {
- prg.packFileName(nom, aire, strNumber( /* ".tfm" */ 811))
- }
- if !prg.bOpenIn(prg.tfmFile) {
- goto badTfm
- }
- fileOpened = true
- // Read the [\.[TFM]] size fields
- {
- {
- lf = uint16(*prg.tfmFile.ByteP())
- if int32(lf) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- lf = uint16(int32(lf)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- lh = uint16(*prg.tfmFile.ByteP())
- if int32(lh) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- lh = uint16(int32(lh)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- bc = uint16(*prg.tfmFile.ByteP())
- if int32(bc) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- bc = uint16(int32(bc)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- ec = uint16(*prg.tfmFile.ByteP())
- if int32(ec) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- ec = uint16(int32(ec)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- if int32(bc) > int32(ec)+1 || int32(ec) > 255 {
- goto badTfm
- }
- if int32(bc) > 255 {
- bc = 1
- ec = 0
- }
- prg.tfmFile.Get()
- {
- nw = uint16(*prg.tfmFile.ByteP())
- if int32(nw) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- nw = uint16(int32(nw)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- nh = uint16(*prg.tfmFile.ByteP())
- if int32(nh) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- nh = uint16(int32(nh)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- nd = uint16(*prg.tfmFile.ByteP())
- if int32(nd) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- nd = uint16(int32(nd)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- ni = uint16(*prg.tfmFile.ByteP())
- if int32(ni) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- ni = uint16(int32(ni)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- nl = uint16(*prg.tfmFile.ByteP())
- if int32(nl) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- nl = uint16(int32(nl)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- nk = uint16(*prg.tfmFile.ByteP())
- if int32(nk) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- nk = uint16(int32(nk)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- ne = uint16(*prg.tfmFile.ByteP())
- if int32(ne) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- ne = uint16(int32(ne)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- prg.tfmFile.Get()
- {
- np = uint16(*prg.tfmFile.ByteP())
- if int32(np) > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- np = uint16(int32(np)*0400 + int32(*prg.tfmFile.ByteP()))
- }
- if int32(lf) != 6+int32(lh)+(int32(ec)-int32(bc)+1)+int32(nw)+int32(nh)+int32(nd)+int32(ni)+int32(nl)+int32(nk)+int32(ne)+int32(np) {
- goto badTfm
- }
- if int32(nw) == 0 || int32(nh) == 0 || int32(nd) == 0 || int32(ni) == 0 {
- goto badTfm
- }
- }
- // Use size fields to allocate font information
- lf = uint16(int32(lf) - 6 - int32(lh)) // |lf| words should be loaded into |font_info|
- if int32(np) < 7 {
- lf = uint16(int32(lf) + 7 - int32(np))
- } // at least seven parameters will appear
- if int32(prg.fontPtr) == fontMax || int32(prg.fmemPtr)+int32(lf) > fontMemSize {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Font " */ 802)
- }
- prg.sprintCs(u)
- prg.printChar(asciiCode('='))
- prg.printFileName(int32(nom), int32(aire) /* "" */, 338)
- if s >= 0 {
- prg.print( /* " at " */ 741)
- prg.printScaled(s)
- prg.print( /* "pt" */ 397)
- } else if s != -1000 {
- prg.print( /* " scaled " */ 803)
- prg.printInt(-s)
- }
- prg.print( /* " not loaded: Not enough room left" */ 812)
- // \xref[Font x=xx not loaded...]
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "I'm afraid I won't be able to make use of this font," */ 813
- prg.helpLine[2] = /* "because my memory for character-size data is too small." */ 814
- prg.helpLine[1] = /* "If you're really stuck, ask a wizard to enlarge me." */ 815
- prg.helpLine[0] = /* "Or maybe try `I\\font<same font id>=<name of loaded font>'." */ 816
- }
- prg.error1()
- goto done
- }
- f = byte(int32(prg.fontPtr) + 1)
- prg.charBase[f] = int32(prg.fmemPtr) - int32(bc)
- prg.widthBase[f] = prg.charBase[f] + int32(ec) + 1
- prg.heightBase[f] = prg.widthBase[f] + int32(nw)
- prg.depthBase[f] = prg.heightBase[f] + int32(nh)
- prg.italicBase[f] = prg.depthBase[f] + int32(nd)
- prg.ligKernBase[f] = prg.italicBase[f] + int32(ni)
- prg.kernBase[f] = prg.ligKernBase[f] + int32(nl) - 256*(128+minQuarterword)
- prg.extenBase[f] = prg.kernBase[f] + 256*(128+minQuarterword) + int32(nk)
- prg.paramBase[f] = prg.extenBase[f] + int32(ne)
- // Read the [\.[TFM]] header
- {
- if int32(lh) < 2 {
- goto badTfm
- }
- {
- prg.tfmFile.Get()
- a = *prg.tfmFile.ByteP()
- qw.b0 = byte(int32(a) + minQuarterword)
- prg.tfmFile.Get()
- b = *prg.tfmFile.ByteP()
- qw.b1 = byte(int32(b) + minQuarterword)
- prg.tfmFile.Get()
- c = *prg.tfmFile.ByteP()
- qw.b2 = byte(int32(c) + minQuarterword)
- prg.tfmFile.Get()
- d = *prg.tfmFile.ByteP()
- qw.b3 = byte(int32(d) + minQuarterword)
- prg.fontCheck[f] = qw
- }
- prg.tfmFile.Get()
- {
- z = int32(*prg.tfmFile.ByteP())
- if z > 127 {
- goto badTfm
- }
- prg.tfmFile.Get()
- z = z*0400 + int32(*prg.tfmFile.ByteP())
- } // this rejects a negative design size
- prg.tfmFile.Get()
- z = z*0400 + int32(*prg.tfmFile.ByteP())
- prg.tfmFile.Get()
- z = z*020 + int32(*prg.tfmFile.ByteP())/020
- if z < 0200000 {
- goto badTfm
- }
- for int32(lh) > 2 {
- prg.tfmFile.Get()
- prg.tfmFile.Get()
- prg.tfmFile.Get()
- prg.tfmFile.Get()
- lh = uint16(int32(lh) - 1) // ignore the rest of the header
- }
- prg.fontDsize[f] = z
- if s != -1000 {
- if s >= 0 {
- z = s
- } else {
- z = prg.xnOverD(z, -s, 1000)
- }
- }
- prg.fontSize[f] = z
- }
- // Read character data
- for ii := int32(prg.fmemPtr); ii <= prg.widthBase[f]-1; ii++ {
- k = fontIndex(ii)
- _ = k
- {
- prg.tfmFile.Get()
- a = *prg.tfmFile.ByteP()
- qw.b0 = byte(int32(a) + minQuarterword)
- prg.tfmFile.Get()
- b = *prg.tfmFile.ByteP()
- qw.b1 = byte(int32(b) + minQuarterword)
- prg.tfmFile.Get()
- c = *prg.tfmFile.ByteP()
- qw.b2 = byte(int32(c) + minQuarterword)
- prg.tfmFile.Get()
- d = *prg.tfmFile.ByteP()
- qw.b3 = byte(int32(d) + minQuarterword)
- *prg.fontInfo[k].qqqq() = qw
- }
- if int32(a) >= int32(nw) || int32(b)/020 >= int32(nh) || int32(b)%020 >= int32(nd) || int32(c)/4 >= int32(ni) {
- goto badTfm
- }
- switch int32(c) % 4 {
- case ligTag:
- if int32(d) >= int32(nl) {
- goto badTfm
- }
- case extTag:
- if int32(d) >= int32(ne) {
- goto badTfm
- }
- case listTag:
- // Check for charlist cycle
- {
- if int32(d) < int32(bc) || int32(d) > int32(ec) {
- goto badTfm
- }
- }
- for int32(d) < int32(k)+int32(bc)-int32(prg.fmemPtr) {
- qw = *prg.fontInfo[prg.charBase[f]+int32(d)].qqqq()
- // N.B.: not |qi(d)|, since |char_base[f]| hasn't been adjusted yet
- if (int32(qw.b2)-minQuarterword)%4 != listTag {
- goto notFound
- }
- d = byte(int32(qw.b3) - minQuarterword) // next character on the list
- }
- if int32(d) == int32(k)+int32(bc)-int32(prg.fmemPtr) {
- goto badTfm
- } // yes, there's a cycle
- // yes, there's a cycle
- notFound:
- ;
- default: // |no_tag|
- }
- }
- // Read box dimensions
- {
- {
- alpha = 16
- for z >= 040000000 {
- z = z / 2
- alpha = alpha + alpha
- }
- beta = byte(256 / alpha)
- alpha = alpha * z
- }
- for ii := prg.widthBase[f]; ii <= prg.ligKernBase[f]-1; ii++ {
- k = fontIndex(ii)
- _ = k
- prg.tfmFile.Get()
- a = *prg.tfmFile.ByteP()
- prg.tfmFile.Get()
- b = *prg.tfmFile.ByteP()
- prg.tfmFile.Get()
- c = *prg.tfmFile.ByteP()
- prg.tfmFile.Get()
- d = *prg.tfmFile.ByteP()
- sw = ((int32(d)*z/0400+int32(c)*z)/0400 + int32(b)*z) / int32(beta)
- if int32(a) == 0 {
- *prg.fontInfo[k].int() = sw
- } else if int32(a) == 255 {
- *prg.fontInfo[k].int() = sw - alpha
- } else {
- goto badTfm
- }
- }
- if *prg.fontInfo[prg.widthBase[f]].int() != 0 {
- goto badTfm
- } // \\[width][0] must be zero
- if *prg.fontInfo[prg.heightBase[f]].int() != 0 {
- goto badTfm
- } // \\[height][0] must be zero
- if *prg.fontInfo[prg.depthBase[f]].int() != 0 {
- goto badTfm
- } // \\[depth][0] must be zero
- if *prg.fontInfo[prg.italicBase[f]].int() != 0 {
- goto badTfm
- } // \\[italic][0] must be zero
- }
- // Read ligature/kern program
- bchLabel = 077777
- bchar = 256
- if int32(nl) > 0 {
- for ii := prg.ligKernBase[f]; ii <= prg.kernBase[f]+256*(128+minQuarterword)-1; ii++ {
- k = fontIndex(ii)
- _ = k
- {
- prg.tfmFile.Get()
- a = *prg.tfmFile.ByteP()
- qw.b0 = byte(int32(a) + minQuarterword)
- prg.tfmFile.Get()
- b = *prg.tfmFile.ByteP()
- qw.b1 = byte(int32(b) + minQuarterword)
- prg.tfmFile.Get()
- c = *prg.tfmFile.ByteP()
- qw.b2 = byte(int32(c) + minQuarterword)
- prg.tfmFile.Get()
- d = *prg.tfmFile.ByteP()
- qw.b3 = byte(int32(d) + minQuarterword)
- *prg.fontInfo[k].qqqq() = qw
- }
- if int32(a) > 128 {
- if 256*int32(c)+int32(d) >= int32(nl) {
- goto badTfm
- }
- if int32(a) == 255 {
- if int32(k) == prg.ligKernBase[f] {
- bchar = uint16(b)
- }
- }
- } else {
- if int32(b) != int32(bchar) {
- {
- if int32(b) < int32(bc) || int32(b) > int32(ec) {
- goto badTfm
- }
- }
- qw = *prg.fontInfo[prg.charBase[f]+int32(b)].qqqq()
- if !(int32(qw.b0) > minQuarterword) {
- goto badTfm
- }
- }
- if int32(c) < 128 {
- {
- if int32(d) < int32(bc) || int32(d) > int32(ec) {
- goto badTfm
- }
- }
- qw = *prg.fontInfo[prg.charBase[f]+int32(d)].qqqq()
- if !(int32(qw.b0) > minQuarterword) {
- goto badTfm
- }
- } else if 256*(int32(c)-128)+int32(d) >= int32(nk) {
- goto badTfm
- } // check kern
- if int32(a) < 128 {
- if int32(k)-prg.ligKernBase[f]+int32(a)+1 >= int32(nl) {
- goto badTfm
- }
- }
- }
- }
- if int32(a) == 255 {
- bchLabel = 256*int32(c) + int32(d)
- }
- }
- for ii := prg.kernBase[f] + 256*(128+minQuarterword); ii <= prg.extenBase[f]-1; ii++ {
- k = fontIndex(ii)
- _ = k
- prg.tfmFile.Get()
- a = *prg.tfmFile.ByteP()
- prg.tfmFile.Get()
- b = *prg.tfmFile.ByteP()
- prg.tfmFile.Get()
- c = *prg.tfmFile.ByteP()
- prg.tfmFile.Get()
- d = *prg.tfmFile.ByteP()
- sw = ((int32(d)*z/0400+int32(c)*z)/0400 + int32(b)*z) / int32(beta)
- if int32(a) == 0 {
- *prg.fontInfo[k].int() = sw
- } else if int32(a) == 255 {
- *prg.fontInfo[k].int() = sw - alpha
- } else {
- goto badTfm
- }
- }
- // Read extensible character recipes
- for ii := prg.extenBase[f]; ii <= prg.paramBase[f]-1; ii++ {
- k = fontIndex(ii)
- _ = k
- {
- prg.tfmFile.Get()
- a = *prg.tfmFile.ByteP()
- qw.b0 = byte(int32(a) + minQuarterword)
- prg.tfmFile.Get()
- b = *prg.tfmFile.ByteP()
- qw.b1 = byte(int32(b) + minQuarterword)
- prg.tfmFile.Get()
- c = *prg.tfmFile.ByteP()
- qw.b2 = byte(int32(c) + minQuarterword)
- prg.tfmFile.Get()
- d = *prg.tfmFile.ByteP()
- qw.b3 = byte(int32(d) + minQuarterword)
- *prg.fontInfo[k].qqqq() = qw
- }
- if int32(a) != 0 {
- {
- if int32(a) < int32(bc) || int32(a) > int32(ec) {
- goto badTfm
- }
- }
- qw = *prg.fontInfo[prg.charBase[f]+int32(a)].qqqq()
- if !(int32(qw.b0) > minQuarterword) {
- goto badTfm
- }
- }
- if int32(b) != 0 {
- {
- if int32(b) < int32(bc) || int32(b) > int32(ec) {
- goto badTfm
- }
- }
- qw = *prg.fontInfo[prg.charBase[f]+int32(b)].qqqq()
- if !(int32(qw.b0) > minQuarterword) {
- goto badTfm
- }
- }
- if int32(c) != 0 {
- {
- if int32(c) < int32(bc) || int32(c) > int32(ec) {
- goto badTfm
- }
- }
- qw = *prg.fontInfo[prg.charBase[f]+int32(c)].qqqq()
- if !(int32(qw.b0) > minQuarterword) {
- goto badTfm
- }
- }
- /* */ {
- {
- if int32(d) < int32(bc) || int32(d) > int32(ec) {
- goto badTfm
- }
- }
- qw = *prg.fontInfo[prg.charBase[f]+int32(d)].qqqq()
- if !(int32(qw.b0) > minQuarterword) {
- goto badTfm
- }
- }
- }
- // Read font parameters
- {
- for ii := int32(1); ii <= int32(np); ii++ {
- k = fontIndex(ii)
- _ = k
- if int32(k) == 1 {
- prg.tfmFile.Get()
- sw = int32(*prg.tfmFile.ByteP())
- if sw > 127 {
- sw = sw - 256
- }
- prg.tfmFile.Get()
- sw = sw*0400 + int32(*prg.tfmFile.ByteP())
- prg.tfmFile.Get()
- sw = sw*0400 + int32(*prg.tfmFile.ByteP())
- prg.tfmFile.Get()
- *prg.fontInfo[prg.paramBase[f]].int() = sw*020 + int32(*prg.tfmFile.ByteP())/020
- } else {
- prg.tfmFile.Get()
- a = *prg.tfmFile.ByteP()
- prg.tfmFile.Get()
- b = *prg.tfmFile.ByteP()
- prg.tfmFile.Get()
- c = *prg.tfmFile.ByteP()
- prg.tfmFile.Get()
- d = *prg.tfmFile.ByteP()
- sw = ((int32(d)*z/0400+int32(c)*z)/0400 + int32(b)*z) / int32(beta)
- if int32(a) == 0 {
- *prg.fontInfo[prg.paramBase[f]+int32(k)-1].int() = sw
- } else if int32(a) == 255 {
- *prg.fontInfo[prg.paramBase[f]+int32(k)-1].int() = sw - alpha
- } else {
- goto badTfm
- }
- }
- }
- if prg.tfmFile.EOF() {
- goto badTfm
- }
- for ii := int32(np) + 1; ii <= 7; ii++ {
- k = fontIndex(ii)
- _ = k
- *prg.fontInfo[prg.paramBase[f]+int32(k)-1].int() = 0
- }
- }
- // Make final adjustments and |goto done|
- if int32(np) >= 7 {
- prg.fontParams[f] = np
- } else {
- prg.fontParams[f] = 7
- }
- prg.hyphenChar[f] = *prg.eqtb[intBase+defaultHyphenCharCode-1].int()
- prg.skewChar[f] = *prg.eqtb[intBase+defaultSkewCharCode-1].int()
- if bchLabel < int32(nl) {
- prg.bcharLabel[f] = uint16(bchLabel + prg.ligKernBase[f])
- } else {
- prg.bcharLabel[f] = uint16(nonAddress)
- }
- prg.fontBchar[f] = uint16(int32(bchar) + minQuarterword)
- prg.fontFalseBchar[f] = uint16(int32(bchar) + minQuarterword)
- if int32(bchar) <= int32(ec) {
- if int32(bchar) >= int32(bc) {
- qw = *prg.fontInfo[prg.charBase[f]+int32(bchar)].qqqq() // N.B.: not |qi(bchar)|
- if int32(qw.b0) > minQuarterword {
- prg.fontFalseBchar[f] = uint16(256 + minQuarterword)
- }
- }
- }
- prg.fontName[f] = nom
- prg.fontArea[f] = aire
- prg.fontBc[f] = byte(bc)
- prg.fontEc[f] = byte(ec)
- prg.fontGlue[f] = 0
- prg.charBase[f] = prg.charBase[f] - minQuarterword
- prg.widthBase[f] = prg.widthBase[f] - minQuarterword
- prg.ligKernBase[f] = prg.ligKernBase[f] - minQuarterword
- prg.kernBase[f] = prg.kernBase[f] - minQuarterword
- prg.extenBase[f] = prg.extenBase[f] - minQuarterword
- prg.paramBase[f] = prg.paramBase[f] - 1
- prg.fmemPtr = uint16(int32(prg.fmemPtr) + int32(lf))
- prg.fontPtr = f
- g = f
- goto done
- badTfm:
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Font " */ 802)
- }
- prg.sprintCs(u)
- prg.printChar(asciiCode('='))
- prg.printFileName(int32(nom), int32(aire) /* "" */, 338)
- if s >= 0 {
- prg.print( /* " at " */ 741)
- prg.printScaled(s)
- prg.print( /* "pt" */ 397)
- } else if s != -1000 {
- prg.print( /* " scaled " */ 803)
- prg.printInt(-s)
- }
- // \xref[Font x=xx not loadable...]
- if fileOpened {
- prg.print( /* " not loadable: Bad metric (TFM) file" */ 804)
- } else {
- prg.print( /* " not loadable: Metric (TFM) file not found" */ 805)
- }
- {
- prg.helpPtr = 5
- prg.helpLine[4] = /* "I wasn't able to read the size data for this font," */ 806
- prg.helpLine[3] = /* "so I will ignore the font specification." */ 807
- prg.helpLine[2] = /* "[Wizards can fix TFM files using TFtoPL/PLtoTF.]" */ 808
- prg.helpLine[1] = /* "You might try inserting a different font spec;" */ 809
- prg.helpLine[0] = /* "e.g., type `I\\font<same font id>=<substitute font name>'." */ 810
- }
- prg.error1()
- done:
- if fileOpened {
- prg.bClose(prg.tfmFile)
- }
- r = g
- return r
- }
- // 564.
- // tangle:pos tex.web:10983:1:
- // Note: A malformed \.[TFM] file might be shorter than it claims to be;
- // thus |eof(tfm_file)| might be true when |read_font_info| refers to
- // |tfm_file^| or when it says |get(tfm_file)|. If such circumstances
- // cause system error messages, you will have to defeat them somehow,
- // for example by defining |fget| to be `\ignorespaces|begin get(tfm_file);|
- // |if eof(tfm_file) then abort; end|\unskip'.
- // \xref[system dependencies]
- // 581.
- // tangle:pos tex.web:11293:1:
- // When \TeX\ wants to typeset a character that doesn't exist, the
- // character node is not created; thus the output routine can assume
- // that characters exist when it sees them. The following procedure
- // prints a warning message unless the user has suppressed it.
- func (prg *prg) charWarning(f internalFontNumber, c eightBits) {
- if *prg.eqtb[intBase+tracingLostCharsCode-1].int() > 0 {
- prg.beginDiagnostic()
- prg.printNl(strNumber( /* "Missing character: There is no " */ 825))
- // \xref[Missing character]
- prg.print(int32(c))
- prg.print( /* " in font " */ 826)
- prg.slowPrint(int32(prg.fontName[f]))
- prg.printChar(asciiCode('!'))
- prg.endDiagnostic(false)
- }
- }
- // 582.
- // tangle:pos tex.web:11308:1:
- // Here is a function that returns a pointer to a character node for a
- // given character in a given font. If that character doesn't exist,
- // |null| is returned instead.
- func (prg *prg) newCharacter(f internalFontNumber, c eightBits) (r halfword) {
- var (
- p halfword // newly allocated node
- )
- if int32(prg.fontBc[f]) <= int32(c) {
- if int32(prg.fontEc[f]) >= int32(c) {
- if int32((*prg.fontInfo[prg.charBase[f]+int32(c)+minQuarterword].qqqq()).b0) > minQuarterword {
- p = prg.getAvail()
- *(*prg.mem[p].hh()).b0() = f
- *(*prg.mem[p].hh()).b1() = byte(int32(c) + minQuarterword)
- r = p
- goto exit
- }
- }
- }
- prg.charWarning(f, c)
- r = 0
- exit:
- ;
- return r
- }
- // 583. \[31] Device-independent file format
- // tangle:pos tex.web:11324:39:
- // The most important output produced by a run of \TeX\ is the ``device
- // independent'' (\.[DVI]) file that specifies where characters and rules
- // are to appear on printed pages. The form of these files was designed by
- // David R. Fuchs in 1979. Almost any reasonable typesetting device can be
- // \xref[Fuchs, David Raymond]
- // \xref[DVI_files][\.[DVI] files]
- // driven by a program that takes \.[DVI] files as input, and dozens of such
- // \.[DVI]-to-whatever programs have been written. Thus, it is possible to
- // print the output of \TeX\ on many different kinds of equipment, using \TeX\
- // as a device-independent ``front end.''
- //
- // A \.[DVI] file is a stream of 8-bit bytes, which may be regarded as a
- // series of commands in a machine-like language. The first byte of each command
- // is the operation code, and this code is followed by zero or more bytes
- // that provide parameters to the command. The parameters themselves may consist
- // of several consecutive bytes; for example, the `|set_rule|' command has two
- // parameters, each of which is four bytes long. Parameters are usually
- // regarded as nonnegative integers; but four-byte-long parameters,
- // and shorter parameters that denote distances, can be
- // either positive or negative. Such parameters are given in two's complement
- // notation. For example, a two-byte-long distance parameter has a value between
- // $-2^[15]$ and $2^[15]-1$. As in \.[TFM] files, numbers that occupy
- // more than one byte position appear in BigEndian order.
- //
- // A \.[DVI] file consists of a ``preamble,'' followed by a sequence of one
- // or more ``pages,'' followed by a ``postamble.'' The preamble is simply a
- // |pre| command, with its parameters that define the dimensions used in the
- // file; this must come first. Each ``page'' consists of a |bop| command,
- // followed by any number of other commands that tell where characters are to
- // be placed on a physical page, followed by an |eop| command. The pages
- // appear in the order that \TeX\ generated them. If we ignore |nop| commands
- // and \\[fnt\_def] commands (which are allowed between any two commands in
- // the file), each |eop| command is immediately followed by a |bop| command,
- // or by a |post| command; in the latter case, there are no more pages in the
- // file, and the remaining bytes form the postamble. Further details about
- // the postamble will be explained later.
- //
- // Some parameters in \.[DVI] commands are ``pointers.'' These are four-byte
- // quantities that give the location number of some other byte in the file;
- // the first byte is number~0, then comes number~1, and so on. For example,
- // one of the parameters of a |bop| command points to the previous |bop|;
- // this makes it feasible to read the pages in backwards order, in case the
- // results are being directed to a device that stacks its output face up.
- // Suppose the preamble of a \.[DVI] file occupies bytes 0 to 99. Now if the
- // first page occupies bytes 100 to 999, say, and if the second
- // page occupies bytes 1000 to 1999, then the |bop| that starts in byte 1000
- // points to 100 and the |bop| that starts in byte 2000 points to 1000. (The
- // very first |bop|, i.e., the one starting in byte 100, has a pointer of~$-1$.)
- // 584.
- // tangle:pos tex.web:11374:1:
- // The \.[DVI] format is intended to be both compact and easily interpreted
- // by a machine. Compactness is achieved by making most of the information
- // implicit instead of explicit. When a \.[DVI]-reading program reads the
- // commands for a page, it keeps track of several quantities: (a)~The current
- // font |f| is an integer; this value is changed only
- // by \\[fnt] and \\[fnt\_num] commands. (b)~The current position on the page
- // is given by two numbers called the horizontal and vertical coordinates,
- // |h| and |v|. Both coordinates are zero at the upper left corner of the page;
- // moving to the right corresponds to increasing the horizontal coordinate, and
- // moving down corresponds to increasing the vertical coordinate. Thus, the
- // coordinates are essentially Cartesian, except that vertical directions are
- // flipped; the Cartesian version of |(h,v)| would be |(h,-v)|. (c)~The
- // current spacing amounts are given by four numbers |w|, |x|, |y|, and |z|,
- // where |w| and~|x| are used for horizontal spacing and where |y| and~|z|
- // are used for vertical spacing. (d)~There is a stack containing
- // |(h,v,w,x,y,z)| values; the \.[DVI] commands |push| and |pop| are used to
- // change the current level of operation. Note that the current font~|f| is
- // not pushed and popped; the stack contains only information about
- // positioning.
- //
- // The values of |h|, |v|, |w|, |x|, |y|, and |z| are signed integers having up
- // to 32 bits, including the sign. Since they represent physical distances,
- // there is a small unit of measurement such that increasing |h| by~1 means
- // moving a certain tiny distance to the right. The actual unit of
- // measurement is variable, as explained below; \TeX\ sets things up so that
- // its \.[DVI] output is in sp units, i.e., scaled points, in agreement with
- // all the |scaled| dimensions in \TeX's data structures.
- // 585.
- // tangle:pos tex.web:11402:1:
- // Here is a list of all the commands that may appear in a \.[DVI] file. Each
- // command is specified by its symbolic name (e.g., |bop|), its opcode byte
- // (e.g., 139), and its parameters (if any). The parameters are followed
- // by a bracketed number telling how many bytes they occupy; for example,
- // `|p[4]|' means that parameter |p| is four bytes long.
- //
- // \yskip\hang|set_char_0| 0. Typeset character number~0 from font~|f|
- // such that the reference point of the character is at |(h,v)|. Then
- // increase |h| by the width of that character. Note that a character may
- // have zero or negative width, so one cannot be sure that |h| will advance
- // after this command; but |h| usually does increase.
- //
- // \yskip\hang\\[set\_char\_1] through \\[set\_char\_127] (opcodes 1 to 127).
- // Do the operations of |set_char_0|; but use the character whose number
- // matches the opcode, instead of character~0.
- //
- // \yskip\hang|set1| 128 |c[1]|. Same as |set_char_0|, except that character
- // number~|c| is typeset. \TeX82 uses this command for characters in the
- // range |128<=c<256|.
- //
- // \yskip\hang| set2| 129 |c[2]|. Same as |set1|, except that |c|~is two
- // bytes long, so it is in the range |0<=c<65536|. \TeX82 never uses this
- // command, but it should come in handy for extensions of \TeX\ that deal
- // with oriental languages.
- // \xref[oriental characters]\xref[Chinese characters]\xref[Japanese characters]
- //
- // \yskip\hang| set3| 130 |c[3]|. Same as |set1|, except that |c|~is three
- // bytes long, so it can be as large as $2^[24]-1$. Not even the Chinese
- // language has this many characters, but this command might prove useful
- // in some yet unforeseen extension.
- //
- // \yskip\hang| set4| 131 |c[4]|. Same as |set1|, except that |c|~is four
- // bytes long. Imagine that.
- //
- // \yskip\hang|set_rule| 132 |a[4]| |b[4]|. Typeset a solid black rectangle
- // of height~|a| and width~|b|, with its bottom left corner at |(h,v)|. Then
- // set |h:=h+b|. If either |a<=0| or |b<=0|, nothing should be typeset. Note
- // that if |b<0|, the value of |h| will decrease even though nothing else happens.
- // See below for details about how to typeset rules so that consistency with
- // \MF\ is guaranteed.
- //
- // \yskip\hang| put1| 133 |c[1]|. Typeset character number~|c| from font~|f|
- // such that the reference point of the character is at |(h,v)|. (The `put'
- // commands are exactly like the `set' commands, except that they simply put out a
- // character or a rule without moving the reference point afterwards.)
- //
- // \yskip\hang| put2| 134 |c[2]|. Same as |set2|, except that |h| is not changed.
- //
- // \yskip\hang| put3| 135 |c[3]|. Same as |set3|, except that |h| is not changed.
- //
- // \yskip\hang| put4| 136 |c[4]|. Same as |set4|, except that |h| is not changed.
- //
- // \yskip\hang|put_rule| 137 |a[4]| |b[4]|. Same as |set_rule|, except that
- // |h| is not changed.
- //
- // \yskip\hang|nop| 138. No operation, do nothing. Any number of |nop|'s
- // may occur between \.[DVI] commands, but a |nop| cannot be inserted between
- // a command and its parameters or between two parameters.
- //
- // \yskip\hang|bop| 139 $c_0[4]$ $c_1[4]$ $\ldots$ $c_9[4]$ $p[4]$. Beginning
- // of a page: Set |(h,v,w,x,y,z):=(0,0,0,0,0,0)| and set the stack empty. Set
- // the current font |f| to an undefined value. The ten $c_i$ parameters hold
- // the values of \.[\\count0] $\ldots$ \.[\\count9] in \TeX\ at the time
- // \.[\\shipout] was invoked for this page; they can be used to identify
- // pages, if a user wants to print only part of a \.[DVI] file. The parameter
- // |p| points to the previous |bop| in the file; the first
- // |bop| has $p=-1$.
- //
- // \yskip\hang|eop| 140. End of page: Print what you have read since the
- // previous |bop|. At this point the stack should be empty. (The \.[DVI]-reading
- // programs that drive most output devices will have kept a buffer of the
- // material that appears on the page that has just ended. This material is
- // largely, but not entirely, in order by |v| coordinate and (for fixed |v|) by
- // |h|~coordinate; so it usually needs to be sorted into some order that is
- // appropriate for the device in question.)
- //
- // \yskip\hang|push| 141. Push the current values of |(h,v,w,x,y,z)| onto the
- // top of the stack; do not change any of these values. Note that |f| is
- // not pushed.
- //
- // \yskip\hang|pop| 142. Pop the top six values off of the stack and assign
- // them respectively to |(h,v,w,x,y,z)|. The number of pops should never
- // exceed the number of pushes, since it would be highly embarrassing if the
- // stack were empty at the time of a |pop| command.
- //
- // \yskip\hang|right1| 143 |b[1]|. Set |h:=h+b|, i.e., move right |b| units.
- // The parameter is a signed number in two's complement notation, |-128<=b<128|;
- // if |b<0|, the reference point moves left.
- //
- // \yskip\hang| right2| 144 |b[2]|. Same as |right1|, except that |b| is a
- // two-byte quantity in the range |-32768<=b<32768|.
- //
- // \yskip\hang| right3| 145 |b[3]|. Same as |right1|, except that |b| is a
- // three-byte quantity in the range |$-2^[23]$<=b<$2^[23]$|.
- //
- // \yskip\hang| right4| 146 |b[4]|. Same as |right1|, except that |b| is a
- // four-byte quantity in the range |$-2^[31]$<=b<$2^[31]$|.
- //
- // \yskip\hang|w0| 147. Set |h:=h+w|; i.e., move right |w| units. With luck,
- // this parameterless command will usually suffice, because the same kind of motion
- // will occur several times in succession; the following commands explain how
- // |w| gets particular values.
- //
- // \yskip\hang|w1| 148 |b[1]|. Set |w:=b| and |h:=h+b|. The value of |b| is a
- // signed quantity in two's complement notation, |-128<=b<128|. This command
- // changes the current |w|~spacing and moves right by |b|.
- //
- // \yskip\hang| w2| 149 |b[2]|. Same as |w1|, but |b| is two bytes long,
- // |-32768<=b<32768|.
- //
- // \yskip\hang| w3| 150 |b[3]|. Same as |w1|, but |b| is three bytes long,
- // |$-2^[23]$<=b<$2^[23]$|.
- //
- // \yskip\hang| w4| 151 |b[4]|. Same as |w1|, but |b| is four bytes long,
- // |$-2^[31]$<=b<$2^[31]$|.
- //
- // \yskip\hang|x0| 152. Set |h:=h+x|; i.e., move right |x| units. The `|x|'
- // commands are like the `|w|' commands except that they involve |x| instead
- // of |w|.
- //
- // \yskip\hang|x1| 153 |b[1]|. Set |x:=b| and |h:=h+b|. The value of |b| is a
- // signed quantity in two's complement notation, |-128<=b<128|. This command
- // changes the current |x|~spacing and moves right by |b|.
- //
- // \yskip\hang| x2| 154 |b[2]|. Same as |x1|, but |b| is two bytes long,
- // |-32768<=b<32768|.
- //
- // \yskip\hang| x3| 155 |b[3]|. Same as |x1|, but |b| is three bytes long,
- // |$-2^[23]$<=b<$2^[23]$|.
- //
- // \yskip\hang| x4| 156 |b[4]|. Same as |x1|, but |b| is four bytes long,
- // |$-2^[31]$<=b<$2^[31]$|.
- //
- // \yskip\hang|down1| 157 |a[1]|. Set |v:=v+a|, i.e., move down |a| units.
- // The parameter is a signed number in two's complement notation, |-128<=a<128|;
- // if |a<0|, the reference point moves up.
- //
- // \yskip\hang| down2| 158 |a[2]|. Same as |down1|, except that |a| is a
- // two-byte quantity in the range |-32768<=a<32768|.
- //
- // \yskip\hang| down3| 159 |a[3]|. Same as |down1|, except that |a| is a
- // three-byte quantity in the range |$-2^[23]$<=a<$2^[23]$|.
- //
- // \yskip\hang| down4| 160 |a[4]|. Same as |down1|, except that |a| is a
- // four-byte quantity in the range |$-2^[31]$<=a<$2^[31]$|.
- //
- // \yskip\hang|y0| 161. Set |v:=v+y|; i.e., move down |y| units. With luck,
- // this parameterless command will usually suffice, because the same kind of motion
- // will occur several times in succession; the following commands explain how
- // |y| gets particular values.
- //
- // \yskip\hang|y1| 162 |a[1]|. Set |y:=a| and |v:=v+a|. The value of |a| is a
- // signed quantity in two's complement notation, |-128<=a<128|. This command
- // changes the current |y|~spacing and moves down by |a|.
- //
- // \yskip\hang| y2| 163 |a[2]|. Same as |y1|, but |a| is two bytes long,
- // |-32768<=a<32768|.
- //
- // \yskip\hang| y3| 164 |a[3]|. Same as |y1|, but |a| is three bytes long,
- // |$-2^[23]$<=a<$2^[23]$|.
- //
- // \yskip\hang| y4| 165 |a[4]|. Same as |y1|, but |a| is four bytes long,
- // |$-2^[31]$<=a<$2^[31]$|.
- //
- // \yskip\hang|z0| 166. Set |v:=v+z|; i.e., move down |z| units. The `|z|' commands
- // are like the `|y|' commands except that they involve |z| instead of |y|.
- //
- // \yskip\hang|z1| 167 |a[1]|. Set |z:=a| and |v:=v+a|. The value of |a| is a
- // signed quantity in two's complement notation, |-128<=a<128|. This command
- // changes the current |z|~spacing and moves down by |a|.
- //
- // \yskip\hang| z2| 168 |a[2]|. Same as |z1|, but |a| is two bytes long,
- // |-32768<=a<32768|.
- //
- // \yskip\hang| z3| 169 |a[3]|. Same as |z1|, but |a| is three bytes long,
- // |$-2^[23]$<=a<$2^[23]$|.
- //
- // \yskip\hang| z4| 170 |a[4]|. Same as |z1|, but |a| is four bytes long,
- // |$-2^[31]$<=a<$2^[31]$|.
- //
- // \yskip\hang|fnt_num_0| 171. Set |f:=0|. Font 0 must previously have been
- // defined by a \\[fnt\_def] instruction, as explained below.
- //
- // \yskip\hang\\[fnt\_num\_1] through \\[fnt\_num\_63] (opcodes 172 to 234). Set
- // |f:=1|, \dots, \hbox[|f:=63|], respectively.
- //
- // \yskip\hang|fnt1| 235 |k[1]|. Set |f:=k|. \TeX82 uses this command for font
- // numbers in the range |64<=k<256|.
- //
- // \yskip\hang| fnt2| 236 |k[2]|. Same as |fnt1|, except that |k|~is two
- // bytes long, so it is in the range |0<=k<65536|. \TeX82 never generates this
- // command, but large font numbers may prove useful for specifications of
- // color or texture, or they may be used for special fonts that have fixed
- // numbers in some external coding scheme.
- //
- // \yskip\hang| fnt3| 237 |k[3]|. Same as |fnt1|, except that |k|~is three
- // bytes long, so it can be as large as $2^[24]-1$.
- //
- // \yskip\hang| fnt4| 238 |k[4]|. Same as |fnt1|, except that |k|~is four
- // bytes long; this is for the really big font numbers (and for the negative ones).
- //
- // \yskip\hang|xxx1| 239 |k[1]| |x[k]|. This command is undefined in
- // general; it functions as a $(k+2)$-byte |nop| unless special \.[DVI]-reading
- // programs are being used. \TeX82 generates |xxx1| when a short enough
- // \.[\\special] appears, setting |k| to the number of bytes being sent. It
- // is recommended that |x| be a string having the form of a keyword followed
- // by possible parameters relevant to that keyword.
- //
- // \yskip\hang| xxx2| 240 |k[2]| |x[k]|. Like |xxx1|, but |0<=k<65536|.
- //
- // \yskip\hang| xxx3| 241 |k[3]| |x[k]|. Like |xxx1|, but |0<=k<$2^[24]$|.
- //
- // \yskip\hang|xxx4| 242 |k[4]| |x[k]|. Like |xxx1|, but |k| can be ridiculously
- // large. \TeX82 uses |xxx4| when sending a string of length 256 or more.
- //
- // \yskip\hang|fnt_def1| 243 |k[1]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
- // Define font |k|, where |0<=k<256|; font definitions will be explained shortly.
- //
- // \yskip\hang| fnt_def2| 244 |k[2]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
- // Define font |k|, where |0<=k<65536|.
- //
- // \yskip\hang| fnt_def3| 245 |k[3]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
- // Define font |k|, where |0<=k<$2^[24]$|.
- //
- // \yskip\hang| fnt_def4| 246 |k[4]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
- // Define font |k|, where |$-2^[31]$<=k<$2^[31]$|.
- //
- // \yskip\hang|pre| 247 |i[1]| |num[4]| |den[4]| |mag[4]| |k[1]| |x[k]|.
- // Beginning of the preamble; this must come at the very beginning of the
- // file. Parameters |i|, |num|, |den|, |mag|, |k|, and |x| are explained below.
- //
- // \yskip\hang|post| 248. Beginning of the postamble, see below.
- //
- // \yskip\hang|post_post| 249. Ending of the postamble, see below.
- //
- // \yskip\noindent Commands 250--255 are undefined at the present time.
- // 586.
- // 587.
- // tangle:pos tex.web:11667:1:
- // The preamble contains basic information about the file as a whole. As
- // stated above, there are six parameters:
- // $$\hbox[| i[1]| | num[4]| | den[4]| | mag[4]| | k[1]| | x[k]|.]$$
- // The |i| byte identifies \.[DVI] format; currently this byte is always set
- // to~2. (The value |i=3| is currently used for an extended format that
- // allows a mixture of right-to-left and left-to-right typesetting.
- // Some day we will set |i=4|, when \.[DVI] format makes another
- // incompatible change---perhaps in the year 2048.)
- //
- // The next two parameters, |num| and |den|, are positive integers that define
- // the units of measurement; they are the numerator and denominator of a
- // fraction by which all dimensions in the \.[DVI] file could be multiplied
- // in order to get lengths in units of $10^[-7]$ meters. Since $\rm 7227[pt] =
- // 254[cm]$, and since \TeX\ works with scaled points where there are $2^[16]$
- // sp in a point, \TeX\ sets
- // $|num|/|den|=(254\cdot10^5)/(7227\cdot2^[16])=25400000/473628672$.
- // \xref[sp]
- //
- // The |mag| parameter is what \TeX\ calls \.[\\mag], i.e., 1000 times the
- // desired magnification. The actual fraction by which dimensions are
- // multiplied is therefore $|mag|\cdot|num|/1000|den|$. Note that if a \TeX\
- // source document does not call for any `\.[true]' dimensions, and if you
- // change it only by specifying a different \.[\\mag] setting, the \.[DVI]
- // file that \TeX\ creates will be completely unchanged except for the value
- // of |mag| in the preamble and postamble. (Fancy \.[DVI]-reading programs allow
- // users to override the |mag|~setting when a \.[DVI] file is being printed.)
- //
- // Finally, |k| and |x| allow the \.[DVI] writer to include a comment, which is not
- // interpreted further. The length of comment |x| is |k|, where |0<=k<256|.
- // 588.
- // tangle:pos tex.web:11699:1:
- // Font definitions for a given font number |k| contain further parameters
- // $$\hbox[|c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.]$$
- // The four-byte value |c| is the check sum that \TeX\ found in the \.[TFM]
- // file for this font; |c| should match the check sum of the font found by
- // programs that read this \.[DVI] file.
- // \xref[check sum]
- //
- // Parameter |s| contains a fixed-point scale factor that is applied to
- // the character widths in font |k|; font dimensions in \.[TFM] files and
- // other font files are relative to this quantity, which is called the
- // ``at size'' elsewhere in this documentation. The value of |s| is
- // always positive and less than $2^[27]$. It is given in the same units
- // as the other \.[DVI] dimensions, i.e., in sp when \TeX82 has made the
- // file. Parameter |d| is similar to |s|; it is the ``design size,'' and
- // (like~|s|) it is given in \.[DVI] units. Thus, font |k| is to be used
- // at $|mag|\cdot s/1000d$ times its normal size.
- //
- // The remaining part of a font definition gives the external name of the font,
- // which is an ASCII string of length |a+l|. The number |a| is the length
- // of the ``area'' or directory, and |l| is the length of the font name itself;
- // the standard local system font area is supposed to be used when |a=0|.
- // The |n| field contains the area in its first |a| bytes.
- //
- // Font definitions must appear before the first use of a particular font number.
- // Once font |k| is defined, it must not be defined again; however, we
- // shall see below that font definitions appear in the postamble as well as
- // in the pages, so in this sense each font number is defined exactly twice,
- // if at all. Like |nop| commands, font definitions can
- // appear before the first |bop|, or between an |eop| and a |bop|.
- // 589.
- // tangle:pos tex.web:11729:1:
- // Sometimes it is desirable to make horizontal or vertical rules line up
- // precisely with certain features in characters of a font. It is possible to
- // guarantee the correct matching between \.[DVI] output and the characters
- // generated by \MF\ by adhering to the following principles: (1)~The \MF\
- // characters should be positioned so that a bottom edge or left edge that is
- // supposed to line up with the bottom or left edge of a rule appears at the
- // reference point, i.e., in row~0 and column~0 of the \MF\ raster. This
- // ensures that the position of the rule will not be rounded differently when
- // the pixel size is not a perfect multiple of the units of measurement in
- // the \.[DVI] file. (2)~A typeset rule of height $a>0$ and width $b>0$
- // should be equivalent to a \MF-generated character having black pixels in
- // precisely those raster positions whose \MF\ coordinates satisfy
- // |0<=x<$\alpha$b| and |0<=y<$\alpha$a|, where $\alpha$ is the number
- // of pixels per \.[DVI] unit.
- // \xref[METAFONT][\MF]
- // \xref[alignment of rules with characters]
- // \xref[rules aligning with characters]
- // 590.
- // tangle:pos tex.web:11747:1:
- // The last page in a \.[DVI] file is followed by `|post|'; this command
- // introduces the postamble, which summarizes important facts that \TeX\ has
- // accumulated about the file, making it possible to print subsets of the data
- // with reasonable efficiency. The postamble has the form
- // $$\vbox[\halign[\hbox[#\hfil]\cr
- // |post| |p[4]| |num[4]| |den[4]| |mag[4]| |l[4]| |u[4]| |s[2]| |t[2]|\cr
- // $\langle\,$font definitions$\,\rangle$\cr
- // |post_post| |q[4]| |i[1]| 223's$[[\G]4]$\cr]]$$
- // Here |p| is a pointer to the final |bop| in the file. The next three
- // parameters, |num|, |den|, and |mag|, are duplicates of the quantities that
- // appeared in the preamble.
- //
- // Parameters |l| and |u| give respectively the height-plus-depth of the tallest
- // page and the width of the widest page, in the same units as other dimensions
- // of the file. These numbers might be used by a \.[DVI]-reading program to
- // position individual ``pages'' on large sheets of film or paper; however,
- // the standard convention for output on normal size paper is to position each
- // page so that the upper left-hand corner is exactly one inch from the left
- // and the top. Experience has shown that it is unwise to design \.[DVI]-to-printer
- // software that attempts cleverly to center the output; a fixed position of
- // the upper left corner is easiest for users to understand and to work with.
- // Therefore |l| and~|u| are often ignored.
- //
- // Parameter |s| is the maximum stack depth (i.e., the largest excess of
- // |push| commands over |pop| commands) needed to process this file. Then
- // comes |t|, the total number of pages (|bop| commands) present.
- //
- // The postamble continues with font definitions, which are any number of
- // \\[fnt\_def] commands as described above, possibly interspersed with |nop|
- // commands. Each font number that is used in the \.[DVI] file must be defined
- // exactly twice: Once before it is first selected by a \\[fnt] command, and once
- // in the postamble.
- // 591.
- // tangle:pos tex.web:11780:1:
- // The last part of the postamble, following the |post_post| byte that
- // signifies the end of the font definitions, contains |q|, a pointer to the
- // |post| command that started the postamble. An identification byte, |i|,
- // comes next; this currently equals~2, as in the preamble.
- //
- // The |i| byte is followed by four or more bytes that are all equal to
- // the decimal number 223 (i.e., @'337 in octal). \TeX\ puts out four to seven of
- // these trailing bytes, until the total length of the file is a multiple of
- // four bytes, since this works out best on machines that pack four bytes per
- // word; but any number of 223's is allowed, as long as there are at least four
- // of them. In effect, 223 is a sort of signature that is added at the very end.
- // \xref[Fuchs, David Raymond]
- //
- // This curious way to finish off a \.[DVI] file makes it feasible for
- // \.[DVI]-reading programs to find the postamble first, on most computers,
- // even though \TeX\ wants to write the postamble last. Most operating
- // systems permit random access to individual words or bytes of a file, so
- // the \.[DVI] reader can start at the end and skip backwards over the 223's
- // until finding the identification byte. Then it can back up four bytes, read
- // |q|, and move to byte |q| of the file. This byte should, of course,
- // contain the value 248 (|post|); now the postamble can be read, so the
- // \.[DVI] reader can discover all the information needed for typesetting the
- // pages. Note that it is also possible to skip through the \.[DVI] file at
- // reasonably high speed to locate a particular page, if that proves
- // desirable. This saves a lot of time, since \.[DVI] files used in production
- // jobs tend to be large.
- //
- // Unfortunately, however, standard \PASCAL\ does not include the ability to
- // \xref[system dependencies]
- // access a random position in a file, or even to determine the length of a file.
- // Almost all systems nowadays provide the necessary capabilities, so \.[DVI]
- // format has been designed to work most efficiently with modern operating systems.
- // But if \.[DVI] files have to be processed under the restrictions of standard
- // \PASCAL, one can simply read them from front to back, since the necessary
- // header information is present in the preamble and in the font definitions.
- // (The |l| and |u| and |s| and |t| parameters, which appear only in the
- // postamble, are ``frills'' that are handy but not absolutely necessary.)
- // 597.
- // tangle:pos tex.web:11911:1:
- // The actual output of |dvi_buf[a..b]| to |dvi_file| is performed by calling
- // |write_dvi(a,b)|. For best results, this procedure should be optimized to
- // run as fast as possible on each particular system, since it is part of
- // \TeX's inner loop. It is safe to assume that |a| and |b+1| will both be
- // multiples of 4 when |write_dvi(a,b)| is called; therefore it is possible on
- // many machines to use efficient methods to pack four bytes per word and to
- // output an array of words with one system call.
- // \xref[system dependencies]
- // \xref[inner loop]
- // \xref[defecation]
- func (prg *prg) writeDvi(a, b dviIndex) {
- var (
- k dviIndex
- )
- for ii := int32(a); ii <= int32(b); ii++ {
- k = dviIndex(ii)
- _ = k
- prg.dviFile.Write(prg.dviBuf[k])
- }
- }
- // 598.
- // tangle:pos tex.web:11927:1:
- // To put a byte in the buffer without paying the cost of invoking a procedure
- // each time, we use the macro |dvi_out|.
- func (prg *prg) dviSwap() {
- if int32(prg.dviLimit) == dviBufSize {
- prg.writeDvi(dviIndex(0), dviIndex(int32(prg.halfBuf)-1))
- prg.dviLimit = prg.halfBuf
- prg.dviOffset = prg.dviOffset + dviBufSize
- prg.dviPtr = 0
- } else {
- prg.writeDvi(prg.halfBuf, dviIndex(dviBufSize-1))
- prg.dviLimit = uint16(dviBufSize)
- }
- prg.dviGone = prg.dviGone + int32(prg.halfBuf)
- }
- // 600.
- // tangle:pos tex.web:11951:1:
- // The |dvi_four| procedure outputs four bytes in two's complement notation,
- // without risking arithmetic overflow.
- func (prg *prg) dviFour(x int32) {
- if x >= 0 {
- prg.dviBuf[prg.dviPtr] = byte(x / 0100000000)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } else {
- x = x + 010000000000
- x = x + 010000000000
- {
- prg.dviBuf[prg.dviPtr] = byte(x/0100000000 + 128)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- }
- x = x % 0100000000
- {
- prg.dviBuf[prg.dviPtr] = byte(x / 0200000)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- x = x % 0200000
- {
- prg.dviBuf[prg.dviPtr] = byte(x / 0400)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(x % 0400)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- }
- // 601.
- // tangle:pos tex.web:11965:1:
- // A mild optimization of the output is performed by the |dvi_pop|
- // routine, which issues a |pop| unless it is possible to cancel a
- // `|push| |pop|' pair. The parameter to |dvi_pop| is the byte address
- // following the old |push| that matches the new |pop|.
- func (prg *prg) dviPop(l int32) {
- if l == prg.dviOffset+int32(prg.dviPtr) && int32(prg.dviPtr) > 0 {
- prg.dviPtr = uint16(int32(prg.dviPtr) - 1)
- } else {
- prg.dviBuf[prg.dviPtr] = byte(pop)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- }
- // 602.
- // tangle:pos tex.web:11975:1:
- // Here's a procedure that outputs a font definition. Since \TeX82 uses at
- // most 256 different fonts per job, |fnt_def1| is always used as the command code.
- func (prg *prg) dviFontDef(f internalFontNumber) {
- var (
- k poolPointer // index into |str_pool|
- )
- {
- prg.dviBuf[prg.dviPtr] = byte(fntDef1)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(f) - fontBase - 1)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.fontCheck[f].b0) - minQuarterword)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.fontCheck[f].b1) - minQuarterword)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.fontCheck[f].b2) - minQuarterword)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.fontCheck[f].b3) - minQuarterword)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.dviFour(prg.fontSize[f])
- prg.dviFour(prg.fontDsize[f])
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.strStart[int32(prg.fontArea[f])+1]) - int32(prg.strStart[prg.fontArea[f]]))
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.strStart[int32(prg.fontName[f])+1]) - int32(prg.strStart[prg.fontName[f]]))
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- // Output the font name whose internal number is |f|
- for ii := int32(prg.strStart[prg.fontArea[f]]); ii <= int32(prg.strStart[int32(prg.fontArea[f])+1])-1; ii++ {
- k = poolPointer(ii)
- _ = k
- prg.dviBuf[prg.dviPtr] = prg.strPool[k]
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- for ii := int32(prg.strStart[prg.fontName[f]]); ii <= int32(prg.strStart[int32(prg.fontName[f])+1])-1; ii++ {
- k = poolPointer(ii)
- _ = k
- prg.dviBuf[prg.dviPtr] = prg.strPool[k]
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- }
- // 604.
- // tangle:pos tex.web:11999:1:
- // Versions of \TeX\ intended for small computers might well choose to omit
- // the ideas in the next few parts of this program, since it is not really
- // necessary to optimize the \.[DVI] code by making use of the |w0|, |x0|,
- // |y0|, and |z0| commands. Furthermore, the algorithm that we are about to
- // describe does not pretend to give an optimum reduction in the length
- // of the \.[DVI] code; after all, speed is more important than compactness.
- // But the method is surprisingly effective, and it takes comparatively little
- // time.
- //
- // We can best understand the basic idea by first considering a simpler problem
- // that has the same essential characteristics. Given a sequence of digits,
- // say $3\,1\,4\,1\,5\,9\,2\,6\,5\,3\,5\,8\,9$, we want to assign subscripts
- // $d$, $y$, or $z$ to each digit so as to maximize the number of ``$y$-hits''
- // and ``$z$-hits''; a $y$-hit is an instance of two appearances of the same
- // digit with the subscript $y$, where no $y$'s intervene between the two
- // appearances, and a $z$-hit is defined similarly. For example, the sequence
- // above could be decorated with subscripts as follows:
- // $$3_z\,1_y\,4_d\,1_y\,5_y\,9_d\,2_d\,6_d\,5_y\,3_z\,5_y\,8_d\,9_d.$$
- // There are three $y$-hits ($1_y\ldots1_y$ and $5_y\ldots5_y\ldots5_y$) and
- // one $z$-hit ($3_z\ldots3_z$); there are no $d$-hits, since the two appearances
- // of $9_d$ have $d$'s between them, but we don't count $d$-hits so it doesn't
- // matter how many there are. These subscripts are analogous to the \.[DVI]
- // commands called \\[down], $y$, and $z$, and the digits are analogous to
- // different amounts of vertical motion; a $y$-hit or $z$-hit corresponds to
- // the opportunity to use the one-byte commands |y0| or |z0| in a \.[DVI] file.
- //
- // \TeX's method of assigning subscripts works like this: Append a new digit,
- // say $\delta$, to the right of the sequence. Now look back through the
- // sequence until one of the following things happens: (a)~You see
- // $\delta_y$ or $\delta_z$, and this was the first time you encountered a
- // $y$ or $z$ subscript, respectively. Then assign $y$ or $z$ to the new
- // $\delta$; you have scored a hit. (b)~You see $\delta_d$, and no $y$
- // subscripts have been encountered so far during this search. Then change
- // the previous $\delta_d$ to $\delta_y$ (this corresponds to changing a
- // command in the output buffer), and assign $y$ to the new $\delta$; it's
- // another hit. (c)~You see $\delta_d$, and a $y$ subscript has been seen
- // but not a $z$. Change the previous $\delta_d$ to $\delta_z$ and assign
- // $z$ to the new $\delta$. (d)~You encounter both $y$ and $z$ subscripts
- // before encountering a suitable $\delta$, or you scan all the way to the
- // front of the sequence. Assign $d$ to the new $\delta$; this assignment may
- // be changed later.
- //
- // The subscripts $3_z\,1_y\,4_d\ldots\,$ in the example above were, in fact,
- // produced by this procedure, as the reader can verify. (Go ahead and try it.)
- // 607.
- // tangle:pos tex.web:12066:1:
- // Here is a subroutine that produces a \.[DVI] command for some specified
- // downward or rightward motion. It has two parameters: |w| is the amount
- // of motion, and |o| is either |down1| or |right1|. We use the fact that
- // the command codes have convenient arithmetic properties: |y1-down1=w1-right1|
- // and |z1-down1=x1-right1|.
- func (prg *prg) movement(w scaled, o eightBits) {
- var (
- mstate smallNumber // have we seen a |y| or |z|?
- p, q halfword // current and top nodes on the stack
- k int32 // index into |dvi_buf|, modulo |dvi_buf_size|
- )
- q = prg.getNode(movementNodeSize) // new node for the top of the stack
- *prg.mem[int32(q)+widthOffset].int() = w
- *prg.mem[int32(q)+2].int() = prg.dviOffset + int32(prg.dviPtr)
- if int32(o) == down1 {
- *(*prg.mem[q].hh()).rh() = prg.downPtr
- prg.downPtr = q
- } else {
- *(*prg.mem[q].hh()).rh() = prg.rightPtr
- prg.rightPtr = q
- }
- // Look at the other stack entries until deciding what sort of \.[DVI] command to generate; |goto found| if node |p| is a “hit”
- p = *(*prg.mem[q].hh()).rh()
- mstate = byte(noneSeen)
- for int32(p) != 0 {
- if *prg.mem[int32(p)+widthOffset].int() == w {
- switch int32(mstate) + int32(*(*prg.mem[p].hh()).lh()) {
- case noneSeen + 3, noneSeen + 4, zSeen + 3, zSeen + 4: //
- if *prg.mem[int32(p)+2].int() < prg.dviGone {
- goto notFound
- } else {
- // Change buffered instruction to |y| or |w| and |goto found|
- k = *prg.mem[int32(p)+2].int() - prg.dviOffset
- if k < 0 {
- k = k + dviBufSize
- }
- prg.dviBuf[k] = byte(int32(prg.dviBuf[k]) + y1 - down1)
- *(*prg.mem[p].hh()).lh() = uint16(yHere)
- goto found
- }
- case noneSeen + 5, ySeen + 3, ySeen + 5: //
- if *prg.mem[int32(p)+2].int() < prg.dviGone {
- goto notFound
- } else {
- // Change buffered instruction to |z| or |x| and |goto found|
- k = *prg.mem[int32(p)+2].int() - prg.dviOffset
- if k < 0 {
- k = k + dviBufSize
- }
- prg.dviBuf[k] = byte(int32(prg.dviBuf[k]) + z1 - down1)
- *(*prg.mem[p].hh()).lh() = uint16(zHere)
- goto found
- }
- case noneSeen + 1, noneSeen + 2, ySeen + 2, zSeen + 1:
- goto found
- default:
- }
- } else {
- switch int32(mstate) + int32(*(*prg.mem[p].hh()).lh()) {
- case noneSeen + 1:
- mstate = byte(ySeen)
- case noneSeen + 2:
- mstate = byte(zSeen)
- case ySeen + 2, zSeen + 1:
- goto notFound
- default:
- }
- }
- p = *(*prg.mem[p].hh()).rh()
- }
- notFound:
- ;
- // Generate a |down| or |right| command for |w| and |return|
- *(*prg.mem[q].hh()).lh() = uint16(yzOk)
- if abs(w) >= 040000000 {
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(o) + 3)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } // |down4| or |right4|
- prg.dviFour(w)
- goto exit
- }
- if abs(w) >= 0100000 {
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(o) + 2)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } // |down3| or |right3|
- if w < 0 {
- w = w + 0100000000
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(w / 0200000)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- w = w % 0200000
- goto _2
- }
- if abs(w) >= 0200 {
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(o) + 1)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } // |down2| or |right2|
- if w < 0 {
- w = w + 0200000
- }
- goto _2
- }
- {
- prg.dviBuf[prg.dviPtr] = o
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } // |down1| or |right1|
- if w < 0 {
- w = w + 0400
- }
- goto _1
- _2:
- {
- prg.dviBuf[prg.dviPtr] = byte(w / 0400)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- _1:
- {
- prg.dviBuf[prg.dviPtr] = byte(w % 0400)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- goto exit
- found:
- *(*prg.mem[q].hh()).lh() = *(*prg.mem[p].hh()).lh()
- if int32(*(*prg.mem[q].hh()).lh()) == yHere {
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(o) + y0 - down1)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } // |y0| or |w0|
- for int32(*(*prg.mem[q].hh()).rh()) != int32(p) {
- q = *(*prg.mem[q].hh()).rh()
- switch *(*prg.mem[q].hh()).lh() {
- case yzOk:
- *(*prg.mem[q].hh()).lh() = uint16(zOk)
- case yOk:
- *(*prg.mem[q].hh()).lh() = uint16(dFixed)
- default:
- }
- }
- } else {
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(o) + z0 - down1)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } // |z0| or |x0|
- for int32(*(*prg.mem[q].hh()).rh()) != int32(p) {
- q = *(*prg.mem[q].hh()).rh()
- switch *(*prg.mem[q].hh()).lh() {
- case yzOk:
- *(*prg.mem[q].hh()).lh() = uint16(yOk)
- case zOk:
- *(*prg.mem[q].hh()).lh() = uint16(dFixed)
- default:
- }
- }
- }
- exit:
- }
- // 608.
- // tangle:pos tex.web:12091:1:
- // The |info| fields in the entries of the down stack or the right stack
- // have six possible settings: |y_here| or |z_here| mean that the \.[DVI]
- // command refers to |y| or |z|, respectively (or to |w| or |x|, in the
- // case of horizontal motion); |yz_OK| means that the \.[DVI] command is
- // \\[down] (or \\[right]) but can be changed to either |y| or |z| (or
- // to either |w| or |x|); |y_OK| means that it is \\[down] and can be changed
- // to |y| but not |z|; |z_OK| is similar; and |d_fixed| means it must stay
- // \\[down].
- //
- // The four settings |yz_OK|, |y_OK|, |z_OK|, |d_fixed| would not need to
- // be distinguished from each other if we were simply solving the
- // digit-subscripting problem mentioned above. But in \TeX's case there is
- // a complication because of the nested structure of |push| and |pop|
- // commands. Suppose we add parentheses to the digit-subscripting problem,
- // redefining hits so that $\delta_y\ldots \delta_y$ is a hit if all $y$'s between
- // the $\delta$'s are enclosed in properly nested parentheses, and if the
- // parenthesis level of the right-hand $\delta_y$ is deeper than or equal to
- // that of the left-hand one. Thus, `(' and `)' correspond to `|push|'
- // and `|pop|'. Now if we want to assign a subscript to the final 1 in the
- // sequence
- // $$2_y\,7_d\,1_d\,(\,8_z\,2_y\,8_z\,)\,1$$
- // we cannot change the previous $1_d$ to $1_y$, since that would invalidate
- // the $2_y\ldots2_y$ hit. But we can change it to $1_z$, scoring a hit
- // since the intervening $8_z$'s are enclosed in parentheses.
- //
- // The program below removes movement nodes that are introduced after a |push|,
- // before it outputs the corresponding |pop|.
- // 615.
- // tangle:pos tex.web:12233:1:
- // In case you are wondering when all the movement nodes are removed from
- // \TeX's memory, the answer is that they are recycled just before
- // |hlist_out| and |vlist_out| finish outputting a box. This restores the
- // down and right stacks to the state they were in before the box was output,
- // except that some |info|'s may have become more restrictive.
- func (prg *prg) pruneMovements(l int32) {
- var (
- p halfword // node being deleted
- )
- for int32(prg.downPtr) != 0 {
- if *prg.mem[int32(prg.downPtr)+2].int() < l {
- goto done
- }
- p = prg.downPtr
- prg.downPtr = *(*prg.mem[p].hh()).rh()
- prg.freeNode(p, halfword(movementNodeSize))
- }
- done:
- for int32(prg.rightPtr) != 0 {
- if *prg.mem[int32(prg.rightPtr)+2].int() < l {
- goto exit
- }
- p = prg.rightPtr
- prg.rightPtr = *(*prg.mem[p].hh()).rh()
- prg.freeNode(p, halfword(movementNodeSize))
- }
- exit:
- } // |hlist_out| and |vlist_out| are mutually
- // recursive
- // 619.
- // tangle:pos tex.web:12319:1:
- // The recursive procedures |hlist_out| and |vlist_out| each have local variables
- // |save_h| and |save_v| to hold the values of |dvi_h| and |dvi_v| just before
- // entering a new level of recursion. In effect, the values of |save_h| and
- // |save_v| on \TeX's run-time stack correspond to the values of |h| and |v|
- // that a \.[DVI]-reading program will push onto its coordinate stack.
- // \4
- // Declare procedures needed in |hlist_out|, |vlist_out|
- func (prg *prg) specialOut(p halfword) {
- var (
- oldSetting/* 0..maxSelector */ byte // holds print |selector|
- k poolPointer // index into |str_pool|
- )
- if prg.curH != prg.dviH {
- prg.movement(prg.curH-prg.dviH, eightBits(right1))
- prg.dviH = prg.curH
- }
- if prg.curV != prg.dviV {
- prg.movement(prg.curV-prg.dviV, eightBits(down1))
- prg.dviV = prg.curV
- }
- oldSetting = prg.selector
- prg.selector = byte(newString)
- prg.showTokenList(int32(*(*prg.mem[*(*prg.mem[int32(p)+1].hh()).rh()].hh()).rh()), 0, poolSize-int32(prg.poolPtr))
- prg.selector = oldSetting
- {
- if int32(prg.poolPtr)+1 > poolSize {
- prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
- } /* \xref[TeX capacity exceeded pool size][\quad pool size] */
- }
- if int32(prg.poolPtr)-int32(prg.strStart[prg.strPtr]) < 256 {
- {
- prg.dviBuf[prg.dviPtr] = byte(xxx1)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- } else {
- {
- prg.dviBuf[prg.dviPtr] = byte(xxx4)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.dviFour(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
- }
- for ii := int32(prg.strStart[prg.strPtr]); ii <= int32(prg.poolPtr)-1; ii++ {
- k = poolPointer(ii)
- _ = k
- prg.dviBuf[prg.dviPtr] = prg.strPool[k]
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.poolPtr = prg.strStart[prg.strPtr] // erase the string
- }
- func (prg *prg) writeOut(p halfword) {
- var (
- oldSetting/* 0..maxSelector */ byte // holds print |selector|
- oldMode int32 // saved |mode|
- j smallNumber // write stream number
- q, r1 halfword // temporary variables for list manipulation
- )
- q = prg.getAvail()
- *(*prg.mem[q].hh()).lh() = uint16(rightBraceToken + '}')
- r1 = prg.getAvail()
- *(*prg.mem[q].hh()).rh() = r1
- *(*prg.mem[r1].hh()).lh() = uint16(07777 + endWrite)
- prg.beginTokenList(q, quarterword(inserted))
- prg.beginTokenList(*(*prg.mem[int32(p)+1].hh()).rh(), quarterword(writeText))
- q = prg.getAvail()
- *(*prg.mem[q].hh()).lh() = uint16(leftBraceToken + '{')
- prg.beginTokenList(q, quarterword(inserted))
- // now we're ready to scan
- // `\.\[$\langle\,$token list$\,\rangle$\.[\] \\endwrite]'
- oldMode = int32(prg.curList.modeField)
- prg.curList.modeField = 0
- // disable \.[\\prevdepth], \.[\\spacefactor], \.[\\lastskip], \.[\\prevgraf]
- prg.curCs = prg.writeLoc
- q = prg.scanToks(false, true) // expand macros, etc.
- prg.getToken()
- if int32(prg.curTok) != 07777+endWrite {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Unbalanced write command" */ 1297)
- }
- // \xref[Unbalanced write...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "On this page there's a \\write with fewer real ['s than ]'s." */ 1298
- prg.helpLine[0] = /* "I can't handle that very well; good luck." */ 1012
- }
- prg.error1()
- for {
- prg.getToken()
- if int32(prg.curTok) == 07777+endWrite {
- break
- }
- }
- }
- prg.curList.modeField = int16(oldMode)
- prg.endTokenList()
- oldSetting = prg.selector
- j = byte(*(*prg.mem[int32(p)+1].hh()).lh())
- if prg.writeOpen[j] {
- prg.selector = j
- } else {
- if int32(j) == 17 && int32(prg.selector) == termAndLog {
- prg.selector = byte(logOnly)
- }
- prg.printNl(strNumber( /* "" */ 338))
- }
- prg.tokenShow(prg.defRef)
- prg.printLn()
- prg.flushList(prg.defRef)
- prg.selector = oldSetting
- }
- func (prg *prg) outWhat(p halfword) {
- var (
- j smallNumber // write stream number
- )
- switch *(*prg.mem[p].hh()).b1() {
- case openNode, writeNode, closeNode:
- // Do some work that has been queued up for \.[\\write]
- if !prg.doingLeaders {
- j = byte(*(*prg.mem[int32(p)+1].hh()).lh())
- if int32(*(*prg.mem[p].hh()).b1()) == writeNode {
- prg.writeOut(p)
- } else {
- if prg.writeOpen[j] {
- prg.aClose(prg.writeFile[j])
- }
- if int32(*(*prg.mem[p].hh()).b1()) == closeNode {
- prg.writeOpen[j] = false
- } else if int32(j) < 16 {
- prg.curName = *(*prg.mem[int32(p)+1].hh()).rh()
- prg.curArea = *(*prg.mem[int32(p)+2].hh()).lh()
- prg.curExt = *(*prg.mem[int32(p)+2].hh()).rh()
- if int32(prg.curExt) == 338 {
- prg.curExt = /* ".tex" */ 791
- }
- prg.packFileName(prg.curName, prg.curArea, prg.curExt)
- for !prg.aOpenOut(prg.writeFile[j]) {
- prg.promptFileName(strNumber( /* "output file name" */ 1300), strNumber( /* ".tex" */ 791))
- }
- prg.writeOpen[j] = true
- }
- }
- }
- case specialNode:
- prg.specialOut(p)
- case languageNode:
- default:
- prg.confusion(strNumber( /* "ext4" */ 1299))
- // \xref[this can't happen ext4][\quad ext4]
- }
- }
- //
- func (prg *prg) hlistOut() {
- var (
- baseLine scaled // the baseline coordinate for this box
- leftEdge scaled // the left coordinate for this box
- saveH, saveV scaled // what |dvi_h| and |dvi_v| should pop to
- thisBox halfword // pointer to containing box
- gOrder glueOrd // applicable order of infinity for glue
- gSign/* normal..shrinking */ byte // selects type of glue
- p halfword // current position in the hlist
- saveLoc int32 // \.[DVI] byte location upon entry
- leaderBox halfword // the leader box being replicated
- leaderWd scaled // width of leader box being replicated
- lx scaled // extra space between leader boxes
- outerDoingLeaders bool // were we doing leaders?
- edge scaled // left edge of sub-box, or right edge of leader space
- glueTemp float64 // glue value before rounding
- curGlue float64 // glue seen so far
- curG scaled // rounded equivalent of |cur_glue| times the glue ratio
- )
- curG = 0
- curGlue = 0.0
- thisBox = prg.tempPtr
- gOrder = *(*prg.mem[int32(thisBox)+listOffset].hh()).b1()
- gSign = *(*prg.mem[int32(thisBox)+listOffset].hh()).b0()
- p = *(*prg.mem[int32(thisBox)+listOffset].hh()).rh()
- prg.curS = prg.curS + 1
- if prg.curS > 0 {
- prg.dviBuf[prg.dviPtr] = byte(push)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- if prg.curS > prg.maxPush {
- prg.maxPush = prg.curS
- }
- saveLoc = prg.dviOffset + int32(prg.dviPtr)
- baseLine = prg.curV
- leftEdge = prg.curH
- for int32(p) != 0 {
- // Output node |p| for |hlist_out| and move to the next node, maintaining the condition |cur_v=base_line|
- // Output node |p| for |hlist_out| and move to the next node, maintaining the condition |cur_v=base_line|
- reswitch:
- if int32(p) >= int32(prg.hiMemMin) {
- if prg.curH != prg.dviH {
- prg.movement(prg.curH-prg.dviH, eightBits(right1))
- prg.dviH = prg.curH
- }
- if prg.curV != prg.dviV {
- prg.movement(prg.curV-prg.dviV, eightBits(down1))
- prg.dviV = prg.curV
- }
- for {
- prg.f = *(*prg.mem[p].hh()).b0()
- prg.c = *(*prg.mem[p].hh()).b1()
- if int32(prg.f) != int32(prg.dviF) {
- if !prg.fontUsed[prg.f] {
- prg.dviFontDef(prg.f)
- prg.fontUsed[prg.f] = true
- }
- if int32(prg.f) <= 64+fontBase {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.f) - fontBase - 1 + fntNum0)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } else {
- {
- prg.dviBuf[prg.dviPtr] = byte(fnt1)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.f) - fontBase - 1)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- }
- prg.dviF = prg.f
- }
- if int32(prg.c) >= 128+minQuarterword {
- prg.dviBuf[prg.dviPtr] = byte(set1)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.c) - minQuarterword)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.curH = prg.curH + *prg.fontInfo[prg.widthBase[prg.f]+int32((*prg.fontInfo[prg.charBase[prg.f]+int32(prg.c)].qqqq()).b0)].int()
- p = *(*prg.mem[p].hh()).rh()
- if !(int32(p) >= int32(prg.hiMemMin)) {
- break
- }
- }
- prg.dviH = prg.curH
- } else {
- // Output the non-|char_node| |p| for |hlist_out| and move to the next node
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode:
- // Output a box in an hlist
- if int32(*(*prg.mem[int32(p)+listOffset].hh()).rh()) == 0 {
- prg.curH = prg.curH + *prg.mem[int32(p)+widthOffset].int()
- } else {
- saveH = prg.dviH
- saveV = prg.dviV
- prg.curV = baseLine + *prg.mem[int32(p)+4].int() // shift the box down
- prg.tempPtr = p
- edge = prg.curH
- if int32(*(*prg.mem[p].hh()).b0()) == vlistNode {
- prg.vlistOut()
- } else {
- prg.hlistOut()
- }
- prg.dviH = saveH
- prg.dviV = saveV
- prg.curH = edge + *prg.mem[int32(p)+widthOffset].int()
- prg.curV = baseLine
- }
- case ruleNode:
- prg.ruleHt = *prg.mem[int32(p)+heightOffset].int()
- prg.ruleDp = *prg.mem[int32(p)+depthOffset].int()
- prg.ruleWd = *prg.mem[int32(p)+widthOffset].int()
- goto finRule
- case whatsitNode:
- // Output the whatsit node |p| in an hlist
- prg.outWhat(p)
- case glueNode:
- // Move right or output leaders
- prg.g = *(*prg.mem[int32(p)+1].hh()).lh()
- prg.ruleWd = *prg.mem[int32(prg.g)+widthOffset].int() - curG
- if int32(gSign) != normal {
- if int32(gSign) == stretching {
- if int32(*(*prg.mem[prg.g].hh()).b0()) == int32(gOrder) {
- curGlue = curGlue + float64(*prg.mem[int32(prg.g)+2].int())
- glueTemp = float64(*prg.mem[int32(thisBox)+glueOffset].gr()) * curGlue
- if glueTemp > 1000000000.0 {
- glueTemp = 1000000000.0
- } else if glueTemp < -1000000000.0 {
- glueTemp = -1000000000.0
- }
- // \xref[real multiplication]
- curG = round(glueTemp)
- }
- } else if int32(*(*prg.mem[prg.g].hh()).b1()) == int32(gOrder) {
- curGlue = curGlue - float64(*prg.mem[int32(prg.g)+3].int())
- glueTemp = float64(*prg.mem[int32(thisBox)+glueOffset].gr()) * curGlue
- if glueTemp > 1000000000.0 {
- glueTemp = 1000000000.0
- } else if glueTemp < -1000000000.0 {
- glueTemp = -1000000000.0
- }
- curG = round(glueTemp)
- }
- }
- prg.ruleWd = prg.ruleWd + curG
- if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
- leaderBox = *(*prg.mem[int32(p)+1].hh()).rh()
- if int32(*(*prg.mem[leaderBox].hh()).b0()) == ruleNode {
- prg.ruleHt = *prg.mem[int32(leaderBox)+heightOffset].int()
- prg.ruleDp = *prg.mem[int32(leaderBox)+depthOffset].int()
- goto finRule
- }
- leaderWd = *prg.mem[int32(leaderBox)+widthOffset].int()
- if leaderWd > 0 && prg.ruleWd > 0 {
- prg.ruleWd = prg.ruleWd + 10 // compensate for floating-point rounding
- edge = prg.curH + prg.ruleWd
- lx = 0
- // Let |cur_h| be the position of the first box, and set |leader_wd+lx| to the spacing between corresponding parts of boxes
- if int32(*(*prg.mem[p].hh()).b1()) == aLeaders {
- saveH = prg.curH
- prg.curH = leftEdge + leaderWd*((prg.curH-leftEdge)/leaderWd)
- if prg.curH < saveH {
- prg.curH = prg.curH + leaderWd
- }
- } else {
- prg.lq = prg.ruleWd / leaderWd // the number of box copies
- prg.lr = prg.ruleWd % leaderWd // the remaining space
- if int32(*(*prg.mem[p].hh()).b1()) == cLeaders {
- prg.curH = prg.curH + prg.lr/2
- } else {
- lx = prg.lr / (prg.lq + 1)
- prg.curH = prg.curH + (prg.lr-(prg.lq-1)*lx)/2
- }
- }
- for prg.curH+leaderWd <= edge {
- // Output a leader box at |cur_h|, then advance |cur_h| by |leader_wd+lx|
- prg.curV = baseLine + *prg.mem[int32(leaderBox)+4].int()
- if prg.curV != prg.dviV {
- prg.movement(prg.curV-prg.dviV, eightBits(down1))
- prg.dviV = prg.curV
- }
- saveV = prg.dviV
- if prg.curH != prg.dviH {
- prg.movement(prg.curH-prg.dviH, eightBits(right1))
- prg.dviH = prg.curH
- }
- saveH = prg.dviH
- prg.tempPtr = leaderBox
- outerDoingLeaders = prg.doingLeaders
- prg.doingLeaders = true
- if int32(*(*prg.mem[leaderBox].hh()).b0()) == vlistNode {
- prg.vlistOut()
- } else {
- prg.hlistOut()
- }
- prg.doingLeaders = outerDoingLeaders
- prg.dviV = saveV
- prg.dviH = saveH
- prg.curV = baseLine
- prg.curH = saveH + leaderWd + lx
- }
- prg.curH = edge - 10
- goto nextP
- }
- }
- goto movePast
- case kernNode, mathNode:
- prg.curH = prg.curH + *prg.mem[int32(p)+widthOffset].int()
- case ligatureNode:
- // Make node |p| look like a |char_node| and |goto reswitch|
- prg.mem[30000-12] = prg.mem[int32(p)+1]
- *(*prg.mem[30000-12].hh()).rh() = *(*prg.mem[p].hh()).rh()
- p = uint16(30000 - 12)
- goto reswitch
- default:
- }
- goto nextP
- finRule:
- if prg.ruleHt == -010000000000 {
- prg.ruleHt = *prg.mem[int32(thisBox)+heightOffset].int()
- }
- if prg.ruleDp == -010000000000 {
- prg.ruleDp = *prg.mem[int32(thisBox)+depthOffset].int()
- }
- prg.ruleHt = prg.ruleHt + prg.ruleDp // this is the rule thickness
- if prg.ruleHt > 0 && prg.ruleWd > 0 {
- if prg.curH != prg.dviH {
- prg.movement(prg.curH-prg.dviH, eightBits(right1))
- prg.dviH = prg.curH
- }
- prg.curV = baseLine + prg.ruleDp
- if prg.curV != prg.dviV {
- prg.movement(prg.curV-prg.dviV, eightBits(down1))
- prg.dviV = prg.curV
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(setRule)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.dviFour(prg.ruleHt)
- prg.dviFour(prg.ruleWd)
- prg.curV = baseLine
- prg.dviH = prg.dviH + prg.ruleWd
- }
- movePast:
- prg.curH = prg.curH + prg.ruleWd
- nextP:
- p = *(*prg.mem[p].hh()).rh()
- }
- }
- prg.pruneMovements(saveLoc)
- if prg.curS > 0 {
- prg.dviPop(saveLoc)
- }
- prg.curS = prg.curS - 1
- }
- // 618.
- // tangle:pos tex.web:12307:1:
- // When |hlist_out| is called, its duty is to output the box represented
- // by the |hlist_node| pointed to by |temp_ptr|. The reference point of that
- // box has coordinates |(cur_h,cur_v)|.
- //
- // Similarly, when |vlist_out| is called, its duty is to output the box represented
- // by the |vlist_node| pointed to by |temp_ptr|. The reference point of that
- // box has coordinates |(cur_h,cur_v)|.
- // \xref[recursion]
- func (prg *prg) vlistOut() {
- var (
- leftEdge scaled // the left coordinate for this box
- topEdge scaled // the top coordinate for this box
- saveH, saveV scaled // what |dvi_h| and |dvi_v| should pop to
- thisBox halfword // pointer to containing box
- gOrder glueOrd // applicable order of infinity for glue
- gSign/* normal..shrinking */ byte // selects type of glue
- p halfword // current position in the vlist
- saveLoc int32 // \.[DVI] byte location upon entry
- leaderBox halfword // the leader box being replicated
- leaderHt scaled // height of leader box being replicated
- lx scaled // extra space between leader boxes
- outerDoingLeaders bool // were we doing leaders?
- edge scaled // bottom boundary of leader space
- glueTemp float64 // glue value before rounding
- curGlue float64 // glue seen so far
- curG scaled // rounded equivalent of |cur_glue| times the glue ratio
- )
- curG = 0
- curGlue = 0.0
- thisBox = prg.tempPtr
- gOrder = *(*prg.mem[int32(thisBox)+listOffset].hh()).b1()
- gSign = *(*prg.mem[int32(thisBox)+listOffset].hh()).b0()
- p = *(*prg.mem[int32(thisBox)+listOffset].hh()).rh()
- prg.curS = prg.curS + 1
- if prg.curS > 0 {
- prg.dviBuf[prg.dviPtr] = byte(push)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- if prg.curS > prg.maxPush {
- prg.maxPush = prg.curS
- }
- saveLoc = prg.dviOffset + int32(prg.dviPtr)
- leftEdge = prg.curH
- prg.curV = prg.curV - *prg.mem[int32(thisBox)+heightOffset].int()
- topEdge = prg.curV
- for int32(p) != 0 {
- // Output node |p| for |vlist_out| and move to the next node, maintaining the condition |cur_h=left_edge|
- if int32(p) >= int32(prg.hiMemMin) {
- prg.confusion(strNumber( /* "vlistout" */ 828))
- } else {
- // Output the non-|char_node| |p| for |vlist_out|
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode:
- // Output a box in a vlist
- if int32(*(*prg.mem[int32(p)+listOffset].hh()).rh()) == 0 {
- prg.curV = prg.curV + *prg.mem[int32(p)+heightOffset].int() + *prg.mem[int32(p)+depthOffset].int()
- } else {
- prg.curV = prg.curV + *prg.mem[int32(p)+heightOffset].int()
- if prg.curV != prg.dviV {
- prg.movement(prg.curV-prg.dviV, eightBits(down1))
- prg.dviV = prg.curV
- }
- saveH = prg.dviH
- saveV = prg.dviV
- prg.curH = leftEdge + *prg.mem[int32(p)+4].int() // shift the box right
- prg.tempPtr = p
- if int32(*(*prg.mem[p].hh()).b0()) == vlistNode {
- prg.vlistOut()
- } else {
- prg.hlistOut()
- }
- prg.dviH = saveH
- prg.dviV = saveV
- prg.curV = saveV + *prg.mem[int32(p)+depthOffset].int()
- prg.curH = leftEdge
- }
- case ruleNode:
- prg.ruleHt = *prg.mem[int32(p)+heightOffset].int()
- prg.ruleDp = *prg.mem[int32(p)+depthOffset].int()
- prg.ruleWd = *prg.mem[int32(p)+widthOffset].int()
- goto finRule
- case whatsitNode:
- // Output the whatsit node |p| in a vlist
- prg.outWhat(p)
- case glueNode:
- // Move down or output leaders
- prg.g = *(*prg.mem[int32(p)+1].hh()).lh()
- prg.ruleHt = *prg.mem[int32(prg.g)+widthOffset].int() - curG
- if int32(gSign) != normal {
- if int32(gSign) == stretching {
- if int32(*(*prg.mem[prg.g].hh()).b0()) == int32(gOrder) {
- curGlue = curGlue + float64(*prg.mem[int32(prg.g)+2].int())
- glueTemp = float64(*prg.mem[int32(thisBox)+glueOffset].gr()) * curGlue
- if glueTemp > 1000000000.0 {
- glueTemp = 1000000000.0
- } else if glueTemp < -1000000000.0 {
- glueTemp = -1000000000.0
- }
- // \xref[real multiplication]
- curG = round(glueTemp)
- }
- } else if int32(*(*prg.mem[prg.g].hh()).b1()) == int32(gOrder) {
- curGlue = curGlue - float64(*prg.mem[int32(prg.g)+3].int())
- glueTemp = float64(*prg.mem[int32(thisBox)+glueOffset].gr()) * curGlue
- if glueTemp > 1000000000.0 {
- glueTemp = 1000000000.0
- } else if glueTemp < -1000000000.0 {
- glueTemp = -1000000000.0
- }
- curG = round(glueTemp)
- }
- }
- prg.ruleHt = prg.ruleHt + curG
- if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
- leaderBox = *(*prg.mem[int32(p)+1].hh()).rh()
- if int32(*(*prg.mem[leaderBox].hh()).b0()) == ruleNode {
- prg.ruleWd = *prg.mem[int32(leaderBox)+widthOffset].int()
- prg.ruleDp = 0
- goto finRule
- }
- leaderHt = *prg.mem[int32(leaderBox)+heightOffset].int() + *prg.mem[int32(leaderBox)+depthOffset].int()
- if leaderHt > 0 && prg.ruleHt > 0 {
- prg.ruleHt = prg.ruleHt + 10 // compensate for floating-point rounding
- edge = prg.curV + prg.ruleHt
- lx = 0
- // Let |cur_v| be the position of the first box, and set |leader_ht+lx| to the spacing between corresponding parts of boxes
- if int32(*(*prg.mem[p].hh()).b1()) == aLeaders {
- saveV = prg.curV
- prg.curV = topEdge + leaderHt*((prg.curV-topEdge)/leaderHt)
- if prg.curV < saveV {
- prg.curV = prg.curV + leaderHt
- }
- } else {
- prg.lq = prg.ruleHt / leaderHt // the number of box copies
- prg.lr = prg.ruleHt % leaderHt // the remaining space
- if int32(*(*prg.mem[p].hh()).b1()) == cLeaders {
- prg.curV = prg.curV + prg.lr/2
- } else {
- lx = prg.lr / (prg.lq + 1)
- prg.curV = prg.curV + (prg.lr-(prg.lq-1)*lx)/2
- }
- }
- for prg.curV+leaderHt <= edge {
- // Output a leader box at |cur_v|, then advance |cur_v| by |leader_ht+lx|
- prg.curH = leftEdge + *prg.mem[int32(leaderBox)+4].int()
- if prg.curH != prg.dviH {
- prg.movement(prg.curH-prg.dviH, eightBits(right1))
- prg.dviH = prg.curH
- }
- saveH = prg.dviH
- prg.curV = prg.curV + *prg.mem[int32(leaderBox)+heightOffset].int()
- if prg.curV != prg.dviV {
- prg.movement(prg.curV-prg.dviV, eightBits(down1))
- prg.dviV = prg.curV
- }
- saveV = prg.dviV
- prg.tempPtr = leaderBox
- outerDoingLeaders = prg.doingLeaders
- prg.doingLeaders = true
- if int32(*(*prg.mem[leaderBox].hh()).b0()) == vlistNode {
- prg.vlistOut()
- } else {
- prg.hlistOut()
- }
- prg.doingLeaders = outerDoingLeaders
- prg.dviV = saveV
- prg.dviH = saveH
- prg.curH = leftEdge
- prg.curV = saveV - *prg.mem[int32(leaderBox)+heightOffset].int() + leaderHt + lx
- }
- prg.curV = edge - 10
- goto nextP
- }
- }
- goto movePast
- case kernNode:
- prg.curV = prg.curV + *prg.mem[int32(p)+widthOffset].int()
- default:
- }
- goto nextP
- finRule:
- if prg.ruleWd == -010000000000 {
- prg.ruleWd = *prg.mem[int32(thisBox)+widthOffset].int()
- }
- prg.ruleHt = prg.ruleHt + prg.ruleDp // this is the rule thickness
- prg.curV = prg.curV + prg.ruleHt
- if prg.ruleHt > 0 && prg.ruleWd > 0 {
- if prg.curH != prg.dviH {
- prg.movement(prg.curH-prg.dviH, eightBits(right1))
- prg.dviH = prg.curH
- }
- if prg.curV != prg.dviV {
- prg.movement(prg.curV-prg.dviV, eightBits(down1))
- prg.dviV = prg.curV
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(putRule)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.dviFour(prg.ruleHt)
- prg.dviFour(prg.ruleWd)
- }
- goto nextP
- movePast:
- prg.curV = prg.curV + prg.ruleHt
- }
- nextP:
- p = *(*prg.mem[p].hh()).rh()
- }
- prg.pruneMovements(saveLoc)
- if prg.curS > 0 {
- prg.dviPop(saveLoc)
- }
- prg.curS = prg.curS - 1
- }
- // 638.
- // tangle:pos tex.web:12678:1:
- // The |hlist_out| and |vlist_out| procedures are now complete, so we are
- // ready for the |ship_out| routine that gets them started in the first place.
- func (prg *prg) shipOut(p halfword) {
- var (
- pageLoc int32 // location of the current |bop|
- j, k/* 0..9 */ byte // indices to first ten count registers
- s poolPointer // index into |str_pool|
- oldSetting/* 0..maxSelector */ byte // saved |selector| setting
- )
- if *prg.eqtb[intBase+tracingOutputCode-1].int() > 0 {
- prg.printNl(strNumber( /* "" */ 338))
- prg.printLn()
- prg.print( /* "Completed box being shipped out" */ 829)
- // \xref[Completed box...]
- }
- if int32(prg.termOffset) > maxPrintLine-9 {
- prg.printLn()
- } else if int32(prg.termOffset) > 0 || int32(prg.fileOffset) > 0 {
- prg.printChar(asciiCode(' '))
- }
- prg.printChar(asciiCode('['))
- j = 9
- for *prg.eqtb[countBase+int32(j)-1].int() == 0 && int32(j) > 0 {
- j = byte(int32(j) - 1)
- }
- for ii := int32(0); ii <= int32(j); ii++ {
- k = byte(ii)
- _ = k
- prg.printInt(*prg.eqtb[countBase+int32(k)-1].int())
- if int32(k) < int32(j) {
- prg.printChar(asciiCode('.'))
- }
- }
- if *prg.eqtb[intBase+tracingOutputCode-1].int() > 0 {
- prg.printChar(asciiCode(']'))
- prg.beginDiagnostic()
- prg.showBox(p)
- prg.endDiagnostic(true)
- }
- // Ship box |p| out
- // Update the values of |max_h| and |max_v|; but if the page is too large, |goto done|
- if *prg.mem[int32(p)+heightOffset].int() > 07777777777 || *prg.mem[int32(p)+depthOffset].int() > 07777777777 || *prg.mem[int32(p)+heightOffset].int()+*prg.mem[int32(p)+depthOffset].int()+*prg.eqtb[dimenBase+vOffsetCode-1].int() > 07777777777 || *prg.mem[int32(p)+widthOffset].int()+*prg.eqtb[dimenBase+hOffsetCode-1].int() > 07777777777 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Huge page cannot be shipped out" */ 833)
- }
- // \xref[Huge page...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "The page just created is more than 18 feet tall or" */ 834
- prg.helpLine[0] = /* "more than 18 feet wide, so I suspect something went wrong." */ 835
- }
- prg.error1()
- if *prg.eqtb[intBase+tracingOutputCode-1].int() <= 0 {
- prg.beginDiagnostic()
- prg.printNl(strNumber( /* "The following box has been deleted:" */ 836))
- // \xref[The following...deleted]
- prg.showBox(p)
- prg.endDiagnostic(true)
- }
- goto done
- }
- if *prg.mem[int32(p)+heightOffset].int()+*prg.mem[int32(p)+depthOffset].int()+*prg.eqtb[dimenBase+vOffsetCode-1].int() > prg.maxV {
- prg.maxV = *prg.mem[int32(p)+heightOffset].int() + *prg.mem[int32(p)+depthOffset].int() + *prg.eqtb[dimenBase+vOffsetCode-1].int()
- }
- if *prg.mem[int32(p)+widthOffset].int()+*prg.eqtb[dimenBase+hOffsetCode-1].int() > prg.maxH {
- prg.maxH = *prg.mem[int32(p)+widthOffset].int() + *prg.eqtb[dimenBase+hOffsetCode-1].int()
- }
- // Initialize variables as |ship_out| begins
- prg.dviH = 0
- prg.dviV = 0
- prg.curH = *prg.eqtb[dimenBase+hOffsetCode-1].int()
- prg.dviF = byte(fontBase)
- if int32(prg.outputFileName) == 0 {
- if int32(prg.jobName) == 0 {
- prg.openLogFile()
- }
- prg.packJobName(strNumber( /* ".dvi" */ 794))
- for !prg.bOpenOut(prg.dviFile) {
- prg.promptFileName(strNumber( /* "file name for output" */ 795), strNumber( /* ".dvi" */ 794))
- }
- prg.outputFileName = prg.bMakeNameString(prg.dviFile)
- }
- if prg.totalPages == 0 {
- {
- prg.dviBuf[prg.dviPtr] = byte(pre)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(idByte)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } // output the preamble
- // \xref[preamble of \.[DVI] file]
- prg.dviFour(25400000)
- prg.dviFour(473628672) // conversion ratio for sp
- prg.prepareMag()
- prg.dviFour(*prg.eqtb[intBase+magCode-1].int()) // magnification factor is frozen
- oldSetting = prg.selector
- prg.selector = byte(newString)
- prg.print( /* " TeX output " */ 827)
- prg.printInt(*prg.eqtb[intBase+yearCode-1].int())
- prg.printChar(asciiCode('.'))
- prg.printTwo(*prg.eqtb[intBase+monthCode-1].int())
- prg.printChar(asciiCode('.'))
- prg.printTwo(*prg.eqtb[intBase+dayCode-1].int())
- prg.printChar(asciiCode(':'))
- prg.printTwo(*prg.eqtb[intBase+timeCode-1].int() / 60)
- prg.printTwo(*prg.eqtb[intBase+timeCode-1].int() % 60)
- prg.selector = oldSetting
- {
- prg.dviBuf[prg.dviPtr] = byte(int32(prg.poolPtr) - int32(prg.strStart[prg.strPtr]))
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- for ii := int32(prg.strStart[prg.strPtr]); ii <= int32(prg.poolPtr)-1; ii++ {
- s = poolPointer(ii)
- _ = s
- prg.dviBuf[prg.dviPtr] = prg.strPool[s]
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.poolPtr = prg.strStart[prg.strPtr] // flush the current string
- }
- pageLoc = prg.dviOffset + int32(prg.dviPtr)
- {
- prg.dviBuf[prg.dviPtr] = byte(bop)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- for ii := int32(0); ii <= 9; ii++ {
- k = byte(ii)
- _ = k
- prg.dviFour(*prg.eqtb[countBase+int32(k)-1].int())
- }
- prg.dviFour(prg.lastBop)
- prg.lastBop = pageLoc
- prg.curV = *prg.mem[int32(p)+heightOffset].int() + *prg.eqtb[dimenBase+vOffsetCode-1].int()
- prg.tempPtr = p
- if int32(*(*prg.mem[p].hh()).b0()) == vlistNode {
- prg.vlistOut()
- } else {
- prg.hlistOut()
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(eop)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.totalPages = prg.totalPages + 1
- prg.curS = -1
- done:
- ;
- if *prg.eqtb[intBase+tracingOutputCode-1].int() <= 0 {
- prg.printChar(asciiCode(']'))
- }
- prg.deadCycles = 0
- // progress report
- // Flush the box from memory, showing statistics if requested
- // if eqtb[int_base+ tracing_stats_code].int >1 then
- // begin print_nl(["Memory usage before: "=]830);
- // [ \xref[Memory usage...] ]
- // print_int(var_used); print_char(["&"=]38);
- // print_int(dyn_used); print_char([";"=]59);
- // end;
- // [ ]
- prg.flushNodeList(p)
- // if eqtb[int_base+ tracing_stats_code].int >1 then
- // begin print([" after: "=]831);
- // print_int(var_used); print_char(["&"=]38);
- // print_int(dyn_used); print(["; still untouched: "=]832);
- // print_int(hi_mem_min-lo_mem_max-1); print_ln;
- // end;
- // [ ]
- }
- // 644. \[33] Packaging
- // tangle:pos tex.web:12811:18:
- // We're essentially done with the parts of \TeX\ that are concerned with
- // the input (|get_next|) and the output (|ship_out|). So it's time to
- // get heavily into the remaining part, which does the real work of typesetting.
- //
- // After lists are constructed, \TeX\ wraps them up and puts them into boxes.
- // Two major subroutines are given the responsibility for this task: |hpack|
- // applies to horizontal lists (hlists) and |vpack| applies to vertical lists
- // (vlists). The main duty of |hpack| and |vpack| is to compute the dimensions
- // of the resulting boxes, and to adjust the glue if one of those dimensions
- // is pre-specified. The computed sizes normally enclose all of the material
- // inside the new box; but some items may stick out if negative glue is used,
- // if the box is overfull, or if a \.[\\vbox] includes other boxes that have
- // been shifted left.
- //
- // The subroutine call |hpack(p,w,m)| returns a pointer to an |hlist_node|
- // for a box containing the hlist that starts at |p|. Parameter |w| specifies
- // a width; and parameter |m| is either `|exactly|' or `|additional|'. Thus,
- // |hpack(p,w,exactly)| produces a box whose width is exactly |w|, while
- // |hpack(p,w,additional)| yields a box whose width is the natural width plus
- // |w|. It is convenient to define a macro called `|natural|' to cover the
- // most common case, so that we can say |hpack(p,natural)| to get a box that
- // has the natural width of list |p|.
- //
- // Similarly, |vpack(p,w,m)| returns a pointer to a |vlist_node| for a
- // box containing the vlist that starts at |p|. In this case |w| represents
- // a height instead of a width; the parameter |m| is interpreted as in |hpack|.
- // 645.
- // tangle:pos tex.web:12843:1:
- // The parameters to |hpack| and |vpack| correspond to \TeX's primitives
- // like `\.[\\hbox] \.[to] \.[300pt]', `\.[\\hbox] \.[spread] \.[10pt]'; note
- // that `\.[\\hbox]' with no dimension following it is equivalent to
- // `\.[\\hbox] \.[spread] \.[0pt]'. The |scan_spec| subroutine scans such
- // constructions in the user's input, including the mandatory left brace that
- // follows them, and it puts the specification onto |save_stack| so that the
- // desired box can later be obtained by executing the following code:
- // $$\vbox[\halign[#\hfil\cr
- // |save_ptr:=save_ptr-2;|\cr
- // |hpack(p,saved(1),saved(0)).|\cr]]$$
- // Special care is necessary to ensure that the special |save_stack| codes
- // are placed just below the new group code, because scanning can change
- // |save_stack| when \.[\\csname] appears.
- func (prg *prg) scanSpec(c groupCode, threeCodes bool) {
- var (
- s int32 // temporarily saved value
- specCode/* exactly..additional */ byte
- )
- if threeCodes {
- s = *prg.saveStack[int32(prg.savePtr)+0].int()
- }
- if prg.scanKeyword(strNumber( /* "to" */ 842)) {
- specCode = byte(exactly)
- } else if prg.scanKeyword(strNumber( /* "spread" */ 843)) {
- specCode = byte(additional)
- } else {
- specCode = byte(additional)
- prg.curVal = 0
- goto found
- }
- prg.scanDimen(false, false, false)
- found:
- if threeCodes {
- *prg.saveStack[int32(prg.savePtr)+0].int() = s
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- }
- *prg.saveStack[int32(prg.savePtr)+0].int() = int32(specCode)
- *prg.saveStack[int32(prg.savePtr)+1].int() = prg.curVal
- prg.savePtr = uint16(int32(prg.savePtr) + 2)
- prg.newSaveLevel(c)
- prg.scanLeftBrace()
- }
- // 649.
- // tangle:pos tex.web:12910:1:
- // Here now is |hpack|, which contains few if any surprises.
- func (prg *prg) hpack(p halfword, w scaled, m smallNumber) (r halfword) {
- var (
- r1 halfword // the box node that will be returned
- q halfword // trails behind |p|
- h, d, x scaled // height, depth, and natural width
- s scaled // shift amount
- g halfword // points to a glue specification
- o glueOrd // order of infinity
- f internalFontNumber // the font in a |char_node|
- i fourQuarters // font information about a |char_node|
- hd eightBits // height and depth indices for a character
- )
- prg.lastBadness = 0
- r1 = prg.getNode(boxNodeSize)
- *(*prg.mem[r1].hh()).b0() = byte(hlistNode)
- *(*prg.mem[r1].hh()).b1() = byte(minQuarterword)
- *prg.mem[int32(r1)+4].int() = 0
- q = uint16(int32(r1) + listOffset)
- *(*prg.mem[q].hh()).rh() = p
- h = 0
- // Clear dimensions to zero
- d = 0
- x = 0
- prg.totalStretch[normal] = 0
- prg.totalShrink[normal] = 0
- prg.totalStretch[fil] = 0
- prg.totalShrink[fil] = 0
- prg.totalStretch[fill] = 0
- prg.totalShrink[fill] = 0
- prg.totalStretch[filll] = 0
- prg.totalShrink[filll] = 0
- for int32(p) != 0 {
- // Examine node |p| in the hlist, taking account of its effect on the dimensions of the new box, or moving it to the adjustment list; then advance |p| to the next node
- // \xref[inner loop]
- reswitch:
- for int32(p) >= int32(prg.hiMemMin) {
- // Incorporate character dimensions into the dimensions of the hbox that will contain~it, then move to the next node
- f = *(*prg.mem[p].hh()).b0()
- i = *prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()
- hd = byte(int32(i.b1) - minQuarterword)
- x = x + *prg.fontInfo[prg.widthBase[f]+int32(i.b0)].int()
- s = *prg.fontInfo[prg.heightBase[f]+int32(hd)/16].int()
- if s > h {
- h = s
- }
- s = *prg.fontInfo[prg.depthBase[f]+int32(hd)%16].int()
- if s > d {
- d = s
- }
- p = *(*prg.mem[p].hh()).rh()
- }
- if int32(p) != 0 {
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, ruleNode, unsetNode:
- // Incorporate box dimensions into the dimensions of the hbox that will contain~it
- x = x + *prg.mem[int32(p)+widthOffset].int()
- if int32(*(*prg.mem[p].hh()).b0()) >= ruleNode {
- s = 0
- } else {
- s = *prg.mem[int32(p)+4].int()
- }
- if *prg.mem[int32(p)+heightOffset].int()-s > h {
- h = *prg.mem[int32(p)+heightOffset].int() - s
- }
- if *prg.mem[int32(p)+depthOffset].int()+s > d {
- d = *prg.mem[int32(p)+depthOffset].int() + s
- }
- case insNode, markNode, adjustNode:
- if int32(prg.adjustTail) != 0 {
- for int32(*(*prg.mem[q].hh()).rh()) != int32(p) {
- q = *(*prg.mem[q].hh()).rh()
- }
- if int32(*(*prg.mem[p].hh()).b0()) == adjustNode {
- *(*prg.mem[prg.adjustTail].hh()).rh() = uint16(*prg.mem[int32(p)+1].int())
- for int32(*(*prg.mem[prg.adjustTail].hh()).rh()) != 0 {
- prg.adjustTail = *(*prg.mem[prg.adjustTail].hh()).rh()
- }
- p = *(*prg.mem[p].hh()).rh()
- prg.freeNode(*(*prg.mem[q].hh()).rh(), halfword(smallNodeSize))
- } else {
- *(*prg.mem[prg.adjustTail].hh()).rh() = p
- prg.adjustTail = p
- p = *(*prg.mem[p].hh()).rh()
- }
- *(*prg.mem[q].hh()).rh() = p
- p = q
- }
- case whatsitNode:
- // Incorporate a whatsit node into an hbox
- // Incorporate a whatsit node into an hbox
- case glueNode:
- // Incorporate glue into the horizontal totals
- g = *(*prg.mem[int32(p)+1].hh()).lh()
- x = x + *prg.mem[int32(g)+widthOffset].int()
- o = *(*prg.mem[g].hh()).b0()
- prg.totalStretch[o] = prg.totalStretch[o] + *prg.mem[int32(g)+2].int()
- o = *(*prg.mem[g].hh()).b1()
- prg.totalShrink[o] = prg.totalShrink[o] + *prg.mem[int32(g)+3].int()
- if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
- g = *(*prg.mem[int32(p)+1].hh()).rh()
- if *prg.mem[int32(g)+heightOffset].int() > h {
- h = *prg.mem[int32(g)+heightOffset].int()
- }
- if *prg.mem[int32(g)+depthOffset].int() > d {
- d = *prg.mem[int32(g)+depthOffset].int()
- }
- }
- case kernNode, mathNode:
- x = x + *prg.mem[int32(p)+widthOffset].int()
- case ligatureNode:
- // Make node |p| look like a |char_node| and |goto reswitch|
- prg.mem[30000-12] = prg.mem[int32(p)+1]
- *(*prg.mem[30000-12].hh()).rh() = *(*prg.mem[p].hh()).rh()
- p = uint16(30000 - 12)
- goto reswitch
- default:
- }
- p = *(*prg.mem[p].hh()).rh()
- }
- }
- if int32(prg.adjustTail) != 0 {
- *(*prg.mem[prg.adjustTail].hh()).rh() = 0
- }
- *prg.mem[int32(r1)+heightOffset].int() = h
- *prg.mem[int32(r1)+depthOffset].int() = d
- // Determine the value of |width(r)| and the appropriate glue setting; then |return| or |goto common_ending|
- if int32(m) == additional {
- w = x + w
- }
- *prg.mem[int32(r1)+widthOffset].int() = w
- x = w - x // now |x| is the excess to be made up
- if x == 0 {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = byte(normal)
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
- goto exit
- } else if x > 0 {
- if prg.totalStretch[filll] != 0 {
- o = byte(filll)
- } else if prg.totalStretch[fill] != 0 {
- o = byte(fill)
- } else if prg.totalStretch[fil] != 0 {
- o = byte(fil)
- } else {
- o = byte(normal)
- }
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = o
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(stretching)
- if prg.totalStretch[o] != 0 {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(float64(x) / float64(prg.totalStretch[o]))
- } else {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0) // there's nothing to stretch
- }
- if int32(o) == normal {
- if int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
- prg.lastBadness = int32(prg.badness(x, prg.totalStretch[normal]))
- if prg.lastBadness > *prg.eqtb[intBase+hbadnessCode-1].int() {
- prg.printLn()
- if prg.lastBadness > 100 {
- prg.printNl(strNumber( /* "Underfull" */ 844))
- } else {
- prg.printNl(strNumber( /* "Loose" */ 845))
- }
- prg.print( /* " \\hbox (badness " */ 846)
- prg.printInt(prg.lastBadness)
- // \xref[Underfull \\hbox...]
- // \xref[Loose \\hbox...]
- // \xref[Underfull \\hbox...]
- // \xref[Loose \\hbox...]
- goto commonEnding
- }
- }
- }
- goto exit
- } else {
- // Determine horizontal glue shrink setting, then |return| or \hbox[|goto common_ending|]
- if prg.totalShrink[filll] != 0 {
- o = byte(filll)
- } else if prg.totalShrink[fill] != 0 {
- o = byte(fill)
- } else if prg.totalShrink[fil] != 0 {
- o = byte(fil)
- } else {
- o = byte(normal)
- }
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = o
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(shrinking)
- if prg.totalShrink[o] != 0 {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(float64(-x) / float64(prg.totalShrink[o]))
- } else {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0) // there's nothing to shrink
- }
- if prg.totalShrink[o] < -x && int32(o) == normal && int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
- prg.lastBadness = 1000000
- *prg.mem[int32(r1)+glueOffset].gr() = float32(1.0) // use the maximum shrinkage
- // Report an overfull hbox and |goto common_ending|, if this box is sufficiently bad
- if -x-prg.totalShrink[normal] > *prg.eqtb[dimenBase+hfuzzCode-1].int() || *prg.eqtb[intBase+hbadnessCode-1].int() < 100 {
- if *prg.eqtb[dimenBase+overfullRuleCode-1].int() > 0 && -x-prg.totalShrink[normal] > *prg.eqtb[dimenBase+hfuzzCode-1].int() {
- for int32(*(*prg.mem[q].hh()).rh()) != 0 {
- q = *(*prg.mem[q].hh()).rh()
- }
- *(*prg.mem[q].hh()).rh() = prg.newRule()
- *prg.mem[int32(*(*prg.mem[q].hh()).rh())+widthOffset].int() = *prg.eqtb[dimenBase+overfullRuleCode-1].int()
- }
- prg.printLn()
- prg.printNl(strNumber( /* "Overfull \\hbox (" */ 852))
- // \xref[Overfull \\hbox...]
- prg.printScaled(-x - prg.totalShrink[normal])
- prg.print( /* "pt too wide" */ 853)
- goto commonEnding
- }
- } else if int32(o) == normal {
- if int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
- prg.lastBadness = int32(prg.badness(-x, prg.totalShrink[normal]))
- if prg.lastBadness > *prg.eqtb[intBase+hbadnessCode-1].int() {
- prg.printLn()
- prg.printNl(strNumber( /* "Tight \\hbox (badness " */ 854))
- prg.printInt(prg.lastBadness)
- // \xref[Tight \\hbox...]
- // \xref[Tight \\hbox...]
- goto commonEnding
- }
- }
- }
- goto exit
- }
- commonEnding:
- if prg.outputActive {
- prg.print( /* ") has occurred while \\output is active" */ 847)
- } else {
- if prg.packBeginLine != 0 {
- if prg.packBeginLine > 0 {
- prg.print( /* ") in paragraph at lines " */ 848)
- } else {
- prg.print( /* ") in alignment at lines " */ 849)
- }
- prg.printInt(abs(prg.packBeginLine))
- prg.print( /* "--" */ 850)
- } else {
- prg.print( /* ") detected at line " */ 851)
- }
- prg.printInt(prg.line)
- }
- prg.printLn()
- prg.fontInShortDisplay = fontBase
- prg.shortDisplay(int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()))
- prg.printLn()
- prg.beginDiagnostic()
- prg.showBox(r1)
- prg.endDiagnostic(true)
- exit:
- r = r1
- return r
- }
- // 668.
- // tangle:pos tex.web:13152:1:
- // The |vpack| subroutine is actually a special case of a slightly more
- // general routine called |vpackage|, which has four parameters. The fourth
- // parameter, which is |max_dimen| in the case of |vpack|, specifies the
- // maximum depth of the page box that is constructed. The depth is first
- // computed by the normal rules; if it exceeds this limit, the reference
- // point is simply moved down until the limiting depth is attained.
- func (prg *prg) vpackage(p halfword, h scaled, m smallNumber, l scaled) (r halfword) {
- var (
- r1 halfword // the box node that will be returned
- w, d, x scaled // width, depth, and natural height
- s scaled // shift amount
- g halfword // points to a glue specification
- o glueOrd // order of infinity
- )
- prg.lastBadness = 0
- r1 = prg.getNode(boxNodeSize)
- *(*prg.mem[r1].hh()).b0() = byte(vlistNode)
- *(*prg.mem[r1].hh()).b1() = byte(minQuarterword)
- *prg.mem[int32(r1)+4].int() = 0
- *(*prg.mem[int32(r1)+listOffset].hh()).rh() = p
- w = 0
- // Clear dimensions to zero
- d = 0
- x = 0
- prg.totalStretch[normal] = 0
- prg.totalShrink[normal] = 0
- prg.totalStretch[fil] = 0
- prg.totalShrink[fil] = 0
- prg.totalStretch[fill] = 0
- prg.totalShrink[fill] = 0
- prg.totalStretch[filll] = 0
- prg.totalShrink[filll] = 0
- for int32(p) != 0 {
- // Examine node |p| in the vlist, taking account of its effect on the dimensions of the new box; then advance |p| to the next node
- if int32(p) >= int32(prg.hiMemMin) {
- prg.confusion(strNumber( /* "vpack" */ 855))
- } else {
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, ruleNode, unsetNode:
- // Incorporate box dimensions into the dimensions of the vbox that will contain~it
- x = x + d + *prg.mem[int32(p)+heightOffset].int()
- d = *prg.mem[int32(p)+depthOffset].int()
- if int32(*(*prg.mem[p].hh()).b0()) >= ruleNode {
- s = 0
- } else {
- s = *prg.mem[int32(p)+4].int()
- }
- if *prg.mem[int32(p)+widthOffset].int()+s > w {
- w = *prg.mem[int32(p)+widthOffset].int() + s
- }
- case whatsitNode:
- // Incorporate a whatsit node into a vbox
- // Incorporate a whatsit node into a vbox
- case glueNode:
- // Incorporate glue into the vertical totals
- x = x + d
- d = 0
- g = *(*prg.mem[int32(p)+1].hh()).lh()
- x = x + *prg.mem[int32(g)+widthOffset].int()
- o = *(*prg.mem[g].hh()).b0()
- prg.totalStretch[o] = prg.totalStretch[o] + *prg.mem[int32(g)+2].int()
- o = *(*prg.mem[g].hh()).b1()
- prg.totalShrink[o] = prg.totalShrink[o] + *prg.mem[int32(g)+3].int()
- if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
- g = *(*prg.mem[int32(p)+1].hh()).rh()
- if *prg.mem[int32(g)+widthOffset].int() > w {
- w = *prg.mem[int32(g)+widthOffset].int()
- }
- }
- case kernNode:
- x = x + d + *prg.mem[int32(p)+widthOffset].int()
- d = 0
- default:
- }
- }
- p = *(*prg.mem[p].hh()).rh()
- }
- *prg.mem[int32(r1)+widthOffset].int() = w
- if d > l {
- x = x + d - l
- *prg.mem[int32(r1)+depthOffset].int() = l
- } else {
- *prg.mem[int32(r1)+depthOffset].int() = d
- }
- // Determine the value of |height(r)| and the appropriate glue setting; then |return| or |goto common_ending|
- if int32(m) == additional {
- h = x + h
- }
- *prg.mem[int32(r1)+heightOffset].int() = h
- x = h - x // now |x| is the excess to be made up
- if x == 0 {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = byte(normal)
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
- goto exit
- } else if x > 0 {
- if prg.totalStretch[filll] != 0 {
- o = byte(filll)
- } else if prg.totalStretch[fill] != 0 {
- o = byte(fill)
- } else if prg.totalStretch[fil] != 0 {
- o = byte(fil)
- } else {
- o = byte(normal)
- }
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = o
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(stretching)
- if prg.totalStretch[o] != 0 {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(float64(x) / float64(prg.totalStretch[o]))
- } else {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0) // there's nothing to stretch
- }
- if int32(o) == normal {
- if int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
- prg.lastBadness = int32(prg.badness(x, prg.totalStretch[normal]))
- if prg.lastBadness > *prg.eqtb[intBase+vbadnessCode-1].int() {
- prg.printLn()
- if prg.lastBadness > 100 {
- prg.printNl(strNumber( /* "Underfull" */ 844))
- } else {
- prg.printNl(strNumber( /* "Loose" */ 845))
- }
- prg.print( /* " \\vbox (badness " */ 856)
- prg.printInt(prg.lastBadness)
- // \xref[Underfull \\vbox...]
- // \xref[Loose \\vbox...]
- // \xref[Underfull \\vbox...]
- // \xref[Loose \\vbox...]
- goto commonEnding
- }
- }
- }
- goto exit
- } else {
- // Determine vertical glue shrink setting, then |return| or \hbox[|goto common_ending|]
- if prg.totalShrink[filll] != 0 {
- o = byte(filll)
- } else if prg.totalShrink[fill] != 0 {
- o = byte(fill)
- } else if prg.totalShrink[fil] != 0 {
- o = byte(fil)
- } else {
- o = byte(normal)
- }
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = o
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(shrinking)
- if prg.totalShrink[o] != 0 {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(float64(-x) / float64(prg.totalShrink[o]))
- } else {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0) // there's nothing to shrink
- }
- if prg.totalShrink[o] < -x && int32(o) == normal && int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
- prg.lastBadness = 1000000
- *prg.mem[int32(r1)+glueOffset].gr() = float32(1.0) // use the maximum shrinkage
- // Report an overfull vbox and |goto common_ending|, if this box is sufficiently bad
- if -x-prg.totalShrink[normal] > *prg.eqtb[dimenBase+vfuzzCode-1].int() || *prg.eqtb[intBase+vbadnessCode-1].int() < 100 {
- prg.printLn()
- prg.printNl(strNumber( /* "Overfull \\vbox (" */ 857))
- // \xref[Overfull \\vbox...]
- prg.printScaled(-x - prg.totalShrink[normal])
- prg.print( /* "pt too high" */ 858)
- goto commonEnding
- }
- } else if int32(o) == normal {
- if int32(*(*prg.mem[int32(r1)+listOffset].hh()).rh()) != 0 {
- prg.lastBadness = int32(prg.badness(-x, prg.totalShrink[normal]))
- if prg.lastBadness > *prg.eqtb[intBase+vbadnessCode-1].int() {
- prg.printLn()
- prg.printNl(strNumber( /* "Tight \\vbox (badness " */ 859))
- prg.printInt(prg.lastBadness)
- // \xref[Tight \\vbox...]
- // \xref[Tight \\vbox...]
- goto commonEnding
- }
- }
- }
- goto exit
- }
- commonEnding:
- if prg.outputActive {
- prg.print( /* ") has occurred while \\output is active" */ 847)
- } else {
- if prg.packBeginLine != 0 {
- prg.print( /* ") in alignment at lines " */ 849)
- prg.printInt(abs(prg.packBeginLine))
- prg.print( /* "--" */ 850)
- } else {
- prg.print( /* ") detected at line " */ 851)
- }
- prg.printInt(prg.line)
- prg.printLn()
- }
- prg.beginDiagnostic()
- prg.showBox(r1)
- prg.endDiagnostic(true)
- exit:
- r = r1
- return r
- }
- // 679.
- // tangle:pos tex.web:13312:1:
- // When a box is being appended to the current vertical list, the
- // baselineskip calculation is handled by the |append_to_vlist| routine.
- func (prg *prg) appendToVlist(b halfword) {
- var (
- d scaled // deficiency of space between baselines
- p halfword // a new glue node
- )
- if *prg.curList.auxField.int() > -65536000 {
- d = *prg.mem[int32(*(*prg.eqtb[glueBase+baselineSkipCode-1].hh()).rh())+widthOffset].int() - *prg.curList.auxField.int() - *prg.mem[int32(b)+heightOffset].int()
- if d < *prg.eqtb[dimenBase+lineSkipLimitCode-1].int() {
- p = prg.newParamGlue(smallNumber(lineSkipCode))
- } else {
- p = prg.newSkipParam(smallNumber(baselineSkipCode))
- *prg.mem[int32(prg.tempPtr)+widthOffset].int() = d // |temp_ptr=glue_ptr(p)|
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- prg.curList.tailField = p
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = b
- prg.curList.tailField = b
- *prg.curList.auxField.int() = *prg.mem[int32(b)+depthOffset].int()
- }
- // 680. \[34] Data structures for math mode
- // tangle:pos tex.web:13329:38:
- // When \TeX\ reads a formula that is enclosed between \.\$'s, it constructs an
- // [\sl mlist], which is essentially a tree structure representing that
- // formula. An mlist is a linear sequence of items, but we can regard it as
- // a tree structure because mlists can appear within mlists. For example, many
- // of the entries can be subscripted or superscripted, and such ``scripts''
- // are mlists in their own right.
- //
- // An entire formula is parsed into such a tree before any of the actual
- // typesetting is done, because the current style of type is usually not
- // known until the formula has been fully scanned. For example, when the
- // formula `\.[\$a+b \\over c+d\$]' is being read, there is no way to tell
- // that `\.[a+b]' will be in script size until `\.[\\over]' has appeared.
- //
- // During the scanning process, each element of the mlist being built is
- // classified as a relation, a binary operator, an open parenthesis, etc.,
- // or as a construct like `\.[\\sqrt]' that must be built up. This classification
- // appears in the mlist data structure.
- //
- // After a formula has been fully scanned, the mlist is converted to an hlist
- // so that it can be incorporated into the surrounding text. This conversion is
- // controlled by a recursive procedure that decides all of the appropriate
- // styles by a ``top-down'' process starting at the outermost level and working
- // in towards the subformulas. The formula is ultimately pasted together using
- // combinations of horizontal and vertical boxes, with glue and penalty nodes
- // inserted as necessary.
- //
- // An mlist is represented internally as a linked list consisting chiefly
- // of ``noads'' (pronounced ``no-adds''), to distinguish them from the somewhat
- // similar ``nodes'' in hlists and vlists. Certain kinds of ordinary nodes are
- // allowed to appear in mlists together with the noads; \TeX\ tells the difference
- // by means of the |type| field, since a noad's |type| is always greater than
- // that of a node. An mlist does not contain character nodes, hlist nodes, vlist
- // nodes, math nodes, ligature nodes,
- // or unset nodes; in particular, each mlist item appears in the
- // variable-size part of |mem|, so the |type| field is always present.
- // 681.
- // tangle:pos tex.web:13366:1:
- // Each noad is four or more words long. The first word contains the |type|
- // and |subtype| and |link| fields that are already so familiar to us; the
- // second, third, and fourth words are called the noad's |nucleus|, |subscr|,
- // and |supscr| fields.
- //
- // Consider, for example, the simple formula `\.[\$x\^2\$]', which would be
- // parsed into an mlist containing a single element called an |ord_noad|.
- // The |nucleus| of this noad is a representation of `\.x', the |subscr| is
- // empty, and the |supscr| is a representation of `\.2'.
- //
- // The |nucleus|, |subscr|, and |supscr| fields are further broken into
- // subfields. If |p| points to a noad, and if |q| is one of its principal
- // fields (e.g., |q=subscr(p)|), there are several possibilities for the
- // subfields, depending on the |math_type| of |q|.
- //
- // \yskip\hang|math_type(q)=math_char| means that |fam(q)| refers to one of
- // the sixteen font families, and |character(q)| is the number of a character
- // within a font of that family, as in a character node.
- //
- // \yskip\hang|math_type(q)=math_text_char| is similar, but the character is
- // unsubscripted and unsuperscripted and it is followed immediately by another
- // character from the same font. (This |math_type| setting appears only
- // briefly during the processing; it is used to suppress unwanted italic
- // corrections.)
- //
- // \yskip\hang|math_type(q)=empty| indicates a field with no value (the
- // corresponding attribute of noad |p| is not present).
- //
- // \yskip\hang|math_type(q)=sub_box| means that |info(q)| points to a box
- // node (either an |hlist_node| or a |vlist_node|) that should be used as the
- // value of the field. The |shift_amount| in the subsidiary box node is the
- // amount by which that box will be shifted downward.
- //
- // \yskip\hang|math_type(q)=sub_mlist| means that |info(q)| points to
- // an mlist; the mlist must be converted to an hlist in order to obtain
- // the value of this field.
- //
- // \yskip\noindent In the latter case, we might have |info(q)=null|. This
- // is not the same as |math_type(q)=empty|; for example, `\.[\$P\_\[\]\$]'
- // and `\.[\$P\$]' produce different results (the former will not have the
- // ``italic correction'' added to the width of |P|, but the ``script skip''
- // will be added).
- //
- // The definitions of subfields given here are evidently wasteful of space,
- // since a halfword is being used for the |math_type| although only three
- // bits would be needed. However, there are hardly ever many noads present at
- // once, since they are soon converted to nodes that take up even more space,
- // so we can afford to represent them in whatever way simplifies the
- // programming.
- // 682.
- // tangle:pos tex.web:13427:1:
- // Each portion of a formula is classified as Ord, Op, Bin, Rel, Open,
- // Close, Punct, or Inner, for purposes of spacing and line breaking. An
- // |ord_noad|, |op_noad|, |bin_noad|, |rel_noad|, |open_noad|, |close_noad|,
- // |punct_noad|, or |inner_noad| is used to represent portions of the various
- // types. For example, an `\.=' sign in a formula leads to the creation of a
- // |rel_noad| whose |nucleus| field is a representation of an equals sign
- // (usually |fam=0|, |character=@'75|). A formula preceded by \.[\\mathrel]
- // also results in a |rel_noad|. When a |rel_noad| is followed by an
- // |op_noad|, say, and possibly separated by one or more ordinary nodes (not
- // noads), \TeX\ will insert a penalty node (with the current |rel_penalty|)
- // just after the formula that corresponds to the |rel_noad|, unless there
- // already was a penalty immediately following; and a ``thick space'' will be
- // inserted just before the formula that corresponds to the |op_noad|.
- //
- // A noad of type |ord_noad|, |op_noad|, \dots, |inner_noad| usually
- // has a |subtype=normal|. The only exception is that an |op_noad| might
- // have |subtype=limits| or |no_limits|, if the normal positioning of
- // limits has been overridden for this operator.
- // 683.
- // tangle:pos tex.web:13457:1:
- // A |radical_noad| is five words long; the fifth word is the |left_delimiter|
- // field, which usually represents a square root sign.
- //
- // A |fraction_noad| is six words long; it has a |right_delimiter| field
- // as well as a |left_delimiter|.
- //
- // Delimiter fields are of type |four_quarters|, and they have four subfields
- // called |small_fam|, |small_char|, |large_fam|, |large_char|. These subfields
- // represent variable-size delimiters by giving the ``small'' and ``large''
- // starting characters, as explained in Chapter~17 of [\sl The \TeX book].
- // \xref[TeXbook][\sl The \TeX book]
- //
- // A |fraction_noad| is actually quite different from all other noads. Not
- // only does it have six words, it has |thickness|, |denominator|, and
- // |numerator| fields instead of |nucleus|, |subscr|, and |supscr|. The
- // |thickness| is a scaled value that tells how thick to make a fraction
- // rule; however, the special value |default_code| is used to stand for the
- // |default_rule_thickness| of the current size. The |numerator| and
- // |denominator| point to mlists that define a fraction; we always have
- // $$\hbox[|math_type(numerator)=math_type(denominator)=sub_mlist|].$$ The
- // |left_delimiter| and |right_delimiter| fields specify delimiters that will
- // be placed at the left and right of the fraction. In this way, a
- // |fraction_noad| is able to represent all of \TeX's operators \.[\\over],
- // \.[\\atop], \.[\\above], \.[\\overwithdelims], \.[\\atopwithdelims], and
- // \.[\\abovewithdelims].
- // 686.
- // tangle:pos tex.web:13511:1:
- // The |new_noad| function creates an |ord_noad| that is completely null.
- func (prg *prg) newNoad() (r halfword) {
- var (
- p halfword
- )
- p = prg.getNode(noadSize)
- *(*prg.mem[p].hh()).b0() = byte(ordNoad)
- *(*prg.mem[p].hh()).b1() = byte(normal)
- *prg.mem[int32(p)+1].hh() = prg.emptyField
- *prg.mem[int32(p)+3].hh() = prg.emptyField
- *prg.mem[int32(p)+2].hh() = prg.emptyField
- r = p
- return r
- }
- // 687.
- // tangle:pos tex.web:13523:1:
- // A few more kinds of noads will complete the set: An |under_noad| has its
- // nucleus underlined; an |over_noad| has it overlined. An |accent_noad| places
- // an accent over its nucleus; the accent character appears as
- // |fam(accent_chr(p))| and |character(accent_chr(p))|. A |vcenter_noad|
- // centers its nucleus vertically with respect to the axis of the formula;
- // in such noads we always have |math_type(nucleus(p))=sub_box|.
- //
- // And finally, we have |left_noad| and |right_noad| types, to implement
- // \TeX's \.[\\left] and \.[\\right]. The |nucleus| of such noads is
- // replaced by a |delimiter| field; thus, for example, `\.[\\left(]' produces
- // a |left_noad| such that |delimiter(p)| holds the family and character
- // codes for all left parentheses. A |left_noad| never appears in an mlist
- // except as the first element, and a |right_noad| never appears in an mlist
- // except as the last element; furthermore, we either have both a |left_noad|
- // and a |right_noad|, or neither one is present. The |subscr| and |supscr|
- // fields are always |empty| in a |left_noad| and a |right_noad|.
- // 688.
- // tangle:pos tex.web:13551:1:
- // Math formulas can also contain instructions like \.[\\textstyle] that
- // override \TeX's normal style rules. A |style_node| is inserted into the
- // data structure to record such instructions; it is three words long, so it
- // is considered a node instead of a noad. The |subtype| is either |display_style|
- // or |text_style| or |script_style| or |script_script_style|. The
- // second and third words of a |style_node| are not used, but they are
- // present because a |choice_node| is converted to a |style_node|.
- //
- // \TeX\ uses even numbers 0, 2, 4, 6 to encode the basic styles
- // |display_style|, \dots, |script_script_style|, and adds~1 to get the
- // “cramped” versions of these styles. This gives a numerical order that
- // is backwards from the convention of Appendix~G in [\sl The \TeX book\/];
- // i.e., a smaller style has a larger numerical value.
- // \xref[TeXbook][\sl The \TeX book]
- func (prg *prg) newStyle(s smallNumber) (r halfword) { // create a style node
- var (
- p halfword // the new node
- )
- p = prg.getNode(styleNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(styleNode)
- *(*prg.mem[p].hh()).b1() = s
- *prg.mem[int32(p)+widthOffset].int() = 0
- *prg.mem[int32(p)+depthOffset].int() = 0 // the |width| and |depth| are not used
- r = p
- return r
- }
- // 689.
- // tangle:pos tex.web:13581:1:
- // Finally, the \.[\\mathchoice] primitive creates a |choice_node|, which
- // has special subfields |display_mlist|, |text_mlist|, |script_mlist|,
- // and |script_script_mlist| pointing to the mlists for each style.
- func (prg *prg) newChoice() (r halfword) { // create a choice node
- var (
- p halfword // the new node
- )
- p = prg.getNode(styleNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(choiceNode)
- *(*prg.mem[p].hh()).b1() = 0 // the |subtype| is not used
- *(*prg.mem[int32(p)+1].hh()).lh() = 0
- *(*prg.mem[int32(p)+1].hh()).rh() = 0
- *(*prg.mem[int32(p)+2].hh()).lh() = 0
- *(*prg.mem[int32(p)+2].hh()).rh() = 0
- r = p
- return r
- }
- func (prg *prg) showInfo() {
- prg.showNodeList(int32(*(*prg.mem[prg.tempPtr].hh()).lh()))
- }
- // 700.
- // tangle:pos tex.web:13804:1:
- // Before an mlist is converted to an hlist, \TeX\ makes sure that
- // the fonts in family~2 have enough parameters to be math-symbol
- // fonts, and that the fonts in family~3 have enough parameters to be
- // math-extension fonts. The math-symbol parameters are referred to by using the
- // following macros, which take a size code as their parameter; for example,
- // |num1(cur_size)| gives the value of the |num1| parameter for the current size.
- // \xref[parameters for symbols]
- // \xref[font parameters]
- // 701.
- // tangle:pos tex.web:13835:1:
- // The math-extension parameters have similar macros, but the size code is
- // omitted (since it is always |cur_size| when we refer to such parameters).
- // \xref[parameters for symbols]
- // \xref[font parameters]
- // 702.
- // tangle:pos tex.web:13849:1:
- // We also need to compute the change in style between mlists and their
- // subsidiaries. The following macros define the subsidiary style for
- // an overlined nucleus (|cramped_style|), for a subscript or a superscript
- // (|sub_style| or |sup_style|), or for a numerator or denominator (|num_style|
- // or |denom_style|).
- // 704.
- // tangle:pos tex.web:13870:1:
- // Here is a function that returns a pointer to a rule node having a given
- // thickness |t|. The rule will extend horizontally to the boundary of the vlist
- // that eventually contains it.
- func (prg *prg) fractionRule(t scaled) (r halfword) {
- // construct the bar for a fraction
- var (
- p halfword // the new node
- )
- p = prg.newRule()
- *prg.mem[int32(p)+heightOffset].int() = t
- *prg.mem[int32(p)+depthOffset].int() = 0
- r = p
- return r
- }
- // 705.
- // tangle:pos tex.web:13880:1:
- // The |overbar| function returns a pointer to a vlist box that consists of
- // a given box |b|, above which has been placed a kern of height |k| under a
- // fraction rule of thickness |t| under additional space of height |t|.
- func (prg *prg) overbar(b halfword, k, t scaled) (r halfword) {
- var (
- p, q halfword // nodes being constructed
- )
- p = prg.newKern(k)
- *(*prg.mem[p].hh()).rh() = b
- q = prg.fractionRule(t)
- *(*prg.mem[q].hh()).rh() = p
- p = prg.newKern(t)
- *(*prg.mem[p].hh()).rh() = q
- r = prg.vpackage(p, scaled(0), smallNumber(additional), scaled(07777777777))
- return r
- }
- // 706.
- // tangle:pos tex.web:13890:1:
- // The |var_delimiter| function, which finds or constructs a sufficiently
- // large delimiter, is the most interesting of the auxiliary functions that
- // currently concern us. Given a pointer |d| to a delimiter field in some noad,
- // together with a size code |s| and a vertical distance |v|, this function
- // returns a pointer to a box that contains the smallest variant of |d| whose
- // height plus depth is |v| or more. (And if no variant is large enough, it
- // returns the largest available variant.) In particular, this routine will
- // construct arbitrarily large delimiters from extensible components, if
- // |d| leads to such characters.
- //
- // The value returned is a box whose |shift_amount| has been set so that
- // the box is vertically centered with respect to the axis in the given size.
- // If a built-up symbol is returned, the height of the box before shifting
- // will be the height of its topmost component.
- // \4
- // Declare subprocedures for |var_delimiter|
- func (prg *prg) charBox(f internalFontNumber, c quarterword) (r halfword) {
- var (
- q fourQuarters
- hd eightBits // |height_depth| byte
- b, p halfword // the new box and its character node
- )
- q = *prg.fontInfo[prg.charBase[f]+int32(c)].qqqq()
- hd = byte(int32(q.b1) - minQuarterword)
- b = prg.newNullBox()
- *prg.mem[int32(b)+widthOffset].int() = *prg.fontInfo[prg.widthBase[f]+int32(q.b0)].int() + *prg.fontInfo[prg.italicBase[f]+(int32(q.b2)-minQuarterword)/4].int()
- *prg.mem[int32(b)+heightOffset].int() = *prg.fontInfo[prg.heightBase[f]+int32(hd)/16].int()
- *prg.mem[int32(b)+depthOffset].int() = *prg.fontInfo[prg.depthBase[f]+int32(hd)%16].int()
- p = prg.getAvail()
- *(*prg.mem[p].hh()).b1() = c
- *(*prg.mem[p].hh()).b0() = f
- *(*prg.mem[int32(b)+listOffset].hh()).rh() = p
- r = b
- return r
- }
- func (prg *prg) stackIntoBox(b halfword, f internalFontNumber,
- c quarterword) {
- var (
- p halfword // new node placed into |b|
- )
- p = prg.charBox(f, c)
- *(*prg.mem[p].hh()).rh() = *(*prg.mem[int32(b)+listOffset].hh()).rh()
- *(*prg.mem[int32(b)+listOffset].hh()).rh() = p
- *prg.mem[int32(b)+heightOffset].int() = *prg.mem[int32(p)+heightOffset].int()
- }
- func (prg *prg) heightPlusDepth(f internalFontNumber, c quarterword) (r scaled) {
- var (
- q fourQuarters
- hd eightBits // |height_depth| byte
- )
- q = *prg.fontInfo[prg.charBase[f]+int32(c)].qqqq()
- hd = byte(int32(q.b1) - minQuarterword)
- r = *prg.fontInfo[prg.heightBase[f]+int32(hd)/16].int() + *prg.fontInfo[prg.depthBase[f]+int32(hd)%16].int()
- return r
- }
- func (prg *prg) varDelimiter(d halfword, s smallNumber, v scaled) (r halfword) {
- var (
- b halfword // the box that will be constructed
- f, g internalFontNumber // best-so-far and tentative font codes
- c, x, y quarterword // best-so-far and tentative character codes
- m, n int32 // the number of extensible pieces
- u scaled // height-plus-depth of a tentative character
- w scaled // largest height-plus-depth so far
- q fourQuarters // character info
- hd eightBits // height-depth byte
- r1 fourQuarters // extensible pieces
- z smallNumber // runs through font family members
- largeAttempt bool // are we trying the ``large'' variant?
- )
- f = byte(fontBase)
- w = 0
- largeAttempt = false
- z = (*prg.mem[d].qqqq()).b0
- x = (*prg.mem[d].qqqq()).b1
- for true {
- if int32(z) != 0 || int32(x) != minQuarterword {
- z = byte(int32(z) + int32(s) + 16)
- for {
- z = byte(int32(z) - 16)
- g = byte(*(*prg.eqtb[mathFontBase+int32(z)-1].hh()).rh())
- if int32(g) != fontBase {
- y = x
- if int32(y)-minQuarterword >= int32(prg.fontBc[g]) && int32(y)-minQuarterword <= int32(prg.fontEc[g]) {
- continue1:
- q = *prg.fontInfo[prg.charBase[g]+int32(y)].qqqq()
- if int32(q.b0) > minQuarterword {
- if (int32(q.b2)-minQuarterword)%4 == extTag {
- f = g
- c = y
- goto found
- }
- hd = byte(int32(q.b1) - minQuarterword)
- u = *prg.fontInfo[prg.heightBase[g]+int32(hd)/16].int() + *prg.fontInfo[prg.depthBase[g]+int32(hd)%16].int()
- if u > w {
- f = g
- c = y
- w = u
- if u >= v {
- goto found
- }
- }
- if (int32(q.b2)-minQuarterword)%4 == listTag {
- y = q.b3
- goto continue1
- }
- }
- }
- }
- if int32(z) < 16 {
- break
- }
- }
- }
- if largeAttempt {
- goto found
- } // there were none large enough
- largeAttempt = true
- z = (*prg.mem[d].qqqq()).b2
- x = (*prg.mem[d].qqqq()).b3
- }
- found:
- if int32(f) != fontBase {
- if (int32(q.b2)-minQuarterword)%4 == extTag {
- b = prg.newNullBox()
- *(*prg.mem[b].hh()).b0() = byte(vlistNode)
- r1 = *prg.fontInfo[prg.extenBase[f]+int32(q.b3)].qqqq()
- // Compute the minimum suitable height, |w|, and the corresponding number of extension steps, |n|; also set |width(b)|
- c = r1.b3
- u = prg.heightPlusDepth(f, c)
- w = 0
- q = *prg.fontInfo[prg.charBase[f]+int32(c)].qqqq()
- *prg.mem[int32(b)+widthOffset].int() = *prg.fontInfo[prg.widthBase[f]+int32(q.b0)].int() + *prg.fontInfo[prg.italicBase[f]+(int32(q.b2)-minQuarterword)/4].int()
- c = r1.b2
- if int32(c) != minQuarterword {
- w = w + prg.heightPlusDepth(f, c)
- }
- c = r1.b1
- if int32(c) != minQuarterword {
- w = w + prg.heightPlusDepth(f, c)
- }
- c = r1.b0
- if int32(c) != minQuarterword {
- w = w + prg.heightPlusDepth(f, c)
- }
- n = 0
- if u > 0 {
- for w < v {
- w = w + u
- n = n + 1
- if int32(r1.b1) != minQuarterword {
- w = w + u
- }
- }
- }
- c = r1.b2
- if int32(c) != minQuarterword {
- prg.stackIntoBox(b, f, c)
- }
- c = r1.b3
- for ii := int32(1); ii <= n; ii++ {
- m = ii
- _ = m
- prg.stackIntoBox(b, f, c)
- }
- c = r1.b1
- if int32(c) != minQuarterword {
- prg.stackIntoBox(b, f, c)
- c = r1.b3
- for ii := int32(1); ii <= n; ii++ {
- m = ii
- _ = m
- prg.stackIntoBox(b, f, c)
- }
- }
- c = r1.b0
- if int32(c) != minQuarterword {
- prg.stackIntoBox(b, f, c)
- }
- *prg.mem[int32(b)+depthOffset].int() = w - *prg.mem[int32(b)+heightOffset].int()
- } else {
- b = prg.charBox(f, c)
- }
- } else {
- b = prg.newNullBox()
- *prg.mem[int32(b)+widthOffset].int() = *prg.eqtb[dimenBase+nullDelimiterSpaceCode-1].int() // use this width if no delimiter was found
- }
- *prg.mem[int32(b)+4].int() = prg.half(*prg.mem[int32(b)+heightOffset].int()-*prg.mem[int32(b)+depthOffset].int()) - *prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(s)-1].hh()).rh()]].int()
- r = b
- return r
- }
- // 715.
- // tangle:pos tex.web:14059:1:
- // The next subroutine is much simpler; it is used for numerators and
- // denominators of fractions as well as for displayed operators and
- // their limits above and below. It takes a given box~|b| and
- // changes it so that the new box is centered in a box of width~|w|.
- // The centering is done by putting \.[\\hss] glue at the left and right
- // of the list inside |b|, then packaging the new box; thus, the
- // actual box might not really be centered, if it already contains
- // infinite glue.
- //
- // The given box might contain a single character whose italic correction
- // has been added to the width of the box; in this case a compensating
- // kern is inserted.
- func (prg *prg) rebox(b halfword, w scaled) (r halfword) {
- var (
- p halfword // temporary register for list manipulation
- f internalFontNumber // font in a one-character box
- v scaled // width of a character without italic correction
- )
- if *prg.mem[int32(b)+widthOffset].int() != w && int32(*(*prg.mem[int32(b)+listOffset].hh()).rh()) != 0 {
- if int32(*(*prg.mem[b].hh()).b0()) == vlistNode {
- b = prg.hpack(b, scaled(0), smallNumber(additional))
- }
- p = *(*prg.mem[int32(b)+listOffset].hh()).rh()
- if int32(p) >= int32(prg.hiMemMin) && int32(*(*prg.mem[p].hh()).rh()) == 0 {
- f = *(*prg.mem[p].hh()).b0()
- v = *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()).b0)].int()
- if v != *prg.mem[int32(b)+widthOffset].int() {
- *(*prg.mem[p].hh()).rh() = prg.newKern(*prg.mem[int32(b)+widthOffset].int() - v)
- }
- }
- prg.freeNode(b, halfword(boxNodeSize))
- b = prg.newGlue(halfword(memBot + glueSpecSize + glueSpecSize + glueSpecSize))
- *(*prg.mem[b].hh()).rh() = p
- for int32(*(*prg.mem[p].hh()).rh()) != 0 {
- p = *(*prg.mem[p].hh()).rh()
- }
- *(*prg.mem[p].hh()).rh() = prg.newGlue(halfword(memBot + glueSpecSize + glueSpecSize + glueSpecSize))
- r = prg.hpack(b, w, smallNumber(exactly))
- } else {
- *prg.mem[int32(b)+widthOffset].int() = w
- r = b
- }
- return r
- }
- // 716.
- // tangle:pos tex.web:14093:1:
- // Here is a subroutine that creates a new glue specification from another
- // one that is expressed in `\.[mu]', given the value of the math unit.
- func (prg *prg) mathGlue(g halfword, m scaled) (r halfword) {
- var (
- p halfword // the new glue specification
- n int32 // integer part of |m|
- f scaled // fraction part of |m|
- )
- n = prg.xOverN(m, 0200000)
- f = prg.remainder
- if f < 0 {
- n = n - 1
- f = f + 0200000
- }
- p = prg.getNode(glueSpecSize)
- *prg.mem[int32(p)+widthOffset].int() = prg.multAndAdd(n, *prg.mem[int32(g)+widthOffset].int(), prg.xnOverD(*prg.mem[int32(g)+widthOffset].int(), f, 0200000), scaled(07777777777)) // convert \.[mu] to \.[pt]
- *(*prg.mem[p].hh()).b0() = *(*prg.mem[g].hh()).b0()
- if int32(*(*prg.mem[p].hh()).b0()) == normal {
- *prg.mem[int32(p)+2].int() = prg.multAndAdd(n, *prg.mem[int32(g)+2].int(), prg.xnOverD(*prg.mem[int32(g)+2].int(), f, 0200000), scaled(07777777777))
- } else {
- *prg.mem[int32(p)+2].int() = *prg.mem[int32(g)+2].int()
- }
- *(*prg.mem[p].hh()).b1() = *(*prg.mem[g].hh()).b1()
- if int32(*(*prg.mem[p].hh()).b1()) == normal {
- *prg.mem[int32(p)+3].int() = prg.multAndAdd(n, *prg.mem[int32(g)+3].int(), prg.xnOverD(*prg.mem[int32(g)+3].int(), f, 0200000), scaled(07777777777))
- } else {
- *prg.mem[int32(p)+3].int() = *prg.mem[int32(g)+3].int()
- }
- r = p
- return r
- }
- // 717.
- // tangle:pos tex.web:14117:1:
- // The |math_kern| subroutine removes |mu_glue| from a kern node, given
- // the value of the math unit.
- func (prg *prg) mathKern(p halfword, m scaled) {
- var (
- n int32 // integer part of |m|
- f scaled // fraction part of |m|
- )
- if int32(*(*prg.mem[p].hh()).b1()) == muGlue {
- n = prg.xOverN(m, 0200000)
- f = prg.remainder
- if f < 0 {
- n = n - 1
- f = f + 0200000
- }
- *prg.mem[int32(p)+widthOffset].int() = prg.multAndAdd(n, *prg.mem[int32(p)+widthOffset].int(), prg.xnOverD(*prg.mem[int32(p)+widthOffset].int(), f, 0200000), scaled(07777777777))
- *(*prg.mem[p].hh()).b1() = byte(explicit)
- }
- }
- // 718.
- // tangle:pos tex.web:14132:1:
- // Sometimes it is necessary to destroy an mlist. The following
- // subroutine empties the current list, assuming that |abs(mode)=mmode|.
- func (prg *prg) flushMath() {
- prg.flushNodeList(*(*prg.mem[prg.curList.headField].hh()).rh())
- prg.flushNodeList(halfword(*prg.curList.auxField.int()))
- *(*prg.mem[prg.curList.headField].hh()).rh() = 0
- prg.curList.tailField = prg.curList.headField
- *prg.curList.auxField.int() = 0
- } // \2
- func (prg *prg) cleanBox(p halfword, s smallNumber) (r halfword) {
- var (
- q halfword // beginning of a list to be boxed
- saveStyle smallNumber // |cur_style| to be restored
- x halfword // box to be returned
- r1 halfword // temporary pointer
- )
- switch *(*prg.mem[p].hh()).rh() {
- case mathChar:
- prg.curMlist = prg.newNoad()
- prg.mem[int32(prg.curMlist)+1] = prg.mem[p]
- case subBox:
- q = *(*prg.mem[p].hh()).lh()
- goto found
- case subMlist:
- prg.curMlist = *(*prg.mem[p].hh()).lh()
- default:
- q = prg.newNullBox()
- goto found
- }
- saveStyle = prg.curStyle
- prg.curStyle = s
- prg.mlistPenalties = false
- prg.mlistToHlist()
- q = *(*prg.mem[30000-3].hh()).rh() // recursive call
- prg.curStyle = saveStyle // restore the style
- // Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
- {
- if int32(prg.curStyle) < scriptStyle {
- prg.curSize = byte(textSize)
- } else {
- prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
- }
- prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
- }
- found:
- if int32(q) >= int32(prg.hiMemMin) || int32(q) == 0 {
- x = prg.hpack(q, scaled(0), smallNumber(additional))
- } else if int32(*(*prg.mem[q].hh()).rh()) == 0 && int32(*(*prg.mem[q].hh()).b0()) <= vlistNode && *prg.mem[int32(q)+4].int() == 0 {
- x = q
- } else {
- x = prg.hpack(q, scaled(0), smallNumber(additional))
- }
- // Simplify a trivial box
- q = *(*prg.mem[int32(x)+listOffset].hh()).rh()
- if int32(q) >= int32(prg.hiMemMin) {
- r1 = *(*prg.mem[q].hh()).rh()
- if int32(r1) != 0 {
- if int32(*(*prg.mem[r1].hh()).rh()) == 0 {
- if !(int32(r1) >= int32(prg.hiMemMin)) {
- if int32(*(*prg.mem[r1].hh()).b0()) == kernNode {
- prg.freeNode(r1, halfword(smallNodeSize))
- *(*prg.mem[q].hh()).rh() = 0
- }
- }
- }
- }
- }
- r = x
- return r
- }
- // 722.
- // tangle:pos tex.web:14212:1:
- // It is convenient to have a procedure that converts a |math_char|
- // field to an “unpacked” form. The |fetch| routine sets |cur_f|, |cur_c|,
- // and |cur_i| to the font code, character code, and character information bytes of
- // a given noad field. It also takes care of issuing error messages for
- // nonexistent characters; in such cases, |char_exists(cur_i)| will be |false|
- // after |fetch| has acted, and the field will also have been reset to |empty|.
- func (prg *prg) fetch(a halfword) {
- prg.curC = *(*prg.mem[a].hh()).b1()
- prg.curF = byte(*(*prg.eqtb[mathFontBase+int32(*(*prg.mem[a].hh()).b0())+int32(prg.curSize)-1].hh()).rh())
- if int32(prg.curF) == fontBase {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "" */ 338)
- }
- prg.printSize(int32(prg.curSize))
- prg.printChar(asciiCode(' '))
- prg.printInt(int32(*(*prg.mem[a].hh()).b0()))
- prg.print( /* " is undefined (character " */ 884)
- prg.print(int32(prg.curC) - minQuarterword)
- prg.printChar(asciiCode(')'))
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "Somewhere in the math formula just ended, you used the" */ 885
- prg.helpLine[2] = /* "stated character from an undefined font family. For example," */ 886
- prg.helpLine[1] = /* "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed," */ 887
- prg.helpLine[0] = /* "and I'll try to forget that I needed that character." */ 888
- }
- prg.error1()
- prg.curI = prg.nullCharacter
- *(*prg.mem[a].hh()).rh() = uint16(empty)
- } else {
- if int32(prg.curC)-minQuarterword >= int32(prg.fontBc[prg.curF]) && int32(prg.curC)-minQuarterword <= int32(prg.fontEc[prg.curF]) {
- prg.curI = *prg.fontInfo[prg.charBase[prg.curF]+int32(prg.curC)].qqqq()
- } else {
- prg.curI = prg.nullCharacter
- }
- if !(int32(prg.curI.b0) > minQuarterword) {
- prg.charWarning(prg.curF, eightBits(int32(prg.curC)-minQuarterword))
- *(*prg.mem[a].hh()).rh() = uint16(empty)
- prg.curI = prg.nullCharacter
- }
- }
- }
- // 725.
- // tangle:pos tex.web:14252:1:
- // We need to do a lot of different things, so |mlist_to_hlist| makes two
- // passes over the given mlist.
- //
- // The first pass does most of the processing: It removes ``mu'' spacing from
- // glue, it recursively evaluates all subsidiary mlists so that only the
- // top-level mlist remains to be handled, it puts fractions and square roots
- // and such things into boxes, it attaches subscripts and superscripts, and
- // it computes the overall height and depth of the top-level mlist so that
- // the size of delimiters for a |left_noad| and a |right_noad| will be known.
- // The hlist resulting from each noad is recorded in that noad's |new_hlist|
- // field, an integer field that replaces the |nucleus| or |thickness|.
- // \xref[recursion]
- //
- // The second pass eliminates all noads and inserts the correct glue and
- // penalties between nodes.
- // 726.
- // tangle:pos tex.web:14270:1:
- // Here is the overall plan of |mlist_to_hlist|, and the list of its
- // local variables.
- // \4
- // Declare math construction procedures
- func (prg *prg) makeOver(q halfword) {
- *(*prg.mem[int32(q)+1].hh()).lh() = prg.overbar(prg.cleanBox(halfword(int32(q)+1), smallNumber(2*(int32(prg.curStyle)/2)+cramped)),
- 3**prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int(), *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
- *(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
- }
- func (prg *prg) makeUnder(q halfword) {
- var (
- p, x, y halfword // temporary registers for box construction
- delta scaled // overall height plus depth
- )
- x = prg.cleanBox(halfword(int32(q)+1), prg.curStyle)
- p = prg.newKern(3 * *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
- *(*prg.mem[x].hh()).rh() = p
- *(*prg.mem[p].hh()).rh() = prg.fractionRule(*prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
- y = prg.vpackage(x, scaled(0), smallNumber(additional), scaled(07777777777))
- delta = *prg.mem[int32(y)+heightOffset].int() + *prg.mem[int32(y)+depthOffset].int() + *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
- *prg.mem[int32(y)+heightOffset].int() = *prg.mem[int32(x)+heightOffset].int()
- *prg.mem[int32(y)+depthOffset].int() = delta - *prg.mem[int32(y)+heightOffset].int()
- *(*prg.mem[int32(q)+1].hh()).lh() = y
- *(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
- }
- func (prg *prg) makeVcenter(q halfword) {
- var (
- v halfword // the box that should be centered vertically
- delta scaled // its height plus depth
- )
- v = *(*prg.mem[int32(q)+1].hh()).lh()
- if int32(*(*prg.mem[v].hh()).b0()) != vlistNode {
- prg.confusion(strNumber( /* "vcenter" */ 539))
- }
- // \xref[this can't happen vcenter][\quad vcenter]
- delta = *prg.mem[int32(v)+heightOffset].int() + *prg.mem[int32(v)+depthOffset].int()
- *prg.mem[int32(v)+heightOffset].int() = *prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() + prg.half(delta)
- *prg.mem[int32(v)+depthOffset].int() = delta - *prg.mem[int32(v)+heightOffset].int()
- }
- func (prg *prg) makeRadical(q halfword) {
- var (
- x, y halfword // temporary registers for box construction
- delta, clr scaled // dimensions involved in the calculation
- )
- x = prg.cleanBox(halfword(int32(q)+1), smallNumber(2*(int32(prg.curStyle)/2)+cramped))
- if int32(prg.curStyle) < textStyle {
- clr = *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() + abs(*prg.fontInfo[5+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int())/4
- } else {
- clr = *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
- clr = clr + abs(clr)/4
- }
- y = prg.varDelimiter(halfword(int32(q)+4), prg.curSize, *prg.mem[int32(x)+heightOffset].int()+*prg.mem[int32(x)+depthOffset].int()+clr+*prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
- delta = *prg.mem[int32(y)+depthOffset].int() - (*prg.mem[int32(x)+heightOffset].int() + *prg.mem[int32(x)+depthOffset].int() + clr)
- if delta > 0 {
- clr = clr + prg.half(delta)
- } // increase the actual clearance
- *prg.mem[int32(y)+4].int() = -(*prg.mem[int32(x)+heightOffset].int() + clr)
- *(*prg.mem[y].hh()).rh() = prg.overbar(x, clr, *prg.mem[int32(y)+heightOffset].int())
- *(*prg.mem[int32(q)+1].hh()).lh() = prg.hpack(y, scaled(0), smallNumber(additional))
- *(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
- }
- func (prg *prg) makeMathAccent(q halfword) {
- var (
- p, x, y halfword // temporary registers for box construction
- a int32 // address of lig/kern instruction
- c quarterword // accent character
- f internalFontNumber // its font
- i fourQuarters // its |char_info|
- s scaled // amount to skew the accent to the right
- h scaled // height of character being accented
- delta scaled // space to remove between accent and accentee
- w scaled // width of the accentee, not including sub/superscripts
- )
- prg.fetch(halfword(int32(q) + 4))
- if int32(prg.curI.b0) > minQuarterword {
- i = prg.curI
- c = prg.curC
- f = prg.curF
- // Compute the amount of skew
- s = 0
- if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathChar {
- prg.fetch(halfword(int32(q) + 1))
- if (int32(prg.curI.b2)-minQuarterword)%4 == ligTag {
- a = prg.ligKernBase[prg.curF] + int32(prg.curI.b3)
- prg.curI = *prg.fontInfo[a].qqqq()
- if int32(prg.curI.b0) > 128+minQuarterword {
- a = prg.ligKernBase[prg.curF] + 256*int32(prg.curI.b2) + int32(prg.curI.b3) + 32768 - 256*(128+minQuarterword)
- prg.curI = *prg.fontInfo[a].qqqq()
- }
- for true {
- if int32(prg.curI.b1)-minQuarterword == prg.skewChar[prg.curF] {
- if int32(prg.curI.b2) >= 128+minQuarterword {
- if int32(prg.curI.b0) <= 128+minQuarterword {
- s = *prg.fontInfo[prg.kernBase[prg.curF]+256*int32(prg.curI.b2)+int32(prg.curI.b3)].int()
- }
- }
- goto done1
- }
- if int32(prg.curI.b0) >= 128+minQuarterword {
- goto done1
- }
- a = a + int32(prg.curI.b0) - minQuarterword + 1
- prg.curI = *prg.fontInfo[a].qqqq()
- }
- }
- }
- done1:
- ;
- x = prg.cleanBox(halfword(int32(q)+1), smallNumber(2*(int32(prg.curStyle)/2)+cramped))
- w = *prg.mem[int32(x)+widthOffset].int()
- h = *prg.mem[int32(x)+heightOffset].int()
- // Switch to a larger accent if available and appropriate
- for true {
- if (int32(i.b2)-minQuarterword)%4 != listTag {
- goto done
- }
- y = uint16(i.b3)
- i = *prg.fontInfo[prg.charBase[f]+int32(y)].qqqq()
- if !(int32(i.b0) > minQuarterword) {
- goto done
- }
- if *prg.fontInfo[prg.widthBase[f]+int32(i.b0)].int() > w {
- goto done
- }
- c = byte(y)
- }
- done:
- ;
- if h < *prg.fontInfo[xHeightCode+prg.paramBase[f]].int() {
- delta = h
- } else {
- delta = *prg.fontInfo[xHeightCode+prg.paramBase[f]].int()
- }
- if int32(*(*prg.mem[int32(q)+2].hh()).rh()) != empty || int32(*(*prg.mem[int32(q)+3].hh()).rh()) != empty {
- if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathChar {
- prg.flushNodeList(x)
- x = prg.newNoad()
- prg.mem[int32(x)+1] = prg.mem[int32(q)+1]
- prg.mem[int32(x)+2] = prg.mem[int32(q)+2]
- prg.mem[int32(x)+3] = prg.mem[int32(q)+3]
- *prg.mem[int32(q)+2].hh() = prg.emptyField
- *prg.mem[int32(q)+3].hh() = prg.emptyField
- *(*prg.mem[int32(q)+1].hh()).rh() = uint16(subMlist)
- *(*prg.mem[int32(q)+1].hh()).lh() = x
- x = prg.cleanBox(halfword(int32(q)+1), prg.curStyle)
- delta = delta + *prg.mem[int32(x)+heightOffset].int() - h
- h = *prg.mem[int32(x)+heightOffset].int()
- }
- }
- y = prg.charBox(f, c)
- *prg.mem[int32(y)+4].int() = s + prg.half(w-*prg.mem[int32(y)+widthOffset].int())
- *prg.mem[int32(y)+widthOffset].int() = 0
- p = prg.newKern(-delta)
- *(*prg.mem[p].hh()).rh() = x
- *(*prg.mem[y].hh()).rh() = p
- y = prg.vpackage(y, scaled(0), smallNumber(additional), scaled(07777777777))
- *prg.mem[int32(y)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int()
- if *prg.mem[int32(y)+heightOffset].int() < h {
- p = prg.newKern(h - *prg.mem[int32(y)+heightOffset].int())
- *(*prg.mem[p].hh()).rh() = *(*prg.mem[int32(y)+listOffset].hh()).rh()
- *(*prg.mem[int32(y)+listOffset].hh()).rh() = p
- *prg.mem[int32(y)+heightOffset].int() = h
- }
- *(*prg.mem[int32(q)+1].hh()).lh() = y
- *(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
- }
- }
- func (prg *prg) makeFraction(q halfword) {
- var (
- p, v, x, y, z halfword // temporary registers for box construction
- delta, delta1, delta2, shiftUp, shiftDown, clr scaled
- // dimensions for box calculations
- )
- if *prg.mem[int32(q)+widthOffset].int() == 010000000000 {
- *prg.mem[int32(q)+widthOffset].int() = *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
- }
- // Create equal-width boxes |x| and |z| for the numerator and denominator, and compute the default amounts |shift_up| and |shift_down| by which they are displaced from the baseline
- x = prg.cleanBox(halfword(int32(q)+2), smallNumber(int32(prg.curStyle)+2-2*(int32(prg.curStyle)/6)))
- z = prg.cleanBox(halfword(int32(q)+3), smallNumber(2*(int32(prg.curStyle)/2)+cramped+2-2*(int32(prg.curStyle)/6)))
- if *prg.mem[int32(x)+widthOffset].int() < *prg.mem[int32(z)+widthOffset].int() {
- x = prg.rebox(x, *prg.mem[int32(z)+widthOffset].int())
- } else {
- z = prg.rebox(z, *prg.mem[int32(x)+widthOffset].int())
- }
- if int32(prg.curStyle) < textStyle {
- shiftUp = *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- shiftDown = *prg.fontInfo[11+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- } else {
- shiftDown = *prg.fontInfo[12+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- if *prg.mem[int32(q)+widthOffset].int() != 0 {
- shiftUp = *prg.fontInfo[9+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- } else {
- shiftUp = *prg.fontInfo[10+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- }
- }
- if *prg.mem[int32(q)+widthOffset].int() == 0 {
- if int32(prg.curStyle) < textStyle {
- clr = 7 * *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
- } else {
- clr = 3 * *prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
- }
- delta = prg.half(clr - (shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.mem[int32(z)+heightOffset].int() - shiftDown)))
- if delta > 0 {
- shiftUp = shiftUp + delta
- shiftDown = shiftDown + delta
- }
- } else {
- // Adjust \(s)|shift_up| and |shift_down| for the case of a fraction line
- if int32(prg.curStyle) < textStyle {
- clr = 3 * *prg.mem[int32(q)+widthOffset].int()
- } else {
- clr = *prg.mem[int32(q)+widthOffset].int()
- }
- delta = prg.half(*prg.mem[int32(q)+widthOffset].int())
- delta1 = clr - (shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() + delta))
- delta2 = clr - (*prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() - delta - (*prg.mem[int32(z)+heightOffset].int() - shiftDown))
- if delta1 > 0 {
- shiftUp = shiftUp + delta1
- }
- if delta2 > 0 {
- shiftDown = shiftDown + delta2
- }
- }
- // Construct a vlist box for the fraction, according to |shift_up| and |shift_down|
- v = prg.newNullBox()
- *(*prg.mem[v].hh()).b0() = byte(vlistNode)
- *prg.mem[int32(v)+heightOffset].int() = shiftUp + *prg.mem[int32(x)+heightOffset].int()
- *prg.mem[int32(v)+depthOffset].int() = *prg.mem[int32(z)+depthOffset].int() + shiftDown
- *prg.mem[int32(v)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int() // this also equals |width(z)|
- if *prg.mem[int32(q)+widthOffset].int() == 0 {
- p = prg.newKern(shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.mem[int32(z)+heightOffset].int() - shiftDown))
- *(*prg.mem[p].hh()).rh() = z
- } else {
- y = prg.fractionRule(*prg.mem[int32(q)+widthOffset].int())
- p = prg.newKern(*prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() - delta - (*prg.mem[int32(z)+heightOffset].int() - shiftDown))
- *(*prg.mem[y].hh()).rh() = p
- *(*prg.mem[p].hh()).rh() = z
- p = prg.newKern(shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() + delta))
- *(*prg.mem[p].hh()).rh() = y
- }
- *(*prg.mem[x].hh()).rh() = p
- *(*prg.mem[int32(v)+listOffset].hh()).rh() = x
- // Put the \(f)fraction into a box with its delimiters, and make |new_hlist(q)| point to it
- if int32(prg.curStyle) < textStyle {
- delta = *prg.fontInfo[20+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- } else {
- delta = *prg.fontInfo[21+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- }
- x = prg.varDelimiter(halfword(int32(q)+4), prg.curSize, delta)
- *(*prg.mem[x].hh()).rh() = v
- z = prg.varDelimiter(halfword(int32(q)+5), prg.curSize, delta)
- *(*prg.mem[v].hh()).rh() = z
- *prg.mem[int32(q)+1].int() = int32(prg.hpack(x, scaled(0), smallNumber(additional)))
- }
- func (prg *prg) makeOp(q halfword) (r scaled) {
- var (
- delta scaled // offset between subscript and superscript
- p, v, x, y, z halfword // temporary registers for box construction
- c quarterword
- i fourQuarters // registers for character examination
- shiftUp, shiftDown scaled // dimensions for box calculation
- )
- if int32(*(*prg.mem[q].hh()).b1()) == normal && int32(prg.curStyle) < textStyle {
- *(*prg.mem[q].hh()).b1() = byte(limits)
- }
- if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathChar {
- prg.fetch(halfword(int32(q) + 1))
- if int32(prg.curStyle) < textStyle && (int32(prg.curI.b2)-minQuarterword)%4 == listTag {
- c = prg.curI.b3
- i = *prg.fontInfo[prg.charBase[prg.curF]+int32(c)].qqqq()
- if int32(i.b0) > minQuarterword {
- prg.curC = c
- prg.curI = i
- *(*prg.mem[int32(q)+1].hh()).b1() = c
- }
- }
- delta = *prg.fontInfo[prg.italicBase[prg.curF]+(int32(prg.curI.b2)-minQuarterword)/4].int()
- x = prg.cleanBox(halfword(int32(q)+1), prg.curStyle)
- if int32(*(*prg.mem[int32(q)+3].hh()).rh()) != empty && int32(*(*prg.mem[q].hh()).b1()) != limits {
- *prg.mem[int32(x)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int() - delta
- } // remove italic correction
- *prg.mem[int32(x)+4].int() = prg.half(*prg.mem[int32(x)+heightOffset].int()-*prg.mem[int32(x)+depthOffset].int()) - *prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- // center vertically
- *(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
- *(*prg.mem[int32(q)+1].hh()).lh() = x
- } else {
- delta = 0
- }
- if int32(*(*prg.mem[q].hh()).b1()) == limits {
- x = prg.cleanBox(halfword(int32(q)+2), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+int32(prg.curStyle)%2))
- y = prg.cleanBox(halfword(int32(q)+1), prg.curStyle)
- z = prg.cleanBox(halfword(int32(q)+3), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+cramped))
- v = prg.newNullBox()
- *(*prg.mem[v].hh()).b0() = byte(vlistNode)
- *prg.mem[int32(v)+widthOffset].int() = *prg.mem[int32(y)+widthOffset].int()
- if *prg.mem[int32(x)+widthOffset].int() > *prg.mem[int32(v)+widthOffset].int() {
- *prg.mem[int32(v)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int()
- }
- if *prg.mem[int32(z)+widthOffset].int() > *prg.mem[int32(v)+widthOffset].int() {
- *prg.mem[int32(v)+widthOffset].int() = *prg.mem[int32(z)+widthOffset].int()
- }
- x = prg.rebox(x, *prg.mem[int32(v)+widthOffset].int())
- y = prg.rebox(y, *prg.mem[int32(v)+widthOffset].int())
- z = prg.rebox(z, *prg.mem[int32(v)+widthOffset].int())
- *prg.mem[int32(x)+4].int() = prg.half(delta)
- *prg.mem[int32(z)+4].int() = -*prg.mem[int32(x)+4].int()
- *prg.mem[int32(v)+heightOffset].int() = *prg.mem[int32(y)+heightOffset].int()
- *prg.mem[int32(v)+depthOffset].int() = *prg.mem[int32(y)+depthOffset].int()
- // Attach the limits to |y| and adjust |height(v)|, |depth(v)| to account for their presence
- if int32(*(*prg.mem[int32(q)+2].hh()).rh()) == empty {
- prg.freeNode(x, halfword(boxNodeSize))
- *(*prg.mem[int32(v)+listOffset].hh()).rh() = y
- } else {
- shiftUp = *prg.fontInfo[11+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() - *prg.mem[int32(x)+depthOffset].int()
- if shiftUp < *prg.fontInfo[9+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() {
- shiftUp = *prg.fontInfo[9+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
- }
- p = prg.newKern(shiftUp)
- *(*prg.mem[p].hh()).rh() = y
- *(*prg.mem[x].hh()).rh() = p
- p = prg.newKern(*prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
- *(*prg.mem[p].hh()).rh() = x
- *(*prg.mem[int32(v)+listOffset].hh()).rh() = p
- *prg.mem[int32(v)+heightOffset].int() = *prg.mem[int32(v)+heightOffset].int() + *prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() + *prg.mem[int32(x)+heightOffset].int() + *prg.mem[int32(x)+depthOffset].int() + shiftUp
- }
- if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty {
- prg.freeNode(z, halfword(boxNodeSize))
- } else {
- shiftDown = *prg.fontInfo[12+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() - *prg.mem[int32(z)+heightOffset].int()
- if shiftDown < *prg.fontInfo[10+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() {
- shiftDown = *prg.fontInfo[10+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int()
- }
- p = prg.newKern(shiftDown)
- *(*prg.mem[y].hh()).rh() = p
- *(*prg.mem[p].hh()).rh() = z
- p = prg.newKern(*prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int())
- *(*prg.mem[z].hh()).rh() = p
- *prg.mem[int32(v)+depthOffset].int() = *prg.mem[int32(v)+depthOffset].int() + *prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() + *prg.mem[int32(z)+heightOffset].int() + *prg.mem[int32(z)+depthOffset].int() + shiftDown
- }
- *prg.mem[int32(q)+1].int() = int32(v)
- }
- r = delta
- return r
- }
- func (prg *prg) makeOrd(q halfword) {
- var (
- a int32 // address of lig/kern instruction
- p, r1 halfword // temporary registers for list manipulation
- )
- restart:
- if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty {
- if int32(*(*prg.mem[int32(q)+2].hh()).rh()) == empty {
- if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathChar {
- p = *(*prg.mem[q].hh()).rh()
- if int32(p) != 0 {
- if int32(*(*prg.mem[p].hh()).b0()) >= ordNoad && int32(*(*prg.mem[p].hh()).b0()) <= punctNoad {
- if int32(*(*prg.mem[int32(p)+1].hh()).rh()) == mathChar {
- if int32(*(*prg.mem[int32(p)+1].hh()).b0()) == int32(*(*prg.mem[int32(q)+1].hh()).b0()) {
- *(*prg.mem[int32(q)+1].hh()).rh() = uint16(mathTextChar)
- prg.fetch(halfword(int32(q) + 1))
- if (int32(prg.curI.b2)-minQuarterword)%4 == ligTag {
- a = prg.ligKernBase[prg.curF] + int32(prg.curI.b3)
- prg.curC = *(*prg.mem[int32(p)+1].hh()).b1()
- prg.curI = *prg.fontInfo[a].qqqq()
- if int32(prg.curI.b0) > 128+minQuarterword {
- a = prg.ligKernBase[prg.curF] + 256*int32(prg.curI.b2) + int32(prg.curI.b3) + 32768 - 256*(128+minQuarterword)
- prg.curI = *prg.fontInfo[a].qqqq()
- }
- for true {
- if int32(prg.curI.b1) == int32(prg.curC) {
- if int32(prg.curI.b0) <= 128+minQuarterword {
- if int32(prg.curI.b2) >= 128+minQuarterword {
- p = prg.newKern(*prg.fontInfo[prg.kernBase[prg.curF]+256*int32(prg.curI.b2)+int32(prg.curI.b3)].int())
- *(*prg.mem[p].hh()).rh() = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = p
- goto exit
- } else {
- {
- if prg.interrupt != 0 {
- prg.pauseForInstructions()
- }
- } // allow a way out of infinite ligature loop
- switch prg.curI.b2 {
- case 1 + minQuarterword, 5 + minQuarterword:
- *(*prg.mem[int32(q)+1].hh()).b1() = prg.curI.b3 // \.[=:\?], \.[=:\?>]
- case 2 + minQuarterword, 6 + minQuarterword:
- *(*prg.mem[int32(p)+1].hh()).b1() = prg.curI.b3 // \.[\?=:], \.[\?=:>]
- case 3 + minQuarterword, 7 + minQuarterword, 11 + minQuarterword:
- r1 = prg.newNoad() // \.[\?=:\?], \.[\?=:\?>], \.[\?=:\?>>]
- *(*prg.mem[int32(r1)+1].hh()).b1() = prg.curI.b3
- *(*prg.mem[int32(r1)+1].hh()).b0() = *(*prg.mem[int32(q)+1].hh()).b0()
- *(*prg.mem[q].hh()).rh() = r1
- *(*prg.mem[r1].hh()).rh() = p
- if int32(prg.curI.b2) < 11+minQuarterword {
- *(*prg.mem[int32(r1)+1].hh()).rh() = uint16(mathChar)
- } else {
- *(*prg.mem[int32(r1)+1].hh()).rh() = uint16(mathTextChar)
- } // prevent combination
- default:
- *(*prg.mem[q].hh()).rh() = *(*prg.mem[p].hh()).rh()
- *(*prg.mem[int32(q)+1].hh()).b1() = prg.curI.b3 // \.[=:]
- prg.mem[int32(q)+3] = prg.mem[int32(p)+3]
- prg.mem[int32(q)+2] = prg.mem[int32(p)+2]
- prg.freeNode(p, halfword(noadSize))
- }
- if int32(prg.curI.b2) > 3+minQuarterword {
- goto exit
- }
- *(*prg.mem[int32(q)+1].hh()).rh() = uint16(mathChar)
- goto restart
- }
- }
- }
- if int32(prg.curI.b0) >= 128+minQuarterword {
- goto exit
- }
- a = a + int32(prg.curI.b0) - minQuarterword + 1
- prg.curI = *prg.fontInfo[a].qqqq()
- }
- }
- }
- }
- }
- }
- }
- }
- }
- exit:
- }
- func (prg *prg) makeScripts(q halfword, delta scaled) {
- var (
- p, x, y, z halfword // temporary registers for box construction
- shiftUp, shiftDown, clr scaled // dimensions in the calculation
- t smallNumber // subsidiary size code
- )
- p = uint16(*prg.mem[int32(q)+1].int())
- if int32(p) >= int32(prg.hiMemMin) {
- shiftUp = 0
- shiftDown = 0
- } else {
- z = prg.hpack(p, scaled(0), smallNumber(additional))
- if int32(prg.curStyle) < scriptStyle {
- t = byte(scriptSize)
- } else {
- t = byte(scriptScriptSize)
- }
- shiftUp = *prg.mem[int32(z)+heightOffset].int() - *prg.fontInfo[18+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(t)-1].hh()).rh()]].int()
- shiftDown = *prg.mem[int32(z)+depthOffset].int() + *prg.fontInfo[19+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(t)-1].hh()).rh()]].int()
- prg.freeNode(z, halfword(boxNodeSize))
- }
- if int32(*(*prg.mem[int32(q)+2].hh()).rh()) == empty {
- x = prg.cleanBox(halfword(int32(q)+3), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+cramped))
- *prg.mem[int32(x)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int() + *prg.eqtb[dimenBase+scriptSpaceCode-1].int()
- if shiftDown < *prg.fontInfo[16+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() {
- shiftDown = *prg.fontInfo[16+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- }
- clr = *prg.mem[int32(x)+heightOffset].int() - abs(*prg.fontInfo[5+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()*4)/5
- if shiftDown < clr {
- shiftDown = clr
- }
- *prg.mem[int32(x)+4].int() = shiftDown
- } else {
- {
- x = prg.cleanBox(halfword(int32(q)+2), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+int32(prg.curStyle)%2))
- *prg.mem[int32(x)+widthOffset].int() = *prg.mem[int32(x)+widthOffset].int() + *prg.eqtb[dimenBase+scriptSpaceCode-1].int()
- if prg.curStyle&1 != 0 {
- clr = *prg.fontInfo[15+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- } else if int32(prg.curStyle) < textStyle {
- clr = *prg.fontInfo[13+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- } else {
- clr = *prg.fontInfo[14+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- }
- if shiftUp < clr {
- shiftUp = clr
- }
- clr = *prg.mem[int32(x)+depthOffset].int() + abs(*prg.fontInfo[5+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int())/4
- if shiftUp < clr {
- shiftUp = clr
- }
- }
- if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty {
- *prg.mem[int32(x)+4].int() = -shiftUp
- } else {
- // Construct a sub/superscript combination box |x|, with the superscript offset by |delta|
- y = prg.cleanBox(halfword(int32(q)+3), smallNumber(2*(int32(prg.curStyle)/4)+scriptStyle+cramped))
- *prg.mem[int32(y)+widthOffset].int() = *prg.mem[int32(y)+widthOffset].int() + *prg.eqtb[dimenBase+scriptSpaceCode-1].int()
- if shiftDown < *prg.fontInfo[17+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int() {
- shiftDown = *prg.fontInfo[17+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- }
- clr = 4**prg.fontInfo[8+prg.paramBase[*(*prg.eqtb[mathFontBase+3+int32(prg.curSize)-1].hh()).rh()]].int() - (shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.mem[int32(y)+heightOffset].int() - shiftDown))
- if clr > 0 {
- shiftDown = shiftDown + clr
- clr = abs(*prg.fontInfo[5+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()*4)/5 - (shiftUp - *prg.mem[int32(x)+depthOffset].int())
- if clr > 0 {
- shiftUp = shiftUp + clr
- shiftDown = shiftDown - clr
- }
- }
- *prg.mem[int32(x)+4].int() = delta // superscript is |delta| to the right of the subscript
- p = prg.newKern(shiftUp - *prg.mem[int32(x)+depthOffset].int() - (*prg.mem[int32(y)+heightOffset].int() - shiftDown))
- *(*prg.mem[x].hh()).rh() = p
- *(*prg.mem[p].hh()).rh() = y
- x = prg.vpackage(x, scaled(0), smallNumber(additional), scaled(07777777777))
- *prg.mem[int32(x)+4].int() = shiftDown
- }
- }
- if *prg.mem[int32(q)+1].int() == 0 {
- *prg.mem[int32(q)+1].int() = int32(x)
- } else {
- p = uint16(*prg.mem[int32(q)+1].int())
- for int32(*(*prg.mem[p].hh()).rh()) != 0 {
- p = *(*prg.mem[p].hh()).rh()
- }
- *(*prg.mem[p].hh()).rh() = x
- }
- }
- func (prg *prg) makeLeftRight(q halfword, style smallNumber,
- maxD, maxH scaled) (r smallNumber) {
- var (
- delta, delta1, delta2 scaled // dimensions used in the calculation
- )
- if int32(style) < scriptStyle {
- prg.curSize = byte(textSize)
- } else {
- prg.curSize = byte(16 * ((int32(style) - textStyle) / 2))
- }
- delta2 = maxD + *prg.fontInfo[22+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int()
- delta1 = maxH + maxD - delta2
- if delta2 > delta1 {
- delta1 = delta2
- } // |delta1| is max distance from axis
- delta = delta1 / 500 * *prg.eqtb[intBase+delimiterFactorCode-1].int()
- delta2 = delta1 + delta1 - *prg.eqtb[dimenBase+delimiterShortfallCode-1].int()
- if delta < delta2 {
- delta = delta2
- }
- *prg.mem[int32(q)+1].int() = int32(prg.varDelimiter(halfword(int32(q)+1), prg.curSize, delta))
- r = byte(int32(*(*prg.mem[q].hh()).b0()) - (leftNoad - openNoad)) // |open_noad| or |close_noad|
- return r
- }
- // 720.
- // tangle:pos tex.web:14163:1:
- // The recursion in |mlist_to_hlist| is due primarily to a subroutine
- // called |clean_box| that puts a given noad field into a box using a given
- // math style; |mlist_to_hlist| can call |clean_box|, which can call
- // |mlist_to_hlist|.
- // \xref[recursion]
- //
- // The box returned by |clean_box| is “clean” in the
- // sense that its |shift_amount| is zero.
- func (prg *prg) mlistToHlist() {
- var (
- mlist halfword // beginning of the given list
- penalties bool // should penalty nodes be inserted?
- style smallNumber // the given style
- saveStyle smallNumber // holds |cur_style| during recursion
- q halfword // runs through the mlist
- r1 halfword // the most recent noad preceding |q|
- rType smallNumber // the |type| of noad |r|, or |op_noad| if |r=null|
- t smallNumber // the effective |type| of noad |q| during the second pass
- p, x, y, z halfword // temporary registers for list construction
- pen int32 // a penalty to be inserted
- s smallNumber // the size of a noad to be deleted
- maxH, maxD scaled // maximum height and depth of the list translated so far
- delta scaled // offset between subscript and superscript
- )
- mlist = prg.curMlist
- penalties = prg.mlistPenalties
- style = prg.curStyle // tuck global parameters away as local variables
- q = mlist
- r1 = 0
- rType = byte(opNoad)
- maxH = 0
- maxD = 0
- // Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
- {
- if int32(prg.curStyle) < scriptStyle {
- prg.curSize = byte(textSize)
- } else {
- prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
- }
- prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
- }
- for int32(q) != 0 {
- // Process node-or-noad |q| as much as possible in preparation for the second pass of |mlist_to_hlist|, then move to the next item in the mlist
- // Do first-pass processing based on |type(q)|; |goto done_with_noad| if a noad has been fully processed, |goto check_dimensions| if it has been translated into |new_hlist(q)|, or |goto done_with_node| if a node has been fully processed
- reswitch:
- delta = 0
- switch *(*prg.mem[q].hh()).b0() {
- case binNoad:
- switch rType {
- case binNoad, opNoad, relNoad, openNoad,
- punctNoad, leftNoad:
- *(*prg.mem[q].hh()).b0() = byte(ordNoad)
- goto reswitch
- default:
- }
- case relNoad, closeNoad, punctNoad, rightNoad:
- if int32(rType) == binNoad {
- *(*prg.mem[r1].hh()).b0() = byte(ordNoad)
- }
- if int32(*(*prg.mem[q].hh()).b0()) == rightNoad {
- goto doneWithNoad
- }
- // \4
- // Cases for noads that can follow a |bin_noad|
- case leftNoad:
- goto doneWithNoad
- case fractionNoad:
- prg.makeFraction(q)
- goto checkDimensions
- case opNoad:
- delta = prg.makeOp(q)
- if int32(*(*prg.mem[q].hh()).b1()) == limits {
- goto checkDimensions
- }
- case ordNoad:
- prg.makeOrd(q)
- case openNoad, innerNoad:
- case radicalNoad:
- prg.makeRadical(q)
- case overNoad:
- prg.makeOver(q)
- case underNoad:
- prg.makeUnder(q)
- case accentNoad:
- prg.makeMathAccent(q)
- case vcenterNoad:
- prg.makeVcenter(q)
- // \4
- // Cases for nodes that can appear in an mlist, after which we |goto done_with_node|
- case styleNode:
- prg.curStyle = *(*prg.mem[q].hh()).b1()
- // Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
- {
- if int32(prg.curStyle) < scriptStyle {
- prg.curSize = byte(textSize)
- } else {
- prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
- }
- prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
- }
- goto doneWithNode
- case choiceNode:
- // Change this node to a style node followed by the correct choice, then |goto done_with_node|
- switch int32(prg.curStyle) / 2 {
- case 0:
- p = *(*prg.mem[int32(q)+1].hh()).lh()
- *(*prg.mem[int32(q)+1].hh()).lh() = 0 // |display_style=0|
- case 1:
- p = *(*prg.mem[int32(q)+1].hh()).rh()
- *(*prg.mem[int32(q)+1].hh()).rh() = 0 // |text_style=2|
- case 2:
- p = *(*prg.mem[int32(q)+2].hh()).lh()
- *(*prg.mem[int32(q)+2].hh()).lh() = 0 // |script_style=4|
- case 3:
- p = *(*prg.mem[int32(q)+2].hh()).rh()
- *(*prg.mem[int32(q)+2].hh()).rh() = 0 // |script_script_style=6|
- } // there are no other cases
- prg.flushNodeList(*(*prg.mem[int32(q)+1].hh()).lh())
- prg.flushNodeList(*(*prg.mem[int32(q)+1].hh()).rh())
- prg.flushNodeList(*(*prg.mem[int32(q)+2].hh()).lh())
- prg.flushNodeList(*(*prg.mem[int32(q)+2].hh()).rh())
- *(*prg.mem[q].hh()).b0() = byte(styleNode)
- *(*prg.mem[q].hh()).b1() = prg.curStyle
- *prg.mem[int32(q)+widthOffset].int() = 0
- *prg.mem[int32(q)+depthOffset].int() = 0
- if int32(p) != 0 {
- z = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = p
- for int32(*(*prg.mem[p].hh()).rh()) != 0 {
- p = *(*prg.mem[p].hh()).rh()
- }
- *(*prg.mem[p].hh()).rh() = z
- }
- goto doneWithNode
- case insNode, markNode, adjustNode, whatsitNode,
- penaltyNode, discNode:
- goto doneWithNode
- case ruleNode:
- if *prg.mem[int32(q)+heightOffset].int() > maxH {
- maxH = *prg.mem[int32(q)+heightOffset].int()
- }
- if *prg.mem[int32(q)+depthOffset].int() > maxD {
- maxD = *prg.mem[int32(q)+depthOffset].int()
- }
- goto doneWithNode
- case glueNode:
- if int32(*(*prg.mem[q].hh()).b1()) == muGlue {
- x = *(*prg.mem[int32(q)+1].hh()).lh()
- y = prg.mathGlue(x, prg.curMu)
- prg.deleteGlueRef(x)
- *(*prg.mem[int32(q)+1].hh()).lh() = y
- *(*prg.mem[q].hh()).b1() = byte(normal)
- } else if int32(prg.curSize) != textSize && int32(*(*prg.mem[q].hh()).b1()) == condMathGlue {
- p = *(*prg.mem[q].hh()).rh()
- if int32(p) != 0 {
- if int32(*(*prg.mem[p].hh()).b0()) == glueNode || int32(*(*prg.mem[p].hh()).b0()) == kernNode {
- *(*prg.mem[q].hh()).rh() = *(*prg.mem[p].hh()).rh()
- *(*prg.mem[p].hh()).rh() = 0
- prg.flushNodeList(p)
- }
- }
- }
- goto doneWithNode
- case kernNode:
- prg.mathKern(q, prg.curMu)
- goto doneWithNode
- default:
- prg.confusion(strNumber( /* "mlist1" */ 889))
- // \xref[this can't happen mlist1][\quad mlist1]
- }
- // Convert \(n)|nucleus(q)| to an hlist and attach the sub/superscripts
- switch *(*prg.mem[int32(q)+1].hh()).rh() {
- case mathChar, mathTextChar:
- // Create a character node |p| for |nucleus(q)|, possibly followed by a kern node for the italic correction, and set |delta| to the italic correction if a subscript is present
- prg.fetch(halfword(int32(q) + 1))
- if int32(prg.curI.b0) > minQuarterword {
- delta = *prg.fontInfo[prg.italicBase[prg.curF]+(int32(prg.curI.b2)-minQuarterword)/4].int()
- p = prg.newCharacter(prg.curF, eightBits(int32(prg.curC)-minQuarterword))
- if int32(*(*prg.mem[int32(q)+1].hh()).rh()) == mathTextChar && *prg.fontInfo[spaceCode+prg.paramBase[prg.curF]].int() != 0 {
- delta = 0
- } // no italic correction in mid-word of text font
- if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty && delta != 0 {
- *(*prg.mem[p].hh()).rh() = prg.newKern(delta)
- delta = 0
- }
- } else {
- p = 0
- }
- case empty:
- p = 0
- case subBox:
- p = *(*prg.mem[int32(q)+1].hh()).lh()
- case subMlist:
- prg.curMlist = *(*prg.mem[int32(q)+1].hh()).lh()
- saveStyle = prg.curStyle
- prg.mlistPenalties = false
- prg.mlistToHlist() // recursive call
- // \xref[recursion]
- prg.curStyle = saveStyle
- // Set up the values...
- {
- if int32(prg.curStyle) < scriptStyle {
- prg.curSize = byte(textSize)
- } else {
- prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
- }
- prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
- }
- p = prg.hpack(*(*prg.mem[30000-3].hh()).rh(), scaled(0), smallNumber(additional))
- default:
- prg.confusion(strNumber( /* "mlist2" */ 890))
- // \xref[this can't happen mlist2][\quad mlist2]
- }
- *prg.mem[int32(q)+1].int() = int32(p)
- if int32(*(*prg.mem[int32(q)+3].hh()).rh()) == empty && int32(*(*prg.mem[int32(q)+2].hh()).rh()) == empty {
- goto checkDimensions
- }
- prg.makeScripts(q, delta)
- checkDimensions:
- z = prg.hpack(halfword(*prg.mem[int32(q)+1].int()), scaled(0), smallNumber(additional))
- if *prg.mem[int32(z)+heightOffset].int() > maxH {
- maxH = *prg.mem[int32(z)+heightOffset].int()
- }
- if *prg.mem[int32(z)+depthOffset].int() > maxD {
- maxD = *prg.mem[int32(z)+depthOffset].int()
- }
- prg.freeNode(z, halfword(boxNodeSize))
- doneWithNoad:
- r1 = q
- rType = *(*prg.mem[r1].hh()).b0()
- doneWithNode:
- q = *(*prg.mem[q].hh()).rh()
- }
- // Convert \(a)a final |bin_noad| to an |ord_noad|
- if int32(rType) == binNoad {
- *(*prg.mem[r1].hh()).b0() = byte(ordNoad)
- }
- // Make a second pass over the mlist, removing all noads and inserting the proper spacing and penalties
- p = uint16(30000 - 3)
- *(*prg.mem[p].hh()).rh() = 0
- q = mlist
- rType = 0
- prg.curStyle = style
- // Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
- {
- if int32(prg.curStyle) < scriptStyle {
- prg.curSize = byte(textSize)
- } else {
- prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
- }
- prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
- }
- for int32(q) != 0 {
- t = byte(ordNoad)
- s = byte(noadSize)
- pen = infPenalty
- switch *(*prg.mem[q].hh()).b0() {
- case opNoad, openNoad, closeNoad, punctNoad,
- innerNoad:
- t = *(*prg.mem[q].hh()).b0()
- case binNoad:
- t = byte(binNoad)
- pen = *prg.eqtb[intBase+binOpPenaltyCode-1].int()
- case relNoad:
- t = byte(relNoad)
- pen = *prg.eqtb[intBase+relPenaltyCode-1].int()
- case ordNoad, vcenterNoad, overNoad, underNoad:
- case radicalNoad:
- s = byte(radicalNoadSize)
- case accentNoad:
- s = byte(accentNoadSize)
- case fractionNoad:
- s = byte(fractionNoadSize)
- case leftNoad, rightNoad:
- t = prg.makeLeftRight(q, style, maxD, maxH)
- case styleNode:
- // Change the current style and |goto delete_q|
- prg.curStyle = *(*prg.mem[q].hh()).b1()
- s = byte(styleNodeSize)
- // Set up the values of |cur_size| and |cur_mu|, based on |cur_style|
- {
- if int32(prg.curStyle) < scriptStyle {
- prg.curSize = byte(textSize)
- } else {
- prg.curSize = byte(16 * ((int32(prg.curStyle) - textStyle) / 2))
- }
- prg.curMu = prg.xOverN(*prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+int32(prg.curSize)-1].hh()).rh()]].int(), 18)
- }
- goto deleteQ
- case whatsitNode, penaltyNode, ruleNode, discNode,
- adjustNode, insNode, markNode, glueNode,
- kernNode: //
- *(*prg.mem[p].hh()).rh() = q
- p = q
- q = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[p].hh()).rh() = 0
- goto done
- default:
- prg.confusion(strNumber( /* "mlist3" */ 891))
- // \xref[this can't happen mlist3][\quad mlist3]
- }
- // Append inter-element spacing based on |r_type| and |t|
- if int32(rType) > 0 {
- switch prg.strPool[int32(rType)*8+int32(t)+prg.magicOffset] {
- case '0':
- x = 0
- // "1"=
- case '1':
- if int32(prg.curStyle) < scriptStyle {
- x = uint16(thinMuSkipCode)
- } else {
- x = 0
- }
- // "2"=
- case '2':
- x = uint16(thinMuSkipCode)
- // "3"=
- case '3':
- if int32(prg.curStyle) < scriptStyle {
- x = uint16(medMuSkipCode)
- } else {
- x = 0
- }
- // "4"=
- case '4':
- if int32(prg.curStyle) < scriptStyle {
- x = uint16(thickMuSkipCode)
- } else {
- x = 0
- }
- default:
- prg.confusion(strNumber( /* "mlist4" */ 893))
- // \xref[this can't happen mlist4][\quad mlist4]
- }
- if int32(x) != 0 {
- y = prg.mathGlue(*(*prg.eqtb[glueBase+int32(x)-1].hh()).rh(), prg.curMu)
- z = prg.newGlue(y)
- *(*prg.mem[y].hh()).rh() = 0
- *(*prg.mem[p].hh()).rh() = z
- p = z
- *(*prg.mem[z].hh()).b1() = byte(int32(x) + 1) // store a symbolic subtype
- }
- }
- // Append any |new_hlist| entries for |q|, and any appropriate penalties
- if *prg.mem[int32(q)+1].int() != 0 {
- *(*prg.mem[p].hh()).rh() = uint16(*prg.mem[int32(q)+1].int())
- for {
- p = *(*prg.mem[p].hh()).rh()
- if int32(*(*prg.mem[p].hh()).rh()) == 0 {
- break
- }
- }
- }
- if penalties {
- if int32(*(*prg.mem[q].hh()).rh()) != 0 {
- if pen < infPenalty {
- rType = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).b0()
- if int32(rType) != penaltyNode {
- if int32(rType) != relNoad {
- z = prg.newPenalty(pen)
- *(*prg.mem[p].hh()).rh() = z
- p = z
- }
- }
- }
- }
- }
- rType = t
- deleteQ:
- r1 = q
- q = *(*prg.mem[q].hh()).rh()
- prg.freeNode(r1, halfword(s))
- done:
- }
- }
- // 768. \[37] Alignment
- // tangle:pos tex.web:15108:18:
- // It's sort of a miracle whenever \.[\\halign] and \.[\\valign] work, because
- // they cut across so many of the control structures of \TeX.
- //
- // Therefore the
- // present page is probably not the best place for a beginner to start reading
- // this program; it is better to master everything else first.
- //
- // Let us focus our thoughts on an example of what the input might be, in order
- // to get some idea about how the alignment miracle happens. The example doesn't
- // do anything useful, but it is sufficiently general to indicate all of the
- // special cases that must be dealt with; please do not be disturbed by its
- // apparent complexity and meaninglessness.
- // $$\vbox[\halign[\.[#]\hfil\cr
- // []\\tabskip 2pt plus 3pt\cr
- // []\\halign to 300pt\[u1\#v1\&\cr
- // \hskip 50pt\\tabskip 1pt plus 1fil u2\#v2\&\cr
- // \hskip 50pt u3\#v3\\cr\cr
- // \hskip 25pt a1\&\\omit a2\&\\vrule\\cr\cr
- // \hskip 25pt \\noalign\[\\vskip 3pt\]\cr
- // \hskip 25pt b1\\span b2\\cr\cr
- // \hskip 25pt \\omit\&c2\\span\\omit\\cr\]\cr]]$$
- // Here's what happens:
- //
- // \yskip
- // (0) When `\.[\\halign to 300pt\[]' is scanned, the |scan_spec| routine
- // places the 300pt dimension onto the |save_stack|, and an |align_group|
- // code is placed above it. This will make it possible to complete the alignment
- // when the matching `\.\]' is found.
- //
- // (1) The preamble is scanned next. Macros in the preamble are not expanded,
- // \xref[preamble]
- // except as part of a tabskip specification. For example, if \.[u2] had been
- // a macro in the preamble above, it would have been expanded, since \TeX\
- // must look for `\.[minus...]' as part of the tabskip glue. A ``preamble list''
- // is constructed based on the user's preamble; in our case it contains the
- // following seven items:
- // $$\vbox[\halign[\.[#]\hfil\qquad&(#)\hfil\cr
- // []\\glue 2pt plus 3pt&the tabskip preceding column 1\cr
- // []\\alignrecord, width $-\infty$&preamble info for column 1\cr
- // []\\glue 2pt plus 3pt&the tabskip between columns 1 and 2\cr
- // []\\alignrecord, width $-\infty$&preamble info for column 2\cr
- // []\\glue 1pt plus 1fil&the tabskip between columns 2 and 3\cr
- // []\\alignrecord, width $-\infty$&preamble info for column 3\cr
- // []\\glue 1pt plus 1fil&the tabskip following column 3\cr]]$$
- // These ``alignrecord'' entries have the same size as an |unset_node|,
- // since they will later be converted into such nodes. However, at the
- // moment they have no |type| or |subtype| fields; they have |info| fields
- // instead, and these |info| fields are initially set to the value |end_span|,
- // for reasons explained below. Furthermore, the alignrecord nodes have no
- // |height| or |depth| fields; these are renamed |u_part| and |v_part|,
- // and they point to token lists for the templates of the alignment.
- // For example, the |u_part| field in the first alignrecord points to the
- // token list `\.[u1]', i.e., the template preceding the `\.\#' for column~1.
- //
- // (2) \TeX\ now looks at what follows the \.[\\cr] that ended the preamble.
- // It is not `\.[\\noalign]' or `\.[\\omit]', so this input is put back to
- // be read again, and the template `\.[u1]' is fed to the scanner. Just
- // before reading `\.[u1]', \TeX\ goes into restricted horizontal mode.
- // Just after reading `\.[u1]', \TeX\ will see `\.[a1]', and then (when the
- // [\.\&] is sensed) \TeX\ will see `\.[v1]'. Then \TeX\ scans an |endv|
- // token, indicating the end of a column. At this point an |unset_node| is
- // created, containing the contents of the current hlist (i.e., `\.[u1a1v1]').
- // The natural width of this unset node replaces the |width| field of the
- // alignrecord for column~1; in general, the alignrecords will record the
- // maximum natural width that has occurred so far in a given column.
- //
- // (3) Since `\.[\\omit]' follows the `\.\&', the templates for column~2
- // are now bypassed. Again \TeX\ goes into restricted horizontal mode and
- // makes an |unset_node| from the resulting hlist; but this time the
- // hlist contains simply `\.[a2]'. The natural width of the new unset box
- // is remembered in the |width| field of the alignrecord for column~2.
- //
- // (4) A third |unset_node| is created for column 3, using essentially the
- // mechanism that worked for column~1; this unset box contains `\.[u3\\vrule
- // v3]'. The vertical rule in this case has running dimensions that will later
- // extend to the height and depth of the whole first row, since each |unset_node|
- // in a row will eventually inherit the height and depth of its enclosing box.
- //
- // (5) The first row has now ended; it is made into a single unset box
- // comprising the following seven items:
- // $$\vbox[\halign[\hbox to 325pt[\qquad\.[#]\hfil]\cr
- // []\\glue 2pt plus 3pt\cr
- // []\\unsetbox for 1 column: u1a1v1\cr
- // []\\glue 2pt plus 3pt\cr
- // []\\unsetbox for 1 column: a2\cr
- // []\\glue 1pt plus 1fil\cr
- // []\\unsetbox for 1 column: u3\\vrule v3\cr
- // []\\glue 1pt plus 1fil\cr]]$$
- // The width of this unset row is unimportant, but it has the correct height
- // and depth, so the correct baselineskip glue will be computed as the row
- // is inserted into a vertical list.
- //
- // (6) Since `\.[\\noalign]' follows the current \.[\\cr], \TeX\ appends
- // additional material (in this case \.[\\vskip 3pt]) to the vertical list.
- // While processing this material, \TeX\ will be in internal vertical
- // mode, and |no_align_group| will be on |save_stack|.
- //
- // (7) The next row produces an unset box that looks like this:
- // $$\vbox[\halign[\hbox to 325pt[\qquad\.[#]\hfil]\cr
- // []\\glue 2pt plus 3pt\cr
- // []\\unsetbox for 2 columns: u1b1v1u2b2v2\cr
- // []\\glue 1pt plus 1fil\cr
- // []\\unsetbox for 1 column: [\rm(empty)]\cr
- // []\\glue 1pt plus 1fil\cr]]$$
- // The natural width of the unset box that spans columns 1~and~2 is stored
- // in a ``span node,'' which we will explain later; the |info| field of the
- // alignrecord for column~1 now points to the new span node, and the |info|
- // of the span node points to |end_span|.
- //
- // (8) The final row produces the unset box
- // $$\vbox[\halign[\hbox to 325pt[\qquad\.[#]\hfil]\cr
- // []\\glue 2pt plus 3pt\cr
- // []\\unsetbox for 1 column: [\rm(empty)]\cr
- // []\\glue 2pt plus 3pt\cr
- // []\\unsetbox for 2 columns: u2c2v2\cr
- // []\\glue 1pt plus 1fil\cr]]$$
- // A new span node is attached to the alignrecord for column 2.
- //
- // (9) The last step is to compute the true column widths and to change all the
- // unset boxes to hboxes, appending the whole works to the vertical list that
- // encloses the \.[\\halign]. The rules for deciding on the final widths of
- // each unset column box will be explained below.
- //
- // \yskip\noindent
- // Note that as \.[\\halign] is being processed, we fearlessly give up control
- // to the rest of \TeX. At critical junctures, an alignment routine is
- // called upon to step in and do some little action, but most of the time
- // these routines just lurk in the background. It's something like
- // post-hypnotic suggestion.
- // 769.
- // tangle:pos tex.web:15239:1:
- // We have mentioned that alignrecords contain no |height| or |depth| fields.
- // Their |glue_sign| and |glue_order| are pre-empted as well, since it
- // is necessary to store information about what to do when a template ends.
- // This information is called the |extra_info| field.
- // 772.
- // tangle:pos tex.web:15281:1:
- // Alignment stack maintenance is handled by a pair of trivial routines
- // called |push_alignment| and |pop_alignment|.
- func (prg *prg) pushAlignment() {
- var (
- p halfword // the new alignment stack node
- )
- p = prg.getNode(alignStackNodeSize)
- *(*prg.mem[p].hh()).rh() = prg.alignPtr
- *(*prg.mem[p].hh()).lh() = prg.curAlign
- *(*prg.mem[int32(p)+1].hh()).lh() = *(*prg.mem[30000-8].hh()).rh()
- *(*prg.mem[int32(p)+1].hh()).rh() = prg.curSpan
- *prg.mem[int32(p)+2].int() = int32(prg.curLoop)
- *prg.mem[int32(p)+3].int() = prg.alignState
- *(*prg.mem[int32(p)+4].hh()).lh() = prg.curHead
- *(*prg.mem[int32(p)+4].hh()).rh() = prg.curTail
- prg.alignPtr = p
- prg.curHead = prg.getAvail()
- }
- func (prg *prg) popAlignment() {
- var (
- p halfword // the top alignment stack node
- )
- {
- *(*prg.mem[prg.curHead].hh()).rh() = prg.avail
- prg.avail = prg.curHead /* dyn_used:= dyn_used-1 ; [ ] */
- }
- p = prg.alignPtr
- prg.curTail = *(*prg.mem[int32(p)+4].hh()).rh()
- prg.curHead = *(*prg.mem[int32(p)+4].hh()).lh()
- prg.alignState = *prg.mem[int32(p)+3].int()
- prg.curLoop = uint16(*prg.mem[int32(p)+2].int())
- prg.curSpan = *(*prg.mem[int32(p)+1].hh()).rh()
- *(*prg.mem[30000-8].hh()).rh() = *(*prg.mem[int32(p)+1].hh()).lh()
- prg.curAlign = *(*prg.mem[p].hh()).lh()
- prg.alignPtr = *(*prg.mem[p].hh()).rh()
- prg.freeNode(p, halfword(alignStackNodeSize))
- }
- // 773.
- // tangle:pos tex.web:15306:1:
- // \TeX\ has eight procedures that govern alignments: |init_align| and
- // |fin_align| are used at the very beginning and the very end; |init_row| and
- // |fin_row| are used at the beginning and end of individual rows; |init_span|
- // is used at the beginning of a sequence of spanned columns (possibly involving
- // only one column); |init_col| and |fin_col| are used at the beginning and
- // end of individual columns; and |align_peek| is used after \.[\\cr] to see
- // whether the next item is \.[\\noalign].
- //
- // We shall consider these routines in the order they are first used during
- // the course of a complete \.[\\halign], namely |init_align|, |align_peek|,
- // |init_row|, |init_span|, |init_col|, |fin_col|, |fin_row|, |fin_align|.
- // 774.
- // tangle:pos tex.web:15318:1:
- // When \.[\\halign] or \.[\\valign] has been scanned in an appropriate
- // mode, \TeX\ calls |init_align|, whose task is to get everything off to a
- // good start. This mostly involves scanning the preamble and putting its
- // information into the preamble list.
- // \xref[preamble]
- // \4
- // Declare the procedure called |get_preamble_token|
- func (prg *prg) getPreambleToken() {
- restart:
- prg.getToken()
- for int32(prg.curChr) == spanCode && int32(prg.curCmd) == tabMark {
- prg.getToken() // this token will be expanded once
- if int32(prg.curCmd) > maxCommand {
- prg.expand()
- prg.getToken()
- }
- }
- if int32(prg.curCmd) == endv {
- prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
- }
- // \xref[interwoven alignment preambles...]
- if int32(prg.curCmd) == assignGlue && int32(prg.curChr) == glueBase+tabSkipCode {
- prg.scanOptionalEquals()
- prg.scanGlue(smallNumber(glueVal))
- if *prg.eqtb[intBase+globalDefsCode-1].int() > 0 {
- prg.geqDefine(halfword(glueBase+tabSkipCode), quarterword(glueRef), halfword(prg.curVal))
- } else {
- prg.eqDefine(halfword(glueBase+tabSkipCode), quarterword(glueRef), halfword(prg.curVal))
- }
- goto restart
- }
- } // \2
- func (prg *prg) initAlign() {
- var (
- saveCsPtr halfword // |warning_index| value for error messages
- p halfword // for short-term temporary use
- )
- saveCsPtr = prg.curCs // \.[\\halign] or \.[\\valign], usually
- prg.pushAlignment()
- prg.alignState = -1000000 // enter a new alignment level
- // Check for improper alignment in displayed math
- if int32(prg.curList.modeField) == mmode && (int32(prg.curList.tailField) != int32(prg.curList.headField) || *prg.curList.auxField.int() != 0) {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Improper " */ 680)
- }
- prg.printEsc(strNumber( /* "halign" */ 520))
- prg.print( /* " inside $$'s" */ 894)
- // \xref[Improper \\halign...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "Displays can use special alignments (like \\eqalignno)" */ 895
- prg.helpLine[1] = /* "only if nothing but the alignment itself is between $$'s." */ 896
- prg.helpLine[0] = /* "So I've deleted the formulas that preceded this alignment." */ 897
- }
- prg.error1()
- prg.flushMath()
- }
- prg.pushNest() // enter a new semantic level
- // Change current mode to |-vmode| for \.[\\halign], |-hmode| for \.[\\valign]
- if int32(prg.curList.modeField) == mmode {
- prg.curList.modeField = int16(-vmode)
- *prg.curList.auxField.int() = *prg.nest[int32(prg.nestPtr)-2].auxField.int()
- } else if int32(prg.curList.modeField) > 0 {
- prg.curList.modeField = -prg.curList.modeField
- }
- prg.scanSpec(groupCode(alignGroup), false)
- // Scan the preamble and record it in the |preamble| list
- *(*prg.mem[30000-8].hh()).rh() = 0
- prg.curAlign = uint16(30000 - 8)
- prg.curLoop = 0
- prg.scannerStatus = byte(aligning)
- prg.warningIndex = saveCsPtr
- prg.alignState = -1000000
- // at this point, |cur_cmd=left_brace|
- for true {
- *(*prg.mem[prg.curAlign].hh()).rh() = prg.newParamGlue(smallNumber(tabSkipCode))
- prg.curAlign = *(*prg.mem[prg.curAlign].hh()).rh()
- if int32(prg.curCmd) == carRet {
- goto done
- } // \.[\\cr] ends the preamble
- // Scan preamble text until |cur_cmd| is |tab_mark| or |car_ret|, looking for changes in the tabskip glue; append an alignrecord to the preamble list
- // Scan the template \<u_j>, putting the resulting token list in |hold_head|
- p = uint16(30000 - 4)
- *(*prg.mem[p].hh()).rh() = 0
- for true {
- prg.getPreambleToken()
- if int32(prg.curCmd) == macParam {
- goto done1
- }
- if int32(prg.curCmd) <= carRet && int32(prg.curCmd) >= tabMark && prg.alignState == -1000000 {
- if int32(p) == 30000-4 && int32(prg.curLoop) == 0 && int32(prg.curCmd) == tabMark {
- prg.curLoop = prg.curAlign
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing # inserted in alignment preamble" */ 903)
- }
- // \xref[Missing \# inserted...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "There should be exactly one # between &'s, when an" */ 904
- prg.helpLine[1] = /* "\\halign or \\valign is being set up. In this case you had" */ 905
- prg.helpLine[0] = /* "none, so I've put one in; maybe that will work." */ 906
- }
- prg.backError()
- goto done1
- }
- } else if int32(prg.curCmd) != spacer || int32(p) != 30000-4 {
- *(*prg.mem[p].hh()).rh() = prg.getAvail()
- p = *(*prg.mem[p].hh()).rh()
- *(*prg.mem[p].hh()).lh() = prg.curTok
- }
- }
- done1:
- ;
- *(*prg.mem[prg.curAlign].hh()).rh() = prg.newNullBox()
- prg.curAlign = *(*prg.mem[prg.curAlign].hh()).rh() // a new alignrecord
- *(*prg.mem[prg.curAlign].hh()).lh() = uint16(30000 - 9)
- *prg.mem[int32(prg.curAlign)+widthOffset].int() = -010000000000
- *prg.mem[int32(prg.curAlign)+heightOffset].int() = int32(*(*prg.mem[30000-4].hh()).rh())
- // Scan the template \<v_j>, putting the resulting token list in |hold_head|
- p = uint16(30000 - 4)
- *(*prg.mem[p].hh()).rh() = 0
- for true {
- continue1:
- prg.getPreambleToken()
- if int32(prg.curCmd) <= carRet && int32(prg.curCmd) >= tabMark && prg.alignState == -1000000 {
- goto done2
- }
- if int32(prg.curCmd) == macParam {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Only one # is allowed per tab" */ 907)
- }
- // \xref[Only one \# is allowed...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "There should be exactly one # between &'s, when an" */ 904
- prg.helpLine[1] = /* "\\halign or \\valign is being set up. In this case you had" */ 905
- prg.helpLine[0] = /* "more than one, so I'm ignoring all but the first." */ 908
- }
- prg.error1()
- goto continue1
- }
- *(*prg.mem[p].hh()).rh() = prg.getAvail()
- p = *(*prg.mem[p].hh()).rh()
- *(*prg.mem[p].hh()).lh() = prg.curTok
- }
- done2:
- *(*prg.mem[p].hh()).rh() = prg.getAvail()
- p = *(*prg.mem[p].hh()).rh()
- *(*prg.mem[p].hh()).lh() = uint16(07777 + frozenEndTemplate)
- *prg.mem[int32(prg.curAlign)+depthOffset].int() = int32(*(*prg.mem[30000-4].hh()).rh())
- }
- done:
- prg.scannerStatus = byte(normal)
- prg.newSaveLevel(groupCode(alignGroup))
- if int32(*(*prg.eqtb[everyCrLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyCrLoc-1].hh()).rh(), quarterword(everyCrText))
- }
- prg.alignPeek() // look for \.[\\noalign] or \.[\\omit]
- }
- // 786.
- // tangle:pos tex.web:15525:1:
- // To start a row (i.e., a `row' that rhymes with `dough' but not with `bough'),
- // we enter a new semantic level, copy the first tabskip glue, and change
- // from internal vertical mode to restricted horizontal mode or vice versa.
- // The |space_factor| and |prev_depth| are not used on this semantic level,
- // but we clear them to zero just to be tidy.
- // \4
- // Declare the procedure called |init_span|
- func (prg *prg) initSpan(p halfword) {
- prg.pushNest()
- if int32(prg.curList.modeField) == -hmode {
- *(*prg.curList.auxField.hh()).lh() = 1000
- } else {
- *prg.curList.auxField.int() = -65536000
- prg.normalParagraph()
- }
- prg.curSpan = p
- }
- //
- func (prg *prg) initRow() {
- prg.pushNest()
- prg.curList.modeField = int16(-hmode - vmode - int32(prg.curList.modeField))
- if int32(prg.curList.modeField) == -hmode {
- *(*prg.curList.auxField.hh()).lh() = 0
- } else {
- *prg.curList.auxField.int() = 0
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(*(*prg.mem[int32(*(*prg.mem[30000-8].hh()).rh())+1].hh()).lh())
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(tabSkipCode + 1)
- prg.curAlign = *(*prg.mem[*(*prg.mem[30000-8].hh()).rh()].hh()).rh()
- prg.curTail = prg.curHead
- prg.initSpan(prg.curAlign)
- }
- // 788.
- // tangle:pos tex.web:15553:1:
- // When a column begins, we assume that |cur_cmd| is either |omit| or else
- // the current token should be put back into the input until the \<u_j>
- // template has been scanned. (Note that |cur_cmd| might be |tab_mark| or
- // |car_ret|.) We also assume that |align_state| is approximately 1000000 at
- // this time. We remain in the same mode, and start the template if it is
- // called for.
- func (prg *prg) initCol() {
- *(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh() = uint16(prg.curCmd)
- if int32(prg.curCmd) == omit {
- prg.alignState = 0
- } else {
- prg.backInput()
- prg.beginTokenList(halfword(*prg.mem[int32(prg.curAlign)+heightOffset].int()), quarterword(uTemplate))
- } // now |align_state=1000000|
- }
- // 791.
- // tangle:pos tex.web:15592:1:
- // When the |endv| command at the end of a \<v_j> template comes through the
- // scanner, things really start to happen; and it is the |fin_col| routine
- // that makes them happen. This routine returns |true| if a row as well as a
- // column has been finished.
- func (prg *prg) finCol() (r bool) {
- var (
- p halfword // the alignrecord after the current one
- q, r1 halfword // temporary pointers for list manipulation
- s halfword // a new span node
- u halfword // a new unset box
- w scaled // natural width
- o glueOrd // order of infinity
- n halfword // span counter
- )
- if int32(prg.curAlign) == 0 {
- prg.confusion(strNumber( /* "endv" */ 909))
- }
- q = *(*prg.mem[prg.curAlign].hh()).rh()
- if int32(q) == 0 {
- prg.confusion(strNumber( /* "endv" */ 909))
- }
- // \xref[this can't happen endv][\quad endv]
- if prg.alignState < 500000 {
- prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
- }
- // \xref[interwoven alignment preambles...]
- p = *(*prg.mem[q].hh()).rh()
- // If the preamble list has been traversed, check that the row has ended
- if int32(p) == 0 && int32(*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh()) < crCode {
- if int32(prg.curLoop) != 0 {
- *(*prg.mem[q].hh()).rh() = prg.newNullBox()
- p = *(*prg.mem[q].hh()).rh() // a new alignrecord
- *(*prg.mem[p].hh()).lh() = uint16(30000 - 9)
- *prg.mem[int32(p)+widthOffset].int() = -010000000000
- prg.curLoop = *(*prg.mem[prg.curLoop].hh()).rh()
- // Copy the templates from node |cur_loop| into node |p|
- q = uint16(30000 - 4)
- r1 = uint16(*prg.mem[int32(prg.curLoop)+heightOffset].int())
- for int32(r1) != 0 {
- *(*prg.mem[q].hh()).rh() = prg.getAvail()
- q = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).lh() = *(*prg.mem[r1].hh()).lh()
- r1 = *(*prg.mem[r1].hh()).rh()
- }
- *(*prg.mem[q].hh()).rh() = 0
- *prg.mem[int32(p)+heightOffset].int() = int32(*(*prg.mem[30000-4].hh()).rh())
- q = uint16(30000 - 4)
- r1 = uint16(*prg.mem[int32(prg.curLoop)+depthOffset].int())
- for int32(r1) != 0 {
- *(*prg.mem[q].hh()).rh() = prg.getAvail()
- q = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).lh() = *(*prg.mem[r1].hh()).lh()
- r1 = *(*prg.mem[r1].hh()).rh()
- }
- *(*prg.mem[q].hh()).rh() = 0
- *prg.mem[int32(p)+depthOffset].int() = int32(*(*prg.mem[30000-4].hh()).rh())
- prg.curLoop = *(*prg.mem[prg.curLoop].hh()).rh()
- *(*prg.mem[p].hh()).rh() = prg.newGlue(*(*prg.mem[int32(prg.curLoop)+1].hh()).lh())
- *(*prg.mem[*(*prg.mem[p].hh()).rh()].hh()).b1() = byte(tabSkipCode + 1)
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Extra alignment tab has been changed to " */ 910)
- }
- // \xref[Extra alignment tab...]
- prg.printEsc(strNumber( /* "cr" */ 899))
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "You have given more \\span or & marks than there were" */ 911
- prg.helpLine[1] = /* "in the preamble to the \\halign or \\valign now in progress." */ 912
- prg.helpLine[0] = /* "So I'll assume that you meant to type \\cr instead." */ 913
- }
- *(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh() = uint16(crCode)
- prg.error1()
- }
- }
- if int32(*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh()) != spanCode {
- prg.unsave()
- prg.newSaveLevel(groupCode(alignGroup))
- // Package an unset box for the current column and record its width
- {
- if int32(prg.curList.modeField) == -hmode {
- prg.adjustTail = prg.curTail
- u = prg.hpack(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional))
- w = *prg.mem[int32(u)+widthOffset].int()
- prg.curTail = prg.adjustTail
- prg.adjustTail = 0
- } else {
- u = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional), scaled(0))
- w = *prg.mem[int32(u)+heightOffset].int()
- }
- n = uint16(minQuarterword) // this represents a span count of 1
- if int32(prg.curSpan) != int32(prg.curAlign) {
- q = prg.curSpan
- for {
- n = uint16(int32(n) + 1)
- q = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).rh()
- if int32(q) == int32(prg.curAlign) {
- break
- }
- }
- if int32(n) > maxQuarterword {
- prg.confusion(strNumber( /* "256 spans" */ 914))
- } // this can happen, but won't
- // \xref[system dependencies]
- // \xref[this can't happen 256 spans][\quad 256 spans]
- q = prg.curSpan
- for int32(*(*prg.mem[*(*prg.mem[q].hh()).lh()].hh()).rh()) < int32(n) {
- q = *(*prg.mem[q].hh()).lh()
- }
- if int32(*(*prg.mem[*(*prg.mem[q].hh()).lh()].hh()).rh()) > int32(n) {
- s = prg.getNode(spanNodeSize)
- *(*prg.mem[s].hh()).lh() = *(*prg.mem[q].hh()).lh()
- *(*prg.mem[s].hh()).rh() = n
- *(*prg.mem[q].hh()).lh() = s
- *prg.mem[int32(s)+widthOffset].int() = w
- } else if *prg.mem[int32(*(*prg.mem[q].hh()).lh())+widthOffset].int() < w {
- *prg.mem[int32(*(*prg.mem[q].hh()).lh())+widthOffset].int() = w
- }
- } else if w > *prg.mem[int32(prg.curAlign)+widthOffset].int() {
- *prg.mem[int32(prg.curAlign)+widthOffset].int() = w
- }
- *(*prg.mem[u].hh()).b0() = byte(unsetNode)
- *(*prg.mem[u].hh()).b1() = byte(n)
- // Determine the stretch order
- if prg.totalStretch[filll] != 0 {
- o = byte(filll)
- } else if prg.totalStretch[fill] != 0 {
- o = byte(fill)
- } else if prg.totalStretch[fil] != 0 {
- o = byte(fil)
- } else {
- o = byte(normal)
- }
- *(*prg.mem[int32(u)+listOffset].hh()).b1() = o
- *prg.mem[int32(u)+glueOffset].int() = prg.totalStretch[o]
- // Determine the shrink order
- if prg.totalShrink[filll] != 0 {
- o = byte(filll)
- } else if prg.totalShrink[fill] != 0 {
- o = byte(fill)
- } else if prg.totalShrink[fil] != 0 {
- o = byte(fil)
- } else {
- o = byte(normal)
- }
- *(*prg.mem[int32(u)+listOffset].hh()).b0() = o
- *prg.mem[int32(u)+4].int() = prg.totalShrink[o]
- prg.popNest()
- *(*prg.mem[prg.curList.tailField].hh()).rh() = u
- prg.curList.tailField = u
- }
- // Copy the tabskip glue between columns
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(*(*prg.mem[int32(*(*prg.mem[prg.curAlign].hh()).rh())+1].hh()).lh())
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(tabSkipCode + 1)
- if int32(*(*prg.mem[int32(prg.curAlign)+listOffset].hh()).lh()) >= crCode {
- r = true
- goto exit
- }
- prg.initSpan(p)
- }
- prg.alignState = 1000000
- // Get the next non-blank non-call token
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- prg.curAlign = p
- prg.initCol()
- r = false
- exit:
- ;
- return r
- }
- // 799.
- // tangle:pos tex.web:15714:1:
- // At the end of a row, we append an unset box to the current vlist (for
- // \.[\\halign]) or the current hlist (for \.[\\valign]). This unset box
- // contains the unset boxes for the columns, separated by the tabskip glue.
- // Everything will be set later.
- func (prg *prg) finRow() {
- var (
- p halfword // the new unset box
- )
- if int32(prg.curList.modeField) == -hmode {
- p = prg.hpack(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional))
- prg.popNest()
- prg.appendToVlist(p)
- if int32(prg.curHead) != int32(prg.curTail) {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[prg.curHead].hh()).rh()
- prg.curList.tailField = prg.curTail
- }
- } else {
- p = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional), scaled(07777777777))
- prg.popNest()
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- prg.curList.tailField = p
- *(*prg.curList.auxField.hh()).lh() = 1000
- }
- *(*prg.mem[p].hh()).b0() = byte(unsetNode)
- *prg.mem[int32(p)+glueOffset].int() = 0
- if int32(*(*prg.eqtb[everyCrLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyCrLoc-1].hh()).rh(), quarterword(everyCrText))
- }
- prg.alignPeek()
- } // \2
- func (prg *prg) finAlign() {
- var (
- p, q, r1, s, u, v halfword // registers for the list operations
- t, w scaled // width of column
- o scaled // shift offset for unset boxes
- n halfword // matching span amount
- ruleSave scaled // temporary storage for |overfull_rule|
- auxSave memoryWord // temporary storage for |aux|
- )
- if int32(prg.curGroup) != alignGroup {
- prg.confusion(strNumber( /* "align1" */ 915))
- }
- // \xref[this can't happen align][\quad align]
- prg.unsave() // that |align_group| was for individual entries
- if int32(prg.curGroup) != alignGroup {
- prg.confusion(strNumber( /* "align0" */ 916))
- }
- prg.unsave() // that |align_group| was for the whole alignment
- if int32(prg.nest[int32(prg.nestPtr)-1].modeField) == mmode {
- o = *prg.eqtb[dimenBase+displayIndentCode-1].int()
- } else {
- o = 0
- }
- // Go through the preamble list, determining the column widths and changing the alignrecords to dummy unset boxes
- q = *(*prg.mem[*(*prg.mem[30000-8].hh()).rh()].hh()).rh()
- for {
- prg.flushList(halfword(*prg.mem[int32(q)+heightOffset].int()))
- prg.flushList(halfword(*prg.mem[int32(q)+depthOffset].int()))
- p = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).rh()
- if *prg.mem[int32(q)+widthOffset].int() == -010000000000 {
- *prg.mem[int32(q)+widthOffset].int() = 0
- r1 = *(*prg.mem[q].hh()).rh()
- s = *(*prg.mem[int32(r1)+1].hh()).lh()
- if int32(s) != memBot {
- *(*prg.mem[memBot].hh()).rh() = uint16(int32(*(*prg.mem[memBot].hh()).rh()) + 1)
- prg.deleteGlueRef(s)
- *(*prg.mem[int32(r1)+1].hh()).lh() = uint16(memBot)
- }
- }
- if int32(*(*prg.mem[q].hh()).lh()) != 30000-9 {
- t = *prg.mem[int32(q)+widthOffset].int() + *prg.mem[int32(*(*prg.mem[int32(*(*prg.mem[q].hh()).rh())+1].hh()).lh())+widthOffset].int()
- r1 = *(*prg.mem[q].hh()).lh()
- s = uint16(30000 - 9)
- *(*prg.mem[s].hh()).lh() = p
- n = uint16(minQuarterword + 1)
- for {
- *prg.mem[int32(r1)+widthOffset].int() = *prg.mem[int32(r1)+widthOffset].int() - t
- u = *(*prg.mem[r1].hh()).lh()
- for int32(*(*prg.mem[r1].hh()).rh()) > int32(n) {
- s = *(*prg.mem[s].hh()).lh()
- n = uint16(int32(*(*prg.mem[*(*prg.mem[s].hh()).lh()].hh()).rh()) + 1)
- }
- if int32(*(*prg.mem[r1].hh()).rh()) < int32(n) {
- *(*prg.mem[r1].hh()).lh() = *(*prg.mem[s].hh()).lh()
- *(*prg.mem[s].hh()).lh() = r1
- *(*prg.mem[r1].hh()).rh() = uint16(int32(*(*prg.mem[r1].hh()).rh()) - 1)
- s = r1
- } else {
- if *prg.mem[int32(r1)+widthOffset].int() > *prg.mem[int32(*(*prg.mem[s].hh()).lh())+widthOffset].int() {
- *prg.mem[int32(*(*prg.mem[s].hh()).lh())+widthOffset].int() = *prg.mem[int32(r1)+widthOffset].int()
- }
- prg.freeNode(r1, halfword(spanNodeSize))
- }
- r1 = u
- if int32(r1) == 30000-9 {
- break
- }
- }
- }
- *(*prg.mem[q].hh()).b0() = byte(unsetNode)
- *(*prg.mem[q].hh()).b1() = byte(minQuarterword)
- *prg.mem[int32(q)+heightOffset].int() = 0
- *prg.mem[int32(q)+depthOffset].int() = 0
- *(*prg.mem[int32(q)+listOffset].hh()).b1() = byte(normal)
- *(*prg.mem[int32(q)+listOffset].hh()).b0() = byte(normal)
- *prg.mem[int32(q)+glueOffset].int() = 0
- *prg.mem[int32(q)+4].int() = 0
- q = p
- if int32(q) == 0 {
- break
- }
- }
- // Package the preamble list, to determine the actual tabskip glue amounts, and let |p| point to this prototype box
- prg.savePtr = uint16(int32(prg.savePtr) - 2)
- prg.packBeginLine = -prg.curList.mlField
- if int32(prg.curList.modeField) == -vmode {
- ruleSave = *prg.eqtb[dimenBase+overfullRuleCode-1].int()
- *prg.eqtb[dimenBase+overfullRuleCode-1].int() = 0 // prevent rule from being packaged
- p = prg.hpack(*(*prg.mem[30000-8].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+1].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+0].int()))
- *prg.eqtb[dimenBase+overfullRuleCode-1].int() = ruleSave
- } else {
- q = *(*prg.mem[*(*prg.mem[30000-8].hh()).rh()].hh()).rh()
- for {
- *prg.mem[int32(q)+heightOffset].int() = *prg.mem[int32(q)+widthOffset].int()
- *prg.mem[int32(q)+widthOffset].int() = 0
- q = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).rh()
- if int32(q) == 0 {
- break
- }
- }
- p = prg.vpackage(*(*prg.mem[30000-8].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+1].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+0].int()), scaled(07777777777))
- q = *(*prg.mem[*(*prg.mem[30000-8].hh()).rh()].hh()).rh()
- for {
- *prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(q)+heightOffset].int()
- *prg.mem[int32(q)+heightOffset].int() = 0
- q = *(*prg.mem[*(*prg.mem[q].hh()).rh()].hh()).rh()
- if int32(q) == 0 {
- break
- }
- }
- }
- prg.packBeginLine = 0
- // Set the glue in all the unset boxes of the current list
- q = *(*prg.mem[prg.curList.headField].hh()).rh()
- s = prg.curList.headField
- for int32(q) != 0 {
- if !(int32(q) >= int32(prg.hiMemMin)) {
- if int32(*(*prg.mem[q].hh()).b0()) == unsetNode {
- if int32(prg.curList.modeField) == -vmode {
- *(*prg.mem[q].hh()).b0() = byte(hlistNode)
- *prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(p)+widthOffset].int()
- } else {
- *(*prg.mem[q].hh()).b0() = byte(vlistNode)
- *prg.mem[int32(q)+heightOffset].int() = *prg.mem[int32(p)+heightOffset].int()
- }
- *(*prg.mem[int32(q)+listOffset].hh()).b1() = *(*prg.mem[int32(p)+listOffset].hh()).b1()
- *(*prg.mem[int32(q)+listOffset].hh()).b0() = *(*prg.mem[int32(p)+listOffset].hh()).b0()
- *prg.mem[int32(q)+glueOffset].gr() = *prg.mem[int32(p)+glueOffset].gr()
- *prg.mem[int32(q)+4].int() = o
- r1 = *(*prg.mem[*(*prg.mem[int32(q)+listOffset].hh()).rh()].hh()).rh()
- s = *(*prg.mem[*(*prg.mem[int32(p)+listOffset].hh()).rh()].hh()).rh()
- for {
- // Set the glue in node |r| and change it from an unset node
- n = uint16(*(*prg.mem[r1].hh()).b1())
- t = *prg.mem[int32(s)+widthOffset].int()
- w = t
- u = uint16(30000 - 4)
- for int32(n) > minQuarterword {
- n = uint16(int32(n) - 1)
- // Append tabskip glue and an empty box to list |u|, and update |s| and |t| as the prototype nodes are passed
- s = *(*prg.mem[s].hh()).rh()
- v = *(*prg.mem[int32(s)+1].hh()).lh()
- *(*prg.mem[u].hh()).rh() = prg.newGlue(v)
- u = *(*prg.mem[u].hh()).rh()
- *(*prg.mem[u].hh()).b1() = byte(tabSkipCode + 1)
- t = t + *prg.mem[int32(v)+widthOffset].int()
- if int32(*(*prg.mem[int32(p)+listOffset].hh()).b0()) == stretching {
- if int32(*(*prg.mem[v].hh()).b0()) == int32(*(*prg.mem[int32(p)+listOffset].hh()).b1()) {
- t = t + round(float64(*prg.mem[int32(p)+glueOffset].gr())*float64(*prg.mem[int32(v)+2].int()))
- }
- // \xref[real multiplication]
- } else if int32(*(*prg.mem[int32(p)+listOffset].hh()).b0()) == shrinking {
- if int32(*(*prg.mem[v].hh()).b1()) == int32(*(*prg.mem[int32(p)+listOffset].hh()).b1()) {
- t = t - round(float64(*prg.mem[int32(p)+glueOffset].gr())*float64(*prg.mem[int32(v)+3].int()))
- }
- }
- s = *(*prg.mem[s].hh()).rh()
- *(*prg.mem[u].hh()).rh() = prg.newNullBox()
- u = *(*prg.mem[u].hh()).rh()
- t = t + *prg.mem[int32(s)+widthOffset].int()
- if int32(prg.curList.modeField) == -vmode {
- *prg.mem[int32(u)+widthOffset].int() = *prg.mem[int32(s)+widthOffset].int()
- } else {
- *(*prg.mem[u].hh()).b0() = byte(vlistNode)
- *prg.mem[int32(u)+heightOffset].int() = *prg.mem[int32(s)+widthOffset].int()
- }
- }
- if int32(prg.curList.modeField) == -vmode {
- *prg.mem[int32(r1)+heightOffset].int() = *prg.mem[int32(q)+heightOffset].int()
- *prg.mem[int32(r1)+depthOffset].int() = *prg.mem[int32(q)+depthOffset].int()
- if t == *prg.mem[int32(r1)+widthOffset].int() {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = byte(normal)
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
- } else if t > *prg.mem[int32(r1)+widthOffset].int() {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(stretching)
- if *prg.mem[int32(r1)+glueOffset].int() == 0 {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
- } else {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(float64(t-*prg.mem[int32(r1)+widthOffset].int()) / float64(*prg.mem[int32(r1)+glueOffset].int()))
- }
- // \xref[real division]
- } else {
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = *(*prg.mem[int32(r1)+listOffset].hh()).b0()
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(shrinking)
- if *prg.mem[int32(r1)+4].int() == 0 {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
- } else if int32(*(*prg.mem[int32(r1)+listOffset].hh()).b1()) == normal && *prg.mem[int32(r1)+widthOffset].int()-t > *prg.mem[int32(r1)+4].int() {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(1.0)
- } else {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(float64(*prg.mem[int32(r1)+widthOffset].int()-t) / float64(*prg.mem[int32(r1)+4].int()))
- }
- }
- *prg.mem[int32(r1)+widthOffset].int() = w
- *(*prg.mem[r1].hh()).b0() = byte(hlistNode)
- } else {
- // Make the unset node |r| into a |vlist_node| of height |w|, setting the glue as if the height were |t|
- *prg.mem[int32(r1)+widthOffset].int() = *prg.mem[int32(q)+widthOffset].int()
- if t == *prg.mem[int32(r1)+heightOffset].int() {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(normal)
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = byte(normal)
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
- } else if t > *prg.mem[int32(r1)+heightOffset].int() {
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(stretching)
- if *prg.mem[int32(r1)+glueOffset].int() == 0 {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
- } else {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(float64(t-*prg.mem[int32(r1)+heightOffset].int()) / float64(*prg.mem[int32(r1)+glueOffset].int()))
- }
- // \xref[real division]
- } else {
- *(*prg.mem[int32(r1)+listOffset].hh()).b1() = *(*prg.mem[int32(r1)+listOffset].hh()).b0()
- *(*prg.mem[int32(r1)+listOffset].hh()).b0() = byte(shrinking)
- if *prg.mem[int32(r1)+4].int() == 0 {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(0.0)
- } else if int32(*(*prg.mem[int32(r1)+listOffset].hh()).b1()) == normal && *prg.mem[int32(r1)+heightOffset].int()-t > *prg.mem[int32(r1)+4].int() {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(1.0)
- } else {
- *prg.mem[int32(r1)+glueOffset].gr() = float32(float64(*prg.mem[int32(r1)+heightOffset].int()-t) / float64(*prg.mem[int32(r1)+4].int()))
- }
- }
- *prg.mem[int32(r1)+heightOffset].int() = w
- *(*prg.mem[r1].hh()).b0() = byte(vlistNode)
- }
- *prg.mem[int32(r1)+4].int() = 0
- if int32(u) != 30000-4 {
- *(*prg.mem[u].hh()).rh() = *(*prg.mem[r1].hh()).rh()
- *(*prg.mem[r1].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
- r1 = u
- }
- r1 = *(*prg.mem[*(*prg.mem[r1].hh()).rh()].hh()).rh()
- s = *(*prg.mem[*(*prg.mem[s].hh()).rh()].hh()).rh()
- if int32(r1) == 0 {
- break
- }
- }
- } else if int32(*(*prg.mem[q].hh()).b0()) == ruleNode {
- if *prg.mem[int32(q)+widthOffset].int() == -010000000000 {
- *prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(p)+widthOffset].int()
- }
- if *prg.mem[int32(q)+heightOffset].int() == -010000000000 {
- *prg.mem[int32(q)+heightOffset].int() = *prg.mem[int32(p)+heightOffset].int()
- }
- if *prg.mem[int32(q)+depthOffset].int() == -010000000000 {
- *prg.mem[int32(q)+depthOffset].int() = *prg.mem[int32(p)+depthOffset].int()
- }
- if o != 0 {
- r1 = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = 0
- q = prg.hpack(q, scaled(0), smallNumber(additional))
- *prg.mem[int32(q)+4].int() = o
- *(*prg.mem[q].hh()).rh() = r1
- *(*prg.mem[s].hh()).rh() = q
- }
- }
- }
- s = q
- q = *(*prg.mem[q].hh()).rh()
- }
- prg.flushNodeList(p)
- prg.popAlignment()
- // Insert the \(c)current list into its environment
- auxSave = prg.curList.auxField
- p = *(*prg.mem[prg.curList.headField].hh()).rh()
- q = prg.curList.tailField
- prg.popNest()
- if int32(prg.curList.modeField) == mmode {
- prg.doAssignments()
- if int32(prg.curCmd) != mathShift {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing $$ inserted" */ 1170)
- }
- // \xref[Missing [\$\$] inserted]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Displays can use special alignments (like \\eqalignno)" */ 895
- prg.helpLine[0] = /* "only if nothing but the alignment itself is between $$'s." */ 896
- }
- prg.backError()
- } else {
- // Check that another \.\$ follows
- prg.getXToken()
- if int32(prg.curCmd) != mathShift {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Display math should end with $$" */ 1166)
- }
- // \xref[Display math...with \$\$]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "The `$' that I just saw supposedly matches a previous `$$'." */ 1167
- prg.helpLine[0] = /* "So I shall assume that you typed `$$' both times." */ 1168
- }
- prg.backError()
- }
- }
- prg.popNest()
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(*prg.eqtb[intBase+preDisplayPenaltyCode-1].int())
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(smallNumber(aboveDisplaySkipCode))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- if int32(p) != 0 {
- prg.curList.tailField = q
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(*prg.eqtb[intBase+postDisplayPenaltyCode-1].int())
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(smallNumber(belowDisplaySkipCode))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *prg.curList.auxField.int() = *auxSave.int()
- prg.resumeAfterDisplay()
- } else {
- prg.curList.auxField = auxSave
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- if int32(p) != 0 {
- prg.curList.tailField = q
- }
- if int32(prg.curList.modeField) == vmode {
- prg.buildPage()
- }
- }
- }
- //
- func (prg *prg) alignPeek() {
- restart:
- prg.alignState = 1000000
- // Get the next non-blank non-call token
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- if int32(prg.curCmd) == noAlign {
- prg.scanLeftBrace()
- prg.newSaveLevel(groupCode(noAlignGroup))
- if int32(prg.curList.modeField) == -vmode {
- prg.normalParagraph()
- }
- } else if int32(prg.curCmd) == rightBrace {
- prg.finAlign()
- } else if int32(prg.curCmd) == carRet && int32(prg.curChr) == crCrCode {
- goto restart
- } else {
- prg.initRow() // start a new row
- prg.initCol() // start a new column and replace what we peeked at
- }
- }
- // 813. \[38] Breaking paragraphs into lines
- // tangle:pos tex.web:15997:39:
- // We come now to what is probably the most interesting algorithm of \TeX:
- // the mechanism for choosing the ``best possible'' breakpoints that yield
- // the individual lines of a paragraph. \TeX's line-breaking algorithm takes
- // a given horizontal list and converts it to a sequence of boxes that are
- // appended to the current vertical list. In the course of doing this, it
- // creates a special data structure containing three kinds of records that are
- // not used elsewhere in \TeX. Such nodes are created while a paragraph is
- // being processed, and they are destroyed afterwards; thus, the other parts
- // of \TeX\ do not need to know anything about how line-breaking is done.
- //
- // The method used here is based on an approach devised by Michael F. Plass and
- // \xref[Plass, Michael Frederick]
- // \xref[Knuth, Donald Ervin]
- // the author in 1977, subsequently generalized and improved by the same two
- // people in 1980. A detailed discussion appears in [\sl Software---Practice
- // and Experience \bf11] (1981), 1119--1184, where it is shown that the
- // line-breaking problem can be regarded as a special case of the problem of
- // computing the shortest path in an acyclic network. The cited paper includes
- // numerous examples and describes the history of line breaking as it has been
- // practiced by printers through the ages. The present implementation adds two
- // new ideas to the algorithm of 1980: Memory space requirements are considerably
- // reduced by using smaller records for inactive nodes than for active ones,
- // and arithmetic overflow is avoided by using ``delta distances'' instead of
- // keeping track of the total distance from the beginning of the paragraph to the
- // current point.
- // 815.
- // tangle:pos tex.web:16048:1:
- // Since |line_break| is a rather lengthy procedure---sort of a small world unto
- // itself---we must build it up little by little, somewhat more cautiously
- // than we have done with the simpler procedures of \TeX. Here is the
- // general outline.
- // \4
- // Declare subprocedures for |line_break|
- func (prg *prg) finiteShrink(p halfword) (r halfword) { // recovers from infinite shrinkage
- var (
- q halfword // new glue specification
- )
- if prg.noShrinkErrorYet {
- prg.noShrinkErrorYet = false
- // if eqtb[int_base+ tracing_paragraphs_code].int >0 then end_diagnostic(true); [ ]
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Infinite glue shrinkage found in a paragraph" */ 917)
- }
- // \xref[Infinite glue shrinkage...]
- {
- prg.helpPtr = 5
- prg.helpLine[4] = /* "The paragraph just ended includes some glue that has" */ 918
- prg.helpLine[3] = /* "infinite shrinkability, e.g., `\\hskip 0pt minus 1fil'." */ 919
- prg.helpLine[2] = /* "Such glue doesn't belong there---it allows a paragraph" */ 920
- prg.helpLine[1] = /* "of any length to fit on one line. But it's safe to proceed," */ 921
- prg.helpLine[0] = /* "since the offensive shrinkability has been made finite." */ 922
- }
- prg.error1()
- // if eqtb[int_base+ tracing_paragraphs_code].int >0 then begin_diagnostic; [ ]
- }
- q = prg.newSpec(p)
- *(*prg.mem[q].hh()).b1() = byte(normal)
- prg.deleteGlueRef(p)
- r = q
- return r
- }
- func (prg *prg) tryBreak(pi int32, breakType smallNumber) {
- var (
- r1 halfword // runs through the active list
- prevR halfword // stays a step behind |r|
- oldL halfword // maximum line number in current equivalence class of lines
- noBreakYet bool // have we found a feasible break at |cur_p|?
- // Other local variables for |try_break|
- prevPrevR halfword // a step behind |prev_r|, if |type(prev_r)=delta_node|
- s halfword // runs through nodes ahead of |cur_p|
- q halfword // points to a new node being created
- v halfword // points to a glue specification or a node ahead of |cur_p|
- t int32 // node count, if |cur_p| is a discretionary node
- f internalFontNumber // used in character width calculation
- l halfword // line number of current active node
- nodeRStaysActive bool // should node |r| remain in the active list?
- lineWidth scaled // the current line will be justified to this width
- fitClass/* veryLooseFit..tightFit */ byte // possible fitness class of test line
- b halfword // badness of test line
- d int32 // demerits of test line
- artificialDemerits bool // has |d| been forced to zero?
- shortfall scaled // used in badness calculations
- )
- if abs(pi) >= infPenalty {
- if pi > 0 {
- goto exit
- } else {
- pi = ejectPenalty
- }
- }
- noBreakYet = true
- prevR = uint16(30000 - 7)
- oldL = 0
- prg.curActiveWidth[1-1] = prg.activeWidth[1-1]
- prg.curActiveWidth[2-1] = prg.activeWidth[2-1]
- prg.curActiveWidth[3-1] = prg.activeWidth[3-1]
- prg.curActiveWidth[4-1] = prg.activeWidth[4-1]
- prg.curActiveWidth[5-1] = prg.activeWidth[5-1]
- prg.curActiveWidth[6-1] = prg.activeWidth[6-1]
- for true {
- continue1:
- r1 = *(*prg.mem[prevR].hh()).rh()
- // If node |r| is of type |delta_node|, update |cur_active_width|, set |prev_r| and |prev_prev_r|, then |goto continue|
- // \xref[inner loop]
- if int32(*(*prg.mem[r1].hh()).b0()) == deltaNode {
- prg.curActiveWidth[1-1] = prg.curActiveWidth[1-1] + *prg.mem[int32(r1)+1].int()
- prg.curActiveWidth[2-1] = prg.curActiveWidth[2-1] + *prg.mem[int32(r1)+2].int()
- prg.curActiveWidth[3-1] = prg.curActiveWidth[3-1] + *prg.mem[int32(r1)+3].int()
- prg.curActiveWidth[4-1] = prg.curActiveWidth[4-1] + *prg.mem[int32(r1)+4].int()
- prg.curActiveWidth[5-1] = prg.curActiveWidth[5-1] + *prg.mem[int32(r1)+5].int()
- prg.curActiveWidth[6-1] = prg.curActiveWidth[6-1] + *prg.mem[int32(r1)+6].int()
- prevPrevR = prevR
- prevR = r1
- goto continue1
- }
- // If a line number class has ended, create new active nodes for the best feasible breaks in that class; then |return| if |r=last_active|, otherwise compute the new |line_width|
- {
- l = *(*prg.mem[int32(r1)+1].hh()).lh()
- if int32(l) > int32(oldL) {
- if prg.minimumDemerits < 07777777777 && (int32(oldL) != int32(prg.easyLine) || int32(r1) == 30000-7) {
- if noBreakYet {
- noBreakYet = false
- prg.breakWidth[1-1] = prg.background[1-1]
- prg.breakWidth[2-1] = prg.background[2-1]
- prg.breakWidth[3-1] = prg.background[3-1]
- prg.breakWidth[4-1] = prg.background[4-1]
- prg.breakWidth[5-1] = prg.background[5-1]
- prg.breakWidth[6-1] = prg.background[6-1]
- s = prg.curP
- if int32(breakType) > unhyphenated {
- if int32(prg.curP) != 0 {
- t = int32(*(*prg.mem[prg.curP].hh()).b1())
- v = prg.curP
- s = *(*prg.mem[int32(prg.curP)+1].hh()).rh()
- for t > 0 {
- t = t - 1
- v = *(*prg.mem[v].hh()).rh()
- // Subtract the width of node |v| from |break_width|
- if int32(v) >= int32(prg.hiMemMin) {
- f = *(*prg.mem[v].hh()).b0()
- prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[v].hh()).b1())].qqqq()).b0)].int()
- } else {
- switch *(*prg.mem[v].hh()).b0() {
- case ligatureNode:
- f = *(*prg.mem[int32(v)+1].hh()).b0()
- prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(v)+1].hh()).b1())].qqqq()).b0)].int()
- case hlistNode, vlistNode, ruleNode, kernNode:
- prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.mem[int32(v)+widthOffset].int()
- default:
- prg.confusion(strNumber( /* "disc1" */ 923))
- // \xref[this can't happen disc1][\quad disc1]
- }
- }
- }
- for int32(s) != 0 {
- if int32(s) >= int32(prg.hiMemMin) {
- f = *(*prg.mem[s].hh()).b0()
- prg.breakWidth[1-1] = prg.breakWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[s].hh()).b1())].qqqq()).b0)].int()
- } else {
- switch *(*prg.mem[s].hh()).b0() {
- case ligatureNode:
- f = *(*prg.mem[int32(s)+1].hh()).b0()
- prg.breakWidth[1-1] = prg.breakWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(s)+1].hh()).b1())].qqqq()).b0)].int()
- case hlistNode, vlistNode, ruleNode, kernNode:
- prg.breakWidth[1-1] = prg.breakWidth[1-1] + *prg.mem[int32(s)+widthOffset].int()
- default:
- prg.confusion(strNumber( /* "disc2" */ 924))
- // \xref[this can't happen disc2][\quad disc2]
- }
- }
- s = *(*prg.mem[s].hh()).rh()
- }
- prg.breakWidth[1-1] = prg.breakWidth[1-1] + prg.discWidth
- if int32(*(*prg.mem[int32(prg.curP)+1].hh()).rh()) == 0 {
- s = *(*prg.mem[v].hh()).rh()
- }
- // nodes may be discardable after the break
- }
- }
- for int32(s) != 0 {
- if int32(s) >= int32(prg.hiMemMin) {
- goto done
- }
- switch *(*prg.mem[s].hh()).b0() {
- case glueNode:
- // Subtract glue from |break_width|
- v = *(*prg.mem[int32(s)+1].hh()).lh()
- prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.mem[int32(v)+widthOffset].int()
- prg.breakWidth[2+int32(*(*prg.mem[v].hh()).b0())-1] = prg.breakWidth[2+int32(*(*prg.mem[v].hh()).b0())-1] - *prg.mem[int32(v)+2].int()
- prg.breakWidth[6-1] = prg.breakWidth[6-1] - *prg.mem[int32(v)+3].int()
- case penaltyNode:
- case mathNode:
- prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.mem[int32(s)+widthOffset].int()
- case kernNode:
- if int32(*(*prg.mem[s].hh()).b1()) != explicit {
- goto done
- } else {
- prg.breakWidth[1-1] = prg.breakWidth[1-1] - *prg.mem[int32(s)+widthOffset].int()
- }
- default:
- goto done
- }
- s = *(*prg.mem[s].hh()).rh()
- }
- done:
- }
- // Insert a delta node to prepare for breaks at |cur_p|
- if int32(*(*prg.mem[prevR].hh()).b0()) == deltaNode {
- *prg.mem[int32(prevR)+1].int() = *prg.mem[int32(prevR)+1].int() - prg.curActiveWidth[1-1] + prg.breakWidth[1-1]
- *prg.mem[int32(prevR)+2].int() = *prg.mem[int32(prevR)+2].int() - prg.curActiveWidth[2-1] + prg.breakWidth[2-1]
- *prg.mem[int32(prevR)+3].int() = *prg.mem[int32(prevR)+3].int() - prg.curActiveWidth[3-1] + prg.breakWidth[3-1]
- *prg.mem[int32(prevR)+4].int() = *prg.mem[int32(prevR)+4].int() - prg.curActiveWidth[4-1] + prg.breakWidth[4-1]
- *prg.mem[int32(prevR)+5].int() = *prg.mem[int32(prevR)+5].int() - prg.curActiveWidth[5-1] + prg.breakWidth[5-1]
- *prg.mem[int32(prevR)+6].int() = *prg.mem[int32(prevR)+6].int() - prg.curActiveWidth[6-1] + prg.breakWidth[6-1]
- } else if int32(prevR) == 30000-7 {
- prg.activeWidth[1-1] = prg.breakWidth[1-1]
- prg.activeWidth[2-1] = prg.breakWidth[2-1]
- prg.activeWidth[3-1] = prg.breakWidth[3-1]
- prg.activeWidth[4-1] = prg.breakWidth[4-1]
- prg.activeWidth[5-1] = prg.breakWidth[5-1]
- prg.activeWidth[6-1] = prg.breakWidth[6-1]
- } else {
- q = prg.getNode(deltaNodeSize)
- *(*prg.mem[q].hh()).rh() = r1
- *(*prg.mem[q].hh()).b0() = byte(deltaNode)
- *(*prg.mem[q].hh()).b1() = 0 // the |subtype| is not used
- *prg.mem[int32(q)+1].int() = prg.breakWidth[1-1] - prg.curActiveWidth[1-1]
- *prg.mem[int32(q)+2].int() = prg.breakWidth[2-1] - prg.curActiveWidth[2-1]
- *prg.mem[int32(q)+3].int() = prg.breakWidth[3-1] - prg.curActiveWidth[3-1]
- *prg.mem[int32(q)+4].int() = prg.breakWidth[4-1] - prg.curActiveWidth[4-1]
- *prg.mem[int32(q)+5].int() = prg.breakWidth[5-1] - prg.curActiveWidth[5-1]
- *prg.mem[int32(q)+6].int() = prg.breakWidth[6-1] - prg.curActiveWidth[6-1]
- *(*prg.mem[prevR].hh()).rh() = q
- prevPrevR = prevR
- prevR = q
- }
- if abs(*prg.eqtb[intBase+adjDemeritsCode-1].int()) >= 07777777777-prg.minimumDemerits {
- prg.minimumDemerits = 07777777777 - 1
- } else {
- prg.minimumDemerits = prg.minimumDemerits + abs(*prg.eqtb[intBase+adjDemeritsCode-1].int())
- }
- for ii := int32(veryLooseFit); ii <= tightFit; ii++ {
- fitClass = byte(ii)
- _ = fitClass
- if prg.minimalDemerits[fitClass] <= prg.minimumDemerits {
- q = prg.getNode(passiveNodeSize)
- *(*prg.mem[q].hh()).rh() = prg.passive
- prg.passive = q
- *(*prg.mem[int32(q)+1].hh()).rh() = prg.curP
- // pass_number:= pass_number+1 ; mem[ q].hh.lh :=pass_number; [ ]
- *(*prg.mem[int32(q)+1].hh()).lh() = prg.bestPlace[fitClass]
- q = prg.getNode(activeNodeSize)
- *(*prg.mem[int32(q)+1].hh()).rh() = prg.passive
- *(*prg.mem[int32(q)+1].hh()).lh() = uint16(int32(prg.bestPlLine[fitClass]) + 1)
- *(*prg.mem[q].hh()).b1() = fitClass
- *(*prg.mem[q].hh()).b0() = breakType
- *prg.mem[int32(q)+2].int() = prg.minimalDemerits[fitClass]
- *(*prg.mem[q].hh()).rh() = r1
- *(*prg.mem[prevR].hh()).rh() = q
- prevR = q
- // if eqtb[int_base+ tracing_paragraphs_code].int >0 then
- //
- // [ Print a symbolic description of the new break node ]
- // begin print_nl(["@@"=]925); print_int( mem[ passive].hh.lh );
- // [ \xref[\AT!\AT!] ]
- // print([": line "=]926); print_int( mem[ q+ 1].hh.lh -1);
- // print_char(["."=]46); print_int(fit_class);
- // if break_type=hyphenated then print_char(["-"=]45);
- // print([" t="=]927); print_int(mem[ q+2].int );
- // print([" -> @@"=]928);
- // if mem[ passive+ 1].hh.lh =0 then print_char(["0"=]48)
- // else print_int( mem[ mem[ passive+ 1].hh.lh ].hh.lh );
- // end
- //
- // ;
- // [ ]
- }
- prg.minimalDemerits[fitClass] = 07777777777
- }
- prg.minimumDemerits = 07777777777
- // Insert a delta node to prepare for the next active node
- if int32(r1) != 30000-7 {
- q = prg.getNode(deltaNodeSize)
- *(*prg.mem[q].hh()).rh() = r1
- *(*prg.mem[q].hh()).b0() = byte(deltaNode)
- *(*prg.mem[q].hh()).b1() = 0 // the |subtype| is not used
- *prg.mem[int32(q)+1].int() = prg.curActiveWidth[1-1] - prg.breakWidth[1-1]
- *prg.mem[int32(q)+2].int() = prg.curActiveWidth[2-1] - prg.breakWidth[2-1]
- *prg.mem[int32(q)+3].int() = prg.curActiveWidth[3-1] - prg.breakWidth[3-1]
- *prg.mem[int32(q)+4].int() = prg.curActiveWidth[4-1] - prg.breakWidth[4-1]
- *prg.mem[int32(q)+5].int() = prg.curActiveWidth[5-1] - prg.breakWidth[5-1]
- *prg.mem[int32(q)+6].int() = prg.curActiveWidth[6-1] - prg.breakWidth[6-1]
- *(*prg.mem[prevR].hh()).rh() = q
- prevPrevR = prevR
- prevR = q
- }
- }
- if int32(r1) == 30000-7 {
- goto exit
- }
- // Compute the new line width
- if int32(l) > int32(prg.easyLine) {
- lineWidth = prg.secondWidth
- oldL = uint16(65535 - 1)
- } else {
- oldL = l
- if int32(l) > int32(prg.lastSpecialLine) {
- lineWidth = prg.secondWidth
- } else if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
- lineWidth = prg.firstWidth
- } else {
- lineWidth = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*int32(l)].int()
- }
- }
- }
- }
- // Consider the demerits for a line from |r| to |cur_p|; deactivate node |r| if it should no longer be active; then |goto continue| if a line from |r| to |cur_p| is infeasible, otherwise record a new feasible break
- {
- artificialDemerits = false
- // \xref[inner loop]
- shortfall = lineWidth - prg.curActiveWidth[1-1] // we're this much too short
- if shortfall > 0 {
- if prg.curActiveWidth[3-1] != 0 || prg.curActiveWidth[4-1] != 0 || prg.curActiveWidth[5-1] != 0 {
- b = 0
- fitClass = byte(decentFit) // infinite stretch
- } else {
- if shortfall > 7230584 {
- if prg.curActiveWidth[2-1] < 1663497 {
- b = uint16(infBad)
- fitClass = byte(veryLooseFit)
- goto done1
- }
- }
- b = prg.badness(shortfall, prg.curActiveWidth[2-1])
- if int32(b) > 12 {
- if int32(b) > 99 {
- fitClass = byte(veryLooseFit)
- } else {
- fitClass = byte(looseFit)
- }
- } else {
- fitClass = byte(decentFit)
- }
- done1:
- }
- } else {
- // Set the value of |b| to the badness for shrinking the line, and compute the corresponding |fit_class|
- if -shortfall > prg.curActiveWidth[6-1] {
- b = uint16(infBad + 1)
- } else {
- b = prg.badness(-shortfall, prg.curActiveWidth[6-1])
- }
- if int32(b) > 12 {
- fitClass = byte(tightFit)
- } else {
- fitClass = byte(decentFit)
- }
- }
- if int32(b) > infBad || pi == ejectPenalty {
- if prg.finalPass && prg.minimumDemerits == 07777777777 && int32(*(*prg.mem[r1].hh()).rh()) == 30000-7 && int32(prevR) == 30000-7 {
- artificialDemerits = true
- } else if int32(b) > prg.threshold {
- goto deactivate
- }
- nodeRStaysActive = false
- } else {
- prevR = r1
- if int32(b) > prg.threshold {
- goto continue1
- }
- nodeRStaysActive = true
- }
- // Record a new feasible break
- if artificialDemerits {
- d = 0
- } else {
- // Compute the demerits, |d|, from |r| to |cur_p|
- d = *prg.eqtb[intBase+linePenaltyCode-1].int() + int32(b)
- if abs(d) >= 10000 {
- d = 100000000
- } else {
- d = d * d
- }
- if pi != 0 {
- if pi > 0 {
- d = d + pi*pi
- } else if pi > ejectPenalty {
- d = d - pi*pi
- }
- }
- if int32(breakType) == hyphenated && int32(*(*prg.mem[r1].hh()).b0()) == hyphenated {
- if int32(prg.curP) != 0 {
- d = d + *prg.eqtb[intBase+doubleHyphenDemeritsCode-1].int()
- } else {
- d = d + *prg.eqtb[intBase+finalHyphenDemeritsCode-1].int()
- }
- }
- if abs(int32(fitClass)-int32(*(*prg.mem[r1].hh()).b1())) > 1 {
- d = d + *prg.eqtb[intBase+adjDemeritsCode-1].int()
- }
- }
- // if eqtb[int_base+ tracing_paragraphs_code].int >0 then
- //
- // [ Print a symbolic description of this feasible break ]
- // begin if printed_node<>cur_p then
- //
- // [ Print the list between |printed_node| and |cur_p|, then set |printed_node:=cur_p| ]
- // begin print_nl([""=]338);
- // if cur_p=0 then short_display( mem[ printed_node].hh.rh )
- // else begin save_link:= mem[ cur_p].hh.rh ;
- // mem[ cur_p].hh.rh :=0 ; print_nl([""=]338); short_display( mem[ printed_node].hh.rh );
- // mem[ cur_p].hh.rh :=save_link;
- // end;
- // printed_node:=cur_p;
- // end
- //
- // ;
- // print_nl(["@"=]64);
- // [ \xref[\AT!] ]
- // if cur_p=0 then print_esc(["par"=]597)
- // else if mem[ cur_p].hh.b0 <>glue_node then
- // begin if mem[ cur_p].hh.b0 =penalty_node then print_esc(["penalty"=]531)
- // else if mem[ cur_p].hh.b0 =disc_node then print_esc(["discretionary"=]349)
- // else if mem[ cur_p].hh.b0 =kern_node then print_esc(["kern"=]340)
- // else print_esc(["math"=]343);
- // end;
- // print([" via @@"=]929);
- // if mem[ r+ 1].hh.rh =0 then print_char(["0"=]48)
- // else print_int( mem[ mem[ r+ 1].hh.rh ].hh.lh );
- // print([" b="=]930);
- // if b>inf_bad then print_char(["*"=]42) else print_int(b);
- // [ \xref[*\relax] ]
- // print([" p="=]931); print_int(pi); print([" d="=]932);
- // if artificial_demerits then print_char(["*"=]42) else print_int(d);
- // end
- //
- // ;
- // [ ]
- d = d + *prg.mem[int32(r1)+2].int() // this is the minimum total demerits
- // from the beginning to |cur_p| via |r|
- if d <= prg.minimalDemerits[fitClass] {
- prg.minimalDemerits[fitClass] = d
- prg.bestPlace[fitClass] = *(*prg.mem[int32(r1)+1].hh()).rh()
- prg.bestPlLine[fitClass] = l
- if d < prg.minimumDemerits {
- prg.minimumDemerits = d
- }
- }
- if nodeRStaysActive {
- goto continue1
- } // |prev_r| has been set to |r|
- // |prev_r| has been set to |r|
- deactivate:
- *(*prg.mem[prevR].hh()).rh() = *(*prg.mem[r1].hh()).rh()
- prg.freeNode(r1, halfword(activeNodeSize))
- if int32(prevR) == 30000-7 {
- r1 = *(*prg.mem[30000-7].hh()).rh()
- if int32(*(*prg.mem[r1].hh()).b0()) == deltaNode {
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(r1)+1].int()
- prg.activeWidth[2-1] = prg.activeWidth[2-1] + *prg.mem[int32(r1)+2].int()
- prg.activeWidth[3-1] = prg.activeWidth[3-1] + *prg.mem[int32(r1)+3].int()
- prg.activeWidth[4-1] = prg.activeWidth[4-1] + *prg.mem[int32(r1)+4].int()
- prg.activeWidth[5-1] = prg.activeWidth[5-1] + *prg.mem[int32(r1)+5].int()
- prg.activeWidth[6-1] = prg.activeWidth[6-1] + *prg.mem[int32(r1)+6].int()
- prg.curActiveWidth[1-1] = prg.activeWidth[1-1]
- prg.curActiveWidth[2-1] = prg.activeWidth[2-1]
- prg.curActiveWidth[3-1] = prg.activeWidth[3-1]
- prg.curActiveWidth[4-1] = prg.activeWidth[4-1]
- prg.curActiveWidth[5-1] = prg.activeWidth[5-1]
- prg.curActiveWidth[6-1] = prg.activeWidth[6-1]
- *(*prg.mem[30000-7].hh()).rh() = *(*prg.mem[r1].hh()).rh()
- prg.freeNode(r1, halfword(deltaNodeSize))
- }
- } else if int32(*(*prg.mem[prevR].hh()).b0()) == deltaNode {
- r1 = *(*prg.mem[prevR].hh()).rh()
- if int32(r1) == 30000-7 {
- prg.curActiveWidth[1-1] = prg.curActiveWidth[1-1] - *prg.mem[int32(prevR)+1].int()
- prg.curActiveWidth[2-1] = prg.curActiveWidth[2-1] - *prg.mem[int32(prevR)+2].int()
- prg.curActiveWidth[3-1] = prg.curActiveWidth[3-1] - *prg.mem[int32(prevR)+3].int()
- prg.curActiveWidth[4-1] = prg.curActiveWidth[4-1] - *prg.mem[int32(prevR)+4].int()
- prg.curActiveWidth[5-1] = prg.curActiveWidth[5-1] - *prg.mem[int32(prevR)+5].int()
- prg.curActiveWidth[6-1] = prg.curActiveWidth[6-1] - *prg.mem[int32(prevR)+6].int()
- *(*prg.mem[prevPrevR].hh()).rh() = uint16(30000 - 7)
- prg.freeNode(prevR, halfword(deltaNodeSize))
- prevR = prevPrevR
- } else if int32(*(*prg.mem[r1].hh()).b0()) == deltaNode {
- prg.curActiveWidth[1-1] = prg.curActiveWidth[1-1] + *prg.mem[int32(r1)+1].int()
- prg.curActiveWidth[2-1] = prg.curActiveWidth[2-1] + *prg.mem[int32(r1)+2].int()
- prg.curActiveWidth[3-1] = prg.curActiveWidth[3-1] + *prg.mem[int32(r1)+3].int()
- prg.curActiveWidth[4-1] = prg.curActiveWidth[4-1] + *prg.mem[int32(r1)+4].int()
- prg.curActiveWidth[5-1] = prg.curActiveWidth[5-1] + *prg.mem[int32(r1)+5].int()
- prg.curActiveWidth[6-1] = prg.curActiveWidth[6-1] + *prg.mem[int32(r1)+6].int()
- *prg.mem[int32(prevR)+1].int() = *prg.mem[int32(prevR)+1].int() + *prg.mem[int32(r1)+1].int()
- *prg.mem[int32(prevR)+2].int() = *prg.mem[int32(prevR)+2].int() + *prg.mem[int32(r1)+2].int()
- *prg.mem[int32(prevR)+3].int() = *prg.mem[int32(prevR)+3].int() + *prg.mem[int32(r1)+3].int()
- *prg.mem[int32(prevR)+4].int() = *prg.mem[int32(prevR)+4].int() + *prg.mem[int32(r1)+4].int()
- *prg.mem[int32(prevR)+5].int() = *prg.mem[int32(prevR)+5].int() + *prg.mem[int32(r1)+5].int()
- *prg.mem[int32(prevR)+6].int() = *prg.mem[int32(prevR)+6].int() + *prg.mem[int32(r1)+6].int()
- *(*prg.mem[prevR].hh()).rh() = *(*prg.mem[r1].hh()).rh()
- prg.freeNode(r1, halfword(deltaNodeSize))
- }
- }
- }
- }
- exit:
- }
- func (prg *prg) postLineBreak(finalWidowPenalty int32) {
- var (
- q, r1, s halfword // temporary registers for list manipulation
- discBreak bool // was the current break at a discretionary node?
- postDiscBreak bool // and did it have a nonempty post-break part?
- curWidth scaled // width of line number |cur_line|
- curIndent scaled // left margin of line number |cur_line|
- t quarterword // used for replacement counts in discretionary nodes
- pen int32 // use when calculating penalties between lines
- curLine halfword // the current line number being justified
- )
- q = *(*prg.mem[int32(prg.bestBet)+1].hh()).rh()
- prg.curP = 0
- for {
- r1 = q
- q = *(*prg.mem[int32(q)+1].hh()).lh()
- *(*prg.mem[int32(r1)+1].hh()).lh() = prg.curP
- prg.curP = r1
- if int32(q) == 0 {
- break
- }
- }
- curLine = uint16(prg.curList.pgField + 1)
- for {
- // Justify the line ending at breakpoint |cur_p|, and append it to the current vertical list, together with associated penalties and other insertions
- // Modify the end of the line to reflect the nature of the break and to include \.[\\rightskip]; also set the proper value of |disc_break|
- q = *(*prg.mem[int32(prg.curP)+1].hh()).rh()
- discBreak = false
- postDiscBreak = false
- if int32(q) != 0 {
- if int32(*(*prg.mem[q].hh()).b0()) == glueNode {
- prg.deleteGlueRef(*(*prg.mem[int32(q)+1].hh()).lh())
- *(*prg.mem[int32(q)+1].hh()).lh() = *(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()
- *(*prg.mem[q].hh()).b1() = byte(rightSkipCode + 1)
- *(*prg.mem[*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()].hh()).rh() = uint16(int32(*(*prg.mem[*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()].hh()).rh()) + 1)
- goto done
- } else {
- if int32(*(*prg.mem[q].hh()).b0()) == discNode {
- t = *(*prg.mem[q].hh()).b1()
- // Destroy the |t| nodes following |q|, and make |r| point to the following node
- if int32(t) == 0 {
- r1 = *(*prg.mem[q].hh()).rh()
- } else {
- r1 = q
- for int32(t) > 1 {
- r1 = *(*prg.mem[r1].hh()).rh()
- t = byte(int32(t) - 1)
- }
- s = *(*prg.mem[r1].hh()).rh()
- r1 = *(*prg.mem[s].hh()).rh()
- *(*prg.mem[s].hh()).rh() = 0
- prg.flushNodeList(*(*prg.mem[q].hh()).rh())
- *(*prg.mem[q].hh()).b1() = 0
- }
- if int32(*(*prg.mem[int32(q)+1].hh()).rh()) != 0 {
- s = *(*prg.mem[int32(q)+1].hh()).rh()
- for int32(*(*prg.mem[s].hh()).rh()) != 0 {
- s = *(*prg.mem[s].hh()).rh()
- }
- *(*prg.mem[s].hh()).rh() = r1
- r1 = *(*prg.mem[int32(q)+1].hh()).rh()
- *(*prg.mem[int32(q)+1].hh()).rh() = 0
- postDiscBreak = true
- }
- if int32(*(*prg.mem[int32(q)+1].hh()).lh()) != 0 {
- s = *(*prg.mem[int32(q)+1].hh()).lh()
- *(*prg.mem[q].hh()).rh() = s
- for int32(*(*prg.mem[s].hh()).rh()) != 0 {
- s = *(*prg.mem[s].hh()).rh()
- }
- *(*prg.mem[int32(q)+1].hh()).lh() = 0
- q = s
- }
- *(*prg.mem[q].hh()).rh() = r1
- discBreak = true
- } else if int32(*(*prg.mem[q].hh()).b0()) == mathNode || int32(*(*prg.mem[q].hh()).b0()) == kernNode {
- *prg.mem[int32(q)+widthOffset].int() = 0
- }
- }
- } else {
- q = uint16(30000 - 3)
- for int32(*(*prg.mem[q].hh()).rh()) != 0 {
- q = *(*prg.mem[q].hh()).rh()
- }
- }
- // Put the \(r)\.[\\rightskip] glue after node |q|
- r1 = prg.newParamGlue(smallNumber(rightSkipCode))
- *(*prg.mem[r1].hh()).rh() = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = r1
- q = r1
- done:
- ;
- // Put the \(l)\.[\\leftskip] glue at the left and detach this line
- r1 = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = 0
- q = *(*prg.mem[30000-3].hh()).rh()
- *(*prg.mem[30000-3].hh()).rh() = r1
- if int32(*(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh()) != memBot {
- r1 = prg.newParamGlue(smallNumber(leftSkipCode))
- *(*prg.mem[r1].hh()).rh() = q
- q = r1
- }
- // Call the packaging subroutine, setting |just_box| to the justified box
- if int32(curLine) > int32(prg.lastSpecialLine) {
- curWidth = prg.secondWidth
- curIndent = prg.secondIndent
- } else if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
- curWidth = prg.firstWidth
- curIndent = prg.firstIndent
- } else {
- curWidth = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*int32(curLine)].int()
- curIndent = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*int32(curLine)-1].int()
- }
- prg.adjustTail = uint16(30000 - 5)
- prg.justBox = prg.hpack(q, curWidth, smallNumber(exactly))
- *prg.mem[int32(prg.justBox)+4].int() = curIndent
- // Append the new box to the current vertical list, followed by the list of special nodes taken out of the box by the packager
- prg.appendToVlist(prg.justBox)
- if 30000-5 != int32(prg.adjustTail) {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[30000-5].hh()).rh()
- prg.curList.tailField = prg.adjustTail
- }
- prg.adjustTail = 0
- // Append a penalty node, if a nonzero penalty is appropriate
- if int32(curLine)+1 != int32(prg.bestLine) {
- pen = *prg.eqtb[intBase+interLinePenaltyCode-1].int()
- if int32(curLine) == prg.curList.pgField+1 {
- pen = pen + *prg.eqtb[intBase+clubPenaltyCode-1].int()
- }
- if int32(curLine)+2 == int32(prg.bestLine) {
- pen = pen + finalWidowPenalty
- }
- if discBreak {
- pen = pen + *prg.eqtb[intBase+brokenPenaltyCode-1].int()
- }
- if pen != 0 {
- r1 = prg.newPenalty(pen)
- *(*prg.mem[prg.curList.tailField].hh()).rh() = r1
- prg.curList.tailField = r1
- }
- }
- curLine = uint16(int32(curLine) + 1)
- prg.curP = *(*prg.mem[int32(prg.curP)+1].hh()).lh()
- if int32(prg.curP) != 0 {
- if !postDiscBreak {
- r1 = uint16(30000 - 3)
- for true {
- q = *(*prg.mem[r1].hh()).rh()
- if int32(q) == int32(*(*prg.mem[int32(prg.curP)+1].hh()).rh()) {
- goto done1
- }
- // |cur_break(cur_p)| is the next breakpoint
- // now |q| cannot be |null|
- if int32(q) >= int32(prg.hiMemMin) {
- goto done1
- }
- if int32(*(*prg.mem[q].hh()).b0()) < mathNode {
- goto done1
- }
- if int32(*(*prg.mem[q].hh()).b0()) == kernNode {
- if int32(*(*prg.mem[q].hh()).b1()) != explicit {
- goto done1
- }
- }
- r1 = q // now |type(q)=glue_node|, |kern_node|, |math_node|, or |penalty_node|
- }
- done1:
- if int32(r1) != 30000-3 {
- *(*prg.mem[r1].hh()).rh() = 0
- prg.flushNodeList(*(*prg.mem[30000-3].hh()).rh())
- *(*prg.mem[30000-3].hh()).rh() = q
- }
- }
- }
- if int32(prg.curP) == 0 {
- break
- }
- }
- if int32(curLine) != int32(prg.bestLine) || int32(*(*prg.mem[30000-3].hh()).rh()) != 0 {
- prg.confusion(strNumber( /* "line breaking" */ 939))
- }
- // \xref[this can't happen line breaking][\quad line breaking]
- prg.curList.pgField = int32(prg.bestLine) - 1
- }
- // \4
- // Declare the function called |reconstitute|
- func (prg *prg) reconstitute(j, n smallNumber, bchar, hchar halfword) (r smallNumber) {
- var (
- p halfword // temporary register for list manipulation
- t halfword // a node being appended to
- q fourQuarters // character information or a lig/kern instruction
- curRh halfword // hyphen character for ligature testing
- testChar halfword // hyphen or other character for ligature testing
- w scaled // amount of kerning
- k fontIndex // position of current lig/kern instruction
- )
- prg.hyphenPassed = 0
- t = uint16(30000 - 4)
- w = 0
- *(*prg.mem[30000-4].hh()).rh() = 0
- // at this point |ligature_present=lft_hit=rt_hit=false|
- // Set up data structures with the cursor following position |j|
- prg.curL = uint16(int32(prg.hu[j]) + minQuarterword)
- prg.curQ = t
- if int32(j) == 0 {
- prg.ligaturePresent = prg.initLig
- p = prg.initList
- if prg.ligaturePresent {
- prg.lftHit = prg.initLft
- }
- for int32(p) > 0 {
- {
- *(*prg.mem[t].hh()).rh() = prg.getAvail()
- t = *(*prg.mem[t].hh()).rh()
- *(*prg.mem[t].hh()).b0() = prg.hf
- *(*prg.mem[t].hh()).b1() = *(*prg.mem[p].hh()).b1()
- }
- p = *(*prg.mem[p].hh()).rh()
- }
- } else if int32(prg.curL) < 256+minQuarterword {
- *(*prg.mem[t].hh()).rh() = prg.getAvail()
- t = *(*prg.mem[t].hh()).rh()
- *(*prg.mem[t].hh()).b0() = prg.hf
- *(*prg.mem[t].hh()).b1() = byte(prg.curL)
- }
- prg.ligStack = 0
- {
- if int32(j) < int32(n) {
- prg.curR = uint16(int32(prg.hu[int32(j)+1]) + minQuarterword)
- } else {
- prg.curR = bchar
- }
- if prg.hyf[j]&1 != 0 {
- curRh = hchar
- } else {
- curRh = uint16(256 + minQuarterword)
- }
- }
- continue1:
- if int32(prg.curL) == 256+minQuarterword {
- k = prg.bcharLabel[prg.hf]
- if int32(k) == nonAddress {
- goto done
- } else {
- q = *prg.fontInfo[k].qqqq()
- }
- } else {
- q = *prg.fontInfo[prg.charBase[prg.hf]+int32(prg.curL)].qqqq()
- if (int32(q.b2)-minQuarterword)%4 != ligTag {
- goto done
- }
- k = uint16(prg.ligKernBase[prg.hf] + int32(q.b3))
- q = *prg.fontInfo[k].qqqq()
- if int32(q.b0) > 128+minQuarterword {
- k = uint16(prg.ligKernBase[prg.hf] + 256*int32(q.b2) + int32(q.b3) + 32768 - 256*(128+minQuarterword))
- q = *prg.fontInfo[k].qqqq()
- }
- } // now |k| is the starting address of the lig/kern program
- if int32(curRh) < 256+minQuarterword {
- testChar = curRh
- } else {
- testChar = prg.curR
- }
- for true {
- if int32(q.b1) == int32(testChar) {
- if int32(q.b0) <= 128+minQuarterword {
- if int32(curRh) < 256+minQuarterword {
- prg.hyphenPassed = j
- hchar = uint16(256 + minQuarterword)
- curRh = uint16(256 + minQuarterword)
- goto continue1
- } else {
- if int32(hchar) < 256+minQuarterword {
- if prg.hyf[j]&1 != 0 {
- prg.hyphenPassed = j
- hchar = uint16(256 + minQuarterword)
- }
- }
- if int32(q.b2) < 128+minQuarterword {
- if int32(prg.curL) == 256+minQuarterword {
- prg.lftHit = true
- }
- if int32(j) == int32(n) {
- if int32(prg.ligStack) == 0 {
- prg.rtHit = true
- }
- }
- {
- if prg.interrupt != 0 {
- prg.pauseForInstructions()
- }
- } // allow a way out in case there's an infinite ligature loop
- switch q.b2 {
- case 1 + minQuarterword, 5 + minQuarterword:
- prg.curL = uint16(q.b3) // \.[=:\?], \.[=:\?>]
- prg.ligaturePresent = true
- case 2 + minQuarterword, 6 + minQuarterword:
- prg.curR = uint16(q.b3) // \.[\?=:], \.[\?=:>]
- if int32(prg.ligStack) > 0 {
- *(*prg.mem[prg.ligStack].hh()).b1() = byte(prg.curR)
- } else {
- prg.ligStack = prg.newLigItem(quarterword(prg.curR))
- if int32(j) == int32(n) {
- bchar = uint16(256 + minQuarterword)
- } else {
- p = prg.getAvail()
- *(*prg.mem[int32(prg.ligStack)+1].hh()).rh() = p
- *(*prg.mem[p].hh()).b1() = byte(int32(prg.hu[int32(j)+1]) + minQuarterword)
- *(*prg.mem[p].hh()).b0() = prg.hf
- }
- }
- case 3 + minQuarterword:
- prg.curR = uint16(q.b3) // \.[\?=:\?]
- p = prg.ligStack
- prg.ligStack = prg.newLigItem(quarterword(prg.curR))
- *(*prg.mem[prg.ligStack].hh()).rh() = p
- case 7 + minQuarterword, 11 + minQuarterword:
- if prg.ligaturePresent {
- p = prg.newLigature(prg.hf, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
- if prg.lftHit {
- *(*prg.mem[p].hh()).b1() = 2
- prg.lftHit = false
- }
- if false {
- if int32(prg.ligStack) == 0 {
- *(*prg.mem[p].hh()).b1() = byte(int32(*(*prg.mem[p].hh()).b1()) + 1)
- prg.rtHit = false
- }
- }
- *(*prg.mem[prg.curQ].hh()).rh() = p
- t = p
- prg.ligaturePresent = false
- } // \.[\?=:\?>], \.[\?=:\?>>]
- prg.curQ = t
- prg.curL = uint16(q.b3)
- prg.ligaturePresent = true
- default:
- prg.curL = uint16(q.b3)
- prg.ligaturePresent = true // \.[=:]
- if int32(prg.ligStack) > 0 {
- if int32(*(*prg.mem[int32(prg.ligStack)+1].hh()).rh()) > 0 {
- *(*prg.mem[t].hh()).rh() = *(*prg.mem[int32(prg.ligStack)+1].hh()).rh()
- t = *(*prg.mem[t].hh()).rh()
- j = byte(int32(j) + 1)
- }
- p = prg.ligStack
- prg.ligStack = *(*prg.mem[p].hh()).rh()
- prg.freeNode(p, halfword(smallNodeSize))
- if int32(prg.ligStack) == 0 {
- if int32(j) < int32(n) {
- prg.curR = uint16(int32(prg.hu[int32(j)+1]) + minQuarterword)
- } else {
- prg.curR = bchar
- }
- if prg.hyf[j]&1 != 0 {
- curRh = hchar
- } else {
- curRh = uint16(256 + minQuarterword)
- }
- } else {
- prg.curR = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
- }
- } else if int32(j) == int32(n) {
- goto done
- } else {
- {
- *(*prg.mem[t].hh()).rh() = prg.getAvail()
- t = *(*prg.mem[t].hh()).rh()
- *(*prg.mem[t].hh()).b0() = prg.hf
- *(*prg.mem[t].hh()).b1() = byte(prg.curR)
- }
- j = byte(int32(j) + 1)
- {
- if int32(j) < int32(n) {
- prg.curR = uint16(int32(prg.hu[int32(j)+1]) + minQuarterword)
- } else {
- prg.curR = bchar
- }
- if prg.hyf[j]&1 != 0 {
- curRh = hchar
- } else {
- curRh = uint16(256 + minQuarterword)
- }
- }
- }
- }
- if int32(q.b2) > 4+minQuarterword {
- if int32(q.b2) != 7+minQuarterword {
- goto done
- }
- }
- goto continue1
- }
- w = *prg.fontInfo[prg.kernBase[prg.hf]+256*int32(q.b2)+int32(q.b3)].int()
- goto done // this kern will be inserted below
- }
- }
- }
- if int32(q.b0) >= 128+minQuarterword {
- if int32(curRh) == 256+minQuarterword {
- goto done
- } else {
- curRh = uint16(256 + minQuarterword)
- goto continue1
- }
- }
- k = uint16(int32(k) + int32(q.b0) - minQuarterword + 1)
- q = *prg.fontInfo[k].qqqq()
- }
- done:
- ;
- // Append a ligature and/or kern to the translation; |goto continue| if the stack of inserted ligatures is nonempty
- if prg.ligaturePresent {
- p = prg.newLigature(prg.hf, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
- if prg.lftHit {
- *(*prg.mem[p].hh()).b1() = 2
- prg.lftHit = false
- }
- if prg.rtHit {
- if int32(prg.ligStack) == 0 {
- *(*prg.mem[p].hh()).b1() = byte(int32(*(*prg.mem[p].hh()).b1()) + 1)
- prg.rtHit = false
- }
- }
- *(*prg.mem[prg.curQ].hh()).rh() = p
- t = p
- prg.ligaturePresent = false
- }
- if w != 0 {
- *(*prg.mem[t].hh()).rh() = prg.newKern(w)
- t = *(*prg.mem[t].hh()).rh()
- w = 0
- }
- if int32(prg.ligStack) > 0 {
- prg.curQ = t
- prg.curL = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
- prg.ligaturePresent = true
- {
- if int32(*(*prg.mem[int32(prg.ligStack)+1].hh()).rh()) > 0 {
- *(*prg.mem[t].hh()).rh() = *(*prg.mem[int32(prg.ligStack)+1].hh()).rh()
- t = *(*prg.mem[t].hh()).rh()
- j = byte(int32(j) + 1)
- }
- p = prg.ligStack
- prg.ligStack = *(*prg.mem[p].hh()).rh()
- prg.freeNode(p, halfword(smallNodeSize))
- if int32(prg.ligStack) == 0 {
- if int32(j) < int32(n) {
- prg.curR = uint16(int32(prg.hu[int32(j)+1]) + minQuarterword)
- } else {
- prg.curR = bchar
- }
- if prg.hyf[j]&1 != 0 {
- curRh = hchar
- } else {
- curRh = uint16(256 + minQuarterword)
- }
- } else {
- prg.curR = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
- }
- }
- goto continue1
- }
- r = j
- return r
- }
- func (prg *prg) hyphenate() {
- var (
- // Local variables for hyphenation
- i, j, l/* 0..65 */ byte // indices into |hc| or |hu|
- q, r1, s halfword // temporary registers for list manipulation
- bchar halfword // boundary character of hyphenated word, or |non_char|
- majorTail, minorTail halfword // the end of lists in the main and
- // discretionary branches being reconstructed
- c asciiCode // character temporarily replaced by a hyphen
- cLoc/* 0..63 */ byte // where that character came from
- rCount int32 // replacement count for discretionary
- hyfNode halfword // the hyphen, if it exists
- z triePointer // an index into |trie|
- v int32 // an index into |hyf_distance|, etc.
- h hyphPointer // an index into |hyph_word| and |hyph_list|
- k strNumber // an index into |str_start|
- u poolPointer // an index into |str_pool|
- )
- for ii := int32(0); ii <= int32(prg.hn); ii++ {
- j = byte(ii)
- _ = j
- prg.hyf[j] = 0
- }
- // Look for the word |hc[1..hn]| in the exception table, and |goto found| (with |hyf| containing the hyphens) if an entry is found
- h = prg.hc[1]
- prg.hn = byte(int32(prg.hn) + 1)
- prg.hc[prg.hn] = uint16(prg.curLang)
- for ii := int32(2); ii <= int32(prg.hn); ii++ {
- j = byte(ii)
- _ = j
- h = uint16((int32(h) + int32(h) + int32(prg.hc[j])) % hyphSize)
- }
- for true {
- k = prg.hyphWord[h]
- if int32(k) == 0 {
- goto notFound
- }
- if int32(prg.strStart[int32(k)+1])-int32(prg.strStart[k]) < int32(prg.hn) {
- goto notFound
- }
- if int32(prg.strStart[int32(k)+1])-int32(prg.strStart[k]) == int32(prg.hn) {
- j = 1
- u = prg.strStart[k]
- for {
- if int32(prg.strPool[u]) < int32(prg.hc[j]) {
- goto notFound
- }
- if int32(prg.strPool[u]) > int32(prg.hc[j]) {
- goto done
- }
- j = byte(int32(j) + 1)
- u = uint16(int32(u) + 1)
- if int32(j) > int32(prg.hn) {
- break
- }
- }
- // Insert hyphens as specified in |hyph_list[h]|
- s = prg.hyphList[h]
- for int32(s) != 0 {
- prg.hyf[*(*prg.mem[s].hh()).lh()] = 1
- s = *(*prg.mem[s].hh()).rh()
- }
- prg.hn = byte(int32(prg.hn) - 1)
- goto found
- }
- done:
- ;
- if int32(h) > 0 {
- h = uint16(int32(h) - 1)
- } else {
- h = uint16(hyphSize)
- }
- }
- notFound:
- prg.hn = byte(int32(prg.hn) - 1)
- if int32(*prg.trie[int32(prg.curLang)+1].b1()) != int32(prg.curLang)+minQuarterword {
- goto exit
- } // no patterns for |cur_lang|
- prg.hc[0] = 0
- prg.hc[int32(prg.hn)+1] = 0
- prg.hc[int32(prg.hn)+2] = 256 // insert delimiters
- for ii := int32(0); ii <= int32(prg.hn)-prg.rHyf+1; ii++ {
- j = byte(ii)
- _ = j
- z = uint16(int32(*prg.trie[int32(prg.curLang)+1].rh()) + int32(prg.hc[j]))
- l = j
- for int32(prg.hc[l]) == int32(*prg.trie[z].b1())-minQuarterword {
- if int32(*prg.trie[z].b0()) != minQuarterword {
- v = int32(*prg.trie[z].b0())
- for {
- v = v + int32(prg.opStart[prg.curLang])
- i = byte(int32(l) - int32(prg.hyfDistance[v-1]))
- if int32(prg.hyfNum[v-1]) > int32(prg.hyf[i]) {
- prg.hyf[i] = prg.hyfNum[v-1]
- }
- v = int32(prg.hyfNext[v-1])
- if v == minQuarterword {
- break
- }
- }
- }
- l = byte(int32(l) + 1)
- z = uint16(int32(*prg.trie[z].rh()) + int32(prg.hc[l]))
- }
- }
- found:
- for ii := int32(0); ii <= prg.lHyf-1; ii++ {
- j = byte(ii)
- _ = j
- prg.hyf[j] = 0
- }
- for ii := int32(0); ii <= prg.rHyf-1; ii++ {
- j = byte(ii)
- _ = j
- prg.hyf[int32(prg.hn)-int32(j)] = 0
- }
- // If no hyphens were found, |return|
- for ii := prg.lHyf; ii <= int32(prg.hn)-prg.rHyf; ii++ {
- j = byte(ii)
- _ = j
- if prg.hyf[j]&1 != 0 {
- goto found1
- }
- }
- goto exit
- found1:
- ;
- // Replace nodes |ha..hb| by a sequence of nodes that includes the discretionary hyphens
- q = *(*prg.mem[prg.hb].hh()).rh()
- *(*prg.mem[prg.hb].hh()).rh() = 0
- r1 = *(*prg.mem[prg.ha].hh()).rh()
- *(*prg.mem[prg.ha].hh()).rh() = 0
- bchar = prg.hyfBchar
- if int32(prg.ha) >= int32(prg.hiMemMin) {
- if int32(*(*prg.mem[prg.ha].hh()).b0()) != int32(prg.hf) {
- goto found2
- } else {
- prg.initList = prg.ha
- prg.initLig = false
- prg.hu[0] = uint16(int32(*(*prg.mem[prg.ha].hh()).b1()) - minQuarterword)
- }
- } else if int32(*(*prg.mem[prg.ha].hh()).b0()) == ligatureNode {
- if int32(*(*prg.mem[int32(prg.ha)+1].hh()).b0()) != int32(prg.hf) {
- goto found2
- } else {
- prg.initList = *(*prg.mem[int32(prg.ha)+1].hh()).rh()
- prg.initLig = true
- prg.initLft = int32(*(*prg.mem[prg.ha].hh()).b1()) > 1
- prg.hu[0] = uint16(int32(*(*prg.mem[int32(prg.ha)+1].hh()).b1()) - minQuarterword)
- if int32(prg.initList) == 0 {
- if prg.initLft {
- prg.hu[0] = 256
- prg.initLig = false
- }
- } // in this case a ligature will be reconstructed from scratch
- prg.freeNode(prg.ha, halfword(smallNodeSize))
- }
- } else {
- if !(int32(r1) >= int32(prg.hiMemMin)) {
- if int32(*(*prg.mem[r1].hh()).b0()) == ligatureNode {
- if int32(*(*prg.mem[r1].hh()).b1()) > 1 {
- goto found2
- }
- }
- }
- j = 1
- s = prg.ha
- prg.initList = 0
- goto commonEnding
- }
- s = prg.curP // we have |cur_p<>ha| because |type(cur_p)=glue_node|
- for int32(*(*prg.mem[s].hh()).rh()) != int32(prg.ha) {
- s = *(*prg.mem[s].hh()).rh()
- }
- j = 0
- goto commonEnding
- found2:
- s = prg.ha
- j = 0
- prg.hu[0] = 256
- prg.initLig = false
- prg.initList = 0
- commonEnding:
- prg.flushNodeList(r1)
- // Reconstitute nodes for the hyphenated word, inserting discretionary hyphens
- for {
- l = j
- j = byte(int32(prg.reconstitute(j, prg.hn, bchar, halfword(prg.hyfChar+minQuarterword))) + 1)
- if int32(prg.hyphenPassed) == 0 {
- *(*prg.mem[s].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
- for int32(*(*prg.mem[s].hh()).rh()) > 0 {
- s = *(*prg.mem[s].hh()).rh()
- }
- if prg.hyf[int32(j)-1]&1 != 0 {
- l = j
- prg.hyphenPassed = byte(int32(j) - 1)
- *(*prg.mem[30000-4].hh()).rh() = 0
- }
- }
- if int32(prg.hyphenPassed) > 0 {
- for {
- r1 = prg.getNode(smallNodeSize)
- *(*prg.mem[r1].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
- *(*prg.mem[r1].hh()).b0() = byte(discNode)
- majorTail = r1
- rCount = 0
- for int32(*(*prg.mem[majorTail].hh()).rh()) > 0 {
- majorTail = *(*prg.mem[majorTail].hh()).rh()
- rCount = rCount + 1
- }
- i = prg.hyphenPassed
- prg.hyf[i] = 0
- // Put the \(c)characters |hu[l..i]| and a hyphen into |pre_break(r)|
- minorTail = 0
- *(*prg.mem[int32(r1)+1].hh()).lh() = 0
- hyfNode = prg.newCharacter(prg.hf, eightBits(prg.hyfChar))
- if int32(hyfNode) != 0 {
- i = byte(int32(i) + 1)
- c = byte(prg.hu[i])
- prg.hu[i] = uint16(prg.hyfChar)
- {
- *(*prg.mem[hyfNode].hh()).rh() = prg.avail
- prg.avail = hyfNode /* dyn_used:= dyn_used-1 ; [ ] */
- }
- }
- for int32(l) <= int32(i) {
- l = byte(int32(prg.reconstitute(l, i, prg.fontBchar[prg.hf], halfword(256+minQuarterword))) + 1)
- if int32(*(*prg.mem[30000-4].hh()).rh()) > 0 {
- if int32(minorTail) == 0 {
- *(*prg.mem[int32(r1)+1].hh()).lh() = *(*prg.mem[30000-4].hh()).rh()
- } else {
- *(*prg.mem[minorTail].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
- }
- minorTail = *(*prg.mem[30000-4].hh()).rh()
- for int32(*(*prg.mem[minorTail].hh()).rh()) > 0 {
- minorTail = *(*prg.mem[minorTail].hh()).rh()
- }
- }
- }
- if int32(hyfNode) != 0 {
- prg.hu[i] = uint16(c) // restore the character in the hyphen position
- l = i
- i = byte(int32(i) - 1)
- }
- // Put the \(c)characters |hu[i+1..@,]| into |post_break(r)|, appending to this list and to |major_tail| until synchronization has been achieved
- minorTail = 0
- *(*prg.mem[int32(r1)+1].hh()).rh() = 0
- cLoc = 0
- if int32(prg.bcharLabel[prg.hf]) != nonAddress {
- l = byte(int32(l) - 1)
- c = byte(prg.hu[l])
- cLoc = l
- prg.hu[l] = 256
- }
- for int32(l) < int32(j) {
- for {
- l = byte(int32(prg.reconstitute(l, prg.hn, bchar, halfword(256+minQuarterword))) + 1)
- if int32(cLoc) > 0 {
- prg.hu[cLoc] = uint16(c)
- cLoc = 0
- }
- if int32(*(*prg.mem[30000-4].hh()).rh()) > 0 {
- if int32(minorTail) == 0 {
- *(*prg.mem[int32(r1)+1].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
- } else {
- *(*prg.mem[minorTail].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
- }
- minorTail = *(*prg.mem[30000-4].hh()).rh()
- for int32(*(*prg.mem[minorTail].hh()).rh()) > 0 {
- minorTail = *(*prg.mem[minorTail].hh()).rh()
- }
- }
- if int32(l) >= int32(j) {
- break
- }
- }
- for int32(l) > int32(j) {
- // Append characters of |hu[j..@,]| to |major_tail|, advancing~|j|
- j = byte(int32(prg.reconstitute(j, prg.hn, bchar, halfword(256+minQuarterword))) + 1)
- *(*prg.mem[majorTail].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
- for int32(*(*prg.mem[majorTail].hh()).rh()) > 0 {
- majorTail = *(*prg.mem[majorTail].hh()).rh()
- rCount = rCount + 1
- }
- }
- }
- // Move pointer |s| to the end of the current list, and set |replace_count(r)| appropriately
- if rCount > 127 {
- *(*prg.mem[s].hh()).rh() = *(*prg.mem[r1].hh()).rh()
- *(*prg.mem[r1].hh()).rh() = 0
- prg.flushNodeList(r1)
- } else {
- *(*prg.mem[s].hh()).rh() = r1
- *(*prg.mem[r1].hh()).b1() = byte(rCount)
- }
- s = majorTail
- prg.hyphenPassed = byte(int32(j) - 1)
- *(*prg.mem[30000-4].hh()).rh() = 0
- if !(prg.hyf[int32(j)-1]&1 != 0) {
- break
- }
- }
- }
- if int32(j) > int32(prg.hn) {
- break
- }
- }
- *(*prg.mem[s].hh()).rh() = q
- prg.flushList(prg.initList)
- exit:
- }
- // Declare procedures for preprocessing hyphenation patterns
- func (prg *prg) newTrieOp(d, n smallNumber, v quarterword) (r quarterword) {
- var (
- h/* -trieOpSize..trieOpSize */ int16 // trial hash location
- u quarterword // trial op code
- l/* 0..trieOpSize */ uint16 // pointer to stored data
- )
- h = int16(abs(int32(n)+313*int32(d)+361*int32(v)+1009*int32(prg.curLang))%(trieOpSize+trieOpSize) - trieOpSize)
- for true {
- l = prg.trieOpHash[h+500]
- if int32(l) == 0 {
- if int32(prg.trieOpPtr) == trieOpSize {
- prg.overflow(strNumber( /* "pattern memory ops" */ 949), trieOpSize)
- }
- u = prg.trieUsed[prg.curLang]
- if int32(u) == maxQuarterword {
- prg.overflow(strNumber( /* "pattern memory ops per language" */ 950), maxQuarterword-minQuarterword)
- }
- prg.trieOpPtr = uint16(int32(prg.trieOpPtr) + 1)
- u = byte(int32(u) + 1)
- prg.trieUsed[prg.curLang] = u
- prg.hyfDistance[prg.trieOpPtr-1] = d
- prg.hyfNum[prg.trieOpPtr-1] = n
- prg.hyfNext[prg.trieOpPtr-1] = v
- prg.trieOpLang[prg.trieOpPtr-1] = prg.curLang
- prg.trieOpHash[h+500] = prg.trieOpPtr
- prg.trieOpVal[prg.trieOpPtr-1] = u
- r = u
- goto exit
- }
- if int32(prg.hyfDistance[l-1]) == int32(d) && int32(prg.hyfNum[l-1]) == int32(n) && int32(prg.hyfNext[l-1]) == int32(v) && int32(prg.trieOpLang[l-1]) == int32(prg.curLang) {
- r = prg.trieOpVal[l-1]
- goto exit
- }
- if int32(h) > -trieOpSize {
- h = int16(int32(h) - 1)
- } else {
- h = int16(trieOpSize)
- }
- }
- exit:
- ;
- return r
- }
- func (prg *prg) trieNode(p triePointer) (r triePointer) {
- var (
- h triePointer // trial hash location
- q triePointer // trial trie node
- )
- h = uint16(abs(int32(prg.trieC[p])+1009*int32(prg.trieO[p])+
- 2718*int32(prg.trieL[p])+3142*int32(prg.trieR[p])) % trieSize)
- for true {
- q = prg.trieHash[h]
- if int32(q) == 0 {
- prg.trieHash[h] = p
- r = p
- goto exit
- }
- if int32(prg.trieC[q]) == int32(prg.trieC[p]) && int32(prg.trieO[q]) == int32(prg.trieO[p]) && int32(prg.trieL[q]) == int32(prg.trieL[p]) && int32(prg.trieR[q]) == int32(prg.trieR[p]) {
- r = q
- goto exit
- }
- if int32(h) > 0 {
- h = uint16(int32(h) - 1)
- } else {
- h = uint16(trieSize)
- }
- }
- exit:
- ;
- return r
- }
- func (prg *prg) compressTrie(p triePointer) (r triePointer) {
- if int32(p) == 0 {
- r = 0
- } else {
- prg.trieL[p] = prg.compressTrie(prg.trieL[p])
- prg.trieR[p] = prg.compressTrie(prg.trieR[p])
- r = prg.trieNode(p)
- }
- return r
- }
- func (prg *prg) firstFit(p triePointer) {
- var (
- h triePointer // candidate for |trie_ref[p]|
- z triePointer // runs through holes
- q triePointer // runs through the family starting at |p|
- c asciiCode // smallest character in the family
- l, r1 triePointer // left and right neighbors
- ll/* 1..256 */ uint16 // upper limit of |trie_min| updating
- )
- c = prg.trieC[p]
- z = prg.trieMin[c] // get the first conceivably good hole
- for true {
- h = uint16(int32(z) - int32(c))
- // Ensure that |trie_max>=h+256|
- if int32(prg.trieMax) < int32(h)+256 {
- if trieSize <= int32(h)+256 {
- prg.overflow(strNumber( /* "pattern memory" */ 951), trieSize)
- }
- // \xref[TeX capacity exceeded pattern memory][\quad pattern memory]
- for {
- prg.trieMax = uint16(int32(prg.trieMax) + 1)
- prg.trieTaken[prg.trieMax-1] = false
- *prg.trie[prg.trieMax].rh() = uint16(int32(prg.trieMax) + 1)
- *prg.trie[prg.trieMax].lh() = uint16(int32(prg.trieMax) - 1)
- if int32(prg.trieMax) == int32(h)+256 {
- break
- }
- }
- }
- if prg.trieTaken[h-1] {
- goto notFound
- }
- // If all characters of the family fit relative to |h|, then |goto found|,\30\ otherwise |goto not_found|
- q = prg.trieR[p]
- for int32(q) > 0 {
- if int32(*prg.trie[int32(h)+int32(prg.trieC[q])].rh()) == 0 {
- goto notFound
- }
- q = prg.trieR[q]
- }
- goto found
- notFound:
- z = *prg.trie[z].rh() // move to the next hole
- }
- found:
- prg.trieTaken[h-1] = true
- prg.trieHash[p] = h
- q = p
- for {
- z = uint16(int32(h) + int32(prg.trieC[q]))
- l = *prg.trie[z].lh()
- r1 = *prg.trie[z].rh()
- *prg.trie[r1].lh() = l
- *prg.trie[l].rh() = r1
- *prg.trie[z].rh() = 0
- if int32(l) < 256 {
- if int32(z) < 256 {
- ll = z
- } else {
- ll = 256
- }
- for {
- prg.trieMin[l] = r1
- l = uint16(int32(l) + 1)
- if int32(l) == int32(ll) {
- break
- }
- }
- }
- q = prg.trieR[q]
- if int32(q) == 0 {
- break
- }
- }
- }
- func (prg *prg) triePack(p triePointer) { // pack subtries of a family
- var (
- q triePointer // a local variable that need not be saved on recursive calls
- )
- for {
- q = prg.trieL[p]
- if int32(q) > 0 && int32(prg.trieHash[q]) == 0 {
- prg.firstFit(q)
- prg.triePack(q)
- }
- p = prg.trieR[p]
- if int32(p) == 0 {
- break
- }
- }
- }
- func (prg *prg) trieFix(p triePointer) { // moves |p| and its siblings into |trie|
- var (
- q triePointer // a local variable that need not be saved on recursive calls
- c asciiCode // another one that need not be saved
- z triePointer // |trie| reference; this local variable must be saved
- )
- z = prg.trieHash[p]
- for {
- q = prg.trieL[p]
- c = prg.trieC[p]
- *prg.trie[int32(z)+int32(c)].rh() = prg.trieHash[q]
- *prg.trie[int32(z)+int32(c)].b1() = byte(int32(c) + minQuarterword)
- *prg.trie[int32(z)+int32(c)].b0() = prg.trieO[p]
- if int32(q) > 0 {
- prg.trieFix(q)
- }
- p = prg.trieR[p]
- if int32(p) == 0 {
- break
- }
- }
- }
- func (prg *prg) newPatterns() {
- var (
- k, l/* 0..64 */ byte // indices into |hc| and |hyf|;
- // not always in |small_number| range
- digitSensed bool // should the next digit be treated as a letter?
- v quarterword // trie op code
- p, q triePointer // nodes of trie traversed during insertion
- firstChild bool // is |p=trie_l[q]|?
- c asciiCode // character being inserted
- )
- if prg.trieNotReady {
- if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
- prg.curLang = 0
- } else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
- prg.curLang = 0
- } else {
- prg.curLang = byte(*prg.eqtb[intBase+languageCode-1].int())
- }
- prg.scanLeftBrace() // a left brace must follow \.[\\patterns]
- // Enter all of the patterns into a linked trie, until coming to a right brace
- k = 0
- prg.hyf[0] = 0
- digitSensed = false
- for true {
- prg.getXToken()
- switch prg.curCmd {
- case letter, otherChar:
- // Append a new letter or a hyphen level
- if digitSensed || int32(prg.curChr) < '0' || int32(prg.curChr) > '9' {
- if int32(prg.curChr) == '.' {
- prg.curChr = 0
- } else {
- prg.curChr = *(*prg.eqtb[lcCodeBase+int32(prg.curChr)-1].hh()).rh()
- if int32(prg.curChr) == 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Nonletter" */ 957)
- }
- // \xref[Nonletter]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "(See Appendix H.)" */ 956
- }
- prg.error1()
- }
- }
- if int32(k) < 63 {
- k = byte(int32(k) + 1)
- prg.hc[k] = prg.curChr
- prg.hyf[k] = 0
- digitSensed = false
- }
- } else if int32(k) < 63 {
- prg.hyf[k] = byte(int32(prg.curChr) - '0')
- digitSensed = true
- }
- case spacer, rightBrace:
- if int32(k) > 0 {
- if int32(prg.hc[1]) == 0 {
- prg.hyf[0] = 0
- }
- if int32(prg.hc[k]) == 0 {
- prg.hyf[k] = 0
- }
- l = k
- v = byte(minQuarterword)
- for true {
- if int32(prg.hyf[l]) != 0 {
- v = prg.newTrieOp(smallNumber(int32(k)-int32(l)), prg.hyf[l], v)
- }
- if int32(l) > 0 {
- l = byte(int32(l) - 1)
- } else {
- goto done1
- }
- }
- done1:
- ;
- q = 0
- prg.hc[0] = uint16(prg.curLang)
- for int32(l) <= int32(k) {
- c = byte(prg.hc[l])
- l = byte(int32(l) + 1)
- p = prg.trieL[q]
- firstChild = true
- for int32(p) > 0 && int32(c) > int32(prg.trieC[p]) {
- q = p
- p = prg.trieR[q]
- firstChild = false
- }
- if int32(p) == 0 || int32(c) < int32(prg.trieC[p]) {
- if int32(prg.triePtr) == trieSize {
- prg.overflow(strNumber( /* "pattern memory" */ 951), trieSize)
- }
- // \xref[TeX capacity exceeded pattern memory][\quad pattern memory]
- prg.triePtr = uint16(int32(prg.triePtr) + 1)
- prg.trieR[prg.triePtr] = p
- p = prg.triePtr
- prg.trieL[p] = 0
- if firstChild {
- prg.trieL[q] = p
- } else {
- prg.trieR[q] = p
- }
- prg.trieC[p] = c
- prg.trieO[p] = byte(minQuarterword)
- }
- q = p // now node |q| represents $p_1\ldots p_[l-1]$
- }
- if int32(prg.trieO[q]) != minQuarterword {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Duplicate pattern" */ 958)
- }
- // \xref[Duplicate pattern]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "(See Appendix H.)" */ 956
- }
- prg.error1()
- }
- prg.trieO[q] = v
- }
- if int32(prg.curCmd) == rightBrace {
- goto done
- }
- k = 0
- prg.hyf[0] = 0
- digitSensed = false
- default:
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Bad " */ 955)
- }
- prg.printEsc(strNumber( /* "patterns" */ 953))
- // \xref[Bad \\patterns]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "(See Appendix H.)" */ 956
- }
- prg.error1()
- }
- }
- done:
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Too late for " */ 952)
- }
- prg.printEsc(strNumber( /* "patterns" */ 953))
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "All patterns must be given before typesetting begins." */ 954
- }
- prg.error1()
- *(*prg.mem[30000-12].hh()).rh() = prg.scanToks(false, false)
- prg.flushList(prg.defRef)
- }
- }
- func (prg *prg) initTrie() {
- var (
- p triePointer // pointer for initialization
- j, k, t int32 // all-purpose registers for initialization
- r1, s triePointer // used to clean up the packed |trie|
- h twoHalves // template used to zero out |trie|'s holes
- )
- prg.opStart[0] = uint16(-minQuarterword)
- for ii := int32(1); ii <= 255; ii++ {
- j = ii
- _ = j
- prg.opStart[j] = uint16(int32(prg.opStart[j-1]) + int32(prg.trieUsed[j-1]) - minQuarterword)
- }
- for ii := int32(1); ii <= int32(prg.trieOpPtr); ii++ {
- j = ii
- _ = j
- prg.trieOpHash[j+500] = uint16(int32(prg.opStart[prg.trieOpLang[j-1]]) + int32(prg.trieOpVal[j-1]))
- } // destination
- for ii := int32(1); ii <= int32(prg.trieOpPtr); ii++ {
- j = ii
- _ = j
- for int32(prg.trieOpHash[j+500]) > j {
- k = int32(prg.trieOpHash[j+500])
- t = int32(prg.hyfDistance[k-1])
- prg.hyfDistance[k-1] = prg.hyfDistance[j-1]
- prg.hyfDistance[j-1] = byte(t)
- t = int32(prg.hyfNum[k-1])
- prg.hyfNum[k-1] = prg.hyfNum[j-1]
- prg.hyfNum[j-1] = byte(t)
- t = int32(prg.hyfNext[k-1])
- prg.hyfNext[k-1] = prg.hyfNext[j-1]
- prg.hyfNext[j-1] = byte(t)
- prg.trieOpHash[j+500] = prg.trieOpHash[k+500]
- prg.trieOpHash[k+500] = uint16(k)
- }
- }
- for ii := int32(0); ii <= trieSize; ii++ {
- p = triePointer(ii)
- _ = p
- prg.trieHash[p] = 0
- }
- prg.trieL[0] = prg.compressTrie(prg.trieL[0]) // identify equivalent subtries
- for ii := int32(0); ii <= int32(prg.triePtr); ii++ {
- p = triePointer(ii)
- _ = p
- prg.trieHash[p] = 0
- }
- for ii := int32(0); ii <= 255; ii++ {
- p = triePointer(ii)
- _ = p
- prg.trieMin[p] = uint16(int32(p) + 1)
- }
- *prg.trie[0].rh() = 1
- prg.trieMax = 0
- if int32(prg.trieL[0]) != 0 {
- prg.firstFit(prg.trieL[0])
- prg.triePack(prg.trieL[0])
- }
- // Move the data into |trie|
- *h.rh() = 0
- *h.b0() = byte(minQuarterword)
- *h.b1() = byte(minQuarterword) // |trie_link:=0|,
- // |trie_op:=min_quarterword|, |trie_char:=qi(0)|
- if int32(prg.trieL[0]) == 0 {
- for ii := int32(0); ii <= 256; ii++ {
- r1 = triePointer(ii)
- _ = r1
- prg.trie[r1] = h
- }
- prg.trieMax = 256
- } else {
- prg.trieFix(prg.trieL[0]) // this fixes the non-holes in |trie|
- r1 = 0 // now we will zero out all the holes
- for {
- s = *prg.trie[r1].rh()
- prg.trie[r1] = h
- r1 = s
- if int32(r1) > int32(prg.trieMax) {
- break
- }
- }
- }
- *prg.trie[0].b1() = byte('?' + minQuarterword) // make |trie_char(c)<>c| for all |c|
- prg.trieNotReady = false
- }
- func (prg *prg) lineBreak(finalWidowPenalty int32) {
- var (
- // Local variables for line breaking
- autoBreaking bool // is node |cur_p| outside a formula?
- prevP halfword // helps to determine when glue nodes are breakpoints
- q, r1, s, prevS halfword // miscellaneous nodes of temporary interest
- f internalFontNumber // used when calculating character widths
- j smallNumber // an index into |hc| or |hu|
- c/* 0..255 */ byte // character being considered for hyphenation
- )
- prg.packBeginLine = prg.curList.mlField // this is for over/underfull box messages
- // Get ready to start line breaking
- *(*prg.mem[30000-3].hh()).rh() = *(*prg.mem[prg.curList.headField].hh()).rh()
- if int32(prg.curList.tailField) >= int32(prg.hiMemMin) {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(infPenalty)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- } else if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) != glueNode {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(infPenalty)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- } else {
- *(*prg.mem[prg.curList.tailField].hh()).b0() = byte(penaltyNode)
- prg.deleteGlueRef(*(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh())
- prg.flushNodeList(*(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh())
- *prg.mem[int32(prg.curList.tailField)+1].int() = infPenalty
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(smallNumber(parFillSkipCode))
- prg.initCurLang = byte(prg.curList.pgField % 0200000)
- prg.initLHyf = prg.curList.pgField / 020000000
- prg.initRHyf = prg.curList.pgField / 0200000 % 0100
- prg.popNest()
- prg.noShrinkErrorYet = true
- if int32(*(*prg.mem[*(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh()].hh()).b1()) != normal && *prg.mem[int32(*(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh())+3].int() != 0 {
- *(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh() = prg.finiteShrink(*(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh())
- }
- if int32(*(*prg.mem[*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()].hh()).b1()) != normal && *prg.mem[int32(*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh())+3].int() != 0 {
- *(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh() = prg.finiteShrink(*(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh())
- }
- q = *(*prg.eqtb[glueBase+leftSkipCode-1].hh()).rh()
- r1 = *(*prg.eqtb[glueBase+rightSkipCode-1].hh()).rh()
- prg.background[1-1] = *prg.mem[int32(q)+widthOffset].int() + *prg.mem[int32(r1)+widthOffset].int()
- prg.background[2-1] = 0
- prg.background[3-1] = 0
- prg.background[4-1] = 0
- prg.background[5-1] = 0
- prg.background[2+int32(*(*prg.mem[q].hh()).b0())-1] = *prg.mem[int32(q)+2].int()
- prg.background[2+int32(*(*prg.mem[r1].hh()).b0())-1] = prg.background[2+int32(*(*prg.mem[r1].hh()).b0())-1] + *prg.mem[int32(r1)+2].int()
- prg.background[6-1] = *prg.mem[int32(q)+3].int() + *prg.mem[int32(r1)+3].int()
- prg.minimumDemerits = 07777777777
- prg.minimalDemerits[tightFit] = 07777777777
- prg.minimalDemerits[decentFit] = 07777777777
- prg.minimalDemerits[looseFit] = 07777777777
- prg.minimalDemerits[veryLooseFit] = 07777777777
- if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
- if *prg.eqtb[dimenBase+hangIndentCode-1].int() == 0 {
- prg.lastSpecialLine = 0
- prg.secondWidth = *prg.eqtb[dimenBase+hsizeCode-1].int()
- prg.secondIndent = 0
- } else {
- // Set line length parameters in preparation for hanging indentation
- prg.lastSpecialLine = uint16(abs(*prg.eqtb[intBase+hangAfterCode-1].int()))
- if *prg.eqtb[intBase+hangAfterCode-1].int() < 0 {
- prg.firstWidth = *prg.eqtb[dimenBase+hsizeCode-1].int() - abs(*prg.eqtb[dimenBase+hangIndentCode-1].int())
- if *prg.eqtb[dimenBase+hangIndentCode-1].int() >= 0 {
- prg.firstIndent = *prg.eqtb[dimenBase+hangIndentCode-1].int()
- } else {
- prg.firstIndent = 0
- }
- prg.secondWidth = *prg.eqtb[dimenBase+hsizeCode-1].int()
- prg.secondIndent = 0
- } else {
- prg.firstWidth = *prg.eqtb[dimenBase+hsizeCode-1].int()
- prg.firstIndent = 0
- prg.secondWidth = *prg.eqtb[dimenBase+hsizeCode-1].int() - abs(*prg.eqtb[dimenBase+hangIndentCode-1].int())
- if *prg.eqtb[dimenBase+hangIndentCode-1].int() >= 0 {
- prg.secondIndent = *prg.eqtb[dimenBase+hangIndentCode-1].int()
- } else {
- prg.secondIndent = 0
- }
- }
- }
- } else {
- prg.lastSpecialLine = uint16(int32(*(*prg.mem[*(*prg.eqtb[parShapeLoc-1].hh()).rh()].hh()).lh()) - 1)
- prg.secondWidth = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*(int32(prg.lastSpecialLine)+1)].int()
- prg.secondIndent = *prg.mem[int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh())+2*int32(prg.lastSpecialLine)+1].int()
- }
- if *prg.eqtb[intBase+loosenessCode-1].int() == 0 {
- prg.easyLine = prg.lastSpecialLine
- } else {
- prg.easyLine = 65535
- }
- // Find optimal breakpoints
- prg.threshold = *prg.eqtb[intBase+pretoleranceCode-1].int()
- if prg.threshold >= 0 {
- prg.secondPass = false
- prg.finalPass = false
- } else {
- prg.threshold = *prg.eqtb[intBase+toleranceCode-1].int()
- prg.secondPass = true
- prg.finalPass = *prg.eqtb[dimenBase+emergencyStretchCode-1].int() <= 0
- // if eqtb[int_base+ tracing_paragraphs_code].int >0 then begin_diagnostic; [ ]
- }
- for true {
- if prg.threshold > infBad {
- prg.threshold = infBad
- }
- if prg.secondPass {
- if prg.trieNotReady {
- prg.initTrie()
- }
- prg.curLang = prg.initCurLang
- prg.lHyf = prg.initLHyf
- prg.rHyf = prg.initRHyf
- }
- // Create an active breakpoint representing the beginning of the paragraph
- q = prg.getNode(activeNodeSize)
- *(*prg.mem[q].hh()).b0() = byte(unhyphenated)
- *(*prg.mem[q].hh()).b1() = byte(decentFit)
- *(*prg.mem[q].hh()).rh() = uint16(30000 - 7)
- *(*prg.mem[int32(q)+1].hh()).rh() = 0
- *(*prg.mem[int32(q)+1].hh()).lh() = uint16(prg.curList.pgField + 1)
- *prg.mem[int32(q)+2].int() = 0
- *(*prg.mem[30000-7].hh()).rh() = q
- prg.activeWidth[1-1] = prg.background[1-1]
- prg.activeWidth[2-1] = prg.background[2-1]
- prg.activeWidth[3-1] = prg.background[3-1]
- prg.activeWidth[4-1] = prg.background[4-1]
- prg.activeWidth[5-1] = prg.background[5-1]
- prg.activeWidth[6-1] = prg.background[6-1]
- prg.passive = 0
- prg.printedNode = uint16(30000 - 3)
- prg.passNumber = 0
- prg.fontInShortDisplay = fontBase
- prg.curP = *(*prg.mem[30000-3].hh()).rh()
- autoBreaking = true
- prevP = prg.curP // glue at beginning is not a legal breakpoint
- for int32(prg.curP) != 0 && int32(*(*prg.mem[30000-7].hh()).rh()) != 30000-7 {
- // Call |try_break| if |cur_p| is a legal breakpoint; on the second pass, also try to hyphenate the next word, if |cur_p| is a glue node; then advance |cur_p| to the next node of the paragraph that could possibly be a legal breakpoint
- if int32(prg.curP) >= int32(prg.hiMemMin) {
- prevP = prg.curP
- for {
- f = *(*prg.mem[prg.curP].hh()).b0()
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[prg.curP].hh()).b1())].qqqq()).b0)].int()
- prg.curP = *(*prg.mem[prg.curP].hh()).rh()
- if !(int32(prg.curP) >= int32(prg.hiMemMin)) {
- break
- }
- }
- }
- switch *(*prg.mem[prg.curP].hh()).b0() {
- case hlistNode, vlistNode, ruleNode:
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(prg.curP)+widthOffset].int()
- case whatsitNode:
- // Advance \(p)past a whatsit node in the \(l)|line_break| loop
- if int32(*(*prg.mem[prg.curP].hh()).b1()) == languageNode {
- prg.curLang = byte(*(*prg.mem[int32(prg.curP)+1].hh()).rh())
- prg.lHyf = int32(*(*prg.mem[int32(prg.curP)+1].hh()).b0())
- prg.rHyf = int32(*(*prg.mem[int32(prg.curP)+1].hh()).b1())
- }
- case glueNode:
- if autoBreaking {
- if int32(prevP) >= int32(prg.hiMemMin) {
- prg.tryBreak(0, smallNumber(unhyphenated))
- } else if int32(*(*prg.mem[prevP].hh()).b0()) < mathNode {
- prg.tryBreak(0, smallNumber(unhyphenated))
- } else if int32(*(*prg.mem[prevP].hh()).b0()) == kernNode && int32(*(*prg.mem[prevP].hh()).b1()) != explicit {
- prg.tryBreak(0, smallNumber(unhyphenated))
- }
- }
- if int32(*(*prg.mem[*(*prg.mem[int32(prg.curP)+1].hh()).lh()].hh()).b1()) != normal && *prg.mem[int32(*(*prg.mem[int32(prg.curP)+1].hh()).lh())+3].int() != 0 {
- *(*prg.mem[int32(prg.curP)+1].hh()).lh() = prg.finiteShrink(*(*prg.mem[int32(prg.curP)+1].hh()).lh())
- }
- q = *(*prg.mem[int32(prg.curP)+1].hh()).lh()
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(q)+widthOffset].int()
- prg.activeWidth[2+int32(*(*prg.mem[q].hh()).b0())-1] = prg.activeWidth[2+int32(*(*prg.mem[q].hh()).b0())-1] + *prg.mem[int32(q)+2].int()
- prg.activeWidth[6-1] = prg.activeWidth[6-1] + *prg.mem[int32(q)+3].int()
- if prg.secondPass && autoBreaking {
- prevS = prg.curP
- s = *(*prg.mem[prevS].hh()).rh()
- if int32(s) != 0 {
- for true {
- if int32(s) >= int32(prg.hiMemMin) {
- c = byte(int32(*(*prg.mem[s].hh()).b1()) - minQuarterword)
- prg.hf = *(*prg.mem[s].hh()).b0()
- } else if int32(*(*prg.mem[s].hh()).b0()) == ligatureNode {
- if int32(*(*prg.mem[int32(s)+1].hh()).rh()) == 0 {
- goto continue1
- } else {
- q = *(*prg.mem[int32(s)+1].hh()).rh()
- c = byte(int32(*(*prg.mem[q].hh()).b1()) - minQuarterword)
- prg.hf = *(*prg.mem[q].hh()).b0()
- }
- } else if int32(*(*prg.mem[s].hh()).b0()) == kernNode && int32(*(*prg.mem[s].hh()).b1()) == normal {
- goto continue1
- } else if int32(*(*prg.mem[s].hh()).b0()) == whatsitNode {
- if int32(*(*prg.mem[s].hh()).b1()) == languageNode {
- prg.curLang = byte(*(*prg.mem[int32(s)+1].hh()).rh())
- prg.lHyf = int32(*(*prg.mem[int32(s)+1].hh()).b0())
- prg.rHyf = int32(*(*prg.mem[int32(s)+1].hh()).b1())
- }
- goto continue1
- } else {
- goto done1
- }
- if int32(*(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()) != 0 {
- if int32(*(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()) == int32(c) || *prg.eqtb[intBase+ucHyphCode-1].int() > 0 {
- goto done2
- } else {
- goto done1
- }
- }
- continue1:
- prevS = s
- s = *(*prg.mem[prevS].hh()).rh()
- }
- done2:
- prg.hyfChar = prg.hyphenChar[prg.hf]
- if prg.hyfChar < 0 {
- goto done1
- }
- if prg.hyfChar > 255 {
- goto done1
- }
- prg.ha = prevS
- if prg.lHyf+prg.rHyf > 63 {
- goto done1
- }
- // Skip to node |hb|, putting letters into |hu| and |hc|
- prg.hn = 0
- for true {
- if int32(s) >= int32(prg.hiMemMin) {
- if int32(*(*prg.mem[s].hh()).b0()) != int32(prg.hf) {
- goto done3
- }
- prg.hyfBchar = uint16(*(*prg.mem[s].hh()).b1())
- c = byte(int32(prg.hyfBchar) - minQuarterword)
- if int32(*(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()) == 0 {
- goto done3
- }
- if int32(prg.hn) == 63 {
- goto done3
- }
- prg.hb = s
- prg.hn = byte(int32(prg.hn) + 1)
- prg.hu[prg.hn] = uint16(c)
- prg.hc[prg.hn] = *(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()
- prg.hyfBchar = uint16(256 + minQuarterword)
- } else if int32(*(*prg.mem[s].hh()).b0()) == ligatureNode {
- if int32(*(*prg.mem[int32(s)+1].hh()).b0()) != int32(prg.hf) {
- goto done3
- }
- j = prg.hn
- q = *(*prg.mem[int32(s)+1].hh()).rh()
- if int32(q) > 0 {
- prg.hyfBchar = uint16(*(*prg.mem[q].hh()).b1())
- }
- for int32(q) > 0 {
- c = byte(int32(*(*prg.mem[q].hh()).b1()) - minQuarterword)
- if int32(*(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()) == 0 {
- goto done3
- }
- if int32(j) == 63 {
- goto done3
- }
- j = byte(int32(j) + 1)
- prg.hu[j] = uint16(c)
- prg.hc[j] = *(*prg.eqtb[lcCodeBase+int32(c)-1].hh()).rh()
- q = *(*prg.mem[q].hh()).rh()
- }
- prg.hb = s
- prg.hn = j
- if *(*prg.mem[s].hh()).b1()&1 != 0 {
- prg.hyfBchar = prg.fontBchar[prg.hf]
- } else {
- prg.hyfBchar = uint16(256 + minQuarterword)
- }
- } else if int32(*(*prg.mem[s].hh()).b0()) == kernNode && int32(*(*prg.mem[s].hh()).b1()) == normal {
- prg.hb = s
- prg.hyfBchar = prg.fontBchar[prg.hf]
- } else {
- goto done3
- }
- s = *(*prg.mem[s].hh()).rh()
- }
- done3:
- ;
- // Check that the nodes following |hb| permit hyphenation and that at least |l_hyf+r_hyf| letters have been found, otherwise |goto done1|
- if int32(prg.hn) < prg.lHyf+prg.rHyf {
- goto done1
- } // |l_hyf| and |r_hyf| are |>=1|
- for true {
- if !(int32(s) >= int32(prg.hiMemMin)) {
- switch *(*prg.mem[s].hh()).b0() {
- case ligatureNode:
- case kernNode:
- if int32(*(*prg.mem[s].hh()).b1()) != normal {
- goto done4
- }
- case whatsitNode, glueNode, penaltyNode, insNode,
- adjustNode, markNode:
- goto done4
- default:
- goto done1
- }
- }
- s = *(*prg.mem[s].hh()).rh()
- }
- done4:
- ;
- prg.hyphenate()
- }
- done1:
- }
- case kernNode:
- if int32(*(*prg.mem[prg.curP].hh()).b1()) == explicit {
- if !(int32(*(*prg.mem[prg.curP].hh()).rh()) >= int32(prg.hiMemMin)) && autoBreaking {
- if int32(*(*prg.mem[*(*prg.mem[prg.curP].hh()).rh()].hh()).b0()) == glueNode {
- prg.tryBreak(0, smallNumber(unhyphenated))
- }
- }
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(prg.curP)+widthOffset].int()
- } else {
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(prg.curP)+widthOffset].int()
- }
- case ligatureNode:
- f = *(*prg.mem[int32(prg.curP)+1].hh()).b0()
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(prg.curP)+1].hh()).b1())].qqqq()).b0)].int()
- case discNode:
- // Try to break after a discretionary fragment, then |goto done5|
- s = *(*prg.mem[int32(prg.curP)+1].hh()).lh()
- prg.discWidth = 0
- if int32(s) == 0 {
- prg.tryBreak(*prg.eqtb[intBase+exHyphenPenaltyCode-1].int(), smallNumber(hyphenated))
- } else {
- for {
- // Add the width of node |s| to |disc_width|
- if int32(s) >= int32(prg.hiMemMin) {
- f = *(*prg.mem[s].hh()).b0()
- prg.discWidth = prg.discWidth + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[s].hh()).b1())].qqqq()).b0)].int()
- } else {
- switch *(*prg.mem[s].hh()).b0() {
- case ligatureNode:
- f = *(*prg.mem[int32(s)+1].hh()).b0()
- prg.discWidth = prg.discWidth + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(s)+1].hh()).b1())].qqqq()).b0)].int()
- case hlistNode, vlistNode, ruleNode, kernNode:
- prg.discWidth = prg.discWidth + *prg.mem[int32(s)+widthOffset].int()
- default:
- prg.confusion(strNumber( /* "disc3" */ 937))
- // \xref[this can't happen disc3][\quad disc3]
- }
- }
- s = *(*prg.mem[s].hh()).rh()
- if int32(s) == 0 {
- break
- }
- }
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + prg.discWidth
- prg.tryBreak(*prg.eqtb[intBase+hyphenPenaltyCode-1].int(), smallNumber(hyphenated))
- prg.activeWidth[1-1] = prg.activeWidth[1-1] - prg.discWidth
- }
- r1 = uint16(*(*prg.mem[prg.curP].hh()).b1())
- s = *(*prg.mem[prg.curP].hh()).rh()
- for int32(r1) > 0 {
- if int32(s) >= int32(prg.hiMemMin) {
- f = *(*prg.mem[s].hh()).b0()
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[s].hh()).b1())].qqqq()).b0)].int()
- } else {
- switch *(*prg.mem[s].hh()).b0() {
- case ligatureNode:
- f = *(*prg.mem[int32(s)+1].hh()).b0()
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[int32(s)+1].hh()).b1())].qqqq()).b0)].int()
- case hlistNode, vlistNode, ruleNode, kernNode:
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(s)+widthOffset].int()
- default:
- prg.confusion(strNumber( /* "disc4" */ 938))
- // \xref[this can't happen disc4][\quad disc4]
- }
- }
- r1 = uint16(int32(r1) - 1)
- s = *(*prg.mem[s].hh()).rh()
- }
- prevP = prg.curP
- prg.curP = s
- goto done5
- case mathNode:
- autoBreaking = int32(*(*prg.mem[prg.curP].hh()).b1()) == after
- {
- if !(int32(*(*prg.mem[prg.curP].hh()).rh()) >= int32(prg.hiMemMin)) && autoBreaking {
- if int32(*(*prg.mem[*(*prg.mem[prg.curP].hh()).rh()].hh()).b0()) == glueNode {
- prg.tryBreak(0, smallNumber(unhyphenated))
- }
- }
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + *prg.mem[int32(prg.curP)+widthOffset].int()
- }
- case penaltyNode:
- prg.tryBreak(*prg.mem[int32(prg.curP)+1].int(), smallNumber(unhyphenated))
- case markNode, insNode, adjustNode:
- default:
- prg.confusion(strNumber( /* "paragraph" */ 936))
- // \xref[this can't happen paragraph][\quad paragraph]
- }
- prevP = prg.curP
- prg.curP = *(*prg.mem[prg.curP].hh()).rh()
- done5:
- }
- if int32(prg.curP) == 0 {
- prg.tryBreak(ejectPenalty, smallNumber(hyphenated))
- if int32(*(*prg.mem[30000-7].hh()).rh()) != 30000-7 {
- r1 = *(*prg.mem[30000-7].hh()).rh()
- prg.fewestDemerits = 07777777777
- for {
- if int32(*(*prg.mem[r1].hh()).b0()) != deltaNode {
- if *prg.mem[int32(r1)+2].int() < prg.fewestDemerits {
- prg.fewestDemerits = *prg.mem[int32(r1)+2].int()
- prg.bestBet = r1
- }
- }
- r1 = *(*prg.mem[r1].hh()).rh()
- if int32(r1) == 30000-7 {
- break
- }
- }
- prg.bestLine = *(*prg.mem[int32(prg.bestBet)+1].hh()).lh()
- if *prg.eqtb[intBase+loosenessCode-1].int() == 0 {
- goto done
- }
- // Find the best active node for the desired looseness
- {
- r1 = *(*prg.mem[30000-7].hh()).rh()
- prg.actualLooseness = 0
- for {
- if int32(*(*prg.mem[r1].hh()).b0()) != deltaNode {
- prg.lineDiff = int32(*(*prg.mem[int32(r1)+1].hh()).lh()) - int32(prg.bestLine)
- if prg.lineDiff < prg.actualLooseness && *prg.eqtb[intBase+loosenessCode-1].int() <= prg.lineDiff || prg.lineDiff > prg.actualLooseness && *prg.eqtb[intBase+loosenessCode-1].int() >= prg.lineDiff {
- prg.bestBet = r1
- prg.actualLooseness = prg.lineDiff
- prg.fewestDemerits = *prg.mem[int32(r1)+2].int()
- } else if prg.lineDiff == prg.actualLooseness && *prg.mem[int32(r1)+2].int() < prg.fewestDemerits {
- prg.bestBet = r1
- prg.fewestDemerits = *prg.mem[int32(r1)+2].int()
- }
- }
- r1 = *(*prg.mem[r1].hh()).rh()
- if int32(r1) == 30000-7 {
- break
- }
- }
- prg.bestLine = *(*prg.mem[int32(prg.bestBet)+1].hh()).lh()
- }
- if prg.actualLooseness == *prg.eqtb[intBase+loosenessCode-1].int() || prg.finalPass {
- goto done
- }
- }
- }
- // Clean up the memory by removing the break nodes
- q = *(*prg.mem[30000-7].hh()).rh()
- for int32(q) != 30000-7 {
- prg.curP = *(*prg.mem[q].hh()).rh()
- if int32(*(*prg.mem[q].hh()).b0()) == deltaNode {
- prg.freeNode(q, halfword(deltaNodeSize))
- } else {
- prg.freeNode(q, halfword(activeNodeSize))
- }
- q = prg.curP
- }
- q = prg.passive
- for int32(q) != 0 {
- prg.curP = *(*prg.mem[q].hh()).rh()
- prg.freeNode(q, halfword(passiveNodeSize))
- q = prg.curP
- }
- if !prg.secondPass {
- prg.threshold = *prg.eqtb[intBase+toleranceCode-1].int()
- prg.secondPass = true
- prg.finalPass = *prg.eqtb[dimenBase+emergencyStretchCode-1].int() <= 0
- } else {
- prg.background[2-1] = prg.background[2-1] + *prg.eqtb[dimenBase+emergencyStretchCode-1].int()
- prg.finalPass = true
- }
- }
- done:
- ;
- // Break the paragraph at the chosen breakpoints, justify the resulting lines to the correct widths, and append them to the current vertical list
- prg.postLineBreak(finalWidowPenalty)
- // Clean up the memory by removing the break nodes
- q = *(*prg.mem[30000-7].hh()).rh()
- for int32(q) != 30000-7 {
- prg.curP = *(*prg.mem[q].hh()).rh()
- if int32(*(*prg.mem[q].hh()).b0()) == deltaNode {
- prg.freeNode(q, halfword(deltaNodeSize))
- } else {
- prg.freeNode(q, halfword(activeNodeSize))
- }
- q = prg.curP
- }
- q = prg.passive
- for int32(q) != 0 {
- prg.curP = *(*prg.mem[q].hh()).rh()
- prg.freeNode(q, halfword(passiveNodeSize))
- q = prg.curP
- }
- prg.packBeginLine = 0
- }
- // 817.
- // tangle:pos tex.web:16090:1:
- // When looking for optimal line breaks, \TeX\ creates a ``break node'' for
- // each break that is [\sl feasible], in the sense that there is a way to end
- // a line at the given place without requiring any line to stretch more than
- // a given tolerance. A break node is characterized by three things: the position
- // of the break (which is a pointer to a |glue_node|, |math_node|, |penalty_node|,
- // or |disc_node|); the ordinal number of the line that will follow this
- // breakpoint; and the fitness classification of the line that has just
- // ended, i.e., |tight_fit|, |decent_fit|, |loose_fit|, or |very_loose_fit|.
- // 818.
- // tangle:pos tex.web:16107:1:
- // The algorithm essentially determines the best possible way to achieve
- // each feasible combination of position, line, and fitness. Thus, it answers
- // questions like, ``What is the best way to break the opening part of the
- // paragraph so that the fourth line is a tight line ending at such-and-such
- // a place?'' However, the fact that all lines are to be the same length
- // after a certain point makes it possible to regard all sufficiently large
- // line numbers as equivalent, when the looseness parameter is zero, and this
- // makes it possible for the algorithm to save space and time.
- //
- // An ``active node'' and a ``passive node'' are created in |mem| for each
- // feasible breakpoint that needs to be considered. Active nodes are three
- // words long and passive nodes are two words long. We need active nodes only
- // for breakpoints near the place in the paragraph that is currently being
- // examined, so they are recycled within a comparatively short time after
- // they are created.
- // 819.
- // tangle:pos tex.web:16123:1:
- // An active node for a given breakpoint contains six fields:
- //
- // \yskip\hang|link| points to the next node in the list of active nodes; the
- // last active node has |link=last_active|.
- //
- // \yskip\hang|break_node| points to the passive node associated with this
- // breakpoint.
- //
- // \yskip\hang|line_number| is the number of the line that follows this
- // breakpoint.
- //
- // \yskip\hang|fitness| is the fitness classification of the line ending at this
- // breakpoint.
- //
- // \yskip\hang|type| is either |hyphenated| or |unhyphenated|, depending on
- // whether this breakpoint is a |disc_node|.
- //
- // \yskip\hang|total_demerits| is the minimum possible sum of demerits over all
- // lines leading from the beginning of the paragraph to this breakpoint.
- //
- // \yskip\noindent
- // The value of |link(active)| points to the first active node on a linked list
- // of all currently active nodes. This list is in order by |line_number|,
- // except that nodes with |line_number>easy_line| may be in any order relative
- // to each other.
- // 822.
- // tangle:pos tex.web:16193:1:
- // The active list also contains ``delta'' nodes that help the algorithm
- // compute the badness of individual lines. Such nodes appear only between two
- // active nodes, and they have |type=delta_node|. If |p| and |r| are active nodes
- // and if |q| is a delta node between them, so that |link(p)=q| and |link(q)=r|,
- // then |q| tells the space difference between lines in the horizontal list that
- // start after breakpoint |p| and lines that start after breakpoint |r|. In
- // other words, if we know the length of the line that starts after |p| and
- // ends at our current position, then the corresponding length of the line that
- // starts after |r| is obtained by adding the amounts in node~|q|. A delta node
- // contains six scaled numbers, since it must record the net change in glue
- // stretchability with respect to all orders of infinity. The natural width
- // difference appears in |mem[q+1].sc|; the stretch differences in units of
- // pt, fil, fill, and filll appear in |mem[q+2..q+5].sc|; and the shrink difference
- // appears in |mem[q+6].sc|. The |subtype| field of a delta node is not used.
- // 824.
- // tangle:pos tex.web:16234:1:
- // Let's state the principles of the delta nodes more precisely and concisely,
- // so that the following programs will be less obscure. For each legal
- // breakpoint~|p| in the paragraph, we define two quantities $\alpha(p)$ and
- // $\beta(p)$ such that the length of material in a line from breakpoint~|p|
- // to breakpoint~|q| is $\gamma+\beta(q)-\alpha(p)$, for some fixed $\gamma$.
- // Intuitively, $\alpha(p)$ and $\beta(q)$ are the total length of material from
- // the beginning of the paragraph to a point ``after'' a break at |p| and to a
- // point ``before'' a break at |q|; and $\gamma$ is the width of an empty line,
- // namely the length contributed by \.[\\leftskip] and \.[\\rightskip].
- //
- // Suppose, for example, that the paragraph consists entirely of alternating
- // boxes and glue skips; let the boxes have widths $x_1\ldots x_n$ and
- // let the skips have widths $y_1\ldots y_n$, so that the paragraph can be
- // represented by $x_1y_1\ldots x_ny_n$. Let $p_i$ be the legal breakpoint
- // at $y_i$; then $\alpha(p_i)=x_1+y_1+\cdots+x_i+y_i$, and $\beta(p_i)=
- // x_1+y_1+\cdots+x_i$. To check this, note that the length of material from
- // $p_2$ to $p_5$, say, is $\gamma+x_3+y_3+x_4+y_4+x_5=\gamma+\beta(p_5)
- // -\alpha(p_2)$.
- //
- // The quantities $\alpha$, $\beta$, $\gamma$ involve glue stretchability and
- // shrinkability as well as a natural width. If we were to compute $\alpha(p)$
- // and $\beta(p)$ for each |p|, we would need multiple precision arithmetic, and
- // the multiprecise numbers would have to be kept in the active nodes.
- // \TeX\ avoids this problem by working entirely with relative differences
- // or ``deltas.'' Suppose, for example, that the active list contains
- // $a_1\,\delta_1\,a_2\,\delta_2\,a_3$, where the |a|'s are active breakpoints
- // and the $\delta$'s are delta nodes. Then $\delta_1=\alpha(a_1)-\alpha(a_2)$
- // and $\delta_2=\alpha(a_2)-\alpha(a_3)$. If the line breaking algorithm is
- // currently positioned at some other breakpoint |p|, the |active_width| array
- // contains the value $\gamma+\beta(p)-\alpha(a_1)$. If we are scanning through
- // the list of active nodes and considering a tentative line that runs from
- // $a_2$ to~|p|, say, the |cur_active_width| array will contain the value
- // $\gamma+\beta(p)-\alpha(a_2)$. Thus, when we move from $a_2$ to $a_3$,
- // we want to add $\alpha(a_2)-\alpha(a_3)$ to |cur_active_width|; and this
- // is just $\delta_2$, which appears in the active list between $a_2$ and
- // $a_3$. The |background| array contains $\gamma$. The |break_width| array
- // will be used to calculate values of new delta nodes when the active
- // list is being updated.
- // 904.
- // tangle:pos tex.web:17720:1:
- // We must now face the fact that the battle is not over, even though the
- // [\def\![\kern-1pt]%
- // hyphens have been found: The process of reconstituting a word can be nontrivial
- // because ligatures might change when a hyphen is present. [\sl The \TeX book\/]
- // discusses the difficulties of the word ``difficult'', and
- // the discretionary material surrounding a
- // hyphen can be considerably more complex than that. Suppose
- // \.[abcdef] is a word in a font for which the only ligatures are \.[b\!c],
- // \.[c\!d], \.[d\!e], and \.[e\!f]. If this word permits hyphenation
- // between \.b and \.c, the two patterns with and without hyphenation are
- // $\.a\,\.b\,\.-\,\.[c\!d]\,\.[e\!f]$ and $\.a\,\.[b\!c]\,\.[d\!e]\,\.f$.
- // Thus the insertion of a hyphen might cause effects to ripple arbitrarily
- // far into the rest of the word. A further complication arises if additional
- // hyphens appear together with such rippling, e.g., if the word in the
- // example just given could also be hyphenated between \.c and \.d; \TeX\
- // avoids this by simply ignoring the additional hyphens in such weird cases.]
- //
- // Still further complications arise in the presence of ligatures that do not
- // delete the original characters. When punctuation precedes the word being
- // hyphenated, \TeX's method is not perfect under all possible scenarios,
- // because punctuation marks and letters can propagate information back and forth.
- // For example, suppose the original pre-hyphenation pair
- // \.[*a] changes to \.[*y] via a \.[\?=:] ligature, which changes to \.[xy]
- // via a \.[=:\?] ligature; if $p_[a-1]=\.x$ and $p_a=\.y$, the reconstitution
- // procedure isn't smart enough to obtain \.[xy] again. In such cases the
- // font designer should include a ligature that goes from \.[xa] to \.[xy].
- // 919. \[42] Hyphenation
- // tangle:pos tex.web:18072:19:
- // When a word |hc[1..hn]| has been set up to contain a candidate for hyphenation,
- // \TeX\ first looks to see if it is in the user's exception dictionary. If not,
- // hyphens are inserted based on patterns that appear within the given word,
- // using an algorithm due to Frank~M. Liang.
- // \xref[Liang, Franklin Mark]
- //
- // Let's consider Liang's method first, since it is much more interesting than the
- // exception-lookup routine. The algorithm begins by setting |hyf[j]| to zero
- // for all |j|, and invalid characters are inserted into |hc[0]|
- // and |hc[hn+1]| to serve as delimiters. Then a reasonably fast method is
- // used to see which of a given set of patterns occurs in the word
- // |hc[0..(hn+1)]|. Each pattern $p_1\ldots p_k$ of length |k| has an associated
- // sequence of |k+1| numbers $n_0\ldots n_k$; and if the pattern occurs in
- // |hc[(j+1)..(j+k)]|, \TeX\ will set |hyf[j+i]:=max(hyf[j+i],$n_i$)| for
- // |0<=i<=k|. After this has been done for each pattern that occurs, a
- // discretionary hyphen will be inserted between |hc[j]| and |hc[j+1]| when
- // |hyf[j]| is odd, as we have already seen.
- //
- // The set of patterns $p_1\ldots p_k$ and associated numbers $n_0\ldots n_k$
- // depends, of course, on the language whose words are being hyphenated, and
- // on the degree of hyphenation that is desired. A method for finding
- // appropriate |p|'s and |n|'s, from a given dictionary of words and acceptable
- // hyphenations, is discussed in Liang's Ph.D. thesis (Stanford University,
- // 1983); \TeX\ simply starts with the patterns and works from there.
- // 934.
- // tangle:pos tex.web:18253:1:
- // We have now completed the hyphenation routine, so the |line_break| procedure
- // is finished at last. Since the hyphenation exception table is fresh in our
- // minds, it's a good time to deal with the routine that adds new entries to it.
- //
- // When \TeX\ has scanned `\.[\\hyphenation]', it calls on a procedure named
- // |new_hyph_exceptions| to do the right thing.
- func (prg *prg) newHyphExceptions() {
- var (
- n/* 0..64 */ byte // length of current word; not always a |small_number|
- j/* 0..64 */ byte // an index into |hc|
- h hyphPointer // an index into |hyph_word| and |hyph_list|
- k strNumber // an index into |str_start|
- p halfword // head of a list of hyphen positions
- q halfword // used when creating a new node for list |p|
- s, t strNumber // strings being compared or stored
- u, v poolPointer // indices into |str_pool|
- )
- prg.scanLeftBrace() // a left brace must follow \.[\\hyphenation]
- if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
- prg.curLang = 0
- } else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
- prg.curLang = 0
- } else {
- prg.curLang = byte(*prg.eqtb[intBase+languageCode-1].int())
- }
- // Enter as many hyphenation exceptions as are listed, until coming to a right brace; then |return|
- n = 0
- p = 0
- for true {
- prg.getXToken()
- reswitch:
- switch prg.curCmd {
- case letter, otherChar, charGiven:
- // Append a new letter or hyphen
- if int32(prg.curChr) == '-' {
- if int32(n) < 63 {
- q = prg.getAvail()
- *(*prg.mem[q].hh()).rh() = p
- *(*prg.mem[q].hh()).lh() = uint16(n)
- p = q
- }
- } else {
- if int32(*(*prg.eqtb[lcCodeBase+int32(prg.curChr)-1].hh()).rh()) == 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Not a letter" */ 945)
- }
- // \xref[Not a letter]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Letters in \\hyphenation words must have \\lccode>0." */ 946
- prg.helpLine[0] = /* "Proceed; I'll ignore the character I just read." */ 947
- }
- prg.error1()
- } else if int32(n) < 63 {
- n = byte(int32(n) + 1)
- prg.hc[n] = *(*prg.eqtb[lcCodeBase+int32(prg.curChr)-1].hh()).rh()
- }
- }
- case charNum:
- prg.scanCharNum()
- prg.curChr = uint16(prg.curVal)
- prg.curCmd = byte(charGiven)
- goto reswitch
- case spacer, rightBrace:
- if int32(n) > 1 {
- n = byte(int32(n) + 1)
- prg.hc[n] = uint16(prg.curLang)
- {
- if int32(prg.poolPtr)+int32(n) > poolSize {
- prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
- } /* \xref[TeX capacity exceeded pool size][\quad pool size] */
- }
- h = 0
- for ii := int32(1); ii <= int32(n); ii++ {
- j = byte(ii)
- _ = j
- h = uint16((int32(h) + int32(h) + int32(prg.hc[j])) % hyphSize)
- {
- prg.strPool[prg.poolPtr] = byte(prg.hc[j])
- prg.poolPtr = uint16(int32(prg.poolPtr) + 1)
- }
- }
- s = prg.makeString()
- // Insert the \(p)pair |(s,p)| into the exception table
- if int32(prg.hyphCount) == hyphSize {
- prg.overflow(strNumber( /* "exception dictionary" */ 948), hyphSize)
- }
- // \xref[TeX capacity exceeded exception dictionary][\quad exception dictionary]
- prg.hyphCount = uint16(int32(prg.hyphCount) + 1)
- for int32(prg.hyphWord[h]) != 0 {
- k = prg.hyphWord[h]
- if int32(prg.strStart[int32(k)+1])-int32(prg.strStart[k]) < int32(prg.strStart[int32(s)+1])-int32(prg.strStart[s]) {
- goto found
- }
- if int32(prg.strStart[int32(k)+1])-int32(prg.strStart[k]) > int32(prg.strStart[int32(s)+1])-int32(prg.strStart[s]) {
- goto notFound
- }
- u = prg.strStart[k]
- v = prg.strStart[s]
- for {
- if int32(prg.strPool[u]) < int32(prg.strPool[v]) {
- goto found
- }
- if int32(prg.strPool[u]) > int32(prg.strPool[v]) {
- goto notFound
- }
- u = uint16(int32(u) + 1)
- v = uint16(int32(v) + 1)
- if int32(u) == int32(prg.strStart[int32(k)+1]) {
- break
- }
- }
- found:
- q = prg.hyphList[h]
- prg.hyphList[h] = p
- p = q
- t = prg.hyphWord[h]
- prg.hyphWord[h] = s
- s = t
- notFound:
- ;
- if int32(h) > 0 {
- h = uint16(int32(h) - 1)
- } else {
- h = uint16(hyphSize)
- }
- }
- prg.hyphWord[h] = s
- prg.hyphList[h] = p
- }
- if int32(prg.curCmd) == rightBrace {
- goto exit
- }
- n = 0
- p = 0
- default:
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Improper " */ 680)
- }
- prg.printEsc(strNumber( /* "hyphenation" */ 941))
- // \xref[Improper \\hyphenation...]
- prg.print( /* " will be flushed" */ 942)
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Hyphenation exceptions must contain only letters" */ 943
- prg.helpLine[0] = /* "and hyphens. But continue; I'll forgive and forget." */ 944
- }
- prg.error1()
- }
- }
- exit:
- }
- // 967. \[44] Breaking vertical lists into pages
- // tangle:pos tex.web:18850:42:
- // The |vsplit| procedure, which implements \TeX's \.[\\vsplit] operation,
- // is considerably simpler than |line_break| because it doesn't have to
- // worry about hyphenation, and because its mission is to discover a single
- // break instead of an optimum sequence of breakpoints. But before we get
- // into the details of |vsplit|, we need to consider a few more basic things.
- // 968.
- // tangle:pos tex.web:18856:1:
- // A subroutine called |prune_page_top| takes a pointer to a vlist and
- // returns a pointer to a modified vlist in which all glue, kern, and penalty nodes
- // have been deleted before the first box or rule node. However, the first
- // box or rule is actually preceded by a newly created glue node designed so that
- // the topmost baseline will be at distance |split_top_skip| from the top,
- // whenever this is possible without backspacing.
- //
- // In this routine and those that follow, we make use of the fact that a
- // vertical list contains no character nodes, hence the |type| field exists
- // for each node in the list.
- // \xref[data structure assumptions]
- func (prg *prg) prunePageTop(p halfword) (r halfword) { // adjust top after page break
- var (
- prevP halfword // lags one step behind |p|
- q halfword // temporary variable for list manipulation
- )
- prevP = uint16(30000 - 3)
- *(*prg.mem[30000-3].hh()).rh() = p
- for int32(p) != 0 {
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, ruleNode:
- // Insert glue for |split_top_skip| and set~|p:=null|
- q = prg.newSkipParam(smallNumber(splitTopSkipCode))
- *(*prg.mem[prevP].hh()).rh() = q
- *(*prg.mem[q].hh()).rh() = p
- // now |temp_ptr=glue_ptr(q)|
- if *prg.mem[int32(prg.tempPtr)+widthOffset].int() > *prg.mem[int32(p)+heightOffset].int() {
- *prg.mem[int32(prg.tempPtr)+widthOffset].int() = *prg.mem[int32(prg.tempPtr)+widthOffset].int() - *prg.mem[int32(p)+heightOffset].int()
- } else {
- *prg.mem[int32(prg.tempPtr)+widthOffset].int() = 0
- }
- p = 0
- case whatsitNode, markNode, insNode:
- prevP = p
- p = *(*prg.mem[prevP].hh()).rh()
- case glueNode, kernNode, penaltyNode:
- q = p
- p = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = 0
- *(*prg.mem[prevP].hh()).rh() = p
- prg.flushNodeList(q)
- default:
- prg.confusion(strNumber( /* "pruning" */ 959))
- // \xref[this can't happen pruning][\quad pruning]
- }
- }
- r = *(*prg.mem[30000-3].hh()).rh()
- return r
- }
- // 970.
- // tangle:pos tex.web:18895:1:
- // The next subroutine finds the best place to break a given vertical list
- // so as to obtain a box of height~|h|, with maximum depth~|d|.
- // A pointer to the beginning of the vertical list is given,
- // and a pointer to the optimum breakpoint is returned. The list is effectively
- // followed by a forced break, i.e., a penalty node with the |eject_penalty|;
- // if the best break occurs at this artificial node, the value |null| is returned.
- //
- // An array of six |scaled| distances is used to keep track of the height
- // from the beginning of the list to the current place, just as in |line_break|.
- // In fact, we use one of the same arrays, only changing its name to reflect
- // its new significance.
- func (prg *prg) vertBreak(p halfword, h, d scaled) (r halfword) {
- var (
- prevP halfword // if |p| is a glue node, |type(prev_p)| determines
- // whether |p| is a legal breakpoint
- q, r1 halfword // glue specifications
- pi int32 // penalty value
- b int32 // badness at a trial breakpoint
- leastCost int32 // the smallest badness plus penalties found so far
- bestPlace halfword // the most recent break that leads to |least_cost|
- prevDp scaled // depth of previous box in the list
- t smallNumber // |type| of the node following a kern
- )
- prevP = p // an initial glue node is not a legal breakpoint
- leastCost = 07777777777
- prg.activeWidth[1-1] = 0
- prg.activeWidth[2-1] = 0
- prg.activeWidth[3-1] = 0
- prg.activeWidth[4-1] = 0
- prg.activeWidth[5-1] = 0
- prg.activeWidth[6-1] = 0
- prevDp = 0
- for true {
- if int32(p) == 0 {
- pi = ejectPenalty
- } else {
- // Use node |p| to update the current height and depth measurements; if this node is not a legal breakpoint, |goto not_found| or |update_heights|, otherwise set |pi| to the associated penalty at the break
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, ruleNode:
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + prevDp + *prg.mem[int32(p)+heightOffset].int()
- prevDp = *prg.mem[int32(p)+depthOffset].int()
- goto notFound
- case whatsitNode:
- // Process whatsit |p| in |vert_break| loop, |goto not_found|
- // Process whatsit |p| in |vert_break| loop, |goto not_found|
- goto notFound
- case glueNode:
- if int32(*(*prg.mem[prevP].hh()).b0()) < mathNode {
- pi = 0
- } else {
- goto updateHeights
- }
- case kernNode:
- if int32(*(*prg.mem[p].hh()).rh()) == 0 {
- t = byte(penaltyNode)
- } else {
- t = *(*prg.mem[*(*prg.mem[p].hh()).rh()].hh()).b0()
- }
- if int32(t) == glueNode {
- pi = 0
- } else {
- goto updateHeights
- }
- case penaltyNode:
- pi = *prg.mem[int32(p)+1].int()
- case markNode, insNode:
- goto notFound
- default:
- prg.confusion(strNumber( /* "vertbreak" */ 960))
- // \xref[this can't happen vertbreak][\quad vertbreak]
- }
- }
- // Check if node |p| is a new champion breakpoint; then \(go)|goto done| if |p| is a forced break or if the page-so-far is already too full
- if pi < infPenalty {
- if prg.activeWidth[1-1] < h {
- if prg.activeWidth[3-1] != 0 || prg.activeWidth[4-1] != 0 || prg.activeWidth[5-1] != 0 {
- b = 0
- } else {
- b = int32(prg.badness(h-prg.activeWidth[1-1], prg.activeWidth[2-1]))
- }
- } else if prg.activeWidth[1-1]-h > prg.activeWidth[6-1] {
- b = 07777777777
- } else {
- b = int32(prg.badness(prg.activeWidth[1-1]-h, prg.activeWidth[6-1]))
- }
- if b < 07777777777 {
- if pi <= ejectPenalty {
- b = pi
- } else if b < infBad {
- b = b + pi
- } else {
- b = 100000
- }
- }
- if b <= leastCost {
- bestPlace = p
- leastCost = b
- prg.bestHeightPlusDepth = prg.activeWidth[1-1] + prevDp
- }
- if b == 07777777777 || pi <= ejectPenalty {
- goto done
- }
- }
- if int32(*(*prg.mem[p].hh()).b0()) < glueNode || int32(*(*prg.mem[p].hh()).b0()) > kernNode {
- goto notFound
- }
- updateHeights:
- if int32(*(*prg.mem[p].hh()).b0()) == kernNode {
- q = p
- } else {
- q = *(*prg.mem[int32(p)+1].hh()).lh()
- prg.activeWidth[2+int32(*(*prg.mem[q].hh()).b0())-1] = prg.activeWidth[2+int32(*(*prg.mem[q].hh()).b0())-1] + *prg.mem[int32(q)+2].int()
- prg.activeWidth[6-1] = prg.activeWidth[6-1] + *prg.mem[int32(q)+3].int()
- if int32(*(*prg.mem[q].hh()).b1()) != normal && *prg.mem[int32(q)+3].int() != 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Infinite glue shrinkage found in box being split" */ 961)
- }
- // \xref[Infinite glue shrinkage...]
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "The box you are \\vsplitting contains some infinitely" */ 962
- prg.helpLine[2] = /* "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'." */ 963
- prg.helpLine[1] = /* "Such glue doesn't belong there; but you can safely proceed," */ 964
- prg.helpLine[0] = /* "since the offensive shrinkability has been made finite." */ 922
- }
- prg.error1()
- r1 = prg.newSpec(q)
- *(*prg.mem[r1].hh()).b1() = byte(normal)
- prg.deleteGlueRef(q)
- *(*prg.mem[int32(p)+1].hh()).lh() = r1
- q = r1
- }
- }
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + prevDp + *prg.mem[int32(q)+widthOffset].int()
- prevDp = 0
- notFound:
- if prevDp > d {
- prg.activeWidth[1-1] = prg.activeWidth[1-1] + prevDp - d
- prevDp = d
- }
- prevP = p
- p = *(*prg.mem[prevP].hh()).rh()
- }
- done:
- r = bestPlace
- return r
- }
- // 977.
- // tangle:pos tex.web:19031:1:
- // Now we are ready to consider |vsplit| itself. Most of
- // its work is accomplished by the two subroutines that we have just considered.
- //
- // Given the number of a vlist box |n|, and given a desired page height |h|,
- // the |vsplit| function finds the best initial segment of the vlist and
- // returns a box for a page of height~|h|. The remainder of the vlist, if
- // any, replaces the original box, after removing glue and penalties and
- // adjusting for |split_top_skip|. Mark nodes in the split-off box are used to
- // set the values of |split_first_mark| and |split_bot_mark|; we use the
- // fact that |split_first_mark=null| if and only if |split_bot_mark=null|.
- //
- // The original box becomes “void” if and only if it has been entirely
- // extracted. The extracted box is “void” if and only if the original
- // box was void (or if it was, erroneously, an hlist box).
- func (prg *prg) vsplit(n eightBits, h scaled) (r halfword) {
- var (
- v halfword // the box to be split
- p halfword // runs through the vlist
- q halfword // points to where the break occurs
- )
- v = *(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()
- if int32(prg.curMark[splitFirstMarkCode]) != 0 {
- prg.deleteTokenRef(prg.curMark[splitFirstMarkCode])
- prg.curMark[splitFirstMarkCode] = 0
- prg.deleteTokenRef(prg.curMark[splitBotMarkCode])
- prg.curMark[splitBotMarkCode] = 0
- }
- // Dispense with trivial cases of void or bad boxes
- if int32(v) == 0 {
- r = 0
- goto exit
- }
- if int32(*(*prg.mem[v].hh()).b0()) != vlistNode {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "" */ 338)
- }
- prg.printEsc(strNumber( /* "vsplit" */ 965))
- prg.print( /* " needs a " */ 966)
- prg.printEsc(strNumber( /* "vbox" */ 967))
- // \xref[vsplit_][\.[\\vsplit needs a \\vbox]]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "The box you are trying to split is an \\hbox." */ 968
- prg.helpLine[0] = /* "I can't split such a box, so I'll leave it alone." */ 969
- }
- prg.error1()
- r = 0
- goto exit
- }
- q = prg.vertBreak(*(*prg.mem[int32(v)+listOffset].hh()).rh(), h, *prg.eqtb[dimenBase+splitMaxDepthCode-1].int())
- // Look at all the marks in nodes before the break, and set the final link to |null| at the break
- p = *(*prg.mem[int32(v)+listOffset].hh()).rh()
- if int32(p) == int32(q) {
- *(*prg.mem[int32(v)+listOffset].hh()).rh() = 0
- } else {
- for true {
- if int32(*(*prg.mem[p].hh()).b0()) == markNode {
- if int32(prg.curMark[splitFirstMarkCode]) == 0 {
- prg.curMark[splitFirstMarkCode] = uint16(*prg.mem[int32(p)+1].int())
- prg.curMark[splitBotMarkCode] = prg.curMark[splitFirstMarkCode]
- *(*prg.mem[prg.curMark[splitFirstMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[splitFirstMarkCode]].hh()).lh()) + 2)
- } else {
- prg.deleteTokenRef(prg.curMark[splitBotMarkCode])
- prg.curMark[splitBotMarkCode] = uint16(*prg.mem[int32(p)+1].int())
- *(*prg.mem[prg.curMark[splitBotMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[splitBotMarkCode]].hh()).lh()) + 1)
- }
- }
- if int32(*(*prg.mem[p].hh()).rh()) == int32(q) {
- *(*prg.mem[p].hh()).rh() = 0
- goto done
- }
- p = *(*prg.mem[p].hh()).rh()
- }
- }
- done:
- ;
- q = prg.prunePageTop(q)
- p = *(*prg.mem[int32(v)+listOffset].hh()).rh()
- prg.freeNode(v, halfword(boxNodeSize))
- if int32(q) == 0 {
- *(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = 0
- } else {
- *(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = prg.vpackage(q, scaled(0), smallNumber(additional), scaled(07777777777))
- }
- r = prg.vpackage(p, h, smallNumber(exactly), *prg.eqtb[dimenBase+splitMaxDepthCode-1].int())
- exit:
- ;
- return r
- }
- // 218.
- // tangle:pos tex.web:4391:3:
- // Here is a procedure that displays what \TeX\ is working on, at all levels.
- func (prg *prg) printTotals() {
- prg.printScaled(prg.pageSoFar[1])
- if prg.pageSoFar[2] != 0 {
- prg.print( /* " plus " */ 312)
- prg.printScaled(prg.pageSoFar[2])
- prg.print( /* "" */ 338)
- }
- if prg.pageSoFar[3] != 0 {
- prg.print( /* " plus " */ 312)
- prg.printScaled(prg.pageSoFar[3])
- prg.print( /* "fil" */ 311)
- }
- if prg.pageSoFar[4] != 0 {
- prg.print( /* " plus " */ 312)
- prg.printScaled(prg.pageSoFar[4])
- prg.print( /* "fill" */ 978)
- }
- if prg.pageSoFar[5] != 0 {
- prg.print( /* " plus " */ 312)
- prg.printScaled(prg.pageSoFar[5])
- prg.print( /* "filll" */ 979)
- }
- if prg.pageSoFar[6] != 0 {
- prg.print( /* " minus " */ 313)
- prg.printScaled(prg.pageSoFar[6])
- }
- }
- // 987.
- // tangle:pos tex.web:19313:1:
- // Here is a procedure that is called when the |page_contents| is changing
- // from |empty| to |inserts_only| or |box_there|.
- func (prg *prg) freezePageSpecs(s smallNumber) {
- prg.pageContents = s
- prg.pageSoFar[0] = *prg.eqtb[dimenBase+vsizeCode-1].int()
- prg.pageMaxDepth = *prg.eqtb[dimenBase+maxDepthCode-1].int()
- prg.pageSoFar[7] = 0
- prg.pageSoFar[1] = 0
- prg.pageSoFar[2] = 0
- prg.pageSoFar[3] = 0
- prg.pageSoFar[4] = 0
- prg.pageSoFar[5] = 0
- prg.pageSoFar[6] = 0
- prg.leastPageCost = 07777777777
- // if eqtb[int_base+ tracing_pages_code].int >0 then
- // begin begin_diagnostic;
- // print_nl(["%% goal height="=]987); print_scaled(page_so_far[0] );
- // [ \xref[goal height] ]
- // print([", max depth="=]988); print_scaled(page_max_depth);
- // end_diagnostic(false);
- // end; [ ]
- }
- // 992.
- // tangle:pos tex.web:19377:1:
- // At certain times box 255 is supposed to be void (i.e., |null|),
- // or an insertion box is supposed to be ready to accept a vertical list.
- // If not, an error message is printed, and the following subroutine
- // flushes the unwanted contents, reporting them to the user.
- func (prg *prg) boxError(n eightBits) {
- prg.error1()
- prg.beginDiagnostic()
- prg.printNl(strNumber( /* "The following box has been deleted:" */ 836))
- // \xref[The following...deleted]
- prg.showBox(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())
- prg.endDiagnostic(true)
- prg.flushNodeList(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())
- *(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = 0
- }
- // 993.
- // tangle:pos tex.web:19390:1:
- // The following procedure guarantees that a given box register
- // does not contain an \.[\\hbox].
- func (prg *prg) ensureVbox(n eightBits) {
- var (
- p halfword // the box register contents
- )
- p = *(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()
- if int32(p) != 0 {
- if int32(*(*prg.mem[p].hh()).b0()) == hlistNode {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Insertions can only be added to a vbox" */ 989)
- }
- // \xref[Insertions can only...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "Tut tut: You're trying to \\insert into a" */ 990
- prg.helpLine[1] = /* "\\box register that now contains an \\hbox." */ 991
- prg.helpLine[0] = /* "Proceed, and I'll discard its present contents." */ 992
- }
- prg.boxError(n)
- }
- }
- }
- // 994.
- // tangle:pos tex.web:19406:1:
- // \TeX\ is not always in vertical mode at the time |build_page|
- // is called; the current mode reflects what \TeX\ should return to, after
- // the contribution list has been emptied. A call on |build_page| should
- // be immediately followed by `|goto big_switch|', which is \TeX's central
- // control point.
- // \4
- // Declare the procedure called |fire_up|
- func (prg *prg) fireUp(c halfword) {
- var (
- p, q, r1, s halfword // nodes being examined and/or changed
- prevP halfword // predecessor of |p|
- n/* minQuarterword..255 */ byte // insertion box number
- wait bool // should the present insertion be held over?
- saveVbadness int32 // saved value of |vbadness|
- saveVfuzz scaled // saved value of |vfuzz|
- saveSplitTopSkip halfword // saved value of |split_top_skip|
- )
- if int32(*(*prg.mem[prg.bestPageBreak].hh()).b0()) == penaltyNode {
- prg.geqWordDefine(halfword(intBase+outputPenaltyCode), *prg.mem[int32(prg.bestPageBreak)+1].int())
- *prg.mem[int32(prg.bestPageBreak)+1].int() = infPenalty
- } else {
- prg.geqWordDefine(halfword(intBase+outputPenaltyCode), infPenalty)
- }
- if int32(prg.curMark[botMarkCode]) != 0 {
- if int32(prg.curMark[topMarkCode]) != 0 {
- prg.deleteTokenRef(prg.curMark[topMarkCode])
- }
- prg.curMark[topMarkCode] = prg.curMark[botMarkCode]
- *(*prg.mem[prg.curMark[topMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[topMarkCode]].hh()).lh()) + 1)
- prg.deleteTokenRef(prg.curMark[firstMarkCode])
- prg.curMark[firstMarkCode] = 0
- }
- // Put the \(o)optimal current page into box 255, update |first_mark| and |bot_mark|, append insertions to their boxes, and put the remaining nodes back on the contribution list
- if int32(c) == int32(prg.bestPageBreak) {
- prg.bestPageBreak = 0
- } // |c| not yet linked in
- // Ensure that box 255 is empty before output
- if int32(*(*prg.eqtb[boxBase+255-1].hh()).rh()) != 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "" */ 338)
- }
- prg.printEsc(strNumber( /* "box" */ 409))
- prg.print( /* "255 is not void" */ 1003)
- // \xref[box255][\.[\\box255 is not void]]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "You shouldn't use \\box255 except in \\output routines." */ 1004
- prg.helpLine[0] = /* "Proceed, and I'll discard its present contents." */ 992
- }
- prg.boxError(eightBits(255))
- }
- prg.insertPenalties = 0 // this will count the number of insertions held over
- saveSplitTopSkip = *(*prg.eqtb[glueBase+splitTopSkipCode-1].hh()).rh()
- if *prg.eqtb[intBase+holdingInsertsCode-1].int() <= 0 {
- r1 = *(*prg.mem[30000].hh()).rh()
- for int32(r1) != 30000 {
- if int32(*(*prg.mem[int32(r1)+2].hh()).lh()) != 0 {
- n = byte(int32(*(*prg.mem[r1].hh()).b1()) - minQuarterword)
- prg.ensureVbox(n)
- if int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()) == 0 {
- *(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = prg.newNullBox()
- }
- p = uint16(int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()) + listOffset)
- for int32(*(*prg.mem[p].hh()).rh()) != 0 {
- p = *(*prg.mem[p].hh()).rh()
- }
- *(*prg.mem[int32(r1)+2].hh()).rh() = p
- }
- r1 = *(*prg.mem[r1].hh()).rh()
- }
- }
- q = uint16(30000 - 4)
- *(*prg.mem[q].hh()).rh() = 0
- prevP = uint16(30000 - 2)
- p = *(*prg.mem[prevP].hh()).rh()
- for int32(p) != int32(prg.bestPageBreak) {
- if int32(*(*prg.mem[p].hh()).b0()) == insNode {
- if *prg.eqtb[intBase+holdingInsertsCode-1].int() <= 0 {
- r1 = *(*prg.mem[30000].hh()).rh()
- for int32(*(*prg.mem[r1].hh()).b1()) != int32(*(*prg.mem[p].hh()).b1()) {
- r1 = *(*prg.mem[r1].hh()).rh()
- }
- if int32(*(*prg.mem[int32(r1)+2].hh()).lh()) == 0 {
- wait = true
- } else {
- wait = false
- s = *(*prg.mem[int32(r1)+2].hh()).rh()
- *(*prg.mem[s].hh()).rh() = *(*prg.mem[int32(p)+4].hh()).lh()
- if int32(*(*prg.mem[int32(r1)+2].hh()).lh()) == int32(p) {
- if int32(*(*prg.mem[r1].hh()).b0()) == splitUp {
- if int32(*(*prg.mem[int32(r1)+1].hh()).lh()) == int32(p) && int32(*(*prg.mem[int32(r1)+1].hh()).rh()) != 0 {
- for int32(*(*prg.mem[s].hh()).rh()) != int32(*(*prg.mem[int32(r1)+1].hh()).rh()) {
- s = *(*prg.mem[s].hh()).rh()
- }
- *(*prg.mem[s].hh()).rh() = 0
- *(*prg.eqtb[glueBase+splitTopSkipCode-1].hh()).rh() = *(*prg.mem[int32(p)+4].hh()).rh()
- *(*prg.mem[int32(p)+4].hh()).lh() = prg.prunePageTop(*(*prg.mem[int32(r1)+1].hh()).rh())
- if int32(*(*prg.mem[int32(p)+4].hh()).lh()) != 0 {
- prg.tempPtr = prg.vpackage(*(*prg.mem[int32(p)+4].hh()).lh(), scaled(0), smallNumber(additional), scaled(07777777777))
- *prg.mem[int32(p)+heightOffset].int() = *prg.mem[int32(prg.tempPtr)+heightOffset].int() + *prg.mem[int32(prg.tempPtr)+depthOffset].int()
- prg.freeNode(prg.tempPtr, halfword(boxNodeSize))
- wait = true
- }
- }
- }
- *(*prg.mem[int32(r1)+2].hh()).lh() = 0
- n = byte(int32(*(*prg.mem[r1].hh()).b1()) - minQuarterword)
- prg.tempPtr = *(*prg.mem[int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())+listOffset].hh()).rh()
- prg.freeNode(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh(), halfword(boxNodeSize))
- *(*prg.eqtb[boxBase+int32(n)-1].hh()).rh() = prg.vpackage(prg.tempPtr, scaled(0), smallNumber(additional), scaled(07777777777))
- } else {
- for int32(*(*prg.mem[s].hh()).rh()) != 0 {
- s = *(*prg.mem[s].hh()).rh()
- }
- *(*prg.mem[int32(r1)+2].hh()).rh() = s
- }
- }
- // Either append the insertion node |p| after node |q|, and remove it from the current page, or delete |node(p)|
- *(*prg.mem[prevP].hh()).rh() = *(*prg.mem[p].hh()).rh()
- *(*prg.mem[p].hh()).rh() = 0
- if wait {
- *(*prg.mem[q].hh()).rh() = p
- q = p
- prg.insertPenalties = prg.insertPenalties + 1
- } else {
- prg.deleteGlueRef(*(*prg.mem[int32(p)+4].hh()).rh())
- prg.freeNode(p, halfword(insNodeSize))
- }
- p = prevP
- }
- } else if int32(*(*prg.mem[p].hh()).b0()) == markNode {
- if int32(prg.curMark[firstMarkCode]) == 0 {
- prg.curMark[firstMarkCode] = uint16(*prg.mem[int32(p)+1].int())
- *(*prg.mem[prg.curMark[firstMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[firstMarkCode]].hh()).lh()) + 1)
- }
- if int32(prg.curMark[botMarkCode]) != 0 {
- prg.deleteTokenRef(prg.curMark[botMarkCode])
- }
- prg.curMark[botMarkCode] = uint16(*prg.mem[int32(p)+1].int())
- *(*prg.mem[prg.curMark[botMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[botMarkCode]].hh()).lh()) + 1)
- }
- prevP = p
- p = *(*prg.mem[prevP].hh()).rh()
- }
- *(*prg.eqtb[glueBase+splitTopSkipCode-1].hh()).rh() = saveSplitTopSkip
- // Break the current page at node |p|, put it in box~255, and put the remaining nodes on the contribution list
- if int32(p) != 0 {
- if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 {
- if int32(prg.nestPtr) == 0 {
- prg.curList.tailField = prg.pageTail
- } else {
- prg.nest[0].tailField = prg.pageTail
- }
- }
- *(*prg.mem[prg.pageTail].hh()).rh() = *(*prg.mem[30000-1].hh()).rh()
- *(*prg.mem[30000-1].hh()).rh() = p
- *(*prg.mem[prevP].hh()).rh() = 0
- }
- saveVbadness = *prg.eqtb[intBase+vbadnessCode-1].int()
- *prg.eqtb[intBase+vbadnessCode-1].int() = infBad
- saveVfuzz = *prg.eqtb[dimenBase+vfuzzCode-1].int()
- *prg.eqtb[dimenBase+vfuzzCode-1].int() = 07777777777 // inhibit error messages
- *(*prg.eqtb[boxBase+255-1].hh()).rh() = prg.vpackage(*(*prg.mem[30000-2].hh()).rh(), prg.bestSize, smallNumber(exactly), prg.pageMaxDepth)
- *prg.eqtb[intBase+vbadnessCode-1].int() = saveVbadness
- *prg.eqtb[dimenBase+vfuzzCode-1].int() = saveVfuzz
- if int32(prg.lastGlue) != 65535 {
- prg.deleteGlueRef(prg.lastGlue)
- }
- // Start a new current page
- prg.pageContents = byte(empty)
- prg.pageTail = uint16(30000 - 2)
- *(*prg.mem[30000-2].hh()).rh() = 0
- prg.lastGlue = 65535
- prg.lastPenalty = 0
- prg.lastKern = 0
- prg.pageSoFar[7] = 0
- prg.pageMaxDepth = 0 // this sets |last_glue:=max_halfword|
- if int32(q) != 30000-4 {
- *(*prg.mem[30000-2].hh()).rh() = *(*prg.mem[30000-4].hh()).rh()
- prg.pageTail = q
- }
- // Delete \(t)the page-insertion nodes
- r1 = *(*prg.mem[30000].hh()).rh()
- for int32(r1) != 30000 {
- q = *(*prg.mem[r1].hh()).rh()
- prg.freeNode(r1, halfword(pageInsNodeSize))
- r1 = q
- }
- *(*prg.mem[30000].hh()).rh() = 30000
- if int32(prg.curMark[topMarkCode]) != 0 && int32(prg.curMark[firstMarkCode]) == 0 {
- prg.curMark[firstMarkCode] = prg.curMark[topMarkCode]
- *(*prg.mem[prg.curMark[topMarkCode]].hh()).lh() = uint16(int32(*(*prg.mem[prg.curMark[topMarkCode]].hh()).lh()) + 1)
- }
- if int32(*(*prg.eqtb[outputRoutineLoc-1].hh()).rh()) != 0 {
- if prg.deadCycles >= *prg.eqtb[intBase+maxDeadCyclesCode-1].int() {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Output loop---" */ 1005)
- }
- prg.printInt(prg.deadCycles)
- // \xref[Output loop...]
- prg.print( /* " consecutive dead cycles" */ 1006)
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "I've concluded that your \\output is awry; it never does a" */ 1007
- prg.helpLine[1] = /* "\\shipout, so I'm shipping \\box255 out myself. Next time" */ 1008
- prg.helpLine[0] = /* "increase \\maxdeadcycles if you want me to be more patient!" */ 1009
- }
- prg.error1()
- } else {
- // Fire up the user's output routine and |return|
- prg.outputActive = true
- prg.deadCycles = prg.deadCycles + 1
- prg.pushNest()
- prg.curList.modeField = int16(-vmode)
- *prg.curList.auxField.int() = -65536000
- prg.curList.mlField = -prg.line
- prg.beginTokenList(*(*prg.eqtb[outputRoutineLoc-1].hh()).rh(), quarterword(outputText))
- prg.newSaveLevel(groupCode(outputGroup))
- prg.normalParagraph()
- prg.scanLeftBrace()
- goto exit
- }
- }
- // Perform the default output routine
- {
- if int32(*(*prg.mem[30000-2].hh()).rh()) != 0 {
- if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 {
- if int32(prg.nestPtr) == 0 {
- prg.curList.tailField = prg.pageTail
- } else {
- prg.nest[0].tailField = prg.pageTail
- }
- } else {
- *(*prg.mem[prg.pageTail].hh()).rh() = *(*prg.mem[30000-1].hh()).rh()
- }
- *(*prg.mem[30000-1].hh()).rh() = *(*prg.mem[30000-2].hh()).rh()
- *(*prg.mem[30000-2].hh()).rh() = 0
- prg.pageTail = uint16(30000 - 2)
- }
- prg.shipOut(*(*prg.eqtb[boxBase+255-1].hh()).rh())
- *(*prg.eqtb[boxBase+255-1].hh()).rh() = 0
- }
- exit:
- } // \2
- func (prg *prg) buildPage() {
- var (
- p halfword // the node being appended
- q, r1 halfword // nodes being examined
- b, c int32 // badness and cost of current page
- pi int32 // penalty to be added to the badness
- n/* minQuarterword..255 */ byte // insertion box number
- delta, h, w scaled // sizes used for insertion calculations
- )
- if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 || prg.outputActive {
- goto exit
- }
- for {
- continue1:
- p = *(*prg.mem[30000-1].hh()).rh()
- // Update the values of |last_glue|, |last_penalty|, and |last_kern|
- if int32(prg.lastGlue) != 65535 {
- prg.deleteGlueRef(prg.lastGlue)
- }
- prg.lastPenalty = 0
- prg.lastKern = 0
- if int32(*(*prg.mem[p].hh()).b0()) == glueNode {
- prg.lastGlue = *(*prg.mem[int32(p)+1].hh()).lh()
- *(*prg.mem[prg.lastGlue].hh()).rh() = uint16(int32(*(*prg.mem[prg.lastGlue].hh()).rh()) + 1)
- } else {
- prg.lastGlue = 65535
- if int32(*(*prg.mem[p].hh()).b0()) == penaltyNode {
- prg.lastPenalty = *prg.mem[int32(p)+1].int()
- } else if int32(*(*prg.mem[p].hh()).b0()) == kernNode {
- prg.lastKern = *prg.mem[int32(p)+widthOffset].int()
- }
- }
- // Move node |p| to the current page; if it is time for a page break, put the nodes following the break back onto the contribution list, and |return| to the user's output routine if there is one
- // If the current page is empty and node |p| is to be deleted, |goto done1|; otherwise use node |p| to update the state of the current page; if this node is an insertion, |goto contribute|; otherwise if this node is not a legal breakpoint, |goto contribute| or |update_heights|; otherwise set |pi| to the penalty associated with this breakpoint
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, ruleNode:
- if int32(prg.pageContents) < boxThere {
- if int32(prg.pageContents) == empty {
- prg.freezePageSpecs(smallNumber(boxThere))
- } else {
- prg.pageContents = byte(boxThere)
- }
- q = prg.newSkipParam(smallNumber(topSkipCode)) // now |temp_ptr=glue_ptr(q)|
- if *prg.mem[int32(prg.tempPtr)+widthOffset].int() > *prg.mem[int32(p)+heightOffset].int() {
- *prg.mem[int32(prg.tempPtr)+widthOffset].int() = *prg.mem[int32(prg.tempPtr)+widthOffset].int() - *prg.mem[int32(p)+heightOffset].int()
- } else {
- *prg.mem[int32(prg.tempPtr)+widthOffset].int() = 0
- }
- *(*prg.mem[q].hh()).rh() = p
- *(*prg.mem[30000-1].hh()).rh() = q
- goto continue1
- } else {
- // Prepare to move a box or rule node to the current page, then |goto contribute|
- prg.pageSoFar[1] = prg.pageSoFar[1] + prg.pageSoFar[7] + *prg.mem[int32(p)+heightOffset].int()
- prg.pageSoFar[7] = *prg.mem[int32(p)+depthOffset].int()
- goto contribute
- }
- case whatsitNode:
- // Prepare to move whatsit |p| to the current page, then |goto contribute|
- // Prepare to move whatsit |p| to the current page, then |goto contribute|
- goto contribute
- case glueNode:
- if int32(prg.pageContents) < boxThere {
- goto done1
- } else if int32(*(*prg.mem[prg.pageTail].hh()).b0()) < mathNode {
- pi = 0
- } else {
- goto updateHeights
- }
- case kernNode:
- if int32(prg.pageContents) < boxThere {
- goto done1
- } else if int32(*(*prg.mem[p].hh()).rh()) == 0 {
- goto exit
- } else if int32(*(*prg.mem[*(*prg.mem[p].hh()).rh()].hh()).b0()) == glueNode {
- pi = 0
- } else {
- goto updateHeights
- }
- case penaltyNode:
- if int32(prg.pageContents) < boxThere {
- goto done1
- } else {
- pi = *prg.mem[int32(p)+1].int()
- }
- case markNode:
- goto contribute
- case insNode:
- // Append an insertion to the current page and |goto contribute|
- if int32(prg.pageContents) == empty {
- prg.freezePageSpecs(smallNumber(insertsOnly))
- }
- n = *(*prg.mem[p].hh()).b1()
- r1 = 30000
- for int32(n) >= int32(*(*prg.mem[*(*prg.mem[r1].hh()).rh()].hh()).b1()) {
- r1 = *(*prg.mem[r1].hh()).rh()
- }
- n = byte(int32(n) - minQuarterword)
- if int32(*(*prg.mem[r1].hh()).b1()) != int32(n)+minQuarterword {
- q = prg.getNode(pageInsNodeSize)
- *(*prg.mem[q].hh()).rh() = *(*prg.mem[r1].hh()).rh()
- *(*prg.mem[r1].hh()).rh() = q
- r1 = q
- *(*prg.mem[r1].hh()).b1() = byte(int32(n) + minQuarterword)
- *(*prg.mem[r1].hh()).b0() = byte(inserting)
- prg.ensureVbox(n)
- if int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh()) == 0 {
- *prg.mem[int32(r1)+heightOffset].int() = 0
- } else {
- *prg.mem[int32(r1)+heightOffset].int() = *prg.mem[int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())+heightOffset].int() + *prg.mem[int32(*(*prg.eqtb[boxBase+int32(n)-1].hh()).rh())+depthOffset].int()
- }
- *(*prg.mem[int32(r1)+2].hh()).lh() = 0
- q = *(*prg.eqtb[skipBase+int32(n)-1].hh()).rh()
- if *prg.eqtb[countBase+int32(n)-1].int() == 1000 {
- h = *prg.mem[int32(r1)+heightOffset].int()
- } else {
- h = prg.xOverN(*prg.mem[int32(r1)+heightOffset].int(), 1000) * *prg.eqtb[countBase+int32(n)-1].int()
- }
- prg.pageSoFar[0] = prg.pageSoFar[0] - h - *prg.mem[int32(q)+widthOffset].int()
- prg.pageSoFar[2+int32(*(*prg.mem[q].hh()).b0())] = prg.pageSoFar[2+int32(*(*prg.mem[q].hh()).b0())] + *prg.mem[int32(q)+2].int()
- prg.pageSoFar[6] = prg.pageSoFar[6] + *prg.mem[int32(q)+3].int()
- if int32(*(*prg.mem[q].hh()).b1()) != normal && *prg.mem[int32(q)+3].int() != 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Infinite glue shrinkage inserted from " */ 998)
- }
- prg.printEsc(strNumber( /* "skip" */ 395))
- // \xref[Infinite glue shrinkage...]
- prg.printInt(int32(n))
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "The correction glue for page breaking with insertions" */ 999
- prg.helpLine[1] = /* "must have finite shrinkability. But you may proceed," */ 1000
- prg.helpLine[0] = /* "since the offensive shrinkability has been made finite." */ 922
- }
- prg.error1()
- }
- }
- if int32(*(*prg.mem[r1].hh()).b0()) == splitUp {
- prg.insertPenalties = prg.insertPenalties + *prg.mem[int32(p)+1].int()
- } else {
- *(*prg.mem[int32(r1)+2].hh()).rh() = p
- delta = prg.pageSoFar[0] - prg.pageSoFar[1] - prg.pageSoFar[7] + prg.pageSoFar[6]
- // this much room is left if we shrink the maximum
- if *prg.eqtb[countBase+int32(n)-1].int() == 1000 {
- h = *prg.mem[int32(p)+heightOffset].int()
- } else {
- h = prg.xOverN(*prg.mem[int32(p)+heightOffset].int(), 1000) * *prg.eqtb[countBase+int32(n)-1].int()
- } // this much room is needed
- if (h <= 0 || h <= delta) && *prg.mem[int32(p)+heightOffset].int()+*prg.mem[int32(r1)+heightOffset].int() <= *prg.eqtb[scaledBase+int32(n)-1].int() {
- prg.pageSoFar[0] = prg.pageSoFar[0] - h
- *prg.mem[int32(r1)+heightOffset].int() = *prg.mem[int32(r1)+heightOffset].int() + *prg.mem[int32(p)+heightOffset].int()
- } else {
- // Find the best way to split the insertion, and change |type(r)| to |split_up|
- if *prg.eqtb[countBase+int32(n)-1].int() <= 0 {
- w = 07777777777
- } else {
- w = prg.pageSoFar[0] - prg.pageSoFar[1] - prg.pageSoFar[7]
- if *prg.eqtb[countBase+int32(n)-1].int() != 1000 {
- w = prg.xOverN(w, *prg.eqtb[countBase+int32(n)-1].int()) * 1000
- }
- }
- if w > *prg.eqtb[scaledBase+int32(n)-1].int()-*prg.mem[int32(r1)+heightOffset].int() {
- w = *prg.eqtb[scaledBase+int32(n)-1].int() - *prg.mem[int32(r1)+heightOffset].int()
- }
- q = prg.vertBreak(*(*prg.mem[int32(p)+4].hh()).lh(), w, *prg.mem[int32(p)+depthOffset].int())
- *prg.mem[int32(r1)+heightOffset].int() = *prg.mem[int32(r1)+heightOffset].int() + prg.bestHeightPlusDepth
- // if eqtb[int_base+ tracing_pages_code].int >0 then
- // [ Display the insertion split cost ]
- // begin begin_diagnostic; print_nl(["% split"=]1001); print_int(n);
- // [ \xref[split] ]
- // print([" to "=]1002); print_scaled(w);
- // print_char([","=]44); print_scaled(best_height_plus_depth);
- //
- // print([" p="=]931);
- // if q=0 then print_int(eject_penalty)
- // else if mem[ q].hh.b0 =penalty_node then print_int( mem[ q+1].int )
- // else print_char(["0"=]48);
- // end_diagnostic(false);
- // end
- //
- // ; [ ]
- if *prg.eqtb[countBase+int32(n)-1].int() != 1000 {
- prg.bestHeightPlusDepth = prg.xOverN(prg.bestHeightPlusDepth, 1000) * *prg.eqtb[countBase+int32(n)-1].int()
- }
- prg.pageSoFar[0] = prg.pageSoFar[0] - prg.bestHeightPlusDepth
- *(*prg.mem[r1].hh()).b0() = byte(splitUp)
- *(*prg.mem[int32(r1)+1].hh()).rh() = q
- *(*prg.mem[int32(r1)+1].hh()).lh() = p
- if int32(q) == 0 {
- prg.insertPenalties = prg.insertPenalties + ejectPenalty
- } else if int32(*(*prg.mem[q].hh()).b0()) == penaltyNode {
- prg.insertPenalties = prg.insertPenalties + *prg.mem[int32(q)+1].int()
- }
- }
- }
- goto contribute
- default:
- prg.confusion(strNumber( /* "page" */ 993))
- // \xref[this can't happen page][\quad page]
- }
- // Check if node |p| is a new champion breakpoint; then \(if)if it is time for a page break, prepare for output, and either fire up the user's output routine and |return| or ship out the page and |goto done|
- if pi < infPenalty {
- if prg.pageSoFar[1] < prg.pageSoFar[0] {
- if prg.pageSoFar[3] != 0 || prg.pageSoFar[4] != 0 || prg.pageSoFar[5] != 0 {
- b = 0
- } else {
- b = int32(prg.badness(prg.pageSoFar[0]-prg.pageSoFar[1], prg.pageSoFar[2]))
- }
- } else if prg.pageSoFar[1]-prg.pageSoFar[0] > prg.pageSoFar[6] {
- b = 07777777777
- } else {
- b = int32(prg.badness(prg.pageSoFar[1]-prg.pageSoFar[0], prg.pageSoFar[6]))
- }
- if b < 07777777777 {
- if pi <= ejectPenalty {
- c = pi
- } else if b < infBad {
- c = b + pi + prg.insertPenalties
- } else {
- c = 100000
- }
- } else {
- c = b
- }
- if prg.insertPenalties >= 10000 {
- c = 07777777777
- }
- // if eqtb[int_base+ tracing_pages_code].int >0 then
- // [ Display the page break cost ]
- // begin begin_diagnostic; print_nl(["%"=]37);
- // print([" t="=]927); print_totals;
- //
- // print([" g="=]996); print_scaled(page_so_far[0] );
- //
- // print([" b="=]930);
- // if b=[07777777777=]1073741823 then print_char(["*"=]42) else print_int(b);
- // [ \xref[*\relax] ]
- // print([" p="=]931); print_int(pi);
- // print([" c="=]997);
- // if c=[07777777777=]1073741823 then print_char(["*"=]42) else print_int(c);
- // if c<=least_page_cost then print_char(["#"=]35);
- // end_diagnostic(false);
- // end
- //
- // ; [ ]
- if c <= prg.leastPageCost {
- prg.bestPageBreak = p
- prg.bestSize = prg.pageSoFar[0]
- prg.leastPageCost = c
- r1 = *(*prg.mem[30000].hh()).rh()
- for int32(r1) != 30000 {
- *(*prg.mem[int32(r1)+2].hh()).lh() = *(*prg.mem[int32(r1)+2].hh()).rh()
- r1 = *(*prg.mem[r1].hh()).rh()
- }
- }
- if c == 07777777777 || pi <= ejectPenalty {
- prg.fireUp(p) // output the current page at the best place
- if prg.outputActive {
- goto exit
- } // user's output routine will act
- // user's output routine will act
- goto done // the page has been shipped out by default output routine
- }
- }
- if int32(*(*prg.mem[p].hh()).b0()) < glueNode || int32(*(*prg.mem[p].hh()).b0()) > kernNode {
- goto contribute
- }
- updateHeights:
- if int32(*(*prg.mem[p].hh()).b0()) == kernNode {
- q = p
- } else {
- q = *(*prg.mem[int32(p)+1].hh()).lh()
- prg.pageSoFar[2+int32(*(*prg.mem[q].hh()).b0())] = prg.pageSoFar[2+int32(*(*prg.mem[q].hh()).b0())] + *prg.mem[int32(q)+2].int()
- prg.pageSoFar[6] = prg.pageSoFar[6] + *prg.mem[int32(q)+3].int()
- if int32(*(*prg.mem[q].hh()).b1()) != normal && *prg.mem[int32(q)+3].int() != 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Infinite glue shrinkage found on current page" */ 994)
- }
- // \xref[Infinite glue shrinkage...]
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "The page about to be output contains some infinitely" */ 995
- prg.helpLine[2] = /* "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'." */ 963
- prg.helpLine[1] = /* "Such glue doesn't belong there; but you can safely proceed," */ 964
- prg.helpLine[0] = /* "since the offensive shrinkability has been made finite." */ 922
- }
- prg.error1()
- r1 = prg.newSpec(q)
- *(*prg.mem[r1].hh()).b1() = byte(normal)
- prg.deleteGlueRef(q)
- *(*prg.mem[int32(p)+1].hh()).lh() = r1
- q = r1
- }
- }
- prg.pageSoFar[1] = prg.pageSoFar[1] + prg.pageSoFar[7] + *prg.mem[int32(q)+widthOffset].int()
- prg.pageSoFar[7] = 0
- contribute:
- if prg.pageSoFar[7] > prg.pageMaxDepth {
- prg.pageSoFar[1] = prg.pageSoFar[1] + prg.pageSoFar[7] - prg.pageMaxDepth
- prg.pageSoFar[7] = prg.pageMaxDepth
- }
- // Link node |p| into the current page and |goto done|
- *(*prg.mem[prg.pageTail].hh()).rh() = p
- prg.pageTail = p
- *(*prg.mem[30000-1].hh()).rh() = *(*prg.mem[p].hh()).rh()
- *(*prg.mem[p].hh()).rh() = 0
- goto done
- done1:
- *(*prg.mem[30000-1].hh()).rh() = *(*prg.mem[p].hh()).rh()
- *(*prg.mem[p].hh()).rh() = 0
- prg.flushNodeList(p)
- done:
- ;
- if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 {
- break
- }
- }
- // Make the contribution list empty by setting its tail to |contrib_head|
- if int32(prg.nestPtr) == 0 {
- prg.curList.tailField = uint16(30000 - 1)
- } else {
- prg.nest[0].tailField = uint16(30000 - 1)
- }
- exit:
- }
- // 1029. \[46] The chief executive
- // tangle:pos tex.web:19977:26:
- // We come now to the |main_control| routine, which contains the master
- // switch that causes all the various pieces of \TeX\ to do their things,
- // in the right order.
- //
- // In a sense, this is the grand climax of the program: It applies all the
- // tools that we have worked so hard to construct. In another sense, this is
- // the messiest part of the program: It necessarily refers to other pieces
- // of code all over the place, so that a person can't fully understand what is
- // going on without paging back and forth to be reminded of conventions that
- // are defined elsewhere. We are now at the hub of the web, the central nervous
- // system that touches most of the other parts and ties them together.
- // \xref[brain]
- //
- // The structure of |main_control| itself is quite simple. There's a label
- // called |big_switch|, at which point the next token of input is fetched
- // using |get_x_token|. Then the program branches at high speed into one of
- // about 100 possible directions, based on the value of the current
- // mode and the newly fetched command code; the sum |abs(mode)+cur_cmd|
- // indicates what to do next. For example, the case `|vmode+letter|' arises
- // when a letter occurs in vertical mode (or internal vertical mode); this
- // case leads to instructions that initialize a new paragraph and enter
- // horizontal mode.
- //
- // The big |case| statement that contains this multiway switch has been labeled
- // |reswitch|, so that the program can |goto reswitch| when the next token
- // has already been fetched. Most of the cases are quite short; they call
- // an ``action procedure'' that does the work for that case, and then they
- // either |goto reswitch| or they ``fall through'' to the end of the |case|
- // statement, which returns control back to |big_switch|. Thus, |main_control|
- // is not an extremely large procedure, in spite of the multiplicity of things
- // it must do; it is small enough to be handled by \PASCAL\ compilers that put
- // severe restrictions on procedure size.
- // \xref[action procedure]
- //
- // One case is singled out for special treatment, because it accounts for most
- // of \TeX's activities in typical applications. The process of reading simple
- // text and converting it into |char_node| records, while looking for ligatures
- // and kerns, is part of \TeX's ``inner loop''; the whole program runs
- // efficiently when its inner loop is fast, so this part has been written
- // with particular care.
- // 1030.
- // tangle:pos tex.web:20017:22:
- // We shall concentrate first on the inner loop of |main_control|, deferring
- // consideration of the other cases until later.
- // \xref[inner loop]
- // \4
- // Declare action procedures for use by |main_control|
- func (prg *prg) appSpace() { // handle spaces when |space_factor<>1000|
- var (
- q halfword // glue node
- )
- if int32(*(*prg.curList.auxField.hh()).lh()) >= 2000 && int32(*(*prg.eqtb[glueBase+xspaceSkipCode-1].hh()).rh()) != memBot {
- q = prg.newParamGlue(smallNumber(xspaceSkipCode))
- } else {
- if int32(*(*prg.eqtb[glueBase+spaceSkipCode-1].hh()).rh()) != memBot {
- prg.mainP = *(*prg.eqtb[glueBase+spaceSkipCode-1].hh()).rh()
- } else {
- // Find the glue specification...
- prg.mainP = prg.fontGlue[*(*prg.eqtb[curFontLoc-1].hh()).rh()]
- if int32(prg.mainP) == 0 {
- prg.mainP = prg.newSpec(halfword(memBot))
- prg.mainK = uint16(prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()] + spaceCode)
- *prg.mem[int32(prg.mainP)+widthOffset].int() = *prg.fontInfo[prg.mainK].int() // that's |space(cur_font)|
- *prg.mem[int32(prg.mainP)+2].int() = *prg.fontInfo[int32(prg.mainK)+1].int() // and |space_stretch(cur_font)|
- *prg.mem[int32(prg.mainP)+3].int() = *prg.fontInfo[int32(prg.mainK)+2].int() // and |space_shrink(cur_font)|
- prg.fontGlue[*(*prg.eqtb[curFontLoc-1].hh()).rh()] = prg.mainP
- }
- }
- prg.mainP = prg.newSpec(prg.mainP)
- // Modify the glue specification in |main_p| according to the space factor
- if int32(*(*prg.curList.auxField.hh()).lh()) >= 2000 {
- *prg.mem[int32(prg.mainP)+widthOffset].int() = *prg.mem[int32(prg.mainP)+widthOffset].int() + *prg.fontInfo[extraSpaceCode+prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()]].int()
- }
- *prg.mem[int32(prg.mainP)+2].int() = prg.xnOverD(*prg.mem[int32(prg.mainP)+2].int(), int32(*(*prg.curList.auxField.hh()).lh()), 1000)
- *prg.mem[int32(prg.mainP)+3].int() = prg.xnOverD(*prg.mem[int32(prg.mainP)+3].int(), 1000, int32(*(*prg.curList.auxField.hh()).lh()))
- q = prg.newGlue(prg.mainP)
- *(*prg.mem[prg.mainP].hh()).rh() = 0
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = q
- prg.curList.tailField = q
- }
- func (prg *prg) insertDollarSign() {
- prg.backInput()
- prg.curTok = uint16(mathShiftToken + '$')
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing $ inserted" */ 1017)
- }
- // \xref[Missing \$ inserted]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I've inserted a begin-math/end-math symbol since I think" */ 1018
- prg.helpLine[0] = /* "you left one out. Proceed, with fingers crossed." */ 1019
- }
- prg.insError()
- }
- func (prg *prg) youCant() {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "You can't use `" */ 685)
- }
- // \xref[You can't use x in y mode]
- prg.printCmdChr(prg.curCmd, prg.curChr)
- prg.print( /* "' in " */ 1020)
- prg.printMode(int32(prg.curList.modeField))
- }
- func (prg *prg) reportIllegalCase() {
- prg.youCant()
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "Sorry, but I'm not programmed to handle this case;" */ 1021
- prg.helpLine[2] = /* "I'll just pretend that you didn't ask for it." */ 1022
- prg.helpLine[1] = /* "If you're in the wrong mode, you might be able to" */ 1023
- prg.helpLine[0] = /* "return to the right one by typing `I]' or `I$' or `I\\par'." */ 1024
- }
- prg.error1()
- }
- func (prg *prg) privileged() (r bool) {
- if int32(prg.curList.modeField) > 0 {
- r = true
- } else {
- prg.reportIllegalCase()
- r = false
- }
- return r
- }
- func (prg *prg) itsAllOver() (r bool) {
- if prg.privileged() {
- if 30000-2 == int32(prg.pageTail) && int32(prg.curList.headField) == int32(prg.curList.tailField) && prg.deadCycles == 0 {
- r = true
- goto exit
- }
- prg.backInput() // we will try to end again after ejecting residual material
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNullBox()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *prg.mem[int32(prg.curList.tailField)+widthOffset].int() = *prg.eqtb[dimenBase+hsizeCode-1].int()
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(halfword(memBot + glueSpecSize + glueSpecSize))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(-010000000000)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- prg.buildPage() // append \.[\\hbox to \\hsize\[\]\\vfill\\penalty-'10000000000]
- }
- r = false
- exit:
- ;
- return r
- }
- func (prg *prg) appendGlue() {
- var (
- s smallNumber // modifier of skip command
- )
- s = byte(prg.curChr)
- switch s {
- case filCode:
- prg.curVal = memBot + glueSpecSize
- case fillCode:
- prg.curVal = memBot + glueSpecSize + glueSpecSize
- case ssCode:
- prg.curVal = memBot + glueSpecSize + glueSpecSize + glueSpecSize
- case filNegCode:
- prg.curVal = memBot + glueSpecSize + glueSpecSize + glueSpecSize + glueSpecSize
- case skipCode:
- prg.scanGlue(smallNumber(glueVal))
- case mskipCode:
- prg.scanGlue(smallNumber(muVal))
- } // now |cur_val| points to the glue specification
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(halfword(prg.curVal))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- if int32(s) >= skipCode {
- *(*prg.mem[prg.curVal].hh()).rh() = uint16(int32(*(*prg.mem[prg.curVal].hh()).rh()) - 1)
- if int32(s) > skipCode {
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(muGlue)
- }
- }
- }
- func (prg *prg) appendKern() {
- var (
- s quarterword // |subtype| of the kern node
- )
- s = byte(prg.curChr)
- prg.scanDimen(int32(s) == muGlue, false, false)
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newKern(prg.curVal)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b1() = s
- }
- func (prg *prg) offSave() {
- var (
- p halfword // inserted token
- )
- if int32(prg.curGroup) == bottomLevel {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Extra " */ 777)
- }
- prg.printCmdChr(prg.curCmd, prg.curChr)
- // \xref[Extra x]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "Things are pretty mixed up, but I think the worst is over." */ 1043
- }
- prg.error1()
- } else {
- prg.backInput()
- p = prg.getAvail()
- *(*prg.mem[30000-3].hh()).rh() = p
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing " */ 625)
- }
- // Prepare to insert a token that matches |cur_group|, and print what it is
- switch prg.curGroup {
- case semiSimpleGroup:
- *(*prg.mem[p].hh()).lh() = uint16(07777 + frozenEndGroup)
- prg.printEsc(strNumber( /* "endgroup" */ 516))
- // \xref[Missing \\endgroup inserted]
- case mathShiftGroup:
- *(*prg.mem[p].hh()).lh() = uint16(mathShiftToken + '$')
- prg.printChar(asciiCode('$'))
- // \xref[Missing \$ inserted]
- case mathLeftGroup:
- *(*prg.mem[p].hh()).lh() = uint16(07777 + frozenRight)
- *(*prg.mem[p].hh()).rh() = prg.getAvail()
- p = *(*prg.mem[p].hh()).rh()
- *(*prg.mem[p].hh()).lh() = uint16(otherToken + '.')
- prg.printEsc(strNumber( /* "right." */ 1042))
- // \xref[Missing \\right\hbox[.] inserted]
- // \xref[null delimiter]
- default:
- *(*prg.mem[p].hh()).lh() = uint16(rightBraceToken + '}')
- prg.printChar(asciiCode('}'))
- // \xref[Missing \] inserted]
- }
- prg.print( /* " inserted" */ 626)
- prg.beginTokenList(*(*prg.mem[30000-3].hh()).rh(), quarterword(inserted))
- {
- prg.helpPtr = 5
- prg.helpLine[4] = /* "I've inserted something that you may have forgotten." */ 1037
- prg.helpLine[3] = /* "(See the <inserted text> above.)" */ 1038
- prg.helpLine[2] = /* "With luck, this will get me unwedged. But if you" */ 1039
- prg.helpLine[1] = /* "really didn't forget anything, try typing `2' now; then" */ 1040
- prg.helpLine[0] = /* "my insertion and my current dilemma will both disappear." */ 1041
- }
- prg.error1()
- }
- }
- func (prg *prg) extraRightBrace() {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Extra ], or forgotten " */ 1048)
- }
- // \xref[Extra \], or forgotten x]
- switch prg.curGroup {
- case semiSimpleGroup:
- prg.printEsc(strNumber( /* "endgroup" */ 516))
- case mathShiftGroup:
- prg.printChar(asciiCode('$'))
- case mathLeftGroup:
- prg.printEsc(strNumber( /* "right" */ 877))
- }
- {
- prg.helpPtr = 5
- prg.helpLine[4] = /* "I've deleted a group-closing symbol because it seems to be" */ 1049
- prg.helpLine[3] = /* "spurious, as in `$x]$'. But perhaps the ] is legitimate and" */ 1050
- prg.helpLine[2] = /* "you forgot something else, as in `\\hbox[$x]'. In such cases" */ 1051
- prg.helpLine[1] = /* "the way to recover is to insert both the forgotten and the" */ 1052
- prg.helpLine[0] = /* "deleted material, e.g., by typing `I$]'." */ 1053
- }
- prg.error1()
- prg.alignState = prg.alignState + 1
- } // \2
- func (prg *prg) normalParagraph() {
- if *prg.eqtb[intBase+loosenessCode-1].int() != 0 {
- prg.eqWordDefine(halfword(intBase+loosenessCode), 0)
- }
- if *prg.eqtb[dimenBase+hangIndentCode-1].int() != 0 {
- prg.eqWordDefine(halfword(dimenBase+hangIndentCode), 0)
- }
- if *prg.eqtb[intBase+hangAfterCode-1].int() != 1 {
- prg.eqWordDefine(halfword(intBase+hangAfterCode), 1)
- }
- if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) != 0 {
- prg.eqDefine(halfword(parShapeLoc), quarterword(shapeRef), halfword(0))
- }
- }
- func (prg *prg) boxEnd(boxContext int32) {
- var (
- p halfword // |ord_noad| for new box in math mode
- )
- if boxContext < 010000000000 {
- if int32(prg.curBox) != 0 {
- *prg.mem[int32(prg.curBox)+4].int() = boxContext
- if abs(int32(prg.curList.modeField)) == vmode {
- prg.appendToVlist(prg.curBox)
- if int32(prg.adjustTail) != 0 {
- if 30000-5 != int32(prg.adjustTail) {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[30000-5].hh()).rh()
- prg.curList.tailField = prg.adjustTail
- }
- prg.adjustTail = 0
- }
- if int32(prg.curList.modeField) > 0 {
- prg.buildPage()
- }
- } else {
- if abs(int32(prg.curList.modeField)) == hmode {
- *(*prg.curList.auxField.hh()).lh() = 1000
- } else {
- p = prg.newNoad()
- *(*prg.mem[int32(p)+1].hh()).rh() = uint16(subBox)
- *(*prg.mem[int32(p)+1].hh()).lh() = prg.curBox
- prg.curBox = p
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.curBox
- prg.curList.tailField = prg.curBox
- }
- }
- } else if boxContext < 010000000000+512 {
- if boxContext < 010000000000+256 {
- prg.eqDefine(halfword(boxBase-010000000000+boxContext), quarterword(boxRef), prg.curBox)
- } else {
- prg.geqDefine(halfword(boxBase-010000000000-256+boxContext), quarterword(boxRef), prg.curBox)
- }
- } else if int32(prg.curBox) != 0 {
- if boxContext > 010000000000+512 {
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
- break
- }
- }
- if int32(prg.curCmd) == hskip && abs(int32(prg.curList.modeField)) != vmode || int32(prg.curCmd) == vskip && abs(int32(prg.curList.modeField)) == vmode {
- prg.appendGlue()
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(boxContext - (010000000000 + 513 - aLeaders))
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = prg.curBox
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Leaders not followed by proper glue" */ 1066)
- }
- // \xref[Leaders not followed by...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "You should say `\\leaders <box or rule><hskip or vskip>'." */ 1067
- prg.helpLine[1] = /* "I found the <box or rule>, but there's no suitable" */ 1068
- prg.helpLine[0] = /* "<hskip or vskip>, so I'm ignoring these leaders." */ 1069
- }
- prg.backError()
- prg.flushNodeList(prg.curBox)
- }
- } else {
- prg.shipOut(prg.curBox)
- }
- }
- }
- func (prg *prg) beginBox(boxContext int32) {
- var (
- p, q halfword // run through the current list
- m quarterword // the length of a replacement list
- k halfword // 0 or |vmode| or |hmode|
- n eightBits // a box number
- )
- switch prg.curChr {
- case boxCode:
- prg.scanEightBitInt()
- prg.curBox = *(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()
- *(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh() = 0 // the box becomes void, at the same level
- case copyCode:
- prg.scanEightBitInt()
- prg.curBox = prg.copyNodeList(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh())
- case lastBoxCode:
- // If the current list ends with a box node, delete it from the list and make |cur_box| point to it; otherwise set |cur_box:=null|
- prg.curBox = 0
- if abs(int32(prg.curList.modeField)) == mmode {
- prg.youCant()
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "Sorry; this \\lastbox will be void." */ 1070
- }
- prg.error1()
- } else if int32(prg.curList.modeField) == vmode && int32(prg.curList.headField) == int32(prg.curList.tailField) {
- prg.youCant()
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Sorry...I usually can't take things from the current page." */ 1071
- prg.helpLine[0] = /* "This \\lastbox will therefore be void." */ 1072
- }
- prg.error1()
- } else {
- if !(int32(prg.curList.tailField) >= int32(prg.hiMemMin)) {
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == hlistNode || int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == vlistNode {
- q = prg.curList.headField
- for {
- p = q
- if !(int32(q) >= int32(prg.hiMemMin)) {
- if int32(*(*prg.mem[q].hh()).b0()) == discNode {
- for ii := int32(1); ii <= int32(*(*prg.mem[q].hh()).b1()); ii++ {
- m = quarterword(ii)
- _ = m
- p = *(*prg.mem[p].hh()).rh()
- }
- if int32(p) == int32(prg.curList.tailField) {
- goto done
- }
- }
- }
- q = *(*prg.mem[p].hh()).rh()
- if int32(q) == int32(prg.curList.tailField) {
- break
- }
- }
- prg.curBox = prg.curList.tailField
- *prg.mem[int32(prg.curBox)+4].int() = 0
- prg.curList.tailField = p
- *(*prg.mem[p].hh()).rh() = 0
- done:
- }
- }
- }
- case vsplitCode:
- // Split off part of a vertical box, make |cur_box| point to it
- prg.scanEightBitInt()
- n = byte(prg.curVal)
- if !prg.scanKeyword(strNumber(842)) {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing `to' inserted" */ 1073)
- }
- // \xref[Missing `to' inserted]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I'm working on `\\vsplit<box number> to <dimen>';" */ 1074
- prg.helpLine[0] = /* "will look for the <dimen> next." */ 1075
- }
- prg.error1()
- }
- prg.scanDimen(false, false, false)
- prg.curBox = prg.vsplit(n, prg.curVal)
- default:
- k = uint16(int32(prg.curChr) - vtopCode)
- *prg.saveStack[int32(prg.savePtr)+0].int() = boxContext
- if int32(k) == hmode {
- if boxContext < 010000000000 && abs(int32(prg.curList.modeField)) == vmode {
- prg.scanSpec(groupCode(adjustedHboxGroup), true)
- } else {
- prg.scanSpec(groupCode(hboxGroup), true)
- }
- } else {
- if int32(k) == vmode {
- prg.scanSpec(groupCode(vboxGroup), true)
- } else {
- prg.scanSpec(groupCode(vtopGroup), true)
- k = uint16(vmode)
- }
- prg.normalParagraph()
- }
- prg.pushNest()
- prg.curList.modeField = int16(-int32(k))
- if int32(k) == vmode {
- *prg.curList.auxField.int() = -65536000
- if int32(*(*prg.eqtb[everyVboxLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyVboxLoc-1].hh()).rh(), quarterword(everyVboxText))
- }
- } else {
- *(*prg.curList.auxField.hh()).lh() = 1000
- if int32(*(*prg.eqtb[everyHboxLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyHboxLoc-1].hh()).rh(), quarterword(everyHboxText))
- }
- }
- goto exit
- }
- prg.boxEnd(boxContext) // in simple cases, we use the box immediately
- // in simple cases, we use the box immediately
- exit:
- }
- func (prg *prg) scanBox(boxContext int32) {
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
- break
- }
- }
- if int32(prg.curCmd) == makeBox {
- prg.beginBox(boxContext)
- } else if boxContext >= 010000000000+513 && (int32(prg.curCmd) == hrule || int32(prg.curCmd) == vrule) {
- prg.curBox = prg.scanRuleSpec()
- prg.boxEnd(boxContext)
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "A <box> was supposed to be here" */ 1076)
- }
- // \xref[A <box> was supposed to...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "I was expecting to see \\hbox or \\vbox or \\copy or \\box or" */ 1077
- prg.helpLine[1] = /* "something like that. So you might find something missing in" */ 1078
- prg.helpLine[0] = /* "your output. But keep trying; you can fix this later." */ 1079
- }
- prg.backError()
- }
- }
- func (prg *prg) package1(c smallNumber) {
- var (
- h scaled // height of box
- p halfword // first node in a box
- d scaled // max depth
- )
- d = *prg.eqtb[dimenBase+boxMaxDepthCode-1].int()
- prg.unsave()
- prg.savePtr = uint16(int32(prg.savePtr) - 3)
- if int32(prg.curList.modeField) == -hmode {
- prg.curBox = prg.hpack(*(*prg.mem[prg.curList.headField].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+2].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+1].int()))
- } else {
- prg.curBox = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+2].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+1].int()), d)
- if int32(c) == vtopCode {
- h = 0
- p = *(*prg.mem[int32(prg.curBox)+listOffset].hh()).rh()
- if int32(p) != 0 {
- if int32(*(*prg.mem[p].hh()).b0()) <= ruleNode {
- h = *prg.mem[int32(p)+heightOffset].int()
- }
- }
- *prg.mem[int32(prg.curBox)+depthOffset].int() = *prg.mem[int32(prg.curBox)+depthOffset].int() - h + *prg.mem[int32(prg.curBox)+heightOffset].int()
- *prg.mem[int32(prg.curBox)+heightOffset].int() = h
- }
- }
- prg.popNest()
- prg.boxEnd(*prg.saveStack[int32(prg.savePtr)+0].int())
- }
- func (prg *prg) normMin(h int32) (r smallNumber) {
- if h <= 0 {
- r = 1
- } else if h >= 63 {
- r = 63
- } else {
- r = byte(h)
- }
- return r
- }
- func (prg *prg) newGraf(indented bool) {
- prg.curList.pgField = 0
- if int32(prg.curList.modeField) == vmode || int32(prg.curList.headField) != int32(prg.curList.tailField) {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(smallNumber(parSkipCode))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- prg.pushNest()
- prg.curList.modeField = int16(hmode)
- *(*prg.curList.auxField.hh()).lh() = 1000
- if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
- prg.curLang = 0
- } else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
- prg.curLang = 0
- } else {
- prg.curLang = byte(*prg.eqtb[intBase+languageCode-1].int())
- }
- *(*prg.curList.auxField.hh()).rh() = uint16(prg.curLang)
- prg.curList.pgField = (int32(prg.normMin(*prg.eqtb[intBase+leftHyphenMinCode-1].int()))*0100+int32(prg.normMin(*prg.eqtb[intBase+rightHyphenMinCode-1].int())))*0200000 + int32(prg.curLang)
- if indented {
- prg.curList.tailField = prg.newNullBox()
- *(*prg.mem[prg.curList.headField].hh()).rh() = prg.curList.tailField
- *prg.mem[int32(prg.curList.tailField)+widthOffset].int() = *prg.eqtb[dimenBase+parIndentCode-1].int()
- }
- if int32(*(*prg.eqtb[everyParLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyParLoc-1].hh()).rh(), quarterword(everyParText))
- }
- if int32(prg.nestPtr) == 1 {
- prg.buildPage()
- } // put |par_skip| glue on current page
- }
- func (prg *prg) indentInHmode() {
- var (
- p, q halfword
- )
- if int32(prg.curChr) > 0 {
- p = prg.newNullBox()
- *prg.mem[int32(p)+widthOffset].int() = *prg.eqtb[dimenBase+parIndentCode-1].int()
- if abs(int32(prg.curList.modeField)) == hmode {
- *(*prg.curList.auxField.hh()).lh() = 1000
- } else {
- q = prg.newNoad()
- *(*prg.mem[int32(q)+1].hh()).rh() = uint16(subBox)
- *(*prg.mem[int32(q)+1].hh()).lh() = p
- p = q
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- }
- }
- func (prg *prg) headForVmode() {
- if int32(prg.curList.modeField) < 0 {
- if int32(prg.curCmd) != hrule {
- prg.offSave()
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "You can't use `" */ 685)
- }
- prg.printEsc(strNumber( /* "hrule" */ 521))
- prg.print( /* "' here except with leaders" */ 1082)
- // \xref[You can't use \\hrule...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "To put a horizontal rule in an hbox or an alignment," */ 1083
- prg.helpLine[0] = /* "you should use \\leaders or \\hrulefill (see The TeXbook)." */ 1084
- }
- prg.error1()
- }
- } else {
- prg.backInput()
- prg.curTok = prg.parToken
- prg.backInput()
- prg.curInput.indexField = byte(inserted)
- }
- }
- func (prg *prg) endGraf() {
- if int32(prg.curList.modeField) == hmode {
- if int32(prg.curList.headField) == int32(prg.curList.tailField) {
- prg.popNest()
- } else {
- prg.lineBreak(*prg.eqtb[intBase+widowPenaltyCode-1].int())
- }
- prg.normalParagraph()
- prg.errorCount = 0
- }
- }
- func (prg *prg) beginInsertOrAdjust() {
- if int32(prg.curCmd) == vadjust {
- prg.curVal = 255
- } else {
- prg.scanEightBitInt()
- if prg.curVal == 255 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "You can't " */ 1085)
- }
- prg.printEsc(strNumber( /* "insert" */ 330))
- prg.printInt(255)
- // \xref[You can't \\insert255]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm changing to \\insert0; box 255 is special." */ 1086
- }
- prg.error1()
- prg.curVal = 0
- }
- }
- *prg.saveStack[int32(prg.savePtr)+0].int() = prg.curVal
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- prg.newSaveLevel(groupCode(insertGroup))
- prg.scanLeftBrace()
- prg.normalParagraph()
- prg.pushNest()
- prg.curList.modeField = int16(-vmode)
- *prg.curList.auxField.int() = -65536000
- }
- func (prg *prg) makeMark() {
- var (
- p halfword // new node
- )
- p = prg.scanToks(false, true)
- p = prg.getNode(smallNodeSize)
- *(*prg.mem[p].hh()).b0() = byte(markNode)
- *(*prg.mem[p].hh()).b1() = 0 // the |subtype| is not used
- *prg.mem[int32(p)+1].int() = int32(prg.defRef)
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- prg.curList.tailField = p
- }
- func (prg *prg) appendPenalty() {
- prg.scanInt()
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(prg.curVal)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- if int32(prg.curList.modeField) == vmode {
- prg.buildPage()
- }
- }
- func (prg *prg) deleteLast() {
- var (
- p, q halfword // run through the current list
- m quarterword // the length of a replacement list
- )
- if int32(prg.curList.modeField) == vmode && int32(prg.curList.tailField) == int32(prg.curList.headField) {
- if int32(prg.curChr) != glueNode || int32(prg.lastGlue) != 65535 {
- prg.youCant()
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Sorry...I usually can't take things from the current page." */ 1071
- prg.helpLine[0] = /* "Try `I\\vskip-\\lastskip' instead." */ 1087
- }
- if int32(prg.curChr) == kernNode {
- prg.helpLine[0] = uint16(1088)
- } else if int32(prg.curChr) != glueNode {
- prg.helpLine[0] = uint16(1089)
- }
- prg.error1()
- }
- } else {
- if !(int32(prg.curList.tailField) >= int32(prg.hiMemMin)) {
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == int32(prg.curChr) {
- q = prg.curList.headField
- for {
- p = q
- if !(int32(q) >= int32(prg.hiMemMin)) {
- if int32(*(*prg.mem[q].hh()).b0()) == discNode {
- for ii := int32(1); ii <= int32(*(*prg.mem[q].hh()).b1()); ii++ {
- m = quarterword(ii)
- _ = m
- p = *(*prg.mem[p].hh()).rh()
- }
- if int32(p) == int32(prg.curList.tailField) {
- goto exit
- }
- }
- }
- q = *(*prg.mem[p].hh()).rh()
- if int32(q) == int32(prg.curList.tailField) {
- break
- }
- }
- *(*prg.mem[p].hh()).rh() = 0
- prg.flushNodeList(prg.curList.tailField)
- prg.curList.tailField = p
- }
- }
- }
- exit:
- }
- func (prg *prg) unpackage() {
- var (
- p halfword // the box
- c/* boxCode..copyCode */ byte // should we copy?
- )
- c = byte(prg.curChr)
- prg.scanEightBitInt()
- p = *(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()
- if int32(p) == 0 {
- goto exit
- }
- if abs(int32(prg.curList.modeField)) == mmode || abs(int32(prg.curList.modeField)) == vmode && int32(*(*prg.mem[p].hh()).b0()) != vlistNode || abs(int32(prg.curList.modeField)) == hmode && int32(*(*prg.mem[p].hh()).b0()) != hlistNode {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Incompatible list can't be unboxed" */ 1097)
- }
- // \xref[Incompatible list...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "Sorry, Pandora. (You sneaky devil.)" */ 1098
- prg.helpLine[1] = /* "I refuse to unbox an \\hbox in vertical mode or vice versa." */ 1099
- prg.helpLine[0] = /* "And I can't open any boxes in math mode." */ 1100
- }
- prg.error1()
- goto exit
- }
- if int32(c) == copyCode {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.copyNodeList(*(*prg.mem[int32(p)+listOffset].hh()).rh())
- } else {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[int32(p)+listOffset].hh()).rh()
- *(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh() = 0
- prg.freeNode(p, halfword(boxNodeSize))
- }
- for int32(*(*prg.mem[prg.curList.tailField].hh()).rh()) != 0 {
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- exit:
- }
- func (prg *prg) appendItalicCorrection() {
- var (
- p halfword // |char_node| at the tail of the current list
- f internalFontNumber // the font in the |char_node|
- )
- if int32(prg.curList.tailField) != int32(prg.curList.headField) {
- if int32(prg.curList.tailField) >= int32(prg.hiMemMin) {
- p = prg.curList.tailField
- } else if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == ligatureNode {
- p = uint16(int32(prg.curList.tailField) + 1)
- } else {
- goto exit
- }
- f = *(*prg.mem[p].hh()).b0()
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newKern(*prg.fontInfo[prg.italicBase[f]+(int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()).b2)-minQuarterword)/4].int())
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(explicit)
- }
- exit:
- }
- func (prg *prg) appendDiscretionary() {
- var (
- c int32 // hyphen character
- )
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newDisc()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- if int32(prg.curChr) == 1 {
- c = prg.hyphenChar[*(*prg.eqtb[curFontLoc-1].hh()).rh()]
- if c >= 0 {
- if c < 256 {
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = prg.newCharacter(internalFontNumber(*(*prg.eqtb[curFontLoc-1].hh()).rh()), eightBits(c))
- }
- }
- } else {
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- *prg.saveStack[int32(prg.savePtr)+-1].int() = 0
- prg.newSaveLevel(groupCode(discGroup))
- prg.scanLeftBrace()
- prg.pushNest()
- prg.curList.modeField = int16(-hmode)
- *(*prg.curList.auxField.hh()).lh() = 1000
- }
- }
- func (prg *prg) buildDiscretionary() {
- var (
- p, q halfword // for link manipulation
- n int32 // length of discretionary list
- )
- prg.unsave()
- // Prune the current list, if necessary, until it contains only |char_node|, |kern_node|, |hlist_node|, |vlist_node|, |rule_node|, and |ligature_node| items; set |n| to the length of the list, and set |q| to the list's tail
- q = prg.curList.headField
- p = *(*prg.mem[q].hh()).rh()
- n = 0
- for int32(p) != 0 {
- if !(int32(p) >= int32(prg.hiMemMin)) {
- if int32(*(*prg.mem[p].hh()).b0()) > ruleNode {
- if int32(*(*prg.mem[p].hh()).b0()) != kernNode {
- if int32(*(*prg.mem[p].hh()).b0()) != ligatureNode {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Improper discretionary list" */ 1107)
- }
- // \xref[Improper discretionary list]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "Discretionary lists must contain only boxes and kerns." */ 1108
- }
- prg.error1()
- prg.beginDiagnostic()
- prg.printNl(strNumber( /* "The following discretionary sublist has been deleted:" */ 1109))
- // \xref[The following...deleted]
- prg.showBox(p)
- prg.endDiagnostic(true)
- prg.flushNodeList(p)
- *(*prg.mem[q].hh()).rh() = 0
- goto done
- }
- }
- }
- }
- q = p
- p = *(*prg.mem[q].hh()).rh()
- n = n + 1
- }
- done:
- ;
- p = *(*prg.mem[prg.curList.headField].hh()).rh()
- prg.popNest()
- switch *prg.saveStack[int32(prg.savePtr)+-1].int() {
- case 0:
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = p
- case 1:
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = p
- case 2:
- // Attach list |p| to the current list, and record its length; then finish up and |return|
- if n > 0 && abs(int32(prg.curList.modeField)) == mmode {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Illegal math " */ 1101)
- }
- prg.printEsc(strNumber( /* "discretionary" */ 349))
- // \xref[Illegal math \\disc...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Sorry: The third part of a discretionary break must be" */ 1102
- prg.helpLine[0] = /* "empty, in math formulas. I had to delete your third part." */ 1103
- }
- prg.flushNodeList(p)
- n = 0
- prg.error1()
- } else {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- }
- if n <= maxQuarterword {
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(n)
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Discretionary list is too long" */ 1104)
- }
- // \xref[Discretionary list is too long]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Wow---I never thought anybody would tweak me here." */ 1105
- prg.helpLine[0] = /* "You can't seriously need such a huge discretionary list?" */ 1106
- }
- prg.error1()
- }
- if n > 0 {
- prg.curList.tailField = q
- }
- prg.savePtr = uint16(int32(prg.savePtr) - 1)
- goto exit
- } // there are no other cases
- *prg.saveStack[int32(prg.savePtr)+-1].int() = *prg.saveStack[int32(prg.savePtr)+-1].int() + 1
- prg.newSaveLevel(groupCode(discGroup))
- prg.scanLeftBrace()
- prg.pushNest()
- prg.curList.modeField = int16(-hmode)
- *(*prg.curList.auxField.hh()).lh() = 1000
- exit:
- }
- func (prg *prg) makeAccent() {
- var (
- s, t float64 // amount of slant
- p, q, r1 halfword // character, box, and kern nodes
- f internalFontNumber // relevant font
- a, h, x, w, delta scaled // heights and widths, as explained above
- i fourQuarters // character information
- )
- prg.scanCharNum()
- f = byte(*(*prg.eqtb[curFontLoc-1].hh()).rh())
- p = prg.newCharacter(f, eightBits(prg.curVal))
- if int32(p) != 0 {
- x = *prg.fontInfo[xHeightCode+prg.paramBase[f]].int()
- s = float64(*prg.fontInfo[slantCode+prg.paramBase[f]].int()) / 65536.0
- // \xref[real division]
- a = *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()).b0)].int()
- prg.doAssignments()
- // Create a character node |q| for the next character, but set |q:=null| if problems arise
- q = 0
- f = byte(*(*prg.eqtb[curFontLoc-1].hh()).rh())
- if int32(prg.curCmd) == letter || int32(prg.curCmd) == otherChar || int32(prg.curCmd) == charGiven {
- q = prg.newCharacter(f, eightBits(prg.curChr))
- } else if int32(prg.curCmd) == charNum {
- prg.scanCharNum()
- q = prg.newCharacter(f, eightBits(prg.curVal))
- } else {
- prg.backInput()
- }
- if int32(q) != 0 {
- t = float64(*prg.fontInfo[slantCode+prg.paramBase[f]].int()) / 65536.0
- // \xref[real division]
- i = *prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[q].hh()).b1())].qqqq()
- w = *prg.fontInfo[prg.widthBase[f]+int32(i.b0)].int()
- h = *prg.fontInfo[prg.heightBase[f]+(int32(i.b1)-minQuarterword)/16].int()
- if h != x {
- p = prg.hpack(p, scaled(0), smallNumber(additional))
- *prg.mem[int32(p)+4].int() = x - h
- }
- delta = round(float64(w-a)/2.0 + float64(h)*t - float64(x)*s)
- // \xref[real multiplication]
- // \xref[real addition]
- r1 = prg.newKern(delta)
- *(*prg.mem[r1].hh()).b1() = byte(accKern)
- *(*prg.mem[prg.curList.tailField].hh()).rh() = r1
- *(*prg.mem[r1].hh()).rh() = p
- prg.curList.tailField = prg.newKern(-a - delta)
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(accKern)
- *(*prg.mem[p].hh()).rh() = prg.curList.tailField
- p = q
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- prg.curList.tailField = p
- *(*prg.curList.auxField.hh()).lh() = 1000
- }
- }
- func (prg *prg) alignError() {
- if abs(prg.alignState) > 2 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Misplaced " */ 1114)
- }
- prg.printCmdChr(prg.curCmd, prg.curChr)
- // \xref[Misplaced \&]
- // \xref[Misplaced \\span]
- // \xref[Misplaced \\cr]
- if int32(prg.curTok) == tabToken+'&' {
- {
- prg.helpPtr = 6
- prg.helpLine[5] = /* "I can't figure out why you would want to use a tab mark" */ 1115
- prg.helpLine[4] = /* "here. If you just want an ampersand, the remedy is" */ 1116
- prg.helpLine[3] = /* "simple: Just type `I\\&' now. But if some right brace" */ 1117
- prg.helpLine[2] = /* "up above has ended a previous alignment prematurely," */ 1118
- prg.helpLine[1] = /* "you're probably due for more error messages, and you" */ 1119
- prg.helpLine[0] = /* "might try typing `S' now just to see what is salvageable." */ 1120
- }
- } else {
- {
- prg.helpPtr = 5
- prg.helpLine[4] = /* "I can't figure out why you would want to use a tab mark" */ 1115
- prg.helpLine[3] = /* "or \\cr or \\span just now. If something like a right brace" */ 1121
- prg.helpLine[2] = /* "up above has ended a previous alignment prematurely," */ 1118
- prg.helpLine[1] = /* "you're probably due for more error messages, and you" */ 1119
- prg.helpLine[0] = /* "might try typing `S' now just to see what is salvageable." */ 1120
- }
- }
- prg.error1()
- } else {
- prg.backInput()
- if prg.alignState < 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing [ inserted" */ 657)
- }
- // \xref[Missing \[ inserted]
- prg.alignState = prg.alignState + 1
- prg.curTok = uint16(leftBraceToken + '{')
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing ] inserted" */ 1110)
- }
- // \xref[Missing \] inserted]
- prg.alignState = prg.alignState - 1
- prg.curTok = uint16(rightBraceToken + '}')
- }
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "I've put in what seems to be necessary to fix" */ 1111
- prg.helpLine[1] = /* "the current column of the current alignment." */ 1112
- prg.helpLine[0] = /* "Try to go on, since this might almost work." */ 1113
- }
- prg.insError()
- }
- }
- func (prg *prg) noAlignError() {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Misplaced " */ 1114)
- }
- prg.printEsc(strNumber( /* "noalign" */ 527))
- // \xref[Misplaced \\noalign]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I expect to see \\noalign only after the \\cr of" */ 1122
- prg.helpLine[0] = /* "an alignment. Proceed, and I'll ignore this case." */ 1123
- }
- prg.error1()
- }
- func (prg *prg) omitError() {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Misplaced " */ 1114)
- }
- prg.printEsc(strNumber( /* "omit" */ 530))
- // \xref[Misplaced \\omit]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I expect to see \\omit only after tab marks or the \\cr of" */ 1124
- prg.helpLine[0] = /* "an alignment. Proceed, and I'll ignore this case." */ 1123
- }
- prg.error1()
- }
- func (prg *prg) doEndv() {
- prg.basePtr = prg.inputPtr
- prg.inputStack[prg.basePtr] = prg.curInput
- for int32(prg.inputStack[prg.basePtr].indexField) != vTemplate && int32(prg.inputStack[prg.basePtr].locField) == 0 && int32(prg.inputStack[prg.basePtr].stateField) == tokenList {
- prg.basePtr = byte(int32(prg.basePtr) - 1)
- }
- if int32(prg.inputStack[prg.basePtr].indexField) != vTemplate || int32(prg.inputStack[prg.basePtr].locField) != 0 || int32(prg.inputStack[prg.basePtr].stateField) != tokenList {
- prg.fatalError(strNumber( /* "(interwoven alignment preambles are not allowed)" */ 595))
- }
- // \xref[interwoven alignment preambles...]
- if int32(prg.curGroup) == alignGroup {
- prg.endGraf()
- if prg.finCol() {
- prg.finRow()
- }
- } else {
- prg.offSave()
- }
- }
- func (prg *prg) csError() {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Extra " */ 777)
- }
- prg.printEsc(strNumber( /* "endcsname" */ 505))
- // \xref[Extra \\endcsname]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm ignoring this, since I wasn't doing a \\csname." */ 1126
- }
- prg.error1()
- }
- func (prg *prg) pushMath(c groupCode) {
- prg.pushNest()
- prg.curList.modeField = int16(-mmode)
- *prg.curList.auxField.int() = 0
- prg.newSaveLevel(c)
- }
- func (prg *prg) initMath() {
- var (
- w scaled // new or partial |pre_display_size|
- l scaled // new |display_width|
- s scaled // new |display_indent|
- p halfword // current node when calculating |pre_display_size|
- q halfword // glue specification when calculating |pre_display_size|
- f internalFontNumber // font in current |char_node|
- n int32 // scope of paragraph shape specification
- v scaled // |w| plus possible glue amount
- d scaled // increment to |v|
- )
- prg.getToken() // |get_x_token| would fail on \.[\\ifmmode]\thinspace!
- if int32(prg.curCmd) == mathShift && int32(prg.curList.modeField) > 0 {
- if int32(prg.curList.headField) == int32(prg.curList.tailField) {
- prg.popNest()
- w = -07777777777
- } else {
- prg.lineBreak(*prg.eqtb[intBase+displayWidowPenaltyCode-1].int())
- // Calculate the natural width, |w|, by which the characters of the final line extend to the right of the reference point, plus two ems; or set |w:=max_dimen| if the non-blank information on that line is affected by stretching or shrinking
- v = *prg.mem[int32(prg.justBox)+4].int() + 2**prg.fontInfo[quadCode+prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()]].int()
- w = -07777777777
- p = *(*prg.mem[int32(prg.justBox)+listOffset].hh()).rh()
- for int32(p) != 0 {
- // Let |d| be the natural width of node |p|; if the node is “visible,” |goto found|; if the node is glue that stretches or shrinks, set |v:=max_dimen|
- reswitch:
- if int32(p) >= int32(prg.hiMemMin) {
- f = *(*prg.mem[p].hh()).b0()
- d = *prg.fontInfo[prg.widthBase[f]+int32((*prg.fontInfo[prg.charBase[f]+int32(*(*prg.mem[p].hh()).b1())].qqqq()).b0)].int()
- goto found
- }
- switch *(*prg.mem[p].hh()).b0() {
- case hlistNode, vlistNode, ruleNode:
- d = *prg.mem[int32(p)+widthOffset].int()
- goto found
- case ligatureNode:
- // Make node |p| look like a |char_node|...
- prg.mem[30000-12] = prg.mem[int32(p)+1]
- *(*prg.mem[30000-12].hh()).rh() = *(*prg.mem[p].hh()).rh()
- p = uint16(30000 - 12)
- goto reswitch
- case kernNode, mathNode:
- d = *prg.mem[int32(p)+widthOffset].int()
- case glueNode:
- // Let |d| be the natural width of this glue; if stretching or shrinking, set |v:=max_dimen|; |goto found| in the case of leaders
- q = *(*prg.mem[int32(p)+1].hh()).lh()
- d = *prg.mem[int32(q)+widthOffset].int()
- if int32(*(*prg.mem[int32(prg.justBox)+listOffset].hh()).b0()) == stretching {
- if int32(*(*prg.mem[int32(prg.justBox)+listOffset].hh()).b1()) == int32(*(*prg.mem[q].hh()).b0()) && *prg.mem[int32(q)+2].int() != 0 {
- v = 07777777777
- }
- } else if int32(*(*prg.mem[int32(prg.justBox)+listOffset].hh()).b0()) == shrinking {
- if int32(*(*prg.mem[int32(prg.justBox)+listOffset].hh()).b1()) == int32(*(*prg.mem[q].hh()).b1()) && *prg.mem[int32(q)+3].int() != 0 {
- v = 07777777777
- }
- }
- if int32(*(*prg.mem[p].hh()).b1()) >= aLeaders {
- goto found
- }
- case whatsitNode:
- // Let |d| be the width of the whatsit |p|
- d = 0
- default:
- d = 0
- }
- if v < 07777777777 {
- v = v + d
- }
- goto notFound
- found:
- if v < 07777777777 {
- v = v + d
- w = v
- } else {
- w = 07777777777
- goto done
- }
- notFound:
- p = *(*prg.mem[p].hh()).rh()
- }
- done:
- }
- // now we are in vertical mode, working on the list that will contain the display
- // Calculate the length, |l|, and the shift amount, |s|, of the display lines
- if int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) == 0 {
- if *prg.eqtb[dimenBase+hangIndentCode-1].int() != 0 && (*prg.eqtb[intBase+hangAfterCode-1].int() >= 0 && prg.curList.pgField+2 > *prg.eqtb[intBase+hangAfterCode-1].int() || prg.curList.pgField+1 < -*prg.eqtb[intBase+hangAfterCode-1].int()) {
- l = *prg.eqtb[dimenBase+hsizeCode-1].int() - abs(*prg.eqtb[dimenBase+hangIndentCode-1].int())
- if *prg.eqtb[dimenBase+hangIndentCode-1].int() > 0 {
- s = *prg.eqtb[dimenBase+hangIndentCode-1].int()
- } else {
- s = 0
- }
- } else {
- l = *prg.eqtb[dimenBase+hsizeCode-1].int()
- s = 0
- }
- } else {
- n = int32(*(*prg.mem[*(*prg.eqtb[parShapeLoc-1].hh()).rh()].hh()).lh())
- if prg.curList.pgField+2 >= n {
- p = uint16(int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) + 2*n)
- } else {
- p = uint16(int32(*(*prg.eqtb[parShapeLoc-1].hh()).rh()) + 2*(prg.curList.pgField+2))
- }
- s = *prg.mem[int32(p)-1].int()
- l = *prg.mem[p].int()
- }
- prg.pushMath(groupCode(mathShiftGroup))
- prg.curList.modeField = int16(mmode)
- prg.eqWordDefine(halfword(intBase+curFamCode), -1)
- prg.eqWordDefine(halfword(dimenBase+preDisplaySizeCode), w)
- prg.eqWordDefine(halfword(dimenBase+displayWidthCode), l)
- prg.eqWordDefine(halfword(dimenBase+displayIndentCode), s)
- if int32(*(*prg.eqtb[everyDisplayLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyDisplayLoc-1].hh()).rh(), quarterword(everyDisplayText))
- }
- if int32(prg.nestPtr) == 1 {
- prg.buildPage()
- }
- } else {
- prg.backInput()
- // Go into ordinary math mode
- {
- prg.pushMath(groupCode(mathShiftGroup))
- prg.eqWordDefine(halfword(intBase+curFamCode), -1)
- if int32(*(*prg.eqtb[everyMathLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyMathLoc-1].hh()).rh(), quarterword(everyMathText))
- }
- }
- }
- }
- func (prg *prg) startEqNo() {
- *prg.saveStack[int32(prg.savePtr)+0].int() = int32(prg.curChr)
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- // Go into ordinary math mode
- {
- prg.pushMath(groupCode(mathShiftGroup))
- prg.eqWordDefine(halfword(intBase+curFamCode), -1)
- if int32(*(*prg.eqtb[everyMathLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyMathLoc-1].hh()).rh(), quarterword(everyMathText))
- }
- }
- }
- func (prg *prg) scanMath(p halfword) {
- var (
- c int32 // math character code
- )
- restart:
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
- break
- }
- }
- reswitch:
- switch prg.curCmd {
- case letter, otherChar, charGiven:
- c = int32(*(*prg.eqtb[mathCodeBase+int32(prg.curChr)-1].hh()).rh()) - 0
- if c == 0100000 {
- {
- prg.curCs = uint16(int32(prg.curChr) + activeBase)
- prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
- prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
- prg.xToken()
- prg.backInput()
- }
- goto restart
- }
- case charNum:
- prg.scanCharNum()
- prg.curChr = uint16(prg.curVal)
- prg.curCmd = byte(charGiven)
- goto reswitch
- case mathCharNum:
- prg.scanFifteenBitInt()
- c = prg.curVal
- case mathGiven:
- c = int32(prg.curChr)
- case delimNum:
- prg.scanTwentySevenBitInt()
- c = prg.curVal / 010000
- default:
- prg.backInput()
- prg.scanLeftBrace()
- *prg.saveStack[int32(prg.savePtr)+0].int() = int32(p)
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- prg.pushMath(groupCode(mathGroup))
- goto exit
- }
- *(*prg.mem[p].hh()).rh() = uint16(mathChar)
- *(*prg.mem[p].hh()).b1() = byte(c%256 + minQuarterword)
- if c >= 070000 && (*prg.eqtb[intBase+curFamCode-1].int() >= 0 && *prg.eqtb[intBase+curFamCode-1].int() < 16) {
- *(*prg.mem[p].hh()).b0() = byte(*prg.eqtb[intBase+curFamCode-1].int())
- } else {
- *(*prg.mem[p].hh()).b0() = byte(c / 256 % 16)
- }
- exit:
- }
- func (prg *prg) setMathChar(c int32) {
- var (
- p halfword // the new noad
- )
- if c >= 0100000 {
- prg.curCs = uint16(int32(prg.curChr) + activeBase)
- prg.curCmd = *(*prg.eqtb[prg.curCs-1].hh()).b0()
- prg.curChr = *(*prg.eqtb[prg.curCs-1].hh()).rh()
- prg.xToken()
- prg.backInput()
- } else {
- p = prg.newNoad()
- *(*prg.mem[int32(p)+1].hh()).rh() = uint16(mathChar)
- *(*prg.mem[int32(p)+1].hh()).b1() = byte(c%256 + minQuarterword)
- *(*prg.mem[int32(p)+1].hh()).b0() = byte(c / 256 % 16)
- if c >= 070000 {
- if *prg.eqtb[intBase+curFamCode-1].int() >= 0 && *prg.eqtb[intBase+curFamCode-1].int() < 16 {
- *(*prg.mem[int32(p)+1].hh()).b0() = byte(*prg.eqtb[intBase+curFamCode-1].int())
- }
- *(*prg.mem[p].hh()).b0() = byte(ordNoad)
- } else {
- *(*prg.mem[p].hh()).b0() = byte(ordNoad + c/010000)
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- prg.curList.tailField = p
- }
- }
- func (prg *prg) mathLimitSwitch() {
- if int32(prg.curList.headField) != int32(prg.curList.tailField) {
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == opNoad {
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(prg.curChr)
- goto exit
- }
- }
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Limit controls must follow a math operator" */ 1130)
- }
- // \xref[Limit controls must follow...]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm ignoring this misplaced \\limits or \\nolimits command." */ 1131
- }
- prg.error1()
- exit:
- }
- func (prg *prg) scanDelimiter(p halfword, r1 bool) {
- if r1 {
- prg.scanTwentySevenBitInt()
- } else {
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
- break
- }
- }
- switch prg.curCmd {
- case letter, otherChar:
- prg.curVal = *prg.eqtb[delCodeBase+int32(prg.curChr)-1].int()
- case delimNum:
- prg.scanTwentySevenBitInt()
- default:
- prg.curVal = -1
- }
- }
- if prg.curVal < 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing delimiter (. inserted)" */ 1132)
- }
- // \xref[Missing delimiter...]
- {
- prg.helpPtr = 6
- prg.helpLine[5] = /* "I was expecting to see something like `(' or `\\[' or" */ 1133
- prg.helpLine[4] = /* "`\\]' here. If you typed, e.g., `[' instead of `\\[', you" */ 1134
- prg.helpLine[3] = /* "should probably delete the `[' by typing `1' now, so that" */ 1135
- prg.helpLine[2] = /* "braces don't get unbalanced. Otherwise just proceed." */ 1136
- prg.helpLine[1] = /* "Acceptable delimiters are characters whose \\delcode is" */ 1137
- prg.helpLine[0] = /* "nonnegative, or you can use `\\delimiter <delimiter code>'." */ 1138
- }
- prg.backError()
- prg.curVal = 0
- }
- (*prg.mem[p].qqqq()).b0 = byte(prg.curVal / 04000000 % 16)
- (*prg.mem[p].qqqq()).b1 = byte(prg.curVal/010000%256 + minQuarterword)
- (*prg.mem[p].qqqq()).b2 = byte(prg.curVal / 256 % 16)
- (*prg.mem[p].qqqq()).b3 = byte(prg.curVal%256 + minQuarterword)
- }
- func (prg *prg) mathRadical() {
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.getNode(radicalNoadSize)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b0() = byte(radicalNoad)
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(normal)
- *prg.mem[int32(prg.curList.tailField)+1].hh() = prg.emptyField
- *prg.mem[int32(prg.curList.tailField)+3].hh() = prg.emptyField
- *prg.mem[int32(prg.curList.tailField)+2].hh() = prg.emptyField
- prg.scanDelimiter(halfword(int32(prg.curList.tailField)+4), true)
- prg.scanMath(halfword(int32(prg.curList.tailField) + 1))
- }
- func (prg *prg) mathAc() {
- if int32(prg.curCmd) == accent {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Please use " */ 1139)
- }
- prg.printEsc(strNumber( /* "mathaccent" */ 523))
- prg.print( /* " for accents in math mode" */ 1140)
- // \xref[Please use \\mathaccent...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I'm changing \\accent to \\mathaccent here; wish me luck." */ 1141
- prg.helpLine[0] = /* "(Accents are not the same in formulas as they are in text.)" */ 1142
- }
- prg.error1()
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.getNode(accentNoadSize)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b0() = byte(accentNoad)
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(normal)
- *prg.mem[int32(prg.curList.tailField)+1].hh() = prg.emptyField
- *prg.mem[int32(prg.curList.tailField)+3].hh() = prg.emptyField
- *prg.mem[int32(prg.curList.tailField)+2].hh() = prg.emptyField
- *(*prg.mem[int32(prg.curList.tailField)+4].hh()).rh() = uint16(mathChar)
- prg.scanFifteenBitInt()
- *(*prg.mem[int32(prg.curList.tailField)+4].hh()).b1() = byte(prg.curVal%256 + minQuarterword)
- if prg.curVal >= 070000 && (*prg.eqtb[intBase+curFamCode-1].int() >= 0 && *prg.eqtb[intBase+curFamCode-1].int() < 16) {
- *(*prg.mem[int32(prg.curList.tailField)+4].hh()).b0() = byte(*prg.eqtb[intBase+curFamCode-1].int())
- } else {
- *(*prg.mem[int32(prg.curList.tailField)+4].hh()).b0() = byte(prg.curVal / 256 % 16)
- }
- prg.scanMath(halfword(int32(prg.curList.tailField) + 1))
- }
- func (prg *prg) appendChoices() {
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newChoice()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- prg.savePtr = uint16(int32(prg.savePtr) + 1)
- *prg.saveStack[int32(prg.savePtr)+-1].int() = 0
- prg.pushMath(groupCode(mathChoiceGroup))
- prg.scanLeftBrace()
- }
- // \4
- // Declare the function called |fin_mlist|
- func (prg *prg) finMlist(p halfword) (r halfword) {
- var (
- q halfword // the mlist to return
- )
- if *prg.curList.auxField.int() != 0 {
- *(*prg.mem[*prg.curList.auxField.int()+3].hh()).rh() = uint16(subMlist)
- *(*prg.mem[*prg.curList.auxField.int()+3].hh()).lh() = *(*prg.mem[prg.curList.headField].hh()).rh()
- if int32(p) == 0 {
- q = uint16(*prg.curList.auxField.int())
- } else {
- q = *(*prg.mem[*prg.curList.auxField.int()+2].hh()).lh()
- if int32(*(*prg.mem[q].hh()).b0()) != leftNoad {
- prg.confusion(strNumber( /* "right" */ 877))
- }
- // \xref[this can't happen right][\quad right]
- *(*prg.mem[*prg.curList.auxField.int()+2].hh()).lh() = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).rh() = uint16(*prg.curList.auxField.int())
- *(*prg.mem[*prg.curList.auxField.int()].hh()).rh() = p
- }
- } else {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- q = *(*prg.mem[prg.curList.headField].hh()).rh()
- }
- prg.popNest()
- r = q
- return r
- }
- //
- func (prg *prg) buildChoices() {
- var (
- p halfword // the current mlist
- )
- prg.unsave()
- p = prg.finMlist(halfword(0))
- switch *prg.saveStack[int32(prg.savePtr)+-1].int() {
- case 0:
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = p
- case 1:
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = p
- case 2:
- *(*prg.mem[int32(prg.curList.tailField)+2].hh()).lh() = p
- case 3:
- *(*prg.mem[int32(prg.curList.tailField)+2].hh()).rh() = p
- prg.savePtr = uint16(int32(prg.savePtr) - 1)
- goto exit
- } // there are no other cases
- *prg.saveStack[int32(prg.savePtr)+-1].int() = *prg.saveStack[int32(prg.savePtr)+-1].int() + 1
- prg.pushMath(groupCode(mathChoiceGroup))
- prg.scanLeftBrace()
- exit:
- }
- func (prg *prg) subSup() {
- var (
- t smallNumber // type of previous sub/superscript
- p halfword // field to be filled by |scan_math|
- )
- t = byte(empty)
- p = 0
- if int32(prg.curList.tailField) != int32(prg.curList.headField) {
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) >= ordNoad && int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) < leftNoad {
- p = uint16(int32(prg.curList.tailField) + 2 + int32(prg.curCmd) - supMark) // |supscr| or |subscr|
- t = byte(*(*prg.mem[p].hh()).rh())
- }
- }
- if int32(p) == 0 || int32(t) != empty {
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- p = uint16(int32(prg.curList.tailField) + 2 + int32(prg.curCmd) - supMark) // |supscr| or |subscr|
- if int32(t) != empty {
- if int32(prg.curCmd) == supMark {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Double superscript" */ 1143)
- }
- // \xref[Double superscript]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I treat `x^1^2' essentially like `x^1[]^2'." */ 1144
- }
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Double subscript" */ 1145)
- }
- // \xref[Double subscript]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I treat `x_1_2' essentially like `x_1[]_2'." */ 1146
- }
- }
- prg.error1()
- }
- }
- prg.scanMath(p)
- }
- func (prg *prg) mathFraction() {
- var (
- c smallNumber // the type of generalized fraction we are scanning
- )
- c = byte(prg.curChr)
- if *prg.curList.auxField.int() != 0 {
- if int32(c) >= delimitedCode {
- prg.scanDelimiter(halfword(30000-12), false)
- prg.scanDelimiter(halfword(30000-12), false)
- }
- if int32(c)%delimitedCode == aboveCode {
- prg.scanDimen(false, false, false)
- }
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Ambiguous; you need another [ and ]" */ 1153)
- }
- // \xref[Ambiguous...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "I'm ignoring this fraction specification, since I don't" */ 1154
- prg.helpLine[1] = /* "know whether a construction like `x \\over y \\over z'" */ 1155
- prg.helpLine[0] = /* "means `[x \\over y] \\over z' or `x \\over [y \\over z]'." */ 1156
- }
- prg.error1()
- } else {
- *prg.curList.auxField.int() = int32(prg.getNode(fractionNoadSize))
- *(*prg.mem[*prg.curList.auxField.int()].hh()).b0() = byte(fractionNoad)
- *(*prg.mem[*prg.curList.auxField.int()].hh()).b1() = byte(normal)
- *(*prg.mem[*prg.curList.auxField.int()+2].hh()).rh() = uint16(subMlist)
- *(*prg.mem[*prg.curList.auxField.int()+2].hh()).lh() = *(*prg.mem[prg.curList.headField].hh()).rh()
- *prg.mem[*prg.curList.auxField.int()+3].hh() = prg.emptyField
- *prg.mem[*prg.curList.auxField.int()+4].qqqq() = prg.nullDelimiter
- *prg.mem[*prg.curList.auxField.int()+5].qqqq() = prg.nullDelimiter
- *(*prg.mem[prg.curList.headField].hh()).rh() = 0
- prg.curList.tailField = prg.curList.headField
- // Use code |c| to distinguish between generalized fractions
- if int32(c) >= delimitedCode {
- prg.scanDelimiter(halfword(*prg.curList.auxField.int()+4), false)
- prg.scanDelimiter(halfword(*prg.curList.auxField.int()+5), false)
- }
- switch int32(c) % delimitedCode {
- case aboveCode:
- prg.scanDimen(false, false, false)
- *prg.mem[*prg.curList.auxField.int()+widthOffset].int() = prg.curVal
- case overCode:
- *prg.mem[*prg.curList.auxField.int()+widthOffset].int() = 010000000000
- case atopCode:
- *prg.mem[*prg.curList.auxField.int()+widthOffset].int() = 0
- }
- }
- }
- func (prg *prg) mathLeftRight() {
- var (
- t smallNumber // |left_noad| or |right_noad|
- p halfword // new noad
- )
- t = byte(prg.curChr)
- if int32(t) == rightNoad && int32(prg.curGroup) != mathLeftGroup {
- if int32(prg.curGroup) == mathShiftGroup {
- prg.scanDelimiter(halfword(30000-12), false)
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Extra " */ 777)
- }
- prg.printEsc(strNumber( /* "right" */ 877))
- // \xref[Extra \\right.]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm ignoring a \\right that had no matching \\left." */ 1157
- }
- prg.error1()
- } else {
- prg.offSave()
- }
- } else {
- p = prg.newNoad()
- *(*prg.mem[p].hh()).b0() = t
- prg.scanDelimiter(halfword(int32(p)+1), false)
- if int32(t) == leftNoad {
- prg.pushMath(groupCode(mathLeftGroup))
- *(*prg.mem[prg.curList.headField].hh()).rh() = p
- prg.curList.tailField = p
- } else {
- p = prg.finMlist(p)
- prg.unsave() // end of |math_left_group|
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b0() = byte(innerNoad)
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = uint16(subMlist)
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = p
- }
- }
- }
- func (prg *prg) afterMath() {
- var (
- l bool // `\.[\\leqno]' instead of `\.[\\eqno]'
- danger bool // not enough symbol fonts are present
- m int32 // |mmode| or |-mmode|
- p halfword // the formula
- a halfword // box containing equation number
- // Local variables for finishing a displayed formula
- b halfword // box containing the equation
- w scaled // width of the equation
- z scaled // width of the line
- e scaled // width of equation number
- q scaled // width of equation number plus space to separate from equation
- d scaled // displacement of equation in the line
- s scaled // move the line right this much
- g1, g2 smallNumber // glue parameter codes for before and after
- r1 halfword // kern node used to position the display
- t halfword // tail of adjustment list
- )
- danger = false
- // Check that the necessary fonts for math symbols are present; if not, flush the current math lists and set |danger:=true|
- if int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+textSize-1].hh()).rh()]) < totalMathsyParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+scriptSize-1].hh()).rh()]) < totalMathsyParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+scriptScriptSize-1].hh()).rh()]) < totalMathsyParams {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Math formula deleted: Insufficient symbol fonts" */ 1158)
- }
- // \xref[Math formula deleted...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "Sorry, but I can't typeset math unless \\textfont 2" */ 1159
- prg.helpLine[1] = /* "and \\scriptfont 2 and \\scriptscriptfont 2 have all" */ 1160
- prg.helpLine[0] = /* "the \\fontdimen values needed in math symbol fonts." */ 1161
- }
- prg.error1()
- prg.flushMath()
- danger = true
- } else if int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+textSize-1].hh()).rh()]) < totalMathexParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+scriptSize-1].hh()).rh()]) < totalMathexParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+scriptScriptSize-1].hh()).rh()]) < totalMathexParams {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Math formula deleted: Insufficient extension fonts" */ 1162)
- }
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "Sorry, but I can't typeset math unless \\textfont 3" */ 1163
- prg.helpLine[1] = /* "and \\scriptfont 3 and \\scriptscriptfont 3 have all" */ 1164
- prg.helpLine[0] = /* "the \\fontdimen values needed in math extension fonts." */ 1165
- }
- prg.error1()
- prg.flushMath()
- danger = true
- }
- m = int32(prg.curList.modeField)
- l = false
- p = prg.finMlist(halfword(0)) // this pops the nest
- if int32(prg.curList.modeField) == -m {
- {
- prg.getXToken()
- if int32(prg.curCmd) != mathShift {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Display math should end with $$" */ 1166)
- }
- // \xref[Display math...with \$\$]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "The `$' that I just saw supposedly matches a previous `$$'." */ 1167
- prg.helpLine[0] = /* "So I shall assume that you typed `$$' both times." */ 1168
- }
- prg.backError()
- }
- }
- prg.curMlist = p
- prg.curStyle = byte(textStyle)
- prg.mlistPenalties = false
- prg.mlistToHlist()
- a = prg.hpack(*(*prg.mem[30000-3].hh()).rh(), scaled(0), smallNumber(additional))
- prg.unsave()
- prg.savePtr = uint16(int32(prg.savePtr) - 1) // now |cur_group=math_shift_group|
- if *prg.saveStack[int32(prg.savePtr)+0].int() == 1 {
- l = true
- }
- danger = false
- // Check that the necessary fonts for math symbols are present; if not, flush the current math lists and set |danger:=true|
- if int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+textSize-1].hh()).rh()]) < totalMathsyParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+scriptSize-1].hh()).rh()]) < totalMathsyParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+2+scriptScriptSize-1].hh()).rh()]) < totalMathsyParams {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Math formula deleted: Insufficient symbol fonts" */ 1158)
- }
- // \xref[Math formula deleted...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "Sorry, but I can't typeset math unless \\textfont 2" */ 1159
- prg.helpLine[1] = /* "and \\scriptfont 2 and \\scriptscriptfont 2 have all" */ 1160
- prg.helpLine[0] = /* "the \\fontdimen values needed in math symbol fonts." */ 1161
- }
- prg.error1()
- prg.flushMath()
- danger = true
- } else if int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+textSize-1].hh()).rh()]) < totalMathexParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+scriptSize-1].hh()).rh()]) < totalMathexParams || int32(prg.fontParams[*(*prg.eqtb[mathFontBase+3+scriptScriptSize-1].hh()).rh()]) < totalMathexParams {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Math formula deleted: Insufficient extension fonts" */ 1162)
- }
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "Sorry, but I can't typeset math unless \\textfont 3" */ 1163
- prg.helpLine[1] = /* "and \\scriptfont 3 and \\scriptscriptfont 3 have all" */ 1164
- prg.helpLine[0] = /* "the \\fontdimen values needed in math extension fonts." */ 1165
- }
- prg.error1()
- prg.flushMath()
- danger = true
- }
- m = int32(prg.curList.modeField)
- p = prg.finMlist(halfword(0))
- } else {
- a = 0
- }
- if m < 0 {
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newMath(*prg.eqtb[dimenBase+mathSurroundCode-1].int(), smallNumber(before))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- prg.curMlist = p
- prg.curStyle = byte(textStyle)
- prg.mlistPenalties = int32(prg.curList.modeField) > 0
- prg.mlistToHlist()
- *(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[30000-3].hh()).rh()
- for int32(*(*prg.mem[prg.curList.tailField].hh()).rh()) != 0 {
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newMath(*prg.eqtb[dimenBase+mathSurroundCode-1].int(), smallNumber(after))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.curList.auxField.hh()).lh() = 1000
- prg.unsave()
- } else {
- if int32(a) == 0 {
- prg.getXToken()
- if int32(prg.curCmd) != mathShift {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Display math should end with $$" */ 1166)
- }
- // \xref[Display math...with \$\$]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "The `$' that I just saw supposedly matches a previous `$$'." */ 1167
- prg.helpLine[0] = /* "So I shall assume that you typed `$$' both times." */ 1168
- }
- prg.backError()
- }
- }
- // Finish displayed math
- prg.curMlist = p
- prg.curStyle = byte(displayStyle)
- prg.mlistPenalties = false
- prg.mlistToHlist()
- p = *(*prg.mem[30000-3].hh()).rh()
- prg.adjustTail = uint16(30000 - 5)
- b = prg.hpack(p, scaled(0), smallNumber(additional))
- p = *(*prg.mem[int32(b)+listOffset].hh()).rh()
- t = prg.adjustTail
- prg.adjustTail = 0
- w = *prg.mem[int32(b)+widthOffset].int()
- z = *prg.eqtb[dimenBase+displayWidthCode-1].int()
- s = *prg.eqtb[dimenBase+displayIndentCode-1].int()
- if int32(a) == 0 || danger {
- e = 0
- q = 0
- } else {
- e = *prg.mem[int32(a)+widthOffset].int()
- q = e + *prg.fontInfo[6+prg.paramBase[*(*prg.eqtb[mathFontBase+2+textSize-1].hh()).rh()]].int()
- }
- if w+q > z {
- if e != 0 && (w-prg.totalShrink[normal]+q <= z || prg.totalShrink[fil] != 0 || prg.totalShrink[fill] != 0 || prg.totalShrink[filll] != 0) {
- prg.freeNode(b, halfword(boxNodeSize))
- b = prg.hpack(p, z-q, smallNumber(exactly))
- } else {
- e = 0
- if w > z {
- prg.freeNode(b, halfword(boxNodeSize))
- b = prg.hpack(p, z, smallNumber(exactly))
- }
- }
- w = *prg.mem[int32(b)+widthOffset].int()
- }
- // Determine the displacement, |d|, of the left edge of the equation, with respect to the line size |z|, assuming that |l=false|
- d = prg.half(z - w)
- if e > 0 && d < 2*e {
- d = prg.half(z - w - e)
- if int32(p) != 0 {
- if !(int32(p) >= int32(prg.hiMemMin)) {
- if int32(*(*prg.mem[p].hh()).b0()) == glueNode {
- d = 0
- }
- }
- }
- }
- // Append the glue or equation number preceding the display
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(*prg.eqtb[intBase+preDisplayPenaltyCode-1].int())
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- if d+s <= *prg.eqtb[dimenBase+preDisplaySizeCode-1].int() || l {
- g1 = byte(aboveDisplaySkipCode)
- g2 = byte(belowDisplaySkipCode)
- } else {
- g1 = byte(aboveDisplayShortSkipCode)
- g2 = byte(belowDisplayShortSkipCode)
- }
- if l && e == 0 {
- *prg.mem[int32(a)+4].int() = s
- prg.appendToVlist(a)
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(infPenalty)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- } else {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(g1)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- // Append the display and perhaps also the equation number
- if e != 0 {
- r1 = prg.newKern(z - w - e - d)
- if l {
- *(*prg.mem[a].hh()).rh() = r1
- *(*prg.mem[r1].hh()).rh() = b
- b = a
- d = 0
- } else {
- *(*prg.mem[b].hh()).rh() = r1
- *(*prg.mem[r1].hh()).rh() = a
- }
- b = prg.hpack(b, scaled(0), smallNumber(additional))
- }
- *prg.mem[int32(b)+4].int() = s + d
- prg.appendToVlist(b)
- // Append the glue or equation number following the display
- if int32(a) != 0 && e == 0 && !l {
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(infPenalty)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *prg.mem[int32(a)+4].int() = s + z - *prg.mem[int32(a)+widthOffset].int()
- prg.appendToVlist(a)
- g2 = 0
- }
- if int32(t) != 30000-5 {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = *(*prg.mem[30000-5].hh()).rh()
- prg.curList.tailField = t
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newPenalty(*prg.eqtb[intBase+postDisplayPenaltyCode-1].int())
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- if int32(g2) > 0 {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newParamGlue(g2)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- prg.resumeAfterDisplay()
- }
- } // \2
- func (prg *prg) resumeAfterDisplay() {
- if int32(prg.curGroup) != mathShiftGroup {
- prg.confusion(strNumber( /* "display" */ 1169))
- }
- // \xref[this can't happen display][\quad display]
- prg.unsave()
- prg.curList.pgField = prg.curList.pgField + 3
- prg.pushNest()
- prg.curList.modeField = int16(hmode)
- *(*prg.curList.auxField.hh()).lh() = 1000
- if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
- prg.curLang = 0
- } else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
- prg.curLang = 0
- } else {
- prg.curLang = byte(*prg.eqtb[intBase+languageCode-1].int())
- }
- *(*prg.curList.auxField.hh()).rh() = uint16(prg.curLang)
- prg.curList.pgField = (int32(prg.normMin(*prg.eqtb[intBase+leftHyphenMinCode-1].int()))*0100+int32(prg.normMin(*prg.eqtb[intBase+rightHyphenMinCode-1].int())))*0200000 + int32(prg.curLang)
- // Scan an optional space
- {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- prg.backInput()
- }
- }
- if int32(prg.nestPtr) == 1 {
- prg.buildPage()
- }
- }
- // \4
- // Declare subprocedures for |prefixed_command|
- func (prg *prg) getRToken() {
- restart:
- for {
- prg.getToken()
- if int32(prg.curTok) != spaceToken {
- break
- }
- }
- if int32(prg.curCs) == 0 || int32(prg.curCs) > frozenControlSequence {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing control sequence inserted" */ 1184)
- }
- // \xref[Missing control...]
- {
- prg.helpPtr = 5
- prg.helpLine[4] = /* "Please don't say `\\def cs[...]', say `\\def\\cs[...]'." */ 1185
- prg.helpLine[3] = /* "I've inserted an inaccessible control sequence so that your" */ 1186
- prg.helpLine[2] = /* "definition will be completed without mixing me up too badly." */ 1187
- prg.helpLine[1] = /* "You can recover graciously from this error, if you're" */ 1188
- prg.helpLine[0] = /* "careful; see exercise 27.2 in The TeXbook." */ 1189
- }
- // \xref[TeXbook][\sl The \TeX book]
- if int32(prg.curCs) == 0 {
- prg.backInput()
- }
- prg.curTok = uint16(07777 + frozenProtection)
- prg.insError()
- goto restart
- }
- }
- func (prg *prg) trapZeroGlue() {
- if *prg.mem[prg.curVal+widthOffset].int() == 0 && *prg.mem[prg.curVal+2].int() == 0 && *prg.mem[prg.curVal+3].int() == 0 {
- *(*prg.mem[memBot].hh()).rh() = uint16(int32(*(*prg.mem[memBot].hh()).rh()) + 1)
- prg.deleteGlueRef(halfword(prg.curVal))
- prg.curVal = memBot
- }
- }
- func (prg *prg) doRegisterCommand(a smallNumber) {
- var (
- l, q, r1, s halfword // for list manipulation
- p/* intVal..muVal */ byte // type of register involved
- )
- q = uint16(prg.curCmd)
- // Compute the register location |l| and its type |p|; but |return| if invalid
- {
- if int32(q) != register {
- prg.getXToken()
- if int32(prg.curCmd) >= assignInt && int32(prg.curCmd) <= assignMuGlue {
- l = prg.curChr
- p = byte(int32(prg.curCmd) - assignInt)
- goto found
- }
- if int32(prg.curCmd) != register {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "You can't use `" */ 685)
- }
- prg.printCmdChr(prg.curCmd, prg.curChr)
- // \xref[You can't use x after ...]
- prg.print( /* "' after " */ 686)
- prg.printCmdChr(quarterword(q), halfword(0))
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm forgetting what you said and not changing anything." */ 1210
- }
- prg.error1()
- goto exit
- }
- }
- p = byte(prg.curChr)
- prg.scanEightBitInt()
- switch p {
- case intVal:
- l = uint16(prg.curVal + countBase)
- case dimenVal:
- l = uint16(prg.curVal + scaledBase)
- case glueVal:
- l = uint16(prg.curVal + skipBase)
- case muVal:
- l = uint16(prg.curVal + muSkipBase)
- } // there are no other cases
- }
- found:
- ;
- if int32(q) == register {
- prg.scanOptionalEquals()
- } else if prg.scanKeyword(strNumber( /* "by" */ 1206)) {
- } // optional `\.[by]'
- // \xref[by]
- prg.arithError = false
- if int32(q) < multiply {
- if int32(p) < glueVal {
- if int32(p) == intVal {
- prg.scanInt()
- } else {
- prg.scanDimen(false, false, false)
- }
- if int32(q) == advance {
- prg.curVal = prg.curVal + *prg.eqtb[l-1].int()
- }
- } else {
- prg.scanGlue(p)
- if int32(q) == advance {
- q = prg.newSpec(halfword(prg.curVal))
- r1 = *(*prg.eqtb[l-1].hh()).rh()
- prg.deleteGlueRef(halfword(prg.curVal))
- *prg.mem[int32(q)+widthOffset].int() = *prg.mem[int32(q)+widthOffset].int() + *prg.mem[int32(r1)+widthOffset].int()
- if *prg.mem[int32(q)+2].int() == 0 {
- *(*prg.mem[q].hh()).b0() = byte(normal)
- }
- if int32(*(*prg.mem[q].hh()).b0()) == int32(*(*prg.mem[r1].hh()).b0()) {
- *prg.mem[int32(q)+2].int() = *prg.mem[int32(q)+2].int() + *prg.mem[int32(r1)+2].int()
- } else if int32(*(*prg.mem[q].hh()).b0()) < int32(*(*prg.mem[r1].hh()).b0()) && *prg.mem[int32(r1)+2].int() != 0 {
- *prg.mem[int32(q)+2].int() = *prg.mem[int32(r1)+2].int()
- *(*prg.mem[q].hh()).b0() = *(*prg.mem[r1].hh()).b0()
- }
- if *prg.mem[int32(q)+3].int() == 0 {
- *(*prg.mem[q].hh()).b1() = byte(normal)
- }
- if int32(*(*prg.mem[q].hh()).b1()) == int32(*(*prg.mem[r1].hh()).b1()) {
- *prg.mem[int32(q)+3].int() = *prg.mem[int32(q)+3].int() + *prg.mem[int32(r1)+3].int()
- } else if int32(*(*prg.mem[q].hh()).b1()) < int32(*(*prg.mem[r1].hh()).b1()) && *prg.mem[int32(r1)+3].int() != 0 {
- *prg.mem[int32(q)+3].int() = *prg.mem[int32(r1)+3].int()
- *(*prg.mem[q].hh()).b1() = *(*prg.mem[r1].hh()).b1()
- }
- prg.curVal = int32(q)
- }
- }
- } else {
- // Compute result of |multiply| or |divide|, put it in |cur_val|
- prg.scanInt()
- if int32(p) < glueVal {
- if int32(q) == multiply {
- if int32(p) == intVal {
- prg.curVal = prg.multAndAdd(*prg.eqtb[l-1].int(), prg.curVal, scaled(0), scaled(017777777777))
- } else {
- prg.curVal = prg.multAndAdd(*prg.eqtb[l-1].int(), prg.curVal, scaled(0), scaled(07777777777))
- }
- } else {
- prg.curVal = prg.xOverN(*prg.eqtb[l-1].int(), prg.curVal)
- }
- } else {
- s = *(*prg.eqtb[l-1].hh()).rh()
- r1 = prg.newSpec(s)
- if int32(q) == multiply {
- *prg.mem[int32(r1)+widthOffset].int() = prg.multAndAdd(*prg.mem[int32(s)+widthOffset].int(), prg.curVal, scaled(0), scaled(07777777777))
- *prg.mem[int32(r1)+2].int() = prg.multAndAdd(*prg.mem[int32(s)+2].int(), prg.curVal, scaled(0), scaled(07777777777))
- *prg.mem[int32(r1)+3].int() = prg.multAndAdd(*prg.mem[int32(s)+3].int(), prg.curVal, scaled(0), scaled(07777777777))
- } else {
- *prg.mem[int32(r1)+widthOffset].int() = prg.xOverN(*prg.mem[int32(s)+widthOffset].int(), prg.curVal)
- *prg.mem[int32(r1)+2].int() = prg.xOverN(*prg.mem[int32(s)+2].int(), prg.curVal)
- *prg.mem[int32(r1)+3].int() = prg.xOverN(*prg.mem[int32(s)+3].int(), prg.curVal)
- }
- prg.curVal = int32(r1)
- }
- }
- if prg.arithError {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Arithmetic overflow" */ 1207)
- }
- // \xref[Arithmetic overflow]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I can't carry out that multiplication or division," */ 1208
- prg.helpLine[0] = /* "since the result is out of range." */ 1209
- }
- if int32(p) >= glueVal {
- prg.deleteGlueRef(halfword(prg.curVal))
- }
- prg.error1()
- goto exit
- }
- if int32(p) < glueVal {
- if int32(a) >= 4 {
- prg.geqWordDefine(l, prg.curVal)
- } else {
- prg.eqWordDefine(l, prg.curVal)
- }
- } else {
- prg.trapZeroGlue()
- if int32(a) >= 4 {
- prg.geqDefine(l, quarterword(glueRef), halfword(prg.curVal))
- } else {
- prg.eqDefine(l, quarterword(glueRef), halfword(prg.curVal))
- }
- }
- exit:
- }
- func (prg *prg) alterAux() {
- var (
- c halfword // |hmode| or |vmode|
- )
- if int32(prg.curChr) != abs(int32(prg.curList.modeField)) {
- prg.reportIllegalCase()
- } else {
- c = prg.curChr
- prg.scanOptionalEquals()
- if int32(c) == vmode {
- prg.scanDimen(false, false, false)
- *prg.curList.auxField.int() = prg.curVal
- } else {
- prg.scanInt()
- if prg.curVal <= 0 || prg.curVal > 32767 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Bad space factor" */ 1213)
- }
- // \xref[Bad space factor]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I allow only values in the range 1..32767 here." */ 1214
- }
- prg.intError(prg.curVal)
- } else {
- *(*prg.curList.auxField.hh()).lh() = uint16(prg.curVal)
- }
- }
- }
- }
- func (prg *prg) alterPrevGraf() {
- var (
- p /* 0..nestSize */ byte // index into |nest|
- )
- prg.nest[prg.nestPtr] = prg.curList
- p = prg.nestPtr
- for abs(int32(prg.nest[p].modeField)) != vmode {
- p = byte(int32(p) - 1)
- }
- prg.scanOptionalEquals()
- prg.scanInt()
- if prg.curVal < 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Bad " */ 955)
- }
- prg.printEsc(strNumber( /* "prevgraf" */ 532))
- // \xref[Bad \\prevgraf]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I allow only nonnegative values here." */ 1215
- }
- prg.intError(prg.curVal)
- } else {
- prg.nest[p].pgField = prg.curVal
- prg.curList = prg.nest[prg.nestPtr]
- }
- }
- func (prg *prg) alterPageSoFar() {
- var (
- c /* 0..7 */ byte // index into |page_so_far|
- )
- c = byte(prg.curChr)
- prg.scanOptionalEquals()
- prg.scanDimen(false, false, false)
- prg.pageSoFar[c] = prg.curVal
- }
- func (prg *prg) alterInteger() {
- var (
- c /* 0..1 */ byte // 0 for \.[\\deadcycles], 1 for \.[\\insertpenalties]
- )
- c = byte(prg.curChr)
- prg.scanOptionalEquals()
- prg.scanInt()
- if int32(c) == 0 {
- prg.deadCycles = prg.curVal
- } else {
- prg.insertPenalties = prg.curVal
- }
- }
- func (prg *prg) alterBoxDimen() {
- var (
- c smallNumber // |width_offset| or |height_offset| or |depth_offset|
- b eightBits // box number
- )
- c = byte(prg.curChr)
- prg.scanEightBitInt()
- b = byte(prg.curVal)
- prg.scanOptionalEquals()
- prg.scanDimen(false, false, false)
- if int32(*(*prg.eqtb[boxBase+int32(b)-1].hh()).rh()) != 0 {
- *prg.mem[int32(*(*prg.eqtb[boxBase+int32(b)-1].hh()).rh())+int32(c)].int() = prg.curVal
- }
- }
- func (prg *prg) newFont(a smallNumber) {
- var (
- u halfword // user's font identifier
- s scaled // stated ``at'' size, or negative of scaled magnification
- f internalFontNumber // runs through existing fonts
- t strNumber // name for the frozen font identifier
- oldSetting/* 0..maxSelector */ byte // holds |selector| setting
- flushableString strNumber // string not yet referenced
- )
- if int32(prg.jobName) == 0 {
- prg.openLogFile()
- }
- // avoid confusing \.[texput] with the font name
- // \xref[texput]
- prg.getRToken()
- u = prg.curCs
- if int32(u) >= hashBase {
- t = *prg.hash[u-514].rh()
- } else if int32(u) >= singleBase {
- if int32(u) == nullCs {
- t = /* "FONT" */ 1219
- } else {
- t = uint16(int32(u) - singleBase)
- }
- } else {
- oldSetting = prg.selector
- prg.selector = byte(newString)
- prg.print( /* "FONT" */ 1219)
- prg.print(int32(u) - activeBase)
- prg.selector = oldSetting
- // \xref[FONTx]
- {
- if int32(prg.poolPtr)+1 > poolSize {
- prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
- } /* \xref[TeX capacity exceeded pool size][\quad pool size] */
- }
- t = prg.makeString()
- }
- if int32(a) >= 4 {
- prg.geqDefine(u, quarterword(setFont), halfword(fontBase))
- } else {
- prg.eqDefine(u, quarterword(setFont), halfword(fontBase))
- }
- prg.scanOptionalEquals()
- prg.scanFileName()
- // Scan the font size specification
- prg.nameInProgress = true // this keeps |cur_name| from being changed
- if prg.scanKeyword(strNumber( /* "at" */ 1220)) {
- prg.scanDimen(false, false, false)
- s = prg.curVal
- if s <= 0 || s >= 01000000000 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Improper `at' size (" */ 1222)
- }
- prg.printScaled(s)
- prg.print( /* "pt), replaced by 10pt" */ 1223)
- // \xref[Improper `at' size...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "I can only handle fonts at positive sizes that are" */ 1224
- prg.helpLine[0] = /* "less than 2048pt, so I've changed what you said to 10pt." */ 1225
- }
- prg.error1()
- s = 10 * 0200000
- }
- } else if prg.scanKeyword(strNumber( /* "scaled" */ 1221)) {
- prg.scanInt()
- s = -prg.curVal
- if prg.curVal <= 0 || prg.curVal > 32768 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Illegal magnification has been changed to 1000" */ 552)
- }
- // \xref[Illegal magnification...]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "The magnification ratio must be between 1 and 32768." */ 553
- }
- prg.intError(prg.curVal)
- s = -1000
- }
- } else {
- s = -1000
- }
- prg.nameInProgress = false
- // If this font has already been loaded, set |f| to the internal font number and |goto common_ending|
- flushableString = uint16(int32(prg.strPtr) - 1)
- for ii := int32(fontBase + 1); ii <= int32(prg.fontPtr); ii++ {
- f = internalFontNumber(ii)
- _ = f
- if prg.strEqStr(prg.fontName[f], prg.curName) && prg.strEqStr(prg.fontArea[f], prg.curArea) {
- if int32(prg.curName) == int32(flushableString) {
- {
- prg.strPtr = uint16(int32(prg.strPtr) - 1)
- prg.poolPtr = prg.strStart[prg.strPtr]
- }
- prg.curName = prg.fontName[f]
- }
- if s > 0 {
- if s == prg.fontSize[f] {
- goto commonEnding
- }
- } else if prg.fontSize[f] == prg.xnOverD(prg.fontDsize[f], -s, 1000) {
- goto commonEnding
- }
- }
- }
- f = prg.readFontInfo(u, prg.curName, prg.curArea, s)
- commonEnding:
- *(*prg.eqtb[u-1].hh()).rh() = uint16(f)
- prg.eqtb[fontIdBase+int32(f)-1] = prg.eqtb[u-1]
- *prg.hash[fontIdBase+int32(f)-514].rh() = t
- }
- func (prg *prg) newInteraction() {
- prg.printLn()
- prg.interaction = byte(prg.curChr)
- // Initialize the print |selector| based on |interaction|
- if int32(prg.interaction) == batchMode {
- prg.selector = byte(noPrint)
- } else {
- prg.selector = byte(termOnly)
- }
- if prg.logOpened {
- prg.selector = byte(int32(prg.selector) + 2)
- }
- }
- //
- func (prg *prg) prefixedCommand() {
- var (
- a smallNumber // accumulated prefix codes so far
- f internalFontNumber // identifies a font
- j halfword // index into a \.[\\parshape] specification
- k fontIndex // index into |font_info|
- p, q halfword // for temporary short-term use
- n int32 // ditto
- e bool // should a definition be expanded? or was \.[\\let] not done?
- )
- a = 0
- for int32(prg.curCmd) == prefix {
- if !(int32(a)/int32(prg.curChr)&1 != 0) {
- a = byte(int32(a) + int32(prg.curChr))
- }
- // Get the next non-blank non-relax...
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
- break
- }
- }
- if int32(prg.curCmd) <= maxNonPrefixedCommand {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "You can't use a prefix with `" */ 1179)
- }
- // \xref[You can't use a prefix with x]
- prg.printCmdChr(prg.curCmd, prg.curChr)
- prg.printChar(asciiCode('\''))
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'll pretend you didn't say \\long or \\outer or \\global." */ 1180
- }
- prg.backError()
- goto exit
- }
- }
- // Discard the prefixes \.[\\long] and \.[\\outer] if they are irrelevant
- if int32(prg.curCmd) != def && int32(a)%4 != 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "You can't use `" */ 685)
- }
- prg.printEsc(strNumber( /* "long" */ 1171))
- prg.print( /* "' or `" */ 1181)
- prg.printEsc(strNumber( /* "outer" */ 1172))
- prg.print( /* "' with `" */ 1182)
- // \xref[You can't use \\long...]
- prg.printCmdChr(prg.curCmd, prg.curChr)
- prg.printChar(asciiCode('\''))
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'll pretend you didn't say \\long or \\outer here." */ 1183
- }
- prg.error1()
- }
- // Adjust \(f)for the setting of \.[\\globaldefs]
- if *prg.eqtb[intBase+globalDefsCode-1].int() != 0 {
- if *prg.eqtb[intBase+globalDefsCode-1].int() < 0 {
- if int32(a) >= 4 {
- a = byte(int32(a) - 4)
- }
- } else {
- if !(int32(a) >= 4) {
- a = byte(int32(a) + 4)
- }
- }
- }
- switch prg.curCmd {
- case setFont:
- if int32(a) >= 4 {
- prg.geqDefine(halfword(curFontLoc), quarterword(data), prg.curChr)
- } else {
- prg.eqDefine(halfword(curFontLoc), quarterword(data), prg.curChr)
- }
- case def:
- if prg.curChr&1 != 0 && !(int32(a) >= 4) && *prg.eqtb[intBase+globalDefsCode-1].int() >= 0 {
- a = byte(int32(a) + 4)
- }
- e = int32(prg.curChr) >= 2
- prg.getRToken()
- p = prg.curCs
- q = prg.scanToks(true, e)
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(call+int32(a)%4), prg.defRef)
- } else {
- prg.eqDefine(p, quarterword(call+int32(a)%4), prg.defRef)
- }
- case let:
- n = int32(prg.curChr)
- prg.getRToken()
- p = prg.curCs
- if n == normal {
- for {
- prg.getToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- if int32(prg.curTok) == otherToken+'=' {
- prg.getToken()
- if int32(prg.curCmd) == spacer {
- prg.getToken()
- }
- }
- } else {
- prg.getToken()
- q = prg.curTok
- prg.getToken()
- prg.backInput()
- prg.curTok = q
- prg.backInput() // look ahead, then back up
- } // note that |back_input| doesn't affect |cur_cmd|, |cur_chr|
- if int32(prg.curCmd) >= call {
- *(*prg.mem[prg.curChr].hh()).lh() = uint16(int32(*(*prg.mem[prg.curChr].hh()).lh()) + 1)
- }
- if int32(a) >= 4 {
- prg.geqDefine(p, prg.curCmd, prg.curChr)
- } else {
- prg.eqDefine(p, prg.curCmd, prg.curChr)
- }
- case shorthandDef:
- n = int32(prg.curChr)
- prg.getRToken()
- p = prg.curCs
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(relax), halfword(256))
- } else {
- prg.eqDefine(p, quarterword(relax), halfword(256))
- }
- prg.scanOptionalEquals()
- switch n {
- case charDefCode:
- prg.scanCharNum()
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(charGiven), halfword(prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(charGiven), halfword(prg.curVal))
- }
- case mathCharDefCode:
- prg.scanFifteenBitInt()
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(mathGiven), halfword(prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(mathGiven), halfword(prg.curVal))
- }
- default:
- prg.scanEightBitInt()
- switch n {
- case countDefCode:
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(assignInt), halfword(countBase+prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(assignInt), halfword(countBase+prg.curVal))
- }
- case dimenDefCode:
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(assignDimen), halfword(scaledBase+prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(assignDimen), halfword(scaledBase+prg.curVal))
- }
- case skipDefCode:
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(assignGlue), halfword(skipBase+prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(assignGlue), halfword(skipBase+prg.curVal))
- }
- case muSkipDefCode:
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(assignMuGlue), halfword(muSkipBase+prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(assignMuGlue), halfword(muSkipBase+prg.curVal))
- }
- case toksDefCode:
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(assignToks), halfword(toksBase+prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(assignToks), halfword(toksBase+prg.curVal))
- }
- } // there are no other cases
- }
- case readToCs:
- prg.scanInt()
- n = prg.curVal
- if !prg.scanKeyword(strNumber(842)) {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing `to' inserted" */ 1073)
- }
- // \xref[Missing `to'...]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "You should have said `\\read<number> to \\cs'." */ 1200
- prg.helpLine[0] = /* "I'm going to look for the \\cs now." */ 1201
- }
- prg.error1()
- }
- prg.getRToken()
- p = prg.curCs
- prg.readToks(n, p)
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(call), halfword(prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(call), halfword(prg.curVal))
- }
- case toksRegister, assignToks:
- q = prg.curCs
- if int32(prg.curCmd) == toksRegister {
- prg.scanEightBitInt()
- p = uint16(toksBase + prg.curVal)
- } else {
- p = prg.curChr
- } // |p=every_par_loc| or |output_routine_loc| or \dots
- prg.scanOptionalEquals()
- // Get the next non-blank non-relax non-call token
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
- break
- }
- }
- if int32(prg.curCmd) != leftBrace {
- if int32(prg.curCmd) == toksRegister {
- prg.scanEightBitInt()
- prg.curCmd = byte(assignToks)
- prg.curChr = uint16(toksBase + prg.curVal)
- }
- if int32(prg.curCmd) == assignToks {
- q = *(*prg.eqtb[prg.curChr-1].hh()).rh()
- if int32(q) == 0 {
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(undefinedCs), halfword(0))
- } else {
- prg.eqDefine(p, quarterword(undefinedCs), halfword(0))
- }
- } else {
- *(*prg.mem[q].hh()).lh() = uint16(int32(*(*prg.mem[q].hh()).lh()) + 1)
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(call), q)
- } else {
- prg.eqDefine(p, quarterword(call), q)
- }
- }
- goto done
- }
- }
- prg.backInput()
- prg.curCs = q
- q = prg.scanToks(false, false)
- if int32(*(*prg.mem[prg.defRef].hh()).rh()) == 0 {
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(undefinedCs), halfword(0))
- } else {
- prg.eqDefine(p, quarterword(undefinedCs), halfword(0))
- }
- {
- *(*prg.mem[prg.defRef].hh()).rh() = prg.avail
- prg.avail = prg.defRef /* dyn_used:= dyn_used-1 ; [ ] */
- }
- } else {
- if int32(p) == outputRoutineLoc {
- *(*prg.mem[q].hh()).rh() = prg.getAvail()
- q = *(*prg.mem[q].hh()).rh()
- *(*prg.mem[q].hh()).lh() = uint16(rightBraceToken + '}')
- q = prg.getAvail()
- *(*prg.mem[q].hh()).lh() = uint16(leftBraceToken + '{')
- *(*prg.mem[q].hh()).rh() = *(*prg.mem[prg.defRef].hh()).rh()
- *(*prg.mem[prg.defRef].hh()).rh() = q
- }
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(call), prg.defRef)
- } else {
- prg.eqDefine(p, quarterword(call), prg.defRef)
- }
- }
- case assignInt:
- p = prg.curChr
- prg.scanOptionalEquals()
- prg.scanInt()
- if int32(a) >= 4 {
- prg.geqWordDefine(p, prg.curVal)
- } else {
- prg.eqWordDefine(p, prg.curVal)
- }
- case assignDimen:
- p = prg.curChr
- prg.scanOptionalEquals()
- prg.scanDimen(false, false, false)
- if int32(a) >= 4 {
- prg.geqWordDefine(p, prg.curVal)
- } else {
- prg.eqWordDefine(p, prg.curVal)
- }
- case assignGlue, assignMuGlue:
- p = prg.curChr
- n = int32(prg.curCmd)
- prg.scanOptionalEquals()
- if n == assignMuGlue {
- prg.scanGlue(smallNumber(muVal))
- } else {
- prg.scanGlue(smallNumber(glueVal))
- }
- prg.trapZeroGlue()
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(glueRef), halfword(prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(glueRef), halfword(prg.curVal))
- }
- case defCode:
- if int32(prg.curChr) == catCodeBase {
- n = maxCharCode
- } else if int32(prg.curChr) == mathCodeBase {
- n = 0100000
- } else if int32(prg.curChr) == sfCodeBase {
- n = 077777
- } else if int32(prg.curChr) == delCodeBase {
- n = 077777777
- } else {
- n = 255
- }
- p = prg.curChr
- prg.scanCharNum()
- p = uint16(int32(p) + prg.curVal)
- prg.scanOptionalEquals()
- prg.scanInt()
- if prg.curVal < 0 && int32(p) < delCodeBase || prg.curVal > n {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Invalid code (" */ 1202)
- }
- prg.printInt(prg.curVal)
- // \xref[Invalid code]
- if int32(p) < delCodeBase {
- prg.print( /* "), should be in the range 0.." */ 1203)
- } else {
- prg.print( /* "), should be at most " */ 1204)
- }
- prg.printInt(n)
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm going to use 0 instead of that illegal code value." */ 1205
- }
- prg.error1()
- prg.curVal = 0
- }
- if int32(p) < mathCodeBase {
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(data), halfword(prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(data), halfword(prg.curVal))
- }
- } else if int32(p) < delCodeBase {
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(data), halfword(prg.curVal+0))
- } else {
- prg.eqDefine(p, quarterword(data), halfword(prg.curVal+0))
- }
- } else if int32(a) >= 4 {
- prg.geqWordDefine(p, prg.curVal)
- } else {
- prg.eqWordDefine(p, prg.curVal)
- }
- case defFamily:
- p = prg.curChr
- prg.scanFourBitInt()
- p = uint16(int32(p) + prg.curVal)
- prg.scanOptionalEquals()
- prg.scanFontIdent()
- if int32(a) >= 4 {
- prg.geqDefine(p, quarterword(data), halfword(prg.curVal))
- } else {
- prg.eqDefine(p, quarterword(data), halfword(prg.curVal))
- }
- case register, advance, multiply, divide:
- prg.doRegisterCommand(a)
- case setBox:
- prg.scanEightBitInt()
- if int32(a) >= 4 {
- n = 256 + prg.curVal
- } else {
- n = prg.curVal
- }
- prg.scanOptionalEquals()
- if prg.setBoxAllowed {
- prg.scanBox(010000000000 + n)
- } else {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Improper " */ 680)
- }
- prg.printEsc(strNumber( /* "setbox" */ 536))
- // \xref[Improper \\setbox]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Sorry, \\setbox is not allowed after \\halign in a display," */ 1211
- prg.helpLine[0] = /* "or between \\accent and an accented character." */ 1212
- }
- prg.error1()
- }
- case setAux:
- prg.alterAux()
- case setPrevGraf:
- prg.alterPrevGraf()
- case setPageDimen:
- prg.alterPageSoFar()
- case setPageInt:
- prg.alterInteger()
- case setBoxDimen:
- prg.alterBoxDimen()
- case setShape:
- prg.scanOptionalEquals()
- prg.scanInt()
- n = prg.curVal
- if n <= 0 {
- p = 0
- } else {
- p = prg.getNode(2*n + 1)
- *(*prg.mem[p].hh()).lh() = uint16(n)
- for ii := int32(1); ii <= n; ii++ {
- j = halfword(ii)
- _ = j
- prg.scanDimen(false, false, false)
- *prg.mem[int32(p)+2*int32(j)-1].int() = prg.curVal // indentation
- prg.scanDimen(false, false, false)
- *prg.mem[int32(p)+2*int32(j)].int() = prg.curVal // width
- }
- }
- if int32(a) >= 4 {
- prg.geqDefine(halfword(parShapeLoc), quarterword(shapeRef), p)
- } else {
- prg.eqDefine(halfword(parShapeLoc), quarterword(shapeRef), p)
- }
- case hyphData:
- if int32(prg.curChr) == 1 {
- prg.newPatterns()
- goto done
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Patterns can be loaded only by INITEX" */ 1216)
- }
- // \xref[Patterns can be...]
- prg.helpPtr = 0
- prg.error1()
- for {
- prg.getToken()
- if int32(prg.curCmd) == rightBrace {
- break
- }
- } // flush the patterns
- // flush the patterns
- goto exit
- } else {
- prg.newHyphExceptions()
- goto done
- }
- case assignFontDimen:
- prg.findFontDimen(true)
- k = uint16(prg.curVal)
- prg.scanOptionalEquals()
- prg.scanDimen(false, false, false)
- *prg.fontInfo[k].int() = prg.curVal
- case assignFontInt:
- n = int32(prg.curChr)
- prg.scanFontIdent()
- f = byte(prg.curVal)
- prg.scanOptionalEquals()
- prg.scanInt()
- if n == 0 {
- prg.hyphenChar[f] = prg.curVal
- } else {
- prg.skewChar[f] = prg.curVal
- }
- case defFont:
- prg.newFont(a)
- case setInteraction:
- prg.newInteraction()
- default:
- prg.confusion(strNumber( /* "prefix" */ 1178))
- // \xref[this can't happen prefix][\quad prefix]
- }
- done:
- if int32(prg.afterToken) != 0 {
- prg.curTok = prg.afterToken
- prg.backInput()
- prg.afterToken = 0
- }
- exit:
- } // note that |glue_shrink(p)=0| since |glue_shrink==shift_amount|
- // 800.
- // tangle:pos tex.web:15736:1:
- // Finally, we will reach the end of the alignment, and we can breathe a
- // sigh of relief that memory hasn't overflowed. All the unset boxes will now be
- // set so that the columns line up, taking due account of spanned columns.
- func (prg *prg) doAssignments() {
- for true {
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer && int32(prg.curCmd) != relax {
- break
- }
- }
- if int32(prg.curCmd) <= maxNonPrefixedCommand {
- goto exit
- }
- prg.setBoxAllowed = false
- prg.prefixedCommand()
- prg.setBoxAllowed = true
- }
- exit:
- }
- func (prg *prg) openOrCloseIn() {
- var (
- c/* 0..1 */ byte // 1 for \.[\\openin], 0 for \.[\\closein]
- n/* 0..15 */ byte // stream number
- )
- c = byte(prg.curChr)
- prg.scanFourBitInt()
- n = byte(prg.curVal)
- if int32(prg.readOpen[n]) != closed {
- prg.aClose(prg.readFile[n])
- prg.readOpen[n] = byte(closed)
- }
- if int32(c) != 0 {
- prg.scanOptionalEquals()
- prg.scanFileName()
- if int32(prg.curExt) == 338 {
- prg.curExt = /* ".tex" */ 791
- }
- prg.packFileName(prg.curName, prg.curArea, prg.curExt)
- if prg.aOpenIn(prg.readFile[n]) {
- prg.readOpen[n] = byte(justOpen)
- }
- }
- }
- func (prg *prg) issueMessage() {
- var (
- oldSetting/* 0..maxSelector */ byte // holds |selector| setting
- c/* 0..1 */ byte // identifies \.[\\message] and \.[\\errmessage]
- s strNumber // the message
- )
- c = byte(prg.curChr)
- *(*prg.mem[30000-12].hh()).rh() = prg.scanToks(false, true)
- oldSetting = prg.selector
- prg.selector = byte(newString)
- prg.tokenShow(prg.defRef)
- prg.selector = oldSetting
- prg.flushList(prg.defRef)
- {
- if int32(prg.poolPtr)+1 > poolSize {
- prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
- } /* \xref[TeX capacity exceeded pool size][\quad pool size] */
- }
- s = prg.makeString()
- if int32(c) == 0 {
- if int32(prg.termOffset)+(int32(prg.strStart[int32(s)+1])-int32(prg.strStart[s])) > maxPrintLine-2 {
- prg.printLn()
- } else if int32(prg.termOffset) > 0 || int32(prg.fileOffset) > 0 {
- prg.printChar(asciiCode(' '))
- }
- prg.slowPrint(int32(s))
- } else {
- // Print string |s| as an error message
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "" */ 338)
- }
- prg.slowPrint(int32(s))
- if int32(*(*prg.eqtb[errHelpLoc-1].hh()).rh()) != 0 {
- prg.useErrHelp = true
- } else if prg.longHelpSeen {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "(That was another \\errmessage.)" */ 1232
- } else {
- if int32(prg.interaction) < errorStopMode {
- prg.longHelpSeen = true
- }
- {
- prg.helpPtr = 4
- prg.helpLine[3] = /* "This error message was generated by an \\errmessage" */ 1233
- prg.helpLine[2] = /* "command, so I can't give any explicit help." */ 1234
- prg.helpLine[1] = /* "Pretend that you're Hercule Poirot: Examine all clues," */ 1235
- prg.helpLine[0] = /* "and deduce the truth by order and method." */ 1236
- }
- }
- prg.error1()
- prg.useErrHelp = false
- }
- {
- prg.strPtr = uint16(int32(prg.strPtr) - 1)
- prg.poolPtr = prg.strStart[prg.strPtr]
- }
- }
- func (prg *prg) shiftCase() {
- var (
- b halfword // |lc_code_base| or |uc_code_base|
- p halfword // runs through the token list
- t halfword // token
- c eightBits // character code
- )
- b = prg.curChr
- p = prg.scanToks(false, false)
- p = *(*prg.mem[prg.defRef].hh()).rh()
- for int32(p) != 0 {
- t = *(*prg.mem[p].hh()).lh()
- if int32(t) < 07777+singleBase {
- c = byte(int32(t) % 256)
- if int32(*(*prg.eqtb[int32(b)+int32(c)-1].hh()).rh()) != 0 {
- *(*prg.mem[p].hh()).lh() = uint16(int32(t) - int32(c) + int32(*(*prg.eqtb[int32(b)+int32(c)-1].hh()).rh()))
- }
- }
- p = *(*prg.mem[p].hh()).rh()
- }
- prg.beginTokenList(*(*prg.mem[prg.defRef].hh()).rh(), quarterword(backedUp))
- {
- *(*prg.mem[prg.defRef].hh()).rh() = prg.avail
- prg.avail = prg.defRef /* dyn_used:= dyn_used-1 ; [ ] */
- } // omit reference count
- }
- func (prg *prg) showWhatever() {
- var (
- p halfword // tail of a token list to show
- )
- if int32(p) == 0 {
- }
- switch prg.curChr {
- case showListsCode:
- prg.beginDiagnostic()
- prg.showActivities()
- case showBoxCode:
- // Show the current contents of a box
- prg.scanEightBitInt()
- prg.beginDiagnostic()
- prg.printNl(strNumber( /* "> \\box" */ 1254))
- prg.printInt(prg.curVal)
- prg.printChar(asciiCode('='))
- if int32(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh()) == 0 {
- prg.print( /* "void" */ 410)
- } else {
- prg.showBox(*(*prg.eqtb[boxBase+prg.curVal-1].hh()).rh())
- }
- case showCode:
- // Show the current meaning of a token, then |goto common_ending|
- prg.getToken()
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "> " */ 1248))
- if int32(prg.curCs) != 0 {
- prg.sprintCs(prg.curCs)
- prg.printChar(asciiCode('='))
- }
- prg.printMeaning()
- goto commonEnding
- default:
- p = prg.theToks()
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "> " */ 1248))
- prg.tokenShow(halfword(30000 - 3))
- prg.flushList(*(*prg.mem[30000-3].hh()).rh())
- goto commonEnding
- }
- // Complete a potentially long \.[\\show] command
- prg.endDiagnostic(true)
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "OK" */ 1255)
- }
- // \xref[OK]
- if int32(prg.selector) == termAndLog {
- if *prg.eqtb[intBase+tracingOnlineCode-1].int() <= 0 {
- prg.selector = byte(termOnly)
- prg.print( /* " (see the transcript file)" */ 1256)
- prg.selector = byte(termAndLog)
- }
- }
- commonEnding:
- if int32(prg.interaction) < errorStopMode {
- prg.helpPtr = 0
- prg.errorCount = int8(int32(prg.errorCount) - 1)
- } else if *prg.eqtb[intBase+tracingOnlineCode-1].int() > 0 {
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "This isn't an error message; I'm just \\showing something." */ 1243
- prg.helpLine[1] = /* "Type `I\\show...' to show more (e.g., \\show\\cs," */ 1244
- prg.helpLine[0] = /* "\\showthe\\count10, \\showbox255, \\showlists)." */ 1245
- }
- } else {
- {
- prg.helpPtr = 5
- prg.helpLine[4] = /* "This isn't an error message; I'm just \\showing something." */ 1243
- prg.helpLine[3] = /* "Type `I\\show...' to show more (e.g., \\show\\cs," */ 1244
- prg.helpLine[2] = /* "\\showthe\\count10, \\showbox255, \\showlists)." */ 1245
- prg.helpLine[1] = /* "And type `I\\tracingonline=1\\show...' to show boxes and" */ 1246
- prg.helpLine[0] = /* "lists on your terminal as well as in the transcript file." */ 1247
- }
- }
- prg.error1()
- }
- func (prg *prg) storeFmtFile() {
- var (
- j, k, l int32 // all-purpose indices
- p, q halfword // all-purpose pointers
- x int32 // something to dump
- w fourQuarters // four ASCII codes
- )
- if int32(prg.savePtr) != 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "You can't dump inside a group" */ 1258)
- }
- // \xref[You can't dump...]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "`[...\\dump]' is a no-no." */ 1259
- }
- {
- if int32(prg.interaction) == errorStopMode {
- prg.interaction = byte(scrollMode)
- }
- if prg.logOpened {
- prg.error1()
- } /* if interaction>batch_mode then debug_help; [ ] */
- prg.history = byte(fatalErrorStop)
- prg.jumpOut()
- }
- }
- // Create the |format_ident|, open the format file, and inform the user that dumping has begun
- prg.selector = byte(newString)
- prg.print( /* " (preloaded format=" */ 1272)
- prg.print(int32(prg.jobName))
- prg.printChar(asciiCode(' '))
- prg.printInt(*prg.eqtb[intBase+yearCode-1].int())
- prg.printChar(asciiCode('.'))
- prg.printInt(*prg.eqtb[intBase+monthCode-1].int())
- prg.printChar(asciiCode('.'))
- prg.printInt(*prg.eqtb[intBase+dayCode-1].int())
- prg.printChar(asciiCode(')'))
- if int32(prg.interaction) == batchMode {
- prg.selector = byte(logOnly)
- } else {
- prg.selector = byte(termAndLog)
- }
- {
- if int32(prg.poolPtr)+1 > poolSize {
- prg.overflow(strNumber( /* "pool size" */ 257), poolSize-int32(prg.initPoolPtr))
- } /* \xref[TeX capacity exceeded pool size][\quad pool size] */
- }
- prg.formatIdent = prg.makeString()
- prg.packJobName(strNumber(formatExtension))
- for !prg.wOpenOut(prg.fmtFile) {
- prg.promptFileName(strNumber( /* "format file name" */ 1273), strNumber(formatExtension))
- }
- prg.printNl(strNumber( /* "Beginning to dump on file " */ 1274))
- // \xref[Beginning to dump...]
- prg.slowPrint(int32(prg.wMakeNameString(prg.fmtFile)))
- {
- prg.strPtr = uint16(int32(prg.strPtr) - 1)
- prg.poolPtr = prg.strStart[prg.strPtr]
- }
- prg.printNl(strNumber( /* "" */ 338))
- prg.slowPrint(int32(prg.formatIdent))
- // Dump constants for consistency check
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = 504454778
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = memBot
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = 30000
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = eqtbSize
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = hashPrime
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = hyphSize
- prg.fmtFile.Put()
- }
- // Dump the string pool
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.poolPtr)
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.strPtr)
- prg.fmtFile.Put()
- }
- for ii := int32(0); ii <= int32(prg.strPtr); ii++ {
- k = ii
- _ = k
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.strStart[k])
- prg.fmtFile.Put()
- }
- k = 0
- for k+4 < int32(prg.poolPtr) {
- w.b0 = byte(int32(prg.strPool[k]) + minQuarterword)
- w.b1 = byte(int32(prg.strPool[k+1]) + minQuarterword)
- w.b2 = byte(int32(prg.strPool[k+2]) + minQuarterword)
- w.b3 = byte(int32(prg.strPool[k+3]) + minQuarterword)
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq() = w
- prg.fmtFile.Put()
- }
- k = k + 4
- }
- k = int32(prg.poolPtr) - 4
- w.b0 = byte(int32(prg.strPool[k]) + minQuarterword)
- w.b1 = byte(int32(prg.strPool[k+1]) + minQuarterword)
- w.b2 = byte(int32(prg.strPool[k+2]) + minQuarterword)
- w.b3 = byte(int32(prg.strPool[k+3]) + minQuarterword)
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq() = w
- prg.fmtFile.Put()
- }
- prg.printLn()
- prg.printInt(int32(prg.strPtr))
- prg.print( /* " strings of total length " */ 1260)
- prg.printInt(int32(prg.poolPtr))
- // Dump the dynamic memory
- prg.sortAvail()
- prg.varUsed = 0
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.loMemMax)
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.rover)
- prg.fmtFile.Put()
- }
- p = uint16(memBot)
- q = prg.rover
- x = 0
- for {
- for ii := int32(p); ii <= int32(q)+1; ii++ {
- k = ii
- _ = k
- *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.mem[k]
- prg.fmtFile.Put()
- }
- x = x + int32(q) + 2 - int32(p)
- prg.varUsed = prg.varUsed + int32(q) - int32(p)
- p = uint16(int32(q) + int32(*(*prg.mem[q].hh()).lh()))
- q = *(*prg.mem[int32(q)+1].hh()).rh()
- if int32(q) == int32(prg.rover) {
- break
- }
- }
- prg.varUsed = prg.varUsed + int32(prg.loMemMax) - int32(p)
- prg.dynUsed = int32(prg.memEnd) + 1 - int32(prg.hiMemMin)
- for ii := int32(p); ii <= int32(prg.loMemMax); ii++ {
- k = ii
- _ = k
- *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.mem[k]
- prg.fmtFile.Put()
- }
- x = x + int32(prg.loMemMax) + 1 - int32(p)
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hiMemMin)
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.avail)
- prg.fmtFile.Put()
- }
- for ii := int32(prg.hiMemMin); ii <= int32(prg.memEnd); ii++ {
- k = ii
- _ = k
- *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.mem[k]
- prg.fmtFile.Put()
- }
- x = x + int32(prg.memEnd) + 1 - int32(prg.hiMemMin)
- p = prg.avail
- for int32(p) != 0 {
- prg.dynUsed = prg.dynUsed - 1
- p = *(*prg.mem[p].hh()).rh()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.varUsed
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.dynUsed
- prg.fmtFile.Put()
- }
- prg.printLn()
- prg.printInt(x)
- prg.print( /* " memory locations dumped; current usage is " */ 1261)
- prg.printInt(prg.varUsed)
- prg.printChar(asciiCode('&'))
- prg.printInt(prg.dynUsed)
- // Dump the table of equivalents
- // Dump regions 1 to 4 of |eqtb|
- k = activeBase
- for {
- j = k
- for j < intBase-1 {
- if int32(*(*prg.eqtb[j-1].hh()).rh()) == int32(*(*prg.eqtb[j+1-1].hh()).rh()) && int32(*(*prg.eqtb[j-1].hh()).b0()) == int32(*(*prg.eqtb[j+1-1].hh()).b0()) && int32(*(*prg.eqtb[j-1].hh()).b1()) == int32(*(*prg.eqtb[j+1-1].hh()).b1()) {
- goto found1
- }
- j = j + 1
- }
- l = intBase
- goto done1 // |j=int_base-1|
- // |j=int_base-1|
- found1:
- j = j + 1
- l = j
- for j < intBase-1 {
- if int32(*(*prg.eqtb[j-1].hh()).rh()) != int32(*(*prg.eqtb[j+1-1].hh()).rh()) || int32(*(*prg.eqtb[j-1].hh()).b0()) != int32(*(*prg.eqtb[j+1-1].hh()).b0()) || int32(*(*prg.eqtb[j-1].hh()).b1()) != int32(*(*prg.eqtb[j+1-1].hh()).b1()) {
- goto done1
- }
- j = j + 1
- }
- done1:
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = l - k
- prg.fmtFile.Put()
- }
- for k < l {
- {
- *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.eqtb[k-1]
- prg.fmtFile.Put()
- }
- k = k + 1
- }
- k = j + 1
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = k - l
- prg.fmtFile.Put()
- }
- if k == intBase {
- break
- }
- }
- // Dump regions 5 and 6 of |eqtb|
- for {
- j = k
- for j < eqtbSize {
- if *prg.eqtb[j-1].int() == *prg.eqtb[j+1-1].int() {
- goto found2
- }
- j = j + 1
- }
- l = eqtbSize + 1
- goto done2 // |j=eqtb_size|
- // |j=eqtb_size|
- found2:
- j = j + 1
- l = j
- for j < eqtbSize {
- if *prg.eqtb[j-1].int() != *prg.eqtb[j+1-1].int() {
- goto done2
- }
- j = j + 1
- }
- done2:
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = l - k
- prg.fmtFile.Put()
- }
- for k < l {
- {
- *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.eqtb[k-1]
- prg.fmtFile.Put()
- }
- k = k + 1
- }
- k = j + 1
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = k - l
- prg.fmtFile.Put()
- }
- if k > eqtbSize {
- break
- }
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.parLoc)
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.writeLoc)
- prg.fmtFile.Put()
- }
- // Dump the hash table
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hashUsed)
- prg.fmtFile.Put()
- }
- prg.csCount = frozenControlSequence - 1 - int32(prg.hashUsed)
- for ii := int32(hashBase); ii <= int32(prg.hashUsed); ii++ {
- p = halfword(ii)
- _ = p
- if int32(*prg.hash[p-514].rh()) != 0 {
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(p)
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh() = prg.hash[p-514]
- prg.fmtFile.Put()
- }
- prg.csCount = prg.csCount + 1
- }
- }
- for ii := int32(prg.hashUsed) + 1; ii <= undefinedControlSequence-1; ii++ {
- p = halfword(ii)
- _ = p
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh() = prg.hash[p-514]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.csCount
- prg.fmtFile.Put()
- }
- prg.printLn()
- prg.printInt(prg.csCount)
- prg.print( /* " multiletter control sequences" */ 1262)
- // Dump the font information
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fmemPtr)
- prg.fmtFile.Put()
- }
- for ii := int32(0); ii <= int32(prg.fmemPtr)-1; ii++ {
- k = ii
- _ = k
- *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P())) = prg.fontInfo[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontPtr)
- prg.fmtFile.Put()
- }
- for ii := int32(fontBase); ii <= int32(prg.fontPtr); ii++ {
- k = ii
- _ = k
- // Dump the array info for internal font number |k|
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq() = prg.fontCheck[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.fontSize[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.fontDsize[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontParams[k])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.hyphenChar[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.skewChar[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontName[k])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontArea[k])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontBc[k])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontEc[k])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.charBase[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.widthBase[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.heightBase[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.depthBase[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.italicBase[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.ligKernBase[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.kernBase[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.extenBase[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = prg.paramBase[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontGlue[k])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.bcharLabel[k])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontBchar[k])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.fontFalseBchar[k])
- prg.fmtFile.Put()
- }
- prg.printNl(strNumber( /* "\\font" */ 1265))
- prg.printEsc(*prg.hash[fontIdBase+k-514].rh())
- prg.printChar(asciiCode('='))
- prg.printFileName(int32(prg.fontName[k]), int32(prg.fontArea[k]) /* "" */, 338)
- if prg.fontSize[k] != prg.fontDsize[k] {
- prg.print( /* " at " */ 741)
- prg.printScaled(prg.fontSize[k])
- prg.print( /* "pt" */ 397)
- }
- }
- prg.printLn()
- prg.printInt(int32(prg.fmemPtr) - 7)
- prg.print( /* " words of font info for " */ 1263)
- prg.printInt(int32(prg.fontPtr) - fontBase)
- prg.print( /* " preloaded font" */ 1264)
- if int32(prg.fontPtr) != fontBase+1 {
- prg.printChar(asciiCode('s'))
- }
- // Dump the hyphenation tables
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyphCount)
- prg.fmtFile.Put()
- }
- for ii := int32(0); ii <= hyphSize; ii++ {
- k = ii
- _ = k
- if int32(prg.hyphWord[k]) != 0 {
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = k
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyphWord[k])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyphList[k])
- prg.fmtFile.Put()
- }
- }
- }
- prg.printLn()
- prg.printInt(int32(prg.hyphCount))
- prg.print( /* " hyphenation exception" */ 1266)
- if int32(prg.hyphCount) != 1 {
- prg.printChar(asciiCode('s'))
- }
- if prg.trieNotReady {
- prg.initTrie()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.trieMax)
- prg.fmtFile.Put()
- }
- for ii := int32(0); ii <= int32(prg.trieMax); ii++ {
- k = ii
- _ = k
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh() = prg.trie[k]
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.trieOpPtr)
- prg.fmtFile.Put()
- }
- for ii := int32(1); ii <= int32(prg.trieOpPtr); ii++ {
- k = ii
- _ = k
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyfDistance[k-1])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyfNum[k-1])
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.hyfNext[k-1])
- prg.fmtFile.Put()
- }
- }
- prg.printNl(strNumber( /* "Hyphenation trie of length " */ 1267))
- prg.printInt(int32(prg.trieMax))
- // \xref[Hyphenation trie...]
- prg.print( /* " has " */ 1268)
- prg.printInt(int32(prg.trieOpPtr))
- prg.print( /* " op" */ 1269)
- if int32(prg.trieOpPtr) != 1 {
- prg.printChar(asciiCode('s'))
- }
- prg.print( /* " out of " */ 1270)
- prg.printInt(trieOpSize)
- for ii := int32(255); ii >= 0; ii-- {
- k = ii
- _ = k
- if int32(prg.trieUsed[k]) > minQuarterword {
- prg.printNl(strNumber( /* " " */ 800))
- prg.printInt(int32(prg.trieUsed[k]) - minQuarterword)
- prg.print( /* " for language " */ 1271)
- prg.printInt(k)
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = k
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.trieUsed[k]) - minQuarterword
- prg.fmtFile.Put()
- }
- }
- }
- // Dump a couple more things and the closing check word
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.interaction)
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = int32(prg.formatIdent)
- prg.fmtFile.Put()
- }
- {
- *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int() = 69069
- prg.fmtFile.Put()
- }
- *prg.eqtb[intBase+tracingStatsCode-1].int() = 0
- // Close the format file
- prg.wClose(prg.fmtFile)
- }
- // \4
- // Declare procedures needed in |do_extension|
- func (prg *prg) newWhatsit(s smallNumber, w smallNumber) {
- var (
- p halfword // the new node
- )
- p = prg.getNode(int32(w))
- *(*prg.mem[p].hh()).b0() = byte(whatsitNode)
- *(*prg.mem[p].hh()).b1() = s
- *(*prg.mem[prg.curList.tailField].hh()).rh() = p
- prg.curList.tailField = p
- }
- func (prg *prg) newWriteWhatsit(w smallNumber) {
- prg.newWhatsit(smallNumber(prg.curChr), w)
- if int32(w) != writeNodeSize {
- prg.scanFourBitInt()
- } else {
- prg.scanInt()
- if prg.curVal < 0 {
- prg.curVal = 17
- } else if prg.curVal > 15 {
- prg.curVal = 16
- }
- }
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = uint16(prg.curVal)
- }
- func (prg *prg) doExtension() {
- var (
- k int32 // all-purpose integers
- p halfword // all-purpose pointers
- )
- switch prg.curChr {
- case openNode:
- // Implement \.[\\openout]
- prg.newWriteWhatsit(smallNumber(openNodeSize))
- prg.scanOptionalEquals()
- prg.scanFileName()
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = prg.curName
- *(*prg.mem[int32(prg.curList.tailField)+2].hh()).lh() = prg.curArea
- *(*prg.mem[int32(prg.curList.tailField)+2].hh()).rh() = prg.curExt
- case writeNode:
- // Implement \.[\\write]
- k = int32(prg.curCs)
- prg.newWriteWhatsit(smallNumber(writeNodeSize))
- prg.curCs = uint16(k)
- p = prg.scanToks(false, false)
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = prg.defRef
- case closeNode:
- // Implement \.[\\closeout]
- prg.newWriteWhatsit(smallNumber(writeNodeSize))
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = 0
- case specialNode:
- // Implement \.[\\special]
- prg.newWhatsit(smallNumber(specialNode), smallNumber(writeNodeSize))
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = 0
- p = prg.scanToks(false, true)
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = prg.defRef
- case immediateCode:
- // Implement \.[\\immediate]
- prg.getXToken()
- if int32(prg.curCmd) == extension && int32(prg.curChr) <= closeNode {
- p = prg.curList.tailField
- prg.doExtension() // append a whatsit node
- prg.outWhat(prg.curList.tailField) // do the action immediately
- prg.flushNodeList(prg.curList.tailField)
- prg.curList.tailField = p
- *(*prg.mem[p].hh()).rh() = 0
- } else {
- prg.backInput()
- }
- case setLanguageCode:
- // Implement \.[\\setlanguage]
- if abs(int32(prg.curList.modeField)) != hmode {
- prg.reportIllegalCase()
- } else {
- prg.newWhatsit(smallNumber(languageNode), smallNumber(smallNodeSize))
- prg.scanInt()
- if prg.curVal <= 0 {
- *(*prg.curList.auxField.hh()).rh() = 0
- } else if prg.curVal > 255 {
- *(*prg.curList.auxField.hh()).rh() = 0
- } else {
- *(*prg.curList.auxField.hh()).rh() = uint16(prg.curVal)
- }
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = *(*prg.curList.auxField.hh()).rh()
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).b0() = prg.normMin(*prg.eqtb[intBase+leftHyphenMinCode-1].int())
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).b1() = prg.normMin(*prg.eqtb[intBase+rightHyphenMinCode-1].int())
- }
- default:
- prg.confusion(strNumber( /* "ext1" */ 1291))
- // \xref[this can't happen ext1][\quad ext1]
- }
- }
- func (prg *prg) fixLanguage() {
- var (
- l asciiCode // the new current language
- )
- if *prg.eqtb[intBase+languageCode-1].int() <= 0 {
- l = 0
- } else if *prg.eqtb[intBase+languageCode-1].int() > 255 {
- l = 0
- } else {
- l = byte(*prg.eqtb[intBase+languageCode-1].int())
- }
- if int32(l) != int32(*(*prg.curList.auxField.hh()).rh()) {
- prg.newWhatsit(smallNumber(languageNode), smallNumber(smallNodeSize))
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = uint16(l)
- *(*prg.curList.auxField.hh()).rh() = uint16(l)
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).b0() = prg.normMin(*prg.eqtb[intBase+leftHyphenMinCode-1].int())
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).b1() = prg.normMin(*prg.eqtb[intBase+rightHyphenMinCode-1].int())
- }
- }
- // \4
- // Declare the procedure called |handle_right_brace|
- func (prg *prg) handleRightBrace() {
- var (
- p, q halfword // for short-term use
- d scaled // holds |split_max_depth| in |insert_group|
- f int32 // holds |floating_penalty| in |insert_group|
- )
- switch prg.curGroup {
- case simpleGroup:
- prg.unsave()
- case bottomLevel:
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Too many ]'s" */ 1044)
- }
- // \xref[Too many \]'s]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "You've closed more groups than you opened." */ 1045
- prg.helpLine[0] = /* "Such booboos are generally harmless, so keep going." */ 1046
- }
- prg.error1()
- case semiSimpleGroup, mathShiftGroup, mathLeftGroup:
- prg.extraRightBrace()
- // \4
- // Cases of |handle_right_brace| where a |right_brace| triggers a delayed action
- case hboxGroup:
- prg.package1(smallNumber(0))
- case adjustedHboxGroup:
- prg.adjustTail = uint16(30000 - 5)
- prg.package1(smallNumber(0))
- case vboxGroup:
- prg.endGraf()
- prg.package1(smallNumber(0))
- case vtopGroup:
- prg.endGraf()
- prg.package1(smallNumber(vtopCode))
- case insertGroup:
- prg.endGraf()
- q = *(*prg.eqtb[glueBase+splitTopSkipCode-1].hh()).rh()
- *(*prg.mem[q].hh()).rh() = uint16(int32(*(*prg.mem[q].hh()).rh()) + 1)
- d = *prg.eqtb[dimenBase+splitMaxDepthCode-1].int()
- f = *prg.eqtb[intBase+floatingPenaltyCode-1].int()
- prg.unsave()
- prg.savePtr = uint16(int32(prg.savePtr) - 1)
- // now |saved(0)| is the insertion number, or 255 for |vadjust|
- p = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), scaled(0), smallNumber(additional), scaled(07777777777))
- prg.popNest()
- if *prg.saveStack[int32(prg.savePtr)+0].int() < 255 {
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.getNode(insNodeSize)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b0() = byte(insNode)
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(*prg.saveStack[int32(prg.savePtr)+0].int() + minQuarterword)
- *prg.mem[int32(prg.curList.tailField)+heightOffset].int() = *prg.mem[int32(p)+heightOffset].int() + *prg.mem[int32(p)+depthOffset].int()
- *(*prg.mem[int32(prg.curList.tailField)+4].hh()).lh() = *(*prg.mem[int32(p)+listOffset].hh()).rh()
- *(*prg.mem[int32(prg.curList.tailField)+4].hh()).rh() = q
- *prg.mem[int32(prg.curList.tailField)+depthOffset].int() = d
- *prg.mem[int32(prg.curList.tailField)+1].int() = f
- } else {
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.getNode(smallNodeSize)
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b0() = byte(adjustNode)
- *(*prg.mem[prg.curList.tailField].hh()).b1() = 0 // the |subtype| is not used
- *prg.mem[int32(prg.curList.tailField)+1].int() = int32(*(*prg.mem[int32(p)+listOffset].hh()).rh())
- prg.deleteGlueRef(q)
- }
- prg.freeNode(p, halfword(boxNodeSize))
- if int32(prg.nestPtr) == 0 {
- prg.buildPage()
- }
- case outputGroup:
- // Resume the page builder...
- if int32(prg.curInput.locField) != 0 || int32(prg.curInput.indexField) != outputText && int32(prg.curInput.indexField) != backedUp {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Unbalanced output routine" */ 1010)
- }
- // \xref[Unbalanced output routine]
- {
- prg.helpPtr = 2
- prg.helpLine[1] = /* "Your sneaky output routine has problematic ['s and/or ]'s." */ 1011
- prg.helpLine[0] = /* "I can't handle that very well; good luck." */ 1012
- }
- prg.error1()
- for {
- prg.getToken()
- if int32(prg.curInput.locField) == 0 {
- break
- }
- }
- }
- prg.endTokenList() // conserve stack space in case more outputs are triggered
- prg.endGraf()
- prg.unsave()
- prg.outputActive = false
- prg.insertPenalties = 0
- // Ensure that box 255 is empty after output
- if int32(*(*prg.eqtb[boxBase+255-1].hh()).rh()) != 0 {
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Output routine didn't use all of " */ 1013)
- }
- prg.printEsc(strNumber( /* "box" */ 409))
- prg.printInt(255)
- // \xref[Output routine didn't use...]
- {
- prg.helpPtr = 3
- prg.helpLine[2] = /* "Your \\output commands should empty \\box255," */ 1014
- prg.helpLine[1] = /* "e.g., by saying `\\shipout\\box255'." */ 1015
- prg.helpLine[0] = /* "Proceed; I'll discard its present contents." */ 1016
- }
- prg.boxError(eightBits(255))
- }
- if int32(prg.curList.tailField) != int32(prg.curList.headField) {
- *(*prg.mem[prg.pageTail].hh()).rh() = *(*prg.mem[prg.curList.headField].hh()).rh()
- prg.pageTail = prg.curList.tailField
- }
- if int32(*(*prg.mem[30000-2].hh()).rh()) != 0 {
- if int32(*(*prg.mem[30000-1].hh()).rh()) == 0 {
- prg.nest[0].tailField = prg.pageTail
- }
- *(*prg.mem[prg.pageTail].hh()).rh() = *(*prg.mem[30000-1].hh()).rh()
- *(*prg.mem[30000-1].hh()).rh() = *(*prg.mem[30000-2].hh()).rh()
- *(*prg.mem[30000-2].hh()).rh() = 0
- prg.pageTail = uint16(30000 - 2)
- }
- prg.popNest()
- prg.buildPage()
- case discGroup:
- prg.buildDiscretionary()
- case alignGroup:
- prg.backInput()
- prg.curTok = uint16(07777 + frozenCr)
- {
- if int32(prg.interaction) == errorStopMode {
- }
- prg.printNl(strNumber( /* "! " */ 262))
- prg.print( /* "Missing " */ 625)
- }
- prg.printEsc(strNumber( /* "cr" */ 899))
- prg.print( /* " inserted" */ 626)
- // \xref[Missing \\cr inserted]
- {
- prg.helpPtr = 1
- prg.helpLine[0] = /* "I'm guessing that you meant to end an alignment here." */ 1125
- }
- prg.insError()
- case noAlignGroup:
- prg.endGraf()
- prg.unsave()
- prg.alignPeek()
- case vcenterGroup:
- prg.endGraf()
- prg.unsave()
- prg.savePtr = uint16(int32(prg.savePtr) - 2)
- p = prg.vpackage(*(*prg.mem[prg.curList.headField].hh()).rh(), *prg.saveStack[int32(prg.savePtr)+1].int(), smallNumber(*prg.saveStack[int32(prg.savePtr)+0].int()), scaled(07777777777))
- prg.popNest()
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b0() = byte(vcenterNoad)
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).rh() = uint16(subBox)
- *(*prg.mem[int32(prg.curList.tailField)+1].hh()).lh() = p
- case mathChoiceGroup:
- prg.buildChoices()
- case mathGroup:
- prg.unsave()
- prg.savePtr = uint16(int32(prg.savePtr) - 1)
- *(*prg.mem[*prg.saveStack[int32(prg.savePtr)+0].int()].hh()).rh() = uint16(subMlist)
- p = prg.finMlist(halfword(0))
- *(*prg.mem[*prg.saveStack[int32(prg.savePtr)+0].int()].hh()).lh() = p
- if int32(p) != 0 {
- if int32(*(*prg.mem[p].hh()).rh()) == 0 {
- if int32(*(*prg.mem[p].hh()).b0()) == ordNoad {
- if int32(*(*prg.mem[int32(p)+3].hh()).rh()) == empty {
- if int32(*(*prg.mem[int32(p)+2].hh()).rh()) == empty {
- *prg.mem[*prg.saveStack[int32(prg.savePtr)+0].int()].hh() = *prg.mem[int32(p)+1].hh()
- prg.freeNode(p, halfword(noadSize))
- }
- }
- } else if int32(*(*prg.mem[p].hh()).b0()) == accentNoad {
- if *prg.saveStack[int32(prg.savePtr)+0].int() == int32(prg.curList.tailField)+1 {
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b0()) == ordNoad {
- q = prg.curList.headField
- for int32(*(*prg.mem[q].hh()).rh()) != int32(prg.curList.tailField) {
- q = *(*prg.mem[q].hh()).rh()
- }
- *(*prg.mem[q].hh()).rh() = p
- prg.freeNode(prg.curList.tailField, halfword(noadSize))
- prg.curList.tailField = p
- }
- }
- }
- }
- }
- default:
- prg.confusion(strNumber( /* "rightbrace" */ 1047))
- // \xref[this can't happen rightbrace][\quad rightbrace]
- }
- }
- func (prg *prg) mainControl() {
- var (
- t int32 // general-purpose temporary variable
- )
- if int32(*(*prg.eqtb[everyJobLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyJobLoc-1].hh()).rh(), quarterword(everyJobText))
- }
- bigSwitch:
- prg.getXToken()
- reswitch:
- if prg.interrupt != 0 {
- if prg.okToInterrupt {
- prg.backInput()
- {
- if prg.interrupt != 0 {
- prg.pauseForInstructions()
- }
- }
- goto bigSwitch
- }
- }
- // if panicking then check_mem(false); [ ]
- if *prg.eqtb[intBase+tracingCommandsCode-1].int() > 0 {
- prg.showCurCmdChr()
- }
- switch abs(int32(prg.curList.modeField)) + int32(prg.curCmd) {
- case hmode + 11, hmode + 12, hmode + 68:
- goto mainLoop
- case hmode + 16:
- prg.scanCharNum()
- prg.curChr = uint16(prg.curVal)
- goto mainLoop
- case hmode + 65:
- prg.getXToken()
- if int32(prg.curCmd) == letter || int32(prg.curCmd) == otherChar || int32(prg.curCmd) == charGiven || int32(prg.curCmd) == charNum {
- prg.cancelBoundary = true
- }
- goto reswitch
- case hmode + 10:
- if int32(*(*prg.curList.auxField.hh()).lh()) == 1000 {
- goto appendNormalSpace
- } else {
- prg.appSpace()
- }
- case hmode + 64, mmode + 64:
- goto appendNormalSpace
- // \4
- // Cases of |main_control| that are not part of the inner loop
- case vmode + 0, hmode + 0, mmode + 0, vmode + 10,
- mmode + 10, mmode + 65:
- case vmode + 39, hmode + 39, mmode + 39:
- for {
- prg.getXToken()
- if int32(prg.curCmd) != spacer {
- break
- }
- }
- goto reswitch
- case vmode + 14:
- if prg.itsAllOver() {
- goto exit
- } // this is the only way out
- // \4
- // Forbidden cases detected in |main_control|
- case vmode + 22, hmode + 21, mmode + 21, vmode + 70,
- hmode + 70, mmode + 70, vmode + 38, vmode + 44,
- vmode + 48, hmode + 48, vmode + 6, hmode + 6,
- mmode + 6:
- prg.reportIllegalCase()
- // Math-only cases in non-math modes, or vice versa
- case vmode + 7, hmode + 7, vmode + 8, hmode + 8,
- vmode + 17, hmode + 17, vmode + 69, hmode + 69,
- vmode + 50, hmode + 50, vmode + 15, hmode + 15,
- vmode + 49, hmode + 49, vmode + 52, hmode + 52,
- vmode + 66, hmode + 66, vmode + 53, hmode + 53,
- vmode + 54, hmode + 54, vmode + 56, hmode + 56,
- vmode + 55, hmode + 55, vmode + 30, hmode + 30,
- vmode + 51, hmode + 51, vmode + 28, hmode + 28,
- vmode + 46, hmode + 46, mmode + 9, mmode + 13,
- mmode + 14, mmode + 27, mmode + 24, mmode + 33,
- mmode + 36:
- prg.insertDollarSign()
- // \4
- // Cases of |main_control| that build boxes and lists
- case vmode + 36, hmode + 35, mmode + 35:
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.scanRuleSpec()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- if abs(int32(prg.curList.modeField)) == vmode {
- *prg.curList.auxField.int() = -65536000
- } else if abs(int32(prg.curList.modeField)) == hmode {
- *(*prg.curList.auxField.hh()).lh() = 1000
- }
- case vmode + 27, hmode + 26, mmode + 26, mmode + 28:
- prg.appendGlue()
- case vmode + 29, hmode + 29, mmode + 29, mmode + 30:
- prg.appendKern()
- case vmode + 1, hmode + 1:
- prg.newSaveLevel(groupCode(simpleGroup))
- case vmode + 61, hmode + 61, mmode + 61:
- prg.newSaveLevel(groupCode(semiSimpleGroup))
- case vmode + 62, hmode + 62, mmode + 62:
- if int32(prg.curGroup) == semiSimpleGroup {
- prg.unsave()
- } else {
- prg.offSave()
- }
- case vmode + 2, hmode + 2, mmode + 2:
- prg.handleRightBrace()
- case vmode + 21, hmode + 22, mmode + 22:
- t = int32(prg.curChr)
- prg.scanDimen(false, false, false)
- if t == 0 {
- prg.scanBox(prg.curVal)
- } else {
- prg.scanBox(-prg.curVal)
- }
- case vmode + 31, hmode + 31, mmode + 31:
- prg.scanBox(010000000000 + 513 - aLeaders + int32(prg.curChr))
- case vmode + 20, hmode + 20, mmode + 20:
- prg.beginBox(0)
- case vmode + 43:
- prg.newGraf(int32(prg.curChr) > 0)
- case vmode + 11, vmode + 12, vmode + 16, vmode + 68,
- vmode + 3, vmode + 23, vmode + 35, vmode + 45,
- vmode + 47, vmode + 26, vmode + 33, vmode + 64,
- vmode + 65: //
- prg.backInput()
- prg.newGraf(true)
- case hmode + 43, mmode + 43:
- prg.indentInHmode()
- case vmode + 13:
- prg.normalParagraph()
- if int32(prg.curList.modeField) > 0 {
- prg.buildPage()
- }
- case hmode + 13:
- if prg.alignState < 0 {
- prg.offSave()
- } // this tries to
- // recover from an alignment that didn't end properly
- prg.endGraf() // this takes us to the enclosing mode, if |mode>0|
- if int32(prg.curList.modeField) == vmode {
- prg.buildPage()
- }
- case hmode + 14, hmode + 27, hmode + 36, hmode + 24,
- hmode + 32:
- prg.headForVmode()
- case vmode + 37, hmode + 37, mmode + 37, hmode + 38,
- mmode + 38:
- prg.beginInsertOrAdjust()
- case vmode + 18, hmode + 18, mmode + 18:
- prg.makeMark()
- case vmode + 42, hmode + 42, mmode + 42:
- prg.appendPenalty()
- case vmode + 25, hmode + 25, mmode + 25:
- prg.deleteLast()
- case vmode + 24, hmode + 23, mmode + 23:
- prg.unpackage()
- case hmode + 44:
- prg.appendItalicCorrection()
- case mmode + 44:
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newKern(scaled(0))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- case hmode + 47, mmode + 47:
- prg.appendDiscretionary()
- case hmode + 45:
- prg.makeAccent()
- case vmode + 5, hmode + 5, mmode + 5, vmode + 4,
- hmode + 4, mmode + 4:
- prg.alignError()
- case vmode + 34, hmode + 34, mmode + 34:
- prg.noAlignError()
- case vmode + 63, hmode + 63, mmode + 63:
- prg.omitError()
- case vmode + 32, hmode + 33:
- prg.initAlign()
- case mmode + 32:
- if prg.privileged() {
- if int32(prg.curGroup) == mathShiftGroup {
- prg.initAlign()
- } else {
- prg.offSave()
- }
- }
- case vmode + 9, hmode + 9:
- prg.doEndv()
- case vmode + 67, hmode + 67, mmode + 67:
- prg.csError()
- case hmode + 3:
- prg.initMath()
- case mmode + 48:
- if prg.privileged() {
- if int32(prg.curGroup) == mathShiftGroup {
- prg.startEqNo()
- } else {
- prg.offSave()
- }
- }
- case mmode + 1:
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- prg.backInput()
- prg.scanMath(halfword(int32(prg.curList.tailField) + 1))
- case mmode + 11, mmode + 12, mmode + 68:
- prg.setMathChar(int32(*(*prg.eqtb[mathCodeBase+int32(prg.curChr)-1].hh()).rh()) - 0)
- case mmode + 16:
- prg.scanCharNum()
- prg.curChr = uint16(prg.curVal)
- prg.setMathChar(int32(*(*prg.eqtb[mathCodeBase+int32(prg.curChr)-1].hh()).rh()) - 0)
- case mmode + 17:
- prg.scanFifteenBitInt()
- prg.setMathChar(prg.curVal)
- case mmode + 69:
- prg.setMathChar(int32(prg.curChr))
- case mmode + 15:
- prg.scanTwentySevenBitInt()
- prg.setMathChar(prg.curVal / 010000)
- case mmode + 50:
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newNoad()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b0() = byte(prg.curChr)
- prg.scanMath(halfword(int32(prg.curList.tailField) + 1))
- case mmode + 51:
- prg.mathLimitSwitch()
- case mmode + 66:
- prg.mathRadical()
- case mmode + 45, mmode + 46:
- prg.mathAc()
- case mmode + 56:
- prg.scanSpec(groupCode(vcenterGroup), false)
- prg.normalParagraph()
- prg.pushNest()
- prg.curList.modeField = int16(-vmode)
- *prg.curList.auxField.int() = -65536000
- if int32(*(*prg.eqtb[everyVboxLoc-1].hh()).rh()) != 0 {
- prg.beginTokenList(*(*prg.eqtb[everyVboxLoc-1].hh()).rh(), quarterword(everyVboxText))
- }
- case mmode + 53:
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newStyle(smallNumber(prg.curChr))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- case mmode + 55:
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newGlue(halfword(memBot))
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- *(*prg.mem[prg.curList.tailField].hh()).b1() = byte(condMathGlue)
- case mmode + 54:
- prg.appendChoices()
- case mmode + 8, mmode + 7:
- prg.subSup()
- case mmode + 52:
- prg.mathFraction()
- case mmode + 49:
- prg.mathLeftRight()
- case mmode + 3:
- if int32(prg.curGroup) == mathShiftGroup {
- prg.afterMath()
- } else {
- prg.offSave()
- }
- // \4
- // Cases of |main_control| that don't depend on |mode|
- case vmode + 71, hmode + 71, mmode + 71, vmode + 72,
- hmode + 72, mmode + 72, vmode + 73, hmode + 73,
- mmode + 73, vmode + 74, hmode + 74, mmode + 74,
- vmode + 75, hmode + 75, mmode + 75, vmode + 76,
- hmode + 76, mmode + 76, vmode + 77, hmode + 77,
- mmode + 77, vmode + 78, hmode + 78, mmode + 78,
- vmode + 79, hmode + 79, mmode + 79, vmode + 80,
- hmode + 80, mmode + 80, vmode + 81, hmode + 81,
- mmode + 81, vmode + 82, hmode + 82, mmode + 82,
- vmode + 83, hmode + 83, mmode + 83, vmode + 84,
- hmode + 84, mmode + 84, vmode + 85, hmode + 85,
- mmode + 85, vmode + 86, hmode + 86, mmode + 86,
- vmode + 87, hmode + 87, mmode + 87, vmode + 88,
- hmode + 88, mmode + 88, vmode + 89, hmode + 89,
- mmode + 89, vmode + 90, hmode + 90, mmode + 90,
- vmode + 91, hmode + 91, mmode + 91, vmode + 92,
- hmode + 92, mmode + 92, vmode + 93, hmode + 93,
- mmode + 93, vmode + 94, hmode + 94, mmode + 94,
- vmode + 95, hmode + 95, mmode + 95, vmode + 96,
- hmode + 96, mmode + 96, vmode + 97, hmode + 97,
- mmode + 97, vmode + 98, hmode + 98, mmode + 98,
- vmode + 99, hmode + 99, mmode + 99, vmode + 100,
- hmode + 100, mmode + 100:
- prg.prefixedCommand()
- case vmode + 40, hmode + 40, mmode + 40:
- prg.getToken()
- prg.afterToken = prg.curTok
- case vmode + 41, hmode + 41, mmode + 41:
- prg.getToken()
- prg.saveForAfter(prg.curTok)
- case vmode + 60, hmode + 60, mmode + 60:
- prg.openOrCloseIn()
- case vmode + 58, hmode + 58, mmode + 58:
- prg.issueMessage()
- case vmode + 57, hmode + 57, mmode + 57:
- prg.shiftCase()
- case vmode + 19, hmode + 19, mmode + 19:
- prg.showWhatever()
- // \4
- // Cases of |main_control| that are for extensions to \TeX
- case vmode + 59, hmode + 59, mmode + 59:
- prg.doExtension()
- } // of the big |case| statement
- // of the big |case| statement
- goto bigSwitch
- mainLoop:
- prg.mainS = int32(*(*prg.eqtb[sfCodeBase+int32(prg.curChr)-1].hh()).rh())
- if prg.mainS == 1000 {
- *(*prg.curList.auxField.hh()).lh() = 1000
- } else if prg.mainS < 1000 {
- if prg.mainS > 0 {
- *(*prg.curList.auxField.hh()).lh() = uint16(prg.mainS)
- }
- } else if int32(*(*prg.curList.auxField.hh()).lh()) < 1000 {
- *(*prg.curList.auxField.hh()).lh() = 1000
- } else {
- *(*prg.curList.auxField.hh()).lh() = uint16(prg.mainS)
- }
- prg.mainF = byte(*(*prg.eqtb[curFontLoc-1].hh()).rh())
- prg.bchar = prg.fontBchar[prg.mainF]
- prg.falseBchar = prg.fontFalseBchar[prg.mainF]
- if int32(prg.curList.modeField) > 0 {
- if *prg.eqtb[intBase+languageCode-1].int() != int32(*(*prg.curList.auxField.hh()).rh()) {
- prg.fixLanguage()
- }
- }
- /* */ {
- prg.ligStack = prg.avail
- if int32(prg.ligStack) == 0 {
- prg.ligStack = prg.getAvail()
- } else {
- prg.avail = *(*prg.mem[prg.ligStack].hh()).rh()
- *(*prg.mem[prg.ligStack].hh()).rh() = 0 /* dyn_used:= dyn_used+1 ; [ ] */
- }
- }
- *(*prg.mem[prg.ligStack].hh()).b0() = prg.mainF
- prg.curL = uint16(int32(prg.curChr) + minQuarterword)
- *(*prg.mem[prg.ligStack].hh()).b1() = byte(prg.curL)
- prg.curQ = prg.curList.tailField
- if prg.cancelBoundary {
- prg.cancelBoundary = false
- prg.mainK = uint16(nonAddress)
- } else {
- prg.mainK = prg.bcharLabel[prg.mainF]
- }
- if int32(prg.mainK) == nonAddress {
- goto mainLoopMove_plus_2
- } // no left boundary processing
- prg.curR = prg.curL
- prg.curL = uint16(256 + minQuarterword)
- goto mainLigLoop_plus_1 // begin with cursor after left boundary
- // begin with cursor after left boundary
- mainLoopWrapup:
- if int32(prg.curL) < 256+minQuarterword {
- if int32(*(*prg.mem[prg.curQ].hh()).rh()) > 0 {
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b1()) == prg.hyphenChar[prg.mainF]+minQuarterword {
- prg.insDisc = true
- }
- }
- if prg.ligaturePresent {
- prg.mainP = prg.newLigature(prg.mainF, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
- if prg.lftHit {
- *(*prg.mem[prg.mainP].hh()).b1() = 2
- prg.lftHit = false
- }
- if prg.rtHit {
- if int32(prg.ligStack) == 0 {
- *(*prg.mem[prg.mainP].hh()).b1() = byte(int32(*(*prg.mem[prg.mainP].hh()).b1()) + 1)
- prg.rtHit = false
- }
- }
- *(*prg.mem[prg.curQ].hh()).rh() = prg.mainP
- prg.curList.tailField = prg.mainP
- prg.ligaturePresent = false
- }
- if prg.insDisc {
- prg.insDisc = false
- if int32(prg.curList.modeField) > 0 {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newDisc()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- }
- }
- mainLoopMove:
- if int32(prg.ligStack) == 0 {
- goto reswitch
- }
- prg.curQ = prg.curList.tailField
- prg.curL = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
- mainLoopMove_plus_1:
- if !(int32(prg.ligStack) >= int32(prg.hiMemMin)) {
- goto mainLoopMoveLig
- }
- mainLoopMove_plus_2:
- if int32(prg.curChr) < int32(prg.fontBc[prg.mainF]) || int32(prg.curChr) > int32(prg.fontEc[prg.mainF]) {
- prg.charWarning(prg.mainF, eightBits(prg.curChr))
- {
- *(*prg.mem[prg.ligStack].hh()).rh() = prg.avail
- prg.avail = prg.ligStack /* dyn_used:= dyn_used-1 ; [ ] */
- }
- goto bigSwitch
- }
- prg.mainI = *prg.fontInfo[prg.charBase[prg.mainF]+int32(prg.curL)].qqqq()
- if !(int32(prg.mainI.b0) > minQuarterword) {
- prg.charWarning(prg.mainF, eightBits(prg.curChr))
- {
- *(*prg.mem[prg.ligStack].hh()).rh() = prg.avail
- prg.avail = prg.ligStack /* dyn_used:= dyn_used-1 ; [ ] */
- }
- goto bigSwitch
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.ligStack
- prg.curList.tailField = prg.ligStack
- mainLoopLookahead:
- prg.getNext() // set only |cur_cmd| and |cur_chr|, for speed
- if int32(prg.curCmd) == letter {
- goto mainLoopLookahead_plus_1
- }
- if int32(prg.curCmd) == otherChar {
- goto mainLoopLookahead_plus_1
- }
- if int32(prg.curCmd) == charGiven {
- goto mainLoopLookahead_plus_1
- }
- prg.xToken() // now expand and set |cur_cmd|, |cur_chr|, |cur_tok|
- if int32(prg.curCmd) == letter {
- goto mainLoopLookahead_plus_1
- }
- if int32(prg.curCmd) == otherChar {
- goto mainLoopLookahead_plus_1
- }
- if int32(prg.curCmd) == charGiven {
- goto mainLoopLookahead_plus_1
- }
- if int32(prg.curCmd) == charNum {
- prg.scanCharNum()
- prg.curChr = uint16(prg.curVal)
- goto mainLoopLookahead_plus_1
- }
- if int32(prg.curCmd) == noBoundary {
- prg.bchar = uint16(256 + minQuarterword)
- }
- prg.curR = prg.bchar
- prg.ligStack = 0
- goto mainLigLoop
- mainLoopLookahead_plus_1:
- prg.mainS = int32(*(*prg.eqtb[sfCodeBase+int32(prg.curChr)-1].hh()).rh())
- if prg.mainS == 1000 {
- *(*prg.curList.auxField.hh()).lh() = 1000
- } else if prg.mainS < 1000 {
- if prg.mainS > 0 {
- *(*prg.curList.auxField.hh()).lh() = uint16(prg.mainS)
- }
- } else if int32(*(*prg.curList.auxField.hh()).lh()) < 1000 {
- *(*prg.curList.auxField.hh()).lh() = 1000
- } else {
- *(*prg.curList.auxField.hh()).lh() = uint16(prg.mainS)
- }
- /* */ {
- prg.ligStack = prg.avail
- if int32(prg.ligStack) == 0 {
- prg.ligStack = prg.getAvail()
- } else {
- prg.avail = *(*prg.mem[prg.ligStack].hh()).rh()
- *(*prg.mem[prg.ligStack].hh()).rh() = 0 /* dyn_used:= dyn_used+1 ; [ ] */
- }
- }
- *(*prg.mem[prg.ligStack].hh()).b0() = prg.mainF
- prg.curR = uint16(int32(prg.curChr) + minQuarterword)
- *(*prg.mem[prg.ligStack].hh()).b1() = byte(prg.curR)
- if int32(prg.curR) == int32(prg.falseBchar) {
- prg.curR = uint16(256 + minQuarterword)
- }
- mainLigLoop:
- if (int32(prg.mainI.b2)-minQuarterword)%4 != ligTag {
- goto mainLoopWrapup
- }
- if int32(prg.curR) == 256+minQuarterword {
- goto mainLoopWrapup
- }
- prg.mainK = uint16(prg.ligKernBase[prg.mainF] + int32(prg.mainI.b3))
- prg.mainJ = *prg.fontInfo[prg.mainK].qqqq()
- if int32(prg.mainJ.b0) <= 128+minQuarterword {
- goto mainLigLoop_plus_2
- }
- prg.mainK = uint16(prg.ligKernBase[prg.mainF] + 256*int32(prg.mainJ.b2) + int32(prg.mainJ.b3) + 32768 - 256*(128+minQuarterword))
- mainLigLoop_plus_1:
- prg.mainJ = *prg.fontInfo[prg.mainK].qqqq()
- mainLigLoop_plus_2:
- if int32(prg.mainJ.b1) == int32(prg.curR) {
- if int32(prg.mainJ.b0) <= 128+minQuarterword {
- if int32(prg.mainJ.b2) >= 128+minQuarterword {
- if int32(prg.curL) < 256+minQuarterword {
- if int32(*(*prg.mem[prg.curQ].hh()).rh()) > 0 {
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b1()) == prg.hyphenChar[prg.mainF]+minQuarterword {
- prg.insDisc = true
- }
- }
- if prg.ligaturePresent {
- prg.mainP = prg.newLigature(prg.mainF, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
- if prg.lftHit {
- *(*prg.mem[prg.mainP].hh()).b1() = 2
- prg.lftHit = false
- }
- if prg.rtHit {
- if int32(prg.ligStack) == 0 {
- *(*prg.mem[prg.mainP].hh()).b1() = byte(int32(*(*prg.mem[prg.mainP].hh()).b1()) + 1)
- prg.rtHit = false
- }
- }
- *(*prg.mem[prg.curQ].hh()).rh() = prg.mainP
- prg.curList.tailField = prg.mainP
- prg.ligaturePresent = false
- }
- if prg.insDisc {
- prg.insDisc = false
- if int32(prg.curList.modeField) > 0 {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newDisc()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- }
- }
- {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newKern(*prg.fontInfo[prg.kernBase[prg.mainF]+256*int32(prg.mainJ.b2)+int32(prg.mainJ.b3)].int())
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- goto mainLoopMove
- }
- if int32(prg.curL) == 256+minQuarterword {
- prg.lftHit = true
- } else if int32(prg.ligStack) == 0 {
- prg.rtHit = true
- }
- {
- if prg.interrupt != 0 {
- prg.pauseForInstructions()
- }
- } // allow a way out in case there's an infinite ligature loop
- switch prg.mainJ.b2 {
- case 1 + minQuarterword, 5 + minQuarterword:
- prg.curL = uint16(prg.mainJ.b3) // \.[=:\?], \.[=:\?>]
- prg.mainI = *prg.fontInfo[prg.charBase[prg.mainF]+int32(prg.curL)].qqqq()
- prg.ligaturePresent = true
- case 2 + minQuarterword, 6 + minQuarterword:
- prg.curR = uint16(prg.mainJ.b3) // \.[\?=:], \.[\?=:>]
- if int32(prg.ligStack) == 0 {
- prg.ligStack = prg.newLigItem(quarterword(prg.curR))
- prg.bchar = uint16(256 + minQuarterword)
- } else if int32(prg.ligStack) >= int32(prg.hiMemMin) {
- prg.mainP = prg.ligStack
- prg.ligStack = prg.newLigItem(quarterword(prg.curR))
- *(*prg.mem[int32(prg.ligStack)+1].hh()).rh() = prg.mainP
- } else {
- *(*prg.mem[prg.ligStack].hh()).b1() = byte(prg.curR)
- }
- case 3 + minQuarterword:
- prg.curR = uint16(prg.mainJ.b3) // \.[\?=:\?]
- prg.mainP = prg.ligStack
- prg.ligStack = prg.newLigItem(quarterword(prg.curR))
- *(*prg.mem[prg.ligStack].hh()).rh() = prg.mainP
- case 7 + minQuarterword, 11 + minQuarterword:
- if int32(prg.curL) < 256+minQuarterword {
- if int32(*(*prg.mem[prg.curQ].hh()).rh()) > 0 {
- if int32(*(*prg.mem[prg.curList.tailField].hh()).b1()) == prg.hyphenChar[prg.mainF]+minQuarterword {
- prg.insDisc = true
- }
- }
- if prg.ligaturePresent {
- prg.mainP = prg.newLigature(prg.mainF, quarterword(prg.curL), *(*prg.mem[prg.curQ].hh()).rh())
- if prg.lftHit {
- *(*prg.mem[prg.mainP].hh()).b1() = 2
- prg.lftHit = false
- }
- if false {
- if int32(prg.ligStack) == 0 {
- *(*prg.mem[prg.mainP].hh()).b1() = byte(int32(*(*prg.mem[prg.mainP].hh()).b1()) + 1)
- prg.rtHit = false
- }
- }
- *(*prg.mem[prg.curQ].hh()).rh() = prg.mainP
- prg.curList.tailField = prg.mainP
- prg.ligaturePresent = false
- }
- if prg.insDisc {
- prg.insDisc = false
- if int32(prg.curList.modeField) > 0 {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.newDisc()
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- }
- }
- } // \.[\?=:\?>], \.[\?=:\?>>]
- prg.curQ = prg.curList.tailField
- prg.curL = uint16(prg.mainJ.b3)
- prg.mainI = *prg.fontInfo[prg.charBase[prg.mainF]+int32(prg.curL)].qqqq()
- prg.ligaturePresent = true
- default:
- prg.curL = uint16(prg.mainJ.b3)
- prg.ligaturePresent = true // \.[=:]
- if int32(prg.ligStack) == 0 {
- goto mainLoopWrapup
- } else {
- goto mainLoopMove_plus_1
- }
- }
- if int32(prg.mainJ.b2) > 4+minQuarterword {
- if int32(prg.mainJ.b2) != 7+minQuarterword {
- goto mainLoopWrapup
- }
- }
- if int32(prg.curL) < 256+minQuarterword {
- goto mainLigLoop
- }
- prg.mainK = prg.bcharLabel[prg.mainF]
- goto mainLigLoop_plus_1
- }
- }
- if int32(prg.mainJ.b0) == 0+minQuarterword {
- prg.mainK = uint16(int32(prg.mainK) + 1)
- } else {
- if int32(prg.mainJ.b0) >= 128+minQuarterword {
- goto mainLoopWrapup
- }
- prg.mainK = uint16(int32(prg.mainK) + int32(prg.mainJ.b0) - minQuarterword + 1)
- }
- goto mainLigLoop_plus_1
- mainLoopMoveLig:
- prg.mainP = *(*prg.mem[int32(prg.ligStack)+1].hh()).rh()
- if int32(prg.mainP) > 0 {
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.mainP
- prg.curList.tailField = *(*prg.mem[prg.curList.tailField].hh()).rh()
- } // append a single character
- prg.tempPtr = prg.ligStack
- prg.ligStack = *(*prg.mem[prg.tempPtr].hh()).rh()
- prg.freeNode(prg.tempPtr, halfword(smallNodeSize))
- prg.mainI = *prg.fontInfo[prg.charBase[prg.mainF]+int32(prg.curL)].qqqq()
- prg.ligaturePresent = true
- if int32(prg.ligStack) == 0 {
- if int32(prg.mainP) > 0 {
- goto mainLoopLookahead
- } else {
- prg.curR = prg.bchar
- }
- } else {
- prg.curR = uint16(*(*prg.mem[prg.ligStack].hh()).b1())
- }
- goto mainLigLoop
- appendNormalSpace:
- if int32(*(*prg.eqtb[glueBase+spaceSkipCode-1].hh()).rh()) == memBot {
- {
- prg.mainP = prg.fontGlue[*(*prg.eqtb[curFontLoc-1].hh()).rh()]
- if int32(prg.mainP) == 0 {
- prg.mainP = prg.newSpec(halfword(memBot))
- prg.mainK = uint16(prg.paramBase[*(*prg.eqtb[curFontLoc-1].hh()).rh()] + spaceCode)
- *prg.mem[int32(prg.mainP)+widthOffset].int() = *prg.fontInfo[prg.mainK].int() // that's |space(cur_font)|
- *prg.mem[int32(prg.mainP)+2].int() = *prg.fontInfo[int32(prg.mainK)+1].int() // and |space_stretch(cur_font)|
- *prg.mem[int32(prg.mainP)+3].int() = *prg.fontInfo[int32(prg.mainK)+2].int() // and |space_shrink(cur_font)|
- prg.fontGlue[*(*prg.eqtb[curFontLoc-1].hh()).rh()] = prg.mainP
- }
- }
- prg.tempPtr = prg.newGlue(prg.mainP)
- } else {
- prg.tempPtr = prg.newParamGlue(smallNumber(spaceSkipCode))
- }
- *(*prg.mem[prg.curList.tailField].hh()).rh() = prg.tempPtr
- prg.curList.tailField = prg.tempPtr
- goto bigSwitch
- exit:
- } // \2
- func (prg *prg) giveErrHelp() {
- prg.tokenShow(*(*prg.eqtb[errHelpLoc-1].hh()).rh())
- }
- // 1303.
- // tangle:pos tex.web:23781:5:
- // Corresponding to the procedure that dumps a format file, we have a function
- // that reads one in. The function returns |false| if the dumped format is
- // incompatible with the present \TeX\ table sizes, etc.
- // \4
- // Declare the function called |open_fmt_file|
- func (prg *prg) openFmtFile() (r bool) {
- var (
- j /* 0..bufSize */ uint16 // the first space after the format file name
- )
- j = prg.curInput.locField
- if int32(prg.buffer[prg.curInput.locField]) == '&' {
- prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
- j = prg.curInput.locField
- prg.buffer[prg.last] = ' '
- for int32(prg.buffer[j]) != ' ' {
- j = uint16(int32(j) + 1)
- }
- prg.packBufferedName(smallNumber(0), int32(prg.curInput.locField), int32(j)-1) // try first without the system file area
- if prg.wOpenIn(prg.fmtFile) {
- goto found
- }
- prg.packBufferedName(smallNumber(formatAreaLength), int32(prg.curInput.locField), int32(j)-1)
- // now try the system format file area
- if prg.wOpenIn(prg.fmtFile) {
- goto found
- }
- prg.termOut.Writeln("Sorry, I can't find that format;", " will try PLAIN.")
- // \xref[Sorry, I can't find...]
- }
- // now pull out all the stops: try for the system \.[plain] file
- prg.packBufferedName(smallNumber(formatDefaultLength-formatExtLength), 1, 0)
- if !prg.wOpenIn(prg.fmtFile) {
- prg.termOut.Writeln("I can't find the PLAIN format file!")
- // \xref[I can't find PLAIN...]
- // \xref[plain]
- r = false
- goto exit
- }
- found:
- prg.curInput.locField = j
- r = true
- exit:
- ;
- return r
- }
- func (prg *prg) loadFmtFile() (r bool) {
- var (
- j, k int32 // all-purpose indices
- p, q halfword // all-purpose pointers
- x int32 // something undumped
- w fourQuarters // four ASCII codes
- )
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- if x != 504454778 {
- goto badFmt
- } // check that strings are the same
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x != memBot {
- goto badFmt
- }
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x != 30000 {
- goto badFmt
- }
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x != eqtbSize {
- goto badFmt
- }
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x != hashPrime {
- goto badFmt
- }
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x != hyphSize {
- goto badFmt
- }
- // Undump the string pool
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 {
- goto badFmt
- }
- if x > poolSize {
- prg.termOut.Writeln("---! Must increase the ", "string pool size") /* \xref[Must increase the x] */ /* \xref[Must increase the x] */
- goto badFmt
- } else {
- prg.poolPtr = uint16(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 {
- goto badFmt
- }
- if x > maxStrings {
- prg.termOut.Writeln("---! Must increase the ", "max strings") /* \xref[Must increase the x] */ /* \xref[Must increase the x] */
- goto badFmt
- } else {
- prg.strPtr = uint16(x)
- }
- }
- for ii := int32(0); ii <= int32(prg.strPtr); ii++ {
- k = ii
- _ = k
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > int32(prg.poolPtr) {
- goto badFmt
- } else {
- prg.strStart[k] = uint16(x)
- }
- }
- k = 0
- for k+4 < int32(prg.poolPtr) {
- {
- prg.fmtFile.Get()
- w = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq()
- }
- prg.strPool[k] = byte(int32(w.b0) - minQuarterword)
- prg.strPool[k+1] = byte(int32(w.b1) - minQuarterword)
- prg.strPool[k+2] = byte(int32(w.b2) - minQuarterword)
- prg.strPool[k+3] = byte(int32(w.b3) - minQuarterword)
- k = k + 4
- }
- k = int32(prg.poolPtr) - 4
- {
- prg.fmtFile.Get()
- w = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq()
- }
- prg.strPool[k] = byte(int32(w.b0) - minQuarterword)
- prg.strPool[k+1] = byte(int32(w.b1) - minQuarterword)
- prg.strPool[k+2] = byte(int32(w.b2) - minQuarterword)
- prg.strPool[k+3] = byte(int32(w.b3) - minQuarterword)
- prg.initStrPtr = prg.strPtr
- prg.initPoolPtr = prg.poolPtr
- // Undump the dynamic memory
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize-1+1000 || x > 30000-13-1 {
- goto badFmt
- } else {
- prg.loMemMax = uint16(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < memBot+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize+glueSpecSize-1+1 || x > int32(prg.loMemMax) {
- goto badFmt
- } else {
- prg.rover = uint16(x)
- }
- }
- p = uint16(memBot)
- q = prg.rover
- for {
- for ii := int32(p); ii <= int32(q)+1; ii++ {
- k = ii
- _ = k
- prg.fmtFile.Get()
- prg.mem[k] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
- }
- p = uint16(int32(q) + int32(*(*prg.mem[q].hh()).lh()))
- if int32(p) > int32(prg.loMemMax) || int32(q) >= int32(*(*prg.mem[int32(q)+1].hh()).rh()) && int32(*(*prg.mem[int32(q)+1].hh()).rh()) != int32(prg.rover) {
- goto badFmt
- }
- q = *(*prg.mem[int32(q)+1].hh()).rh()
- if int32(q) == int32(prg.rover) {
- break
- }
- }
- for ii := int32(p); ii <= int32(prg.loMemMax); ii++ {
- k = ii
- _ = k
- prg.fmtFile.Get()
- prg.mem[k] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
- }
- if memMin < memBot-2 {
- p = *(*prg.mem[int32(prg.rover)+1].hh()).lh()
- q = uint16(memMin + 1)
- *(*prg.mem[memMin].hh()).rh() = 0
- *(*prg.mem[memMin].hh()).lh() = 0 // we don't use the bottom word
- *(*prg.mem[int32(p)+1].hh()).rh() = q
- *(*prg.mem[int32(prg.rover)+1].hh()).lh() = q
- *(*prg.mem[int32(q)+1].hh()).rh() = prg.rover
- *(*prg.mem[int32(q)+1].hh()).lh() = p
- *(*prg.mem[q].hh()).rh() = 65535
- *(*prg.mem[q].hh()).lh() = uint16(memBot - int32(q))
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < int32(prg.loMemMax)+1 || x > 30000-13 {
- goto badFmt
- } else {
- prg.hiMemMin = uint16(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > 30000 {
- goto badFmt
- } else {
- prg.avail = uint16(x)
- }
- }
- prg.memEnd = 30000
- for ii := int32(prg.hiMemMin); ii <= int32(prg.memEnd); ii++ {
- k = ii
- _ = k
- prg.fmtFile.Get()
- prg.mem[k] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
- }
- {
- prg.fmtFile.Get()
- prg.varUsed = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.dynUsed = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- // Undump the table of equivalents
- // Undump regions 1 to 6 of |eqtb|
- k = activeBase
- for {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 1 || k+x > eqtbSize+1 {
- goto badFmt
- }
- for ii := k; ii <= k+x-1; ii++ {
- j = ii
- _ = j
- prg.fmtFile.Get()
- prg.eqtb[j-1] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
- }
- k = k + x
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || k+x > eqtbSize+1 {
- goto badFmt
- }
- for ii := k; ii <= k+x-1; ii++ {
- j = ii
- _ = j
- prg.eqtb[j-1] = prg.eqtb[k-1-1]
- }
- k = k + x
- if k > eqtbSize {
- break
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < hashBase || x > frozenControlSequence {
- goto badFmt
- } else {
- prg.parLoc = uint16(x)
- }
- }
- prg.parToken = uint16(07777 + int32(prg.parLoc))
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < hashBase || x > frozenControlSequence {
- goto badFmt
- } else {
- prg.writeLoc = uint16(x)
- }
- }
- // Undump the hash table
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < hashBase || x > frozenControlSequence {
- goto badFmt
- } else {
- prg.hashUsed = uint16(x)
- }
- }
- p = uint16(hashBase - 1)
- for {
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < int32(p)+1 || x > int32(prg.hashUsed) {
- goto badFmt
- } else {
- p = uint16(x)
- }
- }
- {
- prg.fmtFile.Get()
- prg.hash[p-514] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh()
- }
- if int32(p) == int32(prg.hashUsed) {
- break
- }
- }
- for ii := int32(prg.hashUsed) + 1; ii <= undefinedControlSequence-1; ii++ {
- p = halfword(ii)
- _ = p
- prg.fmtFile.Get()
- prg.hash[p-514] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh()
- }
- {
- prg.fmtFile.Get()
- prg.csCount = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- // Undump the font information
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 7 {
- goto badFmt
- }
- if x > fontMemSize {
- prg.termOut.Writeln("---! Must increase the ", "font mem size") /* \xref[Must increase the x] */ /* \xref[Must increase the x] */
- goto badFmt
- } else {
- prg.fmemPtr = uint16(x)
- }
- }
- for ii := int32(0); ii <= int32(prg.fmemPtr)-1; ii++ {
- k = ii
- _ = k
- prg.fmtFile.Get()
- prg.fontInfo[k] = *(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < fontBase {
- goto badFmt
- }
- if x > fontMax {
- prg.termOut.Writeln("---! Must increase the ", "font max") /* \xref[Must increase the x] */ /* \xref[Must increase the x] */
- goto badFmt
- } else {
- prg.fontPtr = byte(x)
- }
- }
- for ii := int32(fontBase); ii <= int32(prg.fontPtr); ii++ {
- k = ii
- _ = k
- // Undump the array info for internal font number |k|
- {
- prg.fmtFile.Get()
- prg.fontCheck[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).qqqq()
- }
- {
- prg.fmtFile.Get()
- prg.fontSize[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.fontDsize[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > 65535 {
- goto badFmt
- } else {
- prg.fontParams[k] = uint16(x)
- }
- }
- {
- prg.fmtFile.Get()
- prg.hyphenChar[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.skewChar[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > int32(prg.strPtr) {
- goto badFmt
- } else {
- prg.fontName[k] = uint16(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > int32(prg.strPtr) {
- goto badFmt
- } else {
- prg.fontArea[k] = uint16(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > 255 {
- goto badFmt
- } else {
- prg.fontBc[k] = byte(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > 255 {
- goto badFmt
- } else {
- prg.fontEc[k] = byte(x)
- }
- }
- {
- prg.fmtFile.Get()
- prg.charBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.widthBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.heightBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.depthBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.italicBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.ligKernBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.kernBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.extenBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- prg.fmtFile.Get()
- prg.paramBase[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > int32(prg.loMemMax) {
- goto badFmt
- } else {
- prg.fontGlue[k] = uint16(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > int32(prg.fmemPtr)-1 {
- goto badFmt
- } else {
- prg.bcharLabel[k] = uint16(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < minQuarterword || x > 256+minQuarterword {
- goto badFmt
- } else {
- prg.fontBchar[k] = uint16(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < minQuarterword || x > 256+minQuarterword {
- goto badFmt
- } else {
- prg.fontFalseBchar[k] = uint16(x)
- }
- }
- }
- // Undump the hyphenation tables
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > hyphSize {
- goto badFmt
- } else {
- prg.hyphCount = uint16(x)
- }
- }
- for ii := int32(1); ii <= int32(prg.hyphCount); ii++ {
- k = ii
- _ = k
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > hyphSize {
- goto badFmt
- } else {
- j = x
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > int32(prg.strPtr) {
- goto badFmt
- } else {
- prg.hyphWord[j] = uint16(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > 65535 {
- goto badFmt
- } else {
- prg.hyphList[j] = uint16(x)
- }
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 {
- goto badFmt
- }
- if x > trieSize {
- prg.termOut.Writeln("---! Must increase the ", "trie size") /* \xref[Must increase the x] */ /* \xref[Must increase the x] */
- goto badFmt
- } else {
- j = x
- }
- }
- prg.trieMax = uint16(j)
- for ii := int32(0); ii <= j; ii++ {
- k = ii
- _ = k
- prg.fmtFile.Get()
- prg.trie[k] = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).hh()
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 {
- goto badFmt
- }
- if x > trieOpSize {
- prg.termOut.Writeln("---! Must increase the ", "trie op size") /* \xref[Must increase the x] */ /* \xref[Must increase the x] */
- goto badFmt
- } else {
- j = x
- }
- }
- prg.trieOpPtr = uint16(j)
- for ii := int32(1); ii <= j; ii++ {
- k = ii
- _ = k
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > 63 {
- goto badFmt
- } else {
- prg.hyfDistance[k-1] = byte(x)
- }
- } // a |small_number|
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > 63 {
- goto badFmt
- } else {
- prg.hyfNum[k-1] = byte(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < minQuarterword || x > maxQuarterword {
- goto badFmt
- } else {
- prg.hyfNext[k-1] = byte(x)
- }
- }
- }
- for ii := int32(0); ii <= 255; ii++ {
- k = ii
- _ = k
- prg.trieUsed[k] = byte(minQuarterword)
- }
- k = 256
- for j > 0 {
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > k-1 {
- goto badFmt
- } else {
- k = x
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 1 || x > j {
- goto badFmt
- } else {
- x = x
- }
- }
- prg.trieUsed[k] = byte(x + minQuarterword)
- j = j - x
- prg.opStart[k] = uint16(j - minQuarterword)
- }
- prg.trieNotReady = false
- // Undump a couple more things and the closing check word
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < batchMode || x > errorStopMode {
- goto badFmt
- } else {
- prg.interaction = byte(x)
- }
- }
- {
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x < 0 || x > int32(prg.strPtr) {
- goto badFmt
- } else {
- prg.formatIdent = uint16(x)
- }
- }
- {
- prg.fmtFile.Get()
- x = *(*(*memoryWord)(unsafe.Pointer(prg.fmtFile.Data4P()))).int()
- }
- if x != 69069 || prg.fmtFile.EOF() {
- goto badFmt
- }
- r = true
- goto exit // it worked!
- // it worked!
- badFmt:
- ;
- prg.termOut.Writeln("(Fatal format file error; I'm stymied)")
- // \xref[Fatal format file error]
- r = false
- exit:
- ;
- return r
- } // \2
- func (prg *prg) closeFilesAndTerminate() {
- var (
- k int32 // all-purpose index
- )
- for ii := int32(0); ii <= 15; ii++ {
- k = ii
- _ = k
- if prg.writeOpen[k] {
- prg.aClose(prg.writeFile[k])
- }
- }
- *prg.eqtb[intBase+newLineCharCode-1].int() = -1
- // if eqtb[int_base+ tracing_stats_code].int >0 then
- // [ Output statistics about this job ]
- // if log_opened then
- // begin writeln( log_file,' ') ;
- // writeln( log_file,'Here is how much of TeX''s memory',' you used:') ;
- // [ \xref[Here is how much...] ]
- // write(log_file,' ', str_ptr- init_str_ptr: 1,' string') ;
- // if str_ptr<>init_str_ptr+1 then write(log_file,'s') ;
- // writeln( log_file,' out of ', max_strings- init_str_ptr: 1) ;
- //
- // writeln( log_file,' ', pool_ptr- init_pool_ptr: 1,' string characters out of ',
- // pool_size- init_pool_ptr: 1) ;
- //
- // writeln( log_file,' ', lo_mem_max- mem_min+ mem_end- hi_mem_min+ 2: 1,
- // ' words of memory out of ', mem_end+ 1- mem_min: 1) ;
- //
- // writeln( log_file,' ', cs_count: 1,' multiletter control sequences out of ',
- // hash_size: 1) ;
- //
- // write(log_file,' ', fmem_ptr: 1,' words of font info for ',
- // font_ptr- font_base: 1,' font') ;
- // if font_ptr<>font_base+1 then write(log_file,'s') ;
- // writeln( log_file,', out of ', font_mem_size: 1,' for ', font_max- font_base: 1) ;
- //
- // write(log_file,' ', hyph_count: 1,' hyphenation exception') ;
- // if hyph_count<>1 then write(log_file,'s') ;
- // writeln( log_file,' out of ', hyph_size: 1) ;
- //
- // writeln( log_file,' ', max_in_stack: 1,'i,', max_nest_stack: 1,'n,',
- // max_param_stack: 1,'p,',
- // max_buf_stack+ 1: 1,'b,',
- // max_save_stack+ 6: 1,'s stack positions out of ',
- // stack_size: 1,'i,',
- // nest_size: 1,'n,',
- // param_size: 1,'p,',
- // buf_size: 1,'b,',
- // save_size: 1,'s') ;
- // end
- //
- // ; [ ]
- // Finish the \.[DVI] file
- for prg.curS > -1 {
- if prg.curS > 0 {
- prg.dviBuf[prg.dviPtr] = byte(pop)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } else {
- {
- prg.dviBuf[prg.dviPtr] = byte(eop)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.totalPages = prg.totalPages + 1
- }
- prg.curS = prg.curS - 1
- }
- if prg.totalPages == 0 {
- prg.printNl(strNumber( /* "No pages of output." */ 837))
- } else {
- {
- prg.dviBuf[prg.dviPtr] = byte(post)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- } // beginning of the postamble
- prg.dviFour(prg.lastBop)
- prg.lastBop = prg.dviOffset + int32(prg.dviPtr) - 5 // |post| location
- prg.dviFour(25400000)
- prg.dviFour(473628672) // conversion ratio for sp
- prg.prepareMag()
- prg.dviFour(*prg.eqtb[intBase+magCode-1].int()) // magnification factor
- prg.dviFour(prg.maxV)
- prg.dviFour(prg.maxH)
- {
- prg.dviBuf[prg.dviPtr] = byte(prg.maxPush / 256)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(prg.maxPush % 256)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(prg.totalPages / 256 % 256)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(prg.totalPages % 256)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- // Output the font definitions for all fonts that were used
- for int32(prg.fontPtr) > fontBase {
- if prg.fontUsed[prg.fontPtr] {
- prg.dviFontDef(prg.fontPtr)
- }
- prg.fontPtr = byte(int32(prg.fontPtr) - 1)
- }
- {
- prg.dviBuf[prg.dviPtr] = byte(postPost)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- prg.dviFour(prg.lastBop)
- {
- prg.dviBuf[prg.dviPtr] = byte(idByte)
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- k = 4 + (dviBufSize-int32(prg.dviPtr))%4 // the number of 223's
- for k > 0 {
- {
- prg.dviBuf[prg.dviPtr] = 223
- prg.dviPtr = uint16(int32(prg.dviPtr) + 1)
- if int32(prg.dviPtr) == int32(prg.dviLimit) {
- prg.dviSwap()
- }
- }
- k = k - 1
- }
- // Empty the last bytes out of |dvi_buf|
- if int32(prg.dviLimit) == int32(prg.halfBuf) {
- prg.writeDvi(prg.halfBuf, dviIndex(dviBufSize-1))
- }
- if int32(prg.dviPtr) > 0 {
- prg.writeDvi(dviIndex(0), dviIndex(int32(prg.dviPtr)-1))
- }
- prg.printNl(strNumber( /* "Output written on " */ 838))
- prg.slowPrint(int32(prg.outputFileName))
- // \xref[Output written on x]
- prg.print( /* " (" */ 286)
- prg.printInt(prg.totalPages)
- prg.print( /* " page" */ 839)
- if prg.totalPages != 1 {
- prg.printChar(asciiCode('s'))
- }
- prg.print( /* ", " */ 840)
- prg.printInt(prg.dviOffset + int32(prg.dviPtr))
- prg.print( /* " bytes)." */ 841)
- prg.bClose(prg.dviFile)
- }
- if prg.logOpened {
- prg.logFile.Writeln()
- prg.aClose(prg.logFile)
- prg.selector = byte(int32(prg.selector) - 2)
- if int32(prg.selector) == termOnly {
- prg.printNl(strNumber( /* "Transcript written on " */ 1275))
- // \xref[Transcript written...]
- prg.slowPrint(int32(prg.logName))
- prg.printChar(asciiCode('.'))
- }
- }
- prg.termOut.Writeln()
- }
- func (prg *prg) finalCleanup() {
- var (
- c smallNumber // 0 for \.[\\end], 1 for \.[\\dump]
- )
- c = byte(prg.curChr)
- if int32(c) != 1 {
- *prg.eqtb[intBase+newLineCharCode-1].int() = -1
- }
- if int32(prg.jobName) == 0 {
- prg.openLogFile()
- }
- for int32(prg.inputPtr) > 0 {
- if int32(prg.curInput.stateField) == tokenList {
- prg.endTokenList()
- } else {
- prg.endFileReading()
- }
- }
- for int32(prg.openParens) > 0 {
- prg.print( /* " )" */ 1276)
- prg.openParens = byte(int32(prg.openParens) - 1)
- }
- if int32(prg.curLevel) > levelOne {
- prg.printNl(strNumber('('))
- prg.printEsc(strNumber( /* "end occurred " */ 1277))
- prg.print( /* "inside a group at level " */ 1278)
- // \xref[end_][\.[(\\end occurred...)]]
- prg.printInt(int32(prg.curLevel) - levelOne)
- prg.printChar(asciiCode(')'))
- }
- for int32(prg.condPtr) != 0 {
- prg.printNl(strNumber('('))
- prg.printEsc(strNumber( /* "end occurred " */ 1277))
- prg.print( /* "when " */ 1279)
- prg.printCmdChr(quarterword(ifTest), halfword(prg.curIf))
- if prg.ifLine != 0 {
- prg.print( /* " on line " */ 1280)
- prg.printInt(prg.ifLine)
- }
- prg.print( /* " was incomplete)" */ 1281)
- prg.ifLine = *prg.mem[int32(prg.condPtr)+1].int()
- prg.curIf = *(*prg.mem[prg.condPtr].hh()).b1()
- prg.tempPtr = prg.condPtr
- prg.condPtr = *(*prg.mem[prg.condPtr].hh()).rh()
- prg.freeNode(prg.tempPtr, halfword(ifNodeSize))
- }
- if int32(prg.history) != spotless {
- if int32(prg.history) == warningIssued || int32(prg.interaction) < errorStopMode {
- if int32(prg.selector) == termAndLog {
- prg.selector = byte(termOnly)
- prg.printNl(strNumber( /* "(see the transcript file for additional information)" */ 1282))
- // \xref[see the transcript file...]
- prg.selector = byte(termAndLog)
- }
- }
- }
- if int32(c) == 1 {
- for ii := int32(topMarkCode); ii <= splitBotMarkCode; ii++ {
- c = smallNumber(ii)
- _ = c
- if int32(prg.curMark[c]) != 0 {
- prg.deleteTokenRef(prg.curMark[c])
- }
- }
- if int32(prg.lastGlue) != 65535 {
- prg.deleteGlueRef(prg.lastGlue)
- }
- prg.storeFmtFile()
- goto exit
- prg.printNl(strNumber( /* "(\\dump is performed only by INITEX)" */ 1283))
- goto exit
- // \xref[dump_][\.[\\dump...only by INITEX]]
- }
- exit:
- }
- func (prg *prg) initPrim() {
- prg.noNewControlSequence = false
- // Put each...
- prg.primitive(strNumber( /* "lineskip" */ 376), quarterword(assignGlue), halfword(glueBase+lineSkipCode))
- // \xref[line_skip_][\.[\\lineskip] primitive]
- prg.primitive(strNumber( /* "baselineskip" */ 377), quarterword(assignGlue), halfword(glueBase+baselineSkipCode))
- // \xref[baseline_skip_][\.[\\baselineskip] primitive]
- prg.primitive(strNumber( /* "parskip" */ 378), quarterword(assignGlue), halfword(glueBase+parSkipCode))
- // \xref[par_skip_][\.[\\parskip] primitive]
- prg.primitive(strNumber( /* "abovedisplayskip" */ 379), quarterword(assignGlue), halfword(glueBase+aboveDisplaySkipCode))
- // \xref[above_display_skip_][\.[\\abovedisplayskip] primitive]
- prg.primitive(strNumber( /* "belowdisplayskip" */ 380), quarterword(assignGlue), halfword(glueBase+belowDisplaySkipCode))
- // \xref[below_display_skip_][\.[\\belowdisplayskip] primitive]
- prg.primitive(strNumber( /* "abovedisplayshortskip" */ 381), quarterword(assignGlue), halfword(glueBase+aboveDisplayShortSkipCode))
- // \xref[above_display_short_skip_][\.[\\abovedisplayshortskip] primitive]
- prg.primitive(strNumber( /* "belowdisplayshortskip" */ 382), quarterword(assignGlue), halfword(glueBase+belowDisplayShortSkipCode))
- // \xref[below_display_short_skip_][\.[\\belowdisplayshortskip] primitive]
- prg.primitive(strNumber( /* "leftskip" */ 383), quarterword(assignGlue), halfword(glueBase+leftSkipCode))
- // \xref[left_skip_][\.[\\leftskip] primitive]
- prg.primitive(strNumber( /* "rightskip" */ 384), quarterword(assignGlue), halfword(glueBase+rightSkipCode))
- // \xref[right_skip_][\.[\\rightskip] primitive]
- prg.primitive(strNumber( /* "topskip" */ 385), quarterword(assignGlue), halfword(glueBase+topSkipCode))
- // \xref[top_skip_][\.[\\topskip] primitive]
- prg.primitive(strNumber( /* "splittopskip" */ 386), quarterword(assignGlue), halfword(glueBase+splitTopSkipCode))
- // \xref[split_top_skip_][\.[\\splittopskip] primitive]
- prg.primitive(strNumber( /* "tabskip" */ 387), quarterword(assignGlue), halfword(glueBase+tabSkipCode))
- // \xref[tab_skip_][\.[\\tabskip] primitive]
- prg.primitive(strNumber( /* "spaceskip" */ 388), quarterword(assignGlue), halfword(glueBase+spaceSkipCode))
- // \xref[space_skip_][\.[\\spaceskip] primitive]
- prg.primitive(strNumber( /* "xspaceskip" */ 389), quarterword(assignGlue), halfword(glueBase+xspaceSkipCode))
- // \xref[xspace_skip_][\.[\\xspaceskip] primitive]
- prg.primitive(strNumber( /* "parfillskip" */ 390), quarterword(assignGlue), halfword(glueBase+parFillSkipCode))
- // \xref[par_fill_skip_][\.[\\parfillskip] primitive]
- prg.primitive(strNumber( /* "thinmuskip" */ 391), quarterword(assignMuGlue), halfword(glueBase+thinMuSkipCode))
- // \xref[thin_mu_skip_][\.[\\thinmuskip] primitive]
- prg.primitive(strNumber( /* "medmuskip" */ 392), quarterword(assignMuGlue), halfword(glueBase+medMuSkipCode))
- // \xref[med_mu_skip_][\.[\\medmuskip] primitive]
- prg.primitive(strNumber( /* "thickmuskip" */ 393), quarterword(assignMuGlue), halfword(glueBase+thickMuSkipCode))
- // \xref[thick_mu_skip_][\.[\\thickmuskip] primitive]
- prg.primitive(strNumber( /* "output" */ 398), quarterword(assignToks), halfword(outputRoutineLoc))
- // \xref[output_][\.[\\output] primitive]
- prg.primitive(strNumber( /* "everypar" */ 399), quarterword(assignToks), halfword(everyParLoc))
- // \xref[every_par_][\.[\\everypar] primitive]
- prg.primitive(strNumber( /* "everymath" */ 400), quarterword(assignToks), halfword(everyMathLoc))
- // \xref[every_math_][\.[\\everymath] primitive]
- prg.primitive(strNumber( /* "everydisplay" */ 401), quarterword(assignToks), halfword(everyDisplayLoc))
- // \xref[every_display_][\.[\\everydisplay] primitive]
- prg.primitive(strNumber( /* "everyhbox" */ 402), quarterword(assignToks), halfword(everyHboxLoc))
- // \xref[every_hbox_][\.[\\everyhbox] primitive]
- prg.primitive(strNumber( /* "everyvbox" */ 403), quarterword(assignToks), halfword(everyVboxLoc))
- // \xref[every_vbox_][\.[\\everyvbox] primitive]
- prg.primitive(strNumber( /* "everyjob" */ 404), quarterword(assignToks), halfword(everyJobLoc))
- // \xref[every_job_][\.[\\everyjob] primitive]
- prg.primitive(strNumber( /* "everycr" */ 405), quarterword(assignToks), halfword(everyCrLoc))
- // \xref[every_cr_][\.[\\everycr] primitive]
- prg.primitive(strNumber( /* "errhelp" */ 406), quarterword(assignToks), halfword(errHelpLoc))
- // \xref[err_help_][\.[\\errhelp] primitive]
- prg.primitive(strNumber( /* "pretolerance" */ 420), quarterword(assignInt), halfword(intBase+pretoleranceCode))
- // \xref[pretolerance_][\.[\\pretolerance] primitive]
- prg.primitive(strNumber( /* "tolerance" */ 421), quarterword(assignInt), halfword(intBase+toleranceCode))
- // \xref[tolerance_][\.[\\tolerance] primitive]
- prg.primitive(strNumber( /* "linepenalty" */ 422), quarterword(assignInt), halfword(intBase+linePenaltyCode))
- // \xref[line_penalty_][\.[\\linepenalty] primitive]
- prg.primitive(strNumber( /* "hyphenpenalty" */ 423), quarterword(assignInt), halfword(intBase+hyphenPenaltyCode))
- // \xref[hyphen_penalty_][\.[\\hyphenpenalty] primitive]
- prg.primitive(strNumber( /* "exhyphenpenalty" */ 424), quarterword(assignInt), halfword(intBase+exHyphenPenaltyCode))
- // \xref[ex_hyphen_penalty_][\.[\\exhyphenpenalty] primitive]
- prg.primitive(strNumber( /* "clubpenalty" */ 425), quarterword(assignInt), halfword(intBase+clubPenaltyCode))
- // \xref[club_penalty_][\.[\\clubpenalty] primitive]
- prg.primitive(strNumber( /* "widowpenalty" */ 426), quarterword(assignInt), halfword(intBase+widowPenaltyCode))
- // \xref[widow_penalty_][\.[\\widowpenalty] primitive]
- prg.primitive(strNumber( /* "displaywidowpenalty" */ 427), quarterword(assignInt), halfword(intBase+displayWidowPenaltyCode))
- // \xref[display_widow_penalty_][\.[\\displaywidowpenalty] primitive]
- prg.primitive(strNumber( /* "brokenpenalty" */ 428), quarterword(assignInt), halfword(intBase+brokenPenaltyCode))
- // \xref[broken_penalty_][\.[\\brokenpenalty] primitive]
- prg.primitive(strNumber( /* "binoppenalty" */ 429), quarterword(assignInt), halfword(intBase+binOpPenaltyCode))
- // \xref[bin_op_penalty_][\.[\\binoppenalty] primitive]
- prg.primitive(strNumber( /* "relpenalty" */ 430), quarterword(assignInt), halfword(intBase+relPenaltyCode))
- // \xref[rel_penalty_][\.[\\relpenalty] primitive]
- prg.primitive(strNumber( /* "predisplaypenalty" */ 431), quarterword(assignInt), halfword(intBase+preDisplayPenaltyCode))
- // \xref[pre_display_penalty_][\.[\\predisplaypenalty] primitive]
- prg.primitive(strNumber( /* "postdisplaypenalty" */ 432), quarterword(assignInt), halfword(intBase+postDisplayPenaltyCode))
- // \xref[post_display_penalty_][\.[\\postdisplaypenalty] primitive]
- prg.primitive(strNumber( /* "interlinepenalty" */ 433), quarterword(assignInt), halfword(intBase+interLinePenaltyCode))
- // \xref[inter_line_penalty_][\.[\\interlinepenalty] primitive]
- prg.primitive(strNumber( /* "doublehyphendemerits" */ 434), quarterword(assignInt), halfword(intBase+doubleHyphenDemeritsCode))
- // \xref[double_hyphen_demerits_][\.[\\doublehyphendemerits] primitive]
- prg.primitive(strNumber( /* "finalhyphendemerits" */ 435), quarterword(assignInt), halfword(intBase+finalHyphenDemeritsCode))
- // \xref[final_hyphen_demerits_][\.[\\finalhyphendemerits] primitive]
- prg.primitive(strNumber( /* "adjdemerits" */ 436), quarterword(assignInt), halfword(intBase+adjDemeritsCode))
- // \xref[adj_demerits_][\.[\\adjdemerits] primitive]
- prg.primitive(strNumber( /* "mag" */ 437), quarterword(assignInt), halfword(intBase+magCode))
- // \xref[mag_][\.[\\mag] primitive]
- prg.primitive(strNumber( /* "delimiterfactor" */ 438), quarterword(assignInt), halfword(intBase+delimiterFactorCode))
- // \xref[delimiter_factor_][\.[\\delimiterfactor] primitive]
- prg.primitive(strNumber( /* "looseness" */ 439), quarterword(assignInt), halfword(intBase+loosenessCode))
- // \xref[looseness_][\.[\\looseness] primitive]
- prg.primitive(strNumber( /* "time" */ 440), quarterword(assignInt), halfword(intBase+timeCode))
- // \xref[time_][\.[\\time] primitive]
- prg.primitive(strNumber( /* "day" */ 441), quarterword(assignInt), halfword(intBase+dayCode))
- // \xref[day_][\.[\\day] primitive]
- prg.primitive(strNumber( /* "month" */ 442), quarterword(assignInt), halfword(intBase+monthCode))
- // \xref[month_][\.[\\month] primitive]
- prg.primitive(strNumber( /* "year" */ 443), quarterword(assignInt), halfword(intBase+yearCode))
- // \xref[year_][\.[\\year] primitive]
- prg.primitive(strNumber( /* "showboxbreadth" */ 444), quarterword(assignInt), halfword(intBase+showBoxBreadthCode))
- // \xref[show_box_breadth_][\.[\\showboxbreadth] primitive]
- prg.primitive(strNumber( /* "showboxdepth" */ 445), quarterword(assignInt), halfword(intBase+showBoxDepthCode))
- // \xref[show_box_depth_][\.[\\showboxdepth] primitive]
- prg.primitive(strNumber( /* "hbadness" */ 446), quarterword(assignInt), halfword(intBase+hbadnessCode))
- // \xref[hbadness_][\.[\\hbadness] primitive]
- prg.primitive(strNumber( /* "vbadness" */ 447), quarterword(assignInt), halfword(intBase+vbadnessCode))
- // \xref[vbadness_][\.[\\vbadness] primitive]
- prg.primitive(strNumber( /* "pausing" */ 448), quarterword(assignInt), halfword(intBase+pausingCode))
- // \xref[pausing_][\.[\\pausing] primitive]
- prg.primitive(strNumber( /* "tracingonline" */ 449), quarterword(assignInt), halfword(intBase+tracingOnlineCode))
- // \xref[tracing_online_][\.[\\tracingonline] primitive]
- prg.primitive(strNumber( /* "tracingmacros" */ 450), quarterword(assignInt), halfword(intBase+tracingMacrosCode))
- // \xref[tracing_macros_][\.[\\tracingmacros] primitive]
- prg.primitive(strNumber( /* "tracingstats" */ 451), quarterword(assignInt), halfword(intBase+tracingStatsCode))
- // \xref[tracing_stats_][\.[\\tracingstats] primitive]
- prg.primitive(strNumber( /* "tracingparagraphs" */ 452), quarterword(assignInt), halfword(intBase+tracingParagraphsCode))
- // \xref[tracing_paragraphs_][\.[\\tracingparagraphs] primitive]
- prg.primitive(strNumber( /* "tracingpages" */ 453), quarterword(assignInt), halfword(intBase+tracingPagesCode))
- // \xref[tracing_pages_][\.[\\tracingpages] primitive]
- prg.primitive(strNumber( /* "tracingoutput" */ 454), quarterword(assignInt), halfword(intBase+tracingOutputCode))
- // \xref[tracing_output_][\.[\\tracingoutput] primitive]
- prg.primitive(strNumber( /* "tracinglostchars" */ 455), quarterword(assignInt), halfword(intBase+tracingLostCharsCode))
- // \xref[tracing_lost_chars_][\.[\\tracinglostchars] primitive]
- prg.primitive(strNumber( /* "tracingcommands" */ 456), quarterword(assignInt), halfword(intBase+tracingCommandsCode))
- // \xref[tracing_commands_][\.[\\tracingcommands] primitive]
- prg.primitive(strNumber( /* "tracingrestores" */ 457), quarterword(assignInt), halfword(intBase+tracingRestoresCode))
- // \xref[tracing_restores_][\.[\\tracingrestores] primitive]
- prg.primitive(strNumber( /* "uchyph" */ 458), quarterword(assignInt), halfword(intBase+ucHyphCode))
- // \xref[uc_hyph_][\.[\\uchyph] primitive]
- prg.primitive(strNumber( /* "outputpenalty" */ 459), quarterword(assignInt), halfword(intBase+outputPenaltyCode))
- // \xref[output_penalty_][\.[\\outputpenalty] primitive]
- prg.primitive(strNumber( /* "maxdeadcycles" */ 460), quarterword(assignInt), halfword(intBase+maxDeadCyclesCode))
- // \xref[max_dead_cycles_][\.[\\maxdeadcycles] primitive]
- prg.primitive(strNumber( /* "hangafter" */ 461), quarterword(assignInt), halfword(intBase+hangAfterCode))
- // \xref[hang_after_][\.[\\hangafter] primitive]
- prg.primitive(strNumber( /* "floatingpenalty" */ 462), quarterword(assignInt), halfword(intBase+floatingPenaltyCode))
- // \xref[floating_penalty_][\.[\\floatingpenalty] primitive]
- prg.primitive(strNumber( /* "globaldefs" */ 463), quarterword(assignInt), halfword(intBase+globalDefsCode))
- // \xref[global_defs_][\.[\\globaldefs] primitive]
- prg.primitive(strNumber( /* "fam" */ 464), quarterword(assignInt), halfword(intBase+curFamCode))
- // \xref[fam_][\.[\\fam] primitive]
- prg.primitive(strNumber( /* "escapechar" */ 465), quarterword(assignInt), halfword(intBase+escapeCharCode))
- // \xref[escape_char_][\.[\\escapechar] primitive]
- prg.primitive(strNumber( /* "defaulthyphenchar" */ 466), quarterword(assignInt), halfword(intBase+defaultHyphenCharCode))
- // \xref[default_hyphen_char_][\.[\\defaulthyphenchar] primitive]
- prg.primitive(strNumber( /* "defaultskewchar" */ 467), quarterword(assignInt), halfword(intBase+defaultSkewCharCode))
- // \xref[default_skew_char_][\.[\\defaultskewchar] primitive]
- prg.primitive(strNumber( /* "endlinechar" */ 468), quarterword(assignInt), halfword(intBase+endLineCharCode))
- // \xref[end_line_char_][\.[\\endlinechar] primitive]
- prg.primitive(strNumber( /* "newlinechar" */ 469), quarterword(assignInt), halfword(intBase+newLineCharCode))
- // \xref[new_line_char_][\.[\\newlinechar] primitive]
- prg.primitive(strNumber( /* "language" */ 470), quarterword(assignInt), halfword(intBase+languageCode))
- // \xref[language_][\.[\\language] primitive]
- prg.primitive(strNumber( /* "lefthyphenmin" */ 471), quarterword(assignInt), halfword(intBase+leftHyphenMinCode))
- // \xref[left_hyphen_min_][\.[\\lefthyphenmin] primitive]
- prg.primitive(strNumber( /* "righthyphenmin" */ 472), quarterword(assignInt), halfword(intBase+rightHyphenMinCode))
- // \xref[right_hyphen_min_][\.[\\righthyphenmin] primitive]
- prg.primitive(strNumber( /* "holdinginserts" */ 473), quarterword(assignInt), halfword(intBase+holdingInsertsCode))
- // \xref[holding_inserts_][\.[\\holdinginserts] primitive]
- prg.primitive(strNumber( /* "errorcontextlines" */ 474), quarterword(assignInt), halfword(intBase+errorContextLinesCode))
- // \xref[error_context_lines_][\.[\\errorcontextlines] primitive]
- prg.primitive(strNumber( /* "parindent" */ 478), quarterword(assignDimen), halfword(dimenBase+parIndentCode))
- // \xref[par_indent_][\.[\\parindent] primitive]
- prg.primitive(strNumber( /* "mathsurround" */ 479), quarterword(assignDimen), halfword(dimenBase+mathSurroundCode))
- // \xref[math_surround_][\.[\\mathsurround] primitive]
- prg.primitive(strNumber( /* "lineskiplimit" */ 480), quarterword(assignDimen), halfword(dimenBase+lineSkipLimitCode))
- // \xref[line_skip_limit_][\.[\\lineskiplimit] primitive]
- prg.primitive(strNumber( /* "hsize" */ 481), quarterword(assignDimen), halfword(dimenBase+hsizeCode))
- // \xref[hsize_][\.[\\hsize] primitive]
- prg.primitive(strNumber( /* "vsize" */ 482), quarterword(assignDimen), halfword(dimenBase+vsizeCode))
- // \xref[vsize_][\.[\\vsize] primitive]
- prg.primitive(strNumber( /* "maxdepth" */ 483), quarterword(assignDimen), halfword(dimenBase+maxDepthCode))
- // \xref[max_depth_][\.[\\maxdepth] primitive]
- prg.primitive(strNumber( /* "splitmaxdepth" */ 484), quarterword(assignDimen), halfword(dimenBase+splitMaxDepthCode))
- // \xref[split_max_depth_][\.[\\splitmaxdepth] primitive]
- prg.primitive(strNumber( /* "boxmaxdepth" */ 485), quarterword(assignDimen), halfword(dimenBase+boxMaxDepthCode))
- // \xref[box_max_depth_][\.[\\boxmaxdepth] primitive]
- prg.primitive(strNumber( /* "hfuzz" */ 486), quarterword(assignDimen), halfword(dimenBase+hfuzzCode))
- // \xref[hfuzz_][\.[\\hfuzz] primitive]
- prg.primitive(strNumber( /* "vfuzz" */ 487), quarterword(assignDimen), halfword(dimenBase+vfuzzCode))
- // \xref[vfuzz_][\.[\\vfuzz] primitive]
- prg.primitive(strNumber( /* "delimitershortfall" */ 488), quarterword(assignDimen), halfword(dimenBase+delimiterShortfallCode))
- // \xref[delimiter_shortfall_][\.[\\delimitershortfall] primitive]
- prg.primitive(strNumber( /* "nulldelimiterspace" */ 489), quarterword(assignDimen), halfword(dimenBase+nullDelimiterSpaceCode))
- // \xref[null_delimiter_space_][\.[\\nulldelimiterspace] primitive]
- prg.primitive(strNumber( /* "scriptspace" */ 490), quarterword(assignDimen), halfword(dimenBase+scriptSpaceCode))
- // \xref[script_space_][\.[\\scriptspace] primitive]
- prg.primitive(strNumber( /* "predisplaysize" */ 491), quarterword(assignDimen), halfword(dimenBase+preDisplaySizeCode))
- // \xref[pre_display_size_][\.[\\predisplaysize] primitive]
- prg.primitive(strNumber( /* "displaywidth" */ 492), quarterword(assignDimen), halfword(dimenBase+displayWidthCode))
- // \xref[display_width_][\.[\\displaywidth] primitive]
- prg.primitive(strNumber( /* "displayindent" */ 493), quarterword(assignDimen), halfword(dimenBase+displayIndentCode))
- // \xref[display_indent_][\.[\\displayindent] primitive]
- prg.primitive(strNumber( /* "overfullrule" */ 494), quarterword(assignDimen), halfword(dimenBase+overfullRuleCode))
- // \xref[overfull_rule_][\.[\\overfullrule] primitive]
- prg.primitive(strNumber( /* "hangindent" */ 495), quarterword(assignDimen), halfword(dimenBase+hangIndentCode))
- // \xref[hang_indent_][\.[\\hangindent] primitive]
- prg.primitive(strNumber( /* "hoffset" */ 496), quarterword(assignDimen), halfword(dimenBase+hOffsetCode))
- // \xref[h_offset_][\.[\\hoffset] primitive]
- prg.primitive(strNumber( /* "voffset" */ 497), quarterword(assignDimen), halfword(dimenBase+vOffsetCode))
- // \xref[v_offset_][\.[\\voffset] primitive]
- prg.primitive(strNumber( /* "emergencystretch" */ 498), quarterword(assignDimen), halfword(dimenBase+emergencyStretchCode))
- // \xref[emergency_stretch_][\.[\\emergencystretch] primitive]
- prg.primitive(strNumber(' '), quarterword(exSpace), halfword(0))
- // \xref[Single-character primitives /][\quad\.[\\\ ]]
- prg.primitive(strNumber('/'), quarterword(italCorr), halfword(0))
- // \xref[Single-character primitives /][\quad\.[\\/]]
- prg.primitive(strNumber( /* "accent" */ 508), quarterword(accent), halfword(0))
- // \xref[accent_][\.[\\accent] primitive]
- prg.primitive(strNumber( /* "advance" */ 509), quarterword(advance), halfword(0))
- // \xref[advance_][\.[\\advance] primitive]
- prg.primitive(strNumber( /* "afterassignment" */ 510), quarterword(afterAssignment), halfword(0))
- // \xref[after_assignment_][\.[\\afterassignment] primitive]
- prg.primitive(strNumber( /* "aftergroup" */ 511), quarterword(afterGroup), halfword(0))
- // \xref[after_group_][\.[\\aftergroup] primitive]
- prg.primitive(strNumber( /* "begingroup" */ 512), quarterword(beginGroup), halfword(0))
- // \xref[begin_group_][\.[\\begingroup] primitive]
- prg.primitive(strNumber( /* "char" */ 513), quarterword(charNum), halfword(0))
- // \xref[char_][\.[\\char] primitive]
- prg.primitive(strNumber( /* "csname" */ 504), quarterword(csName), halfword(0))
- // \xref[cs_name_][\.[\\csname] primitive]
- prg.primitive(strNumber( /* "delimiter" */ 514), quarterword(delimNum), halfword(0))
- // \xref[delimiter_][\.[\\delimiter] primitive]
- prg.primitive(strNumber( /* "divide" */ 515), quarterword(divide), halfword(0))
- // \xref[divide_][\.[\\divide] primitive]
- prg.primitive(strNumber( /* "endcsname" */ 505), quarterword(endCsName), halfword(0))
- // \xref[end_cs_name_][\.[\\endcsname] primitive]
- prg.primitive(strNumber( /* "endgroup" */ 516), quarterword(endGroup), halfword(0))
- // \xref[end_group_][\.[\\endgroup] primitive]
- *prg.hash[frozenEndGroup-514].rh() = 516
- prg.eqtb[frozenEndGroup-1] = prg.eqtb[prg.curVal-1]
- prg.primitive(strNumber( /* "expandafter" */ 517), quarterword(expandAfter), halfword(0))
- // \xref[expand_after_][\.[\\expandafter] primitive]
- prg.primitive(strNumber( /* "font" */ 518), quarterword(defFont), halfword(0))
- // \xref[font_][\.[\\font] primitive]
- prg.primitive(strNumber( /* "fontdimen" */ 519), quarterword(assignFontDimen), halfword(0))
- // \xref[font_dimen_][\.[\\fontdimen] primitive]
- prg.primitive(strNumber( /* "halign" */ 520), quarterword(halign), halfword(0))
- // \xref[halign_][\.[\\halign] primitive]
- prg.primitive(strNumber( /* "hrule" */ 521), quarterword(hrule), halfword(0))
- // \xref[hrule_][\.[\\hrule] primitive]
- prg.primitive(strNumber( /* "ignorespaces" */ 522), quarterword(ignoreSpaces), halfword(0))
- // \xref[ignore_spaces_][\.[\\ignorespaces] primitive]
- prg.primitive(strNumber( /* "insert" */ 330), quarterword(insert), halfword(0))
- // \xref[insert_][\.[\\insert] primitive]
- prg.primitive(strNumber( /* "mark" */ 351), quarterword(mark), halfword(0))
- // \xref[mark_][\.[\\mark] primitive]
- prg.primitive(strNumber( /* "mathaccent" */ 523), quarterword(mathAccent), halfword(0))
- // \xref[math_accent_][\.[\\mathaccent] primitive]
- prg.primitive(strNumber( /* "mathchar" */ 524), quarterword(mathCharNum), halfword(0))
- // \xref[math_char_][\.[\\mathchar] primitive]
- prg.primitive(strNumber( /* "mathchoice" */ 525), quarterword(mathChoice), halfword(0))
- // \xref[math_choice_][\.[\\mathchoice] primitive]
- prg.primitive(strNumber( /* "multiply" */ 526), quarterword(multiply), halfword(0))
- // \xref[multiply_][\.[\\multiply] primitive]
- prg.primitive(strNumber( /* "noalign" */ 527), quarterword(noAlign), halfword(0))
- // \xref[no_align_][\.[\\noalign] primitive]
- prg.primitive(strNumber( /* "noboundary" */ 528), quarterword(noBoundary), halfword(0))
- // \xref[no_boundary_][\.[\\noboundary] primitive]
- prg.primitive(strNumber( /* "noexpand" */ 529), quarterword(noExpand), halfword(0))
- // \xref[no_expand_][\.[\\noexpand] primitive]
- prg.primitive(strNumber( /* "nonscript" */ 335), quarterword(nonScript), halfword(0))
- // \xref[non_script_][\.[\\nonscript] primitive]
- prg.primitive(strNumber( /* "omit" */ 530), quarterword(omit), halfword(0))
- // \xref[omit_][\.[\\omit] primitive]
- prg.primitive(strNumber( /* "parshape" */ 408), quarterword(setShape), halfword(0))
- // \xref[par_shape_][\.[\\parshape] primitive]
- prg.primitive(strNumber( /* "penalty" */ 531), quarterword(breakPenalty), halfword(0))
- // \xref[penalty_][\.[\\penalty] primitive]
- prg.primitive(strNumber( /* "prevgraf" */ 532), quarterword(setPrevGraf), halfword(0))
- // \xref[prev_graf_][\.[\\prevgraf] primitive]
- prg.primitive(strNumber( /* "radical" */ 533), quarterword(radical), halfword(0))
- // \xref[radical_][\.[\\radical] primitive]
- prg.primitive(strNumber( /* "read" */ 534), quarterword(readToCs), halfword(0))
- // \xref[read_][\.[\\read] primitive]
- prg.primitive(strNumber( /* "relax" */ 535), quarterword(relax), halfword(256)) // cf.\ |scan_file_name|
- // \xref[relax_][\.[\\relax] primitive]
- *prg.hash[frozenRelax-514].rh() = 535
- prg.eqtb[frozenRelax-1] = prg.eqtb[prg.curVal-1]
- prg.primitive(strNumber( /* "setbox" */ 536), quarterword(setBox), halfword(0))
- // \xref[set_box_][\.[\\setbox] primitive]
- prg.primitive(strNumber( /* "the" */ 537), quarterword(the), halfword(0))
- // \xref[the_][\.[\\the] primitive]
- prg.primitive(strNumber( /* "toks" */ 407), quarterword(toksRegister), halfword(0))
- // \xref[toks_][\.[\\toks] primitive]
- prg.primitive(strNumber( /* "vadjust" */ 352), quarterword(vadjust), halfword(0))
- // \xref[vadjust_][\.[\\vadjust] primitive]
- prg.primitive(strNumber( /* "valign" */ 538), quarterword(valign), halfword(0))
- // \xref[valign_][\.[\\valign] primitive]
- prg.primitive(strNumber( /* "vcenter" */ 539), quarterword(vcenter), halfword(0))
- // \xref[vcenter_][\.[\\vcenter] primitive]
- prg.primitive(strNumber( /* "vrule" */ 540), quarterword(vrule), halfword(0))
- // \xref[vrule_][\.[\\vrule] primitive]
- prg.primitive(strNumber( /* "par" */ 597), quarterword(parEnd), halfword(256)) // cf.\ |scan_file_name|
- // \xref[par_][\.[\\par] primitive]
- prg.parLoc = uint16(prg.curVal)
- prg.parToken = uint16(07777 + int32(prg.parLoc))
- prg.primitive(strNumber( /* "input" */ 629), quarterword(input), halfword(0))
- // \xref[input_][\.[\\input] primitive]
- prg.primitive(strNumber( /* "endinput" */ 630), quarterword(input), halfword(1))
- // \xref[end_input_][\.[\\endinput] primitive]
- prg.primitive(strNumber( /* "topmark" */ 631), quarterword(topBotMark), halfword(topMarkCode))
- // \xref[top_mark_][\.[\\topmark] primitive]
- prg.primitive(strNumber( /* "firstmark" */ 632), quarterword(topBotMark), halfword(firstMarkCode))
- // \xref[first_mark_][\.[\\firstmark] primitive]
- prg.primitive(strNumber( /* "botmark" */ 633), quarterword(topBotMark), halfword(botMarkCode))
- // \xref[bot_mark_][\.[\\botmark] primitive]
- prg.primitive(strNumber( /* "splitfirstmark" */ 634), quarterword(topBotMark), halfword(splitFirstMarkCode))
- // \xref[split_first_mark_][\.[\\splitfirstmark] primitive]
- prg.primitive(strNumber( /* "splitbotmark" */ 635), quarterword(topBotMark), halfword(splitBotMarkCode))
- // \xref[split_bot_mark_][\.[\\splitbotmark] primitive]
- prg.primitive(strNumber( /* "count" */ 476), quarterword(register), halfword(intVal))
- // \xref[count_][\.[\\count] primitive]
- prg.primitive(strNumber( /* "dimen" */ 500), quarterword(register), halfword(dimenVal))
- // \xref[dimen_][\.[\\dimen] primitive]
- prg.primitive(strNumber( /* "skip" */ 395), quarterword(register), halfword(glueVal))
- // \xref[skip_][\.[\\skip] primitive]
- prg.primitive(strNumber( /* "muskip" */ 396), quarterword(register), halfword(muVal))
- // \xref[mu_skip_][\.[\\muskip] primitive]
- prg.primitive(strNumber( /* "spacefactor" */ 668), quarterword(setAux), halfword(hmode))
- // \xref[space_factor_][\.[\\spacefactor] primitive]
- prg.primitive(strNumber( /* "prevdepth" */ 669), quarterword(setAux), halfword(vmode))
- // \xref[prev_depth_][\.[\\prevdepth] primitive]
- prg.primitive(strNumber( /* "deadcycles" */ 670), quarterword(setPageInt), halfword(0))
- // \xref[dead_cycles_][\.[\\deadcycles] primitive]
- prg.primitive(strNumber( /* "insertpenalties" */ 671), quarterword(setPageInt), halfword(1))
- // \xref[insert_penalties_][\.[\\insertpenalties] primitive]
- prg.primitive(strNumber( /* "wd" */ 672), quarterword(setBoxDimen), halfword(widthOffset))
- // \xref[wd_][\.[\\wd] primitive]
- prg.primitive(strNumber( /* "ht" */ 673), quarterword(setBoxDimen), halfword(heightOffset))
- // \xref[ht_][\.[\\ht] primitive]
- prg.primitive(strNumber( /* "dp" */ 674), quarterword(setBoxDimen), halfword(depthOffset))
- // \xref[dp_][\.[\\dp] primitive]
- prg.primitive(strNumber( /* "lastpenalty" */ 675), quarterword(lastItem), halfword(intVal))
- // \xref[last_penalty_][\.[\\lastpenalty] primitive]
- prg.primitive(strNumber( /* "lastkern" */ 676), quarterword(lastItem), halfword(dimenVal))
- // \xref[last_kern_][\.[\\lastkern] primitive]
- prg.primitive(strNumber( /* "lastskip" */ 677), quarterword(lastItem), halfword(glueVal))
- // \xref[last_skip_][\.[\\lastskip] primitive]
- prg.primitive(strNumber( /* "inputlineno" */ 678), quarterword(lastItem), halfword(inputLineNoCode))
- // \xref[input_line_no_][\.[\\inputlineno] primitive]
- prg.primitive(strNumber( /* "badness" */ 679), quarterword(lastItem), halfword(badnessCode))
- // \xref[badness_][\.[\\badness] primitive]
- prg.primitive(strNumber( /* "number" */ 735), quarterword(convert), halfword(numberCode))
- // \xref[number_][\.[\\number] primitive]
- prg.primitive(strNumber( /* "romannumeral" */ 736), quarterword(convert), halfword(romanNumeralCode))
- // \xref[roman_numeral_][\.[\\romannumeral] primitive]
- prg.primitive(strNumber( /* "string" */ 737), quarterword(convert), halfword(stringCode))
- // \xref[string_][\.[\\string] primitive]
- prg.primitive(strNumber( /* "meaning" */ 738), quarterword(convert), halfword(meaningCode))
- // \xref[meaning_][\.[\\meaning] primitive]
- prg.primitive(strNumber( /* "fontname" */ 739), quarterword(convert), halfword(fontNameCode))
- // \xref[font_name_][\.[\\fontname] primitive]
- prg.primitive(strNumber( /* "jobname" */ 740), quarterword(convert), halfword(jobNameCode))
- // \xref[job_name_][\.[\\jobname] primitive]
- prg.primitive(strNumber( /* "if" */ 757), quarterword(ifTest), halfword(ifCharCode))
- // \xref[if_char_][\.[\\if] primitive]
- prg.primitive(strNumber( /* "ifcat" */ 758), quarterword(ifTest), halfword(ifCatCode))
- // \xref[if_cat_code_][\.[\\ifcat] primitive]
- prg.primitive(strNumber( /* "ifnum" */ 759), quarterword(ifTest), halfword(ifIntCode))
- // \xref[if_int_][\.[\\ifnum] primitive]
- prg.primitive(strNumber( /* "ifdim" */ 760), quarterword(ifTest), halfword(ifDimCode))
- // \xref[if_dim_][\.[\\ifdim] primitive]
- prg.primitive(strNumber( /* "ifodd" */ 761), quarterword(ifTest), halfword(ifOddCode))
- // \xref[if_odd_][\.[\\ifodd] primitive]
- prg.primitive(strNumber( /* "ifvmode" */ 762), quarterword(ifTest), halfword(ifVmodeCode))
- // \xref[if_vmode_][\.[\\ifvmode] primitive]
- prg.primitive(strNumber( /* "ifhmode" */ 763), quarterword(ifTest), halfword(ifHmodeCode))
- // \xref[if_hmode_][\.[\\ifhmode] primitive]
- prg.primitive(strNumber( /* "ifmmode" */ 764), quarterword(ifTest), halfword(ifMmodeCode))
- // \xref[if_mmode_][\.[\\ifmmode] primitive]
- prg.primitive(strNumber( /* "ifinner" */ 765), quarterword(ifTest), halfword(ifInnerCode))
- // \xref[if_inner_][\.[\\ifinner] primitive]
- prg.primitive(strNumber( /* "ifvoid" */ 766), quarterword(ifTest), halfword(ifVoidCode))
- // \xref[if_void_][\.[\\ifvoid] primitive]
- prg.primitive(strNumber( /* "ifhbox" */ 767), quarterword(ifTest), halfword(ifHboxCode))
- // \xref[if_hbox_][\.[\\ifhbox] primitive]
- prg.primitive(strNumber( /* "ifvbox" */ 768), quarterword(ifTest), halfword(ifVboxCode))
- // \xref[if_vbox_][\.[\\ifvbox] primitive]
- prg.primitive(strNumber( /* "ifx" */ 769), quarterword(ifTest), halfword(ifxCode))
- // \xref[ifx_][\.[\\ifx] primitive]
- prg.primitive(strNumber( /* "ifeof" */ 770), quarterword(ifTest), halfword(ifEofCode))
- // \xref[if_eof_][\.[\\ifeof] primitive]
- prg.primitive(strNumber( /* "iftrue" */ 771), quarterword(ifTest), halfword(ifTrueCode))
- // \xref[if_true_][\.[\\iftrue] primitive]
- prg.primitive(strNumber( /* "iffalse" */ 772), quarterword(ifTest), halfword(ifFalseCode))
- // \xref[if_false_][\.[\\iffalse] primitive]
- prg.primitive(strNumber( /* "ifcase" */ 773), quarterword(ifTest), halfword(ifCaseCode))
- // \xref[if_case_][\.[\\ifcase] primitive]
- prg.primitive(strNumber( /* "fi" */ 774), quarterword(fiOrElse), halfword(fiCode))
- // \xref[fi_][\.[\\fi] primitive]
- *prg.hash[frozenFi-514].rh() = 774
- prg.eqtb[frozenFi-1] = prg.eqtb[prg.curVal-1]
- prg.primitive(strNumber( /* "or" */ 775), quarterword(fiOrElse), halfword(orCode))
- // \xref[or_][\.[\\or] primitive]
- prg.primitive(strNumber( /* "else" */ 776), quarterword(fiOrElse), halfword(elseCode))
- // \xref[else_][\.[\\else] primitive]
- prg.primitive(strNumber( /* "nullfont" */ 801), quarterword(setFont), halfword(fontBase))
- // \xref[null_font_][\.[\\nullfont] primitive]
- *prg.hash[frozenNullFont-514].rh() = 801
- prg.eqtb[frozenNullFont-1] = prg.eqtb[prg.curVal-1]
- prg.primitive(strNumber( /* "span" */ 898), quarterword(tabMark), halfword(spanCode))
- // \xref[span_][\.[\\span] primitive]
- prg.primitive(strNumber( /* "cr" */ 899), quarterword(carRet), halfword(crCode))
- // \xref[cr_][\.[\\cr] primitive]
- *prg.hash[frozenCr-514].rh() = 899
- prg.eqtb[frozenCr-1] = prg.eqtb[prg.curVal-1]
- prg.primitive(strNumber( /* "crcr" */ 900), quarterword(carRet), halfword(crCrCode))
- // \xref[cr_cr_][\.[\\crcr] primitive]
- *prg.hash[frozenEndTemplate-514].rh() = 901
- *prg.hash[frozenEndv-514].rh() = 901
- // \xref[endtemplate]
- *(*prg.eqtb[frozenEndv-1].hh()).b0() = byte(endv)
- *(*prg.eqtb[frozenEndv-1].hh()).rh() = uint16(30000 - 11)
- *(*prg.eqtb[frozenEndv-1].hh()).b1() = byte(levelOne)
- prg.eqtb[frozenEndTemplate-1] = prg.eqtb[frozenEndv-1]
- *(*prg.eqtb[frozenEndTemplate-1].hh()).b0() = byte(endTemplate)
- prg.primitive(strNumber( /* "pagegoal" */ 970), quarterword(setPageDimen), halfword(0))
- // \xref[page_goal_][\.[\\pagegoal] primitive]
- prg.primitive(strNumber( /* "pagetotal" */ 971), quarterword(setPageDimen), halfword(1))
- // \xref[page_total_][\.[\\pagetotal] primitive]
- prg.primitive(strNumber( /* "pagestretch" */ 972), quarterword(setPageDimen), halfword(2))
- // \xref[page_stretch_][\.[\\pagestretch] primitive]
- prg.primitive(strNumber( /* "pagefilstretch" */ 973), quarterword(setPageDimen), halfword(3))
- // \xref[page_fil_stretch_][\.[\\pagefilstretch] primitive]
- prg.primitive(strNumber( /* "pagefillstretch" */ 974), quarterword(setPageDimen), halfword(4))
- // \xref[page_fill_stretch_][\.[\\pagefillstretch] primitive]
- prg.primitive(strNumber( /* "pagefilllstretch" */ 975), quarterword(setPageDimen), halfword(5))
- // \xref[page_filll_stretch_][\.[\\pagefilllstretch] primitive]
- prg.primitive(strNumber( /* "pageshrink" */ 976), quarterword(setPageDimen), halfword(6))
- // \xref[page_shrink_][\.[\\pageshrink] primitive]
- prg.primitive(strNumber( /* "pagedepth" */ 977), quarterword(setPageDimen), halfword(7))
- // \xref[page_depth_][\.[\\pagedepth] primitive]
- prg.primitive(strNumber( /* "end" */ 1025), quarterword(stop), halfword(0))
- // \xref[end_][\.[\\end] primitive]
- prg.primitive(strNumber( /* "dump" */ 1026), quarterword(stop), halfword(1))
- // \xref[dump_][\.[\\dump] primitive]
- prg.primitive(strNumber( /* "hskip" */ 1027), quarterword(hskip), halfword(skipCode))
- // \xref[hskip_][\.[\\hskip] primitive]
- prg.primitive(strNumber( /* "hfil" */ 1028), quarterword(hskip), halfword(filCode))
- // \xref[hfil_][\.[\\hfil] primitive]
- prg.primitive(strNumber( /* "hfill" */ 1029), quarterword(hskip), halfword(fillCode))
- // \xref[hfill_][\.[\\hfill] primitive]
- prg.primitive(strNumber( /* "hss" */ 1030), quarterword(hskip), halfword(ssCode))
- // \xref[hss_][\.[\\hss] primitive]
- prg.primitive(strNumber( /* "hfilneg" */ 1031), quarterword(hskip), halfword(filNegCode))
- // \xref[hfil_neg_][\.[\\hfilneg] primitive]
- prg.primitive(strNumber( /* "vskip" */ 1032), quarterword(vskip), halfword(skipCode))
- // \xref[vskip_][\.[\\vskip] primitive]
- prg.primitive(strNumber( /* "vfil" */ 1033), quarterword(vskip), halfword(filCode))
- // \xref[vfil_][\.[\\vfil] primitive]
- prg.primitive(strNumber( /* "vfill" */ 1034), quarterword(vskip), halfword(fillCode))
- // \xref[vfill_][\.[\\vfill] primitive]
- prg.primitive(strNumber( /* "vss" */ 1035), quarterword(vskip), halfword(ssCode))
- // \xref[vss_][\.[\\vss] primitive]
- prg.primitive(strNumber( /* "vfilneg" */ 1036), quarterword(vskip), halfword(filNegCode))
- // \xref[vfil_neg_][\.[\\vfilneg] primitive]
- prg.primitive(strNumber( /* "mskip" */ 336), quarterword(mskip), halfword(mskipCode))
- // \xref[mskip_][\.[\\mskip] primitive]
- prg.primitive(strNumber( /* "kern" */ 340), quarterword(kern), halfword(explicit))
- // \xref[kern_][\.[\\kern] primitive]
- prg.primitive(strNumber( /* "mkern" */ 342), quarterword(mkern), halfword(muGlue))
- // \xref[mkern_][\.[\\mkern] primitive]
- prg.primitive(strNumber( /* "moveleft" */ 1054), quarterword(hmove), halfword(1))
- // \xref[move_left_][\.[\\moveleft] primitive]
- prg.primitive(strNumber( /* "moveright" */ 1055), quarterword(hmove), halfword(0))
- // \xref[move_right_][\.[\\moveright] primitive]
- prg.primitive(strNumber( /* "raise" */ 1056), quarterword(vmove), halfword(1))
- // \xref[raise_][\.[\\raise] primitive]
- prg.primitive(strNumber( /* "lower" */ 1057), quarterword(vmove), halfword(0))
- // \xref[lower_][\.[\\lower] primitive]
- prg.primitive(strNumber( /* "box" */ 409), quarterword(makeBox), halfword(boxCode))
- // \xref[box_][\.[\\box] primitive]
- prg.primitive(strNumber( /* "copy" */ 1058), quarterword(makeBox), halfword(copyCode))
- // \xref[copy_][\.[\\copy] primitive]
- prg.primitive(strNumber( /* "lastbox" */ 1059), quarterword(makeBox), halfword(lastBoxCode))
- // \xref[last_box_][\.[\\lastbox] primitive]
- prg.primitive(strNumber( /* "vsplit" */ 965), quarterword(makeBox), halfword(vsplitCode))
- // \xref[vsplit_][\.[\\vsplit] primitive]
- prg.primitive(strNumber( /* "vtop" */ 1060), quarterword(makeBox), halfword(vtopCode))
- // \xref[vtop_][\.[\\vtop] primitive]
- prg.primitive(strNumber( /* "vbox" */ 967), quarterword(makeBox), halfword(vtopCode+vmode))
- // \xref[vbox_][\.[\\vbox] primitive]
- prg.primitive(strNumber( /* "hbox" */ 1061), quarterword(makeBox), halfword(vtopCode+hmode))
- // \xref[hbox_][\.[\\hbox] primitive]
- prg.primitive(strNumber( /* "shipout" */ 1062), quarterword(leaderShip), halfword(aLeaders-1)) // |ship_out_flag=leader_flag-1|
- // \xref[ship_out_][\.[\\shipout] primitive]
- prg.primitive(strNumber( /* "leaders" */ 1063), quarterword(leaderShip), halfword(aLeaders))
- // \xref[leaders_][\.[\\leaders] primitive]
- prg.primitive(strNumber( /* "cleaders" */ 1064), quarterword(leaderShip), halfword(cLeaders))
- // \xref[c_leaders_][\.[\\cleaders] primitive]
- prg.primitive(strNumber( /* "xleaders" */ 1065), quarterword(leaderShip), halfword(xLeaders))
- // \xref[x_leaders_][\.[\\xleaders] primitive]
- prg.primitive(strNumber( /* "indent" */ 1080), quarterword(startPar), halfword(1))
- // \xref[indent_][\.[\\indent] primitive]
- prg.primitive(strNumber( /* "noindent" */ 1081), quarterword(startPar), halfword(0))
- // \xref[no_indent_][\.[\\noindent] primitive]
- prg.primitive(strNumber( /* "unpenalty" */ 1090), quarterword(removeItem), halfword(penaltyNode))
- // \xref[un_penalty_][\.[\\unpenalty] primitive]
- prg.primitive(strNumber( /* "unkern" */ 1091), quarterword(removeItem), halfword(kernNode))
- // \xref[un_kern_][\.[\\unkern] primitive]
- prg.primitive(strNumber( /* "unskip" */ 1092), quarterword(removeItem), halfword(glueNode))
- // \xref[un_skip_][\.[\\unskip] primitive]
- prg.primitive(strNumber( /* "unhbox" */ 1093), quarterword(unHbox), halfword(boxCode))
- // \xref[un_hbox_][\.[\\unhbox] primitive]
- prg.primitive(strNumber( /* "unhcopy" */ 1094), quarterword(unHbox), halfword(copyCode))
- // \xref[un_hcopy_][\.[\\unhcopy] primitive]
- prg.primitive(strNumber( /* "unvbox" */ 1095), quarterword(unVbox), halfword(boxCode))
- // \xref[un_vbox_][\.[\\unvbox] primitive]
- prg.primitive(strNumber( /* "unvcopy" */ 1096), quarterword(unVbox), halfword(copyCode))
- // \xref[un_vcopy_][\.[\\unvcopy] primitive]
- prg.primitive(strNumber('-'), quarterword(discretionary), halfword(1))
- // \xref[Single-character primitives -][\quad\.[\\-]]
- prg.primitive(strNumber( /* "discretionary" */ 349), quarterword(discretionary), halfword(0))
- // \xref[discretionary_][\.[\\discretionary] primitive]
- prg.primitive(strNumber( /* "eqno" */ 1127), quarterword(eqNo), halfword(0))
- // \xref[eq_no_][\.[\\eqno] primitive]
- prg.primitive(strNumber( /* "leqno" */ 1128), quarterword(eqNo), halfword(1))
- // \xref[leq_no_][\.[\\leqno] primitive]
- prg.primitive(strNumber( /* "mathord" */ 866), quarterword(mathComp), halfword(ordNoad))
- // \xref[math_ord_][\.[\\mathord] primitive]
- prg.primitive(strNumber( /* "mathop" */ 867), quarterword(mathComp), halfword(opNoad))
- // \xref[math_op_][\.[\\mathop] primitive]
- prg.primitive(strNumber( /* "mathbin" */ 868), quarterword(mathComp), halfword(binNoad))
- // \xref[math_bin_][\.[\\mathbin] primitive]
- prg.primitive(strNumber( /* "mathrel" */ 869), quarterword(mathComp), halfword(relNoad))
- // \xref[math_rel_][\.[\\mathrel] primitive]
- prg.primitive(strNumber( /* "mathopen" */ 870), quarterword(mathComp), halfword(openNoad))
- // \xref[math_open_][\.[\\mathopen] primitive]
- prg.primitive(strNumber( /* "mathclose" */ 871), quarterword(mathComp), halfword(closeNoad))
- // \xref[math_close_][\.[\\mathclose] primitive]
- prg.primitive(strNumber( /* "mathpunct" */ 872), quarterword(mathComp), halfword(punctNoad))
- // \xref[math_punct_][\.[\\mathpunct] primitive]
- prg.primitive(strNumber( /* "mathinner" */ 873), quarterword(mathComp), halfword(innerNoad))
- // \xref[math_inner_][\.[\\mathinner] primitive]
- prg.primitive(strNumber( /* "underline" */ 875), quarterword(mathComp), halfword(underNoad))
- // \xref[underline_][\.[\\underline] primitive]
- prg.primitive(strNumber( /* "overline" */ 874), quarterword(mathComp), halfword(overNoad))
- // \xref[overline_][\.[\\overline] primitive]
- prg.primitive(strNumber( /* "displaylimits" */ 1129), quarterword(limitSwitch), halfword(normal))
- // \xref[display_limits_][\.[\\displaylimits] primitive]
- prg.primitive(strNumber( /* "limits" */ 878), quarterword(limitSwitch), halfword(limits))
- // \xref[limits_][\.[\\limits] primitive]
- prg.primitive(strNumber( /* "nolimits" */ 879), quarterword(limitSwitch), halfword(noLimits))
- // \xref[no_limits_][\.[\\nolimits] primitive]
- prg.primitive(strNumber( /* "displaystyle" */ 861), quarterword(mathStyle), halfword(displayStyle))
- // \xref[display_style_][\.[\\displaystyle] primitive]
- prg.primitive(strNumber( /* "textstyle" */ 862), quarterword(mathStyle), halfword(textStyle))
- // \xref[text_style_][\.[\\textstyle] primitive]
- prg.primitive(strNumber( /* "scriptstyle" */ 863), quarterword(mathStyle), halfword(scriptStyle))
- // \xref[script_style_][\.[\\scriptstyle] primitive]
- prg.primitive(strNumber( /* "scriptscriptstyle" */ 864), quarterword(mathStyle), halfword(scriptScriptStyle))
- // \xref[script_script_style_][\.[\\scriptscriptstyle] primitive]
- prg.primitive(strNumber( /* "above" */ 1147), quarterword(above), halfword(aboveCode))
- // \xref[above_][\.[\\above] primitive]
- prg.primitive(strNumber( /* "over" */ 1148), quarterword(above), halfword(overCode))
- // \xref[over_][\.[\\over] primitive]
- prg.primitive(strNumber( /* "atop" */ 1149), quarterword(above), halfword(atopCode))
- // \xref[atop_][\.[\\atop] primitive]
- prg.primitive(strNumber( /* "abovewithdelims" */ 1150), quarterword(above), halfword(delimitedCode+aboveCode))
- // \xref[above_with_delims_][\.[\\abovewithdelims] primitive]
- prg.primitive(strNumber( /* "overwithdelims" */ 1151), quarterword(above), halfword(delimitedCode+overCode))
- // \xref[over_with_delims_][\.[\\overwithdelims] primitive]
- prg.primitive(strNumber( /* "atopwithdelims" */ 1152), quarterword(above), halfword(delimitedCode+atopCode))
- // \xref[atop_with_delims_][\.[\\atopwithdelims] primitive]
- prg.primitive(strNumber( /* "left" */ 876), quarterword(leftRight), halfword(leftNoad))
- // \xref[left_][\.[\\left] primitive]
- prg.primitive(strNumber( /* "right" */ 877), quarterword(leftRight), halfword(rightNoad))
- // \xref[right_][\.[\\right] primitive]
- *prg.hash[frozenRight-514].rh() = 877
- prg.eqtb[frozenRight-1] = prg.eqtb[prg.curVal-1]
- prg.primitive(strNumber( /* "long" */ 1171), quarterword(prefix), halfword(1))
- // \xref[long_][\.[\\long] primitive]
- prg.primitive(strNumber( /* "outer" */ 1172), quarterword(prefix), halfword(2))
- // \xref[outer_][\.[\\outer] primitive]
- prg.primitive(strNumber( /* "global" */ 1173), quarterword(prefix), halfword(4))
- // \xref[global_][\.[\\global] primitive]
- prg.primitive(strNumber( /* "def" */ 1174), quarterword(def), halfword(0))
- // \xref[def_][\.[\\def] primitive]
- prg.primitive(strNumber( /* "gdef" */ 1175), quarterword(def), halfword(1))
- // \xref[gdef_][\.[\\gdef] primitive]
- prg.primitive(strNumber( /* "edef" */ 1176), quarterword(def), halfword(2))
- // \xref[edef_][\.[\\edef] primitive]
- prg.primitive(strNumber( /* "xdef" */ 1177), quarterword(def), halfword(3))
- // \xref[xdef_][\.[\\xdef] primitive]
- prg.primitive(strNumber( /* "let" */ 1191), quarterword(let), halfword(normal))
- // \xref[let_][\.[\\let] primitive]
- prg.primitive(strNumber( /* "futurelet" */ 1192), quarterword(let), halfword(normal+1))
- // \xref[future_let_][\.[\\futurelet] primitive]
- prg.primitive(strNumber( /* "chardef" */ 1193), quarterword(shorthandDef), halfword(charDefCode))
- // \xref[char_def_][\.[\\chardef] primitive]
- prg.primitive(strNumber( /* "mathchardef" */ 1194), quarterword(shorthandDef), halfword(mathCharDefCode))
- // \xref[math_char_def_][\.[\\mathchardef] primitive]
- prg.primitive(strNumber( /* "countdef" */ 1195), quarterword(shorthandDef), halfword(countDefCode))
- // \xref[count_def_][\.[\\countdef] primitive]
- prg.primitive(strNumber( /* "dimendef" */ 1196), quarterword(shorthandDef), halfword(dimenDefCode))
- // \xref[dimen_def_][\.[\\dimendef] primitive]
- prg.primitive(strNumber( /* "skipdef" */ 1197), quarterword(shorthandDef), halfword(skipDefCode))
- // \xref[skip_def_][\.[\\skipdef] primitive]
- prg.primitive(strNumber( /* "muskipdef" */ 1198), quarterword(shorthandDef), halfword(muSkipDefCode))
- // \xref[mu_skip_def_][\.[\\muskipdef] primitive]
- prg.primitive(strNumber( /* "toksdef" */ 1199), quarterword(shorthandDef), halfword(toksDefCode))
- // \xref[toks_def_][\.[\\toksdef] primitive]
- prg.primitive(strNumber( /* "catcode" */ 415), quarterword(defCode), halfword(catCodeBase))
- // \xref[cat_code_][\.[\\catcode] primitive]
- prg.primitive(strNumber( /* "mathcode" */ 419), quarterword(defCode), halfword(mathCodeBase))
- // \xref[math_code_][\.[\\mathcode] primitive]
- prg.primitive(strNumber( /* "lccode" */ 416), quarterword(defCode), halfword(lcCodeBase))
- // \xref[lc_code_][\.[\\lccode] primitive]
- prg.primitive(strNumber( /* "uccode" */ 417), quarterword(defCode), halfword(ucCodeBase))
- // \xref[uc_code_][\.[\\uccode] primitive]
- prg.primitive(strNumber( /* "sfcode" */ 418), quarterword(defCode), halfword(sfCodeBase))
- // \xref[sf_code_][\.[\\sfcode] primitive]
- prg.primitive(strNumber( /* "delcode" */ 477), quarterword(defCode), halfword(delCodeBase))
- // \xref[del_code_][\.[\\delcode] primitive]
- prg.primitive(strNumber( /* "textfont" */ 412), quarterword(defFamily), halfword(mathFontBase))
- // \xref[text_font_][\.[\\textfont] primitive]
- prg.primitive(strNumber( /* "scriptfont" */ 413), quarterword(defFamily), halfword(mathFontBase+scriptSize))
- // \xref[script_font_][\.[\\scriptfont] primitive]
- prg.primitive(strNumber( /* "scriptscriptfont" */ 414), quarterword(defFamily), halfword(mathFontBase+scriptScriptSize))
- // \xref[script_script_font_][\.[\\scriptscriptfont] primitive]
- prg.primitive(strNumber( /* "hyphenation" */ 941), quarterword(hyphData), halfword(0))
- // \xref[hyphenation_][\.[\\hyphenation] primitive]
- prg.primitive(strNumber( /* "patterns" */ 953), quarterword(hyphData), halfword(1))
- // \xref[patterns_][\.[\\patterns] primitive]
- prg.primitive(strNumber( /* "hyphenchar" */ 1217), quarterword(assignFontInt), halfword(0))
- // \xref[hyphen_char_][\.[\\hyphenchar] primitive]
- prg.primitive(strNumber( /* "skewchar" */ 1218), quarterword(assignFontInt), halfword(1))
- // \xref[skew_char_][\.[\\skewchar] primitive]
- prg.primitive(strNumber( /* "batchmode" */ 274), quarterword(setInteraction), halfword(batchMode))
- // \xref[batch_mode_][\.[\\batchmode] primitive]
- prg.primitive(strNumber( /* "nonstopmode" */ 275), quarterword(setInteraction), halfword(nonstopMode))
- // \xref[nonstop_mode_][\.[\\nonstopmode] primitive]
- prg.primitive(strNumber( /* "scrollmode" */ 276), quarterword(setInteraction), halfword(scrollMode))
- // \xref[scroll_mode_][\.[\\scrollmode] primitive]
- prg.primitive(strNumber( /* "errorstopmode" */ 1227), quarterword(setInteraction), halfword(errorStopMode))
- // \xref[error_stop_mode_][\.[\\errorstopmode] primitive]
- prg.primitive(strNumber( /* "openin" */ 1228), quarterword(inStream), halfword(1))
- // \xref[open_in_][\.[\\openin] primitive]
- prg.primitive(strNumber( /* "closein" */ 1229), quarterword(inStream), halfword(0))
- // \xref[close_in_][\.[\\closein] primitive]
- prg.primitive(strNumber( /* "message" */ 1230), quarterword(message), halfword(0))
- // \xref[message_][\.[\\message] primitive]
- prg.primitive(strNumber( /* "errmessage" */ 1231), quarterword(message), halfword(1))
- // \xref[err_message_][\.[\\errmessage] primitive]
- prg.primitive(strNumber( /* "lowercase" */ 1237), quarterword(caseShift), halfword(lcCodeBase))
- // \xref[lowercase_][\.[\\lowercase] primitive]
- prg.primitive(strNumber( /* "uppercase" */ 1238), quarterword(caseShift), halfword(ucCodeBase))
- // \xref[uppercase_][\.[\\uppercase] primitive]
- prg.primitive(strNumber( /* "show" */ 1239), quarterword(xray), halfword(showCode))
- // \xref[show_][\.[\\show] primitive]
- prg.primitive(strNumber( /* "showbox" */ 1240), quarterword(xray), halfword(showBoxCode))
- // \xref[show_box_][\.[\\showbox] primitive]
- prg.primitive(strNumber( /* "showthe" */ 1241), quarterword(xray), halfword(showTheCode))
- // \xref[show_the_][\.[\\showthe] primitive]
- prg.primitive(strNumber( /* "showlists" */ 1242), quarterword(xray), halfword(showListsCode))
- // \xref[show_lists_code_][\.[\\showlists] primitive]
- prg.primitive(strNumber( /* "openout" */ 1285), quarterword(extension), halfword(openNode))
- // \xref[open_out_][\.[\\openout] primitive]
- prg.primitive(strNumber( /* "write" */ 594), quarterword(extension), halfword(writeNode))
- prg.writeLoc = uint16(prg.curVal)
- // \xref[write_][\.[\\write] primitive]
- prg.primitive(strNumber( /* "closeout" */ 1286), quarterword(extension), halfword(closeNode))
- // \xref[close_out_][\.[\\closeout] primitive]
- prg.primitive(strNumber( /* "special" */ 1287), quarterword(extension), halfword(specialNode))
- // \xref[special_][\.[\\special] primitive]
- prg.primitive(strNumber( /* "immediate" */ 1288), quarterword(extension), halfword(immediateCode))
- // \xref[immediate_][\.[\\immediate] primitive]
- prg.primitive(strNumber( /* "setlanguage" */ 1289), quarterword(extension), halfword(setLanguageCode))
- // \xref[set_language_][\.[\\setlanguage] primitive]
- prg.noNewControlSequence = true
- }
- // procedure debug_help; [routine to display various things]
- // label breakpoint,exit;
- // var k, l, m, n:integer;
- // begin ;
- // while true do begin ;
- // print_nl(["debug # (-1 to exit):"=]1284); ;
- // [ \xref[debug \#] ]
- // read(term_in,m);
- // if m<0 then goto exit
- // else if m=0 then
- // begin goto breakpoint;
- // [go to every declared label at least once]
- // breakpoint: m:=0; ['BREAKPOINT']
- //
- // end
- // else begin read(term_in,n);
- // case m of
- // [ \4 ]
- // [ Numbered cases for |debug_help| ]
- // 1: print_word(mem[n]); [display |mem[n]| in all forms]
- // 2: print_int( mem[ n].hh.lh );
- // 3: print_int( mem[ n].hh.rh );
- // 4: print_word(eqtb[n]);
- // 5: print_word(font_info[n]);
- // 6: print_word(save_stack[n]);
- // 7: show_box(n);
- // [show a box, abbreviated by |show_box_depth| and |show_box_breadth|]
- // 8: begin breadth_max:=10000; depth_threshold:=pool_size-pool_ptr-10;
- // show_node_list(n); [show a box in its entirety]
- // end;
- // 9: show_token_list(n,0 ,1000);
- // 10: slow_print(n);
- // 11: check_mem(n>0); [check wellformedness; print new busy locations if |n>0|]
- // 12: search_mem(n); [look for pointers to |n|]
- // 13: begin read(term_in,l); print_cmd_chr(n,l);
- // end;
- // 14: for k:=0 to n do print(buffer[k]);
- // 15: begin font_in_short_display:=font_base ; short_display(n);
- // end;
- // 16: panicking:=not panicking;
- //
- //
- // else print(["?"=]63)
- // end ;
- // end;
- // end;
- // exit:end;
- // [ ]
- // 1332.
- // tangle:pos tex.web:24275:61:
- // Now this is really it: \TeX\ starts and ends here.
- //
- // The initial test involving |ready_already| should be deleted if the
- // \PASCAL\ runtime system is smart enough to detect such a “mistake.”
- // \xref[system dependencies]
- func (prg *prg) main() {
- defer func() {
- if prg.dviFile != nil {
- prg.dviFile.Close()
- }
- if prg.fmtFile != nil {
- prg.fmtFile.Close()
- }
- if prg.logFile != nil {
- prg.logFile.Close()
- }
- if prg.poolFile != nil {
- prg.poolFile.Close()
- }
- if prg.stderr != nil {
- prg.stderr.Close()
- }
- if prg.stdin != nil {
- prg.stdin.Close()
- }
- if prg.stdout != nil {
- prg.stdout.Close()
- }
- if prg.termIn != nil {
- prg.termIn.Close()
- }
- if prg.termOut != nil {
- prg.termOut.Close()
- }
- if prg.tfmFile != nil {
- prg.tfmFile.Close()
- }
- }()
- prg.history = byte(fatalErrorStop) // in case we quit during initialization
- prg.termOut.Rewrite("TTY:", "/O") // open the terminal for output
- if prg.readyAlready == 314159 {
- goto startOfTex
- }
- // Check the “constant” values...
- prg.bad = 0
- if halfErrorLine < 30 || halfErrorLine > errorLine-15 {
- prg.bad = 1
- }
- if maxPrintLine < 60 {
- prg.bad = 2
- }
- if dviBufSize%8 != 0 {
- prg.bad = 3
- }
- if memBot+1100 > 30000 {
- prg.bad = 4
- }
- if hashPrime > hashSize {
- prg.bad = 5
- }
- if maxInOpen >= 128 {
- prg.bad = 6
- }
- if 30000 < 256+11 {
- prg.bad = 7
- } // we will want |null_list>255|
- if memMin != memBot || memMax != 30000 {
- prg.bad = 10
- }
- if memMin > memBot || memMax < 30000 {
- prg.bad = 10
- }
- if minQuarterword > 0 || maxQuarterword < 127 {
- prg.bad = 11
- }
- if 0 > 0 || 65535 < 32767 {
- prg.bad = 12
- }
- if minQuarterword < 0 || maxQuarterword > 65535 {
- prg.bad = 13
- }
- if memMin < 0 || memMax >= 65535 || memBot-memMin > 65535+1 {
- prg.bad = 14
- }
- if fontBase < minQuarterword || fontMax > maxQuarterword {
- prg.bad = 15
- }
- if fontMax > fontBase+256 {
- prg.bad = 16
- }
- if saveSize > 65535 || maxStrings > 65535 {
- prg.bad = 17
- }
- if bufSize > 65535 {
- prg.bad = 18
- }
- if maxQuarterword-minQuarterword < 255 {
- prg.bad = 19
- }
- if 07777+undefinedControlSequence > 65535 { // 07777=
- prg.bad = 21
- }
- if formatDefaultLength > fileNameSize {
- prg.bad = 31
- }
- if 2*65535 < 30000-memMin {
- prg.bad = 41
- }
- if prg.bad > 0 {
- prg.termOut.Writeln("Ouch---my internal constants have been clobbered!",
- "---case ", prg.bad, knuth.WriteWidth(1))
- // \xref[Ouch...clobbered]
- // \xref[Ouch...clobbered]
- goto finalEnd
- }
- prg.initialize() // set global variables to their starting values
- if !prg.getStringsStarted() {
- goto finalEnd
- }
- prg.initPrim() // call |primitive| for each primitive
- prg.initStrPtr = prg.strPtr
- prg.initPoolPtr = prg.poolPtr
- prg.fixDateAndTime()
- prg.readyAlready = 314159
- startOfTex:
- prg.selector = byte(termOnly)
- prg.tally = 0
- prg.termOffset = 0
- prg.fileOffset = 0
- prg.termOut.Write("This is TeX, Version 3.141592653 (gotex v0.0-prerelease)")
- if int32(prg.formatIdent) == 0 {
- prg.termOut.Writeln(" (no format preloaded)")
- } else {
- prg.slowPrint(int32(prg.formatIdent))
- prg.printLn()
- }
- prg.jobName = 0
- prg.nameInProgress = false
- prg.logOpened = false
- prg.outputFileName = 0
- // Get the first line of input and prepare to start
- {
- {
- prg.inputPtr = 0
- prg.maxInStack = 0
- prg.inOpen = 0
- prg.openParens = 0
- prg.maxBufStack = 0
- prg.paramPtr = 0
- prg.maxParamStack = 0
- prg.first = uint16(bufSize)
- for {
- prg.buffer[prg.first] = 0
- prg.first = uint16(int32(prg.first) - 1)
- if int32(prg.first) == 0 {
- break
- }
- }
- prg.scannerStatus = byte(normal)
- prg.warningIndex = 0
- prg.first = 1
- prg.curInput.stateField = byte(newLine)
- prg.curInput.startField = 1
- prg.curInput.indexField = 0
- prg.line = 0
- prg.curInput.nameField = 0
- prg.forceEof = false
- prg.alignState = 1000000
- if !prg.initTerminal() {
- goto finalEnd
- }
- prg.curInput.limitField = prg.last
- prg.first = uint16(int32(prg.last) + 1) // |init_terminal| has set |loc| and |last|
- }
- if int32(prg.formatIdent) == 0 || int32(prg.buffer[prg.curInput.locField]) == '&' {
- if int32(prg.formatIdent) != 0 {
- prg.initialize()
- } // erase preloaded format
- if !prg.openFmtFile() {
- goto finalEnd
- }
- if !prg.loadFmtFile() {
- prg.wClose(prg.fmtFile)
- goto finalEnd
- }
- prg.wClose(prg.fmtFile)
- for int32(prg.curInput.locField) < int32(prg.curInput.limitField) && int32(prg.buffer[prg.curInput.locField]) == ' ' {
- prg.curInput.locField = uint16(int32(prg.curInput.locField) + 1)
- }
- }
- if *prg.eqtb[intBase+endLineCharCode-1].int() < 0 || *prg.eqtb[intBase+endLineCharCode-1].int() > 255 {
- prg.curInput.limitField = uint16(int32(prg.curInput.limitField) - 1)
- } else {
- prg.buffer[prg.curInput.limitField] = byte(*prg.eqtb[intBase+endLineCharCode-1].int())
- }
- prg.fixDateAndTime()
- // Compute the magic offset
- prg.magicOffset = int32(prg.strStart[mathSpacing]) - 9*ordNoad
- // Initialize the print |selector|...
- if int32(prg.interaction) == batchMode {
- prg.selector = byte(noPrint)
- } else {
- prg.selector = byte(termOnly)
- }
- if int32(prg.curInput.locField) < int32(prg.curInput.limitField) && int32(*(*prg.eqtb[catCodeBase+int32(prg.buffer[prg.curInput.locField])-1].hh()).rh()) != escape {
- prg.startInput()
- }
- // \.[\\input] assumed
- }
- prg.history = byte(spotless) // ready to go!
- prg.mainControl() // come to life
- prg.finalCleanup() // prepare for death
- prg.closeFilesAndTerminate()
- finalEnd:
- prg.readyAlready = 0
- }
- // 1340. \[53] Extensions
- // tangle:pos tex.web:24529:17:
- // The program above includes a bunch of ``hooks'' that allow further
- // capabilities to be added without upsetting \TeX's basic structure.
- // Most of these hooks are concerned with ``whatsit'' nodes, which are
- // intended to be used for special purposes; whenever a new extension to
- // \TeX\ involves a new kind of whatsit node, a corresponding change needs
- // to be made to the routines below that deal with such nodes,
- // but it will usually be unnecessary to make many changes to the
- // other parts of this program.
- //
- // In order to demonstrate how extensions can be made, we shall treat
- // `\.[\\write]', `\.[\\openout]', `\.[\\closeout]', `\.[\\immediate]',
- // `\.[\\special]', and `\.[\\setlanguage]' as if they were extensions.
- // These commands are actually primitives of \TeX, and they should
- // appear in all implementations of the system; but let's try to imagine
- // that they aren't. Then the program below illustrates how a person
- // could add them.
- //
- // Sometimes, of course, an extension will require changes to \TeX\ itself;
- // no system of hooks could be complete enough for all conceivable extensions.
- // The features associated with `\.[\\write]' are almost all confined to the
- // following paragraphs, but there are small parts of the |print_ln| and
- // |print_char| procedures that were introduced specifically to \.[\\write]
- // characters. Furthermore one of the token lists recognized by the scanner
- // is a |write_text|; and there are a few other miscellaneous places where we
- // have already provided for some aspect of \.[\\write]. The goal of a \TeX\
- // extender should be to minimize alterations to the standard parts of the
- // program, and to avoid them completely if possible. He or she should also
- // be quite sure that there's no easy way to accomplish the desired goals
- // with the standard features that \TeX\ already has. ``Think thrice before
- // extending,'' because that may save a lot of work, and it will also keep
- // incompatible extensions of \TeX\ from proliferating.
- // \xref[system dependencies]
- // \xref[extensions to \TeX]
- // 1341.
- // tangle:pos tex.web:24562:23:
- // First let's consider the format of whatsit nodes that are used to represent
- // the data associated with \.[\\write] and its relatives. Recall that a whatsit
- // has |type=whatsit_node|, and the |subtype| is supposed to distinguish
- // different kinds of whatsits. Each node occupies two or more words; the
- // exact number is immaterial, as long as it is readily determined from the
- // |subtype| or other data.
- //
- // We shall introduce five |subtype| values here, corresponding to the
- // control sequences \.[\\openout], \.[\\write], \.[\\closeout], \.[\\special], and
- // \.[\\setlanguage]. The second word of I/O whatsits has a |write_stream| field
- // that identifies the write-stream number (0 to 15, or 16 for out-of-range and
- // positive, or 17 for out-of-range and negative).
- // In the case of \.[\\write] and \.[\\special], there is also a field that
- // points to the reference count of a token list that should be sent. In the
- // case of \.[\\openout], we need three words and three auxiliary subfields
- // to hold the string numbers for name, area, and extension.
- // 1379. \[54] System-dependent changes
- // tangle:pos tex.web:24985:31:
- // This section should be replaced, if necessary, by any special
- // modifications of the program
- // that are necessary to make \TeX\ work at a particular installation.
- // It is usually best to design your change file so that all changes to
- // previous sections preserve the section numbering; then everybody's version
- // will be consistent with the published program. More extensive changes,
- // which introduce new sections, can be inserted here; then only the index
- // itself will get a new section number.
- // \xref[system dependencies]
- // 1380. \[55] Index
- // tangle:pos tex.web:24996:12:
- // Here is where you can find all uses of each identifier in the program,
- // with underlined entries pointing to where the identifier was defined.
- // If the identifier is only one letter long, however, you get to see only
- // the underlined entries. [\sl All references are to section numbers instead of
- // page numbers.]
- //
- // This index also lists error messages and other aspects of the program
- // that you might want to look up some day. For example, the entry
- // for ``system dependencies'' lists all sections that should receive
- // special attention from people who are installing \TeX\ in a new
- // operating environment. A list of various things that can't happen appears
- // under ``this can't happen''. Approximately 40 sections are listed under
- // ``inner loop''; these account for about 60\pct! of \TeX's running time,
- // exclusive of input and output.
|