Parser-5556.pm 323 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079
  1. # Parser.pm: parse texinfo code into a tree.
  2. #
  3. # Copyright 2010, 2011, 2012 Free Software Foundation, Inc.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 3 of the License,
  8. # or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. #
  18. # Original author: Patrice Dumas <pertusus@free.fr>
  19. # Parts (also from Patrice Dumas) come from texi2html.pl or texi2html.init.
  20. # The organization of the file is the following:
  21. # module definitions.
  22. # default parser state. With explanation of the internal structures.
  23. # initializations, determination of command types.
  24. # user visible subroutines.
  25. # internal subroutines, doing the parsing.
  26. package Texinfo::Parser;
  27. # We need the unicode stuff.
  28. use 5.006;
  29. use strict;
  30. # debug
  31. use Carp qw(cluck);
  32. use Data::Dumper;
  33. # to detect if an encoding may be used to open the files
  34. use Encode;
  35. # for fileparse
  36. use File::Basename;
  37. #use POSIX qw(setlocale LC_ALL LC_CTYPE LC_MESSAGES);
  38. # commands definitions
  39. use Texinfo::Common;
  40. # Error reporting and counting, translation of strings.
  41. use Texinfo::Report;
  42. # encoding_alias
  43. use Texinfo::Encoding;
  44. # to expand file names in @include and similar @-commands
  45. use Texinfo::Convert::Text;
  46. # to normalize node name, anchor, float arg, listoffloats and first *ref argument.
  47. use Texinfo::Convert::NodeNameNormalization;
  48. # in error messages, and for macro body expansion
  49. use Texinfo::Convert::Texinfo;
  50. require Exporter;
  51. use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  52. @ISA = qw(Exporter Texinfo::Report);
  53. # Items to export into callers namespace by default. Note: do not export
  54. # names by default without a very good reason. Use EXPORT_OK instead.
  55. # Do not simply export all your public functions/methods/constants.
  56. # This allows declaration use Texinfo::Parser ':all';
  57. # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
  58. # will save memory.
  59. %EXPORT_TAGS = ( 'all' => [ qw(
  60. parser
  61. parse_texi_text
  62. parse_texi_line
  63. parse_texi_file
  64. indices_information
  65. floats_information
  66. internal_references_information
  67. labels_information
  68. global_commands_information
  69. global_informations
  70. ) ] );
  71. @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
  72. @EXPORT = qw(
  73. );
  74. $VERSION = '5.1.90';
  75. sub N__($)
  76. {
  77. return $_[0];
  78. }
  79. #sub __($$)
  80. #{
  81. # my $self = shift;
  82. # return &{$self->{'gettext'}}(@_);
  83. #}
  84. # Customization variables obeyed by the Parser, and the default values.
  85. our %default_customization_values = (
  86. 'TEST' => 0,
  87. 'DEBUG' => 0, # if >= 10, tree is printed in texi2any.pl after parsing.
  88. # If >= 100 tree is printed every line.
  89. 'SHOW_MENU' => 1, # if false no menu error related.
  90. 'INLINE_INSERTCOPYING' => 0,
  91. 'IGNORE_BEFORE_SETFILENAME' => 1,
  92. 'MACRO_BODY_IGNORES_LEADING_SPACE' => 0,
  93. 'IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME' => 1,
  94. 'INPUT_PERL_ENCODING' => undef, # input perl encoding name, set from
  95. # @documentencoding in the default case
  96. 'INPUT_ENCODING_NAME' => undef, # encoding name normalized as preferred
  97. # IANA, set from @documentencoding in the default
  98. # case
  99. 'CPP_LINE_DIRECTIVES' => 1, # handle cpp like synchronization lines
  100. 'MAX_MACRO_CALL_NESTING' => 100000, # max number of nested macro calls
  101. 'GLOBAL_COMMANDS' => [], # list of commands registered
  102. # This is not used directly, but passed to Convert::Text through
  103. # Texinfo::Common::_convert_text_options
  104. 'ENABLE_ENCODING' => 1, # output accented and special characters
  105. # based on @documentencoding
  106. # following are used in Texinfo::Structuring
  107. 'TOP_NODE_UP' => '(dir)', # up node of Top node
  108. 'SIMPLE_MENU' => 0, # not used in the parser but in structuring
  109. 'USE_UP_NODE_FOR_ELEMENT_UP' => 0, # Use node up for Up if there is no
  110. # section up.
  111. );
  112. my %parser_default_configuration = (%Texinfo::Common::default_parser_state_configuration,
  113. %default_customization_values);
  114. # the other possible keys for the parser state are:
  115. #
  116. # expanded_formats_hash each key comes from expanded_formats value is 1
  117. # index_names a structure holding the link between index
  118. # names, prefixes, merged indices,
  119. # initial value is %index_names in Texinfo::Common.
  120. # context_stack stack of the contexts, more recent on top.
  121. # 'line' is added when on a line or
  122. # block @-command line,
  123. # 'def' is added instead if on a definition line.
  124. # 'preformatted' is added in block commands
  125. # where there is no paragraphs and spaces are kept
  126. # (format, example, display...)
  127. # 'rawpreformatted' is added in raw block commands
  128. # (html, xml, docbook...)
  129. # 'menu' is added in menu commands
  130. # 'math', 'footnote', 'caption', 'shortcaption',
  131. # 'inlineraw' are also added when in those commands
  132. # conditionals_stack a stack of conditional commands that are expanded.
  133. # raw_formats_stack a stack of 1 or 0 for raw formats (@html... or
  134. # @inlineraw), is 0 if within a raw format that is
  135. # not expanded.
  136. # macro_stack stack of macros being expanded (more recent first)
  137. # definfoenclose an hash, key is the command name, value is an array
  138. # reference with 2 values, beginning and ending.
  139. # input a stack, with last at bottom. Holds the opened files
  140. # or text. Pending macro expansion or text expansion
  141. # is also in that structure.
  142. # misc_commands the same than %misc_commands in Texinfo::Common,
  143. # but with index entry commands dynamically added
  144. # close_paragraph_commands same than %close_paragraph_commands, but with
  145. # insertcopying removed if INLINE_INSERTCOPYING
  146. # close_preformatted_commands same than %close_preformatted_commands, but with
  147. # insertcopying removed if INLINE_INSERTCOPYING
  148. # no_paragraph_commands the same than %default_no_paragraph_commands
  149. # below, with index
  150. # entry commands dynamically added
  151. # simple_text_commands the same than %simple_text_commands below, but
  152. # with index entry commands dynamically added
  153. # current_node last seen node.
  154. # current_section last seen section.
  155. # nodes list of nodes.
  156. # command_index_prefix associate a command name to an index prefix.
  157. # prefix_to_index_name associate an index prefix to the index name.
  158. # floats key is the normalized float type, value is an array
  159. # reference holding all the floats.
  160. # internal_references an array holding all the internal references.
  161. # set points to the value set when initializing, for
  162. # configuration items that are not to be overriden
  163. # by @-commands. For example documentlanguage.
  164. # A line information is an hash reference with the keys:
  165. # line_nr the line number
  166. # file_name the file name
  167. # macro if in a macro expansion, the name of the macro
  168. #
  169. # A text fragment information is a 2 element array reference, the first is the
  170. # text fragment, the second is the line information.
  171. # The input structure is an array, the first is the most recently included
  172. # file. The last element may be a file if the parsing is done on a file,
  173. # with parse_texi_file, or simply pending text, if called as parse_texi_text.
  174. # each element of the array is a hash reference. The key are:
  175. # pending an array reference containing pending text fragments, either the
  176. # text given as parse_texi_text or macro expansion text.
  177. # name file name
  178. # line_nr current line number in the file
  179. # fh filehandle for the file
  180. # content is not copied but reference is copied when duplicating a parser.
  181. my %tree_informations;
  182. foreach my $tree_information ('values', 'macros', 'explained_commands', 'labels') {
  183. $tree_informations{$tree_information} = 1;
  184. }
  185. # The commands in initialization_overrides are not set in the document if
  186. # set at the parser initialization.
  187. my %initialization_overrides = (
  188. 'INPUT_ENCODING_NAME' => 1,
  189. 'documentlanguage' => 1,
  190. );
  191. my %no_brace_commands = %Texinfo::Common::no_brace_commands;
  192. my %misc_commands = %Texinfo::Common::misc_commands;
  193. my %brace_commands = %Texinfo::Common::brace_commands;
  194. my %accent_commands = %Texinfo::Common::accent_commands;
  195. my %context_brace_commands = %Texinfo::Common::context_brace_commands;
  196. my %block_commands = %Texinfo::Common::block_commands;
  197. my %block_item_commands = %Texinfo::Common::block_item_commands;
  198. my %close_paragraph_commands = %Texinfo::Common::close_paragraph_commands;
  199. my %def_map = %Texinfo::Common::def_map;
  200. my %def_commands = %Texinfo::Common::def_commands;
  201. my %def_aliases = %Texinfo::Common::def_aliases;
  202. my %menu_commands = %Texinfo::Common::menu_commands;
  203. my %preformatted_commands = %Texinfo::Common::preformatted_commands;
  204. my %format_raw_commands = %Texinfo::Common::format_raw_commands;
  205. my %item_container_commands = %Texinfo::Common::item_container_commands;
  206. my %item_line_commands = %Texinfo::Common::item_line_commands;
  207. my %deprecated_commands = %Texinfo::Common::deprecated_commands;
  208. my %root_commands = %Texinfo::Common::root_commands;
  209. my %sectioning_commands = %Texinfo::Common::sectioning_commands;
  210. my %command_index_prefix = %Texinfo::Common::command_index_prefix;
  211. my %command_structuring_level = %Texinfo::Common::command_structuring_level;
  212. my %ref_commands = %Texinfo::Common::ref_commands;
  213. my %region_commands = %Texinfo::Common::region_commands;
  214. my %code_style_commands = %Texinfo::Common::code_style_commands;
  215. my %in_heading_commands = %Texinfo::Common::in_heading_commands;
  216. my %explained_commands = %Texinfo::Common::explained_commands;
  217. my %inline_format_commands = %Texinfo::Common::inline_format_commands;
  218. my %inline_commands = %Texinfo::Common::inline_commands;
  219. my %inline_conditional_commands = %Texinfo::Common::inline_conditional_commands;
  220. my %all_commands = %Texinfo::Common::all_commands;
  221. # equivalence between a @set flag and an @@-command
  222. my %set_flag_command_equivalent = (
  223. 'txicodequoteundirected' => 'codequoteundirected',
  224. 'txicodequotebacktick' => 'codequotebacktick',
  225. # 'txideftypefnnl' => 'deftypefnnewline',
  226. );
  227. # keep line information for those commands.
  228. my %keep_line_nr_brace_commands = %context_brace_commands;
  229. foreach my $keep_line_nr_brace_command ('titlefont', 'anchor') {
  230. $keep_line_nr_brace_commands{$keep_line_nr_brace_command} = 1;
  231. }
  232. foreach my $brace_command (keys (%brace_commands)) {
  233. $keep_line_nr_brace_commands{$brace_command} = 1
  234. if ($brace_commands{$brace_command} > 1);
  235. }
  236. my %type_with_paragraph;
  237. foreach my $type ('before_item', 'text_root', 'document_root',
  238. 'brace_command_context') {
  239. $type_with_paragraph{$type} = 1;
  240. }
  241. my %command_ignore_space_after;
  242. foreach my $command ('anchor', 'hyphenation', 'caption', 'shortcaption') {
  243. $command_ignore_space_after{$command} = 1;
  244. }
  245. my %global_multiple_commands;
  246. foreach my $global_multiple_command (
  247. 'author', 'footnote', 'hyphenation', 'insertcopying', 'printindex',
  248. 'subtitle','titlefont', 'listoffloats', 'detailmenu', 'part',
  249. keys(%Texinfo::Common::document_settable_at_commands), ) {
  250. $global_multiple_commands{$global_multiple_command} = 1;
  251. }
  252. my %global_unique_commands;
  253. foreach my $global_unique_command (
  254. 'copying', 'settitle',
  255. 'shorttitlepage', 'title', 'titlepage', 'top',
  256. keys(%Texinfo::Common::document_settable_unique_at_commands), ) {
  257. $global_unique_commands{$global_unique_command} = 1;
  258. }
  259. my %index_names = %Texinfo::Common::index_names;
  260. # index names that cannot be set by the user.
  261. my %forbidden_index_name = ();
  262. foreach my $name(keys(%index_names)) {
  263. foreach my $prefix (@{$index_names{$name}->{'prefix'}}) {
  264. $forbidden_index_name{$prefix} = 1;
  265. }
  266. }
  267. foreach my $other_forbidden_index_name ('info','ps','pdf','htm',
  268. 'html', 'log','aux','dvi','texi','txi','texinfo','tex','bib') {
  269. $forbidden_index_name{$other_forbidden_index_name} = 1;
  270. }
  271. # @-commands that do not start a paragraph
  272. my %default_no_paragraph_commands;
  273. # @-commands that should be at a line beginning
  274. my %begin_line_commands;
  275. foreach my $command ('node', 'end') {
  276. $begin_line_commands{$command} = $command;
  277. }
  278. foreach my $no_paragraph_command ('titlefont', 'caption', 'shortcaption',
  279. 'image', '*', 'hyphenation', 'anchor', 'errormsg') {
  280. $default_no_paragraph_commands{$no_paragraph_command} = 1;
  281. }
  282. foreach my $no_paragraph_command (keys(%misc_commands)) {
  283. $default_no_paragraph_commands{$no_paragraph_command} = 1;
  284. $begin_line_commands{$no_paragraph_command} = 1;
  285. }
  286. # verbatiminclude is not said to begin at the beginning of the line
  287. # in the manual
  288. foreach my $misc_not_begin_line ('comment', 'c', 'sp', 'refill',
  289. 'noindent', 'indent', 'columnfractions',
  290. 'tab', 'item', 'headitem', 'verbatiminclude',
  291. 'set', 'clear',
  292. 'vskip', keys(%in_heading_commands)) {
  293. delete $begin_line_commands{$misc_not_begin_line};
  294. }
  295. my %block_arg_commands;
  296. foreach my $block_command (keys(%block_commands)) {
  297. $begin_line_commands{$block_command} = 1;
  298. $default_no_paragraph_commands{$block_command} = 1;
  299. $block_arg_commands{$block_command} = 1
  300. if ($block_commands{$block_command} ne 'raw');
  301. # and ! $format_raw_commands{$block_command});
  302. }
  303. my %close_preformatted_commands = %close_paragraph_commands;
  304. foreach my $no_close_preformatted('sp') {
  305. delete $close_preformatted_commands{$no_close_preformatted};
  306. }
  307. # FIXME to close preformated or not to close?
  308. #foreach my $format_raw_command(keys(%format_raw_commands)) {
  309. # $close_preformatted_commands{$format_raw_command} = 1;
  310. #}
  311. # commands that may appear in accents
  312. my %in_accent_commands = %accent_commands;
  313. foreach my $brace_command(keys(%brace_commands)) {
  314. $in_accent_commands{$brace_command} = 1 if (!$brace_commands{$brace_command});
  315. }
  316. foreach my $no_brace_command (keys(%no_brace_commands)) {
  317. $in_accent_commands{$no_brace_command} = 1;
  318. }
  319. $in_accent_commands{'c'} = 1;
  320. $in_accent_commands{'comment'} = 1;
  321. # commands that may appear in texts arguments
  322. my %in_full_text_commands;
  323. foreach my $command (keys(%brace_commands), keys(%no_brace_commands)) {
  324. $in_full_text_commands{$command} = 1;
  325. }
  326. foreach my $misc_command_in_full_text('c', 'comment', 'refill', 'noindent',
  327. 'indent', 'columnfractions', 'set', 'clear', 'end') {
  328. $in_full_text_commands{$misc_command_in_full_text} = 1;
  329. }
  330. foreach my $out_format (keys(%format_raw_commands)) {
  331. $in_full_text_commands{$out_format} = 1;
  332. }
  333. delete $in_full_text_commands{'caption'};
  334. delete $in_full_text_commands{'shortcaption'};
  335. foreach my $block_command (keys(%block_commands)) {
  336. $in_full_text_commands{$block_command} = 1
  337. if ($block_commands{$block_command} eq 'conditional');
  338. }
  339. # commands that may happen on lines where everything is
  340. # permitted
  341. my %in_full_line_commands = %in_full_text_commands;
  342. foreach my $not_in_full_line_commands('noindent', 'indent') {
  343. delete $in_full_line_commands{$not_in_full_line_commands};
  344. }
  345. # commands that may happen on sectioning commands
  346. my %in_full_line_commands_no_refs = %in_full_line_commands;
  347. foreach my $not_in_full_line_commands_no_refs ('titlefont',
  348. 'anchor', 'footnote', 'verb') {
  349. delete $in_full_line_commands_no_refs{$not_in_full_line_commands_no_refs};
  350. }
  351. # commands that may happen in simple text arguments
  352. my %in_simple_text_commands = %in_full_line_commands_no_refs;
  353. foreach my $not_in_simple_text_command('xref', 'ref', 'pxref', 'inforef') {
  354. delete $in_simple_text_commands{$not_in_simple_text_command};
  355. }
  356. # commands that only accept simple text as argument in any context.
  357. my %simple_text_commands;
  358. foreach my $misc_command(keys(%misc_commands)) {
  359. if ($misc_commands{$misc_command} =~ /^\d+$/
  360. or ($misc_commands{$misc_command} eq 'line'
  361. and !($sectioning_commands{$misc_command}
  362. or $def_commands{$misc_command}))
  363. or $misc_commands{$misc_command} eq 'text') {
  364. $simple_text_commands{$misc_command} = 1;
  365. }
  366. }
  367. my %full_line_commands_no_refs = (%sectioning_commands,
  368. %def_commands);
  369. delete $simple_text_commands{'center'};
  370. delete $simple_text_commands{'exdent'};
  371. foreach my $command ('titlefont', 'anchor', 'xref','ref','pxref',
  372. 'inforef', 'shortcaption', 'math', 'indicateurl',
  373. 'email', 'uref', 'url', 'image', 'abbr', 'acronym',
  374. 'dmn', 'ctrl', 'errormsg') {
  375. $simple_text_commands{$command} = 1;
  376. }
  377. # commands that accept full text, but no block or top-level commands
  378. my %full_text_commands;
  379. foreach my $brace_command (keys (%brace_commands)) {
  380. if ($brace_commands{$brace_command} == 1
  381. and !$simple_text_commands{$brace_command}
  382. and !$context_brace_commands{$brace_command}
  383. and !$accent_commands{$brace_command}) {
  384. $full_text_commands{$brace_command} = 1;
  385. }
  386. }
  387. # commands that accept almost the same than in full text, except
  388. # what do not make sense on a line.
  389. my %full_line_commands;
  390. $full_line_commands{'center'} = 1;
  391. $full_line_commands{'exdent'} = 1;
  392. $full_line_commands{'item'} = 1;
  393. $full_line_commands{'itemx'} = 1;
  394. # Fill the valid nestings hash. All commands not in that hash
  395. # are considered to accept anything within. There are additional
  396. # context tests, to make sure, for instance that we are testing
  397. # @-commands on the block, misc or node @-command line and not
  398. # in the content.
  399. # index entry commands are dynamically set as in_simple_text_commands
  400. my %default_valid_nestings;
  401. foreach my $command (keys(%accent_commands)) {
  402. $default_valid_nestings{$command} = \%in_accent_commands;
  403. }
  404. foreach my $command (keys(%full_text_commands)) {
  405. $default_valid_nestings{$command} = \%in_full_text_commands;
  406. }
  407. foreach my $command (keys(%simple_text_commands)) {
  408. $default_valid_nestings{$command} = \%in_simple_text_commands;
  409. }
  410. foreach my $command (keys(%full_line_commands)) {
  411. $default_valid_nestings{$command} = \%in_full_line_commands;
  412. }
  413. foreach my $command (keys(%full_line_commands_no_refs)) {
  414. $default_valid_nestings{$command} = \%in_full_line_commands_no_refs;
  415. }
  416. # Only for block commands with line arguments
  417. foreach my $command (keys(%block_commands)) {
  418. if ($block_commands{$command} and $block_commands{$command} ne 'raw'
  419. and $block_commands{$command} ne 'conditional'
  420. and !$def_commands{$command}) {
  421. $default_valid_nestings{$command} = \%in_simple_text_commands;
  422. }
  423. }
  424. my @preformatted_contexts = ('preformatted', 'rawpreformatted');
  425. my %preformatted_contexts;
  426. foreach my $preformatted_context (@preformatted_contexts) {
  427. $preformatted_contexts{$preformatted_context} = 1;
  428. }
  429. # contexts on the context_stack stack where empty line don't trigger
  430. # paragraph
  431. my %no_paragraph_contexts;
  432. foreach my $no_paragraph_context ('math', 'menu', @preformatted_contexts,
  433. 'def', 'inlineraw') {
  434. $no_paragraph_contexts{$no_paragraph_context} = 1;
  435. };
  436. # Format a bug message
  437. sub _bug_message($$;$$)
  438. {
  439. my $self = shift;
  440. my $message = shift;
  441. my $line_number = shift;
  442. my $current = shift;
  443. my $line_message = '';
  444. if ($line_number) {
  445. my $file = $line_number->{'file_name'};
  446. $line_message
  447. = "last location: $line_number->{'file_name'}:$line_number->{'line_nr'}";
  448. if ($line_number->{'macro'} ne '') {
  449. $line_message .= " (possibly involving $line_number->{'macro'})";
  450. }
  451. $line_message .= "\n";
  452. }
  453. my $message_context_stack = "context_stack: (@{$self->{'context_stack'}})\n";
  454. my $current_element_message = '';
  455. if ($current) {
  456. $current_element_message = "current: ". _print_current($current);
  457. }
  458. warn "You found a bug: $message\n\n".
  459. "Additional informations:\n".
  460. $line_message.$message_context_stack.$current_element_message;
  461. }
  462. # simple deep copy of a structure
  463. sub _deep_copy($)
  464. {
  465. my $struct = shift;
  466. my $string = Data::Dumper->Dump([$struct], ['struct']);
  467. eval $string;
  468. return $struct;
  469. }
  470. # return true if effect of global commands should be ignored.
  471. sub _ignore_global_commands($)
  472. {
  473. my $self = shift;
  474. return !$self->{'expanded_formats_stack'}->[-1];
  475. }
  476. # enter all the commands associated with an index name using the prefix
  477. # list
  478. sub _register_index_commands($$)
  479. {
  480. my $self = shift;
  481. my $index_name = shift;
  482. if (!$self->{'index_names'}->{$index_name}->{'prefix'}) {
  483. $self->{'index_names'}->{$index_name}->{'prefix'} = [$index_name];
  484. }
  485. if (!exists($self->{'index_names'}->{$index_name}->{'name'})) {
  486. $self->{'index_names'}->{$index_name}->{'name'} = $index_name;
  487. }
  488. if (!exists($self->{'index_names'}->{$index_name}->{'contained_indices'})) {
  489. $self->{'index_names'}->{$index_name}->{'contained_indices'}->{$index_name} = 1;
  490. }
  491. foreach my $prefix (@{$self->{'index_names'}->{$index_name}->{'prefix'}}) {
  492. $self->{'misc_commands'}->{$prefix.'index'} = 'line';
  493. $self->{'no_paragraph_commands'}->{$prefix.'index'} = 1;
  494. $self->{'valid_nestings'}->{$prefix.'index'} = \%in_simple_text_commands;
  495. $self->{'command_index_prefix'}->{$prefix.'index'} = $prefix;
  496. $self->{'prefix_to_index_name'}->{$prefix} = $index_name;
  497. }
  498. }
  499. # initialization entry point. Set up a parser.
  500. # The last argument, optional, is a hash provided by the user to change
  501. # the default values for what is present in %parser_default_configuration.
  502. # The exact arguments of the function depend on how it was called,
  503. # in a object oriented way or not.
  504. sub parser(;$$)
  505. {
  506. my $class = shift;
  507. my $conf;
  508. my $parser = _deep_copy(\%parser_default_configuration);
  509. # _deep_copy doesn't handle subs
  510. $parser->{'gettext'} = $parser_default_configuration{'gettext'};
  511. $parser->{'pgettext'} = $parser_default_configuration{'pgettext'};
  512. # called not object-oriented
  513. if (ref($class) eq 'HASH') {
  514. #print STDERR "Not oo\n"
  515. $conf = $class;
  516. bless $parser;
  517. } elsif (ref($class)) {
  518. # called on an existing parser, interpreted as a duplication
  519. my $old_parser = $class;
  520. $class = ref($class);
  521. foreach my $key (keys(%parser_default_configuration)) {
  522. if ($tree_informations{$key}) {
  523. if (defined($old_parser->{$key})) {
  524. foreach my $info_key (keys(%{$old_parser->{$key}})) {
  525. $parser->{$key}->{$info_key}
  526. = $old_parser->{$key}->{$info_key};
  527. }
  528. }
  529. } else {
  530. $parser->{$key} = _deep_copy($old_parser->{$key});
  531. }
  532. }
  533. #$parser = _deep_copy($old_parser);
  534. $parser->{'gettext'} = $old_parser->{'gettext'};
  535. $parser->{'pgettext'} = $old_parser->{'pgettext'};
  536. bless $parser, $class;
  537. $conf = shift;
  538. } elsif (defined($class)) {
  539. bless $parser, $class;
  540. $conf = shift;
  541. } else {
  542. bless $parser;
  543. $conf = shift;
  544. }
  545. if (defined($conf)) {
  546. foreach my $key (keys(%$conf)) {
  547. if (exists($parser_default_configuration{$key})) {
  548. if (ref($conf->{$key}) ne 'CODE' and $key ne 'values') {
  549. $parser->{$key} = _deep_copy($conf->{$key});
  550. } else {
  551. $parser->{$key} = $conf->{$key};
  552. }
  553. if ($initialization_overrides{$key}) {
  554. $parser->{'set'}->{$key} = $parser->{$key};
  555. }
  556. } else {
  557. warn "$key not a possible customization in Texinfo::Parser::parser\n";
  558. }
  559. }
  560. }
  561. #foreach my $value (keys %{$parser->{'values'}}) {
  562. # print STDERR " -> $value $parser->{'values'}->{$value}\n";
  563. #}
  564. # Now initialize command hash that are dynamically modified, notably
  565. # those for index commands, and lists, based on defaults and user provided.
  566. $parser->{'misc_commands'} = _deep_copy (\%misc_commands);
  567. $parser->{'valid_nestings'} = _deep_copy (\%default_valid_nestings);
  568. $parser->{'no_paragraph_commands'} = { %default_no_paragraph_commands };
  569. $parser->{'index_names'} = _deep_copy (\%index_names);
  570. $parser->{'command_index_prefix'} = {%command_index_prefix};
  571. $parser->{'close_paragraph_commands'} = {%close_paragraph_commands};
  572. $parser->{'close_preformatted_commands'} = {%close_preformatted_commands};
  573. if ($parser->{'INLINE_INSERTCOPYING'}) {
  574. delete $parser->{'close_paragraph_commands'}->{'insercopying'};
  575. delete $parser->{'close_preformatted_commands'}->{'insercopying'};
  576. }
  577. # a hash is simply concatenated. It should be like %index_names.
  578. if (ref($parser->{'indices'}) eq 'HASH') {
  579. %{$parser->{'index_names'}} = (%{$parser->{'index_names'}},
  580. %{$parser->{'indices'}});
  581. } else { # an array holds index names defined with @defindex
  582. foreach my $name (@{$parser->{'indices'}}) {
  583. $parser->{'index_names'}->{$name} = {'in_code' => 0};
  584. }
  585. }
  586. foreach my $index (keys (%{$parser->{'index_names'}})) {
  587. $parser->_register_index_commands($index);
  588. }
  589. if ($parser->{'merged_indices'}) {
  590. foreach my $index_from (keys (%{$parser->{'merged_indices'}})) {
  591. my $index_to = $parser->{'merged_indices'}->{$index_from};
  592. if (defined($parser->{'index_names'}->{$index_from})
  593. and defined($parser->{'index_names'}->{$index_to})) {
  594. $parser->{'index_names'}->{$index_from}->{'merged_in'} = $index_to;
  595. $parser->{'index_names'}->{$index_to}->{'contained_indices'}->{$index_from} = 1;
  596. }
  597. }
  598. }
  599. foreach my $explained_command(keys(%explained_commands)) {
  600. if (!defined($parser->{'explained_commands'}->{$explained_command})) {
  601. $parser->{'explained_commands'}->{$explained_command} = {};
  602. }
  603. }
  604. $parser->{'context_stack'} = [ $parser->{'context'} ];
  605. $parser->{'regions_stack'} = [];
  606. $parser->{'macro_stack'} = [];
  607. $parser->{'conditionals_stack'} = [];
  608. $parser->{'expanded_formats_stack'} = [1];
  609. # turn the array to a hash for speed. Not sure it really matters for such
  610. # a small array.
  611. foreach my $expanded_format(@{$parser->{'expanded_formats'}}) {
  612. $parser->{'expanded_formats_hash'}->{$expanded_format} = 1;
  613. }
  614. %{$parser->{'global_commands'}} = %global_multiple_commands;
  615. foreach my $global_command (@{$parser->{'GLOBAL_COMMANDS'}}) {
  616. $parser->{'global_commands'}->{$global_command} = 1;
  617. }
  618. $parser->Texinfo::Report::new;
  619. return $parser;
  620. }
  621. sub get_conf($$)
  622. {
  623. my $self = shift;
  624. my $var = shift;
  625. return $self->{$var};
  626. }
  627. # split a scalar text in an array lines.
  628. sub _text_to_lines($)
  629. {
  630. my $text = shift;
  631. die if (!defined($text));
  632. my $had_final_end_line = chomp($text);
  633. my $lines = [ map {$_."\n"} split (/\n/, $text, -1) ];
  634. $lines = [''] if (!@$lines);
  635. chomp($lines->[-1]) unless ($had_final_end_line);
  636. return $lines;
  637. }
  638. # construct a text fragments array matching a lines array, based on information
  639. # supplied.
  640. # If $fixed_line_number is set the line number is not increased, otherwise
  641. # it is increased, beginning at $first_line.
  642. sub _complete_line_nr($$;$$$)
  643. {
  644. my $lines = shift;
  645. my $first_line = shift;
  646. my $file = shift;
  647. my $macro = shift;
  648. my $fixed_line_number = shift;
  649. $macro = '' if (!defined($macro));
  650. $file = '' if (!defined($file));
  651. my $new_lines = [];
  652. if (defined($first_line)) {
  653. my $line_index = $first_line;
  654. foreach my $index(0..scalar(@$lines)-1) {
  655. $line_index = $index+$first_line if (!$fixed_line_number);
  656. $new_lines->[$index] = [ $lines->[$index],
  657. { 'line_nr' => $line_index,
  658. 'file_name' => $file, 'macro' => $macro } ];
  659. }
  660. } else {
  661. foreach my $line (@$lines) {
  662. push @$new_lines, [ $line ];
  663. }
  664. }
  665. return $new_lines;
  666. }
  667. # entry point for text fragments.
  668. # Used in tests.
  669. # Note that it has no associated root type a opposed to parse_texi_line
  670. # and parse_texi_file.
  671. sub parse_texi_text($$;$$$$)
  672. {
  673. my $self = shift;
  674. my $text = shift;
  675. my $lines_nr = shift;
  676. my $file = shift;
  677. my $macro = shift;
  678. my $fixed_line_number = shift;
  679. return undef if (!defined($text));
  680. my $lines_array = [];
  681. if (!ref($text)) {
  682. $text = _text_to_lines($text);
  683. }
  684. $lines_nr = [] if (!defined($lines_nr));
  685. if (!ref($lines_nr)) {
  686. #$file =~ s/^.*\/// if (defined($file) and $self->{'TEST'});
  687. $lines_array = _complete_line_nr($text, $lines_nr, $file,
  688. $macro, $fixed_line_number);
  689. } else {
  690. while (@$text) {
  691. my $line_nr = shift @$lines_nr;
  692. my $line = shift @$text;
  693. push @$lines_array, [$line, $line_nr];
  694. }
  695. }
  696. $self = parser() if (!defined($self));
  697. $self->{'input'} = [{'pending' => $lines_array}];
  698. my $tree = $self->_parse_texi();
  699. return $tree;
  700. }
  701. # Not used for now, as a @contents after the first sectioning command
  702. # is correct if not using TeX.
  703. sub _check_contents_location($$)
  704. {
  705. my $self = shift;
  706. my $tree = shift;
  707. my $commands = $self->global_commands_information();
  708. return unless ($commands);
  709. # Find the last sectioning command
  710. my $index = -1;
  711. my %ending_root_commands;
  712. my $found = 0;
  713. while ($tree->{'contents'}->[$index]) {
  714. if (defined($tree->{'contents'}->[$index]->{'cmdname'})) {
  715. $ending_root_commands{$tree->{'contents'}->[$index]} = 1;
  716. if ($sectioning_commands{$tree->{'contents'}->[$index]->{'cmdname'}}) {
  717. $found = 1;
  718. last;
  719. }
  720. }
  721. $index--;
  722. }
  723. return if (!$found);
  724. #print STDERR "ending_root_commands ".join('|',keys(%ending_root_commands))."\n";
  725. #print STDERR "tree contents: ".join('|', @{$tree->{'contents'}})."\n";
  726. foreach my $command ('contents', 'shortcontents', 'summarycontents') {
  727. if ($commands->{$command}) {
  728. foreach my $current (@{$commands->{$command}}) {
  729. my $root_command = $self->Texinfo::Common::find_parent_root_command($current);
  730. #print STDERR "root_command for $current->{'cmdname'}: $root_command\n";
  731. if (defined($root_command)
  732. and !$ending_root_commands{$root_command}) {
  733. $self->line_warn(sprintf($self->__(
  734. "\@%s should only appear at beginning or end of document"),
  735. $current->{'cmdname'}), $current->{'line_nr'});
  736. }
  737. }
  738. }
  739. }
  740. }
  741. # parse a texi file
  742. sub parse_texi_file($$)
  743. {
  744. my $self = shift;
  745. my $file_name = shift;
  746. my $filehandle = do { local *FH };
  747. if (! open($filehandle, $file_name)) {
  748. $self->document_error(sprintf($self->__("could not open %s: %s"),
  749. $file_name, $!));
  750. return undef;
  751. }
  752. my $line_nr = 0;
  753. my $line;
  754. my @first_lines;
  755. my $pending_first_texi_line;
  756. # the first line not empty and not with \input is kept in
  757. # $pending_first_texi_line and put in the pending lines just below
  758. while ($line = <$filehandle>) {
  759. $line_nr++;
  760. if ($line =~ /^ *\\input/ or $line =~ /^\s*$/) {
  761. $line =~ s/\x{7F}.*\s*//;
  762. push @first_lines, $line;
  763. } else {
  764. $pending_first_texi_line = $line;
  765. last;
  766. }
  767. }
  768. my $root = { 'contents' => [], 'type' => 'text_root' };
  769. if (@first_lines) {
  770. push @{$root->{'contents'}}, { 'type' => 'preamble', 'contents' => [] };
  771. foreach my $line (@first_lines) {
  772. push @{$root->{'contents'}->[-1]->{'contents'}},
  773. { 'text' => $line,
  774. 'type' => 'preamble_text' };
  775. }
  776. }
  777. my ($directories, $suffix);
  778. ($file_name, $directories, $suffix) = fileparse($file_name)
  779. if ($self->{'TEST'});
  780. $self = parser() if (!defined($self));
  781. $self->{'input'} = [{
  782. 'pending' => [[$pending_first_texi_line, {'line_nr' => $line_nr,
  783. 'macro' => '', 'file_name' => $file_name}]],
  784. 'name' => $file_name,
  785. 'line_nr' => $line_nr,
  786. 'fh' => $filehandle
  787. }];
  788. $self->{'info'}->{'input_file_name'} = $file_name;
  789. my $tree = $self->_parse_texi($root);
  790. # Find 'text_root', which contains everything before first node/section.
  791. # if there are elements, 'text_root' is the first content, otherwise it
  792. # is the root.
  793. my $text_root;
  794. if ($tree->{'type'} eq 'text_root') {
  795. $text_root = $tree;
  796. } elsif ($tree->{'contents'} and $tree->{'contents'}->[0]
  797. and $tree->{'contents'}->[0]->{'type'} eq 'text_root') {
  798. $text_root = $tree->{'contents'}->[0];
  799. }
  800. # Put everything before @setfilename in a special type. This allows to
  801. # ignore everything before @setfilename.
  802. if ($self->{'IGNORE_BEFORE_SETFILENAME'} and $text_root and
  803. $self->{'extra'} and $self->{'extra'}->{'setfilename'}
  804. and $self->{'extra'}->{'setfilename'}->{'parent'} eq $text_root) {
  805. my $before_setfilename = {'type' => 'preamble_before_setfilename',
  806. 'parent' => $text_root,
  807. 'contents' => []};
  808. while ($text_root->{'contents'}->[0] ne $self->{'extra'}->{'setfilename'}) {
  809. my $content = shift @{$text_root->{'contents'}};
  810. $content->{'parent'} = $before_setfilename;
  811. push @{$before_setfilename->{'contents'}}, $content;
  812. }
  813. unshift (@{$text_root->{'contents'}}, $before_setfilename)
  814. if (@{$before_setfilename->{'contents'}});
  815. }
  816. #$self->_check_contents_location($tree);
  817. return $tree;
  818. }
  819. sub parse_texi_line($$;$$$$)
  820. {
  821. my $self = shift;
  822. my $text = shift;
  823. my $lines_nr = shift;
  824. my $file = shift;
  825. my $macro = shift;
  826. my $fixed_line_number = shift;
  827. return undef if (!defined($text));
  828. if (!ref($text)) {
  829. $text = _text_to_lines($text);
  830. }
  831. #$file =~ s/^.*\/// if (defined($file) and $self->{'TEST'});
  832. my $lines_array = _complete_line_nr($text, $lines_nr, $file,
  833. $macro, $fixed_line_number);
  834. $self = parser() if (!defined($self));
  835. $self->{'input'} = [{'pending' => $lines_array}];
  836. my $tree = $self->_parse_texi({'contents' => [], 'type' => 'root_line'});
  837. return $tree;
  838. }
  839. # return indices informations
  840. sub indices_information($)
  841. {
  842. my $self = shift;
  843. return ($self->{'index_names'}, $self->{'merged_indices'});
  844. #return ($self->{'index_names'}, $self->{'merged_indices'}, $self->{'index_entries'});
  845. }
  846. sub floats_information($)
  847. {
  848. my $self = shift;
  849. return $self->{'floats'};
  850. }
  851. sub internal_references_information($)
  852. {
  853. my $self = shift;
  854. return $self->{'internal_references'};
  855. }
  856. sub global_commands_information($)
  857. {
  858. my $self = shift;
  859. return $self->{'extra'};
  860. }
  861. # @ dircategory_direntry
  862. # @ unassociated_menus
  863. # perl_encoding
  864. # input_encoding_name
  865. # input_file_name
  866. sub global_informations($)
  867. {
  868. my $self = shift;
  869. return $self->{'info'};
  870. }
  871. sub labels_information($)
  872. {
  873. my $self = shift;
  874. return $self->{'labels'};
  875. }
  876. # Following are the internal subroutines. The most important are
  877. # _parse_texi: the main parser loop.
  878. # _end_line: called at an end of line. Handling of @include lines is
  879. # done here.
  880. # _next_text: present the next text fragment, from pending text or line,
  881. # as described above.
  882. # for debugging
  883. sub _print_current($)
  884. {
  885. my $current = shift;
  886. return Texinfo::Common::_print_current($current);
  887. }
  888. # for debugging
  889. sub _print_command_args_texi($)
  890. {
  891. my $current = shift;
  892. return '' if (!$current->{'cmdname'});
  893. my $args = '';
  894. my $with_brace;
  895. if ($current->{'args'} and @{$current->{'args'}}) {
  896. $with_brace
  897. = ($current->{'args'}->[0]->{'type'} eq 'brace_command_arg'
  898. or $current->{'args'}->[0]->{'type'} eq 'brace_command_context');
  899. $args .= '{' if ($with_brace);
  900. foreach my $arg (@{$current->{'args'}}) {
  901. $args .= Texinfo::Convert::Texinfo::convert($arg).', ';
  902. }
  903. $args =~ s/, $//;
  904. }
  905. chomp($args);
  906. if ($with_brace) {
  907. $args .= '}';
  908. }
  909. return '@'.$current->{'cmdname'} .$args."\n";
  910. }
  911. sub _print_current_keys($)
  912. {
  913. my $current = shift;
  914. my $string = _print_current($current);
  915. foreach my $key (keys (%$current)) {
  916. $string .= " $key: $current->{$key}\n";
  917. }
  918. if ($current->{'extra'}) {
  919. $string .= " EXTRA\n";
  920. foreach my $key (keys (%{$current->{'extra'}})) {
  921. $string .= " $key: $current->{'extra'}->{$key}\n";
  922. }
  923. }
  924. return $string;
  925. }
  926. # For debugging
  927. my @kept_keys = ('contents', 'cmdname', 'type', 'text', 'args');
  928. my %kept_keys;
  929. foreach my $key (@kept_keys) {
  930. $kept_keys{$key} = 1;
  931. }
  932. sub _filter_print_keys { [grep {$kept_keys{$_}} ( sort keys %{$_[0]} )] };
  933. sub _print_tree($)
  934. {
  935. my $tree = shift;
  936. local $Data::Dumper::Sortkeys = \&_filter_print_keys;
  937. local $Data::Dumper::Purity = 1;
  938. local $Data::Dumper::Indent = 1;
  939. return Data::Dumper->Dump([$tree]);
  940. }
  941. sub _register_global_command($$$$)
  942. {
  943. my $self = shift;
  944. my $command = shift;
  945. my $current = shift;
  946. my $line_nr = shift;
  947. if ($command eq 'summarycontents' and !$self->{'global_commands'}->{$command}) {
  948. $command = 'shortcontents';
  949. }
  950. if ($self->{'global_commands'}->{$command} and $command ne 'author') {
  951. push @{$self->{'extra'}->{$command}}, $current
  952. unless (_ignore_global_commands($self));
  953. $current->{'line_nr'} = $line_nr if (!$current->{'line_nr'});
  954. return 1;
  955. } elsif ($global_unique_commands{$command}) {
  956. # setfilename ignored in an included file
  957. $current->{'line_nr'} = $line_nr if (!$current->{'line_nr'});
  958. if ($command eq 'setfilename'
  959. and scalar(@{$self->{'input'}}) > 1) {
  960. } elsif (exists ($self->{'extra'}->{$current->{'cmdname'}})) {
  961. $self->line_warn(sprintf($self->__('multiple @%s'),
  962. $current->{'cmdname'}), $line_nr);
  963. } else {
  964. $self->{'extra'}->{$current->{'cmdname'}} = $current
  965. unless (_ignore_global_commands($self));
  966. }
  967. return 1;
  968. }
  969. return 0;
  970. }
  971. # parse a @macro line
  972. sub _parse_macro_command_line($$$$$;$)
  973. {
  974. my $self = shift;
  975. my $command = shift;
  976. my $line = shift;
  977. my $parent = shift;
  978. my $line_nr = shift;
  979. my $macro = { 'cmdname' => $command, 'parent' => $parent, 'contents' => [],
  980. 'extra' => {'arg_line' => $line}, 'line_nr' => $line_nr };
  981. # REMACRO
  982. if ($line =~ /^\s+([[:alnum:]][[:alnum:]-]*)\s*(.*)/) {
  983. my $macro_name = $1;
  984. my $args_def = $2;
  985. my @args;
  986. if ($args_def =~ s/^\s*{\s*(.*?)\s*}\s*//) {
  987. @args = split(/\s*,\s*/, $1);
  988. }
  989. # accept an @-command after the arguments in case there is a @c or
  990. # @comment
  991. if ($args_def =~ /^\s*[^\@]/) {
  992. $self->line_error(sprintf($self->__("bad syntax for \@%s argument: %s"),
  993. $command, $args_def),
  994. $line_nr);
  995. $macro->{'extra'}->{'invalid_syntax'} = 1;
  996. }
  997. print STDERR "MACRO \@$command $macro_name\n" if ($self->{'DEBUG'});
  998. $macro->{'args'} = [
  999. { 'type' => 'macro_name', 'text' => $macro_name,
  1000. 'parent' => $macro } ];
  1001. my $index = 0;
  1002. foreach my $formal_arg (@args) {
  1003. push @{$macro->{'args'}},
  1004. { 'type' => 'macro_arg', 'text' => $formal_arg,
  1005. 'parent' => $macro};
  1006. if ($formal_arg !~ /^[\w\-]+$/) {
  1007. $self->line_error(sprintf($self->__("bad or empty \@%s formal argument: %s"),
  1008. $command, $formal_arg), $line_nr);
  1009. $macro->{'extra'}->{'invalid_syntax'} = 1;
  1010. }
  1011. $macro->{'extra'}->{'args_index'}->{$formal_arg} = $index;
  1012. $index++;
  1013. }
  1014. } elsif ($line !~ /\S/) {
  1015. $self->line_error(sprintf($self->
  1016. __("%c%s requires a name"), ord('@'), $command), $line_nr);
  1017. $macro->{'extra'}->{'invalid_syntax'} = 1;
  1018. } else {
  1019. $self->line_error(sprintf($self->
  1020. __("bad name for \@%s"), $command), $line_nr);
  1021. $macro->{'extra'}->{'invalid_syntax'} = 1;
  1022. }
  1023. return $macro;
  1024. }
  1025. # start a paragraph if in a context where paragraphs are to be started.
  1026. sub _begin_paragraph($$;$)
  1027. {
  1028. my $self = shift;
  1029. my $current = shift;
  1030. my $line_nr = shift;
  1031. # !$current->{'type'} is true for @-commands. In fact it is unclear
  1032. # that there may be cases of !$current->{'type'} and !$current->{'cmdname'}
  1033. if ((!$current->{'type'} or $type_with_paragraph{$current->{'type'}})
  1034. and !$no_paragraph_contexts{$self->{'context_stack'}->[-1]}) {
  1035. if (!defined($current->{'contents'})) {
  1036. $self->_bug_message("contents undef", $line_nr, $current);
  1037. die;
  1038. }
  1039. # find whether an @indent precedes the paragraph
  1040. my $indent;
  1041. if (scalar(@{$current->{'contents'}})) {
  1042. my $index = scalar(@{$current->{'contents'}}) -1;
  1043. while ($index >= 0
  1044. and !($current->{'contents'}->[$index]->{'type'}
  1045. and ($current->{'contents'}->[$index]->{'type'} eq 'empty_line'
  1046. or $current->{'contents'}->[$index]->{'type'} eq 'paragraph'))
  1047. and !($current->{'contents'}->[$index]->{'cmdname'}
  1048. and $self->{'close_paragraph_commands'}->{$current->{'contents'}->[$index]->{'cmdname'}})) {
  1049. if ($current->{'contents'}->[$index]->{'cmdname'}
  1050. and ($current->{'contents'}->[$index]->{'cmdname'} eq 'indent'
  1051. or $current->{'contents'}->[$index]->{'cmdname'} eq 'noindent')) {
  1052. $indent = $current->{'contents'}->[$index]->{'cmdname'};
  1053. last;
  1054. }
  1055. $index--;
  1056. }
  1057. }
  1058. push @{$current->{'contents'}},
  1059. { 'type' => 'paragraph', 'parent' => $current, 'contents' => [] };
  1060. $current->{'contents'}->[-1]->{'extra'}->{$indent} = 1 if ($indent);
  1061. $current = $current->{'contents'}->[-1];
  1062. print STDERR "PARAGRAPH\n" if ($self->{'DEBUG'});
  1063. return $current;
  1064. }
  1065. return 0;
  1066. }
  1067. sub _begin_preformatted($)
  1068. {
  1069. my $self = shift;
  1070. my $current = shift;
  1071. if ($preformatted_contexts{$self->{'context_stack'}->[-1]}) {
  1072. push @{$current->{'contents'}},
  1073. { 'type' => $self->{'context_stack'}->[-1],
  1074. 'parent' => $current, 'contents' => [] };
  1075. $current = $current->{'contents'}->[-1];
  1076. print STDERR "PREFORMATTED $self->{'context_stack'}->[-1]\n" if ($self->{'DEBUG'});
  1077. }
  1078. return $current;
  1079. }
  1080. # wrapper around line_warn. Set line_nr to be the line_nr of the command,
  1081. # corresponding to the opening of the command. Call line_warn with
  1082. # sprintf if needed.
  1083. sub _command_warn($$$$;@)
  1084. {
  1085. my $self = shift;
  1086. my $current = shift;
  1087. my $line_nr = shift;
  1088. my $message = shift;
  1089. if ($current->{'line_nr'}) {
  1090. $line_nr = $current->{'line_nr'};
  1091. }
  1092. if (@_) {
  1093. $self->line_warn(sprintf($message, @_), $line_nr);
  1094. } else {
  1095. $self->line_warn($message, $line_nr);
  1096. }
  1097. }
  1098. sub _command_error($$$$;@)
  1099. {
  1100. my $self = shift;
  1101. my $current = shift;
  1102. my $line_nr = shift;
  1103. my $message = shift;
  1104. # use the beginning of the @-command for the error message
  1105. # line number if available.
  1106. # FIXME line_nr currently not registered for regular brace commands
  1107. if ($current->{'line_nr'}) {
  1108. $line_nr = $current->{'line_nr'};
  1109. }
  1110. if (@_) {
  1111. $self->line_error(sprintf($message, @_), $line_nr);
  1112. } else {
  1113. $self->line_error($message, $line_nr);
  1114. }
  1115. }
  1116. # currently doesn't do much more than
  1117. # return $_[1]->{'parent'}
  1118. sub _close_brace_command($$$;$$)
  1119. {
  1120. my $self = shift;
  1121. my $current = shift;
  1122. my $line_nr = shift;
  1123. my $closed_command = shift;
  1124. my $interrupting_command = shift;
  1125. if ($current->{'cmdname'} ne 'verb' or $current->{'type'} eq '') {
  1126. if (defined($closed_command)) {
  1127. $self->_command_error($current, $line_nr,
  1128. $self->__("\@end %s seen before \@%s closing brace"),
  1129. $closed_command, $current->{'cmdname'});
  1130. } elsif (defined($interrupting_command)) {
  1131. $self->_command_error($current, $line_nr,
  1132. $self->__("\@%s seen before \@%s closing brace"),
  1133. $interrupting_command, $current->{'cmdname'});
  1134. } else {
  1135. $self->_command_error($current, $line_nr,
  1136. $self->__("%c%s missing close brace"), ord('@'), $current->{'cmdname'});
  1137. }
  1138. } else {
  1139. $self->_command_error($current, $line_nr,
  1140. $self->__("\@%s missing closing delimiter sequence: %s}"),
  1141. $current->{'cmdname'}, $current->{'type'});
  1142. }
  1143. $current = $current->{'parent'};
  1144. return $current;
  1145. }
  1146. sub _in_code($$)
  1147. {
  1148. my $self = shift;
  1149. my $current = shift;
  1150. while ($current->{'parent'} and $current->{'parent'}->{'cmdname'}
  1151. and exists $brace_commands{$current->{'parent'}->{'cmdname'}}
  1152. and !exists $context_brace_commands{$current->{'parent'}->{'cmdname'}}) {
  1153. return 1 if ($code_style_commands{$current->{'parent'}->{'cmdname'}});
  1154. $current = $current->{'parent'}->{'parent'};
  1155. }
  1156. return 0;
  1157. }
  1158. # close brace commands, that don't set a new context (ie @caption, @footnote)
  1159. sub _close_all_style_commands($$$;$$)
  1160. {
  1161. my $self = shift;
  1162. my $current = shift;
  1163. my $line_nr = shift;
  1164. my $closed_command = shift;
  1165. my $interrupting_command = shift;
  1166. while ($current->{'parent'} and $current->{'parent'}->{'cmdname'}
  1167. and exists $brace_commands{$current->{'parent'}->{'cmdname'}}
  1168. and !exists $context_brace_commands{$current->{'parent'}->{'cmdname'}}) {
  1169. $current = _close_brace_command($self, $current->{'parent'}, $line_nr,
  1170. $closed_command, $interrupting_command);
  1171. }
  1172. return $current;
  1173. }
  1174. # close brace commands except for @caption, @footnote then the paragraph
  1175. sub _end_paragraph($$$;$$)
  1176. {
  1177. my $self = shift;
  1178. my $current = shift;
  1179. my $line_nr = shift;
  1180. my $closed_command = shift;
  1181. my $interrupting_command = shift;
  1182. $current = _close_all_style_commands($self, $current, $line_nr,
  1183. $closed_command, $interrupting_command);
  1184. if ($current->{'type'} and $current->{'type'} eq 'paragraph') {
  1185. print STDERR "CLOSE PARA\n" if ($self->{'DEBUG'});
  1186. $current = $current->{'parent'};
  1187. }
  1188. return $current;
  1189. }
  1190. # close brace commands except for @caption, @footnote then the preformatted
  1191. sub _end_preformatted($$$;$$)
  1192. {
  1193. my $self = shift;
  1194. my $current = shift;
  1195. my $line_nr = shift;
  1196. my $closed_command = shift;
  1197. my $interrupting_command = shift;
  1198. $current = _close_all_style_commands($self, $current, $line_nr,
  1199. $closed_command, $interrupting_command);
  1200. if ($current->{'type'} and $preformatted_contexts{$current->{'type'}}) {
  1201. print STDERR "CLOSE PREFORMATTED $current->{'type'}\n" if ($self->{'DEBUG'});
  1202. # completly remove void preformatted contexts
  1203. if (!@{$current->{'contents'}}) {
  1204. my $removed = pop @{$current->{'parent'}->{'contents'}};
  1205. print STDERR "popping $removed->{'type'}\n" if ($self->{'DEBUG'});
  1206. }
  1207. $current = $current->{'parent'};
  1208. }
  1209. return $current;
  1210. }
  1211. # check that there are no text holding environment (currently
  1212. # checking only paragraphs and preformatted) in contents
  1213. sub _check_no_text($)
  1214. {
  1215. my $current = shift;
  1216. my $after_paragraph = 0;
  1217. foreach my $content (@{$current->{'contents'}}) {
  1218. if ($content->{'type'} and $content->{'type'} eq 'paragraph') {
  1219. $after_paragraph = 1;
  1220. last;
  1221. } elsif ($content->{'type'} and $preformatted_contexts{$content->{'type'}}) {
  1222. foreach my $preformatted_content (@{$content->{'contents'}}) {
  1223. if ((defined($preformatted_content->{'text'})
  1224. and $preformatted_content->{'text'} =~ /\S/)
  1225. or ($preformatted_content->{'cmdname'}
  1226. and ($preformatted_content->{'cmdname'} ne 'c'
  1227. and $preformatted_content->{'cmdname'} ne 'comment')
  1228. and !($preformatted_content->{'type'}
  1229. and $preformatted_content->{'type'} eq 'index_entry_command'))) {
  1230. $after_paragraph = 1;
  1231. last;
  1232. }
  1233. }
  1234. last if ($after_paragraph);
  1235. }
  1236. }
  1237. return $after_paragraph;
  1238. }
  1239. # put everything after the last @item/@itemx in an item_table type container
  1240. # and distinguish table_term and table_entry.
  1241. sub _gather_previous_item($$;$$)
  1242. {
  1243. my $self = shift;
  1244. my $current = shift;
  1245. my $next_command = shift;
  1246. my $line_nr = shift;
  1247. # nothing to do in that case.
  1248. if ($current->{'contents'}->[-1]->{'type'}
  1249. and $current->{'contents'}->[-1]->{'type'} eq 'before_item') {
  1250. if ($next_command and $next_command eq 'itemx') {
  1251. $self->line_warn(sprintf($self->__("\@itemx should not begin \@%s"),
  1252. $current->{'cmdname'}), $line_nr);
  1253. }
  1254. return;
  1255. }
  1256. #print STDERR "GATHER "._print_current($current)."\n";
  1257. my $type;
  1258. # if before an itemx, the type is different since there should not be
  1259. # real content, so it may be treated differently
  1260. if ($next_command and $next_command eq 'itemx') {
  1261. $type = 'inter_item';
  1262. } else {
  1263. $type = 'table_item';
  1264. }
  1265. my $table_gathered = {'type' => $type,
  1266. 'contents' => []};
  1267. # remove everything that is not an @item/@items or before_item to
  1268. # put it in the table_item, starting from the end.
  1269. my $contents_count = scalar(@{$current->{'contents'}});
  1270. for (my $i = 0; $i < $contents_count; $i++) {
  1271. #print STDERR "_gather_previous_item $i on $contents_count: "._print_current($current->{'contents'}->[-1])."\n";
  1272. if ($current->{'contents'}->[-1]->{'cmdname'}
  1273. and ($current->{'contents'}->[-1]->{'cmdname'} eq 'item'
  1274. or ($current->{'contents'}->[-1]->{'cmdname'} eq 'itemx'))) {
  1275. last;
  1276. } else {
  1277. my $item_content = pop @{$current->{'contents'}};
  1278. $item_content->{'parent'} = $table_gathered;
  1279. unshift @{$table_gathered->{'contents'}}, $item_content;
  1280. }
  1281. }
  1282. if ($type eq 'table_item') {
  1283. my $table_entry = {'type' => 'table_entry',
  1284. 'parent' => $current,
  1285. 'contents' => []};
  1286. my $table_term = {'type' => 'table_term',
  1287. 'parent' => $table_entry,
  1288. 'contents' => []};
  1289. push @{$table_entry->{'contents'}}, $table_term;
  1290. my $contents_count = scalar(@{$current->{'contents'}});
  1291. for (my $i = 0; $i < $contents_count; $i++) {
  1292. if ($current->{'contents'}->[-1]->{'type'}
  1293. and ($current->{'contents'}->[-1]->{'type'} eq 'before_item'
  1294. or $current->{'contents'}->[-1]->{'type'} eq 'table_entry')) {
  1295. last;
  1296. } else {
  1297. my $item_content = pop @{$current->{'contents'}};
  1298. $item_content->{'parent'} = $table_term;
  1299. unshift @{$table_term->{'contents'}}, $item_content;
  1300. # debug
  1301. if (! (($item_content->{'cmdname'}
  1302. and ($item_content->{'cmdname'} eq 'itemx'
  1303. or $item_content->{'cmdname'} eq 'item'))
  1304. or ($item_content->{'type'}
  1305. and $item_content->{'type'} eq 'inter_item'))) {
  1306. $self->_bug_message("wrong element in table term", $line_nr,
  1307. $item_content);
  1308. }
  1309. }
  1310. }
  1311. push @{$current->{'contents'}}, $table_entry;
  1312. if (scalar(@{$table_gathered->{'contents'}})) {
  1313. push @{$table_entry->{'contents'}}, $table_gathered;
  1314. $table_gathered->{'parent'} = $table_entry;
  1315. }
  1316. } else {
  1317. my $after_paragraph = _check_no_text($table_gathered);
  1318. if ($after_paragraph) {
  1319. $self->line_error($self->__("\@itemx must follow \@item"), $line_nr);
  1320. }
  1321. if (scalar(@{$table_gathered->{'contents'}})) {
  1322. push @{$current->{'contents'}}, $table_gathered;
  1323. $table_gathered->{'parent'} = $current;
  1324. }
  1325. }
  1326. }
  1327. # Starting from the end, gather everything util the def_line to put in
  1328. # a def_item
  1329. sub _gather_def_item($;$)
  1330. {
  1331. my $current = shift;
  1332. my $next_command = shift;
  1333. my $type;
  1334. # means that we are between a @def*x and a @def
  1335. if ($next_command) {
  1336. $type = 'inter_def_item';
  1337. } else {
  1338. $type = 'def_item';
  1339. }
  1340. # This may happen for a construct like
  1341. # @deffnx a b @section
  1342. # but otherwise the end of line will lead to the command closing
  1343. return if (!$current->{'cmdname'} or $current->{'cmdname'} =~ /x$/);
  1344. #print STDERR "_gather_def_item($type) in "._print_current($current)."\n";
  1345. my $def_item = {'type' => $type,
  1346. 'parent' => $current,
  1347. 'contents' => []};
  1348. # remove everything that is not a def_line to put it in the def_item,
  1349. # starting from the end.
  1350. my $contents_count = scalar(@{$current->{'contents'}});
  1351. for (my $i = 0; $i < $contents_count; $i++) {
  1352. #print STDERR "_gather_def_item $type ($i on $contents_count) "._print_current($current->{'contents'}->[-1])."\n";
  1353. if ($current->{'contents'}->[-1]->{'type'}
  1354. and $current->{'contents'}->[-1]->{'type'} eq 'def_line') {
  1355. # and !$current->{'contents'}->[-1]->{'extra'}->{'not_after_command'}) {
  1356. last;
  1357. } else {
  1358. my $item_content = pop @{$current->{'contents'}};
  1359. $item_content->{'parent'} = $def_item;
  1360. unshift @{$def_item->{'contents'}}, $item_content;
  1361. }
  1362. }
  1363. if (scalar(@{$def_item->{'contents'}})) {
  1364. push @{$current->{'contents'}}, $def_item;
  1365. }
  1366. }
  1367. # close formats
  1368. sub _close_command_cleanup($$$) {
  1369. my $self = shift;
  1370. my $current = shift;
  1371. return unless ($current->{'cmdname'});
  1372. # remove the dynamic counters in multitable, they are not of use in the final
  1373. # tree. Also determine the multitable_body and multitable_head with
  1374. # @item or @headitem rows.
  1375. if ($current->{'cmdname'} eq 'multitable') {
  1376. my $in_head_or_rows;
  1377. my @contents = @{$current->{'contents'}};
  1378. $current->{'contents'} = [];
  1379. foreach my $row (@contents) {
  1380. if ($row->{'type'} and $row->{'type'} eq 'row') {
  1381. delete $row->{'cells_count'};
  1382. if ($row->{'contents'}->[0]->{'cmdname'} eq 'headitem') {
  1383. if (!$in_head_or_rows) {
  1384. push @{$current->{'contents'}}, {'type' => 'multitable_head',
  1385. 'parent' => $current};
  1386. $in_head_or_rows = 1;
  1387. }
  1388. } elsif ($row->{'contents'}->[0]->{'cmdname'} eq 'item') {
  1389. if (!defined($in_head_or_rows) or $in_head_or_rows) {
  1390. push @{$current->{'contents'}}, {'type' => 'multitable_body',
  1391. 'parent' => $current};
  1392. $in_head_or_rows = 0;
  1393. }
  1394. }
  1395. push @{$current->{'contents'}->[-1]->{'contents'}}, $row;
  1396. $row->{'parent'} = $current->{'contents'}->[-1];
  1397. } else {
  1398. push @{$current->{'contents'}}, $row;
  1399. $in_head_or_rows = undef;
  1400. }
  1401. }
  1402. delete $current->{'rows_count'};
  1403. } elsif ($item_container_commands{$current->{'cmdname'}}) {
  1404. delete $current->{'items_count'};
  1405. }
  1406. # put everything after the last @def*x command in a def_item type container.
  1407. if ($def_commands{$current->{'cmdname'}}) {
  1408. # At this point the end command hasn't been added to the command contents.
  1409. # so checks cannot be done at this point.
  1410. _gather_def_item($current);
  1411. }
  1412. if ($item_line_commands{$current->{'cmdname'}}) {
  1413. # At this point the end command hasn't been added to the command contents.
  1414. # so checks cannot be done at this point.
  1415. if (@{$current->{'contents'}}) {
  1416. $self->_gather_previous_item($current);
  1417. }
  1418. }
  1419. # put end out of before_item, and replace it at the end of the parent.
  1420. # remove empty before_item.
  1421. # warn if not empty before_item, but format is empty
  1422. if ($block_item_commands{$current->{'cmdname'}}) {
  1423. if (@{$current->{'contents'}}) {
  1424. my $leading_spaces = 0;
  1425. my $before_item;
  1426. if ($current->{'contents'}->[0]->{'type'}
  1427. and $current->{'contents'}->[0]->{'type'} eq 'empty_line_after_command'
  1428. and $current->{'contents'}->[1]
  1429. and $current->{'contents'}->[1]->{'type'}
  1430. and $current->{'contents'}->[1]->{'type'} eq 'before_item') {
  1431. $leading_spaces = 1;
  1432. $before_item = $current->{'contents'}->[1];
  1433. } elsif ($current->{'contents'}->[0]->{'type'}
  1434. and $current->{'contents'}->[0]->{'type'} eq 'before_item') {
  1435. $before_item = $current->{'contents'}->[0];
  1436. }
  1437. if ($before_item) {
  1438. if ($current->{'extra'}->{'end_command'}
  1439. and @{$before_item->{'contents'}}
  1440. and $before_item->{'contents'}->[-1] eq $current->{'extra'}->{'end_command'}) {
  1441. my $end = pop @{$before_item->{'contents'}};
  1442. $end->{'parent'} = $current;
  1443. push @{$current->{'contents'}}, $end;
  1444. }
  1445. # remove empty before_items
  1446. if (!@{$before_item->{'contents'}}) {
  1447. if ($leading_spaces) {
  1448. my $space = shift @{$current->{'contents'}};
  1449. shift @{$current->{'contents'}};
  1450. unshift @{$current->{'contents'}}, $space;
  1451. } else {
  1452. shift @{$current->{'contents'}};
  1453. }
  1454. } else {
  1455. # warn if not empty before_item, but format is empty
  1456. my $empty_before_item = 1;
  1457. foreach my $before_item_content (@{$before_item->{'contents'}}) {
  1458. if (!$before_item_content->{'cmdname'} or
  1459. ($before_item_content->{'cmdname'} ne 'c'
  1460. and $before_item_content->{'cmdname'} ne 'comment')) {
  1461. $empty_before_item = 0;
  1462. last;
  1463. }
  1464. }
  1465. if (!$empty_before_item) {
  1466. my $empty_format = 1;
  1467. foreach my $format_content (@{$current->{'contents'}}) {
  1468. next if ($format_content eq $before_item);
  1469. if (($format_content->{'cmdname'} and
  1470. ($format_content->{'cmdname'} ne 'c'
  1471. and $format_content->{'cmdname'} ne 'comment'
  1472. and $format_content->{'cmdname'} ne 'end'))
  1473. or ($format_content->{'type'} and
  1474. ($format_content->{'type'} ne 'empty_line_after_command'))) {
  1475. $empty_format = 0;
  1476. last;
  1477. }
  1478. }
  1479. if ($empty_format) {
  1480. $self->line_warn(sprintf($self->__("\@%s has text but no \@item"),
  1481. $current->{'cmdname'}), $current->{'line_nr'});
  1482. }
  1483. }
  1484. }
  1485. }
  1486. }
  1487. }
  1488. }
  1489. # close the current command, with error messages and give the parent.
  1490. # If the last argument is given it is the command being closed if
  1491. # hadn't there be an error, currently only block command, used for a
  1492. # better error message.
  1493. sub _close_current($$$;$$)
  1494. {
  1495. my $self = shift;
  1496. my $current = shift;
  1497. my $line_nr = shift;
  1498. my $closed_command = shift;
  1499. my $interrupting_command = shift;
  1500. if ($current->{'cmdname'}) {
  1501. print STDERR "CLOSING(_close_current) \@$current->{'cmdname'}\n" if ($self->{'DEBUG'});
  1502. if (exists($brace_commands{$current->{'cmdname'}})) {
  1503. pop @{$self->{'context_stack'}}
  1504. if (exists $context_brace_commands{$current->{'cmdname'}});
  1505. $current = _close_brace_command($self, $current, $line_nr,
  1506. $closed_command, $interrupting_command);
  1507. } elsif (exists($block_commands{$current->{'cmdname'}})) {
  1508. if (defined($closed_command)) {
  1509. $self->line_error(sprintf($self->__("`\@end' expected `%s', but saw `%s'"),
  1510. $current->{'cmdname'}, $closed_command), $line_nr);
  1511. } elsif ($interrupting_command) {
  1512. $self->line_error(sprintf($self->__("\@%s seen before \@end %s"),
  1513. $interrupting_command, $current->{'cmdname'}),
  1514. $line_nr);
  1515. } else {
  1516. $self->line_error(sprintf($self->__("no matching `%cend %s'"),
  1517. ord('@'), $current->{'cmdname'}), $line_nr);
  1518. if ($block_commands{$current->{'cmdname'}} eq 'conditional') {
  1519. # in this case we are within an ignored conditional
  1520. my $conditional = pop @{$current->{'parent'}->{'contents'}};
  1521. }
  1522. }
  1523. if ($preformatted_commands{$current->{'cmdname'}}
  1524. or $menu_commands{$current->{'cmdname'}}
  1525. or $format_raw_commands{$current->{'cmdname'}}) {
  1526. my $context = pop @{$self->{'context_stack'}};
  1527. pop @{$self->{'expanded_formats_stack'}}
  1528. if ($format_raw_commands{$current->{'cmdname'}});
  1529. }
  1530. pop @{$self->{'regions_stack'}}
  1531. if ($region_commands{$current->{'cmdname'}});
  1532. $current = $current->{'parent'};
  1533. } else {
  1534. # There @item and @tab commands are closed, and also line commands
  1535. # with invalid content
  1536. $current = $current->{'parent'};
  1537. }
  1538. } elsif ($current->{'type'}) {
  1539. print STDERR "CLOSING type $current->{'type'}\n" if ($self->{'DEBUG'});
  1540. if ($current->{'type'} eq 'bracketed') {
  1541. $self->_command_error($current, $line_nr,
  1542. $self->__("misplaced %c"), ord('{'));
  1543. } elsif ($current->{'type'} eq 'menu_comment'
  1544. or $current->{'type'} eq 'menu_entry_description') {
  1545. my $context = pop @{$self->{'context_stack'}};
  1546. if ($context ne 'preformatted') {
  1547. $self->_bug_message("context $context instead of preformatted",
  1548. $line_nr, $current);
  1549. }
  1550. # close empty menu_comment
  1551. if (!@{$current->{'contents'}}) {
  1552. pop @{$current->{'parent'}->{'contents'}};
  1553. }
  1554. } elsif ($current->{'type'} eq 'misc_line_arg'
  1555. or $current->{'type'} eq 'block_line_arg') {
  1556. my $context = pop @{$self->{'context_stack'}};
  1557. if ($context ne 'line' and $context ne 'def') {
  1558. $self->_bug_message("context $context instead of line or def",
  1559. $line_nr, $current);
  1560. die;
  1561. }
  1562. }
  1563. $current = $current->{'parent'};
  1564. } else { # Should never go here.
  1565. $current = $current->{'parent'} if ($current->{'parent'});
  1566. $self->_bug_message("No type nor cmdname when closing",
  1567. $line_nr, $current);
  1568. }
  1569. return $current;
  1570. }
  1571. # a closed_command arg means closing until that command is found.
  1572. # no command arg means closing until the root or a root_command
  1573. # is found.
  1574. sub _close_commands($$$;$$)
  1575. {
  1576. my $self = shift;
  1577. my $current = shift;
  1578. my $line_nr = shift;
  1579. my $closed_command = shift;
  1580. my $interrupting_command = shift;;
  1581. $current = _end_paragraph($self, $current, $line_nr, $closed_command,
  1582. $interrupting_command);
  1583. $current = _end_preformatted($self, $current, $line_nr, $closed_command,
  1584. $interrupting_command);
  1585. # stop if the command is found
  1586. while (!($closed_command and $current->{'cmdname'}
  1587. and $current->{'cmdname'} eq $closed_command)
  1588. # stop if at the root
  1589. and $current->{'parent'}
  1590. # stop if in a root command
  1591. # or in a context_brace_commands and searching for a specific
  1592. # end block command (with $closed_command set).
  1593. # This second condition means that a footnote is not closed when
  1594. # looking for the end of a block command, but is closed when
  1595. # completly closing the stack.
  1596. and !($current->{'cmdname'}
  1597. and ($root_commands{$current->{'cmdname'}}
  1598. or ($closed_command and $current->{'parent'}->{'cmdname'}
  1599. and $context_brace_commands{$current->{'parent'}->{'cmdname'}})))){
  1600. $self->_close_command_cleanup($current);
  1601. $current = $self->_close_current($current, $line_nr, $closed_command,
  1602. $interrupting_command);
  1603. }
  1604. my $closed_element;
  1605. if ($closed_command and $current->{'cmdname'}
  1606. and $current->{'cmdname'} eq $closed_command) {
  1607. if ($preformatted_commands{$current->{'cmdname'}}) {
  1608. my $context = pop @{$self->{'context_stack'}};
  1609. if ($context ne 'preformatted') {
  1610. $self->_bug_message("context $context instead of preformatted for $closed_command",
  1611. $line_nr, $current);
  1612. }
  1613. } elsif ($format_raw_commands{$current->{'cmdname'}}) {
  1614. my $context = pop @{$self->{'context_stack'}};
  1615. if ($context ne 'rawpreformatted') {
  1616. $self->_bug_message("context $context instead of rawpreformatted for $closed_command",
  1617. $line_nr, $current);
  1618. }
  1619. pop @{$self->{'expanded_formats_stack'}};
  1620. } elsif ($menu_commands{$current->{'cmdname'}}) {
  1621. my $context = pop @{$self->{'context_stack'}};
  1622. # may be in menu, but context is preformatted if in a preformatted too.
  1623. if ($context ne 'menu' and $context ne 'preformatted') {
  1624. $self->_bug_message("context $context instead of preformatted or menu for $closed_command",
  1625. $line_nr, $current);
  1626. }
  1627. }
  1628. #print STDERR "close context $context for $current->{'cmdname'}\n"
  1629. # if ($self->{'DEBUG'});
  1630. pop @{$self->{'regions_stack'}}
  1631. if ($region_commands{$current->{'cmdname'}});
  1632. $closed_element = $current;
  1633. #$self->_close_command_cleanup($current);
  1634. $current = $current->{'parent'};
  1635. } elsif ($closed_command) {
  1636. $self->line_error(sprintf($self->__("unmatched `%c%s'"),
  1637. ord('@'), "end $closed_command"), $line_nr);
  1638. }
  1639. return ($closed_element, $current);
  1640. }
  1641. # begin paragraph if needed. If not try to merge with the previous
  1642. # content if it is also some text.
  1643. sub _merge_text($$$)
  1644. {
  1645. my $self = shift;
  1646. my $current = shift;
  1647. my $text = shift;
  1648. my $paragraph;
  1649. my $no_merge_with_following_text = 0;
  1650. if ($text =~ /\S/) {
  1651. my $leading_spaces;
  1652. if ($text =~ /^(\s+)/) {
  1653. $leading_spaces = $1;
  1654. }
  1655. if ($current->{'contents'} and @{$current->{'contents'}}
  1656. and $current->{'contents'}->[-1]->{'type'}
  1657. and ($current->{'contents'}->[-1]->{'type'} eq 'empty_line_after_command'
  1658. or $current->{'contents'}->[-1]->{'type'} eq 'empty_spaces_before_argument'
  1659. or $current->{'contents'}->[-1]->{'type'} eq 'empty_spaces_after_close_brace')) {
  1660. $no_merge_with_following_text = 1;
  1661. }
  1662. if (_abort_empty_line($self, $current, $leading_spaces)) {
  1663. $text =~ s/^(\s+)//;
  1664. }
  1665. $paragraph = _begin_paragraph($self, $current);
  1666. $current = $paragraph if ($paragraph);
  1667. }
  1668. if (!defined($current->{'contents'})) {
  1669. $self->_bug_message("No contents in _merge_text",
  1670. undef, $current);
  1671. die;
  1672. }
  1673. if (@{$current->{'contents'}}
  1674. and exists($current->{'contents'}->[-1]->{'text'})
  1675. and $current->{'contents'}->[-1]->{'text'} !~ /\n/
  1676. and !$no_merge_with_following_text) {
  1677. $current->{'contents'}->[-1]->{'text'} .= $text;
  1678. print STDERR "MERGED TEXT: $text|||\n" if ($self->{'DEBUG'});
  1679. } else {
  1680. push @{$current->{'contents'}}, { 'text' => $text, 'parent' => $current };
  1681. print STDERR "NEW TEXT: $text|||\n" if ($self->{'DEBUG'});
  1682. }
  1683. return $current;
  1684. }
  1685. # return the parent if in a item_container command, itemize or enumerate
  1686. sub _item_container_parent($)
  1687. {
  1688. my $current = shift;
  1689. if ((($current->{'cmdname'} and $current->{'cmdname'} eq 'item')
  1690. or ($current->{'type'} and $current->{'type'} eq 'before_item'))
  1691. and ($current->{'parent'} and $current->{'parent'}->{'cmdname'}
  1692. and $item_container_commands{$current->{'parent'}->{'cmdname'}})) {
  1693. return ($current->{'parent'});
  1694. }
  1695. return undef;
  1696. }
  1697. # return the parent if in a item_line command, @*table
  1698. sub _item_line_parent($)
  1699. {
  1700. my $current = shift;
  1701. if ($current->{'cmdname'} and ($current->{'cmdname'} eq 'item'
  1702. or $current->{'cmdname'} eq 'itemx')) {
  1703. $current = $current->{'parent'}->{'parent'};
  1704. } elsif ($current->{'type'} and $current->{'type'} eq 'before_item'
  1705. and $current->{'parent'}) {
  1706. $current = $current->{'parent'};
  1707. }
  1708. return $current if ($current->{'cmdname'}
  1709. and $item_line_commands{$current->{'cmdname'}});
  1710. return undef;
  1711. }
  1712. # return the parent if in a multitable
  1713. sub _item_multitable_parent($)
  1714. {
  1715. my $current = shift;
  1716. if (($current->{'cmdname'} and ($current->{'cmdname'} eq 'headitem'
  1717. or $current->{'cmdname'} eq 'item' or $current->{'cmdname'} eq 'tab'))
  1718. and $current->{'parent'} and $current->{'parent'}->{'parent'}) {
  1719. $current = $current->{'parent'}->{'parent'};
  1720. } elsif ($current->{'type'} and $current->{'type'} eq 'before_item'
  1721. and $current->{'parent'}) {
  1722. $current = $current->{'parent'};
  1723. }
  1724. return $current if ($current->{'cmdname'}
  1725. and $current->{'cmdname'} eq 'multitable');
  1726. return undef;
  1727. }
  1728. # returns next text fragment, be it pending from a macro expansion or
  1729. # text or file
  1730. sub _next_text($$$)
  1731. {
  1732. my $self = shift;
  1733. my $line_nr = shift;
  1734. my $current = shift;
  1735. while (@{$self->{'input'}}) {
  1736. my $input = $self->{'input'}->[0];
  1737. if (@{$input->{'pending'}}) {
  1738. my $new_text = shift @{$input->{'pending'}};
  1739. if ($new_text->[1] and $new_text->[1]->{'end_macro'}) {
  1740. delete $new_text->[1]->{'end_macro'};
  1741. my $top_macro = shift @{$self->{'macro_stack'}};
  1742. print STDERR "SHIFT MACRO_STACK(@{$self->{'macro_stack'}}): $top_macro->{'args'}->[0]->{'text'}\n"
  1743. if ($self->{'DEBUG'});
  1744. }
  1745. return ($new_text->[0], $new_text->[1]);
  1746. } elsif ($input->{'fh'}) {
  1747. my $fh = $input->{'fh'};
  1748. my $line = <$fh>;
  1749. while (defined($line)) {
  1750. # add an end of line if there is none at the end of file
  1751. if (eof($fh) and $line !~ /\n/) {
  1752. $line .= "\n";
  1753. }
  1754. $line =~ s/\x{7F}.*\s*//;
  1755. if ($self->{'CPP_LINE_DIRECTIVES'}
  1756. # no cpp directives in ignored/macro/verbatim
  1757. and defined ($current)
  1758. and not
  1759. (($current->{'cmdname'}
  1760. and $block_commands{$current->{'cmdname'}}
  1761. and ($block_commands{$current->{'cmdname'}} eq 'raw'
  1762. or $block_commands{$current->{'cmdname'}} eq 'conditional'))
  1763. or
  1764. ($current->{'parent'} and $current->{'parent'}->{'cmdname'}
  1765. and $current->{'parent'}->{'cmdname'} eq 'verb')
  1766. )
  1767. and $line =~ /^\s*#\s*(line)? (\d+)(( "([^"]+)")(\s+\d+)*)?\s*$/) {
  1768. $input->{'line_nr'} = $2;
  1769. if (defined($5)) {
  1770. $input->{'name'} = $5;
  1771. }
  1772. $line = <$fh>;
  1773. } else {
  1774. $input->{'line_nr'}++;
  1775. return ($line, {'line_nr' => $input->{'line_nr'},
  1776. 'file_name' => $input->{'name'},
  1777. 'macro' => ''});
  1778. }
  1779. }
  1780. }
  1781. my $previous_input = shift(@{$self->{'input'}});
  1782. # Don't close STDIN
  1783. if ($previous_input->{'fh'} and $previous_input->{'name'} ne '-') {
  1784. if (!close($previous_input->{'fh'})) {
  1785. $self->document_warn(sprintf($self->__("error on closing %s: %s"),
  1786. $previous_input->{'name'}, $!));
  1787. }
  1788. }
  1789. }
  1790. return (undef, $line_nr);
  1791. }
  1792. # collect text and line numbers until an end of line is found.
  1793. sub _new_line($$$)
  1794. {
  1795. my $self = shift;
  1796. my $line_nr = shift;
  1797. my $current = shift;
  1798. my $new_line = '';
  1799. while (1) {
  1800. my $new_text;
  1801. ($new_text, $line_nr) = _next_text($self, $line_nr, $current);
  1802. if (!defined($new_text)) {
  1803. $new_line = undef if ($new_line eq '');
  1804. last;
  1805. }
  1806. $new_line .= $new_text;
  1807. my $chomped_text = $new_text;
  1808. last if chomp($chomped_text);
  1809. }
  1810. return ($new_line, $line_nr);
  1811. }
  1812. sub _expand_macro_arguments($$$$)
  1813. {
  1814. my $self = shift;
  1815. my $macro = shift;
  1816. my $line = shift;
  1817. my $line_nr = shift;
  1818. my $braces_level = 1;
  1819. my $arguments = [ '' ];
  1820. my $arg_nr = 0;
  1821. my $args_total = scalar(@{$macro->{'args'}}) -1;
  1822. my $name = $macro->{'args'}->[0]->{'text'};
  1823. my $line_nr_orig = $line_nr;
  1824. while (1) {
  1825. if ($line =~ s/([^\\{},]*)([\\{},])//) {
  1826. my $separator = $2;
  1827. $arguments->[-1] .= $1;
  1828. if ($separator eq '\\') {
  1829. if ($line =~ s/^(.)//) {
  1830. my $protected_char = $1;
  1831. if ($protected_char !~ /[\\{},]/) {
  1832. $arguments->[-1] .= '\\';
  1833. }
  1834. $arguments->[-1] .= $protected_char;
  1835. print STDERR "MACRO ARG: $separator: $protected_char\n" if ($self->{'DEBUG'});
  1836. } else {
  1837. $arguments->[-1] .= '\\';
  1838. print STDERR "MACRO ARG: $separator\n" if ($self->{'DEBUG'});
  1839. }
  1840. } elsif ($separator eq ',') {
  1841. if ($braces_level == 1) {
  1842. if (scalar(@$arguments) < $args_total) {
  1843. push @$arguments, '';
  1844. $line =~ s/^[^\S\f]*//;
  1845. print STDERR "MACRO NEW ARG\n" if ($self->{'DEBUG'});
  1846. } else {
  1847. # implicit quoting when there is one argument.
  1848. if ($args_total != 1) {
  1849. $self->line_error(sprintf($self->__(
  1850. "macro `%s' called with too many args"),
  1851. $name), $line_nr);
  1852. }
  1853. $arguments->[-1] .= ',';
  1854. }
  1855. } else {
  1856. $arguments->[-1] .= ',';
  1857. }
  1858. } elsif ($separator eq '}') {
  1859. $braces_level--;
  1860. last if ($braces_level == 0);
  1861. $arguments->[-1] .= $separator;
  1862. } elsif ($separator eq '{') {
  1863. $braces_level++;
  1864. $arguments->[-1] .= $separator;
  1865. }
  1866. } else {
  1867. print STDERR "MACRO ARG end of line\n" if ($self->{'DEBUG'});
  1868. $arguments->[-1] .= $line;
  1869. ($line, $line_nr) = _new_line($self, $line_nr, $macro);
  1870. if (!defined($line)) {
  1871. $self->line_error(sprintf($self->__("\@%s missing close brace"),
  1872. $name), $line_nr_orig);
  1873. return ($arguments, "\n", $line_nr);
  1874. }
  1875. }
  1876. }
  1877. if ($args_total == 0 and $arguments->[0] =~ /[\S\f]/) {
  1878. $self->line_error(sprintf($self->__(
  1879. "macro `%s' declared without argument called with an argument"),
  1880. $name), $line_nr);
  1881. }
  1882. print STDERR "END MACRO ARGS EXPANSION(".scalar(@$arguments)."): ".
  1883. join("|\n", @$arguments) ."|\n" if ($self->{'DEBUG'});
  1884. return ($arguments, $line, $line_nr);
  1885. }
  1886. sub _expand_macro_body($$$$) {
  1887. my $self = shift;
  1888. my $macro = shift;
  1889. my $args = shift;
  1890. my $line_nr = shift;
  1891. my $macrobody = $macro->{'extra'}->{'macrobody'};
  1892. my $args_total = scalar(@{$macro->{'args'}}) -1;
  1893. my $args_index = $macro->{'extra'}->{'args_index'};
  1894. my $i;
  1895. for ($i=0; $i<=$args_total; $i++) {
  1896. $args->[$i] = "" unless (defined($args->[$i]));
  1897. }
  1898. my $result = '';
  1899. while ($macrobody ne '') {
  1900. if ($macrobody =~ s/^([^\\]*)\\//o) {
  1901. $result .= $1;
  1902. if ($macrobody =~ s/^\\//) {
  1903. $result .= '\\';
  1904. } elsif ($macrobody =~ s/^([^\\]*)\\//) {
  1905. my $arg = $1;
  1906. if (defined($args_index->{$arg})) {
  1907. $result .= $args->[$args_index->{$arg}];
  1908. } else {
  1909. $self->line_error(sprintf($self->__(
  1910. "\\ in \@%s expansion followed `%s' instead of parameter name or \\"),
  1911. $macro->{'args'}->[0]->{'text'}, $arg), $line_nr);
  1912. $result .= '\\' . $arg;
  1913. }
  1914. }
  1915. next;
  1916. }
  1917. $result .= $macrobody;
  1918. last;
  1919. }
  1920. return $result;
  1921. }
  1922. # each time a new line appeared, a container is opened to hold the text
  1923. # consisting only of spaces. This container is removed here, typically
  1924. # this is called when non-space happens on a line.
  1925. sub _abort_empty_line($$;$)
  1926. {
  1927. my $self = shift;
  1928. my $current = shift;
  1929. my $additional_text = shift;
  1930. $additional_text = '' if (!defined($additional_text));
  1931. if ($current->{'contents'} and @{$current->{'contents'}}
  1932. and $current->{'contents'}->[-1]->{'type'}
  1933. and ($current->{'contents'}->[-1]->{'type'} eq 'empty_line'
  1934. or $current->{'contents'}->[-1]->{'type'} eq 'empty_line_after_command'
  1935. or $current->{'contents'}->[-1]->{'type'} eq 'empty_spaces_before_argument'
  1936. or $current->{'contents'}->[-1]->{'type'} eq 'empty_spaces_after_close_brace')) {
  1937. print STDERR "ABORT EMPTY additional text |$additional_text|, current |$current->{'contents'}->[-1]->{'text'}|\n" if ($self->{'DEBUG'});
  1938. $current->{'contents'}->[-1]->{'text'} .= $additional_text;
  1939. # remove empty 'empty*before'.
  1940. if ($current->{'contents'}->[-1]->{'text'} eq '') {
  1941. # as we remove 'empty_spaces_before_argument', 'spaces_before_argument'
  1942. # is removed from 'extra' too.
  1943. if ($current->{'extra'}
  1944. and $current->{'extra'}->{'spaces_before_argument'}
  1945. and $current->{'extra'}->{'spaces_before_argument'}
  1946. eq $current->{'contents'}->[-1]) {
  1947. delete ($current->{'extra'}->{'spaces_before_argument'});
  1948. delete ($current->{'extra'}) if !(keys(%{$current->{'extra'}}));
  1949. }
  1950. pop @{$current->{'contents'}}
  1951. } elsif ($current->{'contents'}->[-1]->{'type'} eq 'empty_line') {
  1952. # exactly the same condition than to begin a paragraph
  1953. if ((!$current->{'type'} or $type_with_paragraph{$current->{'type'}})
  1954. and !$no_paragraph_contexts{$self->{'context_stack'}->[-1]}) {
  1955. $current->{'contents'}->[-1]->{'type'} = 'empty_spaces_before_paragraph';
  1956. } else {
  1957. delete $current->{'contents'}->[-1]->{'type'};
  1958. }
  1959. } elsif ($current->{'contents'}->[-1]->{'type'} eq 'empty_line_after_command') {
  1960. $current->{'contents'}->[-1]->{'type'} = 'empty_spaces_after_command';
  1961. }
  1962. return 1;
  1963. }
  1964. return 0;
  1965. }
  1966. # isolate last space in a command to help expansion disregard unuseful spaces.
  1967. sub _isolate_last_space($$;$)
  1968. {
  1969. my $self = shift;
  1970. my $current = shift;
  1971. my $type = shift;
  1972. $type = 'spaces_at_end' if (!defined($type));
  1973. if ($current->{'contents'} and @{$current->{'contents'}}) {
  1974. my $index = -1;
  1975. # we ignore space before a misc command that is last on line.
  1976. # This is primarily to tag spaces before comments, but this will
  1977. # also tag and, in most converter lead to removal of spaces
  1978. # before any misc command, which is not really problematic as
  1979. # in most cases, if it is not a comment, we are in an invalid
  1980. # nesting of misc command on another @-command line.
  1981. $index = -2
  1982. if (scalar(@{$current->{'contents'}}) > 1
  1983. and $current->{'contents'}->[-1]->{'cmdname'}
  1984. and $self->{'misc_commands'}->{$current->{'contents'}->[-1]->{'cmdname'}});
  1985. if (defined($current->{'contents'}->[$index]->{'text'})
  1986. and !$current->{'contents'}->[$index]->{'type'}
  1987. and $current->{'contents'}->[$index]->{'text'} =~ /\s+$/) {
  1988. if ($current->{'contents'}->[$index]->{'text'} !~ /\S/) {
  1989. $current->{'contents'}->[$index]->{'type'} = $type;
  1990. } else {
  1991. $current->{'contents'}->[$index]->{'text'} =~ s/(\s+)$//;
  1992. my $spaces = $1;
  1993. my $new_spaces = { 'text' => $spaces, 'parent' => $current,
  1994. 'type' => $type };
  1995. if ($index == -1) {
  1996. push @{$current->{'contents'}}, $new_spaces;
  1997. } else {
  1998. splice (@{$current->{'contents'}}, $index+1, 0, $new_spaces);
  1999. }
  2000. }
  2001. }
  2002. }
  2003. }
  2004. # used to put a node name in error messages.
  2005. sub _node_extra_to_texi($)
  2006. {
  2007. my $node = shift;
  2008. my $result = '';
  2009. if ($node->{'manual_content'}) {
  2010. $result = '('.Texinfo::Convert::Texinfo::convert({'contents'
  2011. => $node->{'manual_content'}}) .')';
  2012. }
  2013. if ($node->{'node_content'}) {
  2014. $result .= Texinfo::Convert::Texinfo::convert ({'contents'
  2015. => $node->{'node_content'}});
  2016. }
  2017. return $result;
  2018. }
  2019. sub _find_end_brace($$)
  2020. {
  2021. my $text = shift;
  2022. my $braces_count = shift;
  2023. my $before = '';
  2024. while ($braces_count > 0 and length($text)) {
  2025. if ($text =~ s/([^()]*)([()])//) {
  2026. $before .= $1.$2;
  2027. my $brace = $2;
  2028. if ($brace eq '(') {
  2029. $braces_count++;
  2030. } else {
  2031. $braces_count--;
  2032. if ($braces_count == 0) {
  2033. return ($before, $text, 0);
  2034. }
  2035. }
  2036. } else {
  2037. $before .= $text;
  2038. $text = '';
  2039. }
  2040. }
  2041. return ($before, undef, $braces_count);
  2042. }
  2043. # This only counts opening braces, and returns 0 once all the parentheses
  2044. # are closed
  2045. sub _count_opened_tree_braces($$);
  2046. sub _count_opened_tree_braces($$)
  2047. {
  2048. my $current = shift;
  2049. my $braces_count = shift;
  2050. if (defined($current->{'text'})) {
  2051. my ($before, $after);
  2052. ($before, $after, $braces_count) = _find_end_brace($current->{'text'},
  2053. $braces_count);
  2054. }
  2055. if ($current->{'args'}) {
  2056. foreach my $arg (@{$current->{'args'}}) {
  2057. $braces_count = _count_opened_tree_braces($arg, $braces_count);
  2058. return $braces_count if ($braces_count == 0);
  2059. }
  2060. }
  2061. if ($current->{'contents'}) {
  2062. foreach my $content (@{$current->{'contents'}}) {
  2063. $braces_count = _count_opened_tree_braces($content, $braces_count);
  2064. return $braces_count if ($braces_count == 0);
  2065. }
  2066. }
  2067. return $braces_count;
  2068. }
  2069. # retrieve a leading manual name in parentheses, if there is one.
  2070. sub _parse_node_manual($)
  2071. {
  2072. my $node = shift;
  2073. my @contents = @{$node->{'contents'}};
  2074. _trim_spaces_comment_from_content(\@contents);
  2075. my $manual;
  2076. my $result;
  2077. #print STDERR "RRR $contents[0] and $contents[0]->{'text'} \n";
  2078. if ($contents[0] and $contents[0]->{'text'} and $contents[0]->{'text'} =~ /^\(/) {
  2079. my $braces_count = 1;
  2080. if ($contents[0]->{'text'} !~ /^\($/) {
  2081. my $brace = shift @contents;
  2082. my $brace_text = $brace->{'text'};
  2083. $brace_text =~ s/^\(//;
  2084. unshift @contents, { 'text' => $brace_text, 'type' => $brace->{'type'},
  2085. 'parent' => $brace->{'parent'} } if $brace_text ne '';
  2086. } else {
  2087. shift @contents;
  2088. }
  2089. while(@contents) {
  2090. my $content = shift @contents;
  2091. if (!defined($content->{'text'}) or $content->{'text'} !~ /\)/) {
  2092. push @$manual, $content;
  2093. $braces_count = _count_opened_tree_braces($content, $braces_count);
  2094. # This is an error, braces were closed in a command
  2095. if ($braces_count == 0) {
  2096. last;
  2097. }
  2098. } else {
  2099. my ($before, $after);
  2100. ($before, $after, $braces_count) = _find_end_brace($content->{'text'},
  2101. $braces_count);
  2102. if ($braces_count == 0) {
  2103. $before =~ s/\)$//;
  2104. push @$manual, { 'text' => $before, 'parent' => $content->{'parent'} }
  2105. if ($before ne '');
  2106. $after =~ s/^\s*//;
  2107. unshift @contents, { 'text' => $after, 'parent' => $content->{'parent'} }
  2108. if ($after ne '');
  2109. last;
  2110. } else {
  2111. push @$manual, $content;
  2112. }
  2113. }
  2114. }
  2115. $result->{'manual_content'} = $manual if (defined($manual));
  2116. }
  2117. if (@contents) {
  2118. $result->{'node_content'} = \@contents;
  2119. $result->{'normalized'} =
  2120. Texinfo::Convert::NodeNameNormalization::normalize_node({'contents' => \@contents});
  2121. }
  2122. return $result;
  2123. }
  2124. sub _parse_float_type($)
  2125. {
  2126. my $current = shift;
  2127. if (@{$current->{'args'}}) {
  2128. my @type_contents = @{$current->{'args'}->[0]->{'contents'}};
  2129. _trim_spaces_comment_from_content(\@type_contents);
  2130. if (@type_contents) {
  2131. my $normalized
  2132. = Texinfo::Convert::NodeNameNormalization::normalize_node(
  2133. {'contents' => \@type_contents});
  2134. $current->{'extra'}->{'type'}->{'content'} = \@type_contents;
  2135. if ($normalized =~ /[^-]/) {
  2136. $current->{'extra'}->{'type'}->{'normalized'} = $normalized;
  2137. return 1;
  2138. }
  2139. }
  2140. }
  2141. $current->{'extra'}->{'type'}->{'normalized'} = '';
  2142. return 0;
  2143. }
  2144. # used for definition line parsing
  2145. sub _next_bracketed_or_word($$)
  2146. {
  2147. my $self = shift;
  2148. my $contents = shift;
  2149. return undef if (!scalar(@{$contents}));
  2150. my $spaces;
  2151. $spaces = shift @{$contents} if (defined($contents->[0]->{'text'}) and
  2152. $contents->[0]->{'text'} !~ /\S/);
  2153. if (defined($spaces)) {
  2154. $spaces->{'type'} = 'spaces';
  2155. chomp $spaces->{'text'};
  2156. $spaces = undef if ($spaces->{'text'} eq '');
  2157. }
  2158. return ($spaces, undef) if (!scalar(@{$contents}));
  2159. #print STDERR "BEFORE PROCESSING ".Texinfo::Convert::Texinfo::convert({'contents' => $contents});
  2160. if ($contents->[0]->{'type'} and $contents->[0]->{'type'} eq 'bracketed') {
  2161. #print STDERR "Return bracketed\n";
  2162. my $bracketed = shift @{$contents};
  2163. $self->_isolate_last_space($bracketed, 'empty_space_at_end_def_bracketed');
  2164. my $bracketed_def_content = { 'contents' => $bracketed->{'contents'},
  2165. 'parent' => $bracketed->{'parent'},
  2166. 'type' => 'bracketed_def_content', };
  2167. if ($bracketed->{'extra'} and $bracketed->{'extra'}->{'spaces_before_argument'}) {
  2168. $bracketed_def_content->{'extra'}->{'spaces_before_argument'}
  2169. = $bracketed->{'extra'}->{'spaces_before_argument'};
  2170. }
  2171. return ($spaces, $bracketed_def_content);
  2172. } elsif ($contents->[0]->{'cmdname'}) {
  2173. #print STDERR "Return command $contents->[0]->{'cmdname'}\n";
  2174. return ($spaces, shift @{$contents});
  2175. } else {
  2176. #print STDERR "Process $contents->[0]->{'text'}\n";
  2177. $contents->[0]->{'text'} =~ s/^(\s*)//;
  2178. my $space_text = $1;
  2179. $spaces = {'text' => $space_text, 'type' => 'spaces'} if ($space_text);
  2180. $contents->[0]->{'text'} =~ s/^(\S+)//;
  2181. shift @{$contents} if ($contents->[0]->{'text'} eq '');
  2182. return ($spaces, {'text' => $1});
  2183. }
  2184. }
  2185. # definition line parsing
  2186. sub _parse_def($$$)
  2187. {
  2188. my $self = shift;
  2189. my $command = shift;
  2190. my $contents = shift;
  2191. my @contents = @$contents;
  2192. shift @contents if ($contents[0] and $contents[0]->{'type'}
  2193. and $contents[0]->{'type'} eq 'empty_spaces_after_command');
  2194. if ($def_aliases{$command}) {
  2195. my $real_command = $def_aliases{$command};
  2196. my $prepended = $def_map{$command}->{$real_command};
  2197. my @prepended_content;
  2198. my $text;
  2199. my $in_bracketed;
  2200. if ($prepended =~ /^\{/) {
  2201. $text = $prepended;
  2202. $text =~ s/\{([^\}]+)\}/$1/;
  2203. $in_bracketed = 1;
  2204. } else {
  2205. $text = $prepended;
  2206. }
  2207. my $tree = $self->gdt($text);
  2208. if ($in_bracketed or @{$tree->{'contents'}} > 1) {
  2209. my $bracketed = { 'type' => 'bracketed' };
  2210. $bracketed->{'contents'} = $tree->{'contents'};
  2211. foreach my $content (@{$tree->{'contents'}}) {
  2212. $content->{'parent'} = $bracketed;
  2213. }
  2214. @prepended_content = ($bracketed);
  2215. } else {
  2216. @prepended_content = (@{$tree->{'contents'}});
  2217. }
  2218. push @prepended_content, { 'text' => ' ' };
  2219. unshift @contents, @prepended_content;
  2220. $command = $def_aliases{$command};
  2221. }
  2222. foreach (my $i = 0; $i < scalar(@contents); $i++) {
  2223. # copy, to avoid changing the original
  2224. $contents[$i] = {'text' => $contents[$i]->{'text'}}
  2225. if (defined($contents[$i]->{'text'}));
  2226. }
  2227. my @result;
  2228. my @args = @{$def_map{$command}};
  2229. my $arg_type;
  2230. # Even when $arg_type is not set, that is for def* that is not documented
  2231. # to take args, everything is as is arg_type was set to arg.
  2232. $arg_type = pop @args if ($args[-1] eq 'arg' or $args[-1] eq 'argtype');
  2233. foreach my $arg (@args) {
  2234. #print STDERR "$command $arg"._print_current($contents[0]);
  2235. #foreach my $content (@contents) {print STDERR " "._print_current($content)};
  2236. #print STDERR " contents ->".Texinfo::Convert::Texinfo::convert ({'contents' => \@contents});
  2237. my ($spaces, $next) = $self->_next_bracketed_or_word(\@contents);
  2238. last if (!defined($next));
  2239. #print STDERR "NEXT[$arg] ".Texinfo::Convert::Texinfo::convert($next)."\n";
  2240. push @result, ['spaces', $spaces] if (defined($spaces));
  2241. push @result, [$arg, $next];
  2242. }
  2243. my @args_results;
  2244. while (@contents) {
  2245. my ($spaces, $next) = $self->_next_bracketed_or_word(\@contents);
  2246. push @args_results, ['spaces', $spaces] if (defined($spaces));
  2247. last if (!defined($next));
  2248. if (defined($next->{'text'})) {
  2249. while (1) {
  2250. if ($next->{'text'} =~ s/^([^\[\](),]+)//) {
  2251. push @args_results, ['arg', {'text' => $1}];
  2252. } elsif ($next->{'text'} =~ s/^([\[\](),])//) {
  2253. push @args_results, ['delimiter',
  2254. {'text' => $1, 'type' => 'delimiter'}];
  2255. } else {
  2256. last;
  2257. }
  2258. }
  2259. } else {
  2260. push @args_results, [ 'arg', $next ];
  2261. }
  2262. }
  2263. if ($arg_type and $arg_type eq 'argtype') {
  2264. my $next_is_type = 1;
  2265. foreach my $arg(@args_results) {
  2266. if ($arg->[0] eq 'spaces') {
  2267. } elsif ($arg->[0] eq 'delimiter') {
  2268. $next_is_type = 1;
  2269. } elsif ($arg->[1]->{'cmdname'} and $arg->[1]->{'cmdname'} ne 'code') {
  2270. $next_is_type = 1;
  2271. } elsif ($next_is_type) {
  2272. $arg->[0] = 'typearg';
  2273. $next_is_type = 0;
  2274. } else {
  2275. $next_is_type = 1;
  2276. }
  2277. }
  2278. }
  2279. return [@result, @args_results];
  2280. }
  2281. # register a label, that is something that may be the target of a reference
  2282. # and must be unique in the document. Corresponds with @node, @anchor and
  2283. # @float second arg.
  2284. sub _register_label($$$$)
  2285. {
  2286. my $self = shift;
  2287. my $current = shift;
  2288. my $label = shift;
  2289. my $line_nr = shift;
  2290. my $normalized = $label->{'normalized'};
  2291. if (_ignore_global_commands($self)) {
  2292. $current->{'extra'}->{'normalized'} = $normalized;
  2293. $current->{'extra'}->{'node_content'} = $label->{'node_content'};
  2294. return 0;
  2295. } elsif ($self->{'labels'}->{$normalized}) {
  2296. $self->line_error(sprintf($self->__("\@%s `%s' previously defined"),
  2297. $current->{'cmdname'},
  2298. Texinfo::Convert::Texinfo::convert({'contents' =>
  2299. $label->{'node_content'}})),
  2300. $line_nr);
  2301. $self->line_error(sprintf($self->__("here is the previous definition as \@%s"),
  2302. $self->{'labels'}->{$normalized}->{'cmdname'}),
  2303. $self->{'labels'}->{$normalized}->{'line_nr'}, 1);
  2304. return 0;
  2305. } else {
  2306. $current->{'extra'}->{'normalized'} = $normalized;
  2307. $current->{'extra'}->{'node_content'} = $label->{'node_content'};
  2308. $self->{'labels'}->{$normalized} = $current;
  2309. return 1;
  2310. }
  2311. }
  2312. sub _non_bracketed_contents($)
  2313. {
  2314. my $current = shift;
  2315. if ($current->{'type'} and $current->{'type'} eq 'bracketed') {
  2316. my $new = {};
  2317. $new->{'contents'} = $current->{'contents'} if ($current->{'parent'});
  2318. $new->{'parent'} = $current->{'parent'} if ($current->{'parent'});
  2319. return $new;
  2320. } else {
  2321. return $current;
  2322. }
  2323. }
  2324. # store an index entry.
  2325. # $current is the command element.
  2326. # $content holds the actual content.
  2327. # for index entries and v|ftable items, it is the index entry content,
  2328. # for def, it is the parsed arguments, based on the definition line
  2329. # arguments.
  2330. sub _enter_index_entry($$$$$$$)
  2331. {
  2332. my $self = shift;
  2333. my $command_container = shift;
  2334. my $command = shift;
  2335. my $current = shift;
  2336. my $content = shift;
  2337. my $content_normalized = shift;
  2338. my $line_nr = shift;
  2339. $content_normalized = $content if (!defined($content_normalized));
  2340. my $prefix = $self->{'command_index_prefix'}->{$command_container};
  2341. my $index_name = $self->{'prefix_to_index_name'}->{$prefix};
  2342. my $index = $self->{'index_names'}->{$index_name};
  2343. my $number;
  2344. unless (_ignore_global_commands($self)) {
  2345. $number = (defined($index->{'index_entries'})
  2346. ? (scalar(@{$index->{'index_entries'}}) + 1)
  2347. : 1);
  2348. }
  2349. my $index_entry = { 'index_name' => $index_name,
  2350. 'index_at_command' => $command,
  2351. 'index_type_command' => $command_container,
  2352. 'index_prefix' => $prefix,
  2353. 'content' => $content,
  2354. 'content_normalized' => $content_normalized,
  2355. 'command' => $current,
  2356. 'number' => $number,
  2357. };
  2358. if (@{$self->{'regions_stack'}}) {
  2359. $index_entry->{'region'} = $self->{'regions_stack'}->[-1];
  2360. } elsif ($self->{'current_node'}) {
  2361. $index_entry->{'node'} = $self->{'current_node'};
  2362. } elsif (!$self->{'current_section'}) {
  2363. $self->line_warn(sprintf($self->__("entry for index `%s' outside of any node"),
  2364. $index_name), $line_nr);
  2365. }
  2366. #print STDERR "INDEX ENTRY \@$command->{'cmdname'} $index_name($number)\n";
  2367. unless (_ignore_global_commands($self)) {
  2368. push @{$index->{'index_entries'}}, $index_entry;
  2369. }
  2370. $current->{'extra'}->{'index_entry'} = $index_entry;
  2371. }
  2372. # This is always called at command closing.
  2373. sub _remove_empty_content_arguments($)
  2374. {
  2375. my $current = shift;
  2376. my $type;
  2377. if ($current->{'extra'}) {
  2378. if ($current->{'extra'}->{'block_command_line_contents'}) {
  2379. $type = 'block_command_line_contents';
  2380. } elsif ($current->{'extra'}->{'brace_command_contents'}) {
  2381. $type = 'brace_command_contents';
  2382. }
  2383. }
  2384. if ($type) {
  2385. while (@{$current->{'extra'}->{$type}}
  2386. and not defined($current->{'extra'}->{$type}->[-1])) {
  2387. pop @{$current->{'extra'}->{$type}};
  2388. }
  2389. delete $current->{'extra'}->{$type} if (!@{$current->{'extra'}->{$type}});
  2390. delete $current->{'extra'} if (!keys(%{$current->{'extra'}}));
  2391. }
  2392. }
  2393. sub _strip_macrobody_leading_space($$)
  2394. {
  2395. my $self = shift;
  2396. my $text = shift;
  2397. if ($self->{'MACRO_BODY_IGNORES_LEADING_SPACE'}) {
  2398. $text =~ s/^\s*//mg;
  2399. }
  2400. return $text;
  2401. }
  2402. # close constructs and do stuff at end of line (or end of the document)
  2403. sub _end_line($$$);
  2404. sub _end_line($$$)
  2405. {
  2406. my $self = shift;
  2407. my $current = shift;
  2408. my $line_nr = shift;
  2409. my $current_old = $current;
  2410. my $included_file = 0;
  2411. # a line consisting only of spaces.
  2412. if ($current->{'contents'} and @{$current->{'contents'}}
  2413. and $current->{'contents'}->[-1]->{'type'}
  2414. and $current->{'contents'}->[-1]->{'type'} eq 'empty_line') {
  2415. print STDERR "END EMPTY LINE\n" if ($self->{'DEBUG'});
  2416. if ($current->{'type'} and $current->{'type'} eq 'paragraph') {
  2417. my $empty_line = pop @{$current->{'contents'}};
  2418. $current = _end_paragraph($self, $current, $line_nr);
  2419. push @{$current->{'contents'}}, $empty_line;
  2420. $empty_line->{'parent'} = $current;
  2421. } elsif ($current->{'type'}
  2422. and $current->{'type'} eq 'preformatted'
  2423. and $current->{'parent'}->{'type'}
  2424. and $current->{'parent'}->{'type'} eq 'menu_entry_description') {
  2425. my $empty_line = pop @{$current->{'contents'}};
  2426. if ($current->{'type'} eq 'preformatted') {
  2427. my $empty_preformatted = (!@{$current->{'contents'}});
  2428. $current = $current->{'parent'};
  2429. pop @{$current->{'contents'}} if ($empty_preformatted);
  2430. }
  2431. my $context = pop @{$self->{'context_stack'}};
  2432. if ($context ne 'preformatted') {
  2433. $self->_bug_message("context $context instead of preformatted in empty line after menu_entry_description",
  2434. $line_nr, $current);
  2435. }
  2436. # first parent is menu_entry
  2437. $current = $current->{'parent'}->{'parent'};
  2438. push @{$current->{'contents'}}, { 'type' => 'menu_comment',
  2439. 'parent' => $current,
  2440. 'contents' => [] };
  2441. $current = $current->{'contents'}->[-1];
  2442. push @{$current->{'contents'}}, { 'type' => 'preformatted',
  2443. 'parent' => $current,
  2444. 'contents' => [] };
  2445. $current = $current->{'contents'}->[-1];
  2446. push @{$current->{'contents'}}, { 'type' => 'after_description_line',
  2447. 'text' => $empty_line->{'text'},
  2448. 'parent' => $current };
  2449. push @{$self->{'context_stack'}}, 'preformatted';
  2450. print STDERR "MENU: END DESCRIPTION, OPEN COMMENT\n" if ($self->{'DEBUG'});
  2451. } elsif (!$no_paragraph_contexts{$self->{'context_stack'}->[-1]}) {
  2452. $current = _end_paragraph($self, $current, $line_nr);
  2453. }
  2454. # end of a menu line.
  2455. } elsif ($current->{'type'}
  2456. and ($current->{'type'} eq 'menu_entry_name'
  2457. or $current->{'type'} eq 'menu_entry_node')) {
  2458. my $empty_menu_entry_node = 0;
  2459. my $end_comment;
  2460. if ($current->{'type'} eq 'menu_entry_node') {
  2461. if (@{$current->{'contents'}}
  2462. and $current->{'contents'}->[-1]->{'cmdname'}
  2463. and ($current->{'contents'}->[-1]->{'cmdname'} eq 'c'
  2464. or $current->{'contents'}->[-1]->{'cmdname'} eq 'comment')) {
  2465. $end_comment = pop @{$current->{'contents'}};
  2466. }
  2467. if (!@{$current->{'contents'}}
  2468. # empty if only the end of line or spaces
  2469. or (@{$current->{'contents'}} == 1
  2470. and defined($current->{'contents'}->[-1]->{'text'})
  2471. and $current->{'contents'}->[-1]->{'text'} !~ /\S/)) {
  2472. $empty_menu_entry_node = 1;
  2473. push @{$current->{'contents'}}, $end_comment if ($end_comment);
  2474. }
  2475. }
  2476. # we abort the menu entry if there is no node name
  2477. if ($empty_menu_entry_node
  2478. or $current->{'type'} eq 'menu_entry_name') {
  2479. my $description_or_menu_comment;
  2480. print STDERR "FINALLY NOT MENU ENTRY\n" if ($self->{'DEBUG'});
  2481. my $menu = $current->{'parent'}->{'parent'};
  2482. my $menu_entry = pop @{$menu->{'contents'}};
  2483. if (@{$menu->{'contents'}} and $menu->{'contents'}->[-1]->{'type'}
  2484. and $menu->{'contents'}->[-1]->{'type'} eq 'menu_entry') {
  2485. my $entry = $menu->{'contents'}->[-1];
  2486. my $description;
  2487. foreach my $entry_element (reverse(@{$entry->{'args'}})) {
  2488. if ($entry_element->{'type'} eq 'menu_entry_description') {
  2489. $description = $entry_element;
  2490. last;
  2491. }
  2492. }
  2493. if ($description) {
  2494. $description_or_menu_comment = $description;
  2495. } else {
  2496. # Normally this cannot happen
  2497. $self->_bug_message("No description in menu_entry",
  2498. $line_nr, $current);
  2499. push @{$entry->{'args'}}, {'type' => 'menu_entry_description',
  2500. 'parent' => $entry,
  2501. 'contents' => [] };
  2502. $description_or_menu_comment = $entry->{'args'}->[-1];
  2503. }
  2504. } elsif (@{$menu->{'contents'}} and $menu->{'contents'}->[-1]->{'type'}
  2505. and $menu->{'contents'}->[-1]->{'type'} eq 'menu_comment') {
  2506. $description_or_menu_comment = $menu->{'contents'}->[-1];
  2507. }
  2508. if ($description_or_menu_comment) {
  2509. $current = $description_or_menu_comment;
  2510. if ($current->{'contents'}->[-1] and $current->{'contents'}->[-1]->{'type'}
  2511. and $current->{'contents'}->[-1]->{'type'} eq 'preformatted') {
  2512. $current = $current->{'contents'}->[-1];
  2513. } else {
  2514. # this should not happen
  2515. $self->_bug_message("description or menu comment not in preformatted",
  2516. $line_nr, $current);
  2517. push @{$current->{'contents'}}, {'type' => 'preformatted',
  2518. 'parent' => $current,
  2519. 'contents' => [] };
  2520. $current = $current->{'contents'}->[-1];
  2521. }
  2522. push @{$self->{'context_stack'}}, 'preformatted';
  2523. } else {
  2524. push @{$menu->{'contents'}}, {'type' => 'menu_comment',
  2525. 'parent' => $menu,
  2526. 'contents' => [] };
  2527. $current = $menu->{'contents'}->[-1];
  2528. push @{$current->{'contents'}}, {'type' => 'preformatted',
  2529. 'parent' => $current,
  2530. 'contents' => [] };
  2531. $current = $current->{'contents'}->[-1];
  2532. push @{$self->{'context_stack'}}, 'preformatted';
  2533. print STDERR "THEN MENU_COMMENT OPEN\n" if ($self->{'DEBUG'});
  2534. }
  2535. while (@{$menu_entry->{'args'}}) {
  2536. my $arg = shift @{$menu_entry->{'args'}};
  2537. if (defined($arg->{'text'})) {
  2538. $current = _merge_text($self, $current, $arg->{'text'});
  2539. } else {
  2540. while (@{$arg->{'contents'}}) {
  2541. my $content = shift @{$arg->{'contents'}};
  2542. if (defined($content->{'text'})) {
  2543. $current = _merge_text($self, $current,
  2544. $content->{'text'});
  2545. $content = undef;
  2546. } else {
  2547. $content->{'parent'} = $current;
  2548. push @{$current->{'contents'}}, $content;
  2549. }
  2550. }
  2551. }
  2552. $arg = undef;
  2553. }
  2554. # MENU_COMMENT open
  2555. $menu_entry = undef;
  2556. } else {
  2557. print STDERR "MENU ENTRY END LINE\n" if ($self->{'DEBUG'});
  2558. $current = $current->{'parent'};
  2559. $current = _enter_menu_entry_node($self, $current, $line_nr);
  2560. if (defined($end_comment)) {
  2561. $end_comment->{'parent'} = $current;
  2562. push @{$current->{'contents'}}, $end_comment;
  2563. }
  2564. }
  2565. # def line
  2566. } elsif ($current->{'parent'}
  2567. and $current->{'parent'}->{'type'}
  2568. and $current->{'parent'}->{'type'} eq 'def_line') {
  2569. my $def_context = pop @{$self->{'context_stack'}};
  2570. if ($def_context ne 'def') {
  2571. $self->_bug_message("context $def_context instead of def",
  2572. $line_nr, $current);
  2573. die;
  2574. }
  2575. my $def_command = $current->{'parent'}->{'extra'}->{'def_command'};
  2576. my $arguments = $self->_parse_def($def_command,
  2577. $current->{'contents'});
  2578. if (scalar(@$arguments)) {
  2579. $current->{'parent'}->{'extra'}->{'def_args'} = $arguments;
  2580. my $def_parsed_hash;
  2581. foreach my $arg (@$arguments) {
  2582. die if (!defined($arg->[0]));
  2583. last if ($arg->[0] eq 'arg' or $arg->[0] eq 'typearg'
  2584. or $arg->[0] eq 'delimiter');
  2585. next if ($arg->[0] eq 'spaces');
  2586. # change of type is done in _parse_def.
  2587. #if ($arg->[1]->{'type'} and $arg->[1]->{'type'} eq 'bracketed') {
  2588. # $def_parsed_hash->{$arg->[0]} = { 'contents' => $arg->[1]->{'contents'},
  2589. # 'type' => 'bracketed_def_content',
  2590. # 'parent' => $arg->[1]->{'parent'}};
  2591. #} else {
  2592. # $def_parsed_hash->{$arg->[0]} = $arg->[1];
  2593. #}
  2594. $def_parsed_hash->{$arg->[0]} = $arg->[1];
  2595. }
  2596. $current->{'parent'}->{'extra'}->{'def_parsed_hash'} = $def_parsed_hash;
  2597. # do an standard index entry tree
  2598. my $index_entry;
  2599. if (defined($def_parsed_hash->{'name'})) {
  2600. $index_entry = $def_parsed_hash->{'name'}
  2601. # empty bracketed
  2602. unless ($def_parsed_hash->{'name'}->{'type'}
  2603. and $def_parsed_hash->{'name'}->{'type'} eq 'bracketed_def_content'
  2604. and (!$def_parsed_hash->{'name'}->{'contents'}
  2605. or (!scalar(@{$def_parsed_hash->{'name'}->{'contents'}}))
  2606. or (scalar(@{$def_parsed_hash->{'name'}->{'contents'}}) == 1
  2607. and defined($def_parsed_hash->{'name'}->{'contents'}->[0]->{'text'})
  2608. and $def_parsed_hash->{'name'}->{'contents'}->[0]->{'text'} !~ /\S/)));
  2609. }
  2610. if (defined($index_entry)) {
  2611. my $index_contents_normalized;
  2612. if ($def_parsed_hash->{'class'}) {
  2613. if ($command_index_prefix{$def_command} eq 'f') {
  2614. $index_entry = $self->gdt('{name} on {class}',
  2615. {'name' => $def_parsed_hash->{'name'},
  2616. 'class' => $def_parsed_hash->{'class'}});
  2617. $index_contents_normalized
  2618. = [_non_bracketed_contents($def_parsed_hash->{'name'}),
  2619. { 'text' => ' on '},
  2620. _non_bracketed_contents($def_parsed_hash->{'class'})];
  2621. } elsif ($command_index_prefix{$def_command} eq 'v'
  2622. and $def_command ne 'defcv') {
  2623. $index_entry = $self->gdt('{name} of {class}',
  2624. {'name' => $def_parsed_hash->{'name'},
  2625. 'class' => $def_parsed_hash->{'class'}});
  2626. $index_contents_normalized
  2627. = [_non_bracketed_contents($def_parsed_hash->{'name'}),
  2628. { 'text' => ' of '},
  2629. _non_bracketed_contents($def_parsed_hash->{'class'})];
  2630. }
  2631. }
  2632. $index_contents_normalized = [$index_entry]
  2633. if (!defined($index_contents_normalized));
  2634. my $index_contents;
  2635. # 'root_line' is the container returned by gdt.
  2636. if ($index_entry->{'type'} and $index_entry->{'type'} eq 'root_line') {
  2637. $index_contents = $index_entry->{'contents'};
  2638. } else {
  2639. $index_contents = [$index_entry];
  2640. }
  2641. _enter_index_entry($self,
  2642. $current->{'parent'}->{'extra'}->{'def_command'},
  2643. $current->{'parent'}->{'extra'}->{'original_def_cmdname'},
  2644. $current->{'parent'}, $index_contents,
  2645. $index_contents_normalized, $line_nr);
  2646. } else {
  2647. $self->_command_warn($current->{'parent'}, $line_nr,
  2648. $self->__('missing name for @%s'),
  2649. $current->{'parent'}->{'extra'}->{'original_def_cmdname'});
  2650. }
  2651. } else {
  2652. $self->_command_warn($current->{'parent'}, $line_nr,
  2653. $self->__('missing category for @%s'),
  2654. $current->{'parent'}->{'extra'}->{'original_def_cmdname'});
  2655. }
  2656. $current = $current->{'parent'}->{'parent'};
  2657. $current = $self->_begin_preformatted($current);
  2658. # other block command lines
  2659. } elsif ($current->{'type'}
  2660. and $current->{'type'} eq 'block_line_arg') {
  2661. my $empty_text;
  2662. my $context = pop @{$self->{'context_stack'}};
  2663. if ($context ne 'line') {
  2664. $self->_bug_message("context $context instead of line in block_line_arg",
  2665. $line_nr, $current);
  2666. }
  2667. # @multitable args
  2668. if ($current->{'parent'}->{'cmdname'}
  2669. and $current->{'parent'}->{'cmdname'} eq 'multitable') {
  2670. # parse the prototypes and put them in a special arg
  2671. my @prototype_row;
  2672. # do the same but keeping spaces information
  2673. my @prototype_line;
  2674. foreach my $content (@{$current->{'contents'}}) {
  2675. if ($content->{'type'} and $content->{'type'} eq 'bracketed') {
  2676. push @prototype_row, { 'contents' => $content->{'contents'},
  2677. 'parent' => $content->{'parent'},
  2678. 'type' => 'bracketed_multitable_prototype'};
  2679. push @prototype_line, $content;
  2680. } elsif ($content->{'text'}) {
  2681. if ($content->{'text'} =~ /\S/) {
  2682. foreach my $prototype (split /\s+/, $content->{'text'}) {
  2683. push @prototype_row, { 'text' => $prototype,
  2684. 'type' => 'row_prototype' } unless ($prototype eq '');
  2685. }
  2686. }
  2687. # The regexp breaks between characters, with a non space followed
  2688. # by a space or a space followed by non space. It is like \b, but
  2689. # for \s \S, and not \w \W.
  2690. foreach my $prototype_or_space (split /(?<=\S)(?=\s)|(?=\S)(?<=\s)/,
  2691. $content->{'text'}) {
  2692. if ($prototype_or_space =~ /\S/) {
  2693. push @prototype_line, {'text' => $prototype_or_space,
  2694. 'type' => 'row_prototype' };
  2695. } elsif ($prototype_or_space =~ /\s/) {
  2696. push @prototype_line, {'text' => $prototype_or_space,
  2697. 'type' => 'prototype_space' };
  2698. }
  2699. }
  2700. } else {
  2701. # FIXME could this happen? Should be a debug message?
  2702. if (!$content->{'cmdname'}) {
  2703. $self->_command_warn($current, $line_nr,
  2704. $self->__("unexpected argument on \@%s line: %s"),
  2705. $current->{'cmdname'},
  2706. Texinfo::Convert::Texinfo::convert({ $content->{'contents'} }));
  2707. } elsif ($content->{'cmdname'} eq 'c'
  2708. or $content->{'cmdname'} eq 'comment') {
  2709. } else {
  2710. push @prototype_row, $content;
  2711. push @prototype_line, $content;
  2712. }
  2713. }
  2714. }
  2715. my $multitable = $current->{'parent'};
  2716. $multitable->{'extra'}->{'max_columns'} = scalar(@prototype_row);
  2717. if (!scalar(@prototype_row)) {
  2718. $self->_command_warn($multitable, $line_nr,
  2719. $self->__("empty multitable"));
  2720. }
  2721. $multitable->{'extra'}->{'prototypes'} = \@prototype_row;
  2722. $multitable->{'extra'}->{'prototypes_line'} = \@prototype_line;
  2723. } else {
  2724. $self->_isolate_last_space($current, 'space_at_end_block_command');
  2725. $self->_register_command_arg($current, 'block_command_line_contents');
  2726. }
  2727. # @float args
  2728. if ($current->{'parent'}->{'cmdname'}
  2729. and $current->{'parent'}->{'cmdname'} eq 'float') {
  2730. my $float = $current->{'parent'};
  2731. $float->{'line_nr'} = $line_nr;
  2732. my $type = '';
  2733. if (@{$float->{'args'}}) {
  2734. if ($float->{'args'}->[1]) {
  2735. my $float_label = _parse_node_manual($float->{'args'}->[1]);
  2736. _check_internal_node($self, $float_label, $line_nr);
  2737. if (defined($float_label) and $float_label->{'node_content'}
  2738. and $float_label->{'normalized'} =~ /[^-]/) {
  2739. _register_label($self, $float, $float_label, $line_nr);
  2740. }
  2741. }
  2742. _parse_float_type($float);
  2743. $type = $float->{'extra'}->{'type'}->{'normalized'};
  2744. }
  2745. push @{$self->{'floats'}->{$type}}, $float
  2746. unless (_ignore_global_commands($self));
  2747. $float->{'float_section'} = $self->{'current_section'}
  2748. if (defined($self->{'current_section'}));
  2749. }
  2750. $current = $current->{'parent'};
  2751. delete $current->{'remaining_args'};
  2752. # don't consider empty argument of block @-commands as argument,
  2753. # reparent them as contents
  2754. if ($current->{'args'}->[0]->{'contents'}->[0]
  2755. and $current->{'args'}->[0]->{'contents'}->[0]->{'type'}
  2756. and $current->{'args'}->[0]->{'contents'}->[0]->{'type'} eq 'empty_line_after_command')
  2757. {
  2758. my $empty_text = $current->{'args'}->[0]->{'contents'}->[0];
  2759. $empty_text->{'parent'} = $current;
  2760. unshift @{$current->{'contents'}}, $empty_text;
  2761. delete $current->{'args'};
  2762. }
  2763. # Additionally, remove empty arguments as far as possible
  2764. _remove_empty_content_arguments($current);
  2765. if ($current->{'cmdname'}
  2766. and $block_item_commands{$current->{'cmdname'}}) {
  2767. if ($current->{'cmdname'} eq 'enumerate') {
  2768. my $spec = 1;
  2769. if ($current->{'extra'}->{'block_command_line_contents'}
  2770. and defined($current->{'extra'}->{'block_command_line_contents'}->[0])) {
  2771. if (scalar(@{$current->{'extra'}->{'block_command_line_contents'}->[0]}) > 1) {
  2772. $self->_command_error($current, $line_nr,
  2773. $self->__("superfluous argument to \@%s"),
  2774. $current->{'cmdname'});
  2775. }
  2776. my $arg = $current->{'extra'}->{'block_command_line_contents'}->[0]->[0];
  2777. if (!defined($arg->{'text'}) or $arg->{'text'} !~ /^(([[:digit:]]+)|([[:alpha:]]+))$/) {
  2778. $self->_command_error($current, $line_nr,
  2779. $self->__("bad argument to \@%s"),
  2780. $current->{'cmdname'});
  2781. } else {
  2782. $spec = $arg->{'text'};
  2783. }
  2784. }
  2785. $current->{'extra'}->{'enumerate_specification'} = $spec;
  2786. } elsif ($item_line_commands{$current->{'cmdname'}}) {
  2787. if (!$current->{'extra'}
  2788. or !$current->{'extra'}->{'command_as_argument'}) {
  2789. $self->_command_error($current, $line_nr,
  2790. $self->__("%s requires an argument: the formatter for %citem"),
  2791. $current->{'cmdname'}, ord('@'));
  2792. } elsif (!$brace_commands{$current->{'extra'}->{'command_as_argument'}->{'cmdname'}}
  2793. and !$self->{'definfoenclose'}->{$current->{'extra'}->{'command_as_argument'}->{'cmdname'}}) {
  2794. $self->_command_error($current, $line_nr,
  2795. $self->__("command \@%s not accepting argument in brace should not be on \@%s line"),
  2796. $current->{'extra'}->{'command_as_argument'}->{'cmdname'},
  2797. $current->{'cmdname'});
  2798. delete $current->{'extra'}->{'command_as_argument'};
  2799. }
  2800. }
  2801. # This code checks that the command_as_argument of the @itemize
  2802. # is alone on the line, otherwise it is not a command_as_argument.
  2803. if ($current->{'extra'}
  2804. and $current->{'extra'}->{'command_as_argument'}
  2805. and $current->{'cmdname'} eq 'itemize') {
  2806. my @args = @{$current->{'args'}->[0]->{'contents'}};
  2807. while (@args) {
  2808. my $arg = shift @args;
  2809. last if ($arg eq $current->{'extra'}->{'command_as_argument'});
  2810. }
  2811. while (@args) {
  2812. my $arg = shift @args;
  2813. if (!(($arg->{'cmdname'}
  2814. and ($arg->{'cmdname'} eq 'c'
  2815. or $arg->{'cmdname'} eq 'comment'))
  2816. or (defined($arg->{'text'}) and $arg->{'text'} !~ /\S/))) {
  2817. #print STDERR " -> stop at "._print_current($arg)."\n";
  2818. delete $current->{'extra'}->{'command_as_argument'}->{'type'};
  2819. delete $current->{'extra'}->{'command_as_argument'};
  2820. last;
  2821. }
  2822. }
  2823. }
  2824. if ($current->{'extra'}
  2825. and $current->{'extra'}->{'command_as_argument'}
  2826. and $accent_commands{$current->{'extra'}->{'command_as_argument'}->{'cmdname'}}
  2827. and ($current->{'cmdname'} eq 'itemize'
  2828. or $item_line_commands{$current->{'cmdname'}})) {
  2829. $self->_command_warn($current, $line_nr,
  2830. $self->__("accent command `\@%s' not allowed as \@%s argument"),
  2831. $current->{'extra'}->{'command_as_argument'}->{'cmdname'},
  2832. $current->{'cmdname'});
  2833. delete $current->{'extra'}->{'command_as_argument'};
  2834. delete $current->{'extra'}->{'block_command_line_contents'};
  2835. }
  2836. if (!$current->{'extra'}->{'block_command_line_contents'}
  2837. and $current->{'cmdname'} eq 'itemize') {
  2838. $current->{'extra'}->{'block_command_line_contents'} = [
  2839. [ { 'cmdname' => 'bullet',
  2840. 'type' => 'command_as_argument',
  2841. 'parent' => $current }
  2842. ]
  2843. ];
  2844. $current->{'extra'}->{'command_as_argument'} =
  2845. $current->{'extra'}->{'block_command_line_contents'}->[0]->[0];
  2846. } elsif ($item_line_commands{$current->{'cmdname'}} and
  2847. ! $current->{'extra'}->{'command_as_argument'}) {
  2848. $current->{'extra'}->{'block_command_line_contents'} = [
  2849. [ { 'cmdname' => 'asis',
  2850. 'type' => 'command_as_argument',
  2851. 'parent' => $current }
  2852. ]
  2853. ];
  2854. $current->{'extra'}->{'command_as_argument'} =
  2855. $current->{'extra'}->{'block_command_line_contents'}->[0]->[0];
  2856. }
  2857. push @{$current->{'contents'}}, { 'type' => 'before_item',
  2858. 'contents' => [], 'parent', $current };
  2859. $current = $current->{'contents'}->[-1];
  2860. }
  2861. if ($current->{'cmdname'} and $menu_commands{$current->{'cmdname'}}) {
  2862. push @{$current->{'contents'}}, {'type' => 'menu_comment',
  2863. 'parent' => $current,
  2864. 'contents' => [] };
  2865. $current = $current->{'contents'}->[-1];
  2866. print STDERR "MENU_COMMENT OPEN\n" if ($self->{'DEBUG'});
  2867. push @{$self->{'context_stack'}}, 'preformatted';
  2868. }
  2869. $current = $self->_begin_preformatted($current);
  2870. # if we are after a @end verbatim, we must restart a preformatted if needed,
  2871. # since there is no @end command explicitly associated to raw commands
  2872. # it won't be done elsewhere.
  2873. } elsif ($current->{'contents'}
  2874. and $current->{'contents'}->[-1]
  2875. and $current->{'contents'}->[-1]->{'type'}
  2876. and $current->{'contents'}->[-1]->{'type'} eq 'empty_line_after_command'
  2877. and $current->{'contents'}->[-1]->{'extra'}
  2878. and $current->{'contents'}->[-1]->{'extra'}->{'command'}
  2879. and $current->{'contents'}->[-1]->{'extra'}->{'command'}->{'cmdname'} eq 'verbatim') {
  2880. $current = $self->_begin_preformatted($current);
  2881. # misc command line arguments
  2882. # Never go here if skipline/noarg/...
  2883. } elsif ($current->{'type'}
  2884. and $current->{'type'} eq 'misc_line_arg') {
  2885. my $context = pop @{$self->{'context_stack'}};
  2886. if ($context ne 'line') {
  2887. $self->_bug_message("context $context instead of line in misc_line_arg",
  2888. $line_nr, $current);
  2889. }
  2890. $self->_isolate_last_space($current);
  2891. # first parent is the @command, second is the parent
  2892. $current = $current->{'parent'};
  2893. my $misc_cmd = $current;
  2894. my $command = $current->{'cmdname'};
  2895. my $end_command;
  2896. print STDERR "MISC END \@$command\n" if ($self->{'DEBUG'});
  2897. if ($self->{'misc_commands'}->{$command} =~ /^\d$/) {
  2898. my $args = _parse_line_command_args($self, $current, $line_nr);
  2899. $current->{'extra'}->{'misc_args'} = $args if (defined($args));
  2900. } elsif ($self->{'misc_commands'}->{$command} eq 'text') {
  2901. my $text = Texinfo::Convert::Text::convert($current->{'args'}->[0],
  2902. {'code' => 1,
  2903. Texinfo::Common::_convert_text_options($self)});
  2904. if ($text eq '') {
  2905. $self->_command_warn($current, $line_nr,
  2906. $self->__("\@%s missing argument"), $command);
  2907. $current->{'extra'}->{'missing_argument'} = 1;
  2908. } else {
  2909. $current->{'extra'}->{'text_arg'} = $text;
  2910. if ($command eq 'end') {
  2911. # REMACRO
  2912. my $line = $text;
  2913. if ($line =~ s/^([[:alnum:]][[:alnum:]-]+)//) {
  2914. $end_command = $1;
  2915. if (!exists $block_commands{$end_command}) {
  2916. $self->_command_warn($current, $line_nr,
  2917. $self->__("unknown \@end %s"), $end_command);
  2918. $end_command = undef;
  2919. } else {
  2920. print STDERR "END BLOCK $end_command\n" if ($self->{'DEBUG'});
  2921. if ($block_commands{$end_command} eq 'conditional') {
  2922. if (@{$self->{'conditionals_stack'}}
  2923. and $self->{'conditionals_stack'}->[-1] eq $end_command) {
  2924. pop @{$self->{'conditionals_stack'}};
  2925. } else {
  2926. $self->_command_error($current, $line_nr,
  2927. $self->__("unmatched `%c%s'"), ord('@'), 'end');
  2928. $end_command = undef;
  2929. }
  2930. }
  2931. $current->{'extra'}->{'command_argument'} = $end_command
  2932. if (defined($end_command));
  2933. }
  2934. if ($line =~ /\S/ and defined($end_command)) {
  2935. my $texi_line
  2936. = Texinfo::Convert::Texinfo::convert($current->{'args'}->[0]);
  2937. $texi_line =~ s/^\s*([[:alnum:]][[:alnum:]-]+)//;
  2938. $self->_command_error($current, $line_nr,
  2939. $self->__("superfluous argument to \@%s %s: %s"),
  2940. $command, $end_command, $texi_line);
  2941. }
  2942. } else {
  2943. $self->_command_error($current, $line_nr,
  2944. $self->__("bad argument to \@%s: %s"),
  2945. $command, $line);
  2946. }
  2947. } elsif ($command eq 'include') {
  2948. my $file = Texinfo::Common::locate_include_file($self, $text) ;
  2949. if (defined($file)) {
  2950. my $filehandle = do { local *FH };
  2951. if (open ($filehandle, $file)) {
  2952. $included_file = 1;
  2953. binmode($filehandle, ":encoding($self->{'INPUT_PERL_ENCODING'})")
  2954. if (defined($self->{'INPUT_PERL_ENCODING'}));
  2955. print STDERR "Included $file($filehandle)\n" if ($self->{'DEBUG'});
  2956. unshift @{$self->{'input'}}, {
  2957. 'name' => $file,
  2958. 'line_nr' => 0,
  2959. 'pending' => [],
  2960. 'fh' => $filehandle };
  2961. } else {
  2962. $self->_command_error($current, $line_nr,
  2963. $self->__("\@%s: could not open %s: %s"),
  2964. $command, $text, $!);
  2965. }
  2966. } else {
  2967. $self->_command_error($current, $line_nr,
  2968. $self->__("\@%s: could not find %s"),
  2969. $command, $text);
  2970. }
  2971. } elsif ($command eq 'documentencoding') {
  2972. my ($texinfo_encoding, $perl_encoding, $input_encoding)
  2973. = Texinfo::Encoding::encoding_alias($text);
  2974. $self->_command_warn($current, $line_nr,
  2975. $self->__("encoding `%s' is not a canonical texinfo encoding"),
  2976. $text)
  2977. if (!$texinfo_encoding or $texinfo_encoding ne lc($text));
  2978. if (! _ignore_global_commands($self)) {
  2979. if ($input_encoding) {
  2980. $current->{'extra'}->{'input_encoding_name'} = $input_encoding;
  2981. }
  2982. if (!$perl_encoding) {
  2983. $self->_command_warn($current, $line_nr,
  2984. $self->__("unrecognized encoding name `%s'"), $text);
  2985. } else {
  2986. $current->{'extra'}->{'input_perl_encoding'} = $perl_encoding;
  2987. if ($input_encoding) {
  2988. if (!$self->{'set'}->{'INPUT_ENCODING_NAME'}) {
  2989. $self->{'INPUT_ENCODING_NAME'} = $input_encoding;
  2990. $self->{'info'}->{'input_encoding_name'} = $input_encoding;
  2991. }
  2992. }
  2993. if (!$self->{'set'}->{'INPUT_PERL_ENCODING'}) {
  2994. $self->{'INPUT_PERL_ENCODING'} = $perl_encoding;
  2995. $self->{'info'}->{'input_perl_encoding'} = $perl_encoding;
  2996. foreach my $input (@{$self->{'input'}}) {
  2997. binmode($input->{'fh'}, ":encoding($perl_encoding)") if ($input->{'fh'});
  2998. }
  2999. }
  3000. }
  3001. }
  3002. } elsif ($command eq 'documentlanguage') {
  3003. my @messages = Texinfo::Common::warn_unknown_language($text,
  3004. $self->{'gettext'});
  3005. foreach my $message(@messages) {
  3006. $self->_command_warn($current, $line_nr, $message);
  3007. }
  3008. if (!$self->{'set'}->{'documentlanguage'}
  3009. and !_ignore_global_commands($self)) {
  3010. $self->{'documentlanguage'} = $text;
  3011. }
  3012. }
  3013. }
  3014. } elsif ($command eq 'node') {
  3015. foreach my $arg (@{$current->{'args'}}) {
  3016. my $node = _parse_node_manual($arg);
  3017. push @{$current->{'extra'}->{'nodes_manuals'}}, $node;
  3018. }
  3019. if (_check_node_label($self, $current->{'extra'}->{'nodes_manuals'}->[0],
  3020. $command, $line_nr)) {
  3021. if (_register_label($self, $current,
  3022. $current->{'extra'}->{'nodes_manuals'}->[0], $line_nr)) {
  3023. $self->{'current_node'} = $current;
  3024. push @{$self->{'nodes'}}, $current;
  3025. }
  3026. }
  3027. } elsif ($command eq 'listoffloats') {
  3028. # Empty listoffloats is allowed
  3029. _parse_float_type($current);
  3030. #if (!_parse_float_type($current)) {
  3031. # $self->line_error (sprintf($self->__("\@%s missing argument"),
  3032. # $command), $line_nr);
  3033. #}
  3034. # handle all the other 'line' commands. Here just check that they
  3035. # have an argument and prepare contents without spaces.
  3036. } else {
  3037. my @contents = @{$current->{'args'}->[0]->{'contents'}};
  3038. _trim_spaces_comment_from_content(\@contents);
  3039. # empty @top is allowed
  3040. if (!scalar(@contents) and $command ne 'top') {
  3041. $self->_command_warn($current, $line_nr,
  3042. $self->__("\@%s missing argument"), $command);
  3043. $current->{'extra'}->{'missing_argument'} = 1;
  3044. } else {
  3045. $current->{'extra'}->{'misc_content'} = \@contents;
  3046. if (($command eq 'item' or $command eq 'itemx')
  3047. and $self->{'command_index_prefix'}->{$current->{'parent'}->{'cmdname'}}) {
  3048. _enter_index_entry($self, $current->{'parent'}->{'cmdname'},
  3049. $command, $current,
  3050. $current->{'extra'}->{'misc_content'},
  3051. undef, $line_nr);
  3052. } elsif ($self->{'command_index_prefix'}->{$current->{'cmdname'}}) {
  3053. _enter_index_entry($self, $current->{'cmdname'},
  3054. $current->{'cmdname'}, $current,
  3055. $current->{'extra'}->{'misc_content'},
  3056. undef, $line_nr);
  3057. $current->{'type'} = 'index_entry_command';
  3058. }
  3059. }
  3060. if (defined($command_structuring_level{$command})) {
  3061. $current->{'level'} = $command_structuring_level{$command};
  3062. }
  3063. }
  3064. $current = $current->{'parent'};
  3065. if ($end_command) {
  3066. print STDERR "END COMMAND $end_command\n" if ($self->{'DEBUG'});
  3067. my $end = pop @{$current->{'contents'}};
  3068. if ($block_commands{$end_command} ne 'conditional') {
  3069. my $closed_command;
  3070. ($closed_command, $current)
  3071. = _close_commands($self, $current, $line_nr, $end_command);
  3072. my $inline_copying;
  3073. if ($closed_command) {
  3074. $misc_cmd->{'extra'}->{'command'} = $closed_command;
  3075. $closed_command->{'extra'}->{'end_command'} = $misc_cmd;
  3076. $self->_close_command_cleanup($closed_command);
  3077. $end->{'parent'} = $closed_command;
  3078. # register @insertcopying as a macro if INLINE_INSERTCOPYING is set.
  3079. if ($end_command eq 'copying' and $self->{'INLINE_INSERTCOPYING'}) {
  3080. # remove the end of line following @copying.
  3081. my @contents = @{$closed_command->{'contents'}};
  3082. shift @contents if ($contents[0] and $contents[0]->{'type'}
  3083. and ($contents[0]->{'type'} eq 'empty_line_after_command'
  3084. or $contents[0]->{'type'} eq 'empty_spaces_after_command'));
  3085. # the macrobody is the @copying content converted to Texinfo.
  3086. my $body = Texinfo::Convert::Texinfo::convert(
  3087. {'contents' => \@contents});
  3088. #chomp ($body);
  3089. $self->{'macros'}->{'insertcopying'} = {
  3090. 'args' => [{'text' => 'insertcopying', 'type' => 'macro_name'}],
  3091. 'cmdname' => 'macro',
  3092. 'extra' => {'macrobody' =>
  3093. $self->_strip_macrobody_leading_space($body)}
  3094. };
  3095. $inline_copying = 1;
  3096. print STDERR "INLINE_INSERTCOPYING as macro\n" if ($self->{'DEBUG'});
  3097. }
  3098. push @{$closed_command->{'contents'}}, $end;
  3099. # closing a menu command, but still in a menu. Open a menu_comment
  3100. if ($menu_commands{$closed_command->{'cmdname'}}
  3101. and $self->{'context_stack'}->[-1] eq 'menu') {
  3102. print STDERR "CLOSE MENU but still in menu context\n"
  3103. if ($self->{'DEBUG'});
  3104. push @{$current->{'contents'}}, {'type' => 'menu_comment',
  3105. 'parent' => $current,
  3106. 'contents' => [] };
  3107. $current = $current->{'contents'}->[-1];
  3108. push @{$self->{'context_stack'}}, 'preformatted';
  3109. }
  3110. } else {
  3111. #print STDERR "LLLLLLLLLLLL Cannot be here...\n";
  3112. }
  3113. $current = $self->_begin_preformatted($current)
  3114. if ($close_preformatted_commands{$end_command});
  3115. }
  3116. } else {
  3117. $current = $self->_begin_preformatted($current)
  3118. if ($close_preformatted_commands{$command});
  3119. }
  3120. # if a file was included, remove completly the include file command.
  3121. # Also ignore @setfilename in included file, as said in the manual.
  3122. if ($included_file or ($command eq 'setfilename'
  3123. and scalar(@{$self->{'input'}}) > 1)) {
  3124. # TODO keep the information with sourcemark
  3125. pop @{$current->{'contents'}};
  3126. } elsif ($command eq 'setfilename'
  3127. and ($self->{'current_node'} or $self->{'current_section'})) {
  3128. $self->_command_warn($misc_cmd, $line_nr,
  3129. $self->__("\@%s after the first element"), $command);
  3130. # columnfractions
  3131. } elsif ($command eq 'columnfractions') {
  3132. # in a multitable, we are in a block_line_arg
  3133. if (!$current->{'parent'} or !$current->{'parent'}->{'cmdname'}
  3134. or $current->{'parent'}->{'cmdname'} ne 'multitable') {
  3135. $self->_command_error($current, $line_nr,
  3136. $self->__("\@%s only meaningful on a \@multitable line"),
  3137. $command);
  3138. } else {
  3139. # This is the multitable block_line_arg line context
  3140. my $context = pop @{$self->{'context_stack'}};
  3141. if ($context ne 'line') {
  3142. $self->_bug_message("context $context instead of line for multitable",
  3143. $line_nr, $current);
  3144. }
  3145. $current = $current->{'parent'};
  3146. $current->{'extra'}->{'max_columns'} = 0;
  3147. if (defined($misc_cmd->{'extra'}->{'misc_args'})) {
  3148. $current->{'extra'}->{'max_columns'} =
  3149. scalar(@{$misc_cmd->{'extra'}->{'misc_args'}});
  3150. $current->{'extra'}->{'columnfractions'} = $misc_cmd->{'extra'}->{'misc_args'};
  3151. }
  3152. push @{$current->{'contents'}}, { 'type' => 'before_item',
  3153. 'contents' => [], 'parent', $current };
  3154. $current = $current->{'contents'}->[-1];
  3155. }
  3156. } elsif ($root_commands{$command}) {
  3157. $current = $current->{'contents'}->[-1];
  3158. delete $current->{'remaining_args'};
  3159. $current->{'contents'} = [];
  3160. # we never should be in a raw format bock, so we don't check for
  3161. # _ignore_global_commands($self)
  3162. # associate the section (not part) with the current node.
  3163. if ($command ne 'node' and $command ne 'part') {
  3164. if ($self->{'current_node'}
  3165. and !$self->{'current_node'}->{'extra'}->{'associated_section'}) {
  3166. $self->{'current_node'}->{'extra'}->{'associated_section'} = $current;
  3167. $current->{'extra'}->{'associated_node'} = $self->{'current_node'};
  3168. }
  3169. if ($self->{'current_parts'}) {
  3170. $current->{'extra'}->{'associated_part'} = $self->{'current_parts'}->[-1];
  3171. foreach my $part (@{$self->{'current_parts'}}) {
  3172. $part->{'extra'}->{'part_associated_section'} = $current;
  3173. if ($current->{'cmdname'} eq 'top') {
  3174. $self->line_warn(sprintf($self->__(
  3175. "\@%s should not be associated with \@top"),
  3176. $part->{'cmdname'}), $part->{'line_nr'});
  3177. }
  3178. }
  3179. delete $self->{'current_parts'};
  3180. }
  3181. $self->{'current_section'} = $current;
  3182. } elsif ($command eq 'part') {
  3183. push @{$self->{'current_parts'}}, $current;
  3184. if ($self->{'current_node'}
  3185. and !$self->{'current_node'}->{'extra'}->{'associated_section'}) {
  3186. $self->line_warn (sprintf($self->__(
  3187. "\@node precedes \@%s, but parts may not be associated with nodes"),
  3188. $command), $line_nr);
  3189. }
  3190. }
  3191. }
  3192. # do that last in order to have the line processed if one of the above
  3193. # case is also set.
  3194. } elsif (
  3195. $current->{'contents'}
  3196. and (scalar(@{$current->{'contents'}}) == 1
  3197. and (($current->{'contents'}->[-1]->{'type'}
  3198. and $current->{'contents'}->[-1]->{'type'} eq 'empty_line_after_command'))
  3199. or (scalar(@{$current->{'contents'}}) == 2
  3200. and $current->{'contents'}->[-1]->{'cmdname'}
  3201. and ($current->{'contents'}->[-1]->{'cmdname'} eq 'c'
  3202. or $current->{'contents'}->[-1]->{'cmdname'} eq 'comment')
  3203. and $current->{'contents'}->[-2]
  3204. and $current->{'contents'}->[-2]->{'type'}
  3205. and $current->{'contents'}->[-2]->{'type'} eq 'empty_line_after_command'))) {
  3206. # empty line after a @menu or before a preformatted. Reparent to the menu
  3207. # or other format
  3208. if ($current->{'type'}
  3209. and $preformatted_contexts{$current->{'type'}}) {
  3210. my $parent = $current->{'parent'};
  3211. if ($parent->{'type'} and $parent->{'type'} eq 'menu_comment'
  3212. and scalar(@{$parent->{'contents'}}) == 1) {
  3213. $parent = $parent->{'parent'};
  3214. }
  3215. my $to_reparent = pop @{$parent->{'contents'}};
  3216. print STDERR "LINE AFTER COMMAND IN PREFORMATTED ($to_reparent->{'type'})\n" if ($self->{'DEBUG'});
  3217. while (@{$current->{'contents'}}) {
  3218. my $content = shift @{$current->{'contents'}};
  3219. $content->{'parent'} = $parent;
  3220. push @{$parent->{'contents'}}, $content;
  3221. }
  3222. push @{$parent->{'contents'}}, $to_reparent;
  3223. }
  3224. }
  3225. # this happens if there is a nesting of line @-commands on a line.
  3226. # they are reprocessed here.
  3227. if ($self->{'context_stack'}->[-1] eq 'line'
  3228. or $self->{'context_stack'}->[-1] eq 'def') {
  3229. print STDERR "Still opened line command $self->{'context_stack'}->[-1]:"._print_current($current)
  3230. if ($self->{'DEBUG'});
  3231. if ($self->{'context_stack'}->[-1] eq 'def') {
  3232. while ($current->{'parent'} and !($current->{'parent'}->{'type'}
  3233. and $current->{'parent'}->{'type'} eq 'def_line')) {
  3234. $current = $self->_close_current($current, $line_nr);
  3235. }
  3236. } else {
  3237. while ($current->{'parent'} and !($current->{'type'}
  3238. and ($current->{'type'} eq 'block_line_arg'
  3239. or $current->{'type'} eq 'misc_line_arg'))) {
  3240. $current = $self->_close_current($current, $line_nr);
  3241. }
  3242. }
  3243. # check for infinite loop bugs...
  3244. if ($current eq $current_old) {
  3245. my $indent = '- ';
  3246. my $tree_msg = $indent . _print_current($current);
  3247. while ($current->{'parent'}) {
  3248. $indent = '-'.$indent;
  3249. $current = $current->{'parent'};
  3250. $tree_msg .= $indent . _print_current($current);
  3251. }
  3252. $self->_bug_message("Nothing closed while a line context remains\n$tree_msg",
  3253. $line_nr);
  3254. die;
  3255. }
  3256. $current = $self->_end_line($current, $line_nr);
  3257. }
  3258. return $current;
  3259. }
  3260. # $command may be undef if we are after a wrong misc command such as
  3261. # a buggy @tab.
  3262. sub _start_empty_line_after_command($$$) {
  3263. my $line = shift;
  3264. my $current = shift;
  3265. my $command = shift;
  3266. $line =~ s/^([^\S\r\n]*)//;
  3267. push @{$current->{'contents'}}, { 'type' => 'empty_line_after_command',
  3268. 'text' => $1,
  3269. 'parent' => $current,
  3270. };
  3271. if (defined($command)) {
  3272. $current->{'contents'}->[-1]->{'extra'} = {'command' => $command};
  3273. $command->{'extra'}->{'spaces_after_command'} = $current->{'contents'}->[-1];
  3274. }
  3275. return $line;
  3276. }
  3277. sub _check_empty_node($$$$)
  3278. {
  3279. my $self = shift;
  3280. my $parsed_node = shift;
  3281. my $command = shift;
  3282. my $line_nr = shift;
  3283. if (!defined($parsed_node) or !$parsed_node->{'node_content'}) {
  3284. $self->line_error (sprintf($self->__("empty argument in \@%s"),
  3285. $command), $line_nr);
  3286. return 0;
  3287. } elsif ($parsed_node->{'normalized'} !~ /[^-]/) {
  3288. $self->line_error (sprintf($self->__("empty node name after expansion `%s'"),
  3289. Texinfo::Convert::Texinfo::convert({'contents'
  3290. => $parsed_node->{'node_content'}})),
  3291. $line_nr);
  3292. return 0;
  3293. } else {
  3294. return 1;
  3295. }
  3296. }
  3297. sub _check_internal_node($$$)
  3298. {
  3299. my $self = shift;
  3300. my $parsed_node = shift;
  3301. my $line_nr = shift;
  3302. if ($parsed_node and $parsed_node->{'manual_content'}) {
  3303. $self->line_error (sprintf($self->__("syntax for an external node used for `%s'"),
  3304. _node_extra_to_texi($parsed_node)), $line_nr)
  3305. }
  3306. }
  3307. sub _check_node_label($$$$)
  3308. {
  3309. my $self = shift;
  3310. my $parsed_node = shift;
  3311. my $command = shift;
  3312. my $line_nr = shift;
  3313. _check_internal_node($self, $parsed_node, $line_nr);
  3314. return _check_empty_node($self, $parsed_node, $command, $line_nr);
  3315. }
  3316. sub _register_extra_menu_entry_information($$;$)
  3317. {
  3318. my $self = shift;
  3319. my $current = shift;
  3320. my $line_nr = shift;
  3321. foreach my $arg (@{$current->{'args'}}) {
  3322. if ($arg->{'type'} eq 'menu_entry_name') {
  3323. $current->{'extra'}->{'menu_entry_name'} = $arg;
  3324. my $normalized_menu_entry_name =
  3325. Texinfo::Convert::NodeNameNormalization::normalize_node($arg);
  3326. if ($normalized_menu_entry_name !~ /[^-]/) {
  3327. $self->line_warn(sprintf($self->__("empty menu entry name in `%s'"),
  3328. Texinfo::Convert::Texinfo::convert($current)), $line_nr);
  3329. }
  3330. } elsif ($arg->{'type'} eq 'menu_entry_node') {
  3331. $self->_isolate_last_space($arg, 'space_at_end_menu_node');
  3332. my $parsed_entry_node = _parse_node_manual($arg);
  3333. if (! defined($parsed_entry_node)) {
  3334. if ($self->{'SHOW_MENU'}) {
  3335. $self->line_error ($self->__("empty node name in menu entry"), $line_nr);
  3336. }
  3337. } else {
  3338. $current->{'extra'}->{'menu_entry_node'} = $parsed_entry_node;
  3339. }
  3340. } elsif ($arg->{'type'} eq 'menu_entry_description') {
  3341. $current->{'extra'}->{'menu_entry_description'} = $arg;
  3342. }
  3343. }
  3344. }
  3345. sub _enter_menu_entry_node($$$)
  3346. {
  3347. my $self = shift;
  3348. my $current = shift;
  3349. my $line_nr = shift;
  3350. my $description = { 'type' => 'menu_entry_description',
  3351. 'contents' => [],
  3352. 'parent' => $current };
  3353. push @{$current->{'args'}}, $description;
  3354. _register_extra_menu_entry_information($self, $current, $line_nr);
  3355. $current->{'line_nr'} = $line_nr;
  3356. $current = $description;
  3357. push @{$current->{'contents'}}, {'type' => 'preformatted',
  3358. 'parent' => $current,
  3359. 'contents' => [] };
  3360. $current = $current->{'contents'}->[-1];
  3361. push @{$self->{'context_stack'}}, 'preformatted';
  3362. return $current;
  3363. }
  3364. sub _register_command_arg($$$)
  3365. {
  3366. my $self = shift;
  3367. my $current = shift;
  3368. my $type = shift;
  3369. my @contents = @{$current->{'contents'}};
  3370. _trim_spaces_comment_from_content(\@contents);
  3371. if (scalar(@contents)) {
  3372. push @{$current->{'parent'}->{'extra'}->{$type}}, \@contents;
  3373. } else {
  3374. push @{$current->{'parent'}->{'extra'}->{$type}}, undef;
  3375. }
  3376. }
  3377. sub _command_with_command_as_argument($)
  3378. {
  3379. my $current = shift;
  3380. return ($current and $current->{'type'}
  3381. and $current->{'type'} eq 'block_line_arg'
  3382. and $current->{'parent'}
  3383. and $current->{'parent'}->{'cmdname'} and
  3384. ($current->{'parent'}->{'cmdname'} eq 'itemize'
  3385. or $item_line_commands{$current->{'parent'}->{'cmdname'}})
  3386. and (scalar(@{$current->{'contents'}}) == 1
  3387. or (scalar(@{$current->{'contents'}}) == 2
  3388. and defined($current->{'contents'}->[0]->{'text'})
  3389. and $current->{'contents'}->[0]->{'text'}
  3390. =~ /^[^\S\r\n]*/)))
  3391. }
  3392. # $marked_as_invalid_command may be undef, if there is no
  3393. # tree element because the @-command construct is incorrect, for example
  3394. # wrong @tab.
  3395. sub _mark_and_warn_invalid($$$$$)
  3396. {
  3397. my $self = shift;
  3398. my $command = shift;
  3399. my $invalid_parent = shift;
  3400. my $line_nr = shift;
  3401. my $marked_as_invalid_command = shift;
  3402. if (defined($invalid_parent)) {
  3403. $self->line_warn(sprintf($self->__("\@%s should not appear in \@%s"),
  3404. $command, $invalid_parent), $line_nr);
  3405. $marked_as_invalid_command->{'extra'}->{'invalid_nesting'} = 1
  3406. if (defined($marked_as_invalid_command));
  3407. }
  3408. }
  3409. # the different types
  3410. #c 'menu_entry'
  3411. #c 'menu_entry'
  3412. # t 'menu_entry_leading_text'
  3413. #
  3414. #t 'macro_arg_name'
  3415. #t 'macro_arg_args'
  3416. #
  3417. #t 'raw'
  3418. #
  3419. #t 'misc_arg'
  3420. #c 'misc_line_arg'
  3421. #
  3422. #c 'block_line_arg'
  3423. #
  3424. #c 'brace_command_arg'
  3425. #c 'brace_command_context'
  3426. #
  3427. #c 'before_item' what comes after @*table, @itemize, @enumerate before
  3428. # an @item
  3429. #
  3430. #c 'paragraph'
  3431. #
  3432. #a 'def_line'
  3433. #
  3434. #special for @verb, type is the character
  3435. # the main subroutine
  3436. sub _parse_texi($;$)
  3437. {
  3438. my $self = shift;
  3439. my $root = shift;
  3440. $root = { 'contents' => [], 'type' => 'text_root' } if (!defined($root));
  3441. my $current = $root;
  3442. my $line_nr;
  3443. NEXT_LINE:
  3444. while (1) {
  3445. my $line;
  3446. ($line, $line_nr) = _next_text($self, $line_nr, $current);
  3447. last if (!defined($line));
  3448. if ($self->{'DEBUG'}) {
  3449. $current->{'HERE !!!!'} = 1; # marks where we are in the tree
  3450. if ($self->{'DEBUG'} >= 100) {
  3451. local $Data::Dumper::Indent = 1;
  3452. local $Data::Dumper::Purity = 1;
  3453. print STDERR "".Data::Dumper->Dump([$root], ['$root']);
  3454. }
  3455. my $line_text = '';
  3456. $line_text = "$line_nr->{'line_nr'}.$line_nr->{'macro'}" if ($line_nr);
  3457. print STDERR "NEW LINE(".join('|', @{$self->{'context_stack'}}).":@{$self->{'conditionals_stack'}}:$line_text): $line";
  3458. #print STDERR "CONTEXT_STACK ".join('|',@{$self->{'context_stack'}})."\n";
  3459. delete $current->{'HERE !!!!'};
  3460. }
  3461. if (not
  3462. # raw format or verb
  3463. (($current->{'cmdname'}
  3464. and $block_commands{$current->{'cmdname'}}
  3465. and ($block_commands{$current->{'cmdname'}} eq 'raw'
  3466. or $block_commands{$current->{'cmdname'}} eq 'conditional'))
  3467. or
  3468. ($current->{'parent'} and $current->{'parent'}->{'cmdname'}
  3469. and $current->{'parent'}->{'cmdname'} eq 'verb')
  3470. )
  3471. # not def line
  3472. and $self->{'context_stack'}->[-1] ne 'def') {
  3473. print STDERR "BEGIN LINE\n" if ($self->{'DEBUG'});
  3474. $line =~ s/^([^\S\r\n]*)//;
  3475. push @{$current->{'contents'}}, { 'type' => 'empty_line',
  3476. 'text' => $1,
  3477. 'parent' => $current };
  3478. }
  3479. while (1) {
  3480. # in a raw or ignored conditional block command
  3481. if ($current->{'cmdname'} and
  3482. $block_commands{$current->{'cmdname'}} and
  3483. ($block_commands{$current->{'cmdname'}} eq 'raw'
  3484. or $block_commands{$current->{'cmdname'}} eq 'conditional')) {
  3485. # r?macro may be nested
  3486. if (($current->{'cmdname'} eq 'macro'
  3487. or $current->{'cmdname'} eq 'rmacro')
  3488. and $line =~ /^\s*\@r?macro\s+/) {
  3489. $line =~ s/\s*\@(r?macro)//;
  3490. push @{$current->{'contents'}}, { 'cmdname' => $1,
  3491. 'parent' => $current,
  3492. 'contents' => [],
  3493. 'extra' => {'arg_line' => $line }};
  3494. $current = $current->{'contents'}->[-1];
  3495. last;
  3496. # ifclear/ifset may be nested
  3497. } elsif (($current->{'cmdname'} eq 'ifclear'
  3498. or $current->{'cmdname'} eq 'ifset'
  3499. or $current->{'cmdname'} eq 'ifcommanddefined'
  3500. or $current->{'cmdname'} eq 'ifcommandnotdefined')
  3501. and $line =~ /^\s*\@$current->{'cmdname'}/) {
  3502. $line =~ s/\s*\@($current->{'cmdname'})//;
  3503. push @{$current->{'contents'}}, { 'cmdname' => $1,
  3504. 'parent' => $current,
  3505. 'contents' => [],
  3506. 'extra' => {'line' => $line }};
  3507. $current = $current->{'contents'}->[-1];
  3508. last;
  3509. } elsif ($line =~ /^(\s*?)\@end\s+([a-zA-Z][\w-]*)/
  3510. and ($2 eq $current->{'cmdname'})) {
  3511. my $end_command = $2;
  3512. my $raw_command = $current;
  3513. $line =~ s/^(\s*?)(\@end\s+$current->{'cmdname'})//;
  3514. if ($1 eq '') {
  3515. # FIXME exclude other formats, like @macro, @ifset, @ignore?
  3516. if ($current->{'cmdname'} ne 'verbatim'
  3517. and @{$current->{'contents'}}
  3518. and $current->{'contents'}->[-1]->{'type'}
  3519. and $current->{'contents'}->[-1]->{'type'} eq 'raw') {
  3520. if ($current->{'contents'}->[-1]->{'text'} =~ s/(\n)//) {
  3521. push @{$current->{'contents'}}, {'type' => 'last_raw_newline',
  3522. 'text' => $1, 'parent' => $current};
  3523. }
  3524. }
  3525. } else {
  3526. push @{$current->{'contents'}},
  3527. { 'text' => $1, 'type' => 'raw', 'parent' => $current };
  3528. $self->line_warn(sprintf($self->__("\@end %s should only appear at a line beginning"),
  3529. $end_command), $line_nr);
  3530. }
  3531. # if there is a user defined macro that expandes to spaces, there
  3532. # will be a spurious warning.
  3533. $self->line_warn(sprintf($self->
  3534. __("superfluous argument to \@%s %s: %s"), 'end', $end_command,
  3535. $line), $line_nr)
  3536. if ($line =~ /\S/ and $line !~ /^\s*\@c(omment)?\b/);
  3537. # store toplevel macro specification
  3538. if (($end_command eq 'macro' or $end_command eq 'rmacro')
  3539. and (! $current->{'parent'}
  3540. or !$current->{'parent'}->{'cmdname'}
  3541. or ($current->{'parent'}->{'cmdname'} ne 'macro'
  3542. and $current->{'parent'}->{'cmdname'} ne 'rmacro'))) {
  3543. $current->{'extra'}->{'macrobody'} =
  3544. $self->_strip_macrobody_leading_space(
  3545. Texinfo::Convert::Texinfo::convert({ 'contents'
  3546. => $current->{'contents'} }));
  3547. if ($current->{'args'} and $current->{'args'}->[0]
  3548. and !_ignore_global_commands($self)) {
  3549. my $name = $current->{'args'}->[0]->{'text'};
  3550. if (exists($self->{'macros'}->{$name})) {
  3551. $self->line_warn(sprintf($self->__("macro `%s' previously defined"),
  3552. $name), $current->{'line_nr'});
  3553. $self->line_warn(sprintf($self->__(
  3554. "here is the previous definition of `%s'"),
  3555. $name), $self->{'macros'}->{$name}->{'line_nr'});
  3556. }
  3557. if ($all_commands{$name}) {
  3558. $self->line_warn(sprintf($self->__(
  3559. "redefining Texinfo language command: \@%s"),
  3560. $name), $current->{'line_nr'});
  3561. }
  3562. $self->{'macros'}->{$name} = $current
  3563. unless ($current->{'extra'}->{'invalid_syntax'});
  3564. }
  3565. }
  3566. $current = $current->{'parent'};
  3567. if ($block_commands{$end_command} eq 'conditional') {
  3568. # don't store ignored @if*
  3569. my $conditional = pop @{$current->{'contents'}};
  3570. if (!defined($conditional->{'cmdname'}
  3571. or $conditional->{'cmdname'} ne $end_command)) {
  3572. $self->_bug_message("Ignored command is not the conditional $end_command",
  3573. $line_nr, $conditional);
  3574. die;
  3575. }
  3576. # Ignore until end of line
  3577. if ($line !~ /\n/) {
  3578. ($line, $line_nr) = _new_line($self, $line_nr, $conditional);
  3579. print STDERR "IGNORE CLOSE line: $line" if ($self->{'DEBUG'});
  3580. }
  3581. print STDERR "CLOSED conditional $end_command\n" if ($self->{'DEBUG'});
  3582. last;
  3583. } else {
  3584. print STDERR "CLOSED raw $end_command\n" if ($self->{'DEBUG'});
  3585. $line = _start_empty_line_after_command($line, $current, $raw_command);
  3586. }
  3587. } else {
  3588. if (@{$current->{'contents'}}
  3589. and $current->{'contents'}->[-1]->{'type'}
  3590. and $current->{'contents'}->[-1]->{'type'} eq 'empty_line_after_command'
  3591. and $current->{'contents'}->[-1]->{'text'} !~ /\n/
  3592. and $line !~ /\S/) {
  3593. $current->{'contents'}->[-1]->{'text'} .= $line;
  3594. } else {
  3595. push @{$current->{'contents'}},
  3596. { 'text' => $line, 'type' => 'raw', 'parent' => $current };
  3597. }
  3598. last;
  3599. }
  3600. # in @verb. type should be 'brace_command_arg'
  3601. } elsif ($current->{'parent'} and $current->{'parent'}->{'cmdname'}
  3602. and $current->{'parent'}->{'cmdname'} eq 'verb') {
  3603. # collect the first character if not already done
  3604. if (!defined($current->{'parent'}->{'type'})) {
  3605. if ($line =~ /^$/) {
  3606. $current->{'parent'}->{'type'} = '';
  3607. $self->line_error(sprintf($self->
  3608. __("\@%s without associated character"), 'verb'), $line_nr);
  3609. } else {
  3610. $line =~ s/^(.)//;
  3611. $current->{'parent'}->{'type'} = $1;
  3612. }
  3613. }
  3614. my $char = quotemeta($current->{'parent'}->{'type'});
  3615. if ($line =~ s/^(.*?)$char\}/\}/) {
  3616. push @{$current->{'contents'}},
  3617. { 'text' => $1, 'type' => 'raw', 'parent' => $current }
  3618. if ($1 ne '');
  3619. print STDERR "END VERB\n" if ($self->{'DEBUG'});
  3620. } else {
  3621. push @{$current->{'contents'}},
  3622. { 'text' => $line, 'type' => 'raw', 'parent' => $current };
  3623. print STDERR "LINE VERB: $line" if ($self->{'DEBUG'});
  3624. last;
  3625. }
  3626. }
  3627. # this mostly happens in the following cases:
  3628. # after expansion of user defined macro that doesn't end with EOL
  3629. # after a protection of @\n in @def* line
  3630. # at the end of an expanded Texinfo fragment
  3631. while ($line eq '') {
  3632. print STDERR "EMPTY TEXT\n"
  3633. if ($self->{'DEBUG'});
  3634. ($line, $line_nr) = _next_text($self, $line_nr, $current);
  3635. if (!defined($line)) {
  3636. # end of the file or of a text fragment.
  3637. $current = _end_line ($self, $current, $line_nr);
  3638. # It may happen that there is an @include file on the line, it
  3639. # will be picked up at NEXT_LINE, beginning a new line
  3640. next NEXT_LINE;
  3641. }
  3642. }
  3643. # handle user defined macros before anything else since
  3644. # their expansion may lead to changes in the line
  3645. # REMACRO
  3646. if ($line =~ /^\@([[:alnum:]][[:alnum:]-]*)/
  3647. and ($self->{'macros'}->{$1}
  3648. or (exists $self->{'aliases'}->{$1} and
  3649. $self->{'macros'}->{$self->{'aliases'}->{$1}}))) {
  3650. $line =~ s/^\@([[:alnum:]][[:alnum:]-]*)//o;
  3651. my $command = $1;
  3652. my $alias_command;
  3653. if (exists($self->{'aliases'}->{$command})) {
  3654. $alias_command = $command;
  3655. $command = $self->{'aliases'}->{$command};
  3656. }
  3657. my $expanded_macro = $self->{'macros'}->{$command};
  3658. my $args_number = scalar(@{$expanded_macro->{'args'}}) -1;
  3659. my $arguments = [];
  3660. if ($line =~ s/^\s*{[^\S\f]*//) { # macro with args
  3661. ($arguments, $line, $line_nr) =
  3662. _expand_macro_arguments($self, $expanded_macro, $line, $line_nr);
  3663. } elsif (($args_number >= 2) or ($args_number <1)) {
  3664. # as agreed on the bug-texinfo mailing list, no warn when zero
  3665. # arg and not called with {}.
  3666. $self->line_warn(sprintf($self->__(
  3667. "\@%s defined with zero or more than one argument should be invoked with {}"),
  3668. $command), $line_nr)
  3669. if ($args_number >= 2);
  3670. } else {
  3671. if ($line !~ /\n/) {
  3672. ($line, $line_nr) = _new_line($self, $line_nr, $expanded_macro);
  3673. $line = '' if (!defined($line));
  3674. }
  3675. $line =~ s/^[^\S\f]*// if ($line =~ /[\S\f]/);
  3676. my $has_end_of_line = chomp $line;
  3677. $arguments = [$line];
  3678. $line = "\n" if ($has_end_of_line);
  3679. }
  3680. my $expanded = _expand_macro_body ($self, $expanded_macro,
  3681. $arguments, $line_nr);
  3682. print STDERR "MACROBODY: $expanded".'||||||'."\n"
  3683. if ($self->{'DEBUG'});
  3684. # empty result. It is ignored here.
  3685. if ($expanded eq '') {
  3686. next;
  3687. }
  3688. if ($self->{'MAX_MACRO_CALL_NESTING'}
  3689. and scalar(@{$self->{'macro_stack'}}) > $self->{'MAX_MACRO_CALL_NESTING'}) {
  3690. $self->line_warn(sprintf($self->__(
  3691. "macro call nested too deeply (set MAX_NESTED_MACROS to override; current value %d)"),
  3692. $self->{'MAX_MACRO_CALL_NESTING'}), $line_nr);
  3693. next;
  3694. }
  3695. if ($expanded_macro->{'cmdname'} eq 'macro') {
  3696. my $found = 0;
  3697. foreach my $macro (@{$self->{'macro_stack'}}) {
  3698. if ($macro->{'args'}->[0]->{'text'} eq $command) {
  3699. $self->line_error(sprintf($self->__(
  3700. "recursive call of macro %s is not allowed; use \@rmacro if needed"),
  3701. $command), $line_nr);
  3702. $found = 1;
  3703. last;
  3704. }
  3705. }
  3706. next if ($found);
  3707. }
  3708. unshift @{$self->{'macro_stack'}}, $expanded_macro;
  3709. print STDERR "UNSHIFT MACRO_STACK: $expanded_macro->{'args'}->[0]->{'text'}\n"
  3710. if ($self->{'DEBUG'});
  3711. my $expanded_lines = _text_to_lines($expanded);
  3712. chomp ($expanded_lines->[-1]);
  3713. pop @$expanded_lines if ($expanded_lines->[-1] eq '');
  3714. print STDERR "MACRO EXPANSION LINES: ".join('|', @$expanded_lines)
  3715. ."|\nEND LINES MACRO EXPANSION\n" if ($self->{'DEBUG'});
  3716. next if (!@$expanded_lines);
  3717. my $new_lines = _complete_line_nr($expanded_lines,
  3718. $line_nr->{'line_nr'}, $line_nr->{'file_name'},
  3719. $expanded_macro->{'args'}->[0]->{'text'}, 1);
  3720. $line_nr->{'end_macro'} = 1;
  3721. unshift @{$self->{'input'}->[0]->{'pending'}}, [$line, $line_nr];
  3722. my $new_text = shift @$new_lines;
  3723. ($line, $line_nr) = ($new_text->[0], $new_text->[1]);
  3724. unshift @{$self->{'input'}->[0]->{'pending'}}, @$new_lines;
  3725. # Now handle all the cases that may lead to command closing
  3726. # or following character association with an @-command, especially
  3727. # accent command, that is handle @-command with braces that don't
  3728. # always need a brace.
  3729. # The condition below is only caught right after command opening,
  3730. # otherwise we are in the 'args' and not right in the command container.
  3731. } elsif ($current->{'cmdname'} and
  3732. (defined($brace_commands{$current->{'cmdname'}}) or
  3733. $self->{'definfoenclose'}->{$current->{'cmdname'}})
  3734. and $line !~ /^{/) {
  3735. # special case for @-command as argument of @itemize or @*table.
  3736. if (_command_with_command_as_argument($current->{'parent'})) {
  3737. delete $current->{'contents'};
  3738. print STDERR "FOR PARENT \@$current->{'parent'}->{'parent'}->{'cmdname'} command_as_argument $current->{'cmdname'}\n" if ($self->{'DEBUG'});
  3739. $current->{'type'} = 'command_as_argument' if (!$current->{'type'});
  3740. $current->{'parent'}->{'parent'}->{'extra'}->{'command_as_argument'}
  3741. = $current;
  3742. $current = $current->{'parent'};
  3743. # now accent commands
  3744. } elsif ($accent_commands{$current->{'cmdname'}}) {
  3745. if ($line =~ /^[^\S\r\n]/) {
  3746. if ($current->{'cmdname'} =~ /^[a-zA-Z]/) {
  3747. $line =~ s/^([^\S\r\n]+)//;
  3748. $current->{'extra'}->{'spaces'} = ''
  3749. if (!defined($current->{'extra'}->{'spaces'}));
  3750. $current->{'extra'}->{'spaces'} .= $1;
  3751. } else {
  3752. $self->line_warn(sprintf($self->
  3753. __("accent command `\@%s' must not be followed by whitespace"),
  3754. $current->{'cmdname'}), $line_nr);
  3755. $current = $current->{'parent'};
  3756. }
  3757. } elsif ($line =~ /^\@/) {
  3758. $self->line_error(sprintf($self->
  3759. __("use braces to give a command as an argument to \@%s"),
  3760. $current->{'cmdname'}), $line_nr);
  3761. $current = $current->{'parent'};
  3762. } elsif ($line =~ s/^(.)//o) {
  3763. print STDERR "ACCENT \@$current->{'cmdname'}\n"
  3764. if ($self->{'DEBUG'});
  3765. my $following_arg = {'type' => 'following_arg',
  3766. 'parent' => $current};
  3767. $following_arg->{'contents'} = [{ 'text' => $1,
  3768. 'parent' => $following_arg } ];
  3769. $current->{'args'} = [ $following_arg ];
  3770. if ($current->{'cmdname'} eq 'dotless' and $1 ne 'i' and $1 ne 'j') {
  3771. $self->line_error(sprintf($self->
  3772. __("%c%s expects `i' or `j' as argument, not `%s'"),
  3773. ord('@'), $current->{'cmdname'}, $1), $line_nr);
  3774. }
  3775. if ($current->{'cmdname'} =~ /^[a-zA-Z]/) {
  3776. $current->{'args'}->[-1]->{'type'} = 'space_command_arg';
  3777. }
  3778. delete $current->{'contents'};
  3779. $current = $current->{'parent'};
  3780. } else { # The accent is at end of line
  3781. # whitespace for commands with letter.
  3782. print STDERR "STRANGE ACC \@$current->{'cmdname'}\n" if ($self->{'DEBUG'});
  3783. $self->line_warn(sprintf($self->
  3784. __("accent command `\@%s' must not be followed by new line"),
  3785. $current->{'cmdname'}), $line_nr);
  3786. $current = $current->{'parent'};
  3787. }
  3788. next;
  3789. } else {
  3790. # ignore space after a braced @-command like TeX does
  3791. if ($self->{'IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME'}
  3792. and $line =~ s/^\s+//) {
  3793. next;
  3794. }
  3795. $self->line_error(sprintf($self->__("\@%s expected braces"),
  3796. $current->{'cmdname'}), $line_nr);
  3797. $current = $current->{'parent'};
  3798. }
  3799. # maybe a menu entry beginning: a * at the beginning of a menu line
  3800. } elsif ($line =~ /^\*/ and $current->{'type'}
  3801. and $current->{'type'} eq 'preformatted'
  3802. and $current->{'parent'}->{'type'}
  3803. and ($current->{'parent'}->{'type'} eq 'menu_comment'
  3804. or $current->{'parent'}->{'type'} eq 'menu_entry_description')
  3805. and @{$current->{'contents'}}
  3806. and $current->{'contents'}->[-1]->{'type'}
  3807. and $current->{'contents'}->[-1]->{'type'} eq 'empty_line'
  3808. and $current->{'contents'}->[-1]->{'text'} eq '') {
  3809. print STDERR "MENU STAR\n" if ($self->{'DEBUG'});
  3810. _abort_empty_line($self, $current);
  3811. $line =~ s/^\*//;
  3812. push @{$current->{'contents'}}, { 'type' => 'menu_star',
  3813. 'text' => '*' };
  3814. # a space after a * at the beginning of a menu line
  3815. } elsif ($line =~ /^\s+/ and $current->{'contents'}
  3816. and @{$current->{'contents'}}
  3817. and $current->{'contents'}->[-1]->{'type'}
  3818. and $current->{'contents'}->[-1]->{'type'} eq 'menu_star') {
  3819. print STDERR "MENU ENTRY (certainly)\n" if ($self->{'DEBUG'});
  3820. # this is the menu star collected previously
  3821. pop @{$current->{'contents'}};
  3822. $line =~ s/^(\s+)//;
  3823. my $leading_text = '*' . $1;
  3824. if ($current->{'type'} eq 'preformatted'
  3825. and $current->{'parent'}->{'type'}
  3826. and $current->{'parent'}->{'type'} eq 'menu_comment') {
  3827. my $menu = $current->{'parent'}->{'parent'};
  3828. if (!@{$current->{'contents'}}) {
  3829. pop @{$current->{'parent'}->{'contents'}};
  3830. if (!scalar(@{$current->{'parent'}->{'contents'}})) {
  3831. pop @{$menu->{'contents'}};
  3832. }
  3833. }
  3834. $current = $menu;
  3835. #print STDERR "Close MENU_COMMENT because new menu entry\n";
  3836. } else {
  3837. # first parent preformatted, third is menu_entry
  3838. if ($current->{'type'} ne 'preformatted'
  3839. or $current->{'parent'}->{'type'} ne 'menu_entry_description'
  3840. or $current->{'parent'}->{'parent'}->{'type'} ne 'menu_entry'
  3841. or !$menu_commands{$current->{'parent'}->{'parent'}->{'parent'}->{'cmdname'}}) {
  3842. $self->_bug_message("Not in menu comment nor description",
  3843. $line_nr, $current);
  3844. }
  3845. $current = $current->{'parent'}->{'parent'}->{'parent'};
  3846. }
  3847. my $context = pop @{$self->{'context_stack'}};
  3848. if ($context ne 'preformatted') {
  3849. $self->_bug_message("context $context instead of preformatted after menu leading star",
  3850. $line_nr, $current);
  3851. }
  3852. push @{$current->{'contents'}}, { 'type' => 'menu_entry',
  3853. 'parent' => $current,
  3854. };
  3855. $current = $current->{'contents'}->[-1];
  3856. $current->{'args'} = [ { 'type' => 'menu_entry_leading_text',
  3857. 'text' => $leading_text,
  3858. 'parent' => $current },
  3859. { 'type' => 'menu_entry_name',
  3860. 'contents' => [],
  3861. 'parent' => $current } ];
  3862. $current = $current->{'args'}->[-1];
  3863. # * followed by something else than a space.
  3864. } elsif ($current->{'contents'} and @{$current->{'contents'}}
  3865. and $current->{'contents'}->[-1]->{'type'}
  3866. and $current->{'contents'}->[-1]->{'type'} eq 'menu_star') {
  3867. print STDERR "ABORT MENU STAR ($line)\n" if ($self->{'DEBUG'});
  3868. delete $current->{'contents'}->[-1]->{'type'};
  3869. # after a separator in menu
  3870. } elsif ($current->{'args'} and @{$current->{'args'}}
  3871. and $current->{'args'}->[-1]->{'type'}
  3872. and $current->{'args'}->[-1]->{'type'} eq 'menu_entry_separator') {
  3873. my $separator = $current->{'args'}->[-1]->{'text'};
  3874. # separator is ::, we concatenate and let the while restart
  3875. # in order to collect spaces below
  3876. if ($separator eq ':' and $line =~ s/^(:)//) {
  3877. $current->{'args'}->[-1]->{'text'} .= $1;
  3878. # a . not followed by a space. Not a separator.
  3879. } elsif ($separator eq '.' and $line =~ /^\S/) {
  3880. pop @{$current->{'args'}};
  3881. $current = $current->{'args'}->[-1];
  3882. $current = _merge_text($self, $current, $separator);
  3883. # here we collect spaces following separators.
  3884. } elsif ($line =~ s/^([^\S\r\n]+)//) {
  3885. # FIXME a trailing end of line could be considered to be part
  3886. # of the separator. Right now it is part of the description,
  3887. # since it is catched (in the next while) as one of the case below
  3888. $current->{'args'}->[-1]->{'text'} .= $1;
  3889. # now handle the menu part that was closed
  3890. } elsif ($separator =~ /^::/) {
  3891. print STDERR "MENU NODE no entry $separator\n" if ($self->{'DEBUG'});
  3892. # it was previously registered as menu_entry_name, it is
  3893. # changed to node
  3894. $current->{'args'}->[-2]->{'type'} = 'menu_entry_node';
  3895. $current = _enter_menu_entry_node($self, $current, $line_nr);
  3896. # end of the menu entry name
  3897. } elsif ($separator =~ /^:/) {
  3898. print STDERR "MENU ENTRY $separator\n" if ($self->{'DEBUG'});
  3899. push @{$current->{'args'}}, { 'type' => 'menu_entry_node',
  3900. 'contents' => [],
  3901. 'parent' => $current };
  3902. $current = $current->{'args'}->[-1];
  3903. # anything else is the end of the menu node following a menu_entry_name
  3904. } else {
  3905. print STDERR "MENU NODE $separator\n" if ($self->{'DEBUG'});
  3906. $current = _enter_menu_entry_node($self, $current, $line_nr);
  3907. }
  3908. # REMACRO
  3909. } elsif ($line =~ s/^\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])//o
  3910. or $line =~ s/^\@([[:alnum:]][[:alnum:]-]*)//o) {
  3911. my $command = $1;
  3912. my $alias_command;
  3913. if (exists($self->{'aliases'}->{$command})) {
  3914. $alias_command = $command;
  3915. $command = $self->{'aliases'}->{$command};
  3916. }
  3917. print STDERR "COMMAND $command\n" if ($self->{'DEBUG'});
  3918. if ($command eq 'value') {
  3919. $line =~ s/^\s*//
  3920. if ($self->{'IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME'});
  3921. # REVALUE
  3922. if ($line =~ s/^{([\w\-][^\s{\\}~`\^+"<>|@]*)}//) {
  3923. my $value = $1;
  3924. if (exists($self->{'values'}->{$value})) {
  3925. if (!defined($self->{'values'}->{$value})) {
  3926. print STDERR "BUG? $value exists but not defined\n";
  3927. } elsif (!ref($self->{'values'}->{$value})) {
  3928. $line = $self->{'values'}->{$value} . $line;
  3929. # the push @{$current->{'contents'}}, {}; prevents a trailing
  3930. # text to be merged, to avoid having the value tree modified.
  3931. } elsif (ref($self->{'values'}->{$value}) eq 'ARRAY') {
  3932. # we don't know for sure, but if we don't do it here it
  3933. # won't be done
  3934. _abort_empty_line($self, $current);
  3935. foreach my $content (@{$self->{'values'}->{$value}}) {
  3936. push @{$current->{'contents'}}, $content;
  3937. }
  3938. push @{$current->{'contents'}}, {};
  3939. } elsif (ref($self->{'values'}->{$value}) eq 'HASH') {
  3940. # we don't know for sure, but if we don't do it here it
  3941. # won't be done
  3942. _abort_empty_line($self, $current);
  3943. my $content = $self->{'values'}->{$value};
  3944. push @{$current->{'contents'}}, $content;
  3945. push @{$current->{'contents'}}, {};
  3946. }
  3947. } else {
  3948. # caller should expand something along
  3949. # gdt('@{No value for `{value}\'@}', {'value' => $value}, {'keep_texi'=> 1});
  3950. push @{$current->{'contents'}}, { 'cmdname' => 'value',
  3951. 'type' => $value };
  3952. $self->line_warn(
  3953. sprintf($self->__("undefined flag: %s"), $value), $line_nr);
  3954. }
  3955. } else {
  3956. $self->line_error($self->__("bad syntax for \@value"), $line_nr);
  3957. }
  3958. next;
  3959. }
  3960. if (defined($deprecated_commands{$command})) {
  3961. if ($deprecated_commands{$command} eq '') {
  3962. $self->line_warn(sprintf($self->__("%c%s is obsolete."),
  3963. ord('@'), $command), $line_nr);
  3964. } else {
  3965. $self->line_warn(sprintf($self->__("%c%s is obsolete; %s"),
  3966. ord('@'), $command,
  3967. $self->__($deprecated_commands{$command})), $line_nr);
  3968. }
  3969. }
  3970. if (not _abort_empty_line($self, $current)
  3971. and $begin_line_commands{$command}) {
  3972. $self->line_warn(
  3973. sprintf($self->__("\@%s should only appear at a line beginning"),
  3974. $command), $line_nr);
  3975. }
  3976. my $invalid_parent;
  3977. # error messages for forbidden constructs, like @node in @r,
  3978. # block command on line command, @xref in @anchor or node...
  3979. if ($current->{'parent'}) {
  3980. if ($current->{'parent'}->{'cmdname'}) {
  3981. if (defined($self->{'valid_nestings'}->{$current->{'parent'}->{'cmdname'}})
  3982. and !$self->{'valid_nestings'}->{$current->{'parent'}->{'cmdname'}}->{$command}
  3983. # we make sure that we are on a root @-command line and
  3984. # not in contents
  3985. and (!$root_commands{$current->{'parent'}->{'cmdname'}}
  3986. or ($current->{'type'}
  3987. and $current->{'type'} eq 'misc_line_arg'))
  3988. # we make sure that we are on a block @-command line and
  3989. # not in contents
  3990. and (!($block_commands{$current->{'parent'}->{'cmdname'}})
  3991. or ($current->{'type'}
  3992. and $current->{'type'} eq 'block_line_arg'))
  3993. # we make sure that we are on an @item/@itemx line and
  3994. # not in an @enumerate, @multitable or @itemize @item.
  3995. and (($current->{'parent'}->{'cmdname'} ne 'itemx'
  3996. and $current->{'parent'}->{'cmdname'} ne 'item')
  3997. or ($current->{'type'}
  3998. and $current->{'type'} eq 'misc_line_arg'))) {
  3999. $invalid_parent = $current->{'parent'}->{'cmdname'};
  4000. }
  4001. } elsif ($self->{'context_stack'}->[-1] eq 'def'
  4002. # FIXME instead of hardcoding in_full_line_commands_no_refs
  4003. # it would be better to use the parent command valid_nesting.
  4004. and !$in_full_line_commands_no_refs{$command}) {
  4005. my $def_block = $current;
  4006. while ($def_block->{'parent'} and (!$def_block->{'parent'}->{'type'}
  4007. or $def_block->{'parent'}->{'type'} ne 'def_line')) {
  4008. $def_block = $def_block->{'parent'};
  4009. }
  4010. $invalid_parent = $def_block->{'parent'}->{'parent'}->{'cmdname'};
  4011. }
  4012. }
  4013. # special case with @ followed by a newline protecting end of lines
  4014. # in @def*
  4015. last if ($self->{'context_stack'}->[-1] eq 'def' and $command eq "\n");
  4016. unless ($self->{'no_paragraph_commands'}->{$command}) {
  4017. my $paragraph = _begin_paragraph($self, $current, $line_nr);
  4018. $current = $paragraph if ($paragraph);
  4019. }
  4020. if ($self->{'close_paragraph_commands'}->{$command}) {
  4021. $current = _end_paragraph($self, $current, $line_nr);
  4022. }
  4023. if ($self->{'close_preformatted_commands'}->{$command}) {
  4024. $current = _end_preformatted($self, $current, $line_nr);
  4025. }
  4026. # commands without braces and not block commands, ie no @end
  4027. if (defined($self->{'misc_commands'}->{$command})) {
  4028. if ($root_commands{$command} or $command eq 'bye') {
  4029. $current = _close_commands($self, $current, $line_nr, undef,
  4030. $command);
  4031. # root_level commands leads to setting a new root
  4032. # for the whole document and stuffing the preceding text
  4033. # as the first content, this is done only once.
  4034. if ($current->{'type'} and $current->{'type'} eq 'text_root') {
  4035. if ($command ne 'bye') {
  4036. $root = { 'type' => 'document_root', 'contents' => [$current] };
  4037. $current->{'parent'} = $root;
  4038. $current = $root;
  4039. }
  4040. } else {
  4041. die if (!defined($current->{'parent'}));
  4042. $current = $current->{'parent'};
  4043. }
  4044. }
  4045. # noarg skipline skipspace text line lineraw /^\d$/
  4046. my $arg_spec = $self->{'misc_commands'}->{$command};
  4047. my $misc;
  4048. if ($arg_spec eq 'noarg') {
  4049. my $ignored = 0;
  4050. my $only_in_headings = 0;
  4051. if ($command eq 'insertcopying') {
  4052. my $parent = $current;
  4053. while ($parent) {
  4054. if ($parent->{'cmdname'} and $parent->{'cmdname'} eq 'copying') {
  4055. $self->line_error(
  4056. sprintf($self->__("\@%s not allowed inside `\@%s' block"),
  4057. $command, $parent->{'cmdname'}), $line_nr);
  4058. $ignored = 1;
  4059. last;
  4060. }
  4061. $parent = $parent->{'parent'};
  4062. }
  4063. } elsif ($in_heading_commands{$command}) {
  4064. $self->line_error(
  4065. sprintf($self->__("\@%s should only appear in heading or footing"),
  4066. $command), $line_nr);
  4067. $only_in_headings = 1;
  4068. }
  4069. if (!$ignored) {
  4070. $misc = {'cmdname' => $command,
  4071. 'parent' => $current};
  4072. push @{$current->{'contents'}}, $misc;
  4073. # also sets invalid_nesting in that case
  4074. $misc->{'extra'}->{'invalid_nesting'} = 1 if ($only_in_headings);
  4075. $self->_register_global_command($command, $misc, $line_nr);
  4076. }
  4077. $self->_mark_and_warn_invalid($command, $invalid_parent,
  4078. $line_nr, $misc);
  4079. $current = $self->_begin_preformatted($current)
  4080. if ($close_preformatted_commands{$command});
  4081. # all the cases using the raw line
  4082. } elsif ($arg_spec eq 'skipline' or $arg_spec eq 'lineraw'
  4083. or $arg_spec eq 'special') {
  4084. # complete the line if there was a user macro expansion
  4085. if ($line !~ /\n/) {
  4086. my ($new_line, $new_line_nr) = _new_line($self, $line_nr, undef);
  4087. $line .= $new_line if (defined($new_line));
  4088. }
  4089. $misc = {'cmdname' => $command,
  4090. 'parent' => $current};
  4091. my $args = [];
  4092. my $has_comment;
  4093. if ($arg_spec eq 'lineraw' or $arg_spec eq 'skipline') {
  4094. $args = [ $line ];
  4095. } elsif ($arg_spec eq 'special') {
  4096. ($args, $has_comment)
  4097. = $self->_parse_special_misc_command($line, $command, $line_nr);
  4098. $misc->{'extra'}->{'arg_line'} = $line;
  4099. }
  4100. # if using the @set txi* instead of a proper @-command, replace
  4101. # by the tree obtained with the @-command. Even though
  4102. # _end_line is called below, as $current is not misc_line_arg
  4103. # there should not be anything done in addition than what is
  4104. # done for @clear or @set.
  4105. if (($command eq 'set' or $command eq 'clear')
  4106. and scalar(@$args) >= 1
  4107. and $set_flag_command_equivalent{$args->[0]}) {
  4108. my $arg;
  4109. if ($command eq 'set') {
  4110. $arg = 'on';
  4111. } else {
  4112. $arg = 'off';
  4113. }
  4114. $command = $set_flag_command_equivalent{$args->[0]};
  4115. $misc = {'cmdname' => $command,
  4116. 'parent' => $current,
  4117. 'line_nr' => $line_nr,
  4118. 'extra' => {'misc_args' => [$arg]}};
  4119. my $misc_line_args = {'type' => 'misc_line_arg',
  4120. 'parent' => $misc};
  4121. $misc->{'args'} = [$misc_line_args];
  4122. my $spaces_after_command
  4123. = { 'type' => 'empty_spaces_after_command',
  4124. 'text' => ' ',
  4125. 'parent' => $misc_line_args,
  4126. 'extra' => {'command' => $misc} };
  4127. $misc->{'extra'}->{'spaces_after_command'}
  4128. = $spaces_after_command;
  4129. $misc_line_args->{'contents'} = [ $spaces_after_command,
  4130. { 'text' => $arg,
  4131. 'parent' => $misc_line_args, },
  4132. { 'text' => "\n",
  4133. 'parent' => $misc_line_args,
  4134. 'type' => 'spaces_at_end', } ];
  4135. push @{$current->{'contents'}}, $misc;
  4136. } else {
  4137. push @{$current->{'contents'}}, $misc;
  4138. foreach my $arg (@$args) {
  4139. push @{$misc->{'args'}},
  4140. { 'type' => 'misc_arg', 'text' => $arg,
  4141. 'parent' => $current->{'contents'}->[-1] };
  4142. }
  4143. $misc->{'extra'}->{'misc_args'} = $args
  4144. if (scalar(@$args) and $arg_spec ne 'skipline');
  4145. }
  4146. if (! _ignore_global_commands($self)) {
  4147. if ($command eq 'raisesections') {
  4148. $self->{'sections_level'}++;
  4149. } elsif ($command eq 'lowersections') {
  4150. $self->{'sections_level'}--;
  4151. } elsif ($command eq 'novalidate') {
  4152. $self->{'novalidate'} = 1;
  4153. }
  4154. }
  4155. $self->_mark_and_warn_invalid($command, $invalid_parent,
  4156. $line_nr, $misc);
  4157. $self->_register_global_command($command, $misc, $line_nr);
  4158. # the end of line is ignored for special commands
  4159. if ($arg_spec ne 'special' or !$has_comment) {
  4160. $current = _end_line($self, $current, $line_nr);
  4161. }
  4162. last NEXT_LINE if ($command eq 'bye');
  4163. # Even if _end_line is called, it is not done since there is
  4164. # no misc_line_arg
  4165. $current = $self->_begin_preformatted($current)
  4166. if ($close_preformatted_commands{$command});
  4167. last;
  4168. } else {
  4169. # $arg_spec is text, line, skipspace or a number
  4170. my $line_arg = 0;
  4171. $line_arg = 1 if ($arg_spec ne 'skipspace');
  4172. if ($command eq 'item' or $command eq 'itemx'
  4173. or $command eq 'headitem' or $command eq 'tab') {
  4174. my $parent;
  4175. # itemize or enumerate
  4176. if ($parent = _item_container_parent($current)) {
  4177. if ($command eq 'item') {
  4178. print STDERR "ITEM_CONTAINER\n" if ($self->{'DEBUG'});
  4179. $parent->{'items_count'}++;
  4180. $misc = { 'cmdname' => $command, 'parent' => $parent,
  4181. 'contents' => [],
  4182. 'extra' =>
  4183. {'item_number' => $parent->{'items_count'}} };
  4184. push @{$parent->{'contents'}}, $misc;
  4185. $current = $parent->{'contents'}->[-1];
  4186. } else {
  4187. $self->line_error(sprintf($self->__(
  4188. "\@%s not meaningful inside `\@%s' block"),
  4189. $command, $parent->{'cmdname'}), $line_nr);
  4190. }
  4191. $current = $self->_begin_preformatted($current);
  4192. # *table
  4193. } elsif ($parent = _item_line_parent($current)) {
  4194. if ($command eq 'item' or $command eq 'itemx') {
  4195. print STDERR "ITEM_LINE\n" if ($self->{'DEBUG'});
  4196. $current = $parent;
  4197. $self->_gather_previous_item($current, $command, $line_nr);
  4198. $misc = { 'cmdname' => $command, 'parent' => $current };
  4199. push @{$current->{'contents'}}, $misc;
  4200. # since in the %misc_commands hash the entry for those
  4201. # commands is 'skipspace' we set $line_arg here.
  4202. $line_arg = 1;
  4203. } else {
  4204. $self->line_error(sprintf($self->__(
  4205. "\@%s not meaningful inside `\@%s' block"),
  4206. $command, $parent->{'cmdname'}), $line_nr);
  4207. $current = $self->_begin_preformatted($current);
  4208. }
  4209. # multitable
  4210. } elsif ($parent = _item_multitable_parent($current)) {
  4211. if ($command eq 'item' or $command eq 'headitem'
  4212. or $command eq 'tab') {
  4213. if (!$parent->{'extra'}->{'max_columns'}) {
  4214. $self->line_warn(
  4215. sprintf($self->__("\@%s in empty multitable"),
  4216. $command), $line_nr);
  4217. } elsif ($command eq 'tab') {
  4218. my $row = $parent->{'contents'}->[-1];
  4219. die if (!$row->{'type'});
  4220. if ($row->{'type'} eq 'before_item') {
  4221. $self->line_error($self->__("\@tab before \@item"), $line_nr);
  4222. } elsif ($row->{'cells_count'} >= $parent->{'extra'}->{'max_columns'}) {
  4223. $self->line_error(sprintf($self->__(
  4224. "too many columns in multitable item (max %d)"),
  4225. $parent->{'extra'}->{'max_columns'}), $line_nr);
  4226. } else {
  4227. $row->{'cells_count'}++;
  4228. $misc = { 'cmdname' => $command,
  4229. 'parent' => $row,
  4230. 'contents' => [],
  4231. 'extra' =>
  4232. {'cell_number' => $row->{'cells_count'}} };
  4233. push @{$row->{'contents'}}, $misc;
  4234. $current = $row->{'contents'}->[-1];
  4235. #$current = $self->_begin_preformatted($current);
  4236. print STDERR "TAB\n" if ($self->{'DEBUG'});
  4237. }
  4238. } else {
  4239. print STDERR "ROW\n" if ($self->{'DEBUG'});
  4240. $parent->{'rows_count'}++;
  4241. my $row = { 'type' => 'row', 'contents' => [],
  4242. 'cells_count' => 1,
  4243. 'extra' => {'row_number' => $parent->{'rows_count'} },
  4244. 'parent' => $parent };
  4245. push @{$parent->{'contents'}}, $row;
  4246. $misc = { 'cmdname' => $command,
  4247. 'parent' => $row,
  4248. 'contents' => [],
  4249. 'extra' => {'cell_number' => 1}};
  4250. push @{$row->{'contents'}}, $misc;
  4251. $current = $row->{'contents'}->[-1];
  4252. }
  4253. } else {
  4254. $self->line_error(sprintf($self->__(
  4255. "\@%s not meaningful inside `\@%s' block"),
  4256. $command, $parent->{'cmdname'}), $line_nr);
  4257. }
  4258. $current = $self->_begin_preformatted($current);
  4259. } elsif ($command eq 'tab') {
  4260. $self->line_error($self->__(
  4261. "ignoring \@tab outside of multitable"), $line_nr);
  4262. $current = $self->_begin_preformatted($current);
  4263. } else {
  4264. $self->line_error (sprintf($self->__(
  4265. "\@%s outside of table or list"), $command), $line_nr);
  4266. $current = $self->_begin_preformatted($current);
  4267. }
  4268. $misc->{'line_nr'} = $line_nr if (defined($misc));
  4269. } else {
  4270. $misc = { 'cmdname' => $command, 'parent' => $current,
  4271. 'line_nr' => $line_nr };
  4272. push @{$current->{'contents'}}, $misc;
  4273. if ($self->{'sections_level'} and $root_commands{$command}
  4274. and $command ne 'node' and $command ne 'part') {
  4275. $current->{'contents'}->[-1]->{'extra'}->{'sections_level'}
  4276. = $self->{'sections_level'};
  4277. }
  4278. # def*x
  4279. if ($def_commands{$command}) {
  4280. my $base_command = $command;
  4281. $base_command =~ s/x$//;
  4282. # check that the def*x is first after @def*, no paragraph
  4283. # in-between.
  4284. my $after_paragraph = _check_no_text($current);
  4285. push @{$self->{'context_stack'}}, 'def';
  4286. $current->{'contents'}->[-1]->{'type'} = 'def_line';
  4287. $current->{'contents'}->[-1]->{'extra'} =
  4288. {'def_command' => $base_command,
  4289. 'original_def_cmdname' => $command};
  4290. if ($current->{'cmdname'}
  4291. and $current->{'cmdname'} eq $base_command) {
  4292. pop @{$current->{'contents'}};
  4293. _gather_def_item($current, $command);
  4294. push @{$current->{'contents'}}, $misc;
  4295. }
  4296. if (!$current->{'cmdname'}
  4297. or $current->{'cmdname'} ne $base_command
  4298. or $after_paragraph) {
  4299. $self->line_error(sprintf($self->__(
  4300. "must be after `\@%s' to use `\@%s'"),
  4301. $base_command, $command), $line_nr);
  4302. $current->{'contents'}->[-1]->{'extra'}->{'not_after_command'} = 1;
  4303. }
  4304. }
  4305. }
  4306. # a container for what is on the @-command line, considered to
  4307. # be the @-command argument
  4308. if ($line_arg) {
  4309. $current = $current->{'contents'}->[-1];
  4310. $current->{'args'} = [{ 'type' => 'misc_line_arg',
  4311. 'contents' => [],
  4312. 'parent' => $current }];
  4313. # @node is the only misc command with args separated with comma
  4314. # FIXME a 3 lingering here deep into the code may not
  4315. # be very wise... However having a hash only for one @-command
  4316. # is not very appealing either...
  4317. if ($command eq 'node') {
  4318. $current->{'remaining_args'} = 3;
  4319. } elsif ($command eq 'author') {
  4320. my $parent = $current;
  4321. my $found;
  4322. while ($parent->{'parent'}) {
  4323. $parent = $parent->{'parent'};
  4324. last if ($parent->{'type'}
  4325. and $parent->{'type'} eq 'brace_command_context');
  4326. if ($parent->{'cmdname'}) {
  4327. if ($parent->{'cmdname'} eq 'titlepage') {
  4328. push @{$self->{'extra'}->{'author'}}, $current;
  4329. $current->{'extra'}->{'titlepage'} = $parent;
  4330. $found = 1;
  4331. } elsif ($parent->{'cmdname'} eq 'quotation' or
  4332. $parent->{'cmdname'} eq 'smallquotation') {
  4333. push @{$parent->{'extra'}->{'authors'}}, $current;
  4334. $current->{'extra'}->{'quotation'} = $parent;
  4335. $found = 1;
  4336. }
  4337. last if ($found);
  4338. }
  4339. }
  4340. if (!$found) {
  4341. $self->line_warn(sprintf($self->__(
  4342. "\@%s not meaningful outside `\@titlepage' and `\@quotation' environments"),
  4343. $command), $current->{'line_nr'});
  4344. }
  4345. } elsif ($command eq 'dircategory' and $self->{'current_node'}) {
  4346. $self->line_warn($self->__("\@dircategory after first node"),
  4347. $line_nr);
  4348. }
  4349. $current = $current->{'args'}->[-1];
  4350. push @{$self->{'context_stack'}}, 'line'
  4351. unless ($def_commands{$command});
  4352. }
  4353. $line = _start_empty_line_after_command($line, $current, $misc);
  4354. }
  4355. $self->_mark_and_warn_invalid($command, $invalid_parent,
  4356. $line_nr, $misc);
  4357. $self->_register_global_command($command, $misc, $line_nr);
  4358. if ($command eq 'dircategory'
  4359. and ! _ignore_global_commands($self)) {
  4360. push @{$self->{'info'}->{'dircategory_direntry'}}, $misc;
  4361. }
  4362. # @-command with matching @end opening
  4363. } elsif (exists($block_commands{$command})) {
  4364. if ($command eq 'macro' or $command eq 'rmacro') {
  4365. my $macro = _parse_macro_command_line($self, $command, $line,
  4366. $current, $line_nr);
  4367. push @{$current->{'contents'}}, $macro;
  4368. $self->_mark_and_warn_invalid($command, $invalid_parent,
  4369. $line_nr, $current->{'contents'}->[-1]);
  4370. $current = $current->{'contents'}->[-1];
  4371. last;
  4372. } elsif ($block_commands{$command} eq 'conditional') {
  4373. my $ifvalue_true = 0;
  4374. if ($command eq 'ifclear' or $command eq 'ifset') {
  4375. # REVALUE
  4376. if ($line =~ /^\s+([\w\-][^\s{\\}~`\^+"<>|@]*)\s*(\@(c|comment)((\@|\s+).*)?)?$/) {
  4377. my $name = $1;
  4378. if ((exists($self->{'values'}->{$name}) and $command eq 'ifset')
  4379. or (!exists($self->{'values'}->{$name})
  4380. and $command eq 'ifclear')) {
  4381. $ifvalue_true = 1;
  4382. }
  4383. print STDERR "CONDITIONAL \@$command $name: $ifvalue_true\n" if ($self->{'DEBUG'});
  4384. } elsif ($line !~ /\S/) {
  4385. $self->line_error(sprintf($self->
  4386. __("%c%s requires a name"), ord('@'), $command), $line_nr);
  4387. } else {
  4388. $self->line_error(sprintf($self->
  4389. __("bad name for \@%s"), $command), $line_nr);
  4390. }
  4391. } elsif ($command eq 'ifcommanddefined'
  4392. or $command eq 'ifcommandnotdefined') {
  4393. # REMACRO
  4394. if ($line =~ /^\s+([[:alnum:]][[:alnum:]\-]*)\s*(\@(c|comment)((\@|\s+).*)?)?$/) {
  4395. my $name = $1;
  4396. my $command_is_defined = (
  4397. exists($Texinfo::Common::all_commands{$name})
  4398. or $self->{'macros'}->{$name}
  4399. or $self->{'definfoenclose'}->{$name}
  4400. or $self->{'aliases'}->{$name}
  4401. or $self->{'command_index_prefix'}->{$name}
  4402. );
  4403. if (($command_is_defined
  4404. and $command eq 'ifcommanddefined')
  4405. or (! $command_is_defined
  4406. and $command eq 'ifcommandnotdefined')) {
  4407. $ifvalue_true = 1;
  4408. }
  4409. print STDERR "CONDITIONAL \@$command $name: $ifvalue_true\n" if ($self->{'DEBUG'});
  4410. } elsif ($line !~ /\S/) {
  4411. $self->line_error(sprintf($self->
  4412. __("%c%s requires a name"), ord('@'), $command), $line_nr);
  4413. } else {
  4414. $self->line_error(sprintf($self->
  4415. __("bad name for \@%s"), $command), $line_nr);
  4416. }
  4417. } elsif ($command =~ /^ifnot(.*)/) {
  4418. $ifvalue_true = 1 if !($self->{'expanded_formats_hash'}->{$1}
  4419. # exception as explained in the texinfo manual
  4420. or ($1 eq 'info'
  4421. and $self->{'expanded_formats_hash'}->{'plaintext'}));
  4422. print STDERR "CONDITIONAL \@$command format $1: $ifvalue_true\n" if ($self->{'DEBUG'});
  4423. } else {
  4424. die unless ($command =~ /^if(.*)/);
  4425. $ifvalue_true = 1 if ($self->{'expanded_formats_hash'}->{$1}
  4426. or ($1 eq 'info'
  4427. and $self->{'expanded_formats_hash'}->{'plaintext'}));
  4428. print STDERR "CONDITIONAL \@$command format $1: $ifvalue_true\n" if ($self->{'DEBUG'});
  4429. }
  4430. if ($ifvalue_true) {
  4431. push @{$self->{'conditionals_stack'}}, $command;
  4432. } else {
  4433. push @{$current->{'contents'}}, { 'cmdname' => $command,
  4434. 'parent' => $current,
  4435. 'contents' => [] };
  4436. $current = $current->{'contents'}->[-1];
  4437. }
  4438. # FIXME(Karl) ignore what is remaining on the line, to eat
  4439. # the end of line?
  4440. last;
  4441. } else {
  4442. my $block;
  4443. # a menu command closes a menu_comment, but not the other
  4444. # block commands. This won't catch menu commands buried in
  4445. # other formats (that are incorrect anyway).
  4446. if ($menu_commands{$command} and $current->{'type'}
  4447. and ($current->{'type'} eq 'menu_comment'
  4448. or $current->{'type'} eq 'menu_entry_description')) {
  4449. my $menu;
  4450. $menu = $current->{'parent'};
  4451. pop @{$menu->{'contents'}}
  4452. if (!@{$current->{'contents'}});
  4453. my $context = pop @{$self->{'context_stack'}};
  4454. if ($context ne 'preformatted') {
  4455. $self->_bug_message("context $context instead of preformatted in new menu",
  4456. $line_nr, $current);
  4457. }
  4458. if ($menu->{'type'} and $menu->{'type'} eq 'menu_entry') {
  4459. $menu = $menu->{'parent'};
  4460. }
  4461. $current = $menu;
  4462. }
  4463. # the def command holds a line_def* which corresponds with the
  4464. # definition line. This allows to have a treatement similar
  4465. # with def*x.
  4466. if ($def_commands{$command}) {
  4467. push @{$self->{'context_stack'}}, 'def';
  4468. $block = { 'parent' => $current,
  4469. 'cmdname' => $command,
  4470. 'contents' => [] };
  4471. push @{$current->{'contents'}}, $block;
  4472. $current = $current->{'contents'}->[-1];
  4473. push @{$current->{'contents'}}, {
  4474. 'type' => 'def_line',
  4475. 'parent' => $current,
  4476. 'line_nr' => $line_nr,
  4477. 'extra' =>
  4478. {'def_command' => $command,
  4479. 'original_def_cmdname' => $command}
  4480. };
  4481. } else {
  4482. $block = { 'cmdname' => $command,
  4483. 'parent' => $current,
  4484. 'contents' => [] };
  4485. push @{$current->{'contents'}}, $block;
  4486. }
  4487. $current = $current->{'contents'}->[-1];
  4488. if ($block_arg_commands{$command}) {
  4489. if ($preformatted_commands{$command}) {
  4490. push @{$self->{'context_stack'}}, 'preformatted';
  4491. } elsif ($format_raw_commands{$command}) {
  4492. push @{$self->{'context_stack'}}, 'rawpreformatted';
  4493. if ($self->{'expanded_formats_hash'}->{$command}
  4494. and $self->{'expanded_formats_stack'}->[-1]) {
  4495. push @{$self->{'expanded_formats_stack'}}, $command;
  4496. } else {
  4497. push @{$self->{'expanded_formats_stack'}}, 0;
  4498. }
  4499. }
  4500. if ($region_commands{$command}) {
  4501. if (@{$self->{'regions_stack'}}) {
  4502. $self->line_error(
  4503. sprintf($self->__("region %s inside region %s is not allowed"),
  4504. $command, $self->{'regions_stack'}->[-1]->{'cmdname'}),
  4505. $line_nr);
  4506. }
  4507. push @{$self->{'regions_stack'}}, $block;
  4508. }
  4509. if ($menu_commands{$command}) {
  4510. if ($self->{'context_stack'}->[-1] eq 'preformatted') {
  4511. push @{$self->{'context_stack'}}, 'preformatted';
  4512. } else {
  4513. push @{$self->{'context_stack'}}, 'menu';
  4514. }
  4515. if (! _ignore_global_commands($self)) {
  4516. push @{$self->{'info'}->{'dircategory_direntry'}}, $block
  4517. if ($command eq 'direntry');
  4518. if ($self->{'current_node'}) {
  4519. if ($command eq 'direntry') {
  4520. if ($self->{'SHOW_MENU'}) {
  4521. $self->line_warn($self->__("\@direntry after first node"),
  4522. $line_nr);
  4523. }
  4524. } elsif ($command eq 'menu') {
  4525. push @{$self->{'current_node'}->{'menus'}}, $current;
  4526. }
  4527. } elsif ($command ne 'direntry') {
  4528. if ($self->{'SHOW_MENU'}) {
  4529. $self->line_error(sprintf($self->__("\@%s seen before first \@node"),
  4530. $command), $line_nr);
  4531. $self->line_error($self->__(
  4532. "perhaps your \@top node should be wrapped in \@ifnottex rather than \@ifinfo?"),
  4533. $line_nr, 1);
  4534. }
  4535. if ($command eq 'menu') {
  4536. push @{$self->{'info'}->{'unassociated_menus'}}, $current;
  4537. }
  4538. }
  4539. }
  4540. }
  4541. $current->{'args'} = [ {
  4542. 'type' => 'block_line_arg',
  4543. 'contents' => [],
  4544. 'parent' => $current } ];
  4545. $current->{'remaining_args'} = $block_commands{$command} -1
  4546. if ($block_commands{$command} =~ /^\d+$/
  4547. and $block_commands{$command} -1 > 0);
  4548. $current = $current->{'args'}->[-1];
  4549. push @{$self->{'context_stack'}}, 'line'
  4550. unless ($def_commands{$command});
  4551. }
  4552. $block->{'line_nr'} = $line_nr;
  4553. $self->_mark_and_warn_invalid($command, $invalid_parent,
  4554. $line_nr, $block);
  4555. $self->_register_global_command($command, $block, $line_nr);
  4556. $line = _start_empty_line_after_command($line, $current, $block);
  4557. }
  4558. } elsif (defined($brace_commands{$command})
  4559. or defined($self->{'definfoenclose'}->{$command})) {
  4560. push @{$current->{'contents'}}, { 'cmdname' => $command,
  4561. 'parent' => $current,
  4562. 'contents' => [] };
  4563. $current->{'contents'}->[-1]->{'line_nr'} = $line_nr
  4564. if ($keep_line_nr_brace_commands{$command});
  4565. $self->_mark_and_warn_invalid($command, $invalid_parent,
  4566. $line_nr, $current->{'contents'}->[-1]);
  4567. $current = $current->{'contents'}->[-1];
  4568. if ($command eq 'click') {
  4569. $current->{'extra'}->{'clickstyle'} = $self->{'clickstyle'};
  4570. } elsif ($command eq 'kbd') {
  4571. if ($self->{'context_stack'}->[-1] eq 'preformatted'
  4572. and $self->{'kbdinputstyle'} ne 'distinct') {
  4573. $current->{'extra'}->{'code'} = 1;
  4574. } elsif ($self->{'kbdinputstyle'} eq 'code'
  4575. or ($self->{'kbdinputstyle'} eq 'example'
  4576. and $self->_in_code($current->{'parent'}))) {
  4577. $current->{'extra'}->{'code'} = 1;
  4578. }
  4579. }
  4580. if ($self->{'definfoenclose'}->{$command}) {
  4581. $current->{'type'} = 'definfoenclose_command';
  4582. $current->{'extra'} = {
  4583. 'begin' => $self->{'definfoenclose'}->{$command}->[0],
  4584. 'end' => $self->{'definfoenclose'}->{$command}->[1] };
  4585. }
  4586. } elsif (exists ($no_brace_commands{$command})) {
  4587. push @{$current->{'contents'}},
  4588. { 'cmdname' => $command, 'parent' => $current };
  4589. # FIXME generalize?
  4590. if ($command eq '\\' and $self->{'context_stack'}->[-1] ne 'math') {
  4591. $self->line_warn(sprintf($self->__("\@%s should only appear in math context"),
  4592. $command), $line_nr);
  4593. }
  4594. if ($command eq "\n") {
  4595. $current = _end_line($self, $current, $line_nr);
  4596. last;
  4597. }
  4598. } else {
  4599. $self->line_error(sprintf($self->__("unknown command `%s'"),
  4600. $command), $line_nr);
  4601. }
  4602. } elsif ($line =~ s/^([{}@,:\t.\f])//) {
  4603. my $separator = $1;
  4604. print STDERR "SEPARATOR: $separator\n" if ($self->{'DEBUG'});
  4605. if ($separator eq '@') {
  4606. # this may happen with a @ at the very end of a file, therefore
  4607. # not followed by anything.
  4608. $self->line_error($self->__("unexpected \@"), $line_nr);
  4609. } elsif ($separator eq '{') {
  4610. _abort_empty_line($self, $current);
  4611. if ($current->{'cmdname'}
  4612. and (defined($brace_commands{$current->{'cmdname'}})
  4613. or $self->{'definfoenclose'}->{$current->{'cmdname'}})) {
  4614. my $command = $current->{'cmdname'};
  4615. $current->{'args'} = [ { 'parent' => $current,
  4616. 'contents' => [] } ];
  4617. $current->{'remaining_args'} = $brace_commands{$command} -1
  4618. if ($brace_commands{$command} and $brace_commands{$command} -1);
  4619. $current->{'line_nr'} = $line_nr if ($brace_commands{$command});
  4620. if ($self->{'definfoenclose'}->{$command}) {
  4621. $current->{'remaining_args'} = 0;
  4622. }
  4623. $current = $current->{'args'}->[-1];
  4624. if ($context_brace_commands{$command}) {
  4625. if ($command eq 'caption' or $command eq 'shortcaption') {
  4626. my $float;
  4627. if (!$current->{'parent'}->{'parent'}
  4628. or !$current->{'parent'}->{'parent'}->{'cmdname'}
  4629. or $current->{'parent'}->{'parent'}->{'cmdname'} ne 'float') {
  4630. $float = $current->{'parent'};
  4631. while ($float->{'parent'} and !($float->{'cmdname'}
  4632. and $float->{'cmdname'} eq 'float')) {
  4633. $float = $float->{'parent'};
  4634. }
  4635. if (!($float->{'cmdname'} and $float->{'cmdname'} eq 'float')) {
  4636. $self->line_error(sprintf($self->__(
  4637. "\@%s is not meaningful outside `\@float' environment"),
  4638. $command), $line_nr);
  4639. $float = undef;
  4640. } else {
  4641. $self->line_warn(sprintf($self->__(
  4642. "\@%s should be right below `\@float'"),
  4643. $command), $line_nr);
  4644. }
  4645. } else {
  4646. $float = $current->{'parent'}->{'parent'};
  4647. }
  4648. if ($float) {
  4649. if ($float->{'extra'}->{$command}) {
  4650. $self->line_warn(sprintf($self->__("ignoring multiple \@%s"),
  4651. $command), $line_nr);
  4652. } else {
  4653. $current->{'parent'}->{'extra'}->{'float'} = $float;
  4654. $float->{'extra'}->{$command} = $current->{'parent'};
  4655. }
  4656. }
  4657. }
  4658. push @{$self->{'context_stack'}}, $command;
  4659. $line =~ s/([^\S\f\n]*)//;
  4660. $current->{'type'} = 'brace_command_context';
  4661. push @{$current->{'contents'}}, { 'type' => 'empty_spaces_before_argument',
  4662. 'text' => $1,
  4663. 'parent' => $current };
  4664. $current->{'parent'}->{'extra'}->{'spaces_before_argument'}
  4665. = $current->{'contents'}->[-1];
  4666. } else {
  4667. $current->{'type'} = 'brace_command_arg';
  4668. if ($brace_commands{$command}
  4669. and ($brace_commands{$command} > 1
  4670. or $simple_text_commands{$command})) {
  4671. push @{$current->{'contents'}},
  4672. {'type' => 'empty_spaces_before_argument',
  4673. 'text' => '' };
  4674. $current->{'parent'}->{'extra'}->{'spaces_before_argument'}
  4675. = $current->{'contents'}->[-1];
  4676. }
  4677. if ($inline_commands{$command}) {
  4678. # this is changed when the first argument is known.
  4679. push @{$self->{'expanded_formats_stack'}}, 0;
  4680. push @{$self->{'context_stack'}}, $command
  4681. if ($command eq 'inlineraw');
  4682. }
  4683. }
  4684. print STDERR "OPENED \@$current->{'parent'}->{'cmdname'}, remaining: "
  4685. .(defined($current->{'parent'}->{'remaining_args'}) ? "remaining: $current->{'parent'}->{'remaining_args'}, " : '')
  4686. .($current->{'type'} ? "type: $current->{'type'}" : '')."\n"
  4687. if ($self->{'DEBUG'});
  4688. } elsif ($current->{'parent'}
  4689. and (($current->{'parent'}->{'cmdname'}
  4690. and $current->{'parent'}->{'cmdname'} eq 'multitable')
  4691. or ($current->{'parent'}->{'type'}
  4692. and $current->{'parent'}->{'type'} eq 'def_line'))) {
  4693. push @{$current->{'contents'}},
  4694. { 'type' => 'bracketed', 'contents' => [],
  4695. 'parent' => $current };
  4696. $current = $current->{'contents'}->[-1];
  4697. # we need the line number here in case @ protects end of line
  4698. $current->{'line_nr'} = $line_nr
  4699. if ($current->{'parent'}->{'parent'}->{'type'}
  4700. and $current->{'parent'}->{'parent'}->{'type'} eq 'def_line');
  4701. push @{$current->{'contents'}},
  4702. {'type' => 'empty_spaces_before_argument',
  4703. 'text' => '' };
  4704. print STDERR "BRACKETED in def/multitable\n" if ($self->{'DEBUG'});
  4705. $current->{'extra'}->{'spaces_before_argument'}
  4706. = $current->{'contents'}->[-1];
  4707. # lone braces accepted right in a rawpreformatted
  4708. } elsif ($current->{'type'}
  4709. and $current->{'type'} eq 'rawpreformatted') {
  4710. push @{$current->{'contents'}}, {'text' => '{' };
  4711. # matching braces accepted in a rawpreformatted or math or ignored
  4712. # code
  4713. } elsif ($self->{'context_stack'}->[-1] eq 'math'
  4714. or $self->{'context_stack'}->[-1] eq 'rawpreformatted'
  4715. or $self->{'context_stack'}->[-1] eq 'inlineraw'
  4716. or $self->_ignore_global_commands()) {
  4717. push @{$current->{'contents'}},
  4718. { 'type' => 'bracketed', 'contents' => [],
  4719. 'parent' => $current, 'line_nr' => $line_nr };
  4720. $current = $current->{'contents'}->[-1];
  4721. print STDERR "BRACKETED in math\n" if ($self->{'DEBUG'});
  4722. } else {
  4723. $self->line_error(sprintf($self->__("misplaced %c"),
  4724. ord('{')), $line_nr);
  4725. }
  4726. } elsif ($separator eq '}') {
  4727. _abort_empty_line($self, $current);
  4728. #print STDERR "GGGGG". _print_current ($current);
  4729. if ($current->{'type'} and ($current->{'type'} eq 'bracketed')) {
  4730. $current = $current->{'parent'};
  4731. # the following will not happen for footnote if there is
  4732. # a paragraph withing the footnote
  4733. } elsif ($current->{'parent'}
  4734. and $current->{'parent'}->{'cmdname'}
  4735. and (exists $brace_commands{$current->{'parent'}->{'cmdname'}}
  4736. or $self->{'definfoenclose'}->{$current->{'parent'}->{'cmdname'}})) {
  4737. # for math and footnote out of paragraph
  4738. if ($context_brace_commands{$current->{'parent'}->{'cmdname'}}) {
  4739. my $context_command = pop @{$self->{'context_stack'}};
  4740. if ($context_command ne $current->{'parent'}->{'cmdname'}) {
  4741. $self->_bug_message("context $context_command instead of brace command $current->{'parent'}->{'cmdname'}",
  4742. $line_nr, $current);
  4743. die;
  4744. }
  4745. }
  4746. # first is the arg.
  4747. if ($brace_commands{$current->{'parent'}->{'cmdname'}}
  4748. and ($brace_commands{$current->{'parent'}->{'cmdname'}} > 1
  4749. or $simple_text_commands{$current->{'parent'}->{'cmdname'}})
  4750. and $current->{'parent'}->{'cmdname'} ne 'math') {
  4751. # @inline* always have end spaces considered as normal text
  4752. $self->_isolate_last_space($current)
  4753. unless ($inline_commands{$current->{'parent'}->{'cmdname'}});
  4754. $self->_register_command_arg($current, 'brace_command_contents');
  4755. # Remove empty arguments, as far as possible
  4756. _remove_empty_content_arguments($current);
  4757. }
  4758. my $closed_command = $current->{'parent'}->{'cmdname'};
  4759. print STDERR "CLOSING(brace) \@$current->{'parent'}->{'cmdname'}\n"
  4760. if ($self->{'DEBUG'});
  4761. delete $current->{'parent'}->{'remaining_args'};
  4762. if (defined($brace_commands{$closed_command})
  4763. and $brace_commands{$closed_command} == 0
  4764. and @{$current->{'contents'}}) {
  4765. $self->line_warn(sprintf($self->__(
  4766. "command \@%s does not accept arguments"),
  4767. $closed_command), $line_nr);
  4768. }
  4769. if ($current->{'parent'}->{'cmdname'} eq 'anchor') {
  4770. $current->{'parent'}->{'line_nr'} = $line_nr;
  4771. my $parsed_anchor = _parse_node_manual($current);
  4772. if (_check_node_label($self, $parsed_anchor,
  4773. $current->{'parent'}->{'cmdname'}, $line_nr)) {
  4774. _register_label($self, $current->{'parent'},
  4775. $parsed_anchor, $line_nr);
  4776. if (@{$self->{'regions_stack'}}) {
  4777. $current->{'extra'}->{'region'} = $self->{'regions_stack'}->[-1];
  4778. }
  4779. }
  4780. } elsif ($ref_commands{$current->{'parent'}->{'cmdname'}}) {
  4781. my $ref = $current->{'parent'};
  4782. if (@{$ref->{'args'}}) {
  4783. my @args = @{$ref->{'extra'}->{'brace_command_contents'}};
  4784. if (($closed_command eq 'inforef'
  4785. and !defined($args[0]) and !defined($args[2]))
  4786. or ($closed_command ne 'inforef'
  4787. and !defined($args[0]) and !defined($args[3])
  4788. and !defined($args[4]))) {
  4789. $self->line_warn(sprintf($self->__(
  4790. "command \@%s missing a node or external manual argument"),
  4791. $closed_command), $line_nr);
  4792. } else {
  4793. my $parsed_ref_node = _parse_node_manual($ref->{'args'}->[0]);
  4794. $ref->{'extra'}->{'node_argument'} = $parsed_ref_node
  4795. if (defined($parsed_ref_node));
  4796. if ($closed_command ne 'inforef'
  4797. and !defined($args[3]) and !defined($args[4])
  4798. and !$parsed_ref_node->{'manual_content'}
  4799. and ! _ignore_global_commands($self)) {
  4800. push @{$self->{'internal_references'}}, $ref;
  4801. }
  4802. }
  4803. if (defined($args[1])) {
  4804. my $normalized_cross_ref_name =
  4805. Texinfo::Convert::NodeNameNormalization::normalize_node(
  4806. {'contents' => $args[1]});
  4807. if ($normalized_cross_ref_name !~ /[^-]/) {
  4808. $self->line_warn(sprintf($self->__(
  4809. "in \@%s empty cross reference name after expansion `%s'"),
  4810. $closed_command,
  4811. Texinfo::Convert::Texinfo::convert({'contents' => $args[1]})),
  4812. $line_nr);
  4813. }
  4814. }
  4815. if ($closed_command ne 'inforef' and defined($args[2])) {
  4816. my $normalized_cross_ref_title =
  4817. Texinfo::Convert::NodeNameNormalization::normalize_node({'contents' => $args[2]});
  4818. if ($normalized_cross_ref_title !~ /[^-]/) {
  4819. $self->line_warn(sprintf($self->__(
  4820. "in \@%s empty cross reference title after expansion `%s'"),
  4821. $closed_command,
  4822. Texinfo::Convert::Texinfo::convert({'contents' => $args[2]})),
  4823. $line_nr);
  4824. }
  4825. }
  4826. }
  4827. } elsif ($current->{'parent'}->{'cmdname'} eq 'image') {
  4828. my $image = $current->{'parent'};
  4829. if (!@{$image->{'args'}}
  4830. or !@{$image->{'extra'}->{'brace_command_contents'}}
  4831. or !defined($image->{'extra'}->{'brace_command_contents'}->[0])) {
  4832. $self->line_error(
  4833. $self->__("\@image missing filename argument"), $line_nr);
  4834. }
  4835. } elsif($current->{'parent'}->{'cmdname'} eq 'dotless') {
  4836. my $dotless = $current->{'parent'};
  4837. if (@{$current->{'contents'}}) {
  4838. my $text = $current->{'contents'}->[0]->{'text'};
  4839. if (!defined ($text)
  4840. or ($text ne 'i' and $text ne 'j')) {
  4841. $self->line_error(sprintf($self->
  4842. __("%c%s expects `i' or `j' as argument, not `%s'"),
  4843. ord('@'), $dotless->{'cmdname'},
  4844. Texinfo::Convert::Texinfo::convert($current)), $line_nr);
  4845. }
  4846. }
  4847. } elsif ($explained_commands{$current->{'parent'}->{'cmdname'}}
  4848. or $inline_commands{$current->{'parent'}->{'cmdname'}}) {
  4849. my $current_command = $current->{'parent'};
  4850. if ($inline_commands{$current_command->{'cmdname'}}) {
  4851. if ($current_command->{'cmdname'} eq 'inlineraw') {
  4852. my $context_command = pop @{$self->{'context_stack'}};
  4853. if ($context_command ne $current_command->{'cmdname'}) {
  4854. $self->_bug_message("context $context_command instead of inlineraw $current_command->{'cmdname'}",
  4855. $line_nr, $current);
  4856. die;
  4857. }
  4858. }
  4859. pop @{$self->{'expanded_formats_stack'}};
  4860. }
  4861. if (!@{$current_command->{'args'}}
  4862. or !@{$current_command->{'extra'}->{'brace_command_contents'}}
  4863. or !defined($current_command->{'extra'}->{'brace_command_contents'}->[0])) {
  4864. $self->line_warn(
  4865. sprintf($self->__("\@%s missing first argument"),
  4866. $current_command->{'cmdname'}), $line_nr);
  4867. } else {
  4868. if ($explained_commands{$current_command->{'cmdname'}}) {
  4869. my $normalized_type
  4870. = Texinfo::Convert::NodeNameNormalization::normalize_node(
  4871. {'contents' =>
  4872. $current_command->{'extra'}->{'brace_command_contents'}->[0]});
  4873. $current_command->{'extra'}->{'normalized'} = $normalized_type;
  4874. if (!$current_command->{'extra'}->{'brace_command_contents'}->[1]) {
  4875. if ($self->{'explained_commands'}->{$current_command->{'cmdname'}}->{$normalized_type}) {
  4876. $current_command->{'extra'}->{'explanation_contents'}
  4877. = $self->{'explained_commands'}->{$current_command->{'cmdname'}}->{$normalized_type};
  4878. }
  4879. } elsif (! _ignore_global_commands($self)) {
  4880. $self->{'explained_commands'}->{$current_command->{'cmdname'}}->{$normalized_type}
  4881. = $current_command->{'extra'}->{'brace_command_contents'}->[1];
  4882. }
  4883. }# else {
  4884. # my $argument
  4885. # = Texinfo::Convert::Text::convert({'contents' =>
  4886. # $current_command->{'extra'}->{'brace_command_contents'}->[0]},
  4887. # {Texinfo::Common::_convert_text_options($self)});
  4888. # $current_command->{'extra'}->{'format'} = $argument;
  4889. #}
  4890. }
  4891. } elsif ($current->{'parent'}->{'cmdname'} eq 'errormsg') {
  4892. if (! _ignore_global_commands($self)) {
  4893. my $error_message_text
  4894. = Texinfo::Convert::Text::convert($current,
  4895. {Texinfo::Common::_convert_text_options($self)});
  4896. $self->line_error($error_message_text, $line_nr);
  4897. }
  4898. } elsif (_command_with_command_as_argument($current->{'parent'}->{'parent'})
  4899. and scalar(@{$current->{'contents'}}) == 0) {
  4900. print STDERR "FOR PARENT \@$current->{'parent'}->{'parent'}->{'parent'}->{'cmdname'} command_as_argument braces $current->{'cmdname'}\n" if ($self->{'DEBUG'});
  4901. $current->{'parent'}->{'type'} = 'command_as_argument'
  4902. if (!$current->{'parent'}->{'type'});
  4903. $current->{'parent'}->{'parent'}->{'parent'}->{'extra'}->{'command_as_argument'}
  4904. = $current->{'parent'};
  4905. }
  4906. $self->_register_global_command($current->{'parent'}->{'cmdname'},
  4907. $current->{'parent'}, $line_nr);
  4908. if ($command_ignore_space_after{$current->{'parent'}->{'cmdname'}}) {
  4909. push @{$current->{'parent'}->{'parent'}->{'contents'}},
  4910. {'type' => 'empty_spaces_after_close_brace',
  4911. 'text' => '' };
  4912. }
  4913. $current = $current->{'parent'}->{'parent'};
  4914. $current = $self->_begin_preformatted ($current)
  4915. if ($close_preformatted_commands{$closed_command});
  4916. # lone braces accepted right in a rawpreformatted
  4917. } elsif ($current->{'type'}
  4918. and $current->{'type'} eq 'rawpreformatted') {
  4919. push @{$current->{'contents'}}, {'text' => '}' };
  4920. # footnote caption closing, when there is a paragraph inside.
  4921. } elsif ($context_brace_commands{$self->{'context_stack'}->[-1]}) {
  4922. # closing the context under broader situations
  4923. $current = _end_paragraph($self, $current, $line_nr);
  4924. if ($current->{'parent'}
  4925. and $current->{'parent'}->{'cmdname'}
  4926. and $context_brace_commands{$current->{'parent'}->{'cmdname'}}
  4927. and $current->{'parent'}->{'cmdname'} eq $self->{'context_stack'}->[-1]) {
  4928. my $context_command = pop @{$self->{'context_stack'}};
  4929. if ($context_command ne $current->{'parent'}->{'cmdname'}) {
  4930. $self->_bug_message("context $context_command instead of brace isolated $current->{'parent'}->{'cmdname'}",
  4931. $line_nr, $current);
  4932. die;
  4933. }
  4934. print STDERR "CLOSING(context command) \@$current->{'parent'}->{'cmdname'}\n" if ($self->{'DEBUG'});
  4935. my $closed_command = $current->{'parent'}->{'cmdname'};
  4936. $self->_register_global_command($current->{'parent'}->{'cmdname'},
  4937. $current->{'parent'}, $line_nr);
  4938. $current = $current->{'parent'}->{'parent'};
  4939. $current = $self->_begin_preformatted ($current)
  4940. if ($close_preformatted_commands{$closed_command});
  4941. }
  4942. } else {
  4943. $self->line_error(sprintf($self->__("misplaced %c"),
  4944. ord('}')), $line_nr);
  4945. }
  4946. } elsif ($separator eq ','
  4947. and $current->{'parent'}->{'remaining_args'}) {
  4948. _abort_empty_line ($self, $current);
  4949. if ($brace_commands{$current->{'parent'}->{'cmdname'}}
  4950. and ($brace_commands{$current->{'parent'}->{'cmdname'}} > 1
  4951. or $simple_text_commands{$current->{'parent'}->{'cmdname'}})) {
  4952. $self->_isolate_last_space($current);
  4953. $self->_register_command_arg($current, 'brace_command_contents');
  4954. } else {
  4955. $self->_isolate_last_space($current);
  4956. if (exists $block_commands{$current->{'parent'}->{'cmdname'}}) {
  4957. $self->_register_command_arg($current, 'block_command_line_contents');
  4958. }
  4959. }
  4960. my $type = $current->{'type'};
  4961. $current = $current->{'parent'};
  4962. if ($inline_commands{$current->{'cmdname'}}) {
  4963. if (! $current->{'extra'}->{'format'}) {
  4964. # change the top of the raw_formats_stack now that we know the
  4965. # first arg of the inlineraw
  4966. my $inline_type
  4967. = Texinfo::Convert::Text::convert({'contents' =>
  4968. $current->{'extra'}->{'brace_command_contents'}->[0]},
  4969. {Texinfo::Common::_convert_text_options($self)});
  4970. if ($self->{'expanded_formats_stack'}->[-2]) {
  4971. if ($inline_format_commands{$current->{'cmdname'}}) {
  4972. if ($self->{'expanded_formats_hash'}->{$inline_type}) {
  4973. $self->{'expanded_formats_stack'}->[-1] = $inline_type;
  4974. $current->{'extra'}->{'expand_index'} = 1;
  4975. } else {
  4976. $self->{'expanded_formats_stack'}->[-1] = 0;
  4977. }
  4978. } elsif (($current->{'cmdname'} eq 'inlineifset'
  4979. and exists($self->{'values'}->{$inline_type}))
  4980. or ($current->{'cmdname'} eq 'inlineifclear'
  4981. and ! exists($self->{'values'}->{$inline_type}))) {
  4982. $self->{'expanded_formats_stack'}->[-1]
  4983. = "$current->{'cmdname'} $inline_type";
  4984. $current->{'extra'}->{'expand_index'} = 1;
  4985. } else {
  4986. $self->{'expanded_formats_stack'}->[-1] = 0;
  4987. }
  4988. } else {
  4989. $self->{'expanded_formats_stack'}->[-1] = 0;
  4990. }
  4991. $current->{'extra'}->{'format'} = $inline_type;
  4992. } else {
  4993. # happens for the second arg of inlinefmtifelse
  4994. my $inline_type = $current->{'extra'}->{'format'};
  4995. if ($self->{'expanded_formats_stack'}->[-2]
  4996. and ! ($self->{'expanded_formats_hash'}->{$inline_type})) {
  4997. $self->{'expanded_formats_stack'}->[-1] = $inline_type;
  4998. $current->{'extra'}->{'expand_index'} = 2;
  4999. } else {
  5000. $self->{'expanded_formats_stack'}->[-1] = 0;
  5001. }
  5002. }
  5003. }
  5004. $current->{'remaining_args'}--;
  5005. push @{$current->{'args'}},
  5006. { 'type' => $type, 'parent' => $current, 'contents' => [] };
  5007. #if ($inline_commands{$current->{'cmdname'}}
  5008. # and ! $self->{'expanded_formats_stack'}->[-1]) {
  5009. # $current->{'args'}->[-1]->{'extra'}->{'ignore'} = 1;
  5010. #}
  5011. $current = $current->{'args'}->[-1];
  5012. push @{$current->{'contents'}},
  5013. {'type' => 'empty_spaces_before_argument',
  5014. 'text' => '' };
  5015. } elsif ($separator eq ',' and $current->{'type'}
  5016. and $current->{'type'} eq 'misc_line_arg'
  5017. and $current->{'parent'}->{'cmdname'}
  5018. and $current->{'parent'}->{'cmdname'} eq 'node') {
  5019. $self->line_warn($self->__("superfluous arguments for node"), $line_nr);
  5020. # end of menu node (. must be followed by a space to stop the node).
  5021. } elsif (($separator =~ /[,\t.]/ and $current->{'type'}
  5022. and $current->{'type'} eq 'menu_entry_node')
  5023. or ($separator eq ':' and $current->{'type'}
  5024. and $current->{'type'} eq 'menu_entry_name')) {
  5025. $current = $current->{'parent'};
  5026. push @{$current->{'args'}}, { 'type' => 'menu_entry_separator',
  5027. 'text' => $separator,
  5028. 'parent' => $current };
  5029. } elsif ($separator eq "\f" and $current->{'type'}
  5030. and $current->{'type'} eq 'paragraph') {
  5031. # form feed stops and restart a paragraph.
  5032. $current = $self->_end_paragraph($current);
  5033. push @{$current->{'contents'}}, {'text' => $separator,
  5034. 'type' => 'empty_line',
  5035. 'parent' => $current };
  5036. push @{$current->{'contents'}}, { 'type' => 'empty_line',
  5037. 'text' => '',
  5038. 'parent' => $current };
  5039. } else {
  5040. $current = _merge_text($self, $current, $separator);
  5041. }
  5042. # Misc text except end of line
  5043. } elsif ($line =~ s/^([^{}@,:\t.\n\f]+)//) {
  5044. my $new_text = $1;
  5045. $current = _merge_text($self, $current, $new_text);
  5046. # end of line
  5047. } else {
  5048. if ($self->{'DEBUG'}) {
  5049. print STDERR "END LINE: ". _print_current($current)."\n";
  5050. }
  5051. if ($line =~ s/^(\n)//) {
  5052. $current = _merge_text($self, $current, $1);
  5053. } else {
  5054. if (scalar(@{$self->{'input'}})) {
  5055. $self->_bug_message("Text remaining without normal text but `$line'",
  5056. $line_nr, $current);
  5057. die;
  5058. }
  5059. }
  5060. #print STDERR "END LINE AFTER MERGE END OF LINE: ". _print_current($current)."\n";
  5061. $current = _end_line($self, $current, $line_nr);
  5062. last;
  5063. }
  5064. }
  5065. }
  5066. while (@{$self->{'conditionals_stack'}}) {
  5067. my $end_conditional = pop @{$self->{'conditionals_stack'}};
  5068. $self->line_error(sprintf($self->__("expected \@end %s"), $end_conditional),
  5069. $line_nr);
  5070. }
  5071. $current = _close_commands($self, $current, $line_nr);
  5072. if (@{$self->{'context_stack'}} != 1) {
  5073. # This happens in 2 cases in the tests:
  5074. # @verb not closed on misc commands line
  5075. # def line escaped with @ ending the file
  5076. if ($self->{'DEBUG'}) {
  5077. print STDERR "CONTEXT_STACK no empty end _parse_texi: ".join('|', @{$self->{'context_stack'}})."\n";
  5078. }
  5079. @{$self->{'context_stack'}} = ($self->{'context'});
  5080. }
  5081. if (@{$self->{'expanded_formats_stack'}} != 1) {
  5082. if ($self->{'DEBUG'}) {
  5083. print STDERR "EXPANDED_FORMATS_STACK no empty end _parse_texi: ".join('|', @{$self->{'expanded_formats_stack'}})."\n";
  5084. }
  5085. @{$self->{'expanded_formats_stack'}} = ($self->{'expanded_formats_stack'}->[0]);
  5086. }
  5087. return $root;
  5088. }
  5089. # parse special line @-commands, unmacro, set, clear, clickstyle.
  5090. # Also remove spaces or ignore text, as specified in the misc_commands hash.
  5091. sub _parse_special_misc_command($$$$)
  5092. {
  5093. my $self = shift;
  5094. my $line = shift;
  5095. my $command = shift;
  5096. my $line_nr = shift;
  5097. my $args = [];
  5098. my $has_comment = 0;
  5099. my $remaining;
  5100. if ($command eq 'set') {
  5101. # REVALUE
  5102. #if ($line =~ s/^\s+([\w\-]+)(\s+(.*?))\s*$//) {
  5103. if ($line =~ /^\s+([\w\-][^\s{\\}~`\^+"<>|@]*)(\@(c|comment)((\@|\s+).*)?|[^\S\f]+(.*?))?[^\S\f]*$/) {
  5104. if ($line =~ s/\@(c|comment)((\@|\s+).*)?$//) {
  5105. $has_comment = 1;
  5106. }
  5107. $line =~ /^\s+([\w\-][^\s{\\}~`\^+"<>|@]*)([^\S\f]+(.*?))?[^\S\f]*$/;
  5108. my $name = $1;
  5109. my $arg = $3;
  5110. $arg = '' if (!defined($arg));
  5111. $args = [$name, $arg];
  5112. $self->{'values'}->{$name} = $arg
  5113. unless(_ignore_global_commands($self));
  5114. } elsif ($line !~ /\S/) {
  5115. $self->line_error(sprintf($self->
  5116. __("%c%s requires a name"), ord('@'), $command), $line_nr);
  5117. } else {
  5118. $self->line_error(sprintf($self->
  5119. __("bad name for \@%s"), $command), $line_nr);
  5120. }
  5121. } elsif ($command eq 'clear') {
  5122. # REVALUE
  5123. if ($line =~ /^\s+([\w\-][^\s{\\}~`\^+"<>|@]*)\s*(\@(c|comment)((\@|\s+).*)?)?$/) {
  5124. $args = [$1];
  5125. delete $self->{'values'}->{$1}
  5126. unless(_ignore_global_commands($self));
  5127. $has_comment = 1 if (defined($3));
  5128. #$remaining = $line;
  5129. #$remaining =~ s/^\s+([\w\-]+)\s*(\@(c|comment)((\@|\s+).*)?)?//;
  5130. } elsif ($line !~ /\S/) {
  5131. $self->line_error(sprintf($self->
  5132. __("%c%s requires a name"), ord('@'), $command), $line_nr);
  5133. } else {
  5134. $self->line_error(sprintf($self->
  5135. __("bad name for \@%s"), $command), $line_nr);
  5136. }
  5137. } elsif ($command eq 'unmacro') {
  5138. # REMACRO
  5139. if ($line =~ /^\s+([[:alnum:]][[:alnum:]\-]*)\s*(\@(c|comment)((\@|\s+).*)?)?$/) {
  5140. $args = [$1];
  5141. delete $self->{'macros'}->{$1}
  5142. unless(_ignore_global_commands($self));
  5143. $has_comment = 1 if (defined($3));
  5144. print STDERR "UNMACRO $1\n" if ($self->{'DEBUG'});
  5145. } elsif ($line !~ /\S/) {
  5146. $self->line_error(sprintf($self->
  5147. __("%c%s requires a name"), ord('@'), $command), $line_nr);
  5148. } else {
  5149. $self->line_error(sprintf($self->
  5150. __("bad name for \@%s"), $command), $line_nr);
  5151. }
  5152. } elsif ($command eq 'clickstyle') {
  5153. # REMACRO
  5154. if ($line =~ /^\s+@([[:alnum:]][[:alnum:]\-]*)({})?\s*/) {
  5155. $args = ['@'.$1];
  5156. $self->{'clickstyle'} = $1
  5157. unless(_ignore_global_commands($self));
  5158. $remaining = $line;
  5159. $remaining =~ s/^\s+@([[:alnum:]][[:alnum:]\-]*)({})?\s*(\@(c|comment)((\@|\s+).*)?)?//;
  5160. $has_comment = 1 if (defined($4));
  5161. } else {
  5162. $self->line_error (sprintf($self->__(
  5163. "\@%s should only accept a \@-command as argument, not `%s'"),
  5164. $command, $line), $line_nr);
  5165. }
  5166. } else {
  5167. die $self->_bug_message("Unknown special command $command", $line_nr);
  5168. }
  5169. if (defined($remaining)) {
  5170. chomp($remaining);
  5171. if ($remaining ne '') {
  5172. $self->line_warn(sprintf($self->__(
  5173. "remaining argument on \@%s line: %s"),
  5174. $command, $remaining), $line_nr);
  5175. }
  5176. }
  5177. return ($args, $has_comment);
  5178. }
  5179. sub _trim_spaces_comment_from_content($)
  5180. {
  5181. Texinfo::Common::trim_spaces_comment_from_content($_[0]);
  5182. }
  5183. # at the end of a @-command line with arguments, parse the resulting
  5184. # text, to collect aliases, definfoenclose and collect errors on
  5185. # wrong arguments.
  5186. sub _parse_line_command_args($$$)
  5187. {
  5188. my $self = shift;
  5189. my $line_command = shift;
  5190. my $line_nr = shift;
  5191. my $args;
  5192. my $command = $line_command->{'cmdname'};
  5193. my $arg = $line_command->{'args'}->[0];
  5194. if ($self->{'DEBUG'}) {
  5195. print STDERR "MISC ARGS \@$command\n";
  5196. if (@{$arg->{'contents'}}) {
  5197. my $idx = 0;
  5198. foreach my $content (@{$arg->{'contents'}}) {
  5199. my $name = '';
  5200. $name = '@' . $content->{'cmdname'} if ($content->{'cmdname'});
  5201. my $type = ', t: ';
  5202. $type .= $content->{'type'} if ($content->{'type'});
  5203. my $text = ', ';
  5204. $type .= $content->{'text'} if ($content->{'text'});
  5205. print STDERR " -> $idx $name $type $text\n";
  5206. $idx++;
  5207. }
  5208. }
  5209. }
  5210. my @contents = @{$arg->{'contents'}};
  5211. _trim_spaces_comment_from_content(\@contents);
  5212. if (! @contents) {
  5213. $self->_command_error($line_command, $line_nr,
  5214. $self->__("\@%s missing argument"), $command);
  5215. $line_command->{'extra'}->{'missing_argument'} = 1;
  5216. return undef;
  5217. }
  5218. if (@contents > 1
  5219. or (!defined($contents[0]->{'text'}))) {
  5220. $self->line_error (sprintf($self->__("superfluous argument to \@%s"),
  5221. $command), $line_nr);
  5222. }
  5223. return undef if (!defined($contents[0]->{'text'}));
  5224. my $line = $contents[0]->{'text'};
  5225. if ($command eq 'alias') {
  5226. # REMACRO
  5227. if ($line =~ s/^([[:alnum:]][[:alnum:]-]*)(\s*=\s*)([[:alnum:]][[:alnum:]-]*)$//) {
  5228. my $new_command = $1;
  5229. my $existing_command = $3;
  5230. $args = [$1, $3];
  5231. $self->{'aliases'}->{$new_command} = $existing_command
  5232. unless (_ignore_global_commands($self));
  5233. if (exists($block_commands{$existing_command})) {
  5234. $self->line_warn(sprintf($self->
  5235. __("environment command %s as argument to \@%s"),
  5236. $existing_command, $command), $line_nr);
  5237. }
  5238. } else {
  5239. $self->line_error(sprintf($self->
  5240. __("bad argument to \@%s"), $command), $line_nr);
  5241. }
  5242. } elsif ($command eq 'definfoenclose') {
  5243. # REMACRO
  5244. if ($line =~ s/^([[:alnum:]][[:alnum:]\-]*)\s*,\s*([^\s,]*)\s*,\s*([^\s,]*)$//) {
  5245. $args = [$1, $2, $3 ];
  5246. $self->{'definfoenclose'}->{$1} = [ $2, $3 ]
  5247. unless (_ignore_global_commands($self));
  5248. print STDERR "DEFINFOENCLOSE \@$1: $2, $3\n" if ($self->{'DEBUG'});
  5249. } else {
  5250. $self->line_error(sprintf($self->
  5251. __("bad argument to \@%s"), $command), $line_nr);
  5252. }
  5253. } elsif ($command eq 'columnfractions') {
  5254. my @possible_fractions = split (/\s+/, $line);
  5255. if (!@possible_fractions) {
  5256. $self->line_error (sprintf($self->__("empty \@%s"), $command),
  5257. $line_nr);
  5258. } else {
  5259. foreach my $fraction (@possible_fractions) {
  5260. if ($fraction =~ /^(\d*\.\d+)|(\d+)\.?$/) {
  5261. push @$args, $fraction;
  5262. } else {
  5263. $self->line_error (sprintf($self->
  5264. __("column fraction not a number: %s"),
  5265. $fraction), $line_nr);
  5266. }
  5267. }
  5268. }
  5269. } elsif ($command eq 'sp') {
  5270. if ($line =~ /^([0-9]+)$/) {
  5271. $args = [$1];
  5272. } else {
  5273. $self->line_error(sprintf($self->__("\@sp arg must be numeric, not `%s'"),
  5274. $line), $line_nr);
  5275. }
  5276. } elsif ($command eq 'defindex' || $command eq 'defcodeindex') {
  5277. # REMACRO
  5278. if ($line =~ /^([[:alnum:]][[:alnum:]\-]*)$/) {
  5279. my $name = $1;
  5280. if ($forbidden_index_name{$name}) {
  5281. $self->line_error(sprintf($self->
  5282. __("reserved index name %s"),$name), $line_nr);
  5283. } else {
  5284. my $in_code = 0;
  5285. $in_code = 1 if ($command eq 'defcodeindex');
  5286. $args = [$name];
  5287. if (! _ignore_global_commands($self)) {
  5288. $self->{'index_names'}->{$name} = {'in_code' => $in_code};
  5289. $self->_register_index_commands($name);
  5290. }
  5291. }
  5292. } else {
  5293. $self->line_error(sprintf($self->
  5294. __("bad argument to \@%s: %s"), $command, $line), $line_nr);
  5295. }
  5296. } elsif ($command eq 'synindex' || $command eq 'syncodeindex') {
  5297. # REMACRO
  5298. if ($line =~ /^([[:alnum:]][[:alnum:]\-]*)\s+([[:alnum:]][[:alnum:]\-]*)$/) {
  5299. my $index_from = $1;
  5300. my $index_to = $2;
  5301. $self->line_error(sprintf($self->__("unknown source index in \@%s: %s"),
  5302. $command, $index_from), $line_nr)
  5303. unless $self->{'index_names'}->{$index_from};
  5304. $self->line_error(sprintf($self->__("unknown destination index in \@%s: %s"),
  5305. $command, $index_to), $line_nr)
  5306. unless $self->{'index_names'}->{$index_to};
  5307. if ($self->{'index_names'}->{$index_from}
  5308. and $self->{'index_names'}->{$index_to}) {
  5309. my $current_to = $index_to;
  5310. # find the merged indices recursively avoiding loops
  5311. while ($current_to ne $index_from
  5312. and $self->{'merged_indices'}->{$current_to}) {
  5313. $current_to = $self->{'merged_indices'}->{$current_to};
  5314. }
  5315. if ($current_to ne $index_from) {
  5316. my $index_from_info = $self->{'index_names'}->{$index_from};
  5317. my $index_to_info = $self->{'index_names'}->{$current_to};
  5318. my $in_code = 0;
  5319. $in_code = 1 if ($command eq 'syncodeindex');
  5320. if (! _ignore_global_commands($self)) {
  5321. $self->{'merged_indices'}->{$index_from} = $current_to;
  5322. $index_from_info->{'in_code'} = $in_code;
  5323. foreach my $contained_index (keys %{$index_from_info->{'contained_indices'}}) {
  5324. $index_to_info->{'contained_indices'}->{$contained_index} = 1;
  5325. $self->{'index_names'}->{$contained_index}->{'merged_in'} = $current_to;
  5326. }
  5327. $index_from_info->{'merged_in'} = $current_to;
  5328. $index_to_info->{'contained_indices'}->{$index_from} = 1;
  5329. }
  5330. $args = [$index_from, $index_to];
  5331. } else {
  5332. $self->line_warn(sprintf($self->__(
  5333. "\@%s leads to a merging of %s in itself, ignoring"),
  5334. $command, $index_from), $line_nr);
  5335. }
  5336. }
  5337. } else {
  5338. $self->line_error(sprintf($self->__("bad argument to \@%s: %s"),
  5339. $command, $line), $line_nr);
  5340. }
  5341. } elsif ($command eq 'printindex') {
  5342. # REMACRO
  5343. if ($line =~ /^([[:alnum:]][[:alnum:]\-]*)$/) {
  5344. my $name = $1;
  5345. if (!exists($self->{'index_names'}->{$name})) {
  5346. $self->line_error(sprintf($self->__("unknown index `%s' in \@printindex"),
  5347. $name), $line_nr);
  5348. } else {
  5349. if ($self->{'merged_indices'}->{$name}) {
  5350. $self->line_warn(sprintf($self->__(
  5351. "printing an index `%s' merged in another one `%s'"),
  5352. $name, $self->{'merged_indices'}->{$name}),
  5353. $line_nr);
  5354. }
  5355. if (!defined($self->{'current_node'})
  5356. and !defined($self->{'current_section'})
  5357. and !scalar(@{$self->{'regions_stack'}})) {
  5358. $self->line_warn(sprintf($self->__(
  5359. "printindex before document beginning: \@printindex %s"),
  5360. $name), $line_nr);
  5361. }
  5362. $args = [$name];
  5363. }
  5364. } else {
  5365. $self->line_error(sprintf($self->
  5366. __("bad argument to \@%s: %s"), $command, $line), $line_nr);
  5367. }
  5368. } elsif (grep {$_ eq $command} ('everyheadingmarks', 'everyfootingmarks',
  5369. 'evenheadingmarks', 'oddheadingmarks',
  5370. 'evenfootingmarks', 'oddfootingmarks')) {
  5371. if ($line eq 'top' or $line eq 'bottom') {
  5372. $args = [$line];
  5373. } else {
  5374. $self->line_error(sprintf($self->__(
  5375. "\@%s arg must be `top' or `bottom', not `%s'"),
  5376. $command, $line), $line_nr);
  5377. }
  5378. } elsif ($command eq 'fonttextsize') {
  5379. if ($line eq '10' or $line eq '11') {
  5380. $args = [$line];
  5381. } else {
  5382. $self->line_error(sprintf($self->__(
  5383. "Only \@%s 10 or 11 is supported, not `%s'"),
  5384. $command, $line), $line_nr);
  5385. }
  5386. } elsif ($command eq 'footnotestyle') {
  5387. if ($line eq 'separate' or $line eq 'end') {
  5388. $args = [$line];
  5389. } else {
  5390. $self->line_error(sprintf($self->__(
  5391. "\@%s arg must be `separate' or `end', not `%s'"),
  5392. $command, $line), $line_nr);
  5393. }
  5394. } elsif ($command eq 'setchapternewpage') {
  5395. if ($line eq 'on' or $line eq 'off' or $line eq 'odd') {
  5396. $args = [$1];
  5397. } else {
  5398. $self->line_error(sprintf($self->__(
  5399. "\@%s arg must be `on', `off' or `odd', not `%s'"),
  5400. $command, $line), $line_nr);
  5401. }
  5402. } elsif ($command eq 'need') { # only a warning
  5403. if (($line =~ /^([0-9]+(\.[0-9]*)?)$/) or
  5404. ($line =~ /^(\.[0-9]+)$/)) {
  5405. $args = [$1];
  5406. } else {
  5407. $self->line_error(sprintf($self->__("bad argument to \@%s: %s"),
  5408. $command, $line), $line_nr);
  5409. }
  5410. } elsif ($command eq 'paragraphindent') {
  5411. if ($line =~ /^([\w\-]+)$/) {
  5412. my $value = $1;
  5413. if ($value =~ /^([0-9]+)$/ or $value eq 'none' or $value eq 'asis') {
  5414. $args = [$1];
  5415. } else {
  5416. $self->line_error(sprintf($self->__(
  5417. "\@paragraphindent arg must be numeric/`none'/`asis', not `%s'"),
  5418. $value), $line_nr);
  5419. }
  5420. } else {
  5421. $self->line_error(sprintf($self->__(
  5422. "\@paragraphindent arg must be numeric/`none'/`asis', not `%s'"),
  5423. $line), $line_nr);
  5424. }
  5425. } elsif ($command eq 'firstparagraphindent') {
  5426. if ($line eq 'none' or $line eq 'insert') {
  5427. $args = [$line];
  5428. } else {
  5429. $self->line_error(sprintf($self->__(
  5430. "\@firstparagraphindent arg must be `none' or `insert', not `%s'"),
  5431. $line), $line_nr);
  5432. }
  5433. } elsif ($command eq 'exampleindent') {
  5434. if ($line =~ /^([0-9]+)/) {
  5435. $args = [$1];
  5436. } elsif ($line =~ /^(asis)$/) {
  5437. $args = [$1];
  5438. } else {
  5439. $self->line_error(sprintf($self->__(
  5440. "\@exampleindent arg must be numeric/`asis', not `%s'"),
  5441. $line), $line_nr);
  5442. }
  5443. } elsif ($command eq 'frenchspacing'
  5444. or $command eq 'xrefautomaticsectiontitle'
  5445. or $command eq 'codequoteundirected'
  5446. or $command eq 'codequotebacktick'
  5447. or $command eq 'deftypefnnewline') {
  5448. if ($line eq 'on' or $line eq 'off') {
  5449. $args = [$line];
  5450. } else {
  5451. $self->line_error(sprintf($self->__("expected \@%s on or off, not `%s'"),
  5452. $command, $line), $line_nr);
  5453. }
  5454. } elsif ($command eq 'kbdinputstyle') {
  5455. if ($line eq 'code' or $line eq 'example' or $line eq 'distinct') {
  5456. $self->{'kbdinputstyle'} = $line
  5457. unless (_ignore_global_commands($self));
  5458. $args = [$line];
  5459. } else {
  5460. $self->line_error(sprintf($self->__(
  5461. "\@kbdinputstyle arg must be `code'/`example'/`distinct', not `%s'"),
  5462. $line), $line_nr);
  5463. }
  5464. } elsif ($command eq 'allowcodebreaks') {
  5465. if ($line eq 'true' or $line eq 'false') {
  5466. $args = [$line];
  5467. } else {
  5468. $self->line_error(sprintf($self->__(
  5469. "\@allowcodebreaks arg must be `true' or `false', not `%s'"),
  5470. $line), $line_nr);
  5471. }
  5472. } elsif ($command eq 'urefbreakstyle') {
  5473. if ($line eq 'after' or $line eq 'before' or $line eq 'none') {
  5474. $args = [$line];
  5475. } else {
  5476. $self->line_error(sprintf($self->__(
  5477. "\@urefbreakstyle arg must be `after'/`before'/`none', not `%s'"),
  5478. $line), $line_nr);
  5479. }
  5480. } elsif ($command eq 'headings') {
  5481. if ($line eq 'off' or $line eq 'on' or $line eq 'single'
  5482. or $line eq 'double' or $line eq 'singleafter' or $line eq 'doubleafter') {
  5483. $args = [$line];
  5484. } else {
  5485. $self->line_error(sprintf($self->__("bad argument to \@%s: %s"),
  5486. $command, $line), $line_nr);
  5487. }
  5488. }
  5489. return $args;
  5490. }
  5491. 1;
  5492. __END__
  5493. =head1 NAME
  5494. Texinfo::Parser - Parse Texinfo code in a Perl tree
  5495. =head1 SYNOPSIS
  5496. use Texinfo::Parser;
  5497. my $parser = Texinfo::Parser::parser();
  5498. my $tree = $parser->parse_texi_file("somefile.texi");
  5499. my ($errors, $errors_count) = $parser->errors();
  5500. foreach my $error_message (@$errors) {
  5501. warn $error_message->{'error_line'};
  5502. }
  5503. my ($index_names, $merged_indices_hash)
  5504. = $parser->indices_information();
  5505. my $float_types_arrays = $parser->floats_information();
  5506. my $internal_references_array
  5507. = $parser->internal_references_information();
  5508. # An hash reference on normalized node/float/anchor names
  5509. my $labels_information = $parser->labels_information();
  5510. # A hash reference, keys are @-command names, value is an
  5511. # array reference holding all the corresponding @-commands.
  5512. my $global_commands_information = $parser->global_commands_information();
  5513. # a hash reference on some document informations (encodings,
  5514. # input file name, dircategory and direntry list, for exampel).
  5515. my $global_informations = $parser->global_informations();
  5516. =head1 DESCRIPTION
  5517. Texinfo::Parser will parse Texinfo text into a perl tree. In one pass
  5518. it expands user defined @-commands, conditionals (@ifset, @ifinfo...)
  5519. and @value and constructs the tree. Some extra information is gathered
  5520. while doing the tree, for example the block command associated with @end,
  5521. the number of row in a multitable, the node associated with a section.
  5522. =head1 METHODS
  5523. No method is exported in the default case. The module allows both
  5524. an object oriented syntax, or traditional function, with the parser
  5525. as an opaque data structure given in argument to every function.
  5526. =head2 Initialization
  5527. The following method is used to construct a new C<Texinfo::Parser> object:
  5528. =over
  5529. =item $parser = Texinfo::Parser::parser($options);
  5530. This method creates a new parser. The options may be provided as a hash
  5531. reference. There are two types of options. The first type of options
  5532. change the way the parser behave, they are described right here. The
  5533. other type of options allow to give to the parser some information as if
  5534. it came from texinfo code, for example allow to set aliases (as with
  5535. C<@alias>), values (as with C<@set>), merged indices (as with
  5536. C<@synindex>). These options are described below in L</Texinfo Parser options>.
  5537. =over
  5538. =item expanded_formats
  5539. An array reference of the output formats for which C<@ifI<FORMAT>>
  5540. conditional blocks should be expanded. Default is empty.
  5541. The raw block formats (within C<@html> blocks, for example) are
  5542. always kept.
  5543. =item gettext
  5544. If set, the function reference is used to translate error and warning
  5545. messages. It takes a string as argument and returns a string. The default
  5546. function returns the error message as is.
  5547. =item GLOBAL_COMMANDS
  5548. The associated value is a reference on an array. All the commands in the
  5549. array are collected during parsing. They are afterwards available
  5550. through L<global_informations|/$info = global_informations($parser)>.
  5551. =item include_directories
  5552. An array reference of directories in which C<@include> files should be
  5553. searched for. Default contains the working directory, F<.>.
  5554. =item INLINE_INSERTCOPYING
  5555. If set, C<@insertcopying> is replaced by the C<@copying> content as if
  5556. C<@insertcopying> was a user-defined macro. In the default case, it is
  5557. considered to be a simple @-command and kept as is in the tree.
  5558. =item IGNORE_BEFORE_SETFILENAME
  5559. If set, and C<@setfilename> exists, everything before C<@setfilename>
  5560. is put in a special container type, @C<preamble_before_setfilename>.
  5561. This option is set in the default case.
  5562. =item IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME
  5563. If set, spaces after an @-commande name that take braces are ignored.
  5564. Default on.
  5565. =item MACRO_BODY_IGNORES_LEADING_SPACE
  5566. If set, leading spaces are stripped from user defined macro bodies.
  5567. =item MAX_MACRO_CALL_NESTING
  5568. Maximal number of nested user-defined macro calls. Default is 100000.
  5569. =item SHOW_MENU
  5570. If false, no menu related error are reported. Default is true.
  5571. =begin :comment
  5572. Used by Sectioning only
  5573. =item TOP_NODE_UP
  5574. Text for the up node of the Top node. The default is C<(dir)>. The
  5575. string may contain @-commands.
  5576. =end :comment
  5577. =back
  5578. =back
  5579. =head2 Parsing Texinfo text
  5580. There are three methods that may be called to parse some Texinfo code,
  5581. C<parse_texi_line> for a line, C<parse_texi_text> for a text fragment,
  5582. and C<parse_texi_file> for a file.
  5583. For all those functions, if the I<$parser> argument is undef, a new
  5584. parser object is generated to parse the line, otherwise the parser given
  5585. in argument is used to parse into a tree.
  5586. When C<parse_texi_text> is used, the resulting tree is rooted at
  5587. a C<root_line> type container. Otherwise, the resulting tree should be
  5588. rooted at a C<text_root> type container if it do not contain nodes or
  5589. sections, at a C<document_root> type container otherwise.
  5590. =over
  5591. =item $tree = parse_texi_line($parser, $text, $first_line_number, $file_name, $macro_name, $fixed_line_number)
  5592. This function is used to parse a short fragment of Texinfo code.
  5593. I<$text> may be either an array reference of lines, or a text.
  5594. The other arguments are optional and allow to specify the position
  5595. information of the Texinfo code. I<$first_line_number> is the line number
  5596. of the first text line. I<$file_name> is the name of the file the
  5597. text comes from. I<$macro> is for the user-defined macro name the text
  5598. is expanded from. If I<$fixed_line_number> is set, the line number is
  5599. not increased for the different lines, as if the text was the expansion
  5600. of a macro.
  5601. =item $tree = parse_texi_text ($parser, $text, $line_numbers_specification, $file_name, $macro_name, $fixed_line_number)
  5602. This function is used to parse some Texinfo text.
  5603. I<$text> may be either an array reference of lines, or a text.
  5604. The other arguments are optional and allow to specify the position
  5605. information of the Texinfo code. There are two distinct cases for
  5606. I<$line_numbers_specification>.
  5607. =over
  5608. =item 1.
  5609. If it is an array reference, it is considered to hold objects describing
  5610. the position information of each text lines.
  5611. =item 2.
  5612. If I<$line_numbers_specification> is a scalar, it is the line number of
  5613. the first text line. In that case (like for C<parse_texi_text>),
  5614. I<$file_name> is the name of the file the text comes from.
  5615. I<$macro> is for the user-defined macro name the text
  5616. is expanded from. If I<$fixed_line_number> is set, the line number is
  5617. not increased for the different lines, as if the text was the expansion
  5618. of a macro.
  5619. =back
  5620. =item $tree = parse_texi_file($parser, $file_name)
  5621. The file with name I<$file_name> is considered to be a Texinfo file and
  5622. is parsed into a tree.
  5623. undef is returned if the file couldn't be read.
  5624. =back
  5625. The errors collected during the tree parsing are available through the
  5626. C<errors> method. This method comes from C<Texinfo::Report>, and is
  5627. described in L<errors|Texinfo::Report/($error_warnings_list, $error_count) = errors ($converter)>.
  5628. =head2 Getting informations on the document
  5629. After parsing some informations about the Texinfo code that was processed
  5630. are available from the parser.
  5631. Some global informations is available through C<global_informations>
  5632. =over
  5633. =item $info = global_informations($parser)
  5634. The I<$info> returned is a hash reference. The possible keys are
  5635. =over
  5636. =item input_file_name
  5637. The name of the main Texinfo input file.
  5638. =item input_encoding_name
  5639. =item input_perl_encoding
  5640. C<input_encoding_name> string is the encoding name used for the
  5641. Texinfo code.
  5642. C<input_perl_encoding> string is a corresponding perl encoding name.
  5643. =item dircategory_direntry
  5644. An array of successive C<@dircategory> and C<@direntry> as they appear
  5645. in the document.
  5646. =item unassociated_menus
  5647. An array of menus that are not associated with a node.
  5648. =back
  5649. =back
  5650. Some command lists are available, such that it is possible to go through
  5651. the corresponding tree elements without walking the tree. They are
  5652. available through C<global_commands_information>
  5653. =over
  5654. =item $commands = global_commands_information($parser)
  5655. I<$commands> is an hash reference. The keys are @-command names. The
  5656. associated values are array references containing all the corresponding
  5657. tree elements.
  5658. =back
  5659. All the @-commands that have an associated label, that can be the
  5660. target of cross references, C<@node>, C<@anchor> and C<@float> with
  5661. label have a normalized name associated, constructed as described in the
  5662. B<HTML Xref> node in the Texinfo manual. Those normalized labels and
  5663. the association with @-commands is available through C<labels_information>:
  5664. =over
  5665. =item $labels_information = labels_information($parser)
  5666. I<$labels_information> is a hash reference whose keys are normalized
  5667. labels, and the associated value is the corresponding @-command.
  5668. =back
  5669. Information on C<@float> is also available, grouped by type of
  5670. floats, each type correponding to potential C<@listoffloats>.
  5671. This information is available through the method C<floats_information>.
  5672. =over
  5673. =item $float_types = floats_information($parser)
  5674. I<$float_types> is a hash reference whose keys are normalized float
  5675. types (the first float argument, or the C<@listoffloats> argument).
  5676. The normalization is the same than for node names. The value is the list
  5677. of float tree elements appearing in the texinfo document.
  5678. =back
  5679. Internal references, that is, @-commands that refers to node, anchors
  5680. or floats within the document are also available:
  5681. =over
  5682. =item $internal_references_array = internal_references_information($parser);
  5683. The function returns a list of cross reference commands referring to
  5684. the same document.
  5685. =back
  5686. Information about defined indices, merged indices and index entries is
  5687. also available through the C<indices_information> method.
  5688. =over
  5689. =item indices_information
  5690. ($index_names, $merged_indices_hash)
  5691. = indices_information($parser);
  5692. The index names is a hash reference. The keys are
  5693. =over
  5694. =item in_code
  5695. 1 if the index entries should be formatted as code, 0 in the opposite case.
  5696. =item name
  5697. The index name.
  5698. =item prefix
  5699. An array reference of prefix associated to the index.
  5700. =item merged_in
  5701. In case the index is merged to another index, this key holds the name of
  5702. the index the index is merged into. It takes into account indirectly
  5703. merged indices.
  5704. =item contained_indices
  5705. An hash reference holding names of indices that are merged to the index,
  5706. including itself. It also contains indirectly merged indices. This key
  5707. is present even if the index is itself later merged to another index.
  5708. =item index_entries
  5709. An array reference containing index entry structures for index entries
  5710. associated with the index. The index entry could be associated to
  5711. @-commands like C<@cindex>, or C<@item> in C<@vtable>, or definition
  5712. commands entries like C<@deffn>.
  5713. The keys of the index entry structures are
  5714. =over
  5715. =item index_name
  5716. The index name.
  5717. =item index_prefix
  5718. The associated index prefix.
  5719. =item index_at_command
  5720. The name of the @-command associated with the index entry.
  5721. =item index_type_command
  5722. The @-command associated with the index entry allowing to
  5723. find the index type.
  5724. =item content
  5725. An array reference corresponding to the index entry content.
  5726. =item content_normalized
  5727. An array reference corresponding to the index entry content, independent
  5728. of the current language.
  5729. =item command
  5730. The element in the parsed tree associated with the @-command holding the
  5731. index entry.
  5732. =item node
  5733. The node in the parsed tree containing the index entry.
  5734. =item number
  5735. The number of the index entry.
  5736. =item region
  5737. The region command (C<@copying>, C<@titlepage>) containing the index entry,
  5738. if it is in such an environement.
  5739. =back
  5740. =back
  5741. The following shows the references corresponding with the default indexes
  5742. I<cp> and I<fn>, the I<fn> index having its entries formatted as code and
  5743. the indices corresponding to the following texinfo
  5744. @defindex some
  5745. @defcodeindex code
  5746. $index_names = {'cp' => {'name' => 'cp', 'in_code' => 0,
  5747. 'prefix' => ['c', 'cp']},
  5748. 'fn' => {'name' => 'fn', 'in_code' => 1,
  5749. 'prefix' => ['f', 'fn']},
  5750. 'some' => {'in_code' => 0},
  5751. 'code' => {'in_code' => 1}};
  5752. If C<name> is not set, it is set to the index name. If C<prefix> is
  5753. not set, it is set to an array containing the index name.
  5754. I<$merged_indices_hash> is a hash reference, the key is an index
  5755. name merged in the value.
  5756. =back
  5757. =head2 Texinfo Parser options
  5758. Setting those options is the same as seeing some Texinfo constructs in the
  5759. document.
  5760. =over
  5761. =item aliases
  5762. A hash reference. The key is a command name, the value is the alias, as
  5763. could be set by C<@alias>.
  5764. =item clickstyle
  5765. A string, the command name associated with C<@clickstyle>.
  5766. =item documentlanguage
  5767. A string corresponding to a document language set by C<@documentlanguage>.
  5768. =item explained_commands
  5769. A hash reference of explained commands (currently abbr or acronym).
  5770. The value is also a hash reference. The key of this hash is a normalized
  5771. first argument of these commands, the value is a content array
  5772. corresponding to the explanation associated with this first argument.
  5773. For example giving as an option:
  5774. 'explained_commands'
  5775. => {'acronym' => {'EU' => [{'text' => 'European Union'}]}
  5776. is the same as having the following texinfo code in the document:
  5777. @acronym{EU, European Union}
  5778. =item INPUT_ENCODING_NAME
  5779. =item INPUT_PERL_ENCODING
  5780. C<INPUT_ENCODING_NAME> string is the encoding name as set
  5781. by C<@documentencoding>.
  5782. C<INPUT_PERL_ENCODING> string is a corresponding perl encoding name.
  5783. In general those two strings should be set simultaneously.
  5784. =item indices
  5785. If it is a hash reference, the keys are index names, the values are
  5786. index prefix hash references. The index prefix hash reference values are
  5787. prefix, the value is set if the corresponding index entries should be
  5788. formatted as if in C<@code>. An example is as L</indices_information>.
  5789. If it is an array reference, it is a list of index names, as if they were
  5790. entered as
  5791. @defindex name
  5792. =item kbdinputstyle
  5793. A string, the C<@kbdinputstyle> style.
  5794. =item labels
  5795. A hash reference. Keys are normalized node names as described in the
  5796. B<HTML Xref> node in the Texinfo manual. Instead of a node, it may also
  5797. be a float label or an anchor name. The value is the corresponding
  5798. @-command element in the tree.
  5799. =item macros
  5800. The associated hash reference has as key user-defined macro names. The
  5801. value is the reference on a macro definition element as obtained by
  5802. the Parser when parsing a C<@macro>. For example
  5803. @macro mymacro{arg}
  5804. coucou \arg\ after arg
  5805. @end macro
  5806. Is associated to a macro definition element
  5807. {'cmdname' => 'macro',
  5808. 'args' => [{'text' => 'mymacro', 'type' => 'macro_name'},
  5809. {'text' => 'arg', 'type' => 'macro_arg}],
  5810. 'contents' => [{'text' => "coucou \arg\ after arg\n", 'type' => 'raw'}],
  5811. 'extra' => {'arg_line' => " mymacro{arg}\n",
  5812. 'macrobody' => "coucou \arg\ after arg\n"}}
  5813. = item merged_indices
  5814. The associated hash reference holds merged indices information, each key
  5815. is merged in the value. Same as setting C<@synindex> or C<syncodeindex>.
  5816. =item novalidate
  5817. If set, it is as if C<@novalidate> was set in the document.
  5818. =item sections_level
  5819. Modifier of the sections level. Same as calling C<@lowersections> or
  5820. C<@raisesections>.
  5821. =item values
  5822. A hash reference. Keys are names, values are the corresponding values.
  5823. Same as values set by C<@set>.
  5824. =back
  5825. =head1 TEXINFO TREE
  5826. A Texinfo tree element (called element because node is overloaded in
  5827. the Texinfo world) is an hash reference. There are three main category
  5828. of tree element. Tree elements associated with an @-command have a
  5829. C<cmdname> key holding the @-command name. Tree element corresponding
  5830. to text fragments have a C<text> key holding the corresponding text.
  5831. The last category corresponds to other containers (hereafter called
  5832. containers). In most case these containers have a C<type> key holding
  5833. their name. Text fragments and @-command elements may also have an
  5834. associated type when such information is needed.
  5835. The children of @-command or container elements are in the array
  5836. correponding with the C<args> key or with the C<contents> key. The
  5837. C<args> key is for arguments of @-commands, in braces or on the @-command
  5838. line. C<args> is also used for the elements of a menu entry, as a menu
  5839. entry is well structured with a limited number of arguments.
  5840. The C<contents> key array holds the contents of the texinfo
  5841. code appearing within a block @-command, within a container,
  5842. within a C<@node> or sectioning @-command.
  5843. Another important key for the elements is the C<extra> key which is
  5844. associated to a hash reference and holds all kinds of informations gathered
  5845. during the parsing and that may help with the conversion.
  5846. =head2 Element keys
  5847. =over
  5848. =item cmdname
  5849. The command name of @-command elements.
  5850. =item text
  5851. The text fragment of text elements.
  5852. =item type
  5853. The type of the element. For C<@verb> it is the delimiter. But otherwise
  5854. it is the type of element considered as a container. Frequent types
  5855. encountered are I<paragraph> for a paragraph container,
  5856. I<brace_command_arg> for the container holding the brace @-commands
  5857. contents, I<misc_line_arg> and I<block_line_arg> contain the arguments
  5858. appearing on the line of @-commands. Text fragments may have a type to
  5859. give an information of the kind of text fragment, for example
  5860. C<empty_spaces_before_argument> is associated to spaces after a brace
  5861. opening and before the argument. Many @-commands elements don't have
  5862. a type associated.
  5863. =item args
  5864. Arguments in braces or on @-command line, and the elements of a menu entry.
  5865. =item contents
  5866. The Texinfo appearing in the element. For block commands, other
  5867. containers, C<@node> and sectioning commands.
  5868. =item parent
  5869. The parent element.
  5870. =item line_nr
  5871. An hash reference corresponding to information on the location of the
  5872. element in the Texinfo input manual. It should only be available for
  5873. @-command elements, and only for @-commands that are considered to be
  5874. complex enough that the location in the document is needed, for example
  5875. to prepare an error message.
  5876. The keys of the line number hash references are
  5877. =over
  5878. =item line_nr
  5879. The line number of the @-command.
  5880. =item file_name
  5881. The file name where @-command appeared.
  5882. =item macro
  5883. The user macro name the @-command is expanded from.
  5884. =back
  5885. =item extra
  5886. A hash reference holding any additional information.
  5887. See L</Information available in the extra key>.
  5888. =back
  5889. =head2 The containers and types
  5890. Some types are associated with @-commands. As said above, for C<@verb>
  5891. the type is the delimiter. For a C<@value> command that is not
  5892. expanded because there is no corresponding value set, the type is the
  5893. value argument string.
  5894. The following types also happen for @-commands:
  5895. =over
  5896. =item def_line
  5897. This type may be associated with a definition command with a x form,
  5898. like C<@defunx>, C<@defvrx>. For the form without x, the associated
  5899. I<def_line> is the first C<contents> element. It is described in more
  5900. details below.
  5901. =item command_as_argument
  5902. This is the type of a command given in argument of C<@itemize>,
  5903. C<@table>, C<@vtable> or C<@ftable>. For example in
  5904. @itemize @bullet
  5905. @item item
  5906. @end itemize
  5907. the element corresponding with bullet has the following keys:
  5908. 'cmdname' => 'bullet'
  5909. 'type' => 'command_as_argument'
  5910. The parent @-command has an entry in extra for the I<command_as_argument>
  5911. element:
  5912. 'cmdname' => 'itemize'
  5913. 'extra => {'command_as_argument' => $command_element_as_argument}
  5914. =item index_entry_command
  5915. This is the type of index entry command like C<@cindex>, and, more
  5916. importantly user defined index entry commands. So for example if there
  5917. is
  5918. @defindex foo
  5919. ...
  5920. @fooindex index entry
  5921. the C<@fooindex> @-command element will have the I<index_entry_command>
  5922. type.
  5923. =item following_arg
  5924. This type is set for non alphabetic accent @-commands that don't use brace
  5925. but instead have their argument right after them, as
  5926. @~n
  5927. =item space_command_arg
  5928. This type is set for accent @-commands that don't use brace but instead
  5929. have their argument after some space, as
  5930. @ringaccent A
  5931. =item definfoenclose_command
  5932. This type is set for an @-command that is redefined by C<@definfoenclose>.
  5933. The beginning is in C<< {'extra'}->{'begin'} >> and the end in
  5934. C<< {'extra'}->{'end'} >>.
  5935. =back
  5936. The text elements may be associated to the following types:
  5937. =over
  5938. =item empty_line
  5939. An empty line.
  5940. =item raw
  5941. Text in an environment where it should be kept as is (in C<@verbatim>,
  5942. C<@verb>, C<@html>, C<@macro> body).
  5943. =item last_raw_newline
  5944. The last end of line in a raw block (except for C<@verbatim>).
  5945. =item empty_line_after_command
  5946. =item empty_spaces_after_command
  5947. The text is spaces for I<empty_spaces_after_command>
  5948. or spaces followed by a newline for
  5949. I<empty_line_after_command>, appearing after a @-command that
  5950. takes an argument on the line or a block
  5951. @-commands.
  5952. =item spaces_at_end
  5953. Space at the end of a @-command line, at the end of some @-commands
  5954. with braces or at the end of a bracketed content on a
  5955. C<@multitable> line.
  5956. =item empty_space_at_end_def_bracketed
  5957. Space at the end of a bracketed content on definition line.
  5958. =item space_at_end_block_command
  5959. Space at the end of a block @-command line.
  5960. =item empty_spaces_before_argument
  5961. The text is spaces appearing after an opening brace of after a
  5962. comma separated @-command arguments.
  5963. =item empty_spaces_after_close_brace
  5964. Spaces appearing after a closing brace, for some rare commands for which
  5965. this space should be ignorable (like C<@caption>).
  5966. =item empty_spaces_before_paragraph
  5967. Space appearing before a paragraph beginning.
  5968. =item preamble_text
  5969. Text appearing before real content, including the C<\input texinfo.tex>.
  5970. =item space_at_end_menu_node
  5971. =item after_description_line
  5972. Space after a node in the menu entry, when there is no description,
  5973. and space appearing after the description line.
  5974. =back
  5975. Other special types are described in the following.
  5976. =over
  5977. =item text_root
  5978. =item document_root
  5979. =item root_line
  5980. These types correspond to document roots. C<text_root> is the document
  5981. root when there is no C<@node> or sectioning command. When
  5982. such a command appears, a new root container is used, C<document_root>,
  5983. and C<text_root> becomes the first content of C<document_root>.
  5984. C<root_line> is the type of the root tree when parsing Texinfo line
  5985. fragments using C<parse_texi_line>.
  5986. =item preamble
  5987. This container holds the text appearing before the first content, including
  5988. the C<\input texinfo.tex> line and following blank lines.
  5989. =item preamble_before_setfilename
  5990. This container holds everything that appears before C<@setfilename>
  5991. if I<IGNORE_BEFORE_SETFILENAME> parser option is set.
  5992. =item paragraph
  5993. A paragraph.
  5994. =item preformatted
  5995. Texinfo code within a format that is not filled. Happens within some
  5996. block commands as C<@example>, but also in menu (in menu descriptions,
  5997. menu comments...).
  5998. =item brace_command_arg
  5999. =item brace_command_context
  6000. =item block_line_arg
  6001. =item misc_line_arg
  6002. Those containers are within C<args> of @-commands with braces for
  6003. I<brace_command_arg>, @-commands with braces that start a new context
  6004. (C<@footnote>, C<@caption>, C<@math>) for I<brace_command_context>,
  6005. block command argument on their line for I<block_line_arg> and
  6006. other commands that take texinfo code as argument on their line
  6007. (C<@settitle>, C<@node>, C<@section> and similar) for I<misc_line_arg>.
  6008. They hold the content of the command argument.
  6009. For example
  6010. @code{in code}
  6011. leads to
  6012. {'cmdname' => 'code',
  6013. 'args' => [{'type' => 'brace_command_arg',
  6014. 'contents' => [{'text' => 'in code'}]}]}
  6015. =item misc_arg
  6016. Argument of @-command taking specific textual arguments on the line.
  6017. For example C<@set>, C<@clickstyle>, C<@unmacro>, C<@comment>.
  6018. The argument is associated to the I<text> key.
  6019. =item menu_entry
  6020. =item menu_entry_leading_text
  6021. =item menu_entry_name
  6022. =item menu_entry_separator
  6023. =item menu_entry_node
  6024. =item menu_entry_description
  6025. A I<menu_entry> holds a full menu entry, like
  6026. * node:: description.
  6027. The different elements of the menu entry are directly in the
  6028. I<menu_entry> C<args> array reference.
  6029. I<menu_entry_leading_text> holds the star and following spaces.
  6030. I<menu_entry_name> is the menu entry name (if present), I<menu_entry_node>
  6031. corresponds to the node in the menu entry, I<menu_entry_separator> holds
  6032. the text after the node and before the description, in most case
  6033. C<:: >. Last I<menu_entry_description> is for the description.
  6034. =item menu_comment
  6035. The I<menu_comment> container holds what is between menu entries
  6036. in menus. For example in
  6037. @menu
  6038. Menu title
  6039. * entry::
  6040. Between entries
  6041. * other::
  6042. @end menu
  6043. Both
  6044. Menu title
  6045. and
  6046. Between entries
  6047. will be in I<menu_comment>.
  6048. =item macro_name
  6049. =item macro_arg
  6050. Taken from C<@macro> definition and put in the C<args> key array of
  6051. the macro, I<macro_name> is the type of the text fragment corresponding
  6052. to the macro name, I<macro_arg> is the type of the text fragments
  6053. correponding to macro formal arguments.
  6054. =item before_item
  6055. A container for content before the first C<@item> of block @-commands
  6056. with items (C<@table>, C<@multitable>, C<@enumerate>...).
  6057. =item table_entry
  6058. =item table_term
  6059. =item table_item
  6060. =item inter_item
  6061. Those containers appear in C<@table>, C<@ftable> and C<@vtable>.
  6062. A I<table_entry> container contains C<@item> and C<@itemx> and
  6063. the text following the C<@item> and C<@itemx> entries. A I<table_term>
  6064. container holds all the C<@item> and C<@itemx> of the I<table_entry>.
  6065. The I<table_item> container holds the content following the I<table_term>.
  6066. If there is some content before an C<@itemx> (normally only comments,
  6067. empty lines or maybe index entriees are allowed), it will be in
  6068. a container with type I<inter_item>.
  6069. =item def_line
  6070. =item def_item
  6071. =item inter_def_item
  6072. The I<def_line> type is either associated with a container within a
  6073. definition command, or is the type of a definition command with a x
  6074. form, like C<@deffnx>. It holds the definition line arguments.
  6075. The container with type I<def_item> holds the definition text content.
  6076. Content appearing before a definition command with a x form is in
  6077. an I<inter_def_item> container.
  6078. =item multitable_head
  6079. =item multitable_body
  6080. =item row
  6081. In C<@multitable>, a I<multitable_head> container contains all the row
  6082. with C<@headitem>, while I<multitable_body> contains the rows associated
  6083. with C<@item>. A I<row> container contains the C<@item> and @<tab>
  6084. forming a row.
  6085. =item bracketed
  6086. This a special type containing content in brackets in the context
  6087. where they are valid, in C<@math>.
  6088. =item bracketed_def_content
  6089. Content in brackets on definition command lines.
  6090. =item bracketed_multitable_prototype
  6091. =item row_prototype
  6092. On C<@multitable> line, content in brackets is in
  6093. I<bracketed_multitable_prototype>, text not in brackets
  6094. is in I<row_prototype>.
  6095. =back
  6096. =head2 Information available in the extra key
  6097. Some extra keys are available for more than one @-command:
  6098. =over
  6099. =item block_command_line_contents
  6100. =item brace_command_contents
  6101. An array associated with block @-commands or @-commands with braces
  6102. taking more than one argument or with a simple text content
  6103. (C<@anchor>, C<@titlefont>, C<@dmn>). Each of the element of the
  6104. array is either undef, if there is no argument at that place,
  6105. or an array reference holding the argument contents.
  6106. =item misc_content
  6107. The contents of an @-command taking regular Texinfo code as
  6108. argument, like C<@sttitle> or C<@exdent>.
  6109. =item end_command
  6110. The C<@end> associated to the block @-command.
  6111. =item missing_argument
  6112. Set for some @-commands with line arguments and a missing argument.
  6113. =item invalid_nesting
  6114. Set if the @-command appears in a context it shouldn't appear in,
  6115. like a block @-command on sectioning @-command line.
  6116. =item arg_line
  6117. The string correspond to the line after the @-command
  6118. for @-commands that have special arguments on their line,
  6119. and for C<@macro> line.
  6120. =item text_arg
  6121. The string correspond to the line after the @-command for @-commands
  6122. that have an argument interpreted as simple text, like C<@setfilename>,
  6123. C<@end> or C<@documentencoding>.
  6124. =item index_entry
  6125. The index entry information (described in L</index_entries>
  6126. in details) is associated to @-commands that have an associated
  6127. index entry.
  6128. =item misc_args
  6129. An array holding strings, the arguments of @-commands taking simple
  6130. textual arguments as arguments, like C<@everyheadingmarks>,
  6131. C<@frenchspacing>, C<@alias>, C<@synindex>, C<@columnfractions>.
  6132. Also filled for C<@set>, C<@clickstyle>, C<@unmacro> or C<@comment>
  6133. arguments.
  6134. =item spaces_after_command
  6135. For @-commands followed by spaces, a reference to the corresponding
  6136. text element.
  6137. =item spaces_before_argument
  6138. For @-commands with opening brace followed by spaces held in a
  6139. C<empty_spaces_before_argument> element, a reference to that element.
  6140. =item spaces
  6141. For accent commands consisting in letter only, like C<@ringaccent>
  6142. appearing like
  6143. @ringaccent A
  6144. there is a I<spaces> key which holds the spaces appearing between
  6145. the command and the argument.
  6146. =back
  6147. Then there are extra keys specific of @-commands or containers.
  6148. =over
  6149. =item C<@macro>
  6150. I<invalid_syntax> is set if there was an error on the C<@macro>
  6151. line. The key I<args_index> associates format arguments with
  6152. their index on the @macro line formal arguments definition.
  6153. The I<macrobody> holds the @macro body. I<arg_line> holds the
  6154. line after C<@macro>.
  6155. =item C<@node>
  6156. The arguments are in the I<nodes_manuals> array. Each
  6157. of the entry has a I<node_content> key for
  6158. an array holding the corresponding content, a I<manual_content>
  6159. if there is an associated external manual name, and I<normalized>
  6160. key for the normalized label, built as specified in the Texinfo manual
  6161. in the B<HTML Xref> node.
  6162. An I<associated_section> key holds the tree element of the
  6163. sectioning command that follows the node.
  6164. =item C<@part>
  6165. The next sectioning command is in I<part_associated_section>.
  6166. =item sectioning command
  6167. The node preceding the command is in I<associated_node>.
  6168. The part preceding the command is in I<associated_part>.
  6169. If the level of the document was modified by C<@raisections>
  6170. or C<@lowersections>, the differential level is in I<sections_level>.
  6171. =item C<@float>
  6172. =item C<@listoffloats>
  6173. If float has a second argument, and for C<@listoffloats>
  6174. argument there is a I<type> key which is also a hash reference,
  6175. with two keys. I<content> is an array holding the associated
  6176. contents, I<normalized> holds the normalized float type.
  6177. I<caption> and I<shortcaption> holds the corresponding
  6178. tree elements for float. The C<@caption> or C<@shortcaption>
  6179. have the float tree element stored in I<float>.
  6180. =item C<@float>
  6181. =item C<@anchor>
  6182. @-Commands that are targets for cross references have a I<normalized>
  6183. key for the normalized label, built as specified in the Texinfo manual
  6184. in the B<HTML Xref> node. There is also a I<node_content> key for
  6185. an array holding the corresponding content.
  6186. C<@anchor> also has I<region> set to the special region name if
  6187. in a special region (C<@copying>, C<@titlepage>).
  6188. =item C<@ref>
  6189. =item C<@xref>
  6190. =item C<@pxref>
  6191. =item C<@inforef>
  6192. The I<node_argument> entry holds a parsed node entry, like
  6193. the one appearing in the I<nodes_manuals> array for C<@node>.
  6194. =item C<@abbr>
  6195. =item C<@acronym>
  6196. The first argument normalized is in I<normalized>. If there is no
  6197. second argument, but a second argument appeared previously for the
  6198. same first argument, the second argument content of the previous
  6199. command is stored in I<explanation_contents>.
  6200. =item definition command
  6201. I<def_command> holds the command name, without x if it is
  6202. an x form of a definition command.
  6203. I<original_def_cmdname> is the original def command.
  6204. If it is an x form, it has I<not_after_command> set if not
  6205. appearing after the definition command without x.
  6206. =item def_line
  6207. The I<def_arg> extra key holds an array reference corresponding to
  6208. the parsed definition line argument. Each of the the element of the
  6209. array is a two element array reference. The first element is the type
  6210. which could be I<spaces> for a space, types specific of the
  6211. definition, like I<category>, I<name>, I<class>, I<type>, and, at the
  6212. end, a mix of I<arg>, I<typearg>, I<delimiter> depending on the definition.
  6213. The second element is a hash reference holding the content of the
  6214. type.
  6215. The I<def_parsed_hash> hash reference has as key the type specific
  6216. of the definition, and as value the corresponding content tree.
  6217. =item C<@multitable>
  6218. The key I<max_columns> holds the maximal number of columns. If there
  6219. are prototypes on the line they are in the array associated with
  6220. I<prototypes>. In that case, I<prototypes_line> also holds this
  6221. information, and, in addition, keeps spaces with type C<prototype_space>.
  6222. If there is a C<@columnfractions> as argument, then the
  6223. I<columnfractions> key is associated with the array of columnfractions
  6224. arguments, holding all the column fractions.
  6225. =item C<@enumerate>
  6226. The extra key I<enumerate_specification> contains the enumerate
  6227. argument.
  6228. =item C<@itemize>
  6229. =item C<@table>
  6230. =item C<@vtable>
  6231. =item C<@ftable>
  6232. The I<command_as_argument> extra key points on the @-command on
  6233. as argument on the @-command line.
  6234. =item paragraph
  6235. The I<indent> or I<noindent> key value is set if the corresponding
  6236. @-commands are associated with that paragraph.
  6237. =item C<@item> in C<@enumerate> or C<@itemize>
  6238. The I<item_number> extra key holds the number of this item.
  6239. =item C<@item> and C<@tab> in C<@multitable>
  6240. The I<cell_count> index key holds the index of the column of
  6241. the cell.
  6242. =item row
  6243. The I<row_number> index key holds the index of the row in
  6244. the C<@multitable>.
  6245. =item C<@author>
  6246. If in a C<@titlepage>, the titlepage is in I<titlepage>, if in
  6247. C<@quotation> or C<@smallquotation>, the corresponding tree element
  6248. is in I<quotation>.
  6249. The author tree element is in the I<author> array of the C<@titlepage>
  6250. or the C<@quotation> or C<@smallquotation> it is associated with.
  6251. =item C<@ifclear>
  6252. =item C<@ifset>
  6253. The original line is in I<line>.
  6254. =item C<@end>
  6255. The textual argument is in I<command_argument>.
  6256. The corresponding @-command is in I<command>.
  6257. =item C<@documentencoding>
  6258. The argument, normalized is in I<input_encoding_name> if it is recognized.
  6259. The corresponding perl encoding name is in I<input_perl_encoding>.
  6260. =item C<@click>
  6261. In I<clickstyle> there is the current clickstyle command.
  6262. =item C<@kbd>
  6263. I<code> is set depending on the context and C<@kbdinputstyle>.
  6264. =item definfoenclose defined commands
  6265. I<begin> holds the string beginning the definfoenclose,
  6266. I<end> holds the string ending the definfoenclose.
  6267. =item menu_entry
  6268. The I<menu_entry_description> and I<menu_entry_name> keys
  6269. are associated with the corresponding tree elements. The
  6270. I<menu_entry_node> holds the parsed node entry, like
  6271. the one appearing in the I<nodes_manuals> array for C<@node>.
  6272. =item empty_line_after_command
  6273. The corresponding command is in I<command>.
  6274. =item C<@inlinefmt>
  6275. =item C<@inlineraw>
  6276. =item C<@inlinefmtifelse>
  6277. =item C<@inlineifclear>
  6278. =item C<@inlineifset>
  6279. The first argument is in I<format>. If an argument has been determined
  6280. as being expanded by the Parser, the index of this argument is in
  6281. I<expand_index>. Index numbering begins at 0, but the first argument is
  6282. always the format or flag name, so, if set, it should be 1 or 2 for
  6283. C<@inlinefmtifelse>, and 1 for other commands.
  6284. =back
  6285. =head1 SEE ALSO
  6286. L<Texinfo manual|http://www.gnu.org/s/texinfo/manual/texinfo/>
  6287. =begin :comment
  6288. Mention other useful documentation such as the documentation of
  6289. related modules or operating system documentation (such as man pages
  6290. in UNIX), or any relevant external documentation such as RFCs or
  6291. standards.
  6292. If you have a mailing list set up for your module, mention it here.
  6293. If you have a web site set up for your module, mention it here.
  6294. =end :comment
  6295. =head1 AUTHOR
  6296. Patrice Dumas, E<lt>pertusus@free.frE<gt>
  6297. =head1 COPYRIGHT AND LICENSE
  6298. Copyright 2010, 2011, 2012 Free Software Foundation, Inc.
  6299. This library is free software; you can redistribute it and/or modify
  6300. it under the terms of the GNU General Public License as published by
  6301. the Free Software Foundation; either version 3 of the License,
  6302. or (at your option) any later version.
  6303. =cut