preproc.c 172 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 1996-2018 The NASM Authors - All Rights Reserved
  4. * See the file AUTHORS included with the NASM distribution for
  5. * the specific copyright holders.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following
  9. * conditions are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  19. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  20. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * ----------------------------------------------------------------------- */
  33. /*
  34. * preproc.c macro preprocessor for the Netwide Assembler
  35. */
  36. /* Typical flow of text through preproc
  37. *
  38. * pp_getline gets tokenized lines, either
  39. *
  40. * from a macro expansion
  41. *
  42. * or
  43. * {
  44. * read_line gets raw text from stdmacpos, or predef, or current input file
  45. * tokenize converts to tokens
  46. * }
  47. *
  48. * expand_mmac_params is used to expand %1 etc., unless a macro is being
  49. * defined or a false conditional is being processed
  50. * (%0, %1, %+1, %-1, %%foo
  51. *
  52. * do_directive checks for directives
  53. *
  54. * expand_smacro is used to expand single line macros
  55. *
  56. * expand_mmacro is used to expand multi-line macros
  57. *
  58. * detoken is used to convert the line back to text
  59. */
  60. #include "compiler.h"
  61. #include <stdio.h>
  62. #include <stdarg.h>
  63. #include <stdlib.h>
  64. #include <stddef.h>
  65. #include <string.h>
  66. #include <ctype.h>
  67. #include <limits.h>
  68. #include "nasm.h"
  69. #include "nasmlib.h"
  70. #include "error.h"
  71. #include "preproc.h"
  72. #include "hashtbl.h"
  73. #include "quote.h"
  74. #include "stdscan.h"
  75. #include "eval.h"
  76. #include "tokens.h"
  77. #include "tables.h"
  78. #include "listing.h"
  79. typedef struct SMacro SMacro;
  80. typedef struct MMacro MMacro;
  81. typedef struct MMacroInvocation MMacroInvocation;
  82. typedef struct Context Context;
  83. typedef struct Token Token;
  84. typedef struct Blocks Blocks;
  85. typedef struct Line Line;
  86. typedef struct Include Include;
  87. typedef struct Cond Cond;
  88. typedef struct IncPath IncPath;
  89. /*
  90. * Note on the storage of both SMacro and MMacros: the hash table
  91. * indexes them case-insensitively, and we then have to go through a
  92. * linked list of potential case aliases (and, for MMacros, parameter
  93. * ranges); this is to preserve the matching semantics of the earlier
  94. * code. If the number of case aliases for a specific macro is a
  95. * performance issue, you may want to reconsider your coding style.
  96. */
  97. /*
  98. * Store the definition of a single-line macro.
  99. */
  100. struct SMacro {
  101. SMacro *next;
  102. char *name;
  103. bool casesense;
  104. bool in_progress;
  105. unsigned int nparam;
  106. Token *expansion;
  107. };
  108. /*
  109. * Store the definition of a multi-line macro. This is also used to
  110. * store the interiors of `%rep...%endrep' blocks, which are
  111. * effectively self-re-invoking multi-line macros which simply
  112. * don't have a name or bother to appear in the hash tables. %rep
  113. * blocks are signified by having a NULL `name' field.
  114. *
  115. * In a MMacro describing a `%rep' block, the `in_progress' field
  116. * isn't merely boolean, but gives the number of repeats left to
  117. * run.
  118. *
  119. * The `next' field is used for storing MMacros in hash tables; the
  120. * `next_active' field is for stacking them on istk entries.
  121. *
  122. * When a MMacro is being expanded, `params', `iline', `nparam',
  123. * `paramlen', `rotate' and `unique' are local to the invocation.
  124. */
  125. struct MMacro {
  126. MMacro *next;
  127. MMacroInvocation *prev; /* previous invocation */
  128. char *name;
  129. int nparam_min, nparam_max;
  130. bool casesense;
  131. bool plus; /* is the last parameter greedy? */
  132. bool nolist; /* is this macro listing-inhibited? */
  133. int64_t in_progress; /* is this macro currently being expanded? */
  134. int32_t max_depth; /* maximum number of recursive expansions allowed */
  135. Token *dlist; /* All defaults as one list */
  136. Token **defaults; /* Parameter default pointers */
  137. int ndefs; /* number of default parameters */
  138. Line *expansion;
  139. MMacro *next_active;
  140. MMacro *rep_nest; /* used for nesting %rep */
  141. Token **params; /* actual parameters */
  142. Token *iline; /* invocation line */
  143. unsigned int nparam, rotate;
  144. int *paramlen;
  145. uint64_t unique;
  146. int lineno; /* Current line number on expansion */
  147. uint64_t condcnt; /* number of if blocks... */
  148. const char *fname; /* File where defined */
  149. int32_t xline; /* First line in macro */
  150. };
  151. /* Store the definition of a multi-line macro, as defined in a
  152. * previous recursive macro expansion.
  153. */
  154. struct MMacroInvocation {
  155. MMacroInvocation *prev; /* previous invocation */
  156. Token **params; /* actual parameters */
  157. Token *iline; /* invocation line */
  158. unsigned int nparam, rotate;
  159. int *paramlen;
  160. uint64_t unique;
  161. uint64_t condcnt;
  162. };
  163. /*
  164. * The context stack is composed of a linked list of these.
  165. */
  166. struct Context {
  167. Context *next;
  168. char *name;
  169. struct hash_table localmac;
  170. uint32_t number;
  171. };
  172. /*
  173. * This is the internal form which we break input lines up into.
  174. * Typically stored in linked lists.
  175. *
  176. * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
  177. * necessarily used as-is, but is intended to denote the number of
  178. * the substituted parameter. So in the definition
  179. *
  180. * %define a(x,y) ( (x) & ~(y) )
  181. *
  182. * the token representing `x' will have its type changed to
  183. * TOK_SMAC_PARAM, but the one representing `y' will be
  184. * TOK_SMAC_PARAM+1.
  185. *
  186. * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
  187. * which doesn't need quotes around it. Used in the pre-include
  188. * mechanism as an alternative to trying to find a sensible type of
  189. * quote to use on the filename we were passed.
  190. */
  191. enum pp_token_type {
  192. TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
  193. TOK_PREPROC_ID, TOK_STRING,
  194. TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
  195. TOK_INTERNAL_STRING,
  196. TOK_PREPROC_Q, TOK_PREPROC_QQ,
  197. TOK_PASTE, /* %+ */
  198. TOK_INDIRECT, /* %[...] */
  199. TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
  200. TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
  201. };
  202. #define PP_CONCAT_MASK(x) (1 << (x))
  203. #define PP_CONCAT_MATCH(t, mask) (PP_CONCAT_MASK((t)->type) & mask)
  204. struct tokseq_match {
  205. int mask_head;
  206. int mask_tail;
  207. };
  208. struct Token {
  209. Token *next;
  210. char *text;
  211. union {
  212. SMacro *mac; /* associated macro for TOK_SMAC_END */
  213. size_t len; /* scratch length field */
  214. } a; /* Auxiliary data */
  215. enum pp_token_type type;
  216. };
  217. /*
  218. * Multi-line macro definitions are stored as a linked list of
  219. * these, which is essentially a container to allow several linked
  220. * lists of Tokens.
  221. *
  222. * Note that in this module, linked lists are treated as stacks
  223. * wherever possible. For this reason, Lines are _pushed_ on to the
  224. * `expansion' field in MMacro structures, so that the linked list,
  225. * if walked, would give the macro lines in reverse order; this
  226. * means that we can walk the list when expanding a macro, and thus
  227. * push the lines on to the `expansion' field in _istk_ in reverse
  228. * order (so that when popped back off they are in the right
  229. * order). It may seem cockeyed, and it relies on my design having
  230. * an even number of steps in, but it works...
  231. *
  232. * Some of these structures, rather than being actual lines, are
  233. * markers delimiting the end of the expansion of a given macro.
  234. * This is for use in the cycle-tracking and %rep-handling code.
  235. * Such structures have `finishes' non-NULL, and `first' NULL. All
  236. * others have `finishes' NULL, but `first' may still be NULL if
  237. * the line is blank.
  238. */
  239. struct Line {
  240. Line *next;
  241. MMacro *finishes;
  242. Token *first;
  243. };
  244. /*
  245. * To handle an arbitrary level of file inclusion, we maintain a
  246. * stack (ie linked list) of these things.
  247. */
  248. struct Include {
  249. Include *next;
  250. FILE *fp;
  251. Cond *conds;
  252. Line *expansion;
  253. const char *fname;
  254. int lineno, lineinc;
  255. MMacro *mstk; /* stack of active macros/reps */
  256. };
  257. /*
  258. * Include search path. This is simply a list of strings which get
  259. * prepended, in turn, to the name of an include file, in an
  260. * attempt to find the file if it's not in the current directory.
  261. */
  262. struct IncPath {
  263. IncPath *next;
  264. char *path;
  265. };
  266. /*
  267. * File real name hash, so we don't have to re-search the include
  268. * path for every pass (and potentially more than that if a file
  269. * is used more than once.)
  270. */
  271. struct hash_table FileHash;
  272. /*
  273. * Conditional assembly: we maintain a separate stack of these for
  274. * each level of file inclusion. (The only reason we keep the
  275. * stacks separate is to ensure that a stray `%endif' in a file
  276. * included from within the true branch of a `%if' won't terminate
  277. * it and cause confusion: instead, rightly, it'll cause an error.)
  278. */
  279. struct Cond {
  280. Cond *next;
  281. int state;
  282. };
  283. enum {
  284. /*
  285. * These states are for use just after %if or %elif: IF_TRUE
  286. * means the condition has evaluated to truth so we are
  287. * currently emitting, whereas IF_FALSE means we are not
  288. * currently emitting but will start doing so if a %else comes
  289. * up. In these states, all directives are admissible: %elif,
  290. * %else and %endif. (And of course %if.)
  291. */
  292. COND_IF_TRUE, COND_IF_FALSE,
  293. /*
  294. * These states come up after a %else: ELSE_TRUE means we're
  295. * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
  296. * any %elif or %else will cause an error.
  297. */
  298. COND_ELSE_TRUE, COND_ELSE_FALSE,
  299. /*
  300. * These states mean that we're not emitting now, and also that
  301. * nothing until %endif will be emitted at all. COND_DONE is
  302. * used when we've had our moment of emission
  303. * and have now started seeing %elifs. COND_NEVER is used when
  304. * the condition construct in question is contained within a
  305. * non-emitting branch of a larger condition construct,
  306. * or if there is an error.
  307. */
  308. COND_DONE, COND_NEVER
  309. };
  310. #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
  311. /*
  312. * These defines are used as the possible return values for do_directive
  313. */
  314. #define NO_DIRECTIVE_FOUND 0
  315. #define DIRECTIVE_FOUND 1
  316. /* max reps */
  317. #define REP_LIMIT ((INT64_C(1) << 62))
  318. /*
  319. * Condition codes. Note that we use c_ prefix not C_ because C_ is
  320. * used in nasm.h for the "real" condition codes. At _this_ level,
  321. * we treat CXZ and ECXZ as condition codes, albeit non-invertible
  322. * ones, so we need a different enum...
  323. */
  324. static const char * const conditions[] = {
  325. "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
  326. "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
  327. "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
  328. };
  329. enum pp_conds {
  330. c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
  331. c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
  332. c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
  333. c_none = -1
  334. };
  335. static const enum pp_conds inverse_ccs[] = {
  336. c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
  337. c_A, c_AE, c_B, c_BE, c_C, c_E, c_G, c_GE, c_L, c_LE, c_O, c_P, c_S,
  338. c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
  339. };
  340. /*
  341. * Directive names.
  342. */
  343. /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
  344. static int is_condition(enum preproc_token arg)
  345. {
  346. return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
  347. }
  348. /* For TASM compatibility we need to be able to recognise TASM compatible
  349. * conditional compilation directives. Using the NASM pre-processor does
  350. * not work, so we look for them specifically from the following list and
  351. * then jam in the equivalent NASM directive into the input stream.
  352. */
  353. enum {
  354. TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
  355. TM_IFNDEF, TM_INCLUDE, TM_LOCAL
  356. };
  357. static const char * const tasm_directives[] = {
  358. "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
  359. "ifndef", "include", "local"
  360. };
  361. static int StackSize = 4;
  362. static const char *StackPointer = "ebp";
  363. static int ArgOffset = 8;
  364. static int LocalOffset = 0;
  365. static Context *cstk;
  366. static Include *istk;
  367. static IncPath *ipath = NULL;
  368. static int pass; /* HACK: pass 0 = generate dependencies only */
  369. static StrList **dephead;
  370. static uint64_t unique; /* unique identifier numbers */
  371. static Line *predef = NULL;
  372. static bool do_predef;
  373. /*
  374. * The current set of multi-line macros we have defined.
  375. */
  376. static struct hash_table mmacros;
  377. /*
  378. * The current set of single-line macros we have defined.
  379. */
  380. static struct hash_table smacros;
  381. /*
  382. * The multi-line macro we are currently defining, or the %rep
  383. * block we are currently reading, if any.
  384. */
  385. static MMacro *defining;
  386. static uint64_t nested_mac_count;
  387. static uint64_t nested_rep_count;
  388. /*
  389. * The number of macro parameters to allocate space for at a time.
  390. */
  391. #define PARAM_DELTA 16
  392. /*
  393. * The standard macro set: defined in macros.c in a set of arrays.
  394. * This gives our position in any macro set, while we are processing it.
  395. * The stdmacset is an array of such macro sets.
  396. */
  397. static macros_t *stdmacpos;
  398. static macros_t **stdmacnext;
  399. static macros_t *stdmacros[8];
  400. static macros_t *extrastdmac;
  401. /*
  402. * Tokens are allocated in blocks to improve speed
  403. */
  404. #define TOKEN_BLOCKSIZE 4096
  405. static Token *freeTokens = NULL;
  406. struct Blocks {
  407. Blocks *next;
  408. void *chunk;
  409. };
  410. static Blocks blocks = { NULL, NULL };
  411. /*
  412. * Forward declarations.
  413. */
  414. static void pp_add_stdmac(macros_t *macros);
  415. static Token *expand_mmac_params(Token * tline);
  416. static Token *expand_smacro(Token * tline);
  417. static Token *expand_id(Token * tline);
  418. static Context *get_ctx(const char *name, const char **namep);
  419. static void make_tok_num(Token * tok, int64_t val);
  420. static void pp_verror(int severity, const char *fmt, va_list ap);
  421. static vefunc real_verror;
  422. static void *new_Block(size_t size);
  423. static void delete_Blocks(void);
  424. static Token *new_Token(Token * next, enum pp_token_type type,
  425. const char *text, int txtlen);
  426. static Token *delete_Token(Token * t);
  427. /*
  428. * Macros for safe checking of token pointers, avoid *(NULL)
  429. */
  430. #define tok_type_(x,t) ((x) && (x)->type == (t))
  431. #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
  432. #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
  433. #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
  434. /*
  435. * nasm_unquote with error if the string contains NUL characters.
  436. * If the string contains NUL characters, issue an error and return
  437. * the C len, i.e. truncate at the NUL.
  438. */
  439. static size_t nasm_unquote_cstr(char *qstr, enum preproc_token directive)
  440. {
  441. size_t len = nasm_unquote(qstr, NULL);
  442. size_t clen = strlen(qstr);
  443. if (len != clen)
  444. nasm_error(ERR_NONFATAL, "NUL character in `%s' directive",
  445. pp_directives[directive]);
  446. return clen;
  447. }
  448. /*
  449. * In-place reverse a list of tokens.
  450. */
  451. static Token *reverse_tokens(Token *t)
  452. {
  453. Token *prev = NULL;
  454. Token *next;
  455. while (t) {
  456. next = t->next;
  457. t->next = prev;
  458. prev = t;
  459. t = next;
  460. }
  461. return prev;
  462. }
  463. /*
  464. * Handle TASM specific directives, which do not contain a % in
  465. * front of them. We do it here because I could not find any other
  466. * place to do it for the moment, and it is a hack (ideally it would
  467. * be nice to be able to use the NASM pre-processor to do it).
  468. */
  469. static char *check_tasm_directive(char *line)
  470. {
  471. int32_t i, j, k, m, len;
  472. char *p, *q, *oldline, oldchar;
  473. p = nasm_skip_spaces(line);
  474. /* Binary search for the directive name */
  475. i = -1;
  476. j = ARRAY_SIZE(tasm_directives);
  477. q = nasm_skip_word(p);
  478. len = q - p;
  479. if (len) {
  480. oldchar = p[len];
  481. p[len] = 0;
  482. while (j - i > 1) {
  483. k = (j + i) / 2;
  484. m = nasm_stricmp(p, tasm_directives[k]);
  485. if (m == 0) {
  486. /* We have found a directive, so jam a % in front of it
  487. * so that NASM will then recognise it as one if it's own.
  488. */
  489. p[len] = oldchar;
  490. len = strlen(p);
  491. oldline = line;
  492. line = nasm_malloc(len + 2);
  493. line[0] = '%';
  494. if (k == TM_IFDIFI) {
  495. /*
  496. * NASM does not recognise IFDIFI, so we convert
  497. * it to %if 0. This is not used in NASM
  498. * compatible code, but does need to parse for the
  499. * TASM macro package.
  500. */
  501. strcpy(line + 1, "if 0");
  502. } else {
  503. memcpy(line + 1, p, len + 1);
  504. }
  505. nasm_free(oldline);
  506. return line;
  507. } else if (m < 0) {
  508. j = k;
  509. } else
  510. i = k;
  511. }
  512. p[len] = oldchar;
  513. }
  514. return line;
  515. }
  516. /*
  517. * The pre-preprocessing stage... This function translates line
  518. * number indications as they emerge from GNU cpp (`# lineno "file"
  519. * flags') into NASM preprocessor line number indications (`%line
  520. * lineno file').
  521. */
  522. static char *prepreproc(char *line)
  523. {
  524. int lineno, fnlen;
  525. char *fname, *oldline;
  526. if (line[0] == '#' && line[1] == ' ') {
  527. oldline = line;
  528. fname = oldline + 2;
  529. lineno = atoi(fname);
  530. fname += strspn(fname, "0123456789 ");
  531. if (*fname == '"')
  532. fname++;
  533. fnlen = strcspn(fname, "\"");
  534. line = nasm_malloc(20 + fnlen);
  535. snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
  536. nasm_free(oldline);
  537. }
  538. if (tasm_compatible_mode)
  539. return check_tasm_directive(line);
  540. return line;
  541. }
  542. /*
  543. * Free a linked list of tokens.
  544. */
  545. static void free_tlist(Token * list)
  546. {
  547. while (list)
  548. list = delete_Token(list);
  549. }
  550. /*
  551. * Free a linked list of lines.
  552. */
  553. static void free_llist(Line * list)
  554. {
  555. Line *l, *tmp;
  556. list_for_each_safe(l, tmp, list) {
  557. free_tlist(l->first);
  558. nasm_free(l);
  559. }
  560. }
  561. /*
  562. * Free an MMacro
  563. */
  564. static void free_mmacro(MMacro * m)
  565. {
  566. nasm_free(m->name);
  567. free_tlist(m->dlist);
  568. nasm_free(m->defaults);
  569. free_llist(m->expansion);
  570. nasm_free(m);
  571. }
  572. /*
  573. * Free all currently defined macros, and free the hash tables
  574. */
  575. static void free_smacro_table(struct hash_table *smt)
  576. {
  577. SMacro *s, *tmp;
  578. const char *key;
  579. struct hash_tbl_node *it = NULL;
  580. while ((s = hash_iterate(smt, &it, &key)) != NULL) {
  581. nasm_free((void *)key);
  582. list_for_each_safe(s, tmp, s) {
  583. nasm_free(s->name);
  584. free_tlist(s->expansion);
  585. nasm_free(s);
  586. }
  587. }
  588. hash_free(smt);
  589. }
  590. static void free_mmacro_table(struct hash_table *mmt)
  591. {
  592. MMacro *m, *tmp;
  593. const char *key;
  594. struct hash_tbl_node *it = NULL;
  595. it = NULL;
  596. while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
  597. nasm_free((void *)key);
  598. list_for_each_safe(m ,tmp, m)
  599. free_mmacro(m);
  600. }
  601. hash_free(mmt);
  602. }
  603. static void free_macros(void)
  604. {
  605. free_smacro_table(&smacros);
  606. free_mmacro_table(&mmacros);
  607. }
  608. /*
  609. * Initialize the hash tables
  610. */
  611. static void init_macros(void)
  612. {
  613. hash_init(&smacros, HASH_LARGE);
  614. hash_init(&mmacros, HASH_LARGE);
  615. }
  616. /*
  617. * Pop the context stack.
  618. */
  619. static void ctx_pop(void)
  620. {
  621. Context *c = cstk;
  622. cstk = cstk->next;
  623. free_smacro_table(&c->localmac);
  624. nasm_free(c->name);
  625. nasm_free(c);
  626. }
  627. /*
  628. * Search for a key in the hash index; adding it if necessary
  629. * (in which case we initialize the data pointer to NULL.)
  630. */
  631. static void **
  632. hash_findi_add(struct hash_table *hash, const char *str)
  633. {
  634. struct hash_insert hi;
  635. void **r;
  636. char *strx;
  637. r = hash_findi(hash, str, &hi);
  638. if (r)
  639. return r;
  640. strx = nasm_strdup(str); /* Use a more efficient allocator here? */
  641. return hash_add(&hi, strx, NULL);
  642. }
  643. /*
  644. * Like hash_findi, but returns the data element rather than a pointer
  645. * to it. Used only when not adding a new element, hence no third
  646. * argument.
  647. */
  648. static void *
  649. hash_findix(struct hash_table *hash, const char *str)
  650. {
  651. void **p;
  652. p = hash_findi(hash, str, NULL);
  653. return p ? *p : NULL;
  654. }
  655. /*
  656. * read line from standart macros set,
  657. * if there no more left -- return NULL
  658. */
  659. static char *line_from_stdmac(void)
  660. {
  661. unsigned char c;
  662. const unsigned char *p = stdmacpos;
  663. char *line, *q;
  664. size_t len = 0;
  665. if (!stdmacpos)
  666. return NULL;
  667. while ((c = *p++)) {
  668. if (c >= 0x80)
  669. len += pp_directives_len[c - 0x80] + 1;
  670. else
  671. len++;
  672. }
  673. line = nasm_malloc(len + 1);
  674. q = line;
  675. while ((c = *stdmacpos++)) {
  676. if (c >= 0x80) {
  677. memcpy(q, pp_directives[c - 0x80], pp_directives_len[c - 0x80]);
  678. q += pp_directives_len[c - 0x80];
  679. *q++ = ' ';
  680. } else {
  681. *q++ = c;
  682. }
  683. }
  684. stdmacpos = p;
  685. *q = '\0';
  686. if (!*stdmacpos) {
  687. /* This was the last of this particular macro set */
  688. stdmacpos = NULL;
  689. if (*stdmacnext) {
  690. stdmacpos = *stdmacnext++;
  691. } else if (do_predef) {
  692. Line *pd, *l;
  693. Token *head, **tail, *t;
  694. /*
  695. * Nasty hack: here we push the contents of
  696. * `predef' on to the top-level expansion stack,
  697. * since this is the most convenient way to
  698. * implement the pre-include and pre-define
  699. * features.
  700. */
  701. list_for_each(pd, predef) {
  702. head = NULL;
  703. tail = &head;
  704. list_for_each(t, pd->first) {
  705. *tail = new_Token(NULL, t->type, t->text, 0);
  706. tail = &(*tail)->next;
  707. }
  708. l = nasm_malloc(sizeof(Line));
  709. l->next = istk->expansion;
  710. l->first = head;
  711. l->finishes = NULL;
  712. istk->expansion = l;
  713. }
  714. do_predef = false;
  715. }
  716. }
  717. return line;
  718. }
  719. static char *read_line(void)
  720. {
  721. unsigned int size, c, next;
  722. const unsigned int delta = 512;
  723. const unsigned int pad = 8;
  724. unsigned int nr_cont = 0;
  725. bool cont = false;
  726. char *buffer, *p;
  727. /* Standart macros set (predefined) goes first */
  728. p = line_from_stdmac();
  729. if (p)
  730. return p;
  731. size = delta;
  732. p = buffer = nasm_malloc(size);
  733. for (;;) {
  734. c = fgetc(istk->fp);
  735. if ((int)(c) == EOF) {
  736. p[0] = 0;
  737. break;
  738. }
  739. switch (c) {
  740. case '\r':
  741. next = fgetc(istk->fp);
  742. if (next != '\n')
  743. ungetc(next, istk->fp);
  744. if (cont) {
  745. cont = false;
  746. continue;
  747. }
  748. break;
  749. case '\n':
  750. if (cont) {
  751. cont = false;
  752. continue;
  753. }
  754. break;
  755. case '\\':
  756. next = fgetc(istk->fp);
  757. ungetc(next, istk->fp);
  758. if (next == '\r' || next == '\n') {
  759. cont = true;
  760. nr_cont++;
  761. continue;
  762. }
  763. break;
  764. }
  765. if (c == '\r' || c == '\n') {
  766. *p++ = 0;
  767. break;
  768. }
  769. if (p >= (buffer + size - pad)) {
  770. buffer = nasm_realloc(buffer, size + delta);
  771. p = buffer + size - pad;
  772. size += delta;
  773. }
  774. *p++ = (unsigned char)c;
  775. }
  776. if (p == buffer) {
  777. nasm_free(buffer);
  778. return NULL;
  779. }
  780. src_set_linnum(src_get_linnum() + istk->lineinc +
  781. (nr_cont * istk->lineinc));
  782. /*
  783. * Handle spurious ^Z, which may be inserted into source files
  784. * by some file transfer utilities.
  785. */
  786. buffer[strcspn(buffer, "\032")] = '\0';
  787. lfmt->line(LIST_READ, buffer);
  788. return buffer;
  789. }
  790. /*
  791. * Tokenize a line of text. This is a very simple process since we
  792. * don't need to parse the value out of e.g. numeric tokens: we
  793. * simply split one string into many.
  794. */
  795. static Token *tokenize(char *line)
  796. {
  797. char c, *p = line;
  798. enum pp_token_type type;
  799. Token *list = NULL;
  800. Token *t, **tail = &list;
  801. while (*line) {
  802. p = line;
  803. if (*p == '%') {
  804. p++;
  805. if (*p == '+' && !nasm_isdigit(p[1])) {
  806. p++;
  807. type = TOK_PASTE;
  808. } else if (nasm_isdigit(*p) ||
  809. ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
  810. do {
  811. p++;
  812. }
  813. while (nasm_isdigit(*p));
  814. type = TOK_PREPROC_ID;
  815. } else if (*p == '{') {
  816. p++;
  817. while (*p) {
  818. if (*p == '}')
  819. break;
  820. p[-1] = *p;
  821. p++;
  822. }
  823. if (*p != '}')
  824. nasm_error(ERR_WARNING | ERR_PASS1,
  825. "unterminated %%{ construct");
  826. p[-1] = '\0';
  827. if (*p)
  828. p++;
  829. type = TOK_PREPROC_ID;
  830. } else if (*p == '[') {
  831. int lvl = 1;
  832. line += 2; /* Skip the leading %[ */
  833. p++;
  834. while (lvl && (c = *p++)) {
  835. switch (c) {
  836. case ']':
  837. lvl--;
  838. break;
  839. case '%':
  840. if (*p == '[')
  841. lvl++;
  842. break;
  843. case '\'':
  844. case '\"':
  845. case '`':
  846. p = nasm_skip_string(p - 1);
  847. if (*p)
  848. p++;
  849. break;
  850. default:
  851. break;
  852. }
  853. }
  854. p--;
  855. if (*p)
  856. *p++ = '\0';
  857. if (lvl)
  858. nasm_error(ERR_NONFATAL|ERR_PASS1,
  859. "unterminated %%[ construct");
  860. type = TOK_INDIRECT;
  861. } else if (*p == '?') {
  862. type = TOK_PREPROC_Q; /* %? */
  863. p++;
  864. if (*p == '?') {
  865. type = TOK_PREPROC_QQ; /* %?? */
  866. p++;
  867. }
  868. } else if (*p == '!') {
  869. type = TOK_PREPROC_ID;
  870. p++;
  871. if (isidchar(*p)) {
  872. do {
  873. p++;
  874. }
  875. while (isidchar(*p));
  876. } else if (*p == '\'' || *p == '\"' || *p == '`') {
  877. p = nasm_skip_string(p);
  878. if (*p)
  879. p++;
  880. else
  881. nasm_error(ERR_NONFATAL|ERR_PASS1,
  882. "unterminated %%! string");
  883. } else {
  884. /* %! without string or identifier */
  885. type = TOK_OTHER; /* Legacy behavior... */
  886. }
  887. } else if (isidchar(*p) ||
  888. ((*p == '!' || *p == '%' || *p == '$') &&
  889. isidchar(p[1]))) {
  890. do {
  891. p++;
  892. }
  893. while (isidchar(*p));
  894. type = TOK_PREPROC_ID;
  895. } else {
  896. type = TOK_OTHER;
  897. if (*p == '%')
  898. p++;
  899. }
  900. } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
  901. type = TOK_ID;
  902. p++;
  903. while (*p && isidchar(*p))
  904. p++;
  905. } else if (*p == '\'' || *p == '"' || *p == '`') {
  906. /*
  907. * A string token.
  908. */
  909. type = TOK_STRING;
  910. p = nasm_skip_string(p);
  911. if (*p) {
  912. p++;
  913. } else {
  914. nasm_error(ERR_WARNING|ERR_PASS1, "unterminated string");
  915. /* Handling unterminated strings by UNV */
  916. /* type = -1; */
  917. }
  918. } else if (p[0] == '$' && p[1] == '$') {
  919. type = TOK_OTHER; /* TOKEN_BASE */
  920. p += 2;
  921. } else if (isnumstart(*p)) {
  922. bool is_hex = false;
  923. bool is_float = false;
  924. bool has_e = false;
  925. char c, *r;
  926. /*
  927. * A numeric token.
  928. */
  929. if (*p == '$') {
  930. p++;
  931. is_hex = true;
  932. }
  933. for (;;) {
  934. c = *p++;
  935. if (!is_hex && (c == 'e' || c == 'E')) {
  936. has_e = true;
  937. if (*p == '+' || *p == '-') {
  938. /*
  939. * e can only be followed by +/- if it is either a
  940. * prefixed hex number or a floating-point number
  941. */
  942. p++;
  943. is_float = true;
  944. }
  945. } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
  946. is_hex = true;
  947. } else if (c == 'P' || c == 'p') {
  948. is_float = true;
  949. if (*p == '+' || *p == '-')
  950. p++;
  951. } else if (isnumchar(c))
  952. ; /* just advance */
  953. else if (c == '.') {
  954. /*
  955. * we need to deal with consequences of the legacy
  956. * parser, like "1.nolist" being two tokens
  957. * (TOK_NUMBER, TOK_ID) here; at least give it
  958. * a shot for now. In the future, we probably need
  959. * a flex-based scanner with proper pattern matching
  960. * to do it as well as it can be done. Nothing in
  961. * the world is going to help the person who wants
  962. * 0x123.p16 interpreted as two tokens, though.
  963. */
  964. r = p;
  965. while (*r == '_')
  966. r++;
  967. if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
  968. (!is_hex && (*r == 'e' || *r == 'E')) ||
  969. (*r == 'p' || *r == 'P')) {
  970. p = r;
  971. is_float = true;
  972. } else
  973. break; /* Terminate the token */
  974. } else
  975. break;
  976. }
  977. p--; /* Point to first character beyond number */
  978. if (p == line+1 && *line == '$') {
  979. type = TOK_OTHER; /* TOKEN_HERE */
  980. } else {
  981. if (has_e && !is_hex) {
  982. /* 1e13 is floating-point, but 1e13h is not */
  983. is_float = true;
  984. }
  985. type = is_float ? TOK_FLOAT : TOK_NUMBER;
  986. }
  987. } else if (nasm_isspace(*p)) {
  988. type = TOK_WHITESPACE;
  989. p = nasm_skip_spaces(p);
  990. /*
  991. * Whitespace just before end-of-line is discarded by
  992. * pretending it's a comment; whitespace just before a
  993. * comment gets lumped into the comment.
  994. */
  995. if (!*p || *p == ';') {
  996. type = TOK_COMMENT;
  997. while (*p)
  998. p++;
  999. }
  1000. } else if (*p == ';') {
  1001. type = TOK_COMMENT;
  1002. while (*p)
  1003. p++;
  1004. } else {
  1005. /*
  1006. * Anything else is an operator of some kind. We check
  1007. * for all the double-character operators (>>, <<, //,
  1008. * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
  1009. * else is a single-character operator.
  1010. */
  1011. type = TOK_OTHER;
  1012. if ((p[0] == '>' && p[1] == '>') ||
  1013. (p[0] == '<' && p[1] == '<') ||
  1014. (p[0] == '/' && p[1] == '/') ||
  1015. (p[0] == '<' && p[1] == '=') ||
  1016. (p[0] == '>' && p[1] == '=') ||
  1017. (p[0] == '=' && p[1] == '=') ||
  1018. (p[0] == '!' && p[1] == '=') ||
  1019. (p[0] == '<' && p[1] == '>') ||
  1020. (p[0] == '&' && p[1] == '&') ||
  1021. (p[0] == '|' && p[1] == '|') ||
  1022. (p[0] == '^' && p[1] == '^')) {
  1023. p++;
  1024. }
  1025. p++;
  1026. }
  1027. /* Handling unterminated string by UNV */
  1028. /*if (type == -1)
  1029. {
  1030. *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
  1031. t->text[p-line] = *line;
  1032. tail = &t->next;
  1033. }
  1034. else */
  1035. if (type != TOK_COMMENT) {
  1036. *tail = t = new_Token(NULL, type, line, p - line);
  1037. tail = &t->next;
  1038. }
  1039. line = p;
  1040. }
  1041. return list;
  1042. }
  1043. /*
  1044. * this function allocates a new managed block of memory and
  1045. * returns a pointer to the block. The managed blocks are
  1046. * deleted only all at once by the delete_Blocks function.
  1047. */
  1048. static void *new_Block(size_t size)
  1049. {
  1050. Blocks *b = &blocks;
  1051. /* first, get to the end of the linked list */
  1052. while (b->next)
  1053. b = b->next;
  1054. /* now allocate the requested chunk */
  1055. b->chunk = nasm_malloc(size);
  1056. /* now allocate a new block for the next request */
  1057. b->next = nasm_zalloc(sizeof(Blocks));
  1058. return b->chunk;
  1059. }
  1060. /*
  1061. * this function deletes all managed blocks of memory
  1062. */
  1063. static void delete_Blocks(void)
  1064. {
  1065. Blocks *a, *b = &blocks;
  1066. /*
  1067. * keep in mind that the first block, pointed to by blocks
  1068. * is a static and not dynamically allocated, so we don't
  1069. * free it.
  1070. */
  1071. while (b) {
  1072. if (b->chunk)
  1073. nasm_free(b->chunk);
  1074. a = b;
  1075. b = b->next;
  1076. if (a != &blocks)
  1077. nasm_free(a);
  1078. }
  1079. memset(&blocks, 0, sizeof(blocks));
  1080. }
  1081. /*
  1082. * this function creates a new Token and passes a pointer to it
  1083. * back to the caller. It sets the type and text elements, and
  1084. * also the a.mac and next elements to NULL.
  1085. */
  1086. static Token *new_Token(Token * next, enum pp_token_type type,
  1087. const char *text, int txtlen)
  1088. {
  1089. Token *t;
  1090. int i;
  1091. if (!freeTokens) {
  1092. freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
  1093. for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
  1094. freeTokens[i].next = &freeTokens[i + 1];
  1095. freeTokens[i].next = NULL;
  1096. }
  1097. t = freeTokens;
  1098. freeTokens = t->next;
  1099. t->next = next;
  1100. t->a.mac = NULL;
  1101. t->type = type;
  1102. if (type == TOK_WHITESPACE || !text) {
  1103. t->text = NULL;
  1104. } else {
  1105. if (txtlen == 0)
  1106. txtlen = strlen(text);
  1107. t->text = nasm_malloc(txtlen+1);
  1108. memcpy(t->text, text, txtlen);
  1109. t->text[txtlen] = '\0';
  1110. }
  1111. return t;
  1112. }
  1113. static Token *delete_Token(Token * t)
  1114. {
  1115. Token *next = t->next;
  1116. nasm_free(t->text);
  1117. t->next = freeTokens;
  1118. freeTokens = t;
  1119. return next;
  1120. }
  1121. /*
  1122. * Convert a line of tokens back into text.
  1123. * If expand_locals is not zero, identifiers of the form "%$*xxx"
  1124. * will be transformed into ..@ctxnum.xxx
  1125. */
  1126. static char *detoken(Token * tlist, bool expand_locals)
  1127. {
  1128. Token *t;
  1129. char *line, *p;
  1130. const char *q;
  1131. int len = 0;
  1132. list_for_each(t, tlist) {
  1133. if (t->type == TOK_PREPROC_ID && t->text &&
  1134. t->text[0] && t->text[1] == '!') {
  1135. char *v;
  1136. char *q = t->text;
  1137. v = t->text + 2;
  1138. if (*v == '\'' || *v == '\"' || *v == '`') {
  1139. size_t len = nasm_unquote(v, NULL);
  1140. size_t clen = strlen(v);
  1141. if (len != clen) {
  1142. nasm_error(ERR_NONFATAL | ERR_PASS1,
  1143. "NUL character in %%! string");
  1144. v = NULL;
  1145. }
  1146. }
  1147. if (v) {
  1148. char *p = getenv(v);
  1149. if (!p) {
  1150. nasm_error(ERR_NONFATAL | ERR_PASS1,
  1151. "nonexistent environment variable `%s'", v);
  1152. /*
  1153. * FIXME We better should investigate if accessing
  1154. * ->text[1] without ->text[0] is safe enough.
  1155. */
  1156. t->text = nasm_zalloc(2);
  1157. } else
  1158. t->text = nasm_strdup(p);
  1159. nasm_free(q);
  1160. }
  1161. }
  1162. /* Expand local macros here and not during preprocessing */
  1163. if (expand_locals &&
  1164. t->type == TOK_PREPROC_ID && t->text &&
  1165. t->text[0] == '%' && t->text[1] == '$') {
  1166. const char *q;
  1167. char *p;
  1168. Context *ctx = get_ctx(t->text, &q);
  1169. if (ctx) {
  1170. char buffer[40];
  1171. snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
  1172. p = nasm_strcat(buffer, q);
  1173. nasm_free(t->text);
  1174. t->text = p;
  1175. }
  1176. }
  1177. if (t->type == TOK_WHITESPACE)
  1178. len++;
  1179. else if (t->text)
  1180. len += strlen(t->text);
  1181. }
  1182. p = line = nasm_malloc(len + 1);
  1183. list_for_each(t, tlist) {
  1184. if (t->type == TOK_WHITESPACE) {
  1185. *p++ = ' ';
  1186. } else if (t->text) {
  1187. q = t->text;
  1188. while (*q)
  1189. *p++ = *q++;
  1190. }
  1191. }
  1192. *p = '\0';
  1193. return line;
  1194. }
  1195. /*
  1196. * A scanner, suitable for use by the expression evaluator, which
  1197. * operates on a line of Tokens. Expects a pointer to a pointer to
  1198. * the first token in the line to be passed in as its private_data
  1199. * field.
  1200. *
  1201. * FIX: This really needs to be unified with stdscan.
  1202. */
  1203. static int ppscan(void *private_data, struct tokenval *tokval)
  1204. {
  1205. Token **tlineptr = private_data;
  1206. Token *tline;
  1207. char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
  1208. do {
  1209. tline = *tlineptr;
  1210. *tlineptr = tline ? tline->next : NULL;
  1211. } while (tline && (tline->type == TOK_WHITESPACE ||
  1212. tline->type == TOK_COMMENT));
  1213. if (!tline)
  1214. return tokval->t_type = TOKEN_EOS;
  1215. tokval->t_charptr = tline->text;
  1216. if (tline->text[0] == '$' && !tline->text[1])
  1217. return tokval->t_type = TOKEN_HERE;
  1218. if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
  1219. return tokval->t_type = TOKEN_BASE;
  1220. if (tline->type == TOK_ID) {
  1221. p = tokval->t_charptr = tline->text;
  1222. if (p[0] == '$') {
  1223. tokval->t_charptr++;
  1224. return tokval->t_type = TOKEN_ID;
  1225. }
  1226. for (r = p, s = ourcopy; *r; r++) {
  1227. if (r >= p+MAX_KEYWORD)
  1228. return tokval->t_type = TOKEN_ID; /* Not a keyword */
  1229. *s++ = nasm_tolower(*r);
  1230. }
  1231. *s = '\0';
  1232. /* right, so we have an identifier sitting in temp storage. now,
  1233. * is it actually a register or instruction name, or what? */
  1234. return nasm_token_hash(ourcopy, tokval);
  1235. }
  1236. if (tline->type == TOK_NUMBER) {
  1237. bool rn_error;
  1238. tokval->t_integer = readnum(tline->text, &rn_error);
  1239. tokval->t_charptr = tline->text;
  1240. if (rn_error)
  1241. return tokval->t_type = TOKEN_ERRNUM;
  1242. else
  1243. return tokval->t_type = TOKEN_NUM;
  1244. }
  1245. if (tline->type == TOK_FLOAT) {
  1246. return tokval->t_type = TOKEN_FLOAT;
  1247. }
  1248. if (tline->type == TOK_STRING) {
  1249. char bq, *ep;
  1250. bq = tline->text[0];
  1251. tokval->t_charptr = tline->text;
  1252. tokval->t_inttwo = nasm_unquote(tline->text, &ep);
  1253. if (ep[0] != bq || ep[1] != '\0')
  1254. return tokval->t_type = TOKEN_ERRSTR;
  1255. else
  1256. return tokval->t_type = TOKEN_STR;
  1257. }
  1258. if (tline->type == TOK_OTHER) {
  1259. if (!strcmp(tline->text, "<<"))
  1260. return tokval->t_type = TOKEN_SHL;
  1261. if (!strcmp(tline->text, ">>"))
  1262. return tokval->t_type = TOKEN_SHR;
  1263. if (!strcmp(tline->text, "//"))
  1264. return tokval->t_type = TOKEN_SDIV;
  1265. if (!strcmp(tline->text, "%%"))
  1266. return tokval->t_type = TOKEN_SMOD;
  1267. if (!strcmp(tline->text, "=="))
  1268. return tokval->t_type = TOKEN_EQ;
  1269. if (!strcmp(tline->text, "<>"))
  1270. return tokval->t_type = TOKEN_NE;
  1271. if (!strcmp(tline->text, "!="))
  1272. return tokval->t_type = TOKEN_NE;
  1273. if (!strcmp(tline->text, "<="))
  1274. return tokval->t_type = TOKEN_LE;
  1275. if (!strcmp(tline->text, ">="))
  1276. return tokval->t_type = TOKEN_GE;
  1277. if (!strcmp(tline->text, "&&"))
  1278. return tokval->t_type = TOKEN_DBL_AND;
  1279. if (!strcmp(tline->text, "^^"))
  1280. return tokval->t_type = TOKEN_DBL_XOR;
  1281. if (!strcmp(tline->text, "||"))
  1282. return tokval->t_type = TOKEN_DBL_OR;
  1283. }
  1284. /*
  1285. * We have no other options: just return the first character of
  1286. * the token text.
  1287. */
  1288. return tokval->t_type = tline->text[0];
  1289. }
  1290. /*
  1291. * Compare a string to the name of an existing macro; this is a
  1292. * simple wrapper which calls either strcmp or nasm_stricmp
  1293. * depending on the value of the `casesense' parameter.
  1294. */
  1295. static int mstrcmp(const char *p, const char *q, bool casesense)
  1296. {
  1297. return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
  1298. }
  1299. /*
  1300. * Compare a string to the name of an existing macro; this is a
  1301. * simple wrapper which calls either strcmp or nasm_stricmp
  1302. * depending on the value of the `casesense' parameter.
  1303. */
  1304. static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
  1305. {
  1306. return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
  1307. }
  1308. /*
  1309. * Return the Context structure associated with a %$ token. Return
  1310. * NULL, having _already_ reported an error condition, if the
  1311. * context stack isn't deep enough for the supplied number of $
  1312. * signs.
  1313. *
  1314. * If "namep" is non-NULL, set it to the pointer to the macro name
  1315. * tail, i.e. the part beyond %$...
  1316. */
  1317. static Context *get_ctx(const char *name, const char **namep)
  1318. {
  1319. Context *ctx;
  1320. int i;
  1321. if (namep)
  1322. *namep = name;
  1323. if (!name || name[0] != '%' || name[1] != '$')
  1324. return NULL;
  1325. if (!cstk) {
  1326. nasm_error(ERR_NONFATAL, "`%s': context stack is empty", name);
  1327. return NULL;
  1328. }
  1329. name += 2;
  1330. ctx = cstk;
  1331. i = 0;
  1332. while (ctx && *name == '$') {
  1333. name++;
  1334. i++;
  1335. ctx = ctx->next;
  1336. }
  1337. if (!ctx) {
  1338. nasm_error(ERR_NONFATAL, "`%s': context stack is only"
  1339. " %d level%s deep", name, i, (i == 1 ? "" : "s"));
  1340. return NULL;
  1341. }
  1342. if (namep)
  1343. *namep = name;
  1344. return ctx;
  1345. }
  1346. /*
  1347. * Open an include file. This routine must always return a valid
  1348. * file pointer if it returns - it's responsible for throwing an
  1349. * ERR_FATAL and bombing out completely if not. It should also try
  1350. * the include path one by one until it finds the file or reaches
  1351. * the end of the path.
  1352. *
  1353. * Note: for INC_PROBE the function returns NULL at all times;
  1354. * instead look for the
  1355. */
  1356. enum incopen_mode {
  1357. INC_NEEDED, /* File must exist */
  1358. INC_OPTIONAL, /* Missing is OK */
  1359. INC_PROBE /* Only an existence probe */
  1360. };
  1361. /* This is conducts a full pathname search */
  1362. static FILE *inc_fopen_search(const char *file, StrList **slpath,
  1363. enum incopen_mode omode, enum file_flags fmode)
  1364. {
  1365. FILE *fp;
  1366. char *prefix = "";
  1367. const IncPath *ip = ipath;
  1368. int len;
  1369. StrList *sl;
  1370. char *sp;
  1371. bool found;
  1372. while (1) {
  1373. sp = nasm_catfile(prefix, file);
  1374. len = strlen(sp) + 1;
  1375. sl = nasm_malloc(len + sizeof sl->next);
  1376. memcpy(sl->str, sp, len);
  1377. sl->next = NULL;
  1378. nasm_free(sp);
  1379. if (omode == INC_PROBE) {
  1380. fp = NULL;
  1381. found = nasm_file_exists(sl->str);
  1382. } else {
  1383. fp = nasm_open_read(sl->str, fmode);
  1384. found = (fp != NULL);
  1385. }
  1386. if (found) {
  1387. *slpath = sl;
  1388. return fp;
  1389. }
  1390. nasm_free(sl);
  1391. if (!ip)
  1392. return NULL;
  1393. prefix = ip->path;
  1394. ip = ip->next;
  1395. }
  1396. }
  1397. /*
  1398. * Open a file, or test for the presence of one (depending on omode),
  1399. * considering the include path.
  1400. */
  1401. static FILE *inc_fopen(const char *file,
  1402. StrList **dhead,
  1403. const char **found_path,
  1404. enum incopen_mode omode,
  1405. enum file_flags fmode)
  1406. {
  1407. StrList *sl;
  1408. struct hash_insert hi;
  1409. void **hp;
  1410. char *path;
  1411. FILE *fp = NULL;
  1412. hp = hash_find(&FileHash, file, &hi);
  1413. if (hp) {
  1414. path = *hp;
  1415. if (path || omode != INC_NEEDED) {
  1416. nasm_add_string_to_strlist(dhead, path ? path : file);
  1417. }
  1418. } else {
  1419. /* Need to do the actual path search */
  1420. size_t file_len;
  1421. sl = NULL;
  1422. fp = inc_fopen_search(file, &sl, omode, fmode);
  1423. file_len = strlen(file);
  1424. if (!sl) {
  1425. /* Store negative result for this file */
  1426. sl = nasm_malloc(file_len + 1 + sizeof sl->next);
  1427. memcpy(sl->str, file, file_len+1);
  1428. sl->next = NULL;
  1429. file = sl->str;
  1430. path = NULL;
  1431. } else {
  1432. path = sl->str;
  1433. file = strchr(path, '\0') - file_len;
  1434. }
  1435. hash_add(&hi, file, path); /* Positive or negative result */
  1436. /*
  1437. * Add file to dependency path. The in_list() is needed
  1438. * in case the file was already added with %depend.
  1439. */
  1440. if (path || omode != INC_NEEDED)
  1441. nasm_add_to_strlist(dhead, sl);
  1442. }
  1443. if (!path) {
  1444. if (omode == INC_NEEDED)
  1445. nasm_fatal(0, "unable to open include file `%s'", file);
  1446. if (found_path)
  1447. *found_path = NULL;
  1448. return NULL;
  1449. }
  1450. if (!fp && omode != INC_PROBE)
  1451. fp = nasm_open_read(path, fmode);
  1452. if (found_path)
  1453. *found_path = path;
  1454. return fp;
  1455. }
  1456. /*
  1457. * Opens an include or input file. Public version, for use by modules
  1458. * that get a file:lineno pair and need to look at the file again
  1459. * (e.g. the CodeView debug backend). Returns NULL on failure.
  1460. */
  1461. FILE *pp_input_fopen(const char *filename, enum file_flags mode)
  1462. {
  1463. return inc_fopen(filename, NULL, NULL, INC_OPTIONAL, mode);
  1464. }
  1465. /*
  1466. * Determine if we should warn on defining a single-line macro of
  1467. * name `name', with `nparam' parameters. If nparam is 0 or -1, will
  1468. * return true if _any_ single-line macro of that name is defined.
  1469. * Otherwise, will return true if a single-line macro with either
  1470. * `nparam' or no parameters is defined.
  1471. *
  1472. * If a macro with precisely the right number of parameters is
  1473. * defined, or nparam is -1, the address of the definition structure
  1474. * will be returned in `defn'; otherwise NULL will be returned. If `defn'
  1475. * is NULL, no action will be taken regarding its contents, and no
  1476. * error will occur.
  1477. *
  1478. * Note that this is also called with nparam zero to resolve
  1479. * `ifdef'.
  1480. *
  1481. * If you already know which context macro belongs to, you can pass
  1482. * the context pointer as first parameter; if you won't but name begins
  1483. * with %$ the context will be automatically computed. If all_contexts
  1484. * is true, macro will be searched in outer contexts as well.
  1485. */
  1486. static bool
  1487. smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
  1488. bool nocase)
  1489. {
  1490. struct hash_table *smtbl;
  1491. SMacro *m;
  1492. if (ctx) {
  1493. smtbl = &ctx->localmac;
  1494. } else if (name[0] == '%' && name[1] == '$') {
  1495. if (cstk)
  1496. ctx = get_ctx(name, &name);
  1497. if (!ctx)
  1498. return false; /* got to return _something_ */
  1499. smtbl = &ctx->localmac;
  1500. } else {
  1501. smtbl = &smacros;
  1502. }
  1503. m = (SMacro *) hash_findix(smtbl, name);
  1504. while (m) {
  1505. if (!mstrcmp(m->name, name, m->casesense && nocase) &&
  1506. (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
  1507. if (defn) {
  1508. if (nparam == (int) m->nparam || nparam == -1)
  1509. *defn = m;
  1510. else
  1511. *defn = NULL;
  1512. }
  1513. return true;
  1514. }
  1515. m = m->next;
  1516. }
  1517. return false;
  1518. }
  1519. /*
  1520. * Count and mark off the parameters in a multi-line macro call.
  1521. * This is called both from within the multi-line macro expansion
  1522. * code, and also to mark off the default parameters when provided
  1523. * in a %macro definition line.
  1524. */
  1525. static void count_mmac_params(Token * t, int *nparam, Token *** params)
  1526. {
  1527. int paramsize, brace;
  1528. *nparam = paramsize = 0;
  1529. *params = NULL;
  1530. while (t) {
  1531. /* +1: we need space for the final NULL */
  1532. if (*nparam+1 >= paramsize) {
  1533. paramsize += PARAM_DELTA;
  1534. *params = nasm_realloc(*params, sizeof(**params) * paramsize);
  1535. }
  1536. skip_white_(t);
  1537. brace = 0;
  1538. if (tok_is_(t, "{"))
  1539. brace++;
  1540. (*params)[(*nparam)++] = t;
  1541. if (brace) {
  1542. while (brace && (t = t->next) != NULL) {
  1543. if (tok_is_(t, "{"))
  1544. brace++;
  1545. else if (tok_is_(t, "}"))
  1546. brace--;
  1547. }
  1548. if (t) {
  1549. /*
  1550. * Now we've found the closing brace, look further
  1551. * for the comma.
  1552. */
  1553. t = t->next;
  1554. skip_white_(t);
  1555. if (tok_isnt_(t, ",")) {
  1556. nasm_error(ERR_NONFATAL,
  1557. "braces do not enclose all of macro parameter");
  1558. while (tok_isnt_(t, ","))
  1559. t = t->next;
  1560. }
  1561. }
  1562. } else {
  1563. while (tok_isnt_(t, ","))
  1564. t = t->next;
  1565. }
  1566. if (t) { /* got a comma/brace */
  1567. t = t->next; /* eat the comma */
  1568. }
  1569. }
  1570. }
  1571. /*
  1572. * Determine whether one of the various `if' conditions is true or
  1573. * not.
  1574. *
  1575. * We must free the tline we get passed.
  1576. */
  1577. static bool if_condition(Token * tline, enum preproc_token ct)
  1578. {
  1579. enum pp_conditional i = PP_COND(ct);
  1580. bool j;
  1581. Token *t, *tt, **tptr, *origline;
  1582. struct tokenval tokval;
  1583. expr *evalresult;
  1584. enum pp_token_type needtype;
  1585. char *p;
  1586. origline = tline;
  1587. switch (i) {
  1588. case PPC_IFCTX:
  1589. j = false; /* have we matched yet? */
  1590. while (true) {
  1591. skip_white_(tline);
  1592. if (!tline)
  1593. break;
  1594. if (tline->type != TOK_ID) {
  1595. nasm_error(ERR_NONFATAL,
  1596. "`%s' expects context identifiers", pp_directives[ct]);
  1597. free_tlist(origline);
  1598. return -1;
  1599. }
  1600. if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
  1601. j = true;
  1602. tline = tline->next;
  1603. }
  1604. break;
  1605. case PPC_IFDEF:
  1606. j = false; /* have we matched yet? */
  1607. while (tline) {
  1608. skip_white_(tline);
  1609. if (!tline || (tline->type != TOK_ID &&
  1610. (tline->type != TOK_PREPROC_ID ||
  1611. tline->text[1] != '$'))) {
  1612. nasm_error(ERR_NONFATAL,
  1613. "`%s' expects macro identifiers", pp_directives[ct]);
  1614. goto fail;
  1615. }
  1616. if (smacro_defined(NULL, tline->text, 0, NULL, true))
  1617. j = true;
  1618. tline = tline->next;
  1619. }
  1620. break;
  1621. case PPC_IFENV:
  1622. tline = expand_smacro(tline);
  1623. j = false; /* have we matched yet? */
  1624. while (tline) {
  1625. skip_white_(tline);
  1626. if (!tline || (tline->type != TOK_ID &&
  1627. tline->type != TOK_STRING &&
  1628. (tline->type != TOK_PREPROC_ID ||
  1629. tline->text[1] != '!'))) {
  1630. nasm_error(ERR_NONFATAL,
  1631. "`%s' expects environment variable names",
  1632. pp_directives[ct]);
  1633. goto fail;
  1634. }
  1635. p = tline->text;
  1636. if (tline->type == TOK_PREPROC_ID)
  1637. p += 2; /* Skip leading %! */
  1638. if (*p == '\'' || *p == '\"' || *p == '`')
  1639. nasm_unquote_cstr(p, ct);
  1640. if (getenv(p))
  1641. j = true;
  1642. tline = tline->next;
  1643. }
  1644. break;
  1645. case PPC_IFIDN:
  1646. case PPC_IFIDNI:
  1647. tline = expand_smacro(tline);
  1648. t = tt = tline;
  1649. while (tok_isnt_(tt, ","))
  1650. tt = tt->next;
  1651. if (!tt) {
  1652. nasm_error(ERR_NONFATAL,
  1653. "`%s' expects two comma-separated arguments",
  1654. pp_directives[ct]);
  1655. goto fail;
  1656. }
  1657. tt = tt->next;
  1658. j = true; /* assume equality unless proved not */
  1659. while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
  1660. if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
  1661. nasm_error(ERR_NONFATAL, "`%s': more than one comma on line",
  1662. pp_directives[ct]);
  1663. goto fail;
  1664. }
  1665. if (t->type == TOK_WHITESPACE) {
  1666. t = t->next;
  1667. continue;
  1668. }
  1669. if (tt->type == TOK_WHITESPACE) {
  1670. tt = tt->next;
  1671. continue;
  1672. }
  1673. if (tt->type != t->type) {
  1674. j = false; /* found mismatching tokens */
  1675. break;
  1676. }
  1677. /* When comparing strings, need to unquote them first */
  1678. if (t->type == TOK_STRING) {
  1679. size_t l1 = nasm_unquote(t->text, NULL);
  1680. size_t l2 = nasm_unquote(tt->text, NULL);
  1681. if (l1 != l2) {
  1682. j = false;
  1683. break;
  1684. }
  1685. if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
  1686. j = false;
  1687. break;
  1688. }
  1689. } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
  1690. j = false; /* found mismatching tokens */
  1691. break;
  1692. }
  1693. t = t->next;
  1694. tt = tt->next;
  1695. }
  1696. if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
  1697. j = false; /* trailing gunk on one end or other */
  1698. break;
  1699. case PPC_IFMACRO:
  1700. {
  1701. bool found = false;
  1702. MMacro searching, *mmac;
  1703. skip_white_(tline);
  1704. tline = expand_id(tline);
  1705. if (!tok_type_(tline, TOK_ID)) {
  1706. nasm_error(ERR_NONFATAL,
  1707. "`%s' expects a macro name", pp_directives[ct]);
  1708. goto fail;
  1709. }
  1710. searching.name = nasm_strdup(tline->text);
  1711. searching.casesense = true;
  1712. searching.plus = false;
  1713. searching.nolist = false;
  1714. searching.in_progress = 0;
  1715. searching.max_depth = 0;
  1716. searching.rep_nest = NULL;
  1717. searching.nparam_min = 0;
  1718. searching.nparam_max = INT_MAX;
  1719. tline = expand_smacro(tline->next);
  1720. skip_white_(tline);
  1721. if (!tline) {
  1722. } else if (!tok_type_(tline, TOK_NUMBER)) {
  1723. nasm_error(ERR_NONFATAL,
  1724. "`%s' expects a parameter count or nothing",
  1725. pp_directives[ct]);
  1726. } else {
  1727. searching.nparam_min = searching.nparam_max =
  1728. readnum(tline->text, &j);
  1729. if (j)
  1730. nasm_error(ERR_NONFATAL,
  1731. "unable to parse parameter count `%s'",
  1732. tline->text);
  1733. }
  1734. if (tline && tok_is_(tline->next, "-")) {
  1735. tline = tline->next->next;
  1736. if (tok_is_(tline, "*"))
  1737. searching.nparam_max = INT_MAX;
  1738. else if (!tok_type_(tline, TOK_NUMBER))
  1739. nasm_error(ERR_NONFATAL,
  1740. "`%s' expects a parameter count after `-'",
  1741. pp_directives[ct]);
  1742. else {
  1743. searching.nparam_max = readnum(tline->text, &j);
  1744. if (j)
  1745. nasm_error(ERR_NONFATAL,
  1746. "unable to parse parameter count `%s'",
  1747. tline->text);
  1748. if (searching.nparam_min > searching.nparam_max) {
  1749. nasm_error(ERR_NONFATAL,
  1750. "minimum parameter count exceeds maximum");
  1751. searching.nparam_max = searching.nparam_min;
  1752. }
  1753. }
  1754. }
  1755. if (tline && tok_is_(tline->next, "+")) {
  1756. tline = tline->next;
  1757. searching.plus = true;
  1758. }
  1759. mmac = (MMacro *) hash_findix(&mmacros, searching.name);
  1760. while (mmac) {
  1761. if (!strcmp(mmac->name, searching.name) &&
  1762. (mmac->nparam_min <= searching.nparam_max
  1763. || searching.plus)
  1764. && (searching.nparam_min <= mmac->nparam_max
  1765. || mmac->plus)) {
  1766. found = true;
  1767. break;
  1768. }
  1769. mmac = mmac->next;
  1770. }
  1771. if (tline && tline->next)
  1772. nasm_error(ERR_WARNING|ERR_PASS1,
  1773. "trailing garbage after %%ifmacro ignored");
  1774. nasm_free(searching.name);
  1775. j = found;
  1776. break;
  1777. }
  1778. case PPC_IFID:
  1779. needtype = TOK_ID;
  1780. goto iftype;
  1781. case PPC_IFNUM:
  1782. needtype = TOK_NUMBER;
  1783. goto iftype;
  1784. case PPC_IFSTR:
  1785. needtype = TOK_STRING;
  1786. goto iftype;
  1787. iftype:
  1788. t = tline = expand_smacro(tline);
  1789. while (tok_type_(t, TOK_WHITESPACE) ||
  1790. (needtype == TOK_NUMBER &&
  1791. tok_type_(t, TOK_OTHER) &&
  1792. (t->text[0] == '-' || t->text[0] == '+') &&
  1793. !t->text[1]))
  1794. t = t->next;
  1795. j = tok_type_(t, needtype);
  1796. break;
  1797. case PPC_IFTOKEN:
  1798. t = tline = expand_smacro(tline);
  1799. while (tok_type_(t, TOK_WHITESPACE))
  1800. t = t->next;
  1801. j = false;
  1802. if (t) {
  1803. t = t->next; /* Skip the actual token */
  1804. while (tok_type_(t, TOK_WHITESPACE))
  1805. t = t->next;
  1806. j = !t; /* Should be nothing left */
  1807. }
  1808. break;
  1809. case PPC_IFEMPTY:
  1810. t = tline = expand_smacro(tline);
  1811. while (tok_type_(t, TOK_WHITESPACE))
  1812. t = t->next;
  1813. j = !t; /* Should be empty */
  1814. break;
  1815. case PPC_IF:
  1816. t = tline = expand_smacro(tline);
  1817. tptr = &t;
  1818. tokval.t_type = TOKEN_INVALID;
  1819. evalresult = evaluate(ppscan, tptr, &tokval,
  1820. NULL, pass | CRITICAL, NULL);
  1821. if (!evalresult)
  1822. return -1;
  1823. if (tokval.t_type)
  1824. nasm_error(ERR_WARNING|ERR_PASS1,
  1825. "trailing garbage after expression ignored");
  1826. if (!is_simple(evalresult)) {
  1827. nasm_error(ERR_NONFATAL,
  1828. "non-constant value given to `%s'", pp_directives[ct]);
  1829. goto fail;
  1830. }
  1831. j = reloc_value(evalresult) != 0;
  1832. break;
  1833. default:
  1834. nasm_error(ERR_FATAL,
  1835. "preprocessor directive `%s' not yet implemented",
  1836. pp_directives[ct]);
  1837. goto fail;
  1838. }
  1839. free_tlist(origline);
  1840. return j ^ PP_NEGATIVE(ct);
  1841. fail:
  1842. free_tlist(origline);
  1843. return -1;
  1844. }
  1845. /*
  1846. * Common code for defining an smacro
  1847. */
  1848. static bool define_smacro(Context *ctx, const char *mname, bool casesense,
  1849. int nparam, Token *expansion)
  1850. {
  1851. SMacro *smac, **smhead;
  1852. struct hash_table *smtbl;
  1853. if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
  1854. if (!smac) {
  1855. nasm_error(ERR_WARNING|ERR_PASS1,
  1856. "single-line macro `%s' defined both with and"
  1857. " without parameters", mname);
  1858. /*
  1859. * Some instances of the old code considered this a failure,
  1860. * some others didn't. What is the right thing to do here?
  1861. */
  1862. free_tlist(expansion);
  1863. return false; /* Failure */
  1864. } else {
  1865. /*
  1866. * We're redefining, so we have to take over an
  1867. * existing SMacro structure. This means freeing
  1868. * what was already in it.
  1869. */
  1870. nasm_free(smac->name);
  1871. free_tlist(smac->expansion);
  1872. }
  1873. } else {
  1874. smtbl = ctx ? &ctx->localmac : &smacros;
  1875. smhead = (SMacro **) hash_findi_add(smtbl, mname);
  1876. smac = nasm_malloc(sizeof(SMacro));
  1877. smac->next = *smhead;
  1878. *smhead = smac;
  1879. }
  1880. smac->name = nasm_strdup(mname);
  1881. smac->casesense = casesense;
  1882. smac->nparam = nparam;
  1883. smac->expansion = expansion;
  1884. smac->in_progress = false;
  1885. return true; /* Success */
  1886. }
  1887. /*
  1888. * Undefine an smacro
  1889. */
  1890. static void undef_smacro(Context *ctx, const char *mname)
  1891. {
  1892. SMacro **smhead, *s, **sp;
  1893. struct hash_table *smtbl;
  1894. smtbl = ctx ? &ctx->localmac : &smacros;
  1895. smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
  1896. if (smhead) {
  1897. /*
  1898. * We now have a macro name... go hunt for it.
  1899. */
  1900. sp = smhead;
  1901. while ((s = *sp) != NULL) {
  1902. if (!mstrcmp(s->name, mname, s->casesense)) {
  1903. *sp = s->next;
  1904. nasm_free(s->name);
  1905. free_tlist(s->expansion);
  1906. nasm_free(s);
  1907. } else {
  1908. sp = &s->next;
  1909. }
  1910. }
  1911. }
  1912. }
  1913. /*
  1914. * Parse a mmacro specification.
  1915. */
  1916. static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
  1917. {
  1918. bool err;
  1919. tline = tline->next;
  1920. skip_white_(tline);
  1921. tline = expand_id(tline);
  1922. if (!tok_type_(tline, TOK_ID)) {
  1923. nasm_error(ERR_NONFATAL, "`%s' expects a macro name", directive);
  1924. return false;
  1925. }
  1926. def->prev = NULL;
  1927. def->name = nasm_strdup(tline->text);
  1928. def->plus = false;
  1929. def->nolist = false;
  1930. def->in_progress = 0;
  1931. def->rep_nest = NULL;
  1932. def->nparam_min = 0;
  1933. def->nparam_max = 0;
  1934. tline = expand_smacro(tline->next);
  1935. skip_white_(tline);
  1936. if (!tok_type_(tline, TOK_NUMBER)) {
  1937. nasm_error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
  1938. } else {
  1939. def->nparam_min = def->nparam_max =
  1940. readnum(tline->text, &err);
  1941. if (err)
  1942. nasm_error(ERR_NONFATAL,
  1943. "unable to parse parameter count `%s'", tline->text);
  1944. }
  1945. if (tline && tok_is_(tline->next, "-")) {
  1946. tline = tline->next->next;
  1947. if (tok_is_(tline, "*")) {
  1948. def->nparam_max = INT_MAX;
  1949. } else if (!tok_type_(tline, TOK_NUMBER)) {
  1950. nasm_error(ERR_NONFATAL,
  1951. "`%s' expects a parameter count after `-'", directive);
  1952. } else {
  1953. def->nparam_max = readnum(tline->text, &err);
  1954. if (err) {
  1955. nasm_error(ERR_NONFATAL, "unable to parse parameter count `%s'",
  1956. tline->text);
  1957. }
  1958. if (def->nparam_min > def->nparam_max) {
  1959. nasm_error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
  1960. def->nparam_max = def->nparam_min;
  1961. }
  1962. }
  1963. }
  1964. if (tline && tok_is_(tline->next, "+")) {
  1965. tline = tline->next;
  1966. def->plus = true;
  1967. }
  1968. if (tline && tok_type_(tline->next, TOK_ID) &&
  1969. !nasm_stricmp(tline->next->text, ".nolist")) {
  1970. tline = tline->next;
  1971. def->nolist = true;
  1972. }
  1973. /*
  1974. * Handle default parameters.
  1975. */
  1976. if (tline && tline->next) {
  1977. def->dlist = tline->next;
  1978. tline->next = NULL;
  1979. count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
  1980. } else {
  1981. def->dlist = NULL;
  1982. def->defaults = NULL;
  1983. }
  1984. def->expansion = NULL;
  1985. if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
  1986. !def->plus)
  1987. nasm_error(ERR_WARNING|ERR_PASS1|WARN_MDP,
  1988. "too many default macro parameters");
  1989. return true;
  1990. }
  1991. /*
  1992. * Decode a size directive
  1993. */
  1994. static int parse_size(const char *str) {
  1995. static const char *size_names[] =
  1996. { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
  1997. static const int sizes[] =
  1998. { 0, 1, 4, 16, 8, 10, 2, 32 };
  1999. return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0;
  2000. }
  2001. /*
  2002. * Process a preprocessor %pragma directive. Currently there are none.
  2003. * Gets passed the token list starting with the "preproc" token from
  2004. * "%pragma preproc".
  2005. */
  2006. static void do_pragma_preproc(Token *tline)
  2007. {
  2008. /* Skip to the real stuff */
  2009. tline = tline->next;
  2010. skip_white_(tline);
  2011. if (!tline)
  2012. return;
  2013. (void)tline; /* Nothing else to do at present */
  2014. }
  2015. /**
  2016. * find and process preprocessor directive in passed line
  2017. * Find out if a line contains a preprocessor directive, and deal
  2018. * with it if so.
  2019. *
  2020. * If a directive _is_ found, it is the responsibility of this routine
  2021. * (and not the caller) to free_tlist() the line.
  2022. *
  2023. * @param tline a pointer to the current tokeninzed line linked list
  2024. * @param output if this directive generated output
  2025. * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
  2026. *
  2027. */
  2028. static int do_directive(Token *tline, char **output)
  2029. {
  2030. enum preproc_token i;
  2031. int j;
  2032. bool err;
  2033. int nparam;
  2034. bool nolist;
  2035. bool casesense;
  2036. int k, m;
  2037. int offset;
  2038. char *p, *pp;
  2039. const char *found_path;
  2040. const char *mname;
  2041. Include *inc;
  2042. Context *ctx;
  2043. Cond *cond;
  2044. MMacro *mmac, **mmhead;
  2045. Token *t = NULL, *tt, *param_start, *macro_start, *last, **tptr, *origline;
  2046. Line *l;
  2047. struct tokenval tokval;
  2048. expr *evalresult;
  2049. MMacro *tmp_defining; /* Used when manipulating rep_nest */
  2050. int64_t count;
  2051. size_t len;
  2052. int severity;
  2053. *output = NULL; /* No output generated */
  2054. origline = tline;
  2055. skip_white_(tline);
  2056. if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
  2057. (tline->text[0] && (tline->text[1] == '%' ||
  2058. tline->text[1] == '$' ||
  2059. tline->text[1] == '!')))
  2060. return NO_DIRECTIVE_FOUND;
  2061. i = pp_token_hash(tline->text);
  2062. /*
  2063. * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
  2064. * since they are known to be buggy at moment, we need to fix them
  2065. * in future release (2.09-2.10)
  2066. */
  2067. if (i == PP_RMACRO || i == PP_IRMACRO || i == PP_EXITMACRO) {
  2068. nasm_error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
  2069. tline->text);
  2070. return NO_DIRECTIVE_FOUND;
  2071. }
  2072. /*
  2073. * If we're in a non-emitting branch of a condition construct,
  2074. * or walking to the end of an already terminated %rep block,
  2075. * we should ignore all directives except for condition
  2076. * directives.
  2077. */
  2078. if (((istk->conds && !emitting(istk->conds->state)) ||
  2079. (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
  2080. return NO_DIRECTIVE_FOUND;
  2081. }
  2082. /*
  2083. * If we're defining a macro or reading a %rep block, we should
  2084. * ignore all directives except for %macro/%imacro (which nest),
  2085. * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
  2086. * If we're in a %rep block, another %rep nests, so should be let through.
  2087. */
  2088. if (defining && i != PP_MACRO && i != PP_IMACRO &&
  2089. i != PP_RMACRO && i != PP_IRMACRO &&
  2090. i != PP_ENDMACRO && i != PP_ENDM &&
  2091. (defining->name || (i != PP_ENDREP && i != PP_REP))) {
  2092. return NO_DIRECTIVE_FOUND;
  2093. }
  2094. if (defining) {
  2095. if (i == PP_MACRO || i == PP_IMACRO ||
  2096. i == PP_RMACRO || i == PP_IRMACRO) {
  2097. nested_mac_count++;
  2098. return NO_DIRECTIVE_FOUND;
  2099. } else if (nested_mac_count > 0) {
  2100. if (i == PP_ENDMACRO) {
  2101. nested_mac_count--;
  2102. return NO_DIRECTIVE_FOUND;
  2103. }
  2104. }
  2105. if (!defining->name) {
  2106. if (i == PP_REP) {
  2107. nested_rep_count++;
  2108. return NO_DIRECTIVE_FOUND;
  2109. } else if (nested_rep_count > 0) {
  2110. if (i == PP_ENDREP) {
  2111. nested_rep_count--;
  2112. return NO_DIRECTIVE_FOUND;
  2113. }
  2114. }
  2115. }
  2116. }
  2117. switch (i) {
  2118. case PP_INVALID:
  2119. nasm_error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
  2120. tline->text);
  2121. return NO_DIRECTIVE_FOUND; /* didn't get it */
  2122. case PP_PRAGMA:
  2123. /*
  2124. * %pragma namespace options...
  2125. *
  2126. * The namespace "preproc" is reserved for the preprocessor;
  2127. * all other namespaces generate a [pragma] assembly directive.
  2128. *
  2129. * Invalid %pragmas are ignored and may have different
  2130. * meaning in future versions of NASM.
  2131. */
  2132. tline = tline->next;
  2133. skip_white_(tline);
  2134. tline = expand_smacro(tline);
  2135. if (tok_type_(tline, TOK_ID)) {
  2136. if (!nasm_stricmp(tline->text, "preproc")) {
  2137. /* Preprocessor pragma */
  2138. do_pragma_preproc(tline);
  2139. } else {
  2140. /* Build the assembler directive */
  2141. t = new_Token(NULL, TOK_OTHER, "[", 1);
  2142. t->next = new_Token(NULL, TOK_ID, "pragma", 6);
  2143. t->next->next = new_Token(tline, TOK_WHITESPACE, NULL, 0);
  2144. tline = t;
  2145. for (t = tline; t->next; t = t->next)
  2146. ;
  2147. t->next = new_Token(NULL, TOK_OTHER, "]", 1);
  2148. /* true here can be revisited in the future */
  2149. *output = detoken(tline, true);
  2150. }
  2151. }
  2152. free_tlist(origline);
  2153. return DIRECTIVE_FOUND;
  2154. case PP_STACKSIZE:
  2155. /* Directive to tell NASM what the default stack size is. The
  2156. * default is for a 16-bit stack, and this can be overriden with
  2157. * %stacksize large.
  2158. */
  2159. tline = tline->next;
  2160. if (tline && tline->type == TOK_WHITESPACE)
  2161. tline = tline->next;
  2162. if (!tline || tline->type != TOK_ID) {
  2163. nasm_error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
  2164. free_tlist(origline);
  2165. return DIRECTIVE_FOUND;
  2166. }
  2167. if (nasm_stricmp(tline->text, "flat") == 0) {
  2168. /* All subsequent ARG directives are for a 32-bit stack */
  2169. StackSize = 4;
  2170. StackPointer = "ebp";
  2171. ArgOffset = 8;
  2172. LocalOffset = 0;
  2173. } else if (nasm_stricmp(tline->text, "flat64") == 0) {
  2174. /* All subsequent ARG directives are for a 64-bit stack */
  2175. StackSize = 8;
  2176. StackPointer = "rbp";
  2177. ArgOffset = 16;
  2178. LocalOffset = 0;
  2179. } else if (nasm_stricmp(tline->text, "large") == 0) {
  2180. /* All subsequent ARG directives are for a 16-bit stack,
  2181. * far function call.
  2182. */
  2183. StackSize = 2;
  2184. StackPointer = "bp";
  2185. ArgOffset = 4;
  2186. LocalOffset = 0;
  2187. } else if (nasm_stricmp(tline->text, "small") == 0) {
  2188. /* All subsequent ARG directives are for a 16-bit stack,
  2189. * far function call. We don't support near functions.
  2190. */
  2191. StackSize = 2;
  2192. StackPointer = "bp";
  2193. ArgOffset = 6;
  2194. LocalOffset = 0;
  2195. } else {
  2196. nasm_error(ERR_NONFATAL, "`%%stacksize' invalid size type");
  2197. free_tlist(origline);
  2198. return DIRECTIVE_FOUND;
  2199. }
  2200. free_tlist(origline);
  2201. return DIRECTIVE_FOUND;
  2202. case PP_ARG:
  2203. /* TASM like ARG directive to define arguments to functions, in
  2204. * the following form:
  2205. *
  2206. * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
  2207. */
  2208. offset = ArgOffset;
  2209. do {
  2210. char *arg, directive[256];
  2211. int size = StackSize;
  2212. /* Find the argument name */
  2213. tline = tline->next;
  2214. if (tline && tline->type == TOK_WHITESPACE)
  2215. tline = tline->next;
  2216. if (!tline || tline->type != TOK_ID) {
  2217. nasm_error(ERR_NONFATAL, "`%%arg' missing argument parameter");
  2218. free_tlist(origline);
  2219. return DIRECTIVE_FOUND;
  2220. }
  2221. arg = tline->text;
  2222. /* Find the argument size type */
  2223. tline = tline->next;
  2224. if (!tline || tline->type != TOK_OTHER
  2225. || tline->text[0] != ':') {
  2226. nasm_error(ERR_NONFATAL,
  2227. "Syntax error processing `%%arg' directive");
  2228. free_tlist(origline);
  2229. return DIRECTIVE_FOUND;
  2230. }
  2231. tline = tline->next;
  2232. if (!tline || tline->type != TOK_ID) {
  2233. nasm_error(ERR_NONFATAL, "`%%arg' missing size type parameter");
  2234. free_tlist(origline);
  2235. return DIRECTIVE_FOUND;
  2236. }
  2237. /* Allow macro expansion of type parameter */
  2238. tt = tokenize(tline->text);
  2239. tt = expand_smacro(tt);
  2240. size = parse_size(tt->text);
  2241. if (!size) {
  2242. nasm_error(ERR_NONFATAL,
  2243. "Invalid size type for `%%arg' missing directive");
  2244. free_tlist(tt);
  2245. free_tlist(origline);
  2246. return DIRECTIVE_FOUND;
  2247. }
  2248. free_tlist(tt);
  2249. /* Round up to even stack slots */
  2250. size = ALIGN(size, StackSize);
  2251. /* Now define the macro for the argument */
  2252. snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
  2253. arg, StackPointer, offset);
  2254. do_directive(tokenize(directive), output);
  2255. offset += size;
  2256. /* Move to the next argument in the list */
  2257. tline = tline->next;
  2258. if (tline && tline->type == TOK_WHITESPACE)
  2259. tline = tline->next;
  2260. } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
  2261. ArgOffset = offset;
  2262. free_tlist(origline);
  2263. return DIRECTIVE_FOUND;
  2264. case PP_LOCAL:
  2265. /* TASM like LOCAL directive to define local variables for a
  2266. * function, in the following form:
  2267. *
  2268. * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
  2269. *
  2270. * The '= LocalSize' at the end is ignored by NASM, but is
  2271. * required by TASM to define the local parameter size (and used
  2272. * by the TASM macro package).
  2273. */
  2274. offset = LocalOffset;
  2275. do {
  2276. char *local, directive[256];
  2277. int size = StackSize;
  2278. /* Find the argument name */
  2279. tline = tline->next;
  2280. if (tline && tline->type == TOK_WHITESPACE)
  2281. tline = tline->next;
  2282. if (!tline || tline->type != TOK_ID) {
  2283. nasm_error(ERR_NONFATAL,
  2284. "`%%local' missing argument parameter");
  2285. free_tlist(origline);
  2286. return DIRECTIVE_FOUND;
  2287. }
  2288. local = tline->text;
  2289. /* Find the argument size type */
  2290. tline = tline->next;
  2291. if (!tline || tline->type != TOK_OTHER
  2292. || tline->text[0] != ':') {
  2293. nasm_error(ERR_NONFATAL,
  2294. "Syntax error processing `%%local' directive");
  2295. free_tlist(origline);
  2296. return DIRECTIVE_FOUND;
  2297. }
  2298. tline = tline->next;
  2299. if (!tline || tline->type != TOK_ID) {
  2300. nasm_error(ERR_NONFATAL,
  2301. "`%%local' missing size type parameter");
  2302. free_tlist(origline);
  2303. return DIRECTIVE_FOUND;
  2304. }
  2305. /* Allow macro expansion of type parameter */
  2306. tt = tokenize(tline->text);
  2307. tt = expand_smacro(tt);
  2308. size = parse_size(tt->text);
  2309. if (!size) {
  2310. nasm_error(ERR_NONFATAL,
  2311. "Invalid size type for `%%local' missing directive");
  2312. free_tlist(tt);
  2313. free_tlist(origline);
  2314. return DIRECTIVE_FOUND;
  2315. }
  2316. free_tlist(tt);
  2317. /* Round up to even stack slots */
  2318. size = ALIGN(size, StackSize);
  2319. offset += size; /* Negative offset, increment before */
  2320. /* Now define the macro for the argument */
  2321. snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
  2322. local, StackPointer, offset);
  2323. do_directive(tokenize(directive), output);
  2324. /* Now define the assign to setup the enter_c macro correctly */
  2325. snprintf(directive, sizeof(directive),
  2326. "%%assign %%$localsize %%$localsize+%d", size);
  2327. do_directive(tokenize(directive), output);
  2328. /* Move to the next argument in the list */
  2329. tline = tline->next;
  2330. if (tline && tline->type == TOK_WHITESPACE)
  2331. tline = tline->next;
  2332. } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
  2333. LocalOffset = offset;
  2334. free_tlist(origline);
  2335. return DIRECTIVE_FOUND;
  2336. case PP_CLEAR:
  2337. if (tline->next)
  2338. nasm_error(ERR_WARNING|ERR_PASS1,
  2339. "trailing garbage after `%%clear' ignored");
  2340. free_macros();
  2341. init_macros();
  2342. free_tlist(origline);
  2343. return DIRECTIVE_FOUND;
  2344. case PP_DEPEND:
  2345. t = tline->next = expand_smacro(tline->next);
  2346. skip_white_(t);
  2347. if (!t || (t->type != TOK_STRING &&
  2348. t->type != TOK_INTERNAL_STRING)) {
  2349. nasm_error(ERR_NONFATAL, "`%%depend' expects a file name");
  2350. free_tlist(origline);
  2351. return DIRECTIVE_FOUND; /* but we did _something_ */
  2352. }
  2353. if (t->next)
  2354. nasm_error(ERR_WARNING|ERR_PASS1,
  2355. "trailing garbage after `%%depend' ignored");
  2356. p = t->text;
  2357. if (t->type != TOK_INTERNAL_STRING)
  2358. nasm_unquote_cstr(p, i);
  2359. nasm_add_string_to_strlist(dephead, p);
  2360. free_tlist(origline);
  2361. return DIRECTIVE_FOUND;
  2362. case PP_INCLUDE:
  2363. t = tline->next = expand_smacro(tline->next);
  2364. skip_white_(t);
  2365. if (!t || (t->type != TOK_STRING &&
  2366. t->type != TOK_INTERNAL_STRING)) {
  2367. nasm_error(ERR_NONFATAL, "`%%include' expects a file name");
  2368. free_tlist(origline);
  2369. return DIRECTIVE_FOUND; /* but we did _something_ */
  2370. }
  2371. if (t->next)
  2372. nasm_error(ERR_WARNING|ERR_PASS1,
  2373. "trailing garbage after `%%include' ignored");
  2374. p = t->text;
  2375. if (t->type != TOK_INTERNAL_STRING)
  2376. nasm_unquote_cstr(p, i);
  2377. inc = nasm_malloc(sizeof(Include));
  2378. inc->next = istk;
  2379. inc->conds = NULL;
  2380. found_path = NULL;
  2381. inc->fp = inc_fopen(p, dephead, &found_path,
  2382. pass == 0 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
  2383. if (!inc->fp) {
  2384. /* -MG given but file not found */
  2385. nasm_free(inc);
  2386. } else {
  2387. inc->fname = src_set_fname(found_path ? found_path : p);
  2388. inc->lineno = src_set_linnum(0);
  2389. inc->lineinc = 1;
  2390. inc->expansion = NULL;
  2391. inc->mstk = NULL;
  2392. istk = inc;
  2393. lfmt->uplevel(LIST_INCLUDE);
  2394. }
  2395. free_tlist(origline);
  2396. return DIRECTIVE_FOUND;
  2397. case PP_USE:
  2398. {
  2399. static macros_t *use_pkg;
  2400. const char *pkg_macro = NULL;
  2401. tline = tline->next;
  2402. skip_white_(tline);
  2403. tline = expand_id(tline);
  2404. if (!tline || (tline->type != TOK_STRING &&
  2405. tline->type != TOK_INTERNAL_STRING &&
  2406. tline->type != TOK_ID)) {
  2407. nasm_error(ERR_NONFATAL, "`%%use' expects a package name");
  2408. free_tlist(origline);
  2409. return DIRECTIVE_FOUND; /* but we did _something_ */
  2410. }
  2411. if (tline->next)
  2412. nasm_error(ERR_WARNING|ERR_PASS1,
  2413. "trailing garbage after `%%use' ignored");
  2414. if (tline->type == TOK_STRING)
  2415. nasm_unquote_cstr(tline->text, i);
  2416. use_pkg = nasm_stdmac_find_package(tline->text);
  2417. if (!use_pkg)
  2418. nasm_error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
  2419. else
  2420. pkg_macro = (char *)use_pkg + 1; /* The first string will be <%define>__USE_*__ */
  2421. if (use_pkg && ! smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
  2422. /* Not already included, go ahead and include it */
  2423. stdmacpos = use_pkg;
  2424. }
  2425. free_tlist(origline);
  2426. return DIRECTIVE_FOUND;
  2427. }
  2428. case PP_PUSH:
  2429. case PP_REPL:
  2430. case PP_POP:
  2431. tline = tline->next;
  2432. skip_white_(tline);
  2433. tline = expand_id(tline);
  2434. if (tline) {
  2435. if (!tok_type_(tline, TOK_ID)) {
  2436. nasm_error(ERR_NONFATAL, "`%s' expects a context identifier",
  2437. pp_directives[i]);
  2438. free_tlist(origline);
  2439. return DIRECTIVE_FOUND; /* but we did _something_ */
  2440. }
  2441. if (tline->next)
  2442. nasm_error(ERR_WARNING|ERR_PASS1,
  2443. "trailing garbage after `%s' ignored",
  2444. pp_directives[i]);
  2445. p = nasm_strdup(tline->text);
  2446. } else {
  2447. p = NULL; /* Anonymous */
  2448. }
  2449. if (i == PP_PUSH) {
  2450. ctx = nasm_malloc(sizeof(Context));
  2451. ctx->next = cstk;
  2452. hash_init(&ctx->localmac, HASH_SMALL);
  2453. ctx->name = p;
  2454. ctx->number = unique++;
  2455. cstk = ctx;
  2456. } else {
  2457. /* %pop or %repl */
  2458. if (!cstk) {
  2459. nasm_error(ERR_NONFATAL, "`%s': context stack is empty",
  2460. pp_directives[i]);
  2461. } else if (i == PP_POP) {
  2462. if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
  2463. nasm_error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
  2464. "expected %s",
  2465. cstk->name ? cstk->name : "anonymous", p);
  2466. else
  2467. ctx_pop();
  2468. } else {
  2469. /* i == PP_REPL */
  2470. nasm_free(cstk->name);
  2471. cstk->name = p;
  2472. p = NULL;
  2473. }
  2474. nasm_free(p);
  2475. }
  2476. free_tlist(origline);
  2477. return DIRECTIVE_FOUND;
  2478. case PP_FATAL:
  2479. severity = ERR_FATAL;
  2480. goto issue_error;
  2481. case PP_ERROR:
  2482. severity = ERR_NONFATAL;
  2483. goto issue_error;
  2484. case PP_WARNING:
  2485. severity = ERR_WARNING|WARN_USER;
  2486. goto issue_error;
  2487. issue_error:
  2488. {
  2489. /* Only error out if this is the final pass */
  2490. if (pass != 2 && i != PP_FATAL)
  2491. return DIRECTIVE_FOUND;
  2492. tline->next = expand_smacro(tline->next);
  2493. tline = tline->next;
  2494. skip_white_(tline);
  2495. t = tline ? tline->next : NULL;
  2496. skip_white_(t);
  2497. if (tok_type_(tline, TOK_STRING) && !t) {
  2498. /* The line contains only a quoted string */
  2499. p = tline->text;
  2500. nasm_unquote(p, NULL); /* Ignore NUL character truncation */
  2501. nasm_error(severity, "%s", p);
  2502. } else {
  2503. /* Not a quoted string, or more than a quoted string */
  2504. p = detoken(tline, false);
  2505. nasm_error(severity, "%s", p);
  2506. nasm_free(p);
  2507. }
  2508. free_tlist(origline);
  2509. return DIRECTIVE_FOUND;
  2510. }
  2511. CASE_PP_IF:
  2512. if (istk->conds && !emitting(istk->conds->state))
  2513. j = COND_NEVER;
  2514. else {
  2515. j = if_condition(tline->next, i);
  2516. tline->next = NULL; /* it got freed */
  2517. j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
  2518. }
  2519. cond = nasm_malloc(sizeof(Cond));
  2520. cond->next = istk->conds;
  2521. cond->state = j;
  2522. istk->conds = cond;
  2523. if(istk->mstk)
  2524. istk->mstk->condcnt ++;
  2525. free_tlist(origline);
  2526. return DIRECTIVE_FOUND;
  2527. CASE_PP_ELIF:
  2528. if (!istk->conds)
  2529. nasm_error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
  2530. switch(istk->conds->state) {
  2531. case COND_IF_TRUE:
  2532. istk->conds->state = COND_DONE;
  2533. break;
  2534. case COND_DONE:
  2535. case COND_NEVER:
  2536. break;
  2537. case COND_ELSE_TRUE:
  2538. case COND_ELSE_FALSE:
  2539. nasm_error(ERR_WARNING|ERR_PASS1|ERR_PP_PRECOND,
  2540. "`%%elif' after `%%else' ignored");
  2541. istk->conds->state = COND_NEVER;
  2542. break;
  2543. case COND_IF_FALSE:
  2544. /*
  2545. * IMPORTANT: In the case of %if, we will already have
  2546. * called expand_mmac_params(); however, if we're
  2547. * processing an %elif we must have been in a
  2548. * non-emitting mode, which would have inhibited
  2549. * the normal invocation of expand_mmac_params().
  2550. * Therefore, we have to do it explicitly here.
  2551. */
  2552. j = if_condition(expand_mmac_params(tline->next), i);
  2553. tline->next = NULL; /* it got freed */
  2554. istk->conds->state =
  2555. j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
  2556. break;
  2557. }
  2558. free_tlist(origline);
  2559. return DIRECTIVE_FOUND;
  2560. case PP_ELSE:
  2561. if (tline->next)
  2562. nasm_error(ERR_WARNING|ERR_PASS1|ERR_PP_PRECOND,
  2563. "trailing garbage after `%%else' ignored");
  2564. if (!istk->conds)
  2565. nasm_fatal(0, "`%%else: no matching `%%if'");
  2566. switch(istk->conds->state) {
  2567. case COND_IF_TRUE:
  2568. case COND_DONE:
  2569. istk->conds->state = COND_ELSE_FALSE;
  2570. break;
  2571. case COND_NEVER:
  2572. break;
  2573. case COND_IF_FALSE:
  2574. istk->conds->state = COND_ELSE_TRUE;
  2575. break;
  2576. case COND_ELSE_TRUE:
  2577. case COND_ELSE_FALSE:
  2578. nasm_error(ERR_WARNING|ERR_PASS1|ERR_PP_PRECOND,
  2579. "`%%else' after `%%else' ignored.");
  2580. istk->conds->state = COND_NEVER;
  2581. break;
  2582. }
  2583. free_tlist(origline);
  2584. return DIRECTIVE_FOUND;
  2585. case PP_ENDIF:
  2586. if (tline->next)
  2587. nasm_error(ERR_WARNING|ERR_PASS1|ERR_PP_PRECOND,
  2588. "trailing garbage after `%%endif' ignored");
  2589. if (!istk->conds)
  2590. nasm_error(ERR_FATAL, "`%%endif': no matching `%%if'");
  2591. cond = istk->conds;
  2592. istk->conds = cond->next;
  2593. nasm_free(cond);
  2594. if(istk->mstk)
  2595. istk->mstk->condcnt --;
  2596. free_tlist(origline);
  2597. return DIRECTIVE_FOUND;
  2598. case PP_RMACRO:
  2599. case PP_IRMACRO:
  2600. case PP_MACRO:
  2601. case PP_IMACRO:
  2602. if (defining) {
  2603. nasm_error(ERR_FATAL, "`%s': already defining a macro",
  2604. pp_directives[i]);
  2605. return DIRECTIVE_FOUND;
  2606. }
  2607. defining = nasm_zalloc(sizeof(MMacro));
  2608. defining->max_depth = ((i == PP_RMACRO) || (i == PP_IRMACRO))
  2609. ? nasm_limit[LIMIT_MACROS] : 0;
  2610. defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
  2611. if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
  2612. nasm_free(defining);
  2613. defining = NULL;
  2614. return DIRECTIVE_FOUND;
  2615. }
  2616. src_get(&defining->xline, &defining->fname);
  2617. mmac = (MMacro *) hash_findix(&mmacros, defining->name);
  2618. while (mmac) {
  2619. if (!strcmp(mmac->name, defining->name) &&
  2620. (mmac->nparam_min <= defining->nparam_max
  2621. || defining->plus)
  2622. && (defining->nparam_min <= mmac->nparam_max
  2623. || mmac->plus)) {
  2624. nasm_error(ERR_WARNING|ERR_PASS1,
  2625. "redefining multi-line macro `%s'", defining->name);
  2626. return DIRECTIVE_FOUND;
  2627. }
  2628. mmac = mmac->next;
  2629. }
  2630. free_tlist(origline);
  2631. return DIRECTIVE_FOUND;
  2632. case PP_ENDM:
  2633. case PP_ENDMACRO:
  2634. if (! (defining && defining->name)) {
  2635. nasm_error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
  2636. return DIRECTIVE_FOUND;
  2637. }
  2638. mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
  2639. defining->next = *mmhead;
  2640. *mmhead = defining;
  2641. defining = NULL;
  2642. free_tlist(origline);
  2643. return DIRECTIVE_FOUND;
  2644. case PP_EXITMACRO:
  2645. /*
  2646. * We must search along istk->expansion until we hit a
  2647. * macro-end marker for a macro with a name. Then we
  2648. * bypass all lines between exitmacro and endmacro.
  2649. */
  2650. list_for_each(l, istk->expansion)
  2651. if (l->finishes && l->finishes->name)
  2652. break;
  2653. if (l) {
  2654. /*
  2655. * Remove all conditional entries relative to this
  2656. * macro invocation. (safe to do in this context)
  2657. */
  2658. for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
  2659. cond = istk->conds;
  2660. istk->conds = cond->next;
  2661. nasm_free(cond);
  2662. }
  2663. istk->expansion = l;
  2664. } else {
  2665. nasm_error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
  2666. }
  2667. free_tlist(origline);
  2668. return DIRECTIVE_FOUND;
  2669. case PP_UNMACRO:
  2670. case PP_UNIMACRO:
  2671. {
  2672. MMacro **mmac_p;
  2673. MMacro spec;
  2674. spec.casesense = (i == PP_UNMACRO);
  2675. if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
  2676. return DIRECTIVE_FOUND;
  2677. }
  2678. mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
  2679. while (mmac_p && *mmac_p) {
  2680. mmac = *mmac_p;
  2681. if (mmac->casesense == spec.casesense &&
  2682. !mstrcmp(mmac->name, spec.name, spec.casesense) &&
  2683. mmac->nparam_min == spec.nparam_min &&
  2684. mmac->nparam_max == spec.nparam_max &&
  2685. mmac->plus == spec.plus) {
  2686. *mmac_p = mmac->next;
  2687. free_mmacro(mmac);
  2688. } else {
  2689. mmac_p = &mmac->next;
  2690. }
  2691. }
  2692. free_tlist(origline);
  2693. free_tlist(spec.dlist);
  2694. return DIRECTIVE_FOUND;
  2695. }
  2696. case PP_ROTATE:
  2697. if (tline->next && tline->next->type == TOK_WHITESPACE)
  2698. tline = tline->next;
  2699. if (!tline->next) {
  2700. free_tlist(origline);
  2701. nasm_error(ERR_NONFATAL, "`%%rotate' missing rotate count");
  2702. return DIRECTIVE_FOUND;
  2703. }
  2704. t = expand_smacro(tline->next);
  2705. tline->next = NULL;
  2706. free_tlist(origline);
  2707. tline = t;
  2708. tptr = &t;
  2709. tokval.t_type = TOKEN_INVALID;
  2710. evalresult =
  2711. evaluate(ppscan, tptr, &tokval, NULL, pass, NULL);
  2712. free_tlist(tline);
  2713. if (!evalresult)
  2714. return DIRECTIVE_FOUND;
  2715. if (tokval.t_type)
  2716. nasm_error(ERR_WARNING|ERR_PASS1,
  2717. "trailing garbage after expression ignored");
  2718. if (!is_simple(evalresult)) {
  2719. nasm_error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
  2720. return DIRECTIVE_FOUND;
  2721. }
  2722. mmac = istk->mstk;
  2723. while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
  2724. mmac = mmac->next_active;
  2725. if (!mmac) {
  2726. nasm_error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
  2727. } else if (mmac->nparam == 0) {
  2728. nasm_error(ERR_NONFATAL,
  2729. "`%%rotate' invoked within macro without parameters");
  2730. } else {
  2731. int rotate = mmac->rotate + reloc_value(evalresult);
  2732. rotate %= (int)mmac->nparam;
  2733. if (rotate < 0)
  2734. rotate += mmac->nparam;
  2735. mmac->rotate = rotate;
  2736. }
  2737. return DIRECTIVE_FOUND;
  2738. case PP_REP:
  2739. nolist = false;
  2740. do {
  2741. tline = tline->next;
  2742. } while (tok_type_(tline, TOK_WHITESPACE));
  2743. if (tok_type_(tline, TOK_ID) &&
  2744. nasm_stricmp(tline->text, ".nolist") == 0) {
  2745. nolist = true;
  2746. do {
  2747. tline = tline->next;
  2748. } while (tok_type_(tline, TOK_WHITESPACE));
  2749. }
  2750. if (tline) {
  2751. t = expand_smacro(tline);
  2752. tptr = &t;
  2753. tokval.t_type = TOKEN_INVALID;
  2754. evalresult =
  2755. evaluate(ppscan, tptr, &tokval, NULL, pass, NULL);
  2756. if (!evalresult) {
  2757. free_tlist(origline);
  2758. return DIRECTIVE_FOUND;
  2759. }
  2760. if (tokval.t_type)
  2761. nasm_error(ERR_WARNING|ERR_PASS1,
  2762. "trailing garbage after expression ignored");
  2763. if (!is_simple(evalresult)) {
  2764. nasm_error(ERR_NONFATAL, "non-constant value given to `%%rep'");
  2765. return DIRECTIVE_FOUND;
  2766. }
  2767. count = reloc_value(evalresult);
  2768. if (count > nasm_limit[LIMIT_REP]) {
  2769. nasm_error(ERR_NONFATAL,
  2770. "`%%rep' count %"PRId64" exceeds limit (currently %"PRId64")",
  2771. count, nasm_limit[LIMIT_REP]);
  2772. count = 0;
  2773. } else if (count < 0) {
  2774. nasm_error(ERR_WARNING|ERR_PASS2|WARN_NEG_REP,
  2775. "negative `%%rep' count: %"PRId64, count);
  2776. count = 0;
  2777. } else {
  2778. count++;
  2779. }
  2780. } else {
  2781. nasm_error(ERR_NONFATAL, "`%%rep' expects a repeat count");
  2782. count = 0;
  2783. }
  2784. free_tlist(origline);
  2785. tmp_defining = defining;
  2786. defining = nasm_malloc(sizeof(MMacro));
  2787. defining->prev = NULL;
  2788. defining->name = NULL; /* flags this macro as a %rep block */
  2789. defining->casesense = false;
  2790. defining->plus = false;
  2791. defining->nolist = nolist;
  2792. defining->in_progress = count;
  2793. defining->max_depth = 0;
  2794. defining->nparam_min = defining->nparam_max = 0;
  2795. defining->defaults = NULL;
  2796. defining->dlist = NULL;
  2797. defining->expansion = NULL;
  2798. defining->next_active = istk->mstk;
  2799. defining->rep_nest = tmp_defining;
  2800. return DIRECTIVE_FOUND;
  2801. case PP_ENDREP:
  2802. if (!defining || defining->name) {
  2803. nasm_error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
  2804. return DIRECTIVE_FOUND;
  2805. }
  2806. /*
  2807. * Now we have a "macro" defined - although it has no name
  2808. * and we won't be entering it in the hash tables - we must
  2809. * push a macro-end marker for it on to istk->expansion.
  2810. * After that, it will take care of propagating itself (a
  2811. * macro-end marker line for a macro which is really a %rep
  2812. * block will cause the macro to be re-expanded, complete
  2813. * with another macro-end marker to ensure the process
  2814. * continues) until the whole expansion is forcibly removed
  2815. * from istk->expansion by a %exitrep.
  2816. */
  2817. l = nasm_malloc(sizeof(Line));
  2818. l->next = istk->expansion;
  2819. l->finishes = defining;
  2820. l->first = NULL;
  2821. istk->expansion = l;
  2822. istk->mstk = defining;
  2823. lfmt->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
  2824. tmp_defining = defining;
  2825. defining = defining->rep_nest;
  2826. free_tlist(origline);
  2827. return DIRECTIVE_FOUND;
  2828. case PP_EXITREP:
  2829. /*
  2830. * We must search along istk->expansion until we hit a
  2831. * macro-end marker for a macro with no name. Then we set
  2832. * its `in_progress' flag to 0.
  2833. */
  2834. list_for_each(l, istk->expansion)
  2835. if (l->finishes && !l->finishes->name)
  2836. break;
  2837. if (l)
  2838. l->finishes->in_progress = 1;
  2839. else
  2840. nasm_error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
  2841. free_tlist(origline);
  2842. return DIRECTIVE_FOUND;
  2843. case PP_XDEFINE:
  2844. case PP_IXDEFINE:
  2845. case PP_DEFINE:
  2846. case PP_IDEFINE:
  2847. casesense = (i == PP_DEFINE || i == PP_XDEFINE);
  2848. tline = tline->next;
  2849. skip_white_(tline);
  2850. tline = expand_id(tline);
  2851. if (!tline || (tline->type != TOK_ID &&
  2852. (tline->type != TOK_PREPROC_ID ||
  2853. tline->text[1] != '$'))) {
  2854. nasm_error(ERR_NONFATAL, "`%s' expects a macro identifier",
  2855. pp_directives[i]);
  2856. free_tlist(origline);
  2857. return DIRECTIVE_FOUND;
  2858. }
  2859. ctx = get_ctx(tline->text, &mname);
  2860. last = tline;
  2861. param_start = tline = tline->next;
  2862. nparam = 0;
  2863. /* Expand the macro definition now for %xdefine and %ixdefine */
  2864. if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
  2865. tline = expand_smacro(tline);
  2866. if (tok_is_(tline, "(")) {
  2867. /*
  2868. * This macro has parameters.
  2869. */
  2870. tline = tline->next;
  2871. while (1) {
  2872. skip_white_(tline);
  2873. if (!tline) {
  2874. nasm_error(ERR_NONFATAL, "parameter identifier expected");
  2875. free_tlist(origline);
  2876. return DIRECTIVE_FOUND;
  2877. }
  2878. if (tline->type != TOK_ID) {
  2879. nasm_error(ERR_NONFATAL,
  2880. "`%s': parameter identifier expected",
  2881. tline->text);
  2882. free_tlist(origline);
  2883. return DIRECTIVE_FOUND;
  2884. }
  2885. tline->type = TOK_SMAC_PARAM + nparam++;
  2886. tline = tline->next;
  2887. skip_white_(tline);
  2888. if (tok_is_(tline, ",")) {
  2889. tline = tline->next;
  2890. } else {
  2891. if (!tok_is_(tline, ")")) {
  2892. nasm_error(ERR_NONFATAL,
  2893. "`)' expected to terminate macro template");
  2894. free_tlist(origline);
  2895. return DIRECTIVE_FOUND;
  2896. }
  2897. break;
  2898. }
  2899. }
  2900. last = tline;
  2901. tline = tline->next;
  2902. }
  2903. if (tok_type_(tline, TOK_WHITESPACE))
  2904. last = tline, tline = tline->next;
  2905. macro_start = NULL;
  2906. last->next = NULL;
  2907. t = tline;
  2908. while (t) {
  2909. if (t->type == TOK_ID) {
  2910. list_for_each(tt, param_start)
  2911. if (tt->type >= TOK_SMAC_PARAM &&
  2912. !strcmp(tt->text, t->text))
  2913. t->type = tt->type;
  2914. }
  2915. tt = t->next;
  2916. t->next = macro_start;
  2917. macro_start = t;
  2918. t = tt;
  2919. }
  2920. /*
  2921. * Good. We now have a macro name, a parameter count, and a
  2922. * token list (in reverse order) for an expansion. We ought
  2923. * to be OK just to create an SMacro, store it, and let
  2924. * free_tlist have the rest of the line (which we have
  2925. * carefully re-terminated after chopping off the expansion
  2926. * from the end).
  2927. */
  2928. define_smacro(ctx, mname, casesense, nparam, macro_start);
  2929. free_tlist(origline);
  2930. return DIRECTIVE_FOUND;
  2931. case PP_UNDEF:
  2932. tline = tline->next;
  2933. skip_white_(tline);
  2934. tline = expand_id(tline);
  2935. if (!tline || (tline->type != TOK_ID &&
  2936. (tline->type != TOK_PREPROC_ID ||
  2937. tline->text[1] != '$'))) {
  2938. nasm_error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
  2939. free_tlist(origline);
  2940. return DIRECTIVE_FOUND;
  2941. }
  2942. if (tline->next) {
  2943. nasm_error(ERR_WARNING|ERR_PASS1,
  2944. "trailing garbage after macro name ignored");
  2945. }
  2946. /* Find the context that symbol belongs to */
  2947. ctx = get_ctx(tline->text, &mname);
  2948. undef_smacro(ctx, mname);
  2949. free_tlist(origline);
  2950. return DIRECTIVE_FOUND;
  2951. case PP_DEFSTR:
  2952. case PP_IDEFSTR:
  2953. casesense = (i == PP_DEFSTR);
  2954. tline = tline->next;
  2955. skip_white_(tline);
  2956. tline = expand_id(tline);
  2957. if (!tline || (tline->type != TOK_ID &&
  2958. (tline->type != TOK_PREPROC_ID ||
  2959. tline->text[1] != '$'))) {
  2960. nasm_error(ERR_NONFATAL, "`%s' expects a macro identifier",
  2961. pp_directives[i]);
  2962. free_tlist(origline);
  2963. return DIRECTIVE_FOUND;
  2964. }
  2965. ctx = get_ctx(tline->text, &mname);
  2966. last = tline;
  2967. tline = expand_smacro(tline->next);
  2968. last->next = NULL;
  2969. while (tok_type_(tline, TOK_WHITESPACE))
  2970. tline = delete_Token(tline);
  2971. p = detoken(tline, false);
  2972. macro_start = nasm_malloc(sizeof(*macro_start));
  2973. macro_start->next = NULL;
  2974. macro_start->text = nasm_quote(p, strlen(p));
  2975. macro_start->type = TOK_STRING;
  2976. macro_start->a.mac = NULL;
  2977. nasm_free(p);
  2978. /*
  2979. * We now have a macro name, an implicit parameter count of
  2980. * zero, and a string token to use as an expansion. Create
  2981. * and store an SMacro.
  2982. */
  2983. define_smacro(ctx, mname, casesense, 0, macro_start);
  2984. free_tlist(origline);
  2985. return DIRECTIVE_FOUND;
  2986. case PP_DEFTOK:
  2987. case PP_IDEFTOK:
  2988. casesense = (i == PP_DEFTOK);
  2989. tline = tline->next;
  2990. skip_white_(tline);
  2991. tline = expand_id(tline);
  2992. if (!tline || (tline->type != TOK_ID &&
  2993. (tline->type != TOK_PREPROC_ID ||
  2994. tline->text[1] != '$'))) {
  2995. nasm_error(ERR_NONFATAL,
  2996. "`%s' expects a macro identifier as first parameter",
  2997. pp_directives[i]);
  2998. free_tlist(origline);
  2999. return DIRECTIVE_FOUND;
  3000. }
  3001. ctx = get_ctx(tline->text, &mname);
  3002. last = tline;
  3003. tline = expand_smacro(tline->next);
  3004. last->next = NULL;
  3005. t = tline;
  3006. while (tok_type_(t, TOK_WHITESPACE))
  3007. t = t->next;
  3008. /* t should now point to the string */
  3009. if (!tok_type_(t, TOK_STRING)) {
  3010. nasm_error(ERR_NONFATAL,
  3011. "`%s` requires string as second parameter",
  3012. pp_directives[i]);
  3013. free_tlist(tline);
  3014. free_tlist(origline);
  3015. return DIRECTIVE_FOUND;
  3016. }
  3017. /*
  3018. * Convert the string to a token stream. Note that smacros
  3019. * are stored with the token stream reversed, so we have to
  3020. * reverse the output of tokenize().
  3021. */
  3022. nasm_unquote_cstr(t->text, i);
  3023. macro_start = reverse_tokens(tokenize(t->text));
  3024. /*
  3025. * We now have a macro name, an implicit parameter count of
  3026. * zero, and a numeric token to use as an expansion. Create
  3027. * and store an SMacro.
  3028. */
  3029. define_smacro(ctx, mname, casesense, 0, macro_start);
  3030. free_tlist(tline);
  3031. free_tlist(origline);
  3032. return DIRECTIVE_FOUND;
  3033. case PP_PATHSEARCH:
  3034. {
  3035. const char *found_path;
  3036. casesense = true;
  3037. tline = tline->next;
  3038. skip_white_(tline);
  3039. tline = expand_id(tline);
  3040. if (!tline || (tline->type != TOK_ID &&
  3041. (tline->type != TOK_PREPROC_ID ||
  3042. tline->text[1] != '$'))) {
  3043. nasm_error(ERR_NONFATAL,
  3044. "`%%pathsearch' expects a macro identifier as first parameter");
  3045. free_tlist(origline);
  3046. return DIRECTIVE_FOUND;
  3047. }
  3048. ctx = get_ctx(tline->text, &mname);
  3049. last = tline;
  3050. tline = expand_smacro(tline->next);
  3051. last->next = NULL;
  3052. t = tline;
  3053. while (tok_type_(t, TOK_WHITESPACE))
  3054. t = t->next;
  3055. if (!t || (t->type != TOK_STRING &&
  3056. t->type != TOK_INTERNAL_STRING)) {
  3057. nasm_error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
  3058. free_tlist(tline);
  3059. free_tlist(origline);
  3060. return DIRECTIVE_FOUND; /* but we did _something_ */
  3061. }
  3062. if (t->next)
  3063. nasm_error(ERR_WARNING|ERR_PASS1,
  3064. "trailing garbage after `%%pathsearch' ignored");
  3065. p = t->text;
  3066. if (t->type != TOK_INTERNAL_STRING)
  3067. nasm_unquote(p, NULL);
  3068. inc_fopen(p, NULL, &found_path, INC_PROBE, NF_BINARY);
  3069. if (!found_path)
  3070. found_path = p;
  3071. macro_start = nasm_malloc(sizeof(*macro_start));
  3072. macro_start->next = NULL;
  3073. macro_start->text = nasm_quote(found_path, strlen(found_path));
  3074. macro_start->type = TOK_STRING;
  3075. macro_start->a.mac = NULL;
  3076. /*
  3077. * We now have a macro name, an implicit parameter count of
  3078. * zero, and a string token to use as an expansion. Create
  3079. * and store an SMacro.
  3080. */
  3081. define_smacro(ctx, mname, casesense, 0, macro_start);
  3082. free_tlist(tline);
  3083. free_tlist(origline);
  3084. return DIRECTIVE_FOUND;
  3085. }
  3086. case PP_STRLEN:
  3087. casesense = true;
  3088. tline = tline->next;
  3089. skip_white_(tline);
  3090. tline = expand_id(tline);
  3091. if (!tline || (tline->type != TOK_ID &&
  3092. (tline->type != TOK_PREPROC_ID ||
  3093. tline->text[1] != '$'))) {
  3094. nasm_error(ERR_NONFATAL,
  3095. "`%%strlen' expects a macro identifier as first parameter");
  3096. free_tlist(origline);
  3097. return DIRECTIVE_FOUND;
  3098. }
  3099. ctx = get_ctx(tline->text, &mname);
  3100. last = tline;
  3101. tline = expand_smacro(tline->next);
  3102. last->next = NULL;
  3103. t = tline;
  3104. while (tok_type_(t, TOK_WHITESPACE))
  3105. t = t->next;
  3106. /* t should now point to the string */
  3107. if (!tok_type_(t, TOK_STRING)) {
  3108. nasm_error(ERR_NONFATAL,
  3109. "`%%strlen` requires string as second parameter");
  3110. free_tlist(tline);
  3111. free_tlist(origline);
  3112. return DIRECTIVE_FOUND;
  3113. }
  3114. macro_start = nasm_malloc(sizeof(*macro_start));
  3115. macro_start->next = NULL;
  3116. make_tok_num(macro_start, nasm_unquote(t->text, NULL));
  3117. macro_start->a.mac = NULL;
  3118. /*
  3119. * We now have a macro name, an implicit parameter count of
  3120. * zero, and a numeric token to use as an expansion. Create
  3121. * and store an SMacro.
  3122. */
  3123. define_smacro(ctx, mname, casesense, 0, macro_start);
  3124. free_tlist(tline);
  3125. free_tlist(origline);
  3126. return DIRECTIVE_FOUND;
  3127. case PP_STRCAT:
  3128. casesense = true;
  3129. tline = tline->next;
  3130. skip_white_(tline);
  3131. tline = expand_id(tline);
  3132. if (!tline || (tline->type != TOK_ID &&
  3133. (tline->type != TOK_PREPROC_ID ||
  3134. tline->text[1] != '$'))) {
  3135. nasm_error(ERR_NONFATAL,
  3136. "`%%strcat' expects a macro identifier as first parameter");
  3137. free_tlist(origline);
  3138. return DIRECTIVE_FOUND;
  3139. }
  3140. ctx = get_ctx(tline->text, &mname);
  3141. last = tline;
  3142. tline = expand_smacro(tline->next);
  3143. last->next = NULL;
  3144. len = 0;
  3145. list_for_each(t, tline) {
  3146. switch (t->type) {
  3147. case TOK_WHITESPACE:
  3148. break;
  3149. case TOK_STRING:
  3150. len += t->a.len = nasm_unquote(t->text, NULL);
  3151. break;
  3152. case TOK_OTHER:
  3153. if (!strcmp(t->text, ",")) /* permit comma separators */
  3154. break;
  3155. /* else fall through */
  3156. default:
  3157. nasm_error(ERR_NONFATAL,
  3158. "non-string passed to `%%strcat' (%d)", t->type);
  3159. free_tlist(tline);
  3160. free_tlist(origline);
  3161. return DIRECTIVE_FOUND;
  3162. }
  3163. }
  3164. p = pp = nasm_malloc(len);
  3165. list_for_each(t, tline) {
  3166. if (t->type == TOK_STRING) {
  3167. memcpy(p, t->text, t->a.len);
  3168. p += t->a.len;
  3169. }
  3170. }
  3171. /*
  3172. * We now have a macro name, an implicit parameter count of
  3173. * zero, and a numeric token to use as an expansion. Create
  3174. * and store an SMacro.
  3175. */
  3176. macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
  3177. macro_start->text = nasm_quote(pp, len);
  3178. nasm_free(pp);
  3179. define_smacro(ctx, mname, casesense, 0, macro_start);
  3180. free_tlist(tline);
  3181. free_tlist(origline);
  3182. return DIRECTIVE_FOUND;
  3183. case PP_SUBSTR:
  3184. {
  3185. int64_t start, count;
  3186. size_t len;
  3187. casesense = true;
  3188. tline = tline->next;
  3189. skip_white_(tline);
  3190. tline = expand_id(tline);
  3191. if (!tline || (tline->type != TOK_ID &&
  3192. (tline->type != TOK_PREPROC_ID ||
  3193. tline->text[1] != '$'))) {
  3194. nasm_error(ERR_NONFATAL,
  3195. "`%%substr' expects a macro identifier as first parameter");
  3196. free_tlist(origline);
  3197. return DIRECTIVE_FOUND;
  3198. }
  3199. ctx = get_ctx(tline->text, &mname);
  3200. last = tline;
  3201. tline = expand_smacro(tline->next);
  3202. last->next = NULL;
  3203. if (tline) /* skip expanded id */
  3204. t = tline->next;
  3205. while (tok_type_(t, TOK_WHITESPACE))
  3206. t = t->next;
  3207. /* t should now point to the string */
  3208. if (!tok_type_(t, TOK_STRING)) {
  3209. nasm_error(ERR_NONFATAL,
  3210. "`%%substr` requires string as second parameter");
  3211. free_tlist(tline);
  3212. free_tlist(origline);
  3213. return DIRECTIVE_FOUND;
  3214. }
  3215. tt = t->next;
  3216. tptr = &tt;
  3217. tokval.t_type = TOKEN_INVALID;
  3218. evalresult = evaluate(ppscan, tptr, &tokval, NULL, pass, NULL);
  3219. if (!evalresult) {
  3220. free_tlist(tline);
  3221. free_tlist(origline);
  3222. return DIRECTIVE_FOUND;
  3223. } else if (!is_simple(evalresult)) {
  3224. nasm_error(ERR_NONFATAL, "non-constant value given to `%%substr`");
  3225. free_tlist(tline);
  3226. free_tlist(origline);
  3227. return DIRECTIVE_FOUND;
  3228. }
  3229. start = evalresult->value - 1;
  3230. while (tok_type_(tt, TOK_WHITESPACE))
  3231. tt = tt->next;
  3232. if (!tt) {
  3233. count = 1; /* Backwards compatibility: one character */
  3234. } else {
  3235. tokval.t_type = TOKEN_INVALID;
  3236. evalresult = evaluate(ppscan, tptr, &tokval, NULL, pass, NULL);
  3237. if (!evalresult) {
  3238. free_tlist(tline);
  3239. free_tlist(origline);
  3240. return DIRECTIVE_FOUND;
  3241. } else if (!is_simple(evalresult)) {
  3242. nasm_error(ERR_NONFATAL, "non-constant value given to `%%substr`");
  3243. free_tlist(tline);
  3244. free_tlist(origline);
  3245. return DIRECTIVE_FOUND;
  3246. }
  3247. count = evalresult->value;
  3248. }
  3249. len = nasm_unquote(t->text, NULL);
  3250. /* make start and count being in range */
  3251. if (start < 0)
  3252. start = 0;
  3253. if (count < 0)
  3254. count = len + count + 1 - start;
  3255. if (start + count > (int64_t)len)
  3256. count = len - start;
  3257. if (!len || count < 0 || start >=(int64_t)len)
  3258. start = -1, count = 0; /* empty string */
  3259. macro_start = nasm_malloc(sizeof(*macro_start));
  3260. macro_start->next = NULL;
  3261. macro_start->text = nasm_quote((start < 0) ? "" : t->text + start, count);
  3262. macro_start->type = TOK_STRING;
  3263. macro_start->a.mac = NULL;
  3264. /*
  3265. * We now have a macro name, an implicit parameter count of
  3266. * zero, and a numeric token to use as an expansion. Create
  3267. * and store an SMacro.
  3268. */
  3269. define_smacro(ctx, mname, casesense, 0, macro_start);
  3270. free_tlist(tline);
  3271. free_tlist(origline);
  3272. return DIRECTIVE_FOUND;
  3273. }
  3274. case PP_ASSIGN:
  3275. case PP_IASSIGN:
  3276. casesense = (i == PP_ASSIGN);
  3277. tline = tline->next;
  3278. skip_white_(tline);
  3279. tline = expand_id(tline);
  3280. if (!tline || (tline->type != TOK_ID &&
  3281. (tline->type != TOK_PREPROC_ID ||
  3282. tline->text[1] != '$'))) {
  3283. nasm_error(ERR_NONFATAL,
  3284. "`%%%sassign' expects a macro identifier",
  3285. (i == PP_IASSIGN ? "i" : ""));
  3286. free_tlist(origline);
  3287. return DIRECTIVE_FOUND;
  3288. }
  3289. ctx = get_ctx(tline->text, &mname);
  3290. last = tline;
  3291. tline = expand_smacro(tline->next);
  3292. last->next = NULL;
  3293. t = tline;
  3294. tptr = &t;
  3295. tokval.t_type = TOKEN_INVALID;
  3296. evalresult = evaluate(ppscan, tptr, &tokval, NULL, pass, NULL);
  3297. free_tlist(tline);
  3298. if (!evalresult) {
  3299. free_tlist(origline);
  3300. return DIRECTIVE_FOUND;
  3301. }
  3302. if (tokval.t_type)
  3303. nasm_error(ERR_WARNING|ERR_PASS1,
  3304. "trailing garbage after expression ignored");
  3305. if (!is_simple(evalresult)) {
  3306. nasm_error(ERR_NONFATAL,
  3307. "non-constant value given to `%%%sassign'",
  3308. (i == PP_IASSIGN ? "i" : ""));
  3309. free_tlist(origline);
  3310. return DIRECTIVE_FOUND;
  3311. }
  3312. macro_start = nasm_malloc(sizeof(*macro_start));
  3313. macro_start->next = NULL;
  3314. make_tok_num(macro_start, reloc_value(evalresult));
  3315. macro_start->a.mac = NULL;
  3316. /*
  3317. * We now have a macro name, an implicit parameter count of
  3318. * zero, and a numeric token to use as an expansion. Create
  3319. * and store an SMacro.
  3320. */
  3321. define_smacro(ctx, mname, casesense, 0, macro_start);
  3322. free_tlist(origline);
  3323. return DIRECTIVE_FOUND;
  3324. case PP_LINE:
  3325. /*
  3326. * Syntax is `%line nnn[+mmm] [filename]'
  3327. */
  3328. if (unlikely(pp_noline)) {
  3329. free_tlist(origline);
  3330. return DIRECTIVE_FOUND;
  3331. }
  3332. tline = tline->next;
  3333. skip_white_(tline);
  3334. if (!tok_type_(tline, TOK_NUMBER)) {
  3335. nasm_error(ERR_NONFATAL, "`%%line' expects line number");
  3336. free_tlist(origline);
  3337. return DIRECTIVE_FOUND;
  3338. }
  3339. k = readnum(tline->text, &err);
  3340. m = 1;
  3341. tline = tline->next;
  3342. if (tok_is_(tline, "+")) {
  3343. tline = tline->next;
  3344. if (!tok_type_(tline, TOK_NUMBER)) {
  3345. nasm_error(ERR_NONFATAL, "`%%line' expects line increment");
  3346. free_tlist(origline);
  3347. return DIRECTIVE_FOUND;
  3348. }
  3349. m = readnum(tline->text, &err);
  3350. tline = tline->next;
  3351. }
  3352. skip_white_(tline);
  3353. src_set_linnum(k);
  3354. istk->lineinc = m;
  3355. if (tline) {
  3356. char *fname = detoken(tline, false);
  3357. src_set_fname(fname);
  3358. nasm_free(fname);
  3359. }
  3360. free_tlist(origline);
  3361. return DIRECTIVE_FOUND;
  3362. default:
  3363. nasm_error(ERR_FATAL,
  3364. "preprocessor directive `%s' not yet implemented",
  3365. pp_directives[i]);
  3366. return DIRECTIVE_FOUND;
  3367. }
  3368. }
  3369. /*
  3370. * Ensure that a macro parameter contains a condition code and
  3371. * nothing else. Return the condition code index if so, or -1
  3372. * otherwise.
  3373. */
  3374. static int find_cc(Token * t)
  3375. {
  3376. Token *tt;
  3377. if (!t)
  3378. return -1; /* Probably a %+ without a space */
  3379. skip_white_(t);
  3380. if (!t)
  3381. return -1;
  3382. if (t->type != TOK_ID)
  3383. return -1;
  3384. tt = t->next;
  3385. skip_white_(tt);
  3386. if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
  3387. return -1;
  3388. return bsii(t->text, (const char **)conditions, ARRAY_SIZE(conditions));
  3389. }
  3390. /*
  3391. * This routines walks over tokens strem and hadnles tokens
  3392. * pasting, if @handle_explicit passed then explicit pasting
  3393. * term is handled, otherwise -- implicit pastings only.
  3394. */
  3395. static bool paste_tokens(Token **head, const struct tokseq_match *m,
  3396. size_t mnum, bool handle_explicit)
  3397. {
  3398. Token *tok, *next, **prev_next, **prev_nonspace;
  3399. bool pasted = false;
  3400. char *buf, *p;
  3401. size_t len, i;
  3402. /*
  3403. * The last token before pasting. We need it
  3404. * to be able to connect new handled tokens.
  3405. * In other words if there were a tokens stream
  3406. *
  3407. * A -> B -> C -> D
  3408. *
  3409. * and we've joined tokens B and C, the resulting
  3410. * stream should be
  3411. *
  3412. * A -> BC -> D
  3413. */
  3414. tok = *head;
  3415. prev_next = NULL;
  3416. if (!tok_type_(tok, TOK_WHITESPACE) && !tok_type_(tok, TOK_PASTE))
  3417. prev_nonspace = head;
  3418. else
  3419. prev_nonspace = NULL;
  3420. while (tok && (next = tok->next)) {
  3421. switch (tok->type) {
  3422. case TOK_WHITESPACE:
  3423. /* Zap redundant whitespaces */
  3424. while (tok_type_(next, TOK_WHITESPACE))
  3425. next = delete_Token(next);
  3426. tok->next = next;
  3427. break;
  3428. case TOK_PASTE:
  3429. /* Explicit pasting */
  3430. if (!handle_explicit)
  3431. break;
  3432. next = delete_Token(tok);
  3433. while (tok_type_(next, TOK_WHITESPACE))
  3434. next = delete_Token(next);
  3435. if (!pasted)
  3436. pasted = true;
  3437. /* Left pasting token is start of line */
  3438. if (!prev_nonspace)
  3439. nasm_error(ERR_FATAL, "No lvalue found on pasting");
  3440. /*
  3441. * No ending token, this might happen in two
  3442. * cases
  3443. *
  3444. * 1) There indeed no right token at all
  3445. * 2) There is a bare "%define ID" statement,
  3446. * and @ID does expand to whitespace.
  3447. *
  3448. * So technically we need to do a grammar analysis
  3449. * in another stage of parsing, but for now lets don't
  3450. * change the behaviour people used to. Simply allow
  3451. * whitespace after paste token.
  3452. */
  3453. if (!next) {
  3454. /*
  3455. * Zap ending space tokens and that's all.
  3456. */
  3457. tok = (*prev_nonspace)->next;
  3458. while (tok_type_(tok, TOK_WHITESPACE))
  3459. tok = delete_Token(tok);
  3460. tok = *prev_nonspace;
  3461. tok->next = NULL;
  3462. break;
  3463. }
  3464. tok = *prev_nonspace;
  3465. while (tok_type_(tok, TOK_WHITESPACE))
  3466. tok = delete_Token(tok);
  3467. len = strlen(tok->text);
  3468. len += strlen(next->text);
  3469. p = buf = nasm_malloc(len + 1);
  3470. strcpy(p, tok->text);
  3471. p = strchr(p, '\0');
  3472. strcpy(p, next->text);
  3473. delete_Token(tok);
  3474. tok = tokenize(buf);
  3475. nasm_free(buf);
  3476. *prev_nonspace = tok;
  3477. while (tok && tok->next)
  3478. tok = tok->next;
  3479. tok->next = delete_Token(next);
  3480. /* Restart from pasted tokens head */
  3481. tok = *prev_nonspace;
  3482. break;
  3483. default:
  3484. /* implicit pasting */
  3485. for (i = 0; i < mnum; i++) {
  3486. if (!(PP_CONCAT_MATCH(tok, m[i].mask_head)))
  3487. continue;
  3488. len = 0;
  3489. while (next && PP_CONCAT_MATCH(next, m[i].mask_tail)) {
  3490. len += strlen(next->text);
  3491. next = next->next;
  3492. }
  3493. /* No match or no text to process */
  3494. if (tok == next || len == 0)
  3495. break;
  3496. len += strlen(tok->text);
  3497. p = buf = nasm_malloc(len + 1);
  3498. strcpy(p, tok->text);
  3499. p = strchr(p, '\0');
  3500. tok = delete_Token(tok);
  3501. while (tok != next) {
  3502. if (PP_CONCAT_MATCH(tok, m[i].mask_tail)) {
  3503. strcpy(p, tok->text);
  3504. p = strchr(p, '\0');
  3505. }
  3506. tok = delete_Token(tok);
  3507. }
  3508. tok = tokenize(buf);
  3509. nasm_free(buf);
  3510. if (prev_next)
  3511. *prev_next = tok;
  3512. else
  3513. *head = tok;
  3514. /*
  3515. * Connect pasted into original stream,
  3516. * ie A -> new-tokens -> B
  3517. */
  3518. while (tok && tok->next)
  3519. tok = tok->next;
  3520. tok->next = next;
  3521. if (!pasted)
  3522. pasted = true;
  3523. /* Restart from pasted tokens head */
  3524. tok = prev_next ? *prev_next : *head;
  3525. }
  3526. break;
  3527. }
  3528. prev_next = &tok->next;
  3529. if (tok->next &&
  3530. !tok_type_(tok->next, TOK_WHITESPACE) &&
  3531. !tok_type_(tok->next, TOK_PASTE))
  3532. prev_nonspace = prev_next;
  3533. tok = tok->next;
  3534. }
  3535. return pasted;
  3536. }
  3537. /*
  3538. * expands to a list of tokens from %{x:y}
  3539. */
  3540. static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
  3541. {
  3542. Token *t = tline, **tt, *tm, *head;
  3543. char *pos;
  3544. int fst, lst, j, i;
  3545. pos = strchr(tline->text, ':');
  3546. nasm_assert(pos);
  3547. lst = atoi(pos + 1);
  3548. fst = atoi(tline->text + 1);
  3549. /*
  3550. * only macros params are accounted so
  3551. * if someone passes %0 -- we reject such
  3552. * value(s)
  3553. */
  3554. if (lst == 0 || fst == 0)
  3555. goto err;
  3556. /* the values should be sane */
  3557. if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
  3558. (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
  3559. goto err;
  3560. fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
  3561. lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
  3562. /* counted from zero */
  3563. fst--, lst--;
  3564. /*
  3565. * It will be at least one token. Note we
  3566. * need to scan params until separator, otherwise
  3567. * only first token will be passed.
  3568. */
  3569. tm = mac->params[(fst + mac->rotate) % mac->nparam];
  3570. if (!tm)
  3571. goto err;
  3572. head = new_Token(NULL, tm->type, tm->text, 0);
  3573. tt = &head->next, tm = tm->next;
  3574. while (tok_isnt_(tm, ",")) {
  3575. t = new_Token(NULL, tm->type, tm->text, 0);
  3576. *tt = t, tt = &t->next, tm = tm->next;
  3577. }
  3578. if (fst < lst) {
  3579. for (i = fst + 1; i <= lst; i++) {
  3580. t = new_Token(NULL, TOK_OTHER, ",", 0);
  3581. *tt = t, tt = &t->next;
  3582. j = (i + mac->rotate) % mac->nparam;
  3583. tm = mac->params[j];
  3584. while (tok_isnt_(tm, ",")) {
  3585. t = new_Token(NULL, tm->type, tm->text, 0);
  3586. *tt = t, tt = &t->next, tm = tm->next;
  3587. }
  3588. }
  3589. } else {
  3590. for (i = fst - 1; i >= lst; i--) {
  3591. t = new_Token(NULL, TOK_OTHER, ",", 0);
  3592. *tt = t, tt = &t->next;
  3593. j = (i + mac->rotate) % mac->nparam;
  3594. tm = mac->params[j];
  3595. while (tok_isnt_(tm, ",")) {
  3596. t = new_Token(NULL, tm->type, tm->text, 0);
  3597. *tt = t, tt = &t->next, tm = tm->next;
  3598. }
  3599. }
  3600. }
  3601. *last = tt;
  3602. return head;
  3603. err:
  3604. nasm_error(ERR_NONFATAL, "`%%{%s}': macro parameters out of range",
  3605. &tline->text[1]);
  3606. return tline;
  3607. }
  3608. /*
  3609. * Expand MMacro-local things: parameter references (%0, %n, %+n,
  3610. * %-n) and MMacro-local identifiers (%%foo) as well as
  3611. * macro indirection (%[...]) and range (%{..:..}).
  3612. */
  3613. static Token *expand_mmac_params(Token * tline)
  3614. {
  3615. Token *t, *tt, **tail, *thead;
  3616. bool changed = false;
  3617. char *pos;
  3618. tail = &thead;
  3619. thead = NULL;
  3620. while (tline) {
  3621. if (tline->type == TOK_PREPROC_ID && tline->text && tline->text[0] &&
  3622. (((tline->text[1] == '+' || tline->text[1] == '-') && tline->text[2]) ||
  3623. (tline->text[1] >= '0' && tline->text[1] <= '9') ||
  3624. tline->text[1] == '%')) {
  3625. char *text = NULL;
  3626. int type = 0, cc; /* type = 0 to placate optimisers */
  3627. char tmpbuf[30];
  3628. unsigned int n;
  3629. int i;
  3630. MMacro *mac;
  3631. t = tline;
  3632. tline = tline->next;
  3633. mac = istk->mstk;
  3634. while (mac && !mac->name) /* avoid mistaking %reps for macros */
  3635. mac = mac->next_active;
  3636. if (!mac) {
  3637. nasm_error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
  3638. } else {
  3639. pos = strchr(t->text, ':');
  3640. if (!pos) {
  3641. switch (t->text[1]) {
  3642. /*
  3643. * We have to make a substitution of one of the
  3644. * forms %1, %-1, %+1, %%foo, %0.
  3645. */
  3646. case '0':
  3647. type = TOK_NUMBER;
  3648. snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
  3649. text = nasm_strdup(tmpbuf);
  3650. break;
  3651. case '%':
  3652. type = TOK_ID;
  3653. snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
  3654. mac->unique);
  3655. text = nasm_strcat(tmpbuf, t->text + 2);
  3656. break;
  3657. case '-':
  3658. n = atoi(t->text + 2) - 1;
  3659. if (n >= mac->nparam)
  3660. tt = NULL;
  3661. else {
  3662. if (mac->nparam > 1)
  3663. n = (n + mac->rotate) % mac->nparam;
  3664. tt = mac->params[n];
  3665. }
  3666. cc = find_cc(tt);
  3667. if (cc == -1) {
  3668. nasm_error(ERR_NONFATAL,
  3669. "macro parameter %d is not a condition code",
  3670. n + 1);
  3671. text = NULL;
  3672. } else {
  3673. type = TOK_ID;
  3674. if (inverse_ccs[cc] == -1) {
  3675. nasm_error(ERR_NONFATAL,
  3676. "condition code `%s' is not invertible",
  3677. conditions[cc]);
  3678. text = NULL;
  3679. } else
  3680. text = nasm_strdup(conditions[inverse_ccs[cc]]);
  3681. }
  3682. break;
  3683. case '+':
  3684. n = atoi(t->text + 2) - 1;
  3685. if (n >= mac->nparam)
  3686. tt = NULL;
  3687. else {
  3688. if (mac->nparam > 1)
  3689. n = (n + mac->rotate) % mac->nparam;
  3690. tt = mac->params[n];
  3691. }
  3692. cc = find_cc(tt);
  3693. if (cc == -1) {
  3694. nasm_error(ERR_NONFATAL,
  3695. "macro parameter %d is not a condition code",
  3696. n + 1);
  3697. text = NULL;
  3698. } else {
  3699. type = TOK_ID;
  3700. text = nasm_strdup(conditions[cc]);
  3701. }
  3702. break;
  3703. default:
  3704. n = atoi(t->text + 1) - 1;
  3705. if (n >= mac->nparam)
  3706. tt = NULL;
  3707. else {
  3708. if (mac->nparam > 1)
  3709. n = (n + mac->rotate) % mac->nparam;
  3710. tt = mac->params[n];
  3711. }
  3712. if (tt) {
  3713. for (i = 0; i < mac->paramlen[n]; i++) {
  3714. *tail = new_Token(NULL, tt->type, tt->text, 0);
  3715. tail = &(*tail)->next;
  3716. tt = tt->next;
  3717. }
  3718. }
  3719. text = NULL; /* we've done it here */
  3720. break;
  3721. }
  3722. } else {
  3723. /*
  3724. * seems we have a parameters range here
  3725. */
  3726. Token *head, **last;
  3727. head = expand_mmac_params_range(mac, t, &last);
  3728. if (head != t) {
  3729. *tail = head;
  3730. *last = tline;
  3731. tline = head;
  3732. text = NULL;
  3733. }
  3734. }
  3735. }
  3736. if (!text) {
  3737. delete_Token(t);
  3738. } else {
  3739. *tail = t;
  3740. tail = &t->next;
  3741. t->type = type;
  3742. nasm_free(t->text);
  3743. t->text = text;
  3744. t->a.mac = NULL;
  3745. }
  3746. changed = true;
  3747. continue;
  3748. } else if (tline->type == TOK_INDIRECT) {
  3749. t = tline;
  3750. tline = tline->next;
  3751. tt = tokenize(t->text);
  3752. tt = expand_mmac_params(tt);
  3753. tt = expand_smacro(tt);
  3754. *tail = tt;
  3755. while (tt) {
  3756. tt->a.mac = NULL; /* Necessary? */
  3757. tail = &tt->next;
  3758. tt = tt->next;
  3759. }
  3760. delete_Token(t);
  3761. changed = true;
  3762. } else {
  3763. t = *tail = tline;
  3764. tline = tline->next;
  3765. t->a.mac = NULL;
  3766. tail = &t->next;
  3767. }
  3768. }
  3769. *tail = NULL;
  3770. if (changed) {
  3771. const struct tokseq_match t[] = {
  3772. {
  3773. PP_CONCAT_MASK(TOK_ID) |
  3774. PP_CONCAT_MASK(TOK_FLOAT), /* head */
  3775. PP_CONCAT_MASK(TOK_ID) |
  3776. PP_CONCAT_MASK(TOK_NUMBER) |
  3777. PP_CONCAT_MASK(TOK_FLOAT) |
  3778. PP_CONCAT_MASK(TOK_OTHER) /* tail */
  3779. },
  3780. {
  3781. PP_CONCAT_MASK(TOK_NUMBER), /* head */
  3782. PP_CONCAT_MASK(TOK_NUMBER) /* tail */
  3783. }
  3784. };
  3785. paste_tokens(&thead, t, ARRAY_SIZE(t), false);
  3786. }
  3787. return thead;
  3788. }
  3789. /*
  3790. * Expand all single-line macro calls made in the given line.
  3791. * Return the expanded version of the line. The original is deemed
  3792. * to be destroyed in the process. (In reality we'll just move
  3793. * Tokens from input to output a lot of the time, rather than
  3794. * actually bothering to destroy and replicate.)
  3795. */
  3796. static Token *expand_smacro(Token * tline)
  3797. {
  3798. Token *t, *tt, *mstart, **tail, *thead;
  3799. SMacro *head = NULL, *m;
  3800. Token **params;
  3801. int *paramsize;
  3802. unsigned int nparam, sparam;
  3803. int brackets;
  3804. Token *org_tline = tline;
  3805. Context *ctx;
  3806. const char *mname;
  3807. int64_t deadman = nasm_limit[LIMIT_MACROS];
  3808. bool expanded;
  3809. /*
  3810. * Trick: we should avoid changing the start token pointer since it can
  3811. * be contained in "next" field of other token. Because of this
  3812. * we allocate a copy of first token and work with it; at the end of
  3813. * routine we copy it back
  3814. */
  3815. if (org_tline) {
  3816. tline = new_Token(org_tline->next, org_tline->type,
  3817. org_tline->text, 0);
  3818. tline->a.mac = org_tline->a.mac;
  3819. nasm_free(org_tline->text);
  3820. org_tline->text = NULL;
  3821. }
  3822. expanded = true; /* Always expand %+ at least once */
  3823. again:
  3824. thead = NULL;
  3825. tail = &thead;
  3826. while (tline) { /* main token loop */
  3827. if (!--deadman) {
  3828. nasm_error(ERR_NONFATAL, "interminable macro recursion");
  3829. goto err;
  3830. }
  3831. if ((mname = tline->text)) {
  3832. /* if this token is a local macro, look in local context */
  3833. if (tline->type == TOK_ID) {
  3834. head = (SMacro *)hash_findix(&smacros, mname);
  3835. } else if (tline->type == TOK_PREPROC_ID) {
  3836. ctx = get_ctx(mname, &mname);
  3837. head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
  3838. } else
  3839. head = NULL;
  3840. /*
  3841. * We've hit an identifier. As in is_mmacro below, we first
  3842. * check whether the identifier is a single-line macro at
  3843. * all, then think about checking for parameters if
  3844. * necessary.
  3845. */
  3846. list_for_each(m, head)
  3847. if (!mstrcmp(m->name, mname, m->casesense))
  3848. break;
  3849. if (m) {
  3850. mstart = tline;
  3851. params = NULL;
  3852. paramsize = NULL;
  3853. if (m->nparam == 0) {
  3854. /*
  3855. * Simple case: the macro is parameterless. Discard the
  3856. * one token that the macro call took, and push the
  3857. * expansion back on the to-do stack.
  3858. */
  3859. if (!m->expansion) {
  3860. if (!strcmp("__FILE__", m->name)) {
  3861. const char *file = src_get_fname();
  3862. /* nasm_free(tline->text); here? */
  3863. tline->text = nasm_quote(file, strlen(file));
  3864. tline->type = TOK_STRING;
  3865. continue;
  3866. }
  3867. if (!strcmp("__LINE__", m->name)) {
  3868. nasm_free(tline->text);
  3869. make_tok_num(tline, src_get_linnum());
  3870. continue;
  3871. }
  3872. if (!strcmp("__BITS__", m->name)) {
  3873. nasm_free(tline->text);
  3874. make_tok_num(tline, globalbits);
  3875. continue;
  3876. }
  3877. tline = delete_Token(tline);
  3878. continue;
  3879. }
  3880. } else {
  3881. /*
  3882. * Complicated case: at least one macro with this name
  3883. * exists and takes parameters. We must find the
  3884. * parameters in the call, count them, find the SMacro
  3885. * that corresponds to that form of the macro call, and
  3886. * substitute for the parameters when we expand. What a
  3887. * pain.
  3888. */
  3889. /*tline = tline->next;
  3890. skip_white_(tline); */
  3891. do {
  3892. t = tline->next;
  3893. while (tok_type_(t, TOK_SMAC_END)) {
  3894. t->a.mac->in_progress = false;
  3895. t->text = NULL;
  3896. t = tline->next = delete_Token(t);
  3897. }
  3898. tline = t;
  3899. } while (tok_type_(tline, TOK_WHITESPACE));
  3900. if (!tok_is_(tline, "(")) {
  3901. /*
  3902. * This macro wasn't called with parameters: ignore
  3903. * the call. (Behaviour borrowed from gnu cpp.)
  3904. */
  3905. tline = mstart;
  3906. m = NULL;
  3907. } else {
  3908. int paren = 0;
  3909. int white = 0;
  3910. brackets = 0;
  3911. nparam = 0;
  3912. sparam = PARAM_DELTA;
  3913. params = nasm_malloc(sparam * sizeof(Token *));
  3914. params[0] = tline->next;
  3915. paramsize = nasm_malloc(sparam * sizeof(int));
  3916. paramsize[0] = 0;
  3917. while (true) { /* parameter loop */
  3918. /*
  3919. * For some unusual expansions
  3920. * which concatenates function call
  3921. */
  3922. t = tline->next;
  3923. while (tok_type_(t, TOK_SMAC_END)) {
  3924. t->a.mac->in_progress = false;
  3925. t->text = NULL;
  3926. t = tline->next = delete_Token(t);
  3927. }
  3928. tline = t;
  3929. if (!tline) {
  3930. nasm_error(ERR_NONFATAL,
  3931. "macro call expects terminating `)'");
  3932. break;
  3933. }
  3934. if (tline->type == TOK_WHITESPACE
  3935. && brackets <= 0) {
  3936. if (paramsize[nparam])
  3937. white++;
  3938. else
  3939. params[nparam] = tline->next;
  3940. continue; /* parameter loop */
  3941. }
  3942. if (tline->type == TOK_OTHER
  3943. && tline->text[1] == 0) {
  3944. char ch = tline->text[0];
  3945. if (ch == ',' && !paren && brackets <= 0) {
  3946. if (++nparam >= sparam) {
  3947. sparam += PARAM_DELTA;
  3948. params = nasm_realloc(params,
  3949. sparam * sizeof(Token *));
  3950. paramsize = nasm_realloc(paramsize,
  3951. sparam * sizeof(int));
  3952. }
  3953. params[nparam] = tline->next;
  3954. paramsize[nparam] = 0;
  3955. white = 0;
  3956. continue; /* parameter loop */
  3957. }
  3958. if (ch == '{' &&
  3959. (brackets > 0 || (brackets == 0 &&
  3960. !paramsize[nparam])))
  3961. {
  3962. if (!(brackets++)) {
  3963. params[nparam] = tline->next;
  3964. continue; /* parameter loop */
  3965. }
  3966. }
  3967. if (ch == '}' && brackets > 0)
  3968. if (--brackets == 0) {
  3969. brackets = -1;
  3970. continue; /* parameter loop */
  3971. }
  3972. if (ch == '(' && !brackets)
  3973. paren++;
  3974. if (ch == ')' && brackets <= 0)
  3975. if (--paren < 0)
  3976. break;
  3977. }
  3978. if (brackets < 0) {
  3979. brackets = 0;
  3980. nasm_error(ERR_NONFATAL, "braces do not "
  3981. "enclose all of macro parameter");
  3982. }
  3983. paramsize[nparam] += white + 1;
  3984. white = 0;
  3985. } /* parameter loop */
  3986. nparam++;
  3987. while (m && (m->nparam != nparam ||
  3988. mstrcmp(m->name, mname,
  3989. m->casesense)))
  3990. m = m->next;
  3991. if (!m)
  3992. nasm_error(ERR_WARNING|ERR_PASS1|WARN_MNP,
  3993. "macro `%s' exists, "
  3994. "but not taking %d parameters",
  3995. mstart->text, nparam);
  3996. }
  3997. }
  3998. if (m && m->in_progress)
  3999. m = NULL;
  4000. if (!m) { /* in progess or didn't find '(' or wrong nparam */
  4001. /*
  4002. * Design question: should we handle !tline, which
  4003. * indicates missing ')' here, or expand those
  4004. * macros anyway, which requires the (t) test a few
  4005. * lines down?
  4006. */
  4007. nasm_free(params);
  4008. nasm_free(paramsize);
  4009. tline = mstart;
  4010. } else {
  4011. /*
  4012. * Expand the macro: we are placed on the last token of the
  4013. * call, so that we can easily split the call from the
  4014. * following tokens. We also start by pushing an SMAC_END
  4015. * token for the cycle removal.
  4016. */
  4017. t = tline;
  4018. if (t) {
  4019. tline = t->next;
  4020. t->next = NULL;
  4021. }
  4022. tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
  4023. tt->a.mac = m;
  4024. m->in_progress = true;
  4025. tline = tt;
  4026. list_for_each(t, m->expansion) {
  4027. if (t->type >= TOK_SMAC_PARAM) {
  4028. Token *pcopy = tline, **ptail = &pcopy;
  4029. Token *ttt, *pt;
  4030. int i;
  4031. ttt = params[t->type - TOK_SMAC_PARAM];
  4032. i = paramsize[t->type - TOK_SMAC_PARAM];
  4033. while (--i >= 0) {
  4034. pt = *ptail = new_Token(tline, ttt->type,
  4035. ttt->text, 0);
  4036. ptail = &pt->next;
  4037. ttt = ttt->next;
  4038. if (!ttt && i > 0) {
  4039. /*
  4040. * FIXME: Need to handle more gracefully,
  4041. * exiting early on agruments analysis.
  4042. */
  4043. nasm_error(ERR_FATAL,
  4044. "macro `%s' expects %d args",
  4045. mstart->text,
  4046. (int)paramsize[t->type - TOK_SMAC_PARAM]);
  4047. }
  4048. }
  4049. tline = pcopy;
  4050. } else if (t->type == TOK_PREPROC_Q) {
  4051. tt = new_Token(tline, TOK_ID, mname, 0);
  4052. tline = tt;
  4053. } else if (t->type == TOK_PREPROC_QQ) {
  4054. tt = new_Token(tline, TOK_ID, m->name, 0);
  4055. tline = tt;
  4056. } else {
  4057. tt = new_Token(tline, t->type, t->text, 0);
  4058. tline = tt;
  4059. }
  4060. }
  4061. /*
  4062. * Having done that, get rid of the macro call, and clean
  4063. * up the parameters.
  4064. */
  4065. nasm_free(params);
  4066. nasm_free(paramsize);
  4067. free_tlist(mstart);
  4068. expanded = true;
  4069. continue; /* main token loop */
  4070. }
  4071. }
  4072. }
  4073. if (tline->type == TOK_SMAC_END) {
  4074. /* On error path it might already be dropped */
  4075. if (tline->a.mac)
  4076. tline->a.mac->in_progress = false;
  4077. tline = delete_Token(tline);
  4078. } else {
  4079. t = *tail = tline;
  4080. tline = tline->next;
  4081. t->a.mac = NULL;
  4082. t->next = NULL;
  4083. tail = &t->next;
  4084. }
  4085. }
  4086. /*
  4087. * Now scan the entire line and look for successive TOK_IDs that resulted
  4088. * after expansion (they can't be produced by tokenize()). The successive
  4089. * TOK_IDs should be concatenated.
  4090. * Also we look for %+ tokens and concatenate the tokens before and after
  4091. * them (without white spaces in between).
  4092. */
  4093. if (expanded) {
  4094. const struct tokseq_match t[] = {
  4095. {
  4096. PP_CONCAT_MASK(TOK_ID) |
  4097. PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
  4098. PP_CONCAT_MASK(TOK_ID) |
  4099. PP_CONCAT_MASK(TOK_PREPROC_ID) |
  4100. PP_CONCAT_MASK(TOK_NUMBER) /* tail */
  4101. }
  4102. };
  4103. if (paste_tokens(&thead, t, ARRAY_SIZE(t), true)) {
  4104. /*
  4105. * If we concatenated something, *and* we had previously expanded
  4106. * an actual macro, scan the lines again for macros...
  4107. */
  4108. tline = thead;
  4109. expanded = false;
  4110. goto again;
  4111. }
  4112. }
  4113. err:
  4114. if (org_tline) {
  4115. if (thead) {
  4116. *org_tline = *thead;
  4117. /* since we just gave text to org_line, don't free it */
  4118. thead->text = NULL;
  4119. delete_Token(thead);
  4120. } else {
  4121. /* the expression expanded to empty line;
  4122. we can't return NULL for some reasons
  4123. we just set the line to a single WHITESPACE token. */
  4124. memset(org_tline, 0, sizeof(*org_tline));
  4125. org_tline->text = NULL;
  4126. org_tline->type = TOK_WHITESPACE;
  4127. }
  4128. thead = org_tline;
  4129. }
  4130. return thead;
  4131. }
  4132. /*
  4133. * Similar to expand_smacro but used exclusively with macro identifiers
  4134. * right before they are fetched in. The reason is that there can be
  4135. * identifiers consisting of several subparts. We consider that if there
  4136. * are more than one element forming the name, user wants a expansion,
  4137. * otherwise it will be left as-is. Example:
  4138. *
  4139. * %define %$abc cde
  4140. *
  4141. * the identifier %$abc will be left as-is so that the handler for %define
  4142. * will suck it and define the corresponding value. Other case:
  4143. *
  4144. * %define _%$abc cde
  4145. *
  4146. * In this case user wants name to be expanded *before* %define starts
  4147. * working, so we'll expand %$abc into something (if it has a value;
  4148. * otherwise it will be left as-is) then concatenate all successive
  4149. * PP_IDs into one.
  4150. */
  4151. static Token *expand_id(Token * tline)
  4152. {
  4153. Token *cur, *oldnext = NULL;
  4154. if (!tline || !tline->next)
  4155. return tline;
  4156. cur = tline;
  4157. while (cur->next &&
  4158. (cur->next->type == TOK_ID ||
  4159. cur->next->type == TOK_PREPROC_ID
  4160. || cur->next->type == TOK_NUMBER))
  4161. cur = cur->next;
  4162. /* If identifier consists of just one token, don't expand */
  4163. if (cur == tline)
  4164. return tline;
  4165. if (cur) {
  4166. oldnext = cur->next; /* Detach the tail past identifier */
  4167. cur->next = NULL; /* so that expand_smacro stops here */
  4168. }
  4169. tline = expand_smacro(tline);
  4170. if (cur) {
  4171. /* expand_smacro possibly changhed tline; re-scan for EOL */
  4172. cur = tline;
  4173. while (cur && cur->next)
  4174. cur = cur->next;
  4175. if (cur)
  4176. cur->next = oldnext;
  4177. }
  4178. return tline;
  4179. }
  4180. /*
  4181. * Determine whether the given line constitutes a multi-line macro
  4182. * call, and return the MMacro structure called if so. Doesn't have
  4183. * to check for an initial label - that's taken care of in
  4184. * expand_mmacro - but must check numbers of parameters. Guaranteed
  4185. * to be called with tline->type == TOK_ID, so the putative macro
  4186. * name is easy to find.
  4187. */
  4188. static MMacro *is_mmacro(Token * tline, Token *** params_array)
  4189. {
  4190. MMacro *head, *m;
  4191. Token **params;
  4192. int nparam;
  4193. head = (MMacro *) hash_findix(&mmacros, tline->text);
  4194. /*
  4195. * Efficiency: first we see if any macro exists with the given
  4196. * name. If not, we can return NULL immediately. _Then_ we
  4197. * count the parameters, and then we look further along the
  4198. * list if necessary to find the proper MMacro.
  4199. */
  4200. list_for_each(m, head)
  4201. if (!mstrcmp(m->name, tline->text, m->casesense))
  4202. break;
  4203. if (!m)
  4204. return NULL;
  4205. /*
  4206. * OK, we have a potential macro. Count and demarcate the
  4207. * parameters.
  4208. */
  4209. count_mmac_params(tline->next, &nparam, &params);
  4210. /*
  4211. * So we know how many parameters we've got. Find the MMacro
  4212. * structure that handles this number.
  4213. */
  4214. while (m) {
  4215. if (m->nparam_min <= nparam
  4216. && (m->plus || nparam <= m->nparam_max)) {
  4217. /*
  4218. * This one is right. Just check if cycle removal
  4219. * prohibits us using it before we actually celebrate...
  4220. */
  4221. if (m->in_progress > m->max_depth) {
  4222. if (m->max_depth > 0) {
  4223. nasm_error(ERR_WARNING,
  4224. "reached maximum recursion depth of %i",
  4225. m->max_depth);
  4226. }
  4227. nasm_free(params);
  4228. return NULL;
  4229. }
  4230. /*
  4231. * It's right, and we can use it. Add its default
  4232. * parameters to the end of our list if necessary.
  4233. */
  4234. if (m->defaults && nparam < m->nparam_min + m->ndefs) {
  4235. params =
  4236. nasm_realloc(params,
  4237. ((m->nparam_min + m->ndefs +
  4238. 1) * sizeof(*params)));
  4239. while (nparam < m->nparam_min + m->ndefs) {
  4240. params[nparam] = m->defaults[nparam - m->nparam_min];
  4241. nparam++;
  4242. }
  4243. }
  4244. /*
  4245. * If we've gone over the maximum parameter count (and
  4246. * we're in Plus mode), ignore parameters beyond
  4247. * nparam_max.
  4248. */
  4249. if (m->plus && nparam > m->nparam_max)
  4250. nparam = m->nparam_max;
  4251. /*
  4252. * Then terminate the parameter list, and leave.
  4253. */
  4254. if (!params) { /* need this special case */
  4255. params = nasm_malloc(sizeof(*params));
  4256. nparam = 0;
  4257. }
  4258. params[nparam] = NULL;
  4259. *params_array = params;
  4260. return m;
  4261. }
  4262. /*
  4263. * This one wasn't right: look for the next one with the
  4264. * same name.
  4265. */
  4266. list_for_each(m, m->next)
  4267. if (!mstrcmp(m->name, tline->text, m->casesense))
  4268. break;
  4269. }
  4270. /*
  4271. * After all that, we didn't find one with the right number of
  4272. * parameters. Issue a warning, and fail to expand the macro.
  4273. */
  4274. nasm_error(ERR_WARNING|ERR_PASS1|WARN_MNP,
  4275. "macro `%s' exists, but not taking %d parameters",
  4276. tline->text, nparam);
  4277. nasm_free(params);
  4278. return NULL;
  4279. }
  4280. /*
  4281. * Save MMacro invocation specific fields in
  4282. * preparation for a recursive macro expansion
  4283. */
  4284. static void push_mmacro(MMacro *m)
  4285. {
  4286. MMacroInvocation *i;
  4287. i = nasm_malloc(sizeof(MMacroInvocation));
  4288. i->prev = m->prev;
  4289. i->params = m->params;
  4290. i->iline = m->iline;
  4291. i->nparam = m->nparam;
  4292. i->rotate = m->rotate;
  4293. i->paramlen = m->paramlen;
  4294. i->unique = m->unique;
  4295. i->condcnt = m->condcnt;
  4296. m->prev = i;
  4297. }
  4298. /*
  4299. * Restore MMacro invocation specific fields that were
  4300. * saved during a previous recursive macro expansion
  4301. */
  4302. static void pop_mmacro(MMacro *m)
  4303. {
  4304. MMacroInvocation *i;
  4305. if (m->prev) {
  4306. i = m->prev;
  4307. m->prev = i->prev;
  4308. m->params = i->params;
  4309. m->iline = i->iline;
  4310. m->nparam = i->nparam;
  4311. m->rotate = i->rotate;
  4312. m->paramlen = i->paramlen;
  4313. m->unique = i->unique;
  4314. m->condcnt = i->condcnt;
  4315. nasm_free(i);
  4316. }
  4317. }
  4318. /*
  4319. * Expand the multi-line macro call made by the given line, if
  4320. * there is one to be expanded. If there is, push the expansion on
  4321. * istk->expansion and return 1. Otherwise return 0.
  4322. */
  4323. static int expand_mmacro(Token * tline)
  4324. {
  4325. Token *startline = tline;
  4326. Token *label = NULL;
  4327. int dont_prepend = 0;
  4328. Token **params, *t, *tt;
  4329. MMacro *m;
  4330. Line *l, *ll;
  4331. int i, nparam, *paramlen;
  4332. const char *mname;
  4333. t = tline;
  4334. skip_white_(t);
  4335. /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
  4336. if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
  4337. return 0;
  4338. m = is_mmacro(t, &params);
  4339. if (m) {
  4340. mname = t->text;
  4341. } else {
  4342. Token *last;
  4343. /*
  4344. * We have an id which isn't a macro call. We'll assume
  4345. * it might be a label; we'll also check to see if a
  4346. * colon follows it. Then, if there's another id after
  4347. * that lot, we'll check it again for macro-hood.
  4348. */
  4349. label = last = t;
  4350. t = t->next;
  4351. if (tok_type_(t, TOK_WHITESPACE))
  4352. last = t, t = t->next;
  4353. if (tok_is_(t, ":")) {
  4354. dont_prepend = 1;
  4355. last = t, t = t->next;
  4356. if (tok_type_(t, TOK_WHITESPACE))
  4357. last = t, t = t->next;
  4358. }
  4359. if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &params)))
  4360. return 0;
  4361. last->next = NULL;
  4362. mname = t->text;
  4363. tline = t;
  4364. }
  4365. /*
  4366. * Fix up the parameters: this involves stripping leading and
  4367. * trailing whitespace, then stripping braces if they are
  4368. * present.
  4369. */
  4370. for (nparam = 0; params[nparam]; nparam++) ;
  4371. paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
  4372. for (i = 0; params[i]; i++) {
  4373. int brace = 0;
  4374. int comma = (!m->plus || i < nparam - 1);
  4375. t = params[i];
  4376. skip_white_(t);
  4377. if (tok_is_(t, "{"))
  4378. t = t->next, brace++, comma = false;
  4379. params[i] = t;
  4380. paramlen[i] = 0;
  4381. while (t) {
  4382. if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
  4383. break; /* ... because we have hit a comma */
  4384. if (comma && t->type == TOK_WHITESPACE
  4385. && tok_is_(t->next, ","))
  4386. break; /* ... or a space then a comma */
  4387. if (brace && t->type == TOK_OTHER) {
  4388. if (t->text[0] == '{')
  4389. brace++; /* ... or a nested opening brace */
  4390. else if (t->text[0] == '}')
  4391. if (!--brace)
  4392. break; /* ... or a brace */
  4393. }
  4394. t = t->next;
  4395. paramlen[i]++;
  4396. }
  4397. if (brace)
  4398. nasm_error(ERR_NONFATAL, "macro params should be enclosed in braces");
  4399. }
  4400. /*
  4401. * OK, we have a MMacro structure together with a set of
  4402. * parameters. We must now go through the expansion and push
  4403. * copies of each Line on to istk->expansion. Substitution of
  4404. * parameter tokens and macro-local tokens doesn't get done
  4405. * until the single-line macro substitution process; this is
  4406. * because delaying them allows us to change the semantics
  4407. * later through %rotate.
  4408. *
  4409. * First, push an end marker on to istk->expansion, mark this
  4410. * macro as in progress, and set up its invocation-specific
  4411. * variables.
  4412. */
  4413. ll = nasm_malloc(sizeof(Line));
  4414. ll->next = istk->expansion;
  4415. ll->finishes = m;
  4416. ll->first = NULL;
  4417. istk->expansion = ll;
  4418. /*
  4419. * Save the previous MMacro expansion in the case of
  4420. * macro recursion
  4421. */
  4422. if (m->max_depth && m->in_progress)
  4423. push_mmacro(m);
  4424. m->in_progress ++;
  4425. m->params = params;
  4426. m->iline = tline;
  4427. m->nparam = nparam;
  4428. m->rotate = 0;
  4429. m->paramlen = paramlen;
  4430. m->unique = unique++;
  4431. m->lineno = 0;
  4432. m->condcnt = 0;
  4433. m->next_active = istk->mstk;
  4434. istk->mstk = m;
  4435. list_for_each(l, m->expansion) {
  4436. Token **tail;
  4437. ll = nasm_malloc(sizeof(Line));
  4438. ll->finishes = NULL;
  4439. ll->next = istk->expansion;
  4440. istk->expansion = ll;
  4441. tail = &ll->first;
  4442. list_for_each(t, l->first) {
  4443. Token *x = t;
  4444. switch (t->type) {
  4445. case TOK_PREPROC_Q:
  4446. tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
  4447. break;
  4448. case TOK_PREPROC_QQ:
  4449. tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
  4450. break;
  4451. case TOK_PREPROC_ID:
  4452. if (t->text[1] == '0' && t->text[2] == '0') {
  4453. dont_prepend = -1;
  4454. x = label;
  4455. if (!x)
  4456. continue;
  4457. }
  4458. /* fall through */
  4459. default:
  4460. tt = *tail = new_Token(NULL, x->type, x->text, 0);
  4461. break;
  4462. }
  4463. tail = &tt->next;
  4464. }
  4465. *tail = NULL;
  4466. }
  4467. /*
  4468. * If we had a label, push it on as the first line of
  4469. * the macro expansion.
  4470. */
  4471. if (label) {
  4472. if (dont_prepend < 0)
  4473. free_tlist(startline);
  4474. else {
  4475. ll = nasm_malloc(sizeof(Line));
  4476. ll->finishes = NULL;
  4477. ll->next = istk->expansion;
  4478. istk->expansion = ll;
  4479. ll->first = startline;
  4480. if (!dont_prepend) {
  4481. while (label->next)
  4482. label = label->next;
  4483. label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
  4484. }
  4485. }
  4486. }
  4487. lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
  4488. return 1;
  4489. }
  4490. /*
  4491. * This function adds macro names to error messages, and suppresses
  4492. * them if necessary.
  4493. */
  4494. static void pp_verror(int severity, const char *fmt, va_list arg)
  4495. {
  4496. char buff[BUFSIZ];
  4497. MMacro *mmac = NULL;
  4498. int delta = 0;
  4499. /*
  4500. * If we're in a dead branch of IF or something like it, ignore the error.
  4501. * However, because %else etc are evaluated in the state context
  4502. * of the previous branch, errors might get lost:
  4503. * %if 0 ... %else trailing garbage ... %endif
  4504. * So %else etc should set the ERR_PP_PRECOND flag.
  4505. */
  4506. if ((severity & ERR_MASK) < ERR_FATAL &&
  4507. istk && istk->conds &&
  4508. ((severity & ERR_PP_PRECOND) ?
  4509. istk->conds->state == COND_NEVER :
  4510. !emitting(istk->conds->state)))
  4511. return;
  4512. /* get %macro name */
  4513. if (!(severity & ERR_NOFILE) && istk && istk->mstk) {
  4514. mmac = istk->mstk;
  4515. /* but %rep blocks should be skipped */
  4516. while (mmac && !mmac->name)
  4517. mmac = mmac->next_active, delta++;
  4518. }
  4519. if (mmac) {
  4520. vsnprintf(buff, sizeof(buff), fmt, arg);
  4521. nasm_set_verror(real_verror);
  4522. nasm_error(severity, "(%s:%d) %s",
  4523. mmac->name, mmac->lineno - delta, buff);
  4524. nasm_set_verror(pp_verror);
  4525. } else {
  4526. real_verror(severity, fmt, arg);
  4527. }
  4528. }
  4529. static void
  4530. pp_reset(const char *file, int apass, StrList **deplist)
  4531. {
  4532. Token *t;
  4533. cstk = NULL;
  4534. istk = nasm_malloc(sizeof(Include));
  4535. istk->next = NULL;
  4536. istk->conds = NULL;
  4537. istk->expansion = NULL;
  4538. istk->mstk = NULL;
  4539. istk->fp = nasm_open_read(file, NF_TEXT);
  4540. istk->fname = NULL;
  4541. src_set(0, file);
  4542. istk->lineinc = 1;
  4543. if (!istk->fp)
  4544. nasm_fatal(ERR_NOFILE, "unable to open input file `%s'", file);
  4545. defining = NULL;
  4546. nested_mac_count = 0;
  4547. nested_rep_count = 0;
  4548. init_macros();
  4549. unique = 0;
  4550. if (tasm_compatible_mode)
  4551. pp_add_stdmac(nasm_stdmac_tasm);
  4552. pp_add_stdmac(nasm_stdmac_nasm);
  4553. pp_add_stdmac(nasm_stdmac_version);
  4554. if (extrastdmac)
  4555. pp_add_stdmac(extrastdmac);
  4556. stdmacpos = stdmacros[0];
  4557. stdmacnext = &stdmacros[1];
  4558. do_predef = true;
  4559. /*
  4560. * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
  4561. * The caller, however, will also pass in 3 for preprocess-only so
  4562. * we can set __PASS__ accordingly.
  4563. */
  4564. pass = apass > 2 ? 2 : apass;
  4565. dephead = deplist;
  4566. nasm_add_string_to_strlist(dephead, file);
  4567. /*
  4568. * Define the __PASS__ macro. This is defined here unlike
  4569. * all the other builtins, because it is special -- it varies between
  4570. * passes.
  4571. */
  4572. t = nasm_malloc(sizeof(*t));
  4573. t->next = NULL;
  4574. make_tok_num(t, apass);
  4575. t->a.mac = NULL;
  4576. define_smacro(NULL, "__PASS__", true, 0, t);
  4577. }
  4578. static void pp_init(void)
  4579. {
  4580. hash_init(&FileHash, HASH_MEDIUM);
  4581. }
  4582. static char *pp_getline(void)
  4583. {
  4584. char *line;
  4585. Token *tline;
  4586. real_verror = nasm_set_verror(pp_verror);
  4587. while (1) {
  4588. /*
  4589. * Fetch a tokenized line, either from the macro-expansion
  4590. * buffer or from the input file.
  4591. */
  4592. tline = NULL;
  4593. while (istk->expansion && istk->expansion->finishes) {
  4594. Line *l = istk->expansion;
  4595. if (!l->finishes->name && l->finishes->in_progress > 1) {
  4596. Line *ll;
  4597. /*
  4598. * This is a macro-end marker for a macro with no
  4599. * name, which means it's not really a macro at all
  4600. * but a %rep block, and the `in_progress' field is
  4601. * more than 1, meaning that we still need to
  4602. * repeat. (1 means the natural last repetition; 0
  4603. * means termination by %exitrep.) We have
  4604. * therefore expanded up to the %endrep, and must
  4605. * push the whole block on to the expansion buffer
  4606. * again. We don't bother to remove the macro-end
  4607. * marker: we'd only have to generate another one
  4608. * if we did.
  4609. */
  4610. l->finishes->in_progress--;
  4611. list_for_each(l, l->finishes->expansion) {
  4612. Token *t, *tt, **tail;
  4613. ll = nasm_malloc(sizeof(Line));
  4614. ll->next = istk->expansion;
  4615. ll->finishes = NULL;
  4616. ll->first = NULL;
  4617. tail = &ll->first;
  4618. list_for_each(t, l->first) {
  4619. if (t->text || t->type == TOK_WHITESPACE) {
  4620. tt = *tail = new_Token(NULL, t->type, t->text, 0);
  4621. tail = &tt->next;
  4622. }
  4623. }
  4624. istk->expansion = ll;
  4625. }
  4626. } else {
  4627. /*
  4628. * Check whether a `%rep' was started and not ended
  4629. * within this macro expansion. This can happen and
  4630. * should be detected. It's a fatal error because
  4631. * I'm too confused to work out how to recover
  4632. * sensibly from it.
  4633. */
  4634. if (defining) {
  4635. if (defining->name)
  4636. nasm_panic(0, "defining with name in expansion");
  4637. else if (istk->mstk->name)
  4638. nasm_fatal(0, "`%%rep' without `%%endrep' within"
  4639. " expansion of macro `%s'",
  4640. istk->mstk->name);
  4641. }
  4642. /*
  4643. * FIXME: investigate the relationship at this point between
  4644. * istk->mstk and l->finishes
  4645. */
  4646. {
  4647. MMacro *m = istk->mstk;
  4648. istk->mstk = m->next_active;
  4649. if (m->name) {
  4650. /*
  4651. * This was a real macro call, not a %rep, and
  4652. * therefore the parameter information needs to
  4653. * be freed.
  4654. */
  4655. if (m->prev) {
  4656. pop_mmacro(m);
  4657. l->finishes->in_progress --;
  4658. } else {
  4659. nasm_free(m->params);
  4660. free_tlist(m->iline);
  4661. nasm_free(m->paramlen);
  4662. l->finishes->in_progress = 0;
  4663. }
  4664. }
  4665. /*
  4666. * FIXME It is incorrect to always free_mmacro here.
  4667. * It leads to usage-after-free.
  4668. *
  4669. * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
  4670. */
  4671. #if 0
  4672. else
  4673. free_mmacro(m);
  4674. #endif
  4675. }
  4676. istk->expansion = l->next;
  4677. nasm_free(l);
  4678. lfmt->downlevel(LIST_MACRO);
  4679. }
  4680. }
  4681. while (1) { /* until we get a line we can use */
  4682. if (istk->expansion) { /* from a macro expansion */
  4683. char *p;
  4684. Line *l = istk->expansion;
  4685. if (istk->mstk)
  4686. istk->mstk->lineno++;
  4687. tline = l->first;
  4688. istk->expansion = l->next;
  4689. nasm_free(l);
  4690. p = detoken(tline, false);
  4691. lfmt->line(LIST_MACRO, p);
  4692. nasm_free(p);
  4693. break;
  4694. }
  4695. line = read_line();
  4696. if (line) { /* from the current input file */
  4697. line = prepreproc(line);
  4698. tline = tokenize(line);
  4699. nasm_free(line);
  4700. break;
  4701. }
  4702. /*
  4703. * The current file has ended; work down the istk
  4704. */
  4705. {
  4706. Include *i = istk;
  4707. fclose(i->fp);
  4708. if (i->conds) {
  4709. /* nasm_error can't be conditionally suppressed */
  4710. nasm_fatal(0,
  4711. "expected `%%endif' before end of file");
  4712. }
  4713. /* only set line and file name if there's a next node */
  4714. if (i->next)
  4715. src_set(i->lineno, i->fname);
  4716. istk = i->next;
  4717. lfmt->downlevel(LIST_INCLUDE);
  4718. nasm_free(i);
  4719. if (!istk) {
  4720. line = NULL;
  4721. goto done;
  4722. }
  4723. if (istk->expansion && istk->expansion->finishes)
  4724. break;
  4725. }
  4726. }
  4727. /*
  4728. * We must expand MMacro parameters and MMacro-local labels
  4729. * _before_ we plunge into directive processing, to cope
  4730. * with things like `%define something %1' such as STRUC
  4731. * uses. Unless we're _defining_ a MMacro, in which case
  4732. * those tokens should be left alone to go into the
  4733. * definition; and unless we're in a non-emitting
  4734. * condition, in which case we don't want to meddle with
  4735. * anything.
  4736. */
  4737. if (!defining && !(istk->conds && !emitting(istk->conds->state))
  4738. && !(istk->mstk && !istk->mstk->in_progress)) {
  4739. tline = expand_mmac_params(tline);
  4740. }
  4741. /*
  4742. * Check the line to see if it's a preprocessor directive.
  4743. */
  4744. if (do_directive(tline, &line) == DIRECTIVE_FOUND) {
  4745. if (line)
  4746. break; /* Directive generated output */
  4747. else
  4748. continue;
  4749. } else if (defining) {
  4750. /*
  4751. * We're defining a multi-line macro. We emit nothing
  4752. * at all, and just
  4753. * shove the tokenized line on to the macro definition.
  4754. */
  4755. Line *l = nasm_malloc(sizeof(Line));
  4756. l->next = defining->expansion;
  4757. l->first = tline;
  4758. l->finishes = NULL;
  4759. defining->expansion = l;
  4760. continue;
  4761. } else if (istk->conds && !emitting(istk->conds->state)) {
  4762. /*
  4763. * We're in a non-emitting branch of a condition block.
  4764. * Emit nothing at all, not even a blank line: when we
  4765. * emerge from the condition we'll give a line-number
  4766. * directive so we keep our place correctly.
  4767. */
  4768. free_tlist(tline);
  4769. continue;
  4770. } else if (istk->mstk && !istk->mstk->in_progress) {
  4771. /*
  4772. * We're in a %rep block which has been terminated, so
  4773. * we're walking through to the %endrep without
  4774. * emitting anything. Emit nothing at all, not even a
  4775. * blank line: when we emerge from the %rep block we'll
  4776. * give a line-number directive so we keep our place
  4777. * correctly.
  4778. */
  4779. free_tlist(tline);
  4780. continue;
  4781. } else {
  4782. tline = expand_smacro(tline);
  4783. if (!expand_mmacro(tline)) {
  4784. /*
  4785. * De-tokenize the line again, and emit it.
  4786. */
  4787. line = detoken(tline, true);
  4788. free_tlist(tline);
  4789. break;
  4790. } else {
  4791. continue; /* expand_mmacro calls free_tlist */
  4792. }
  4793. }
  4794. }
  4795. done:
  4796. nasm_set_verror(real_verror);
  4797. return line;
  4798. }
  4799. static void pp_cleanup(int pass)
  4800. {
  4801. real_verror = nasm_set_verror(pp_verror);
  4802. if (defining) {
  4803. if (defining->name) {
  4804. nasm_error(ERR_NONFATAL,
  4805. "end of file while still defining macro `%s'",
  4806. defining->name);
  4807. } else {
  4808. nasm_error(ERR_NONFATAL, "end of file while still in %%rep");
  4809. }
  4810. free_mmacro(defining);
  4811. defining = NULL;
  4812. }
  4813. nasm_set_verror(real_verror);
  4814. while (cstk)
  4815. ctx_pop();
  4816. free_macros();
  4817. while (istk) {
  4818. Include *i = istk;
  4819. istk = istk->next;
  4820. fclose(i->fp);
  4821. nasm_free(i);
  4822. }
  4823. while (cstk)
  4824. ctx_pop();
  4825. src_set_fname(NULL);
  4826. if (pass == 0) {
  4827. IncPath *i;
  4828. free_llist(predef);
  4829. predef = NULL;
  4830. delete_Blocks();
  4831. freeTokens = NULL;
  4832. while ((i = ipath)) {
  4833. ipath = i->next;
  4834. if (i->path)
  4835. nasm_free(i->path);
  4836. nasm_free(i);
  4837. }
  4838. }
  4839. }
  4840. static void pp_include_path(char *path)
  4841. {
  4842. IncPath *i;
  4843. i = nasm_malloc(sizeof(IncPath));
  4844. i->path = path ? nasm_strdup(path) : NULL;
  4845. i->next = NULL;
  4846. if (ipath) {
  4847. IncPath *j = ipath;
  4848. while (j->next)
  4849. j = j->next;
  4850. j->next = i;
  4851. } else {
  4852. ipath = i;
  4853. }
  4854. }
  4855. static void pp_pre_include(char *fname)
  4856. {
  4857. Token *inc, *space, *name;
  4858. Line *l;
  4859. name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
  4860. space = new_Token(name, TOK_WHITESPACE, NULL, 0);
  4861. inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
  4862. l = nasm_malloc(sizeof(Line));
  4863. l->next = predef;
  4864. l->first = inc;
  4865. l->finishes = NULL;
  4866. predef = l;
  4867. }
  4868. static void pp_pre_define(char *definition)
  4869. {
  4870. Token *def, *space;
  4871. Line *l;
  4872. char *equals;
  4873. real_verror = nasm_set_verror(pp_verror);
  4874. equals = strchr(definition, '=');
  4875. space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
  4876. def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
  4877. if (equals)
  4878. *equals = ' ';
  4879. space->next = tokenize(definition);
  4880. if (equals)
  4881. *equals = '=';
  4882. if (space->next->type != TOK_PREPROC_ID &&
  4883. space->next->type != TOK_ID)
  4884. nasm_error(ERR_WARNING, "pre-defining non ID `%s\'\n", definition);
  4885. l = nasm_malloc(sizeof(Line));
  4886. l->next = predef;
  4887. l->first = def;
  4888. l->finishes = NULL;
  4889. predef = l;
  4890. nasm_set_verror(real_verror);
  4891. }
  4892. static void pp_pre_undefine(char *definition)
  4893. {
  4894. Token *def, *space;
  4895. Line *l;
  4896. space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
  4897. def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
  4898. space->next = tokenize(definition);
  4899. l = nasm_malloc(sizeof(Line));
  4900. l->next = predef;
  4901. l->first = def;
  4902. l->finishes = NULL;
  4903. predef = l;
  4904. }
  4905. /* Insert an early preprocessor command that doesn't need special handling */
  4906. static void pp_pre_command(const char *what, char *string)
  4907. {
  4908. char *cmd;
  4909. Token *def, *space;
  4910. Line *l;
  4911. def = tokenize(string);
  4912. if (what) {
  4913. cmd = nasm_strcat(what[0] == '%' ? "" : "%", what);
  4914. space = new_Token(def, TOK_WHITESPACE, NULL, 0);
  4915. def = new_Token(space, TOK_PREPROC_ID, cmd, 0);
  4916. }
  4917. l = nasm_malloc(sizeof(Line));
  4918. l->next = predef;
  4919. l->first = def;
  4920. l->finishes = NULL;
  4921. predef = l;
  4922. }
  4923. static void pp_add_stdmac(macros_t *macros)
  4924. {
  4925. macros_t **mp;
  4926. /* Find the end of the list and avoid duplicates */
  4927. for (mp = stdmacros; *mp; mp++) {
  4928. if (*mp == macros)
  4929. return; /* Nothing to do */
  4930. }
  4931. nasm_assert(mp < &stdmacros[ARRAY_SIZE(stdmacros)-1]);
  4932. *mp = macros;
  4933. }
  4934. static void pp_extra_stdmac(macros_t *macros)
  4935. {
  4936. extrastdmac = macros;
  4937. }
  4938. static void make_tok_num(Token * tok, int64_t val)
  4939. {
  4940. char numbuf[32];
  4941. snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
  4942. tok->text = nasm_strdup(numbuf);
  4943. tok->type = TOK_NUMBER;
  4944. }
  4945. static void pp_list_one_macro(MMacro *m, int severity)
  4946. {
  4947. if (!m)
  4948. return;
  4949. /* We need to print the next_active list in reverse order */
  4950. pp_list_one_macro(m->next_active, severity);
  4951. if (m->name && !m->nolist) {
  4952. src_set(m->xline + m->lineno, m->fname);
  4953. nasm_error(severity, "... from macro `%s' defined", m->name);
  4954. }
  4955. }
  4956. static void pp_error_list_macros(int severity)
  4957. {
  4958. int32_t saved_line;
  4959. const char *saved_fname = NULL;
  4960. severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
  4961. src_get(&saved_line, &saved_fname);
  4962. if (istk)
  4963. pp_list_one_macro(istk->mstk, severity);
  4964. src_set(saved_line, saved_fname);
  4965. }
  4966. const struct preproc_ops nasmpp = {
  4967. pp_init,
  4968. pp_reset,
  4969. pp_getline,
  4970. pp_cleanup,
  4971. pp_extra_stdmac,
  4972. pp_pre_define,
  4973. pp_pre_undefine,
  4974. pp_pre_include,
  4975. pp_pre_command,
  4976. pp_include_path,
  4977. pp_error_list_macros,
  4978. };