nodefbcc.c 210 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223
  1. /*
  2. Copyright (c) 2021, bartpleiter
  3. Copyright (c) 2012-2020, Alexey Frunze
  4. All rights reserved.
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions are met:
  7. 1. Redistributions of source code must retain the above copyright notice, this
  8. list of conditions and the following disclaimer.
  9. 2. Redistributions in binary form must reproduce the above copyright notice,
  10. this list of conditions and the following disclaimer in the documentation
  11. and/or other materials provided with the distribution.
  12. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  13. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  14. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  16. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  17. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  18. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  19. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  21. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. /*****************************************************************************/
  24. /* */
  25. /* BCC (B322 C Compiler) */
  26. /* */
  27. /* C compiler for B322 */
  28. /* */
  29. /* Based on SmallerC: */
  30. /* A simple and small single-pass C compiler */
  31. /* */
  32. /* Main file */
  33. /* */
  34. /*****************************************************************************/
  35. // NOTE: still has a lot of extras in it that are not needed
  36. // only the "MIPS" part is needed with no extras
  37. // Making most functions static helps with code optimization,
  38. // use that to further reduce compiler's code size on RetroBSD.
  39. #define STATIC
  40. #define NO_EXTRAS
  41. #define CAN_COMPILE_32BIT
  42. #define MIPS
  43. #define B322
  44. #define NO_PPACK
  45. #define NO_TYPEDEF_ENUM
  46. #define NO_FUNC_
  47. #define NO_EXTRA_WARNS
  48. #define NO_FOR_DECL
  49. #define NO_STRUCT_BY_VAL
  50. #define NO_FP
  51. #define NO_WCHAR
  52. #define NULL 0
  53. #define size_t unsigned int
  54. #define CHAR_BIT (8)
  55. #define CHAR_MIN (-128)
  56. #define CHAR_MAX (127)
  57. #define INT_MAX (2147483647)
  58. #define INT_MIN (-2147483647-1)
  59. #define UINT_MAX (4294967295u)
  60. #define UINT_MIN (0u)
  61. #define EXIT_FAILURE 1
  62. void exit(int);
  63. int atoi(char*);
  64. size_t strlen(char*);
  65. char* strcpy(char*, char*);
  66. char* strchr(char*, int);
  67. int strcmp(char*, char*);
  68. int strncmp(char*, char*, size_t);
  69. void* memmove(void*, void*, size_t);
  70. void* memcpy(void*, void*, size_t);
  71. void* memset(void*, int, size_t);
  72. int memcmp(void*, void*, size_t);
  73. int isspace(int);
  74. int isdigit(int);
  75. int isalpha(int);
  76. int isalnum(int);
  77. #define FILE void
  78. #define EOF (-1)
  79. FILE* fopen(char*, char*);
  80. int fclose(FILE*);
  81. //int putchar(int);
  82. int fputc(int, FILE*);
  83. int fgetc(FILE*);
  84. //int puts(char*);
  85. int fputs(char*, FILE*);
  86. //int sprintf(char*, char*, ...);
  87. //int vsprintf(char*, char*, va_list);
  88. //int vsprintf(char*, char*, void*);
  89. int printf(char*, ...);
  90. //int fprintf(FILE*, char*, ...);
  91. //int vprintf(char*, va_list);
  92. //int vprintf(char*, void*);
  93. //int vfprintf(FILE*, char*, va_list);
  94. int vfprintf(FILE*, char*, void*);
  95. /*
  96. struct fpos_t_
  97. {
  98. union
  99. {
  100. unsigned short halves[2]; // for 16-bit memory models without 32-bit longs
  101. int align; // for alignment on machine word boundary
  102. } u;
  103. }; // keep in sync with stdio.h !!!
  104. #define fpos_t struct fpos_t_
  105. int fgetpos(FILE*, fpos_t*);
  106. int fsetpos(FILE*, fpos_t*);
  107. */
  108. ////////////////////////////////////////////////////////////////////////////////
  109. // all public macros
  110. #define MAX_IDENT_LEN 63
  111. #define MAX_STRING_LEN 255
  112. #define MAX_CHAR_QUEUE_LEN (MAX_STRING_LEN + 1)
  113. #define MAX_MACRO_TABLE_LEN (4096+1024)
  114. #define MAX_IDENT_TABLE_LEN (4096+1024+512) // must be greater than MAX_IDENT_LEN
  115. #define SYNTAX_STACK_MAX (2048+1024)
  116. #define MAX_FILE_NAME_LEN 95
  117. #define MAX_INCLUDES 8
  118. #define PREP_STACK_SIZE 8
  119. #define MAX_SEARCH_PATH 256
  120. /* +-~* /% &|^! << >> && || < <= > >= == != () *[] ++ -- = += -= ~= *= /= %= &= |= ^= <<= >>= {} ,;: -> ... */
  121. #define tokEof 0
  122. #define tokNumInt 1
  123. #define tokNumUint 2
  124. #define tokLitStr 3
  125. #define tokLShift 4
  126. #define tokRShift 5
  127. #define tokLogAnd 6
  128. #define tokLogOr 7
  129. #define tokEQ 8
  130. #define tokNEQ 9
  131. #define tokLEQ 10
  132. #define tokGEQ 11
  133. #define tokInc 12
  134. #define tokDec 13
  135. #define tokArrow 14
  136. #define tokEllipsis 15
  137. #define tokIdent 16
  138. #define tokVoid 17
  139. #define tokChar 18
  140. #define tokInt 19
  141. #define tokReturn 20
  142. #define tokGoto 21
  143. #define tokIf 22
  144. #define tokElse 23
  145. #define tokWhile 24
  146. #define tokCont 25
  147. #define tokBreak 26
  148. #define tokSizeof 27
  149. #define tokAssignMul 'A'
  150. #define tokAssignDiv 'B'
  151. #define tokAssignMod 'C'
  152. #define tokAssignAdd 'D'
  153. #define tokAssignSub 'E'
  154. #define tokAssignLSh 'F'
  155. #define tokAssignRSh 'G'
  156. #define tokAssignAnd 'H'
  157. #define tokAssignXor 'I'
  158. #define tokAssignOr 'J'
  159. #define tokFloat 'a'
  160. #define tokDouble 'b'
  161. #define tokLong 'c'
  162. #define tokShort 'd'
  163. #define tokUnsigned 'e'
  164. #define tokSigned 'f'
  165. #define tokConst 'g'
  166. #define tokVolatile 'h'
  167. #define tokRestrict 'i'
  168. #define tokStatic 'j'
  169. #define tokInline 'k'
  170. #define tokExtern 'l'
  171. #define tokAuto 'm'
  172. #define tokRegister 'n'
  173. #define tokTypedef 'o'
  174. #define tokEnum 'p'
  175. #define tokStruct 'q'
  176. #define tokUnion 'r'
  177. #define tokDo 's'
  178. #define tokFor 't'
  179. #define tokSwitch 'u'
  180. #define tokCase 'v'
  181. #define tokDefault 'w'
  182. #define tok_Bool 'x'
  183. #define tok_Complex 'y'
  184. #define tok_Imagin 'z'
  185. #define tok_Asm '`'
  186. /* Pseudo-tokens (converted from others or generated) */
  187. #define tokURShift 28
  188. #define tokUDiv 29
  189. #define tokUMod 30
  190. #define tokAssignURSh 31
  191. #define tokAssignUDiv '@'
  192. #define tokAssignUMod 'K'
  193. #define tokComma '0'
  194. #define tokIfNot 'L'
  195. #define tokUnaryAnd 'M'
  196. #define tokUnaryStar 'N'
  197. #define tokUnaryPlus 'O'
  198. #define tokUnaryMinus 'P'
  199. #define tokPostInc 'Q'
  200. #define tokPostDec 'R'
  201. #define tokPostAdd 'S'
  202. #define tokPostSub 'T'
  203. #define tokULess 'U'
  204. #define tokUGreater 'V'
  205. #define tokULEQ 'W'
  206. #define tokUGEQ 'X'
  207. #define tokLocalOfs 'Y'
  208. #define tokShortCirc 'Z'
  209. #define tokSChar 0x80
  210. #define tokUChar 0x81
  211. #define tokUShort 0x82
  212. #define tokULong 0x83
  213. //#define tokLongLong 0x84
  214. //#define tokULongLong 0x85
  215. //#define tokLongDbl 0x86
  216. #define tokGotoLabel 0x8F
  217. #define tokStructPtr 0x90
  218. #define tokTag 0x91
  219. #define tokMemberIdent 0x92
  220. #define tokEnumPtr 0x93
  221. #define tokIntr 0x94
  222. #define tokNumFloat 0x95
  223. #define tokNumCharWide 0x96
  224. #define tokLitStrWide 0x97
  225. //#define FormatFlat 0
  226. #define FormatSegmented 1
  227. //#define FormatSegTurbo 2
  228. #define FormatSegHuge 3
  229. #define FormatSegUnreal 4
  230. #define SymVoidSynPtr 0
  231. #define SymIntSynPtr 1
  232. #define SymUintSynPtr 2
  233. #define SymWideCharSynPtr 3
  234. #define SymFloatSynPtr 4
  235. #define SymFuncPtr 5
  236. #define STACK_SIZE 129
  237. #define SymFxn 1
  238. #define SymGlobalVar 2
  239. #define SymGlobalArr 3
  240. #define SymLocalVar 4
  241. #define SymLocalArr 5
  242. // Division and Modulo without / and %
  243. STATIC
  244. int divmod(int dividend, int divisor, int* rem)
  245. {
  246. int quotient = 1;
  247. int neg = 1;
  248. if ((dividend>0 &&divisor<0)||(dividend<0 && divisor>0))
  249. neg = -1;
  250. // Convert to positive
  251. int tempdividend = (dividend < 0) ? -dividend : dividend;
  252. int tempdivisor = (divisor < 0) ? -divisor : divisor;
  253. if (tempdivisor == tempdividend) {
  254. *rem = 0;
  255. return 1*neg;
  256. }
  257. else if (tempdividend < tempdivisor) {
  258. if (dividend < 0)
  259. *rem = tempdividend*neg;
  260. else
  261. *rem = tempdividend;
  262. return 0;
  263. }
  264. while (tempdivisor<<1 <= tempdividend)
  265. {
  266. tempdivisor = tempdivisor << 1;
  267. quotient = quotient << 1;
  268. }
  269. // Call division recursively
  270. if(dividend < 0)
  271. quotient = quotient*neg + divmod(-(tempdividend-tempdivisor), divisor, rem);
  272. else
  273. quotient = quotient*neg + divmod(tempdividend-tempdivisor, divisor, rem);
  274. return quotient;
  275. }
  276. STATIC
  277. int division(int dividend, int divisor)
  278. {
  279. int rem = 0;
  280. return divmod(dividend, divisor, &rem);
  281. }
  282. STATIC
  283. int modulo(int dividend, int divisor)
  284. {
  285. int rem = 0;
  286. divmod(dividend, divisor, &rem);
  287. return rem;
  288. }
  289. // isalpha
  290. STATIC
  291. int isalpha(int argument)
  292. {
  293. if (argument >= 'A' && argument <= 'Z')
  294. return 2;
  295. if (argument >= 'a' && argument <= 'z')
  296. return 1;
  297. return 0;
  298. }
  299. // isdigit
  300. STATIC
  301. int isdigit(int argument)
  302. {
  303. if (argument >= '0' && argument <= '9')
  304. return 1;
  305. return 0;
  306. }
  307. // isalnum
  308. STATIC
  309. int isalnum(int argument)
  310. {
  311. if (isdigit(argument) || isalpha(argument))
  312. return 1;
  313. return 0;
  314. }
  315. STATIC
  316. void* memcpy(void *dest, const void *src, size_t len)
  317. {
  318. // Typecast src and dest addresses to (char *)
  319. char *csrc = (char *)src;
  320. char *cdest = (char *)dest;
  321. // Copy contents of src[] to dest[]
  322. int i;
  323. for (i=0; i<len; i++)
  324. cdest[i] = csrc[i];
  325. }
  326. STATIC
  327. void* memmove(void* dest, const void* src, size_t n)
  328. {
  329. unsigned char* from = (unsigned char*) src;
  330. unsigned char* to = (unsigned char*) dest;
  331. if (from == to || n == 0)
  332. return dest;
  333. if (to > from && to-from < (int)n) {
  334. /* to overlaps with from */
  335. /* <from......> */
  336. /* <to........> */
  337. /* copy in reverse, to avoid overwriting from */
  338. int i;
  339. for(i=n-1; i>=0; i--)
  340. to[i] = from[i];
  341. return dest;
  342. }
  343. if (from > to && from-to < (int)n) {
  344. /* to overlaps with from */
  345. /* <from......> */
  346. /* <to........> */
  347. /* copy forwards, to avoid overwriting from */
  348. size_t i;
  349. for(i=0; i<n; i++)
  350. to[i] = from[i];
  351. return dest;
  352. }
  353. memcpy(dest, src, n);
  354. return dest;
  355. }
  356. // Function to implement `strcpy()` function
  357. STATIC
  358. char* strcpy(char* destination, const char* source)
  359. {
  360. // return if no memory is allocated to the destination
  361. if (destination == NULL) {
  362. return NULL;
  363. }
  364. // take a pointer pointing to the beginning of the destination string
  365. char *ptr = destination;
  366. // copy the C-string pointed by source into the array
  367. // pointed by destination
  368. while (*source != '\0')
  369. {
  370. *destination = *source;
  371. destination++;
  372. source++;
  373. }
  374. // include the terminating null character
  375. *destination = '\0';
  376. // the destination is returned by standard `strcpy()`
  377. return ptr;
  378. }
  379. STATIC
  380. size_t strlen(const char *str)
  381. {
  382. const char *s;
  383. for (s = str; *s; ++s);
  384. return (s - str);
  385. }
  386. STATIC
  387. char* strcat (char *dest, const char *src)
  388. {
  389. strcpy (dest + strlen (dest), src);
  390. return dest;
  391. }
  392. STATIC
  393. char* strchr (const char *s, int c)
  394. {
  395. do {
  396. if (*s == c)
  397. {
  398. return (char*)s;
  399. }
  400. } while (*s++);
  401. return (0);
  402. }
  403. STATIC
  404. int strcmp(const char* s1, const char* s2)
  405. {
  406. while(*s1 && (*s1 == *s2))
  407. {
  408. s1++;
  409. s2++;
  410. }
  411. return *(unsigned char*)s1 - *(unsigned char*)s2;
  412. }
  413. //STATIC
  414. int strncmp(const char * s1, const char * s2, size_t n )
  415. {
  416. while ( n && *s1 && ( *s1 == *s2 ) )
  417. {
  418. ++s1;
  419. ++s2;
  420. --n;
  421. }
  422. if ( n == 0 )
  423. {
  424. return 0;
  425. }
  426. else
  427. {
  428. return ( *(unsigned char *)s1 - *(unsigned char *)s2 );
  429. }
  430. }
  431. // all public prototypes
  432. STATIC
  433. unsigned truncUint(unsigned);
  434. STATIC
  435. int truncInt(int);
  436. STATIC
  437. int GetToken(void);
  438. STATIC
  439. char* GetTokenName(int token);
  440. STATIC
  441. void DumpMacroTable(void);
  442. STATIC
  443. int AddIdent(char* name);
  444. STATIC
  445. int FindIdent(char* name);
  446. STATIC
  447. void DumpIdentTable(void);
  448. STATIC
  449. char* lab2str(char* p, int n);
  450. STATIC
  451. void GenInit(void);
  452. STATIC
  453. void GenFin(void);
  454. STATIC
  455. int GenInitParams(int argc, char** argv, int* idx);
  456. STATIC
  457. void GenInitFinalize(void);
  458. STATIC
  459. void GenStartCommentLine(void);
  460. STATIC
  461. void GenWordAlignment(int bss);
  462. STATIC
  463. void GenLabel(char* Label, int Static);
  464. STATIC
  465. void GenNumLabel(int Label);
  466. STATIC
  467. void GenZeroData(unsigned Size, int bss);
  468. STATIC
  469. void GenIntData(int Size, int Val);
  470. STATIC
  471. void GenStartAsciiString(void);
  472. STATIC
  473. void GenAddrData(int Size, char* Label, int ofs);
  474. STATIC
  475. void GenJumpUncond(int Label);
  476. STATIC
  477. void GenJumpIfZero(int Label);
  478. STATIC
  479. void GenJumpIfNotZero(int Label);
  480. STATIC
  481. void GenJumpIfEqual(int val, int Label);
  482. STATIC
  483. void GenFxnProlog(void);
  484. STATIC
  485. void GenFxnEpilog(void);
  486. void GenIsrProlog(void);
  487. void GenIsrEpilog(void);
  488. STATIC
  489. int GenMaxLocalsSize(void);
  490. STATIC
  491. void GenDumpChar(int ch);
  492. STATIC
  493. void GenExpr(void);
  494. STATIC
  495. void PushSyntax(int t);
  496. STATIC
  497. void PushSyntax2(int t, int v);
  498. STATIC
  499. void DumpSynDecls(void);
  500. STATIC
  501. void push2(int v, int v2);
  502. STATIC
  503. void ins2(int pos, int v, int v2);
  504. STATIC
  505. void ins(int pos, int v);
  506. STATIC
  507. void del(int pos, int cnt);
  508. STATIC
  509. int TokenStartsDeclaration(int t, int params);
  510. STATIC
  511. int ParseDecl(int tok, unsigned structInfo[4], int cast, int label);
  512. STATIC
  513. void ShiftChar(void);
  514. STATIC
  515. int puts2(char*);
  516. STATIC
  517. int printf2(char*, ...);
  518. STATIC
  519. void error(char* format, ...);
  520. STATIC
  521. void warning(char* format, ...);
  522. STATIC
  523. void errorFile(char* n);
  524. STATIC
  525. void errorFileName(void);
  526. STATIC
  527. void errorInternal(int n);
  528. STATIC
  529. void errorChrStr(void);
  530. STATIC
  531. void errorStrLen(void);
  532. STATIC
  533. void errorUnexpectedToken(int tok);
  534. STATIC
  535. void errorDirective(void);
  536. STATIC
  537. void errorCtrlOutOfScope(void);
  538. STATIC
  539. void errorDecl(void);
  540. STATIC
  541. void errorVarSize(void);
  542. STATIC
  543. void errorInit(void);
  544. STATIC
  545. void errorUnexpectedVoid(void);
  546. STATIC
  547. void errorOpType(void);
  548. STATIC
  549. void errorNotLvalue(void);
  550. STATIC
  551. void errorNotConst(void);
  552. STATIC
  553. void errorLongExpr(void);
  554. STATIC
  555. int FindSymbol(char* s);
  556. STATIC
  557. int SymType(int SynPtr);
  558. STATIC
  559. int FindTaggedDecl(char* s, int start, int* CurScope);
  560. STATIC
  561. int GetDeclSize(int SyntaxPtr, int SizeForDeref);
  562. STATIC
  563. int ParseExpr(int tok, int* GotUnary, int* ExprTypeSynPtr, int* ConstExpr, int* ConstVal, int option, int option2);
  564. STATIC
  565. int GetFxnInfo(int ExprTypeSynPtr, int* MinParams, int* MaxParams, int* ReturnExprTypeSynPtr, int* FirstParamSynPtr);
  566. // all data
  567. int verbose = 0;
  568. int warnings = 0;
  569. int warnCnt = 0;
  570. // custom compiler flags
  571. int compileUserBDOS = 0;
  572. int compileOS = 0;
  573. // prep.c data
  574. // TBD!!! get rid of TokenIdentName[] and TokenValueString[]
  575. // and work with CharQueue[] directly
  576. int TokenValueInt = 0;
  577. char TokenIdentName[MAX_IDENT_LEN + 1];
  578. int TokenIdentNameLen = 0;
  579. char TokenValueString[MAX_STRING_LEN + 1];
  580. unsigned TokenStringLen = 0;
  581. unsigned TokenStringSize = 0; // TokenStringLen * sizeof(char/wchar_t)
  582. int LineNo = 1;
  583. int LinePos = 1;
  584. char CharQueue[MAX_CHAR_QUEUE_LEN];
  585. int CharQueueLen = 0;
  586. /*
  587. Macro table entry format:
  588. idlen char: identifier length (<= 127)
  589. id char[idlen]: identifier (ASCIIZ)
  590. exlen char: length of what the identifier expands into (<= 127)
  591. ex char[exlen]: what the identifier expands into (ASCII)
  592. */
  593. char MacroTable[MAX_MACRO_TABLE_LEN];
  594. int MacroTableLen = 0;
  595. /*
  596. Identifier table entry format:
  597. id char[idlen]: string (ASCIIZ)
  598. idlen char: string length (<= 127)
  599. */
  600. char IdentTable[MAX_IDENT_TABLE_LEN];
  601. int IdentTableLen = 0;
  602. int DummyIdent; // corresponds to empty string
  603. #define MAX_GOTO_LABELS 16
  604. int gotoLabels[MAX_GOTO_LABELS][2];
  605. // gotoLabStat[]: bit 1 = used (by "goto label;"), bit 0 = defined (with "label:")
  606. char gotoLabStat[MAX_GOTO_LABELS];
  607. int gotoLabCnt = 0;
  608. #define MAX_CASES 128
  609. int Cases[MAX_CASES][2]; // [0] is case constant, [1] is case label number
  610. int CasesCnt = 0;
  611. // Data structures to support #include
  612. int FileCnt = 0;
  613. char FileNames[MAX_INCLUDES][MAX_FILE_NAME_LEN + 1];
  614. FILE* Files[MAX_INCLUDES];
  615. FILE* OutFile;
  616. char CharQueues[MAX_INCLUDES][3];
  617. int LineNos[MAX_INCLUDES];
  618. int LinePoss[MAX_INCLUDES];
  619. char SysSearchPaths[MAX_SEARCH_PATH];
  620. int SysSearchPathsLen = 0;
  621. char SearchPaths[MAX_SEARCH_PATH];
  622. int SearchPathsLen = 0;
  623. // Data structures to support #ifdef/#ifndef,#else,#endif
  624. int PrepDontSkipTokens = 1;
  625. int PrepStack[PREP_STACK_SIZE][2];
  626. int PrepSp = 0;
  627. // expr.c data
  628. int ExprLevel = 0;
  629. // TBD??? merge expression and operator stacks into one
  630. int stack[STACK_SIZE][2];
  631. int sp = 0;
  632. #define OPERATOR_STACK_SIZE STACK_SIZE
  633. int opstack[OPERATOR_STACK_SIZE][2];
  634. int opsp = 0;
  635. // smc.c data
  636. int OutputFormat = FormatSegmented;
  637. int GenExterns = 1;
  638. int UseBss = 1;
  639. // Names of C functions and variables are usually prefixed with an underscore.
  640. // One notable exception is the ELF format used by gcc in Linux.
  641. // Global C identifiers in the ELF format should not be predixed with an underscore.
  642. int UseLeadingUnderscores = 1;
  643. char* FileHeader = "";
  644. char* CodeHeaderFooter[2] = { "", "" };
  645. char* DataHeaderFooter[2] = { "", "" };
  646. char* RoDataHeaderFooter[2] = { "", "" };
  647. char* BssHeaderFooter[2] = { "", "" };
  648. char** CurHeaderFooter;
  649. int CharIsSigned = 1;
  650. int SizeOfWord = 2; // in chars (char can be a multiple of octets); ints and pointers are of word size
  651. int SizeOfWideChar = 2; // in chars/bytes, 2 or 4
  652. int WideCharIsSigned = 0; // 0 or 1
  653. int WideCharType1;
  654. int WideCharType2; // (un)signed counterpart of WideCharType1
  655. // TBD??? implement a function to allocate N labels with overflow checks
  656. int LabelCnt = 1; // label counter for jumps
  657. int StructCpyLabel = 0; // label of the function to copy structures/unions
  658. int StructPushLabel = 0; // label of the function to push structures/unions onto the stack
  659. // call stack (from higher to lower addresses):
  660. // arg n
  661. // ...
  662. // arg 1
  663. // return address
  664. // saved xbp register
  665. // local var 1
  666. // ...
  667. // local var n
  668. int CurFxnSyntaxPtr = 0;
  669. int CurFxnParamCntMin = 0;
  670. int CurFxnParamCntMax = 0;
  671. int CurFxnLocalOfs = 0; // negative
  672. int CurFxnMinLocalOfs = 0; // negative
  673. int CurFxnReturnExprTypeSynPtr = 0;
  674. int CurFxnEpilogLabel = 0;
  675. char* CurFxnName = NULL;
  676. int IsMain; // if inside main()
  677. int ParseLevel = 0; // Parse level/scope (file:0, fxn:1+)
  678. int ParamLevel = 0; // 1+ if parsing params, 0 otherwise
  679. unsigned char SyntaxStack0[SYNTAX_STACK_MAX];
  680. int SyntaxStack1[SYNTAX_STACK_MAX];
  681. int SyntaxStackCnt;
  682. // all code
  683. STATIC
  684. unsigned truncUint(unsigned n)
  685. {
  686. // Truncate n to SizeOfWord * 8 bits
  687. if (SizeOfWord == 2)
  688. n &= ~(~0u << 8 << 8);
  689. else if (SizeOfWord == 4)
  690. n &= ~(~0u << 8 << 12 << 12);
  691. return n;
  692. }
  693. STATIC
  694. int truncInt(int n)
  695. {
  696. // Truncate n to SizeOfWord * 8 bits and then sign-extend it
  697. unsigned un = n;
  698. if (SizeOfWord == 2)
  699. {
  700. un &= ~(~0u << 8 << 8);
  701. un |= (((un >> 8 >> 7) & 1) * ~0u) << 8 << 8;
  702. }
  703. else if (SizeOfWord == 4)
  704. {
  705. un &= ~(~0u << 8 << 12 << 12);
  706. un |= (((un >> 8 >> 12 >> 11) & 1) * ~0u) << 8 << 12 << 12;
  707. }
  708. return (int)un;
  709. }
  710. // prep.c code
  711. STATIC
  712. int FindMacro(char* name)
  713. {
  714. int i;
  715. for (i = 0; i < MacroTableLen; )
  716. {
  717. if (!strcmp(MacroTable + i + 1, name))
  718. return i + 1 + MacroTable[i];
  719. i = i + 1 + MacroTable[i]; // skip id
  720. i = i + 1 + MacroTable[i]; // skip ex
  721. }
  722. return -1;
  723. }
  724. STATIC
  725. int UndefineMacro(char* name)
  726. {
  727. int i;
  728. for (i = 0; i < MacroTableLen; )
  729. {
  730. if (!strcmp(MacroTable + i + 1, name))
  731. {
  732. int len = 1 + MacroTable[i]; // id part len
  733. len = len + 1 + MacroTable[i + len]; // + ex part len
  734. memmove(MacroTable + i,
  735. MacroTable + i + len,
  736. MacroTableLen - i - len);
  737. MacroTableLen -= len;
  738. return 1;
  739. }
  740. i = i + 1 + MacroTable[i]; // skip id
  741. i = i + 1 + MacroTable[i]; // skip ex
  742. }
  743. return 0;
  744. }
  745. STATIC
  746. void AddMacroIdent(char* name)
  747. {
  748. int l = strlen(name);
  749. if (l >= 127)
  750. error("Macro identifier too long '%s'\n", name);
  751. if (MAX_MACRO_TABLE_LEN - MacroTableLen < l + 3)
  752. error("Macro table exhausted\n");
  753. MacroTable[MacroTableLen++] = l + 1; // idlen
  754. strcpy(MacroTable + MacroTableLen, name);
  755. MacroTableLen += l + 1;
  756. MacroTable[MacroTableLen] = 0; // exlen
  757. }
  758. STATIC
  759. void AddMacroExpansionChar(char e)
  760. {
  761. if (e == '\0')
  762. {
  763. // finalize macro definition entry
  764. // remove trailing space first
  765. while (MacroTable[MacroTableLen] &&
  766. strchr(" \t", MacroTable[MacroTableLen + MacroTable[MacroTableLen]]))
  767. MacroTable[MacroTableLen]--;
  768. MacroTableLen += 1 + MacroTable[MacroTableLen];
  769. return;
  770. }
  771. if (MacroTableLen + 1 + MacroTable[MacroTableLen] >= MAX_MACRO_TABLE_LEN)
  772. error("Macro table exhausted\n");
  773. if (MacroTable[MacroTableLen] >= 127)
  774. error("Macro definition too long\n");
  775. MacroTable[MacroTableLen + 1 + MacroTable[MacroTableLen]] = e;
  776. MacroTable[MacroTableLen]++;
  777. }
  778. STATIC
  779. void DefineMacro(char* name, char* expansion)
  780. {
  781. AddMacroIdent(name);
  782. do
  783. {
  784. AddMacroExpansionChar(*expansion);
  785. } while (*expansion++ != '\0');
  786. }
  787. STATIC
  788. void DumpMacroTable(void)
  789. {
  790. int i, j;
  791. puts2("");
  792. GenStartCommentLine(); printf2("Macro table:\n");
  793. for (i = 0; i < MacroTableLen; )
  794. {
  795. GenStartCommentLine(); printf2("Macro %s = ", MacroTable + i + 1);
  796. i = i + 1 + MacroTable[i]; // skip id
  797. printf2("`");
  798. j = MacroTable[i++];
  799. while (j--)
  800. printf2("%c", MacroTable[i++]);
  801. printf2("`\n");
  802. }
  803. GenStartCommentLine(); printf2("Bytes used: %d/%d\n\n", MacroTableLen, MAX_MACRO_TABLE_LEN);
  804. }
  805. STATIC
  806. int FindIdent(char* name)
  807. {
  808. int i;
  809. for (i = IdentTableLen; i > 0; )
  810. {
  811. i -= 1 + IdentTable[i - 1];
  812. if (!strcmp(IdentTable + i, name))
  813. return i;
  814. }
  815. return -1;
  816. }
  817. STATIC
  818. int AddIdent(char* name)
  819. {
  820. int i, len;
  821. if ((i = FindIdent(name)) >= 0)
  822. return i;
  823. i = IdentTableLen;
  824. len = strlen(name);
  825. if (len >= 127)
  826. error("Identifier too long\n");
  827. if (MAX_IDENT_TABLE_LEN - IdentTableLen < len + 2)
  828. error("Identifier table exhausted\n");
  829. strcpy(IdentTable + IdentTableLen, name);
  830. IdentTableLen += len + 1;
  831. IdentTable[IdentTableLen++] = len + 1;
  832. return i;
  833. }
  834. STATIC
  835. int AddNumericIdent(int n)
  836. {
  837. char s[1 + (2 + CHAR_BIT * sizeof n) / 3];
  838. char *p = s + sizeof s;
  839. *--p = '\0';
  840. p = lab2str(p, n);
  841. return AddIdent(p);
  842. }
  843. STATIC
  844. int AddGotoLabel(char* name, int label)
  845. {
  846. int i;
  847. for (i = 0; i < gotoLabCnt; i++)
  848. {
  849. if (!strcmp(IdentTable + gotoLabels[i][0], name))
  850. {
  851. if (gotoLabStat[i] & label)
  852. error("Redefinition of label '%s'\n", name);
  853. gotoLabStat[i] |= 2*!label + label;
  854. return gotoLabels[i][1];
  855. }
  856. }
  857. if (gotoLabCnt >= MAX_GOTO_LABELS)
  858. error("Goto table exhausted\n");
  859. gotoLabels[gotoLabCnt][0] = AddIdent(name);
  860. gotoLabels[gotoLabCnt][1] = LabelCnt++;
  861. gotoLabStat[gotoLabCnt] = 2*!label + label;
  862. return gotoLabels[gotoLabCnt++][1];
  863. }
  864. STATIC
  865. void UndoNonLabelIdents(int len)
  866. {
  867. int i;
  868. IdentTableLen = len;
  869. for (i = 0; i < gotoLabCnt; i++)
  870. if (gotoLabels[i][0] >= len)
  871. {
  872. char* pfrom = IdentTable + gotoLabels[i][0];
  873. char* pto = IdentTable + IdentTableLen;
  874. int l = strlen(pfrom) + 2;
  875. memmove(pto, pfrom, l);
  876. IdentTableLen += l;
  877. gotoLabels[i][0] = pto - IdentTable;
  878. }
  879. }
  880. STATIC
  881. void AddCase(int val, int label)
  882. {
  883. if (CasesCnt >= MAX_CASES)
  884. error("Case table exhausted\n");
  885. Cases[CasesCnt][0] = val;
  886. Cases[CasesCnt++][1] = label;
  887. }
  888. STATIC
  889. void DumpIdentTable(void)
  890. {
  891. int i;
  892. puts2("");
  893. GenStartCommentLine(); printf2("Identifier table:\n");
  894. for (i = 0; i < IdentTableLen; )
  895. {
  896. GenStartCommentLine(); printf2("Ident %s\n", IdentTable + i);
  897. i += strlen(IdentTable + i) + 2;
  898. }
  899. GenStartCommentLine(); printf2("Bytes used: %d/%d\n\n", IdentTableLen, MAX_IDENT_TABLE_LEN);
  900. }
  901. char* rws[] =
  902. {
  903. "break", "case", "char", "continue", "default", "do", "else",
  904. "extern", "for", "if", "int", "return", "signed", "sizeof",
  905. "static", "switch", "unsigned", "void", "while", "asm", "auto",
  906. "const", "double", "enum", "float", "goto", "inline", "long",
  907. "register", "restrict", "short", "struct", "typedef", "union",
  908. "volatile", "_Bool", "_Complex", "_Imaginary",
  909. "__interrupt"
  910. };
  911. unsigned char rwtk[] =
  912. {
  913. tokBreak, tokCase, tokChar, tokCont, tokDefault, tokDo, tokElse,
  914. tokExtern, tokFor, tokIf, tokInt, tokReturn, tokSigned, tokSizeof,
  915. tokStatic, tokSwitch, tokUnsigned, tokVoid, tokWhile, tok_Asm, tokAuto,
  916. tokConst, tokDouble, tokEnum, tokFloat, tokGoto, tokInline, tokLong,
  917. tokRegister, tokRestrict, tokShort, tokStruct, tokTypedef, tokUnion,
  918. tokVolatile, tok_Bool, tok_Complex, tok_Imagin,
  919. tokIntr
  920. };
  921. STATIC
  922. int GetTokenByWord(char* word)
  923. {
  924. unsigned i;
  925. for (i = 0; i < division(sizeof rws, sizeof rws[0]); i++)
  926. if (!strcmp(rws[i], word))
  927. return rwtk[i];
  928. return tokIdent;
  929. }
  930. unsigned char tktk[] =
  931. {
  932. tokEof,
  933. // Single-character operators and punctuators:
  934. '+', '-', '~', '*', '/', '%', '&', '|', '^', '!',
  935. '<', '>', '(', ')', '[', ']',
  936. '{', '}', '=', ',', ';', ':', '.', '?',
  937. // Multi-character operators and punctuators:
  938. tokLShift, tokLogAnd, tokEQ, tokLEQ, tokInc, tokArrow, tokAssignMul,
  939. tokAssignMod, tokAssignSub, tokAssignRSh, tokAssignXor,
  940. tokRShift, tokLogOr, tokNEQ, tokGEQ, tokDec, tokEllipsis,
  941. tokAssignDiv, tokAssignAdd, tokAssignLSh, tokAssignAnd, tokAssignOr,
  942. // Some of the above tokens get converted into these in the process:
  943. tokUnaryAnd, tokUnaryPlus, tokPostInc, tokPostAdd,
  944. tokULess, tokULEQ, tokURShift, tokUDiv, tokUMod, tokComma,
  945. tokUnaryStar, tokUnaryMinus, tokPostDec, tokPostSub,
  946. tokUGreater, tokUGEQ, tokAssignURSh, tokAssignUDiv, tokAssignUMod,
  947. // Helper (pseudo-)tokens:
  948. tokNumInt, tokLitStr, tokLocalOfs, tokNumUint, tokIdent, tokShortCirc,
  949. tokSChar, tokShort, tokLong, tokUChar, tokUShort, tokULong, tokNumFloat,
  950. tokNumCharWide, tokLitStrWide
  951. };
  952. char* tks[] =
  953. {
  954. "<EOF>",
  955. // Single-character operators and punctuators:
  956. "+", "-", "~", "*", "/", "%", "&", "|", "^", "!",
  957. "<", ">", "(", ")", "[", "]",
  958. "{", "}", "=", ",", ";", ":", ".", "?",
  959. // Multi-character operators and punctuators:
  960. "<<", "&&", "==", "<=", "++", "->", "*=",
  961. "%=", "-=", ">>=", "^=",
  962. ">>", "||", "!=", ">=", "--", "...",
  963. "/=", "+=", "<<=", "&=", "|=",
  964. // Some of the above tokens get converted into these in the process:
  965. "&u", "+u", "++p", "+=p",
  966. "<u", "<=u", ">>u", "/u", "%u", ",b",
  967. "*u", "-u", "--p", "-=p",
  968. ">u", ">=u", ">>=u", "/=u", "%=u",
  969. // Helper (pseudo-)tokens:
  970. "<NumInt>", "<LitStr>", "<LocalOfs>", "<NumUint>", "<Ident>", "<ShortCirc>",
  971. "signed char", "short", "long", "unsigned char", "unsigned short", "unsigned long", "float",
  972. "<NumCharWide>", "<LitStrWide>"
  973. };
  974. STATIC
  975. char* GetTokenName(int token)
  976. {
  977. unsigned i;
  978. /* +-~* /% &|^! << >> && || < <= > >= == != () *[] ++ -- = += -= ~= *= /= %= &= |= ^= <<= >>= {} ,;: -> ... */
  979. // Tokens other than reserved keywords:
  980. for (i = 0; i < division(sizeof tktk , sizeof tktk[0]); i++)
  981. if (tktk[i] == token)
  982. return tks[i];
  983. // Reserved keywords:
  984. for (i = 0; i < division(sizeof rws , sizeof rws[0]); i++)
  985. if (rwtk[i] == token)
  986. return rws[i];
  987. //error("Internal Error: GetTokenName(): Invalid token %d\n", token);
  988. errorInternal(1);
  989. return "";
  990. }
  991. STATIC
  992. int GetNextChar(void)
  993. {
  994. int ch = EOF;
  995. if (FileCnt && Files[FileCnt - 1])
  996. {
  997. if ((ch = fgetc(Files[FileCnt - 1])) == EOF)
  998. {
  999. fclose(Files[FileCnt - 1]);
  1000. Files[FileCnt - 1] = NULL;
  1001. // store the last line/pos, they may still be needed later
  1002. LineNos[FileCnt - 1] = LineNo;
  1003. LinePoss[FileCnt - 1] = LinePos;
  1004. // don't drop the file record just yet
  1005. }
  1006. }
  1007. return ch;
  1008. }
  1009. STATIC
  1010. void ShiftChar(void)
  1011. {
  1012. if (CharQueueLen)
  1013. memmove(CharQueue, CharQueue + 1, --CharQueueLen);
  1014. // make sure there always are at least 3 chars in the queue
  1015. while (CharQueueLen < 3)
  1016. {
  1017. int ch = GetNextChar();
  1018. if (ch == EOF)
  1019. ch = '\0';
  1020. CharQueue[CharQueueLen++] = ch;
  1021. }
  1022. }
  1023. STATIC
  1024. void ShiftCharN(int n)
  1025. {
  1026. while (n-- > 0)
  1027. {
  1028. ShiftChar();
  1029. LinePos++;
  1030. }
  1031. }
  1032. STATIC
  1033. void IncludeFile(int quot)
  1034. {
  1035. int nlen = strlen(TokenValueString);
  1036. if (CharQueueLen != 3)
  1037. //error("#include parsing error\n");
  1038. errorInternal(2);
  1039. if (FileCnt >= MAX_INCLUDES)
  1040. error("Too many include files\n");
  1041. // store the including file's position and buffered chars
  1042. LineNos[FileCnt - 1] = LineNo;
  1043. LinePoss[FileCnt - 1] = LinePos;
  1044. memcpy(CharQueues[FileCnt - 1], CharQueue, CharQueueLen);
  1045. // open the included file
  1046. if (nlen > MAX_FILE_NAME_LEN)
  1047. //error("File name too long\n");
  1048. errorFileName();
  1049. // DONE: differentiate between quot == '"' and quot == '<'
  1050. // First, try opening "file" in the current directory
  1051. // (Open Watcom C/C++ 1.9, Turbo C++ 1.01 use the current directory,
  1052. // unlike gcc, which uses the same directory as the current file)
  1053. if (quot == '"')
  1054. {
  1055. // Get path from c file to compile, so it can be appended to the include paths
  1056. char cFileDir[255] = "";
  1057. strcpy(cFileDir, FileNames[0]);
  1058. int len = strlen(cFileDir);
  1059. while (len > 0)
  1060. {
  1061. len--;
  1062. if (cFileDir[len] == '/')
  1063. {
  1064. cFileDir[len+1] = '\0'; // keep the slash
  1065. break;
  1066. }
  1067. }
  1068. if (len == 0) // remove directory if there is none
  1069. {
  1070. cFileDir[0] = '\0';
  1071. }
  1072. strcpy(FileNames[FileCnt], TokenValueString);
  1073. strcat(cFileDir, FileNames[FileCnt]);
  1074. Files[FileCnt] = fopen(cFileDir, "r");
  1075. }
  1076. // Next, iterate the search paths trying to open "file" or <file>.
  1077. // "file" is first searched using the list provided by the -I option.
  1078. // "file" is then searched using the list provided by the -SI option.
  1079. // <file> is searched using the list provided by the -SI option.
  1080. if (Files[FileCnt] == NULL)
  1081. {
  1082. int i;
  1083. char *paths = SearchPaths;
  1084. int pl = SearchPathsLen;
  1085. for (;;)
  1086. {
  1087. if (quot == '<')
  1088. {
  1089. paths = SysSearchPaths;
  1090. pl = SysSearchPathsLen;
  1091. }
  1092. for (i = 0; i < pl; )
  1093. {
  1094. int plen = strlen(paths + i);
  1095. if (plen + 1 + nlen < MAX_FILE_NAME_LEN)
  1096. {
  1097. strcpy(FileNames[FileCnt], paths + i);
  1098. strcpy(FileNames[FileCnt] + plen + 1, TokenValueString);
  1099. // Use '/' as a separator, typical for Linux/Unix,
  1100. // but also supported by file APIs in DOS/Windows just as '\\'
  1101. FileNames[FileCnt][plen] = '/';
  1102. if ((Files[FileCnt] = fopen(FileNames[FileCnt], "r")) != NULL)
  1103. break;
  1104. }
  1105. i += plen + 1;
  1106. }
  1107. if (Files[FileCnt] || quot == '<')
  1108. break;
  1109. quot = '<';
  1110. }
  1111. }
  1112. if (Files[FileCnt] == NULL)
  1113. {
  1114. //error("Cannot open file \"%s\"\n", TokenValueString);
  1115. errorFile(TokenValueString);
  1116. }
  1117. // reset line/pos and empty the char queue
  1118. CharQueueLen = 0;
  1119. LineNo = LinePos = 1;
  1120. FileCnt++;
  1121. // fill the char queue with file data
  1122. ShiftChar();
  1123. }
  1124. STATIC
  1125. int EndOfFiles(void)
  1126. {
  1127. // if there are no including files, we're done
  1128. if (!--FileCnt)
  1129. return 1;
  1130. // restore the including file's position and buffered chars
  1131. LineNo = LineNos[FileCnt - 1];
  1132. LinePos = LinePoss[FileCnt - 1];
  1133. CharQueueLen = 3;
  1134. memcpy(CharQueue, CharQueues[FileCnt - 1], CharQueueLen);
  1135. return 0;
  1136. }
  1137. STATIC
  1138. void SkipSpace(int SkipNewLines)
  1139. {
  1140. char* p = CharQueue;
  1141. while (*p != '\0')
  1142. {
  1143. if (strchr(" \t\f\v", *p))
  1144. {
  1145. ShiftCharN(1);
  1146. continue;
  1147. }
  1148. if (strchr("\r\n", *p))
  1149. {
  1150. if (!SkipNewLines)
  1151. return;
  1152. if (*p == '\r' && p[1] == '\n')
  1153. ShiftChar();
  1154. ShiftChar();
  1155. LineNo++;
  1156. LinePos = 1;
  1157. continue;
  1158. }
  1159. if (*p == '/')
  1160. {
  1161. if (p[1] == '/')
  1162. {
  1163. // // comment
  1164. ShiftCharN(2);
  1165. while (!strchr("\r\n", *p))
  1166. ShiftCharN(1);
  1167. continue;
  1168. }
  1169. else if (p[1] == '*')
  1170. {
  1171. // /**/ comment
  1172. ShiftCharN(2);
  1173. while (*p != '\0' && !(*p == '*' && p[1] == '/'))
  1174. {
  1175. if (strchr("\r\n", *p))
  1176. {
  1177. if (!SkipNewLines)
  1178. error("Invalid comment\n");
  1179. if (*p == '\r' && p[1] == '\n')
  1180. ShiftChar();
  1181. ShiftChar();
  1182. LineNo++;
  1183. LinePos = 1;
  1184. }
  1185. else
  1186. {
  1187. ShiftCharN(1);
  1188. }
  1189. }
  1190. if (*p == '\0')
  1191. error("Invalid comment\n");
  1192. ShiftCharN(2);
  1193. continue;
  1194. }
  1195. } // endof if (*p == '/')
  1196. break;
  1197. } // endof while (*p != '\0')
  1198. }
  1199. STATIC
  1200. void SkipLine(void)
  1201. {
  1202. char* p = CharQueue;
  1203. while (*p != '\0')
  1204. {
  1205. if (strchr("\r\n", *p))
  1206. {
  1207. if (*p == '\r' && p[1] == '\n')
  1208. ShiftChar();
  1209. ShiftChar();
  1210. LineNo++;
  1211. LinePos = 1;
  1212. break;
  1213. }
  1214. else
  1215. {
  1216. ShiftCharN(1);
  1217. }
  1218. }
  1219. }
  1220. STATIC
  1221. void GetIdent(void)
  1222. {
  1223. char* p = CharQueue;
  1224. if (*p != '_' && !isalpha(*p & 0xFFu))
  1225. error("Identifier expected\n");
  1226. TokenIdentNameLen = 0;
  1227. TokenIdentName[TokenIdentNameLen++] = *p;
  1228. TokenIdentName[TokenIdentNameLen] = '\0';
  1229. ShiftCharN(1);
  1230. while (*p == '_' || isalnum(*p & 0xFFu))
  1231. {
  1232. if (TokenIdentNameLen == MAX_IDENT_LEN)
  1233. error("Identifier too long '%s'\n", TokenIdentName);
  1234. TokenIdentName[TokenIdentNameLen++] = *p;
  1235. TokenIdentName[TokenIdentNameLen] = '\0';
  1236. ShiftCharN(1);
  1237. }
  1238. }
  1239. STATIC
  1240. unsigned GetCharValue(int wide)
  1241. {
  1242. char* p = CharQueue;
  1243. unsigned ch = 0;
  1244. int cnt = 0;
  1245. if (*p == '\\')
  1246. {
  1247. ShiftCharN(1);
  1248. if (strchr("\n\r", *p))
  1249. goto lerr;
  1250. if (*p == 'x')
  1251. {
  1252. // hexadecimal character codes \xN+
  1253. // hexadecimal escape sequence is not limited in length per se
  1254. // (may have many leading zeroes)
  1255. static char digs[] = "0123456789ABCDEFabcdef";
  1256. static char vals[] =
  1257. {
  1258. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  1259. 10, 11, 12, 13, 14, 15,
  1260. 10, 11, 12, 13, 14, 15
  1261. };
  1262. char* pp;
  1263. int zeroes = 0;
  1264. ShiftCharN(1);
  1265. if (strchr("\n\r", *p))
  1266. goto lerr;
  1267. if (*p == '0')
  1268. {
  1269. do
  1270. {
  1271. ShiftCharN(1);
  1272. } while (*p == '0');
  1273. zeroes = 1;
  1274. }
  1275. while (*p && (pp = strchr(digs, *p)) != NULL)
  1276. {
  1277. ch <<= 4;
  1278. ch |= vals[pp - digs];
  1279. ShiftCharN(1);
  1280. if (++cnt > 2)
  1281. {
  1282. if (PrepDontSkipTokens)
  1283. goto lerr;
  1284. }
  1285. }
  1286. if (zeroes + cnt == 0)
  1287. goto lerr;
  1288. }
  1289. else if (*p >= '0' && *p <= '7')
  1290. {
  1291. // octal character codes \N+
  1292. // octal escape sequence is terminated after three octal digits
  1293. do
  1294. {
  1295. ch <<= 3;
  1296. ch |= *p - '0';
  1297. ShiftCharN(1);
  1298. ++cnt;
  1299. } while (*p >= '0' && *p <= '7' && cnt < 3);
  1300. if (ch >> 8)
  1301. goto lerr;
  1302. }
  1303. else
  1304. {
  1305. switch (*p)
  1306. {
  1307. case 'a': ch = '\a'; ShiftCharN(1); break;
  1308. case 'b': ch = '\b'; ShiftCharN(1); break;
  1309. case 'f': ch = '\f'; ShiftCharN(1); break;
  1310. case 'n': ch = '\n'; ShiftCharN(1); break;
  1311. case 'r': ch = '\r'; ShiftCharN(1); break;
  1312. case 't': ch = '\t'; ShiftCharN(1); break;
  1313. case 'v': ch = '\v'; ShiftCharN(1); break;
  1314. default:
  1315. goto lself;
  1316. }
  1317. }
  1318. }
  1319. else
  1320. {
  1321. lself:
  1322. if (strchr("\n\r", *p))
  1323. {
  1324. lerr:
  1325. //error("Unsupported or invalid character/string constant\n");
  1326. errorChrStr();
  1327. }
  1328. ch = *p & 0xFFu;
  1329. ShiftCharN(1);
  1330. }
  1331. return ch;
  1332. }
  1333. STATIC
  1334. void GetString(char terminator, int wide, int option)
  1335. {
  1336. char* p = CharQueue;
  1337. unsigned ch = '\0';
  1338. unsigned chsz = 1;
  1339. int i;
  1340. TokenStringLen = 0;
  1341. TokenStringSize = 0;
  1342. TokenValueString[TokenStringLen] = '\0';
  1343. ShiftCharN(1);
  1344. while (!(*p == terminator || strchr("\n\r", *p)))
  1345. {
  1346. ch = GetCharValue(wide);
  1347. switch (option)
  1348. {
  1349. case '#': // string literal (with file name) for #line and #include
  1350. if (TokenStringLen == MAX_STRING_LEN)
  1351. errorStrLen();
  1352. TokenValueString[TokenStringLen++] = ch;
  1353. TokenValueString[TokenStringLen] = '\0';
  1354. TokenStringSize += chsz;
  1355. break;
  1356. case 'a': // string literal for asm()
  1357. printf2("%c", ch);
  1358. break;
  1359. case 'd': // string literal / array of char in expression or initializer
  1360. // Dump the char data to the appropriate data section
  1361. for (i = 0; i < chsz; i++)
  1362. {
  1363. GenDumpChar(ch & 0xFFu);
  1364. ch >>= 8;
  1365. TokenStringLen++; // GenDumpChar() expects it to grow, doesn't know about wchar_t
  1366. }
  1367. TokenStringLen -= chsz;
  1368. // fallthrough
  1369. default: // skipped string literal (we may still need the size)
  1370. if (TokenStringSize > UINT_MAX - chsz)
  1371. errorStrLen();
  1372. TokenStringSize += chsz;
  1373. TokenStringLen++;
  1374. break;
  1375. } // endof switch (option)
  1376. } // endof while (!(*p == '\0' || *p == terminator || strchr("\n\r", *p)))
  1377. if (*p != terminator)
  1378. //error("Unsupported or invalid character/string constant\n");
  1379. errorChrStr();
  1380. if (option == 'd')
  1381. GenDumpChar(-1);
  1382. ShiftCharN(1);
  1383. SkipSpace(option != '#');
  1384. }
  1385. STATIC
  1386. void pushPrep(int NoSkip)
  1387. {
  1388. if (PrepSp >= PREP_STACK_SIZE)
  1389. error("Too many #if(n)def's\n");
  1390. PrepStack[PrepSp][0] = PrepDontSkipTokens;
  1391. PrepStack[PrepSp++][1] = NoSkip;
  1392. PrepDontSkipTokens &= NoSkip;
  1393. }
  1394. STATIC
  1395. int popPrep(void)
  1396. {
  1397. if (PrepSp <= 0)
  1398. error("#else or #endif without #if(n)def\n");
  1399. PrepDontSkipTokens = PrepStack[--PrepSp][0];
  1400. return PrepStack[PrepSp][1];
  1401. }
  1402. STATIC
  1403. int GetNumber(void)
  1404. {
  1405. char* p = CharQueue;
  1406. int ch = *p;
  1407. int leadingZero = (ch == '0');
  1408. unsigned n = 0;
  1409. int type = 0;
  1410. int uSuffix = 0;
  1411. int lSuffix = 0;
  1412. char* eTooBig = "Constant too big\n";
  1413. // First, detect and handle hex constants. Octals can't be detected immediately
  1414. // because floating-point constants also may begin with the digit 0.
  1415. if (leadingZero && (p[1] == 'x' || p[1] == 'X'))
  1416. {
  1417. // this is a hex constant
  1418. int cnt = 0;
  1419. type = 'h';
  1420. ShiftCharN(1);
  1421. ShiftCharN(1);
  1422. while ((ch = *p) != '\0' && (isdigit(ch & 0xFFu) || strchr("abcdefABCDEF", ch)))
  1423. {
  1424. if (ch >= 'a') ch -= 'a' - 10;
  1425. else if (ch >= 'A') ch -= 'A' - 10;
  1426. else ch -= '0';
  1427. //if (PrepDontSkipTokens && (n * 16 / 16 != n || n * 16 + ch < n * 16))
  1428. // error(eTooBig);
  1429. n = n * 16 + ch;
  1430. ShiftCharN(1);
  1431. cnt++;
  1432. }
  1433. if (!cnt)
  1434. error("Invalid hexadecimal constant\n");
  1435. }
  1436. else
  1437. {
  1438. // handle decimal and octal integers
  1439. int base = leadingZero ? 8 : 10;
  1440. type = leadingZero ? 'o' : 'd';
  1441. while ((ch = *p) >= '0' && ch < base + '0')
  1442. {
  1443. ch -= '0';
  1444. if (PrepDontSkipTokens && (n * base + ch < n * base)) //n * base / base != n ||
  1445. error(eTooBig);
  1446. n = n * base + ch;
  1447. ShiftCharN(1);
  1448. }
  1449. }
  1450. // possible combinations of integer suffixes:
  1451. // none
  1452. // U
  1453. // UL
  1454. // L
  1455. // LU
  1456. {
  1457. if ((ch = *p) == 'u' || ch == 'U')
  1458. {
  1459. uSuffix = 1;
  1460. ShiftCharN(1);
  1461. }
  1462. if ((ch = *p) == 'l' || ch == 'L')
  1463. {
  1464. lSuffix = 1;
  1465. ShiftCharN(1);
  1466. if (!uSuffix && ((ch = *p) == 'u' || ch == 'U'))
  1467. {
  1468. uSuffix = 1;
  1469. ShiftCharN(1);
  1470. }
  1471. }
  1472. }
  1473. if (!PrepDontSkipTokens)
  1474. {
  1475. // Don't fail on big constants when skipping tokens under #if
  1476. TokenValueInt = 0;
  1477. return tokNumInt;
  1478. }
  1479. // Ensure the constant fits into 16(32) bits
  1480. if (
  1481. (SizeOfWord == 2 && n >> 8 >> 8) // equiv. to SizeOfWord == 2 && n > 0xFFFF
  1482. || (SizeOfWord == 2 && lSuffix) // long (which must have at least 32 bits) isn't supported in 16-bit models
  1483. || (SizeOfWord == 4 && n >> 8 >> 12 >> 12) // equiv. to SizeOfWord == 4 && n > 0xFFFFFFFF
  1484. )
  1485. error("Constant too big for %d-bit type\n", SizeOfWord * 8);
  1486. TokenValueInt = (int)n;
  1487. // Unsuffixed (with 'u') integer constants (octal, decimal, hex)
  1488. // fitting into 15(31) out of 16(32) bits are signed ints
  1489. if (!uSuffix &&
  1490. (
  1491. (SizeOfWord == 2 && !(n >> 15)) // equiv. to SizeOfWord == 2 && n <= 0x7FFF
  1492. || (SizeOfWord == 4 && !(n >> 8 >> 12 >> 11)) // equiv. to SizeOfWord == 4 && n <= 0x7FFFFFFF
  1493. )
  1494. )
  1495. return tokNumInt;
  1496. // Unlike octal and hex constants, decimal constants are always
  1497. // a signed type. Error out when a decimal constant doesn't fit
  1498. // into an int since currently there's no next bigger signed type
  1499. // (e.g. long) to use instead of int.
  1500. if (!uSuffix && type == 'd')
  1501. error("Constant too big for %d-bit signed type\n", SizeOfWord * 8);
  1502. return tokNumUint;
  1503. }
  1504. STATIC
  1505. int GetTokenInner(void)
  1506. {
  1507. char* p = CharQueue;
  1508. int ch = *p;
  1509. int wide = 0;
  1510. // these single-character tokens/operators need no further processing
  1511. if (strchr(",;:()[]{}~?", ch))
  1512. {
  1513. ShiftCharN(1);
  1514. return ch;
  1515. }
  1516. // parse multi-character tokens/operators
  1517. // DONE: other assignment operators
  1518. switch (ch)
  1519. {
  1520. case '+':
  1521. if (p[1] == '+') { ShiftCharN(2); return tokInc; }
  1522. if (p[1] == '=') { ShiftCharN(2); return tokAssignAdd; }
  1523. ShiftCharN(1); return ch;
  1524. case '-':
  1525. if (p[1] == '-') { ShiftCharN(2); return tokDec; }
  1526. if (p[1] == '=') { ShiftCharN(2); return tokAssignSub; }
  1527. if (p[1] == '>') { ShiftCharN(2); return tokArrow; }
  1528. ShiftCharN(1); return ch;
  1529. case '!':
  1530. if (p[1] == '=') { ShiftCharN(2); return tokNEQ; }
  1531. ShiftCharN(1); return ch;
  1532. case '=':
  1533. if (p[1] == '=') { ShiftCharN(2); return tokEQ; }
  1534. ShiftCharN(1); return ch;
  1535. case '<':
  1536. if (p[1] == '=') { ShiftCharN(2); return tokLEQ; }
  1537. if (p[1] == '<') { ShiftCharN(2); if (p[0] != '=') return tokLShift; ShiftCharN(1); return tokAssignLSh; }
  1538. ShiftCharN(1); return ch;
  1539. case '>':
  1540. if (p[1] == '=') { ShiftCharN(2); return tokGEQ; }
  1541. if (p[1] == '>') { ShiftCharN(2); if (p[0] != '=') return tokRShift; ShiftCharN(1); return tokAssignRSh; }
  1542. ShiftCharN(1); return ch;
  1543. case '&':
  1544. if (p[1] == '&') { ShiftCharN(2); return tokLogAnd; }
  1545. if (p[1] == '=') { ShiftCharN(2); return tokAssignAnd; }
  1546. ShiftCharN(1); return ch;
  1547. case '|':
  1548. if (p[1] == '|') { ShiftCharN(2); return tokLogOr; }
  1549. if (p[1] == '=') { ShiftCharN(2); return tokAssignOr; }
  1550. ShiftCharN(1); return ch;
  1551. case '^':
  1552. if (p[1] == '=') { ShiftCharN(2); return tokAssignXor; }
  1553. ShiftCharN(1); return ch;
  1554. case '.':
  1555. if (p[1] == '.' && p[2] == '.') { ShiftCharN(3); return tokEllipsis; }
  1556. ShiftCharN(1); return ch;
  1557. case '*':
  1558. if (p[1] == '=') { ShiftCharN(2); return tokAssignMul; }
  1559. ShiftCharN(1); return ch;
  1560. case '%':
  1561. if (p[1] == '=') { ShiftCharN(2); return tokAssignMod; }
  1562. ShiftCharN(1); return ch;
  1563. case '/':
  1564. if (p[1] == '=') { ShiftCharN(2); return tokAssignDiv; }
  1565. ShiftCharN(1); return ch;
  1566. }
  1567. // DONE: hex and octal constants
  1568. if (isdigit(ch & 0xFFu))
  1569. return GetNumber();
  1570. // parse character and string constants
  1571. if (ch == '\'')
  1572. {
  1573. unsigned v = 0;
  1574. int cnt = 0;
  1575. int max_cnt = SizeOfWord;
  1576. ShiftCharN(1);
  1577. if (strchr("'\n\r", *p))
  1578. //error("Character constant too short\n");
  1579. errorChrStr();
  1580. do
  1581. {
  1582. v <<= 8;
  1583. v |= GetCharValue(wide);
  1584. if (++cnt > max_cnt)
  1585. //error("Character constant too long\n");
  1586. errorChrStr();
  1587. } while (!strchr("'\n\r", *p));
  1588. if (*p != '\'')
  1589. //error("Unsupported or invalid character/string constant\n");
  1590. errorChrStr();
  1591. ShiftCharN(1);
  1592. {
  1593. if (cnt == 1)
  1594. {
  1595. TokenValueInt = v;
  1596. TokenValueInt -= (CharIsSigned && TokenValueInt >= 0x80) * 0x100;
  1597. }
  1598. else
  1599. {
  1600. TokenValueInt = v;
  1601. TokenValueInt -= (SizeOfWord == 2 && TokenValueInt >= 0x8000) * 0x10000;
  1602. }
  1603. return tokNumInt;
  1604. }
  1605. }
  1606. else if (ch == '"')
  1607. {
  1608. // The caller of GetTokenInner()/GetToken() will call GetString('"', wide, 'd')
  1609. // to complete string literal parsing and storing as appropriate
  1610. return tokLitStr;
  1611. }
  1612. return tokEof;
  1613. }
  1614. STATIC
  1615. void Reserve4Expansion(char* name, int len)
  1616. {
  1617. if (MAX_CHAR_QUEUE_LEN - CharQueueLen < len + 1)
  1618. error("Too long expansion of macro '%s'\n", name);
  1619. memmove(CharQueue + len + 1, CharQueue, CharQueueLen);
  1620. CharQueue[len] = ' '; // space to avoid concatenation
  1621. CharQueueLen += len + 1;
  1622. }
  1623. // TBD??? implement file I/O for input source code and output code (use fxn ptrs/wrappers to make librarization possible)
  1624. // DONE: support string literals
  1625. STATIC
  1626. int GetToken(void)
  1627. {
  1628. char* p = CharQueue;
  1629. int ch;
  1630. int tok;
  1631. for (;;)
  1632. {
  1633. /* +-~* /% &|^! << >> && || < <= > >= == != () *[] ++ -- = += -= ~= *= /= %= &= |= ^= <<= >>= {} ,;: -> ... */
  1634. // skip white space and comments
  1635. SkipSpace(1);
  1636. if ((ch = *p) == '\0')
  1637. {
  1638. // done with the current file, drop its record,
  1639. // pick up the including files (if any) or terminate
  1640. if (EndOfFiles())
  1641. break;
  1642. continue;
  1643. }
  1644. if ((tok = GetTokenInner()) != tokEof)
  1645. {
  1646. if (PrepDontSkipTokens)
  1647. return tok;
  1648. if (tok == tokLitStr)
  1649. GetString('"', 0, 0);
  1650. continue;
  1651. }
  1652. // parse identifiers and reserved keywords
  1653. if (ch == '_' || isalpha(ch & 0xFFu))
  1654. {
  1655. int midx;
  1656. GetIdent();
  1657. if (!PrepDontSkipTokens)
  1658. continue;
  1659. tok = GetTokenByWord(TokenIdentName);
  1660. // TBD!!! think of expanding macros in the context of concatenating string literals,
  1661. // maybe factor out this piece of code
  1662. if (!strcmp(TokenIdentName, "__FILE__"))
  1663. {
  1664. char* p = FileNames[FileCnt - 1];
  1665. int len = strlen(p);
  1666. Reserve4Expansion(TokenIdentName, len + 2);
  1667. *CharQueue = '"';
  1668. memcpy(CharQueue + 1, p, len);
  1669. CharQueue[len + 1] = '"';
  1670. continue;
  1671. }
  1672. else if (!strcmp(TokenIdentName, "__LINE__"))
  1673. {
  1674. char s[(2 + CHAR_BIT * sizeof LineNo) / 3];
  1675. char *p = lab2str(s + sizeof s, LineNo);
  1676. int len = s + sizeof s - p;
  1677. Reserve4Expansion(TokenIdentName, len);
  1678. memcpy(CharQueue, p, len);
  1679. continue;
  1680. }
  1681. else if ((midx = FindMacro(TokenIdentName)) >= 0)
  1682. {
  1683. // this is a macro identifier, need to expand it
  1684. int len = MacroTable[midx];
  1685. Reserve4Expansion(TokenIdentName, len);
  1686. memcpy(CharQueue, MacroTable + midx + 1, len);
  1687. continue;
  1688. }
  1689. // treat keywords auto, const, register, restrict and volatile as white space for now
  1690. if ((tok == tokConst) | (tok == tokVolatile) |
  1691. (tok == tokAuto) | (tok == tokRegister) |
  1692. (tok == tokRestrict))
  1693. continue;
  1694. return tok;
  1695. } // endof if (ch == '_' || isalpha(ch))
  1696. // parse preprocessor directives
  1697. if (ch == '#')
  1698. {
  1699. int line = 0;
  1700. ShiftCharN(1);
  1701. // Skip space
  1702. SkipSpace(0);
  1703. // Allow # not followed by a directive
  1704. if (strchr("\r\n", *p))
  1705. continue;
  1706. // Get preprocessor directive
  1707. if (isdigit(*p & 0xFFu))
  1708. {
  1709. // gcc-style #line directive without "line"
  1710. line = 1;
  1711. }
  1712. else
  1713. {
  1714. GetIdent();
  1715. if (!strcmp(TokenIdentName, "line"))
  1716. {
  1717. // C89-style #line directive
  1718. SkipSpace(0);
  1719. if (!isdigit(*p & 0xFFu))
  1720. errorDirective();
  1721. line = 1;
  1722. }
  1723. }
  1724. if (line)
  1725. {
  1726. // Support for external, gcc-like, preprocessor output:
  1727. // # linenum filename flags
  1728. //
  1729. // no flags, flag = 1 -- start of a file
  1730. // flag = 2 -- return to a file after #include
  1731. // other flags -- uninteresting
  1732. // DONE: should also support the following C89 form:
  1733. // # line linenum filename-opt
  1734. if (GetNumber() != tokNumInt)
  1735. //error("Invalid line number in preprocessor output\n");
  1736. errorDirective();
  1737. line = TokenValueInt;
  1738. SkipSpace(0);
  1739. if (*p == '"' || *p == '<')
  1740. {
  1741. if (*p == '"')
  1742. GetString('"', 0, '#');
  1743. else
  1744. GetString('>', 0, '#');
  1745. if (strlen(TokenValueString) > MAX_FILE_NAME_LEN)
  1746. //error("File name too long in preprocessor output\n");
  1747. errorFileName();
  1748. strcpy(FileNames[FileCnt - 1], TokenValueString);
  1749. }
  1750. // Ignore gcc-style #line's flags, if any
  1751. while (!strchr("\r\n", *p))
  1752. ShiftCharN(1);
  1753. LineNo = line - 1; // "line" is the number of the next line
  1754. LinePos = 1;
  1755. continue;
  1756. } // endof if (line)
  1757. if (!strcmp(TokenIdentName, "define"))
  1758. {
  1759. // Skip space and get macro name
  1760. SkipSpace(0);
  1761. GetIdent();
  1762. if (!PrepDontSkipTokens)
  1763. {
  1764. SkipSpace(0);
  1765. while (!strchr("\r\n", *p))
  1766. ShiftCharN(1);
  1767. continue;
  1768. }
  1769. if (FindMacro(TokenIdentName) >= 0)
  1770. error("Redefinition of macro '%s'\n", TokenIdentName);
  1771. if (*p == '(')
  1772. //error("Unsupported type of macro '%s'\n", TokenIdentName);
  1773. errorDirective();
  1774. AddMacroIdent(TokenIdentName);
  1775. SkipSpace(0);
  1776. // accumulate the macro expansion text
  1777. while (!strchr("\r\n", *p))
  1778. {
  1779. AddMacroExpansionChar(*p);
  1780. ShiftCharN(1);
  1781. if (*p != '\0' && (strchr(" \t", *p) || (*p == '/' && (p[1] == '/' || p[1] == '*'))))
  1782. {
  1783. SkipSpace(0);
  1784. AddMacroExpansionChar(' ');
  1785. }
  1786. }
  1787. AddMacroExpansionChar('\0');
  1788. continue;
  1789. }
  1790. else if (!strcmp(TokenIdentName, "undef"))
  1791. {
  1792. // Skip space and get macro name
  1793. SkipSpace(0);
  1794. GetIdent();
  1795. if (PrepDontSkipTokens)
  1796. UndefineMacro(TokenIdentName);
  1797. SkipSpace(0);
  1798. if (!strchr("\r\n", *p))
  1799. //error("Invalid preprocessor directive\n");
  1800. errorDirective();
  1801. continue;
  1802. }
  1803. else if (!strcmp(TokenIdentName, "include"))
  1804. {
  1805. int quot;
  1806. // Skip space and get file name
  1807. SkipSpace(0);
  1808. quot = *p;
  1809. if (*p == '"')
  1810. GetString('"', 0, '#');
  1811. else if (*p == '<')
  1812. GetString('>', 0, '#');
  1813. else
  1814. //error("Invalid file name\n");
  1815. errorFileName();
  1816. SkipSpace(0);
  1817. if (!strchr("\r\n", *p))
  1818. //error("Unsupported or invalid preprocessor directive\n");
  1819. errorDirective();
  1820. if (PrepDontSkipTokens)
  1821. IncludeFile(quot);
  1822. continue;
  1823. }
  1824. else if (!strcmp(TokenIdentName, "ifdef"))
  1825. {
  1826. int def;
  1827. // Skip space and get macro name
  1828. SkipSpace(0);
  1829. GetIdent();
  1830. def = FindMacro(TokenIdentName) >= 0;
  1831. SkipSpace(0);
  1832. if (!strchr("\r\n", *p))
  1833. //error("Invalid preprocessor directive\n");
  1834. errorDirective();
  1835. pushPrep(def);
  1836. continue;
  1837. }
  1838. else if (!strcmp(TokenIdentName, "ifndef"))
  1839. {
  1840. int def;
  1841. // Skip space and get macro name
  1842. SkipSpace(0);
  1843. GetIdent();
  1844. def = FindMacro(TokenIdentName) >= 0;
  1845. SkipSpace(0);
  1846. if (!strchr("\r\n", *p))
  1847. //error("Invalid preprocessor directive\n");
  1848. errorDirective();
  1849. pushPrep(!def);
  1850. continue;
  1851. }
  1852. else if (!strcmp(TokenIdentName, "else"))
  1853. {
  1854. int def;
  1855. SkipSpace(0);
  1856. if (!strchr("\r\n", *p))
  1857. //error("Invalid preprocessor directive\n");
  1858. errorDirective();
  1859. def = popPrep();
  1860. if (def >= 2)
  1861. error("#else or #endif without #if(n)def\n");
  1862. pushPrep(2 + !def); // #else works in opposite way to its preceding #if(n)def
  1863. continue;
  1864. }
  1865. else if (!strcmp(TokenIdentName, "endif"))
  1866. {
  1867. SkipSpace(0);
  1868. if (!strchr("\r\n", *p))
  1869. //error("Invalid preprocessor directive\n");
  1870. errorDirective();
  1871. popPrep();
  1872. continue;
  1873. }
  1874. if (!PrepDontSkipTokens)
  1875. {
  1876. // If skipping code and directives under #ifdef/#ifndef/#else,
  1877. // ignore unsupported directives #if, #elif, #error (no error checking)
  1878. if (!strcmp(TokenIdentName, "if"))
  1879. pushPrep(0);
  1880. else if (!strcmp(TokenIdentName, "elif"))
  1881. popPrep(), pushPrep(0);
  1882. SkipLine();
  1883. continue;
  1884. }
  1885. //error("Unsupported or invalid preprocessor directive\n");
  1886. errorDirective();
  1887. } // endof if (ch == '#')
  1888. error("Invalid or unsupported character with code 0x%02X\n", *p & 0xFFu);
  1889. } // endof for (;;)
  1890. return tokEof;
  1891. }
  1892. STATIC
  1893. void errorRedecl(char* s)
  1894. {
  1895. error("Invalid or unsupported redeclaration of '%s'\n", s);
  1896. }
  1897. #include "backend.c"
  1898. // expr.c code
  1899. STATIC
  1900. void push2(int v, int v2)
  1901. {
  1902. if (sp >= STACK_SIZE)
  1903. //error("expression stack overflow!\n");
  1904. errorLongExpr();
  1905. stack[sp][0] = v;
  1906. stack[sp++][1] = v2;
  1907. }
  1908. STATIC
  1909. void push(int v)
  1910. {
  1911. push2(v, 0);
  1912. }
  1913. STATIC
  1914. int stacktop()
  1915. {
  1916. if (sp == 0)
  1917. //error("expression stack underflow!\n");
  1918. errorInternal(3);
  1919. return stack[sp - 1][0];
  1920. }
  1921. STATIC
  1922. int pop2(int* v2)
  1923. {
  1924. int v = stacktop();
  1925. *v2 = stack[sp - 1][1];
  1926. sp--;
  1927. return v;
  1928. }
  1929. int pop()
  1930. {
  1931. int v2;
  1932. return pop2(&v2);
  1933. }
  1934. STATIC
  1935. void ins2(int pos, int v, int v2)
  1936. {
  1937. if (sp >= STACK_SIZE)
  1938. //error("expression stack overflow!\n");
  1939. errorLongExpr();
  1940. memmove(&stack[pos + 1], &stack[pos], sizeof(stack[0]) * (sp - pos));
  1941. stack[pos][0] = v;
  1942. stack[pos][1] = v2;
  1943. sp++;
  1944. }
  1945. STATIC
  1946. void ins(int pos, int v)
  1947. {
  1948. ins2(pos, v, 0);
  1949. }
  1950. STATIC
  1951. void del(int pos, int cnt)
  1952. {
  1953. memmove(stack[pos],
  1954. stack[pos + cnt],
  1955. sizeof(stack[0]) * (sp - (pos + cnt)));
  1956. sp -= cnt;
  1957. }
  1958. STATIC
  1959. void pushop2(int v, int v2)
  1960. {
  1961. if (opsp >= OPERATOR_STACK_SIZE)
  1962. //error("operator stack overflow!\n");
  1963. errorLongExpr();
  1964. opstack[opsp][0] = v;
  1965. opstack[opsp++][1] = v2;
  1966. }
  1967. STATIC
  1968. void pushop(int v)
  1969. {
  1970. pushop2(v, 0);
  1971. }
  1972. STATIC
  1973. int opstacktop()
  1974. {
  1975. if (opsp == 0)
  1976. //error("operator stack underflow!\n");
  1977. errorInternal(4);
  1978. return opstack[opsp - 1][0];
  1979. }
  1980. STATIC
  1981. int popop2(int* v2)
  1982. {
  1983. int v = opstacktop();
  1984. *v2 = opstack[opsp - 1][1];
  1985. opsp--;
  1986. return v;
  1987. }
  1988. STATIC
  1989. int popop()
  1990. {
  1991. int v2;
  1992. return popop2(&v2);
  1993. }
  1994. STATIC
  1995. int isop(int tok)
  1996. {
  1997. static unsigned char toks[] =
  1998. {
  1999. '!',
  2000. '~',
  2001. '&',
  2002. '*',
  2003. '/', '%',
  2004. '+', '-',
  2005. '|', '^',
  2006. '<', '>',
  2007. '=',
  2008. tokLogOr, tokLogAnd,
  2009. tokEQ, tokNEQ,
  2010. tokLEQ, tokGEQ,
  2011. tokLShift, tokRShift,
  2012. tokInc, tokDec,
  2013. tokSizeof,
  2014. tokAssignMul, tokAssignDiv, tokAssignMod,
  2015. tokAssignAdd, tokAssignSub,
  2016. tokAssignLSh, tokAssignRSh,
  2017. tokAssignAnd, tokAssignXor, tokAssignOr,
  2018. tokComma,
  2019. '?'
  2020. };
  2021. unsigned i;
  2022. for (i = 0; i < division(sizeof toks , sizeof toks[0]); i++)
  2023. if (toks[i] == tok)
  2024. return 1;
  2025. return 0;
  2026. }
  2027. STATIC
  2028. int isunary(int tok)
  2029. {
  2030. return (tok == '!') | (tok == '~') | (tok == tokInc) | (tok == tokDec) | (tok == tokSizeof);
  2031. }
  2032. STATIC
  2033. int preced(int tok)
  2034. {
  2035. switch (tok)
  2036. {
  2037. case '*': case '/': case '%': return 13;
  2038. case '+': case '-': return 12;
  2039. case tokLShift: case tokRShift: return 11;
  2040. case '<': case '>': case tokLEQ: case tokGEQ: return 10;
  2041. case tokEQ: case tokNEQ: return 9;
  2042. case '&': return 8;
  2043. case '^': return 7;
  2044. case '|': return 6;
  2045. case tokLogAnd: return 5;
  2046. case tokLogOr: return 4;
  2047. case '?': case ':': return 3;
  2048. case '=':
  2049. case tokAssignMul: case tokAssignDiv: case tokAssignMod:
  2050. case tokAssignAdd: case tokAssignSub:
  2051. case tokAssignLSh: case tokAssignRSh:
  2052. case tokAssignAnd: case tokAssignXor: case tokAssignOr:
  2053. return 2;
  2054. case tokComma:
  2055. return 1;
  2056. }
  2057. return 0;
  2058. }
  2059. STATIC
  2060. int precedGEQ(int lfttok, int rhttok)
  2061. {
  2062. // DONE: rethink the comma operator as it could be implemented similarly
  2063. // DONE: is this correct:???
  2064. int pl = preced(lfttok);
  2065. int pr = preced(rhttok);
  2066. // ternary/conditional operator ?: is right-associative
  2067. if (pl == 3 && pr >= 3)
  2068. pl = 0;
  2069. // assignment is right-associative
  2070. if (pl == 2 && pr >= 2)
  2071. pl = 0;
  2072. return pl >= pr;
  2073. }
  2074. STATIC
  2075. int expr(int tok, int* gotUnary, int commaSeparator);
  2076. STATIC
  2077. char* lab2str(char* p, int n)
  2078. {
  2079. do
  2080. {
  2081. *--p = '0' + modulo(n , 10);
  2082. n = division(n, 10);
  2083. } while (n);
  2084. return p;
  2085. }
  2086. STATIC
  2087. int exprUnary(int tok, int* gotUnary, int commaSeparator, int argOfSizeOf)
  2088. {
  2089. static int sizeofLevel = 0;
  2090. int decl = 0;
  2091. *gotUnary = 0;
  2092. if (isop(tok) && (isunary(tok) || strchr("&*+-", tok)))
  2093. {
  2094. int lastTok = tok;
  2095. int sizeofLevelInc = lastTok == tokSizeof;
  2096. sizeofLevel += sizeofLevelInc;
  2097. tok = exprUnary(GetToken(), gotUnary, commaSeparator, sizeofLevelInc);
  2098. sizeofLevel -= sizeofLevelInc;
  2099. if (!*gotUnary)
  2100. //error("exprUnary(): primary expression expected after token %s\n", GetTokenName(lastTok));
  2101. errorUnexpectedToken(tok);
  2102. switch (lastTok)
  2103. {
  2104. // DONE: remove all collapsing of all unary operators.
  2105. // It's wrong because type checking must occur before any optimizations.
  2106. // WRONG: DONE: collapse alternating & and * (e.g. "*&*&x" "&*&*x")
  2107. // WRONGISH: DONE: replace prefix ++/-- with +=1/-=1
  2108. case '&':
  2109. push(tokUnaryAnd);
  2110. break;
  2111. case '*':
  2112. push(tokUnaryStar);
  2113. break;
  2114. case '+':
  2115. push(tokUnaryPlus);
  2116. break;
  2117. case '-':
  2118. push(tokUnaryMinus);
  2119. break;
  2120. case '!':
  2121. // replace "!" with "== 0"
  2122. push(tokNumInt);
  2123. push(tokEQ);
  2124. break;
  2125. default:
  2126. push(lastTok);
  2127. break;
  2128. }
  2129. }
  2130. else
  2131. {
  2132. int inspos = sp;
  2133. if (tok == tokNumInt ||
  2134. tok == tokNumUint)
  2135. {
  2136. push2(tok, TokenValueInt);
  2137. *gotUnary = 1;
  2138. tok = GetToken();
  2139. }
  2140. else if (tok == tokLitStr
  2141. )
  2142. {
  2143. int lbl = LabelCnt++;
  2144. int id;
  2145. int ltok = tok;
  2146. int wide = 0;
  2147. unsigned chsz = 1;
  2148. unsigned sz = chsz;
  2149. // imitate definition: char #[len] = "...";
  2150. if (!sizeofLevel)
  2151. {
  2152. if (CurHeaderFooter)
  2153. puts2(CurHeaderFooter[1]);
  2154. puts2(RoDataHeaderFooter[0]);
  2155. GenNumLabel(lbl);
  2156. }
  2157. do
  2158. {
  2159. GetString('"', wide, sizeofLevel ? 0 : 'd'); // throw away string data inside sizeof, e.g. sizeof "a" or sizeof("a" + 1)
  2160. if (sz + TokenStringSize < sz ||
  2161. sz + TokenStringSize >= truncUint(-1))
  2162. errorStrLen();
  2163. sz += TokenStringSize;
  2164. tok = GetToken();
  2165. } while (tok == ltok); // concatenate adjacent string literals
  2166. if (!sizeofLevel)
  2167. {
  2168. GenZeroData(chsz, 0);
  2169. puts2(RoDataHeaderFooter[1]);
  2170. if (CurHeaderFooter)
  2171. puts2(CurHeaderFooter[0]);
  2172. }
  2173. // DONE: can this break incomplete yet declarations???, e.g.: int x[sizeof("az")][5];
  2174. PushSyntax2(tokIdent, id = AddNumericIdent(lbl));
  2175. PushSyntax('[');
  2176. PushSyntax2(tokNumUint, division(sz, chsz));
  2177. PushSyntax(']');
  2178. PushSyntax(tokChar);
  2179. push2(tokIdent, id);
  2180. *gotUnary = 1;
  2181. }
  2182. else if (tok == tokIdent)
  2183. {
  2184. push2(tok, AddIdent(TokenIdentName));
  2185. *gotUnary = 1;
  2186. tok = GetToken();
  2187. }
  2188. else if (tok == '(')
  2189. {
  2190. tok = GetToken();
  2191. decl = TokenStartsDeclaration(tok, 1);
  2192. if (decl)
  2193. {
  2194. int synPtr;
  2195. int lbl = LabelCnt++;
  2196. char s[1 + (2 + CHAR_BIT * sizeof lbl) / 3 + sizeof "<something>" - 1];
  2197. char *p = s + sizeof s;
  2198. tok = ParseDecl(tok, NULL, !argOfSizeOf, 0);
  2199. if (tok != ')')
  2200. //error("exprUnary(): ')' expected, unexpected token %s\n", GetTokenName(tok));
  2201. errorUnexpectedToken(tok);
  2202. synPtr = FindSymbol("<something>");
  2203. // Rename "<something>" to "<something#>", where # is lbl.
  2204. // This makes the nameless declaration uniquely identifiable by name.
  2205. *--p = '\0';
  2206. *--p = ")>"[argOfSizeOf]; // differentiate casts (something#) from not casts <something#>
  2207. p = lab2str(p, lbl);
  2208. p -= sizeof "<something>" - 2 - 1;
  2209. memcpy(p, "something", sizeof "something" - 1);
  2210. *--p = "(<"[argOfSizeOf]; // differentiate casts (something#) from not casts <something#>
  2211. SyntaxStack1[synPtr] = AddIdent(p);
  2212. tok = GetToken();
  2213. if (argOfSizeOf)
  2214. {
  2215. // expression: sizeof(type)
  2216. *gotUnary = 1;
  2217. }
  2218. else
  2219. {
  2220. // unary type cast operator: (type)
  2221. decl = 0;
  2222. tok = exprUnary(tok, gotUnary, commaSeparator, 0);
  2223. if (!*gotUnary)
  2224. //error("exprUnary(): primary expression expected after '(type)'\n");
  2225. errorUnexpectedToken(tok);
  2226. }
  2227. push2(tokIdent, SyntaxStack1[synPtr]);
  2228. }
  2229. else
  2230. {
  2231. tok = expr(tok, gotUnary, 0);
  2232. if (tok != ')')
  2233. //error("exprUnary(): ')' expected, unexpected token %s\n", GetTokenName(tok));
  2234. errorUnexpectedToken(tok);
  2235. if (!*gotUnary)
  2236. //error("exprUnary(): primary expression expected in '()'\n");
  2237. errorUnexpectedToken(tok);
  2238. tok = GetToken();
  2239. }
  2240. }
  2241. while (*gotUnary && !decl)
  2242. {
  2243. // DONE: f(args1)(args2) and the like: need stack order: args2, args1, f, (), ()
  2244. // DONE: reverse the order of evaluation of groups of args in
  2245. // f(args1)(args2)(args3)
  2246. // DONE: reverse the order of function argument evaluation for variadic functions
  2247. // we want 1st arg to be the closest to the stack top.
  2248. // DONE: (args)[index] can be repeated interchangeably indefinitely
  2249. // DONE: (expr)() & (expr)[]
  2250. // DONE: [index] can be followed by ++/--, which can be followed by [index] and so on...
  2251. // DONE: postfix ++/-- & differentiate from prefix ++/--
  2252. if (tok == '(')
  2253. {
  2254. int acnt = 0;
  2255. ins(inspos, '(');
  2256. for (;;)
  2257. {
  2258. int pos2 = sp;
  2259. tok = GetToken();
  2260. tok = expr(tok, gotUnary, 1);
  2261. // Reverse the order of argument evaluation, which is important for
  2262. // variadic functions like printf():
  2263. // we want 1st arg to be the closest to the stack top.
  2264. // This also reverses the order of evaluation of all groups of
  2265. // arguments.
  2266. while (pos2 < sp)
  2267. {
  2268. // TBD??? not quite efficient
  2269. int v, v2;
  2270. v = pop2(&v2);
  2271. ins2(inspos + 1, v, v2);
  2272. pos2++;
  2273. }
  2274. if (tok == ',')
  2275. {
  2276. if (!*gotUnary)
  2277. //error("exprUnary(): primary expression (fxn argument) expected before ','\n");
  2278. errorUnexpectedToken(tok);
  2279. acnt++;
  2280. ins(inspos + 1, ','); // helper argument separator (hint for expression evaluator)
  2281. continue; // off to next arg
  2282. }
  2283. if (tok == ')')
  2284. {
  2285. if (acnt && !*gotUnary)
  2286. //error("exprUnary(): primary expression (fxn argument) expected between ',' and ')'\n");
  2287. errorUnexpectedToken(tok);
  2288. *gotUnary = 1; // don't fail for 0 args in ()
  2289. break; // end of args
  2290. }
  2291. // DONE: think of inserting special arg pseudo tokens for verification purposes
  2292. //error("exprUnary(): ',' or ')' expected, unexpected token %s\n", GetTokenName(tok));
  2293. errorUnexpectedToken(tok);
  2294. } // endof for(;;) for fxn args
  2295. push(')');
  2296. }
  2297. else if (tok == '[')
  2298. {
  2299. tok = GetToken();
  2300. tok = expr(tok, gotUnary, 0);
  2301. if (!*gotUnary)
  2302. //error("exprUnary(): primary expression expected in '[]'\n");
  2303. errorUnexpectedToken(tok);
  2304. if (tok != ']')
  2305. //error("exprUnary(): ']' expected, unexpected token %s\n", GetTokenName(tok));
  2306. errorUnexpectedToken(tok);
  2307. // TBD??? add implicit casts to size_t of array indicies.
  2308. // E1[E2] -> *(E1 + E2)
  2309. // push('[');
  2310. push('+');
  2311. push(tokUnaryStar);
  2312. }
  2313. // WRONG: DONE: replace postfix ++/-- with (+=1)-1/(-=1)+1
  2314. else if (tok == tokInc)
  2315. {
  2316. push(tokPostInc);
  2317. }
  2318. else if (tok == tokDec)
  2319. {
  2320. push(tokPostDec);
  2321. }
  2322. else if (tok == '.' || tok == tokArrow)
  2323. {
  2324. // transform a.b into (&a)->b
  2325. if (tok == '.')
  2326. push(tokUnaryAnd);
  2327. tok = GetToken();
  2328. if (tok != tokIdent)
  2329. errorUnexpectedToken(tok);
  2330. push2(tok, AddIdent(TokenIdentName));
  2331. // "->" in "a->b" will function as "+" in "*(type_of_b*)((char*)a + offset_of_b_in_a)"
  2332. push(tokArrow);
  2333. push(tokUnaryStar);
  2334. }
  2335. else
  2336. {
  2337. break;
  2338. }
  2339. tok = GetToken();
  2340. } // endof while (*gotUnary)
  2341. }
  2342. if (tok == ',' && !commaSeparator)
  2343. tok = tokComma;
  2344. return tok;
  2345. }
  2346. STATIC
  2347. int expr(int tok, int* gotUnary, int commaSeparator)
  2348. {
  2349. *gotUnary = 0;
  2350. pushop(tokEof);
  2351. tok = exprUnary(tok, gotUnary, commaSeparator, 0);
  2352. while (tok != tokEof && strchr(",;:)]}", tok) == NULL && *gotUnary)
  2353. {
  2354. if (isop(tok) && !isunary(tok))
  2355. {
  2356. while (precedGEQ(opstacktop(), tok))
  2357. {
  2358. int v, v2;
  2359. v = popop2(&v2);
  2360. // move ?expr: as a whole to the expression stack as "expr?"
  2361. if (v == '?')
  2362. {
  2363. int cnt = v2;
  2364. while (cnt--)
  2365. {
  2366. v = popop2(&v2);
  2367. push2(v, v2);
  2368. }
  2369. v = '?';
  2370. v2 = 0;
  2371. }
  2372. push2(v, v2);
  2373. }
  2374. // here: preced(postacktop()) < preced(tok)
  2375. // treat the ternary/conditional operator ?expr: as a pseudo binary operator
  2376. if (tok == '?')
  2377. {
  2378. int ssp = sp;
  2379. int cnt;
  2380. tok = expr(GetToken(), gotUnary, 0);
  2381. if (!*gotUnary || tok != ':')
  2382. errorUnexpectedToken(tok);
  2383. // move ?expr: as a whole to the operator stack
  2384. // this is beautiful and ugly at the same time
  2385. cnt = sp - ssp;
  2386. while (sp > ssp)
  2387. {
  2388. int v, v2;
  2389. v = pop2(&v2);
  2390. pushop2(v, v2);
  2391. }
  2392. // remember the length of the expression between ? and :
  2393. pushop2('?', cnt);
  2394. }
  2395. else
  2396. {
  2397. pushop(tok);
  2398. }
  2399. tok = exprUnary(GetToken(), gotUnary, commaSeparator, 0);
  2400. // DONE: figure out a check to see if exprUnary() fails to add a rhs operand
  2401. if (!*gotUnary)
  2402. //error("expr(): primary expression expected after token %s\n", GetTokenName(lastTok));
  2403. errorUnexpectedToken(tok);
  2404. continue;
  2405. }
  2406. //error("expr(): Unexpected token %s\n", GetTokenName(tok));
  2407. errorUnexpectedToken(tok);
  2408. }
  2409. while (opstacktop() != tokEof)
  2410. {
  2411. int v, v2;
  2412. v = popop2(&v2);
  2413. // move ?expr: as a whole to the expression stack as "expr?"
  2414. if (v == '?')
  2415. {
  2416. int cnt = v2;
  2417. while (cnt--)
  2418. {
  2419. v = popop2(&v2);
  2420. push2(v, v2);
  2421. }
  2422. v = '?';
  2423. v2 = 0;
  2424. }
  2425. push2(v, v2);
  2426. }
  2427. popop();
  2428. return tok;
  2429. }
  2430. STATIC
  2431. int isAnyPtr(int ExprTypeSynPtr)
  2432. {
  2433. if (ExprTypeSynPtr < 0)
  2434. return 1;
  2435. switch (SyntaxStack0[ExprTypeSynPtr])
  2436. {
  2437. case '*':
  2438. case '[':
  2439. case '(':
  2440. return 1;
  2441. }
  2442. return 0;
  2443. }
  2444. STATIC
  2445. int derefAnyPtr(int ExprTypeSynPtr)
  2446. {
  2447. if (ExprTypeSynPtr < 0)
  2448. return -ExprTypeSynPtr;
  2449. switch (SyntaxStack0[ExprTypeSynPtr])
  2450. {
  2451. case '*':
  2452. return ExprTypeSynPtr + 1;
  2453. case '[':
  2454. return ExprTypeSynPtr + 3;
  2455. case '(':
  2456. return ExprTypeSynPtr;
  2457. }
  2458. errorInternal(22);
  2459. return -1;
  2460. }
  2461. STATIC
  2462. void decayArray(int* ExprTypeSynPtr, int arithmetic)
  2463. {
  2464. // Dacay arrays to pointers to their first elements
  2465. if (*ExprTypeSynPtr >= 0 && SyntaxStack0[*ExprTypeSynPtr] == '[')
  2466. {
  2467. (*ExprTypeSynPtr) += 3;
  2468. // we cannot insert another '*' into the type to make it a pointer
  2469. // to the first element, so make the index into the type negative
  2470. *ExprTypeSynPtr = -*ExprTypeSynPtr;
  2471. }
  2472. // DONE: disallow arithmetic on pointers to void
  2473. // DONE: disallow function pointers
  2474. if (arithmetic && isAnyPtr(*ExprTypeSynPtr))
  2475. {
  2476. int pointee = derefAnyPtr(*ExprTypeSynPtr);
  2477. switch (SyntaxStack0[pointee])
  2478. {
  2479. case tokVoid:
  2480. //error("decayArray(): cannot do pointer arithmetic on a pointer to 'void'\n");
  2481. errorUnexpectedVoid();
  2482. default:
  2483. //error("decayArray(): cannot do pointer arithmetic on a pointer to an incomplete type\n");
  2484. if (!GetDeclSize(pointee, 0))
  2485. // "fallthrough"
  2486. case '(':
  2487. //error("decayArray(): cannot do pointer arithmetic on a pointer to a function\n");
  2488. errorOpType();
  2489. }
  2490. }
  2491. }
  2492. STATIC
  2493. void lvalueCheck(int ExprTypeSynPtr, int pos)
  2494. {
  2495. if (ExprTypeSynPtr >= 0 &&
  2496. (SyntaxStack0[ExprTypeSynPtr] == '[' || SyntaxStack0[ExprTypeSynPtr] == '('))
  2497. {
  2498. // we can have arrays formed by dereference, e.g.
  2499. // char (*pac)[1]; // *pac is array of 1 char
  2500. // // ++*pac or (*pac)-- are not allowed
  2501. // and likewise functions, e.g.
  2502. // int (*pf)(int); // *pf is a function taking int and returning int
  2503. // // *pf = 0; is not allowed
  2504. // and that dereference shouldn't be confused for lvalue,
  2505. // hence explicitly checking for array and function types
  2506. //error("exprval(): lvalue expected\n");
  2507. errorNotLvalue();
  2508. }
  2509. // lvalue is a dereferenced address, check for a dereference
  2510. if (stack[pos][0] != tokUnaryStar)
  2511. //error("exprval(): lvalue expected\n");
  2512. errorNotLvalue();
  2513. }
  2514. STATIC
  2515. void nonVoidTypeCheck(int ExprTypeSynPtr)
  2516. {
  2517. if (ExprTypeSynPtr >= 0 && SyntaxStack0[ExprTypeSynPtr] == tokVoid)
  2518. //error("nonVoidTypeCheck(): unexpected operand type 'void' for operator '%s'\n", GetTokenName(tok));
  2519. errorUnexpectedVoid();
  2520. }
  2521. STATIC
  2522. void scalarTypeCheck(int ExprTypeSynPtr)
  2523. {
  2524. nonVoidTypeCheck(ExprTypeSynPtr);
  2525. if (ExprTypeSynPtr >= 0 && SyntaxStack0[ExprTypeSynPtr] == tokStructPtr)
  2526. errorOpType();
  2527. }
  2528. STATIC
  2529. void numericTypeCheck(int ExprTypeSynPtr)
  2530. {
  2531. if (ExprTypeSynPtr >= 0)
  2532. switch (SyntaxStack0[ExprTypeSynPtr])
  2533. {
  2534. case tokChar:
  2535. case tokSChar:
  2536. case tokUChar:
  2537. case tokShort:
  2538. case tokUShort:
  2539. case tokInt:
  2540. case tokUnsigned:
  2541. return;
  2542. }
  2543. //error("numericTypeCheck(): unexpected operand type for operator '%s', numeric type expected\n", GetTokenName(tok));
  2544. errorOpType();
  2545. }
  2546. STATIC
  2547. void anyIntTypeCheck(int ExprTypeSynPtr)
  2548. {
  2549. // Check for any integer type
  2550. numericTypeCheck(ExprTypeSynPtr);
  2551. }
  2552. STATIC
  2553. int isUint(int ExprTypeSynPtr)
  2554. {
  2555. return ExprTypeSynPtr >= 0 && SyntaxStack0[ExprTypeSynPtr] == tokUnsigned;
  2556. }
  2557. STATIC
  2558. void compatCheck(int* ExprTypeSynPtr, int TheOtherExprTypeSynPtr, int ConstExpr[2], int lidx, int ridx)
  2559. {
  2560. int exprTypeSynPtr = *ExprTypeSynPtr;
  2561. int c = 0;
  2562. int lptr, rptr, lnum, rnum;
  2563. // (un)decay/convert functions to pointers to functions
  2564. // and to simplify matters convert all '*' pointers to negative type indices
  2565. if (exprTypeSynPtr >= 0)
  2566. {
  2567. switch (SyntaxStack0[exprTypeSynPtr])
  2568. {
  2569. case '*':
  2570. exprTypeSynPtr++;
  2571. // fallthrough
  2572. case '(':
  2573. exprTypeSynPtr = -exprTypeSynPtr;
  2574. }
  2575. *ExprTypeSynPtr = exprTypeSynPtr;
  2576. }
  2577. if (TheOtherExprTypeSynPtr >= 0)
  2578. {
  2579. switch (SyntaxStack0[TheOtherExprTypeSynPtr])
  2580. {
  2581. case '*':
  2582. TheOtherExprTypeSynPtr++;
  2583. // fallthrough
  2584. case '(':
  2585. TheOtherExprTypeSynPtr = -TheOtherExprTypeSynPtr;
  2586. }
  2587. }
  2588. lptr = exprTypeSynPtr < 0;
  2589. rptr = TheOtherExprTypeSynPtr < 0;
  2590. lnum = !lptr && (SyntaxStack0[exprTypeSynPtr] == tokInt ||
  2591. SyntaxStack0[exprTypeSynPtr] == tokUnsigned);
  2592. rnum = !rptr && (SyntaxStack0[TheOtherExprTypeSynPtr] == tokInt ||
  2593. SyntaxStack0[TheOtherExprTypeSynPtr] == tokUnsigned);
  2594. // both operands have arithmetic type
  2595. // (arithmetic operands have been already promoted):
  2596. if (lnum && rnum)
  2597. return;
  2598. // both operands have void type:
  2599. if (!lptr && SyntaxStack0[exprTypeSynPtr] == tokVoid &&
  2600. !rptr && SyntaxStack0[TheOtherExprTypeSynPtr] == tokVoid)
  2601. return;
  2602. // one operand is a pointer and the other is NULL constant
  2603. // ((void*)0 is also a valid null pointer constant),
  2604. // the type of the expression is that of the pointer:
  2605. if (lptr &&
  2606. ((rnum && ConstExpr[1] && truncInt(stack[ridx][1]) == 0) ||
  2607. (rptr && SyntaxStack0[-TheOtherExprTypeSynPtr] == tokVoid &&
  2608. (stack[ridx][0] == tokNumInt || stack[ridx][0] == tokNumUint) &&
  2609. truncInt(stack[ridx][1]) == 0)))
  2610. return;
  2611. if (rptr &&
  2612. ((lnum && ConstExpr[0] && truncInt(stack[lidx][1]) == 0) ||
  2613. (lptr && SyntaxStack0[-exprTypeSynPtr] == tokVoid &&
  2614. (stack[lidx][0] == tokNumInt || stack[lidx][0] == tokNumUint) &&
  2615. truncInt(stack[lidx][1]) == 0)))
  2616. {
  2617. *ExprTypeSynPtr = TheOtherExprTypeSynPtr;
  2618. return;
  2619. }
  2620. // not expecting non-pointers beyond this point
  2621. if (!(lptr && rptr))
  2622. errorOpType();
  2623. // one operand is a pointer and the other is a pointer to void
  2624. // (except (void*)0 (AKA NULL), which is different from other pointers to void),
  2625. // the type of the expression is pointer to void:
  2626. if (SyntaxStack0[-exprTypeSynPtr] == tokVoid)
  2627. return;
  2628. if (SyntaxStack0[-TheOtherExprTypeSynPtr] == tokVoid)
  2629. {
  2630. *ExprTypeSynPtr = TheOtherExprTypeSynPtr;
  2631. return;
  2632. }
  2633. // both operands are pointers to compatible types:
  2634. if (exprTypeSynPtr == TheOtherExprTypeSynPtr)
  2635. return;
  2636. exprTypeSynPtr = -exprTypeSynPtr;
  2637. TheOtherExprTypeSynPtr = -TheOtherExprTypeSynPtr;
  2638. for (;;)
  2639. {
  2640. int tok = SyntaxStack0[exprTypeSynPtr];
  2641. if (tok != SyntaxStack0[TheOtherExprTypeSynPtr])
  2642. errorOpType();
  2643. if (tok != tokIdent &&
  2644. SyntaxStack1[exprTypeSynPtr] != SyntaxStack1[TheOtherExprTypeSynPtr])
  2645. errorOpType();
  2646. c += (tok == '(') - (tok == ')') + (tok == '[') - (tok == ']');
  2647. if (!c)
  2648. {
  2649. switch (tok)
  2650. {
  2651. case tokVoid:
  2652. case tokChar: case tokSChar: case tokUChar:
  2653. case tokShort: case tokUShort:
  2654. case tokInt: case tokUnsigned:
  2655. case tokStructPtr:
  2656. return;
  2657. }
  2658. }
  2659. exprTypeSynPtr++;
  2660. TheOtherExprTypeSynPtr++;
  2661. }
  2662. }
  2663. STATIC
  2664. void shiftCountCheck(int *psr, int idx, int ExprTypeSynPtr)
  2665. {
  2666. int sr = *psr;
  2667. // can't shift by a negative count and by a count exceeding
  2668. // the number of bits in int
  2669. if ((SyntaxStack0[ExprTypeSynPtr] != tokUnsigned && sr < 0) ||
  2670. (unsigned)sr >= CHAR_BIT * sizeof(int) ||
  2671. (unsigned)sr >= 8u * SizeOfWord)
  2672. {
  2673. //error("exprval(): Invalid shift count\n");
  2674. warning("Shift count out of range\n");
  2675. // truncate the count, so the assembler doesn't get an invalid count
  2676. sr &= SizeOfWord * 8 - 1;
  2677. *psr = sr;
  2678. stack[idx][1] = sr;
  2679. }
  2680. }
  2681. STATIC
  2682. int divCheckAndCalc(int tok, int* psl, int sr, int Unsigned, int ConstExpr[2])
  2683. {
  2684. int div0 = 0;
  2685. int sl = *psl;
  2686. if (!ConstExpr[1])
  2687. return !div0;
  2688. if (Unsigned)
  2689. {
  2690. sl = (int)truncUint(sl);
  2691. sr = (int)truncUint(sr);
  2692. }
  2693. else
  2694. {
  2695. sl = truncInt(sl);
  2696. sr = truncInt(sr);
  2697. }
  2698. if (sr == 0)
  2699. {
  2700. div0 = 1;
  2701. }
  2702. else if (!ConstExpr[0])
  2703. {
  2704. return !div0;
  2705. }
  2706. else if (!Unsigned && ((sl == INT_MIN && sr == -1) || division(sl , sr) != truncInt(division(sl , sr))))
  2707. {
  2708. div0 = 1;
  2709. }
  2710. else
  2711. {
  2712. if (Unsigned)
  2713. {
  2714. if (tok == '/')
  2715. sl = (int)((unsigned)division(sl , sr));
  2716. else
  2717. sl = (int)((unsigned)modulo(sl , sr));
  2718. }
  2719. else
  2720. {
  2721. // TBD!!! C89 gives freedom in how exactly division of negative integers
  2722. // can be implemented w.r.t. rounding and w.r.t. the sign of the remainder.
  2723. // A stricter, C99-conforming implementation, non-dependent on the
  2724. // compiler used to compile Smaller C is needed.
  2725. if (tok == '/')
  2726. sl = division(sl, sr);
  2727. else
  2728. sl = modulo(sl, sr);
  2729. }
  2730. *psl = sl;
  2731. }
  2732. if (div0)
  2733. warning("Division by 0 or division overflow\n");
  2734. return !div0;
  2735. }
  2736. STATIC
  2737. void promoteType(int* ExprTypeSynPtr, int* TheOtherExprTypeSynPtr)
  2738. {
  2739. // Integer promotion to signed int or unsigned int from smaller types
  2740. // (all kinds of char and short). Promotion to unsigned int occurs
  2741. // only if the other operand (of a binary operator) is already an
  2742. // unsigned int. Effectively, this promotion to unsigned int performs
  2743. // usual arithmetic conversion for integers.
  2744. if (*ExprTypeSynPtr >= 0)
  2745. {
  2746. // chars must be promoted to ints in expressions as the very first thing
  2747. switch (SyntaxStack0[*ExprTypeSynPtr])
  2748. {
  2749. case tokChar:
  2750. case tokShort:
  2751. case tokUShort:
  2752. case tokSChar:
  2753. case tokUChar:
  2754. *ExprTypeSynPtr = SymIntSynPtr;
  2755. }
  2756. if (*TheOtherExprTypeSynPtr >= 0)
  2757. {
  2758. // ints must be converted to unsigned ints if they are used in binary
  2759. // operators whose other operand is unsigned int (except <<,>>,<<=,>>=)
  2760. if (SyntaxStack0[*ExprTypeSynPtr] == tokInt &&
  2761. SyntaxStack0[*TheOtherExprTypeSynPtr] == tokUnsigned)
  2762. *ExprTypeSynPtr = SymUintSynPtr;
  2763. }
  2764. }
  2765. }
  2766. STATIC
  2767. int GetFxnInfo(int ExprTypeSynPtr, int* MinParams, int* MaxParams, int* ReturnExprTypeSynPtr, int* FirstParamSynPtr)
  2768. {
  2769. *MaxParams = *MinParams = 0;
  2770. if (ExprTypeSynPtr < 0)
  2771. {
  2772. ExprTypeSynPtr = -ExprTypeSynPtr;
  2773. }
  2774. else
  2775. {
  2776. while (SyntaxStack0[ExprTypeSynPtr] == tokIdent || SyntaxStack0[ExprTypeSynPtr] == tokLocalOfs)
  2777. ExprTypeSynPtr++;
  2778. if (SyntaxStack0[ExprTypeSynPtr] == '*')
  2779. ExprTypeSynPtr++;
  2780. }
  2781. if (SyntaxStack0[ExprTypeSynPtr] != '(')
  2782. return 0;
  2783. // DONE: return syntax pointer to the function's return type
  2784. // Count params
  2785. ExprTypeSynPtr++;
  2786. if (FirstParamSynPtr)
  2787. *FirstParamSynPtr = ExprTypeSynPtr;
  2788. if (SyntaxStack0[ExprTypeSynPtr] == ')')
  2789. {
  2790. // "fxn()": unspecified parameters, so, there can be any number of them
  2791. *MaxParams = 32767; // INT_MAX;
  2792. *ReturnExprTypeSynPtr = ExprTypeSynPtr + 1;
  2793. return 1;
  2794. }
  2795. if (SyntaxStack0[ExprTypeSynPtr + 1] == tokVoid)
  2796. {
  2797. // "fxn(void)": 0 parameters
  2798. *ReturnExprTypeSynPtr = ExprTypeSynPtr + 3;
  2799. return 1;
  2800. }
  2801. for (;;)
  2802. {
  2803. int tok = SyntaxStack0[ExprTypeSynPtr];
  2804. if (tok == tokIdent)
  2805. {
  2806. if (SyntaxStack0[ExprTypeSynPtr + 1] != tokEllipsis)
  2807. {
  2808. ++*MinParams;
  2809. ++*MaxParams;
  2810. }
  2811. else
  2812. {
  2813. *MaxParams = 32767; // INT_MAX;
  2814. }
  2815. }
  2816. else if (tok == '(')
  2817. {
  2818. // skip parameters in parameters
  2819. int c = 1;
  2820. while (c && ExprTypeSynPtr < SyntaxStackCnt)
  2821. {
  2822. tok = SyntaxStack0[++ExprTypeSynPtr];
  2823. c += (tok == '(') - (tok == ')');
  2824. }
  2825. }
  2826. else if (tok == ')')
  2827. {
  2828. ExprTypeSynPtr++;
  2829. break;
  2830. }
  2831. ExprTypeSynPtr++;
  2832. }
  2833. // get the function's return type
  2834. *ReturnExprTypeSynPtr = ExprTypeSynPtr;
  2835. return 1;
  2836. }
  2837. STATIC
  2838. void simplifyConstExpr(int val, int isConst, int* ExprTypeSynPtr, int top, int bottom)
  2839. {
  2840. // If non-const, nothing to do.
  2841. // If const and already a number behind the scenes, nothing to do
  2842. // (val must not differ from the number!).
  2843. if (!isConst || stack[top][0] == tokNumInt || stack[top][0] == tokNumUint)
  2844. return;
  2845. // Const, but not a number yet. Reduce to a number equal val.
  2846. if (SyntaxStack0[*ExprTypeSynPtr] == tokUnsigned)
  2847. stack[top][0] = tokNumUint;
  2848. else
  2849. stack[top][0] = tokNumInt;
  2850. stack[top][1] = val;
  2851. del(bottom, top - bottom);
  2852. }
  2853. STATIC
  2854. int AllocLocal(unsigned size)
  2855. {
  2856. // Let's calculate variable's relative on-stack location
  2857. int oldOfs = CurFxnLocalOfs;
  2858. // Note: local vars are word-aligned on the stack
  2859. CurFxnLocalOfs = (int)((CurFxnLocalOfs - size) & ~(SizeOfWord - 1u));
  2860. if (CurFxnLocalOfs >= oldOfs ||
  2861. CurFxnLocalOfs != truncInt(CurFxnLocalOfs) ||
  2862. CurFxnLocalOfs < -GenMaxLocalsSize())
  2863. //error("AllocLocal(): Local variables take too much space\n");
  2864. errorVarSize();
  2865. if (CurFxnMinLocalOfs > CurFxnLocalOfs)
  2866. CurFxnMinLocalOfs = CurFxnLocalOfs;
  2867. return CurFxnLocalOfs;
  2868. }
  2869. // DONE: sizeof(type)
  2870. // DONE: "sizeof expr"
  2871. // DONE: constant expressions
  2872. // DONE: collapse constant subexpressions into constants
  2873. STATIC
  2874. int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
  2875. {
  2876. int tok;
  2877. int s;
  2878. int RightExprTypeSynPtr;
  2879. int oldIdxRight;
  2880. int oldSpRight;
  2881. int constExpr[3];
  2882. if (*idx < 0)
  2883. //error("exprval(): idx < 0\n");
  2884. errorInternal(5);
  2885. tok = stack[*idx][0];
  2886. s = stack[*idx][1];
  2887. --*idx;
  2888. oldIdxRight = *idx;
  2889. oldSpRight = sp;
  2890. switch (tok)
  2891. {
  2892. // Constants
  2893. case tokNumInt:
  2894. // return the constant's type: int
  2895. *ExprTypeSynPtr = SymIntSynPtr;
  2896. *ConstExpr = 1;
  2897. break;
  2898. case tokNumUint:
  2899. // return the constant's type: unsigned int
  2900. *ExprTypeSynPtr = SymUintSynPtr;
  2901. *ConstExpr = 1;
  2902. break;
  2903. // Identifiers
  2904. case tokIdent:
  2905. {
  2906. // DONE: support __func__
  2907. char* ident = IdentTable + s;
  2908. int synPtr, type;
  2909. {
  2910. synPtr = FindSymbol(ident);
  2911. // "Rename" static vars in function scope
  2912. if (synPtr >= 0 && synPtr + 1 < SyntaxStackCnt && SyntaxStack0[synPtr + 1] == tokIdent)
  2913. {
  2914. s = stack[*idx + 1][1] = SyntaxStack1[++synPtr];
  2915. ident = IdentTable + s;
  2916. }
  2917. }
  2918. if (synPtr < 0)
  2919. {
  2920. if ((*idx + 2 >= sp) || stack[*idx + 2][0] != ')')
  2921. error("Undeclared identifier '%s'\n", ident);
  2922. else
  2923. {
  2924. warning("Call to undeclared function '%s()'\n", ident);
  2925. // Implicitly declare "extern int ident();"
  2926. PushSyntax2(tokIdent, s);
  2927. PushSyntax('(');
  2928. PushSyntax(')');
  2929. PushSyntax(tokInt);
  2930. synPtr = FindSymbol(ident);
  2931. }
  2932. }
  2933. // DONE: this declaration is actually a type cast
  2934. if (!strncmp(IdentTable + SyntaxStack1[synPtr], "(something", sizeof "(something)" - 1 - 1))
  2935. {
  2936. int castSize;
  2937. if (SyntaxStack0[++synPtr] == tokLocalOfs) // TBD!!! is this really needed???
  2938. synPtr++;
  2939. s = exprval(idx, ExprTypeSynPtr, ConstExpr);
  2940. // can't cast void or structure/union to anything (except void)
  2941. if (*ExprTypeSynPtr >= 0 &&
  2942. (SyntaxStack0[*ExprTypeSynPtr] == tokVoid ||
  2943. SyntaxStack0[*ExprTypeSynPtr] == tokStructPtr) &&
  2944. SyntaxStack0[synPtr] != tokVoid)
  2945. errorOpType();
  2946. // can't cast to function, array or structure/union
  2947. if (SyntaxStack0[synPtr] == '(' ||
  2948. SyntaxStack0[synPtr] == '[' ||
  2949. SyntaxStack0[synPtr] == tokStructPtr)
  2950. errorOpType();
  2951. // will try to propagate constants through casts
  2952. if (!*ConstExpr &&
  2953. (stack[oldIdxRight - (oldSpRight - sp)][0] == tokNumInt ||
  2954. stack[oldIdxRight - (oldSpRight - sp)][0] == tokNumUint))
  2955. {
  2956. s = stack[oldIdxRight - (oldSpRight - sp)][1];
  2957. *ConstExpr = 1;
  2958. }
  2959. castSize = GetDeclSize(synPtr, 1); // 0 for cast to void
  2960. // insertion of tokUChar, tokSChar and tokUnaryPlus transforms
  2961. // lvalues (values formed by dereferences) into rvalues
  2962. // (by hiding the dereferences), just as casts should do
  2963. switch (castSize)
  2964. {
  2965. case 1:
  2966. // cast to unsigned char
  2967. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUChar;
  2968. s &= 0xFFu;
  2969. break;
  2970. case -1:
  2971. // cast to signed char
  2972. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokSChar;
  2973. if ((s &= 0xFFu) >= 0x80)
  2974. s -= 0x100;
  2975. break;
  2976. default:
  2977. if (castSize && castSize != SizeOfWord)
  2978. {
  2979. // cast not to void and not to word-sized type (int/unsigned/pointer/float)
  2980. if (castSize == 2)
  2981. {
  2982. // cast to unsigned short
  2983. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUShort;
  2984. s &= 0xFFFFu;
  2985. }
  2986. else
  2987. {
  2988. // cast to signed short
  2989. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokShort;
  2990. if ((s &= 0xFFFFu) >= 0x8000)
  2991. s -= 0x10000;
  2992. }
  2993. }
  2994. else // fallthrough
  2995. {
  2996. // cast to void or word-sized type (int/unsigned/pointer/float)
  2997. if (stack[oldIdxRight - (oldSpRight - sp)][0] == tokUnaryStar)
  2998. // hide the dereference
  2999. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUnaryPlus;
  3000. }
  3001. break;
  3002. }
  3003. if (*ConstExpr)
  3004. stack[oldIdxRight - (oldSpRight - sp)][1] = s;
  3005. *ExprTypeSynPtr = synPtr;
  3006. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3007. if (!*ConstExpr && stack[oldIdxRight + 1 - (oldSpRight - sp)][0] == tokIdent)
  3008. // nothing to hide, remove the cast
  3009. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  3010. switch (SyntaxStack0[synPtr])
  3011. {
  3012. case tokChar:
  3013. case tokSChar:
  3014. case tokUChar:
  3015. case tokShort:
  3016. case tokUShort:
  3017. case tokInt:
  3018. case tokUnsigned:
  3019. break;
  3020. default:
  3021. // only numeric types can be const
  3022. *ConstExpr = 0;
  3023. break;
  3024. }
  3025. break;
  3026. }
  3027. // Finally, not __func__, not enum, not cast.
  3028. type = SymType(synPtr);
  3029. if (type == SymLocalVar || type == SymLocalArr)
  3030. {
  3031. // replace local variables/arrays with their local addresses
  3032. // (global variables/arrays' addresses are their names)
  3033. stack[*idx + 1][0] = tokLocalOfs;
  3034. stack[*idx + 1][1] = SyntaxStack1[synPtr + 1];
  3035. }
  3036. if (type == SymLocalVar || type == SymGlobalVar)
  3037. {
  3038. // add implicit dereferences for local/global variables
  3039. ins2(*idx + 2, tokUnaryStar, GetDeclSize(synPtr, 1));
  3040. }
  3041. // return the identifier's type
  3042. while (SyntaxStack0[synPtr] == tokIdent || SyntaxStack0[synPtr] == tokLocalOfs)
  3043. synPtr++;
  3044. *ExprTypeSynPtr = synPtr;
  3045. }
  3046. *ConstExpr = 0;
  3047. break;
  3048. // sizeof operator
  3049. case tokSizeof:
  3050. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3051. s = GetDeclSize(*ExprTypeSynPtr, 0);
  3052. if (s == 0)
  3053. error("sizeof of incomplete type\n");
  3054. // replace sizeof with its numeric value
  3055. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokNumUint;
  3056. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = s;
  3057. // remove the sizeof's subexpression
  3058. del(*idx + 1, oldIdxRight - (oldSpRight - sp) - *idx);
  3059. *ExprTypeSynPtr = SymUintSynPtr;
  3060. *ConstExpr = 1;
  3061. break;
  3062. // Address unary operator
  3063. case tokUnaryAnd:
  3064. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3065. if (*ExprTypeSynPtr >= 0 &&
  3066. (SyntaxStack0[*ExprTypeSynPtr] == '[' || SyntaxStack0[*ExprTypeSynPtr] == '('))
  3067. {
  3068. // convert an array into a pointer to the array,
  3069. // convert a function into a pointer to the function,
  3070. // remove the reference
  3071. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  3072. }
  3073. else if (*ExprTypeSynPtr >= 0 &&
  3074. stack[oldIdxRight - (oldSpRight - sp)][0] == tokUnaryStar)
  3075. {
  3076. // it's an lvalue (with implicit or explicit dereference),
  3077. // convert it into its address by
  3078. // collapsing/removing the reference and the dereference
  3079. del(oldIdxRight - (oldSpRight - sp), 2);
  3080. }
  3081. else
  3082. //error("exprval(): lvalue expected after '&'\n");
  3083. errorNotLvalue();
  3084. // we cannot insert another '*' into the type to make it a pointer
  3085. // to an array/function/etc, so make the index into the type negative
  3086. *ExprTypeSynPtr = -*ExprTypeSynPtr;
  3087. *ConstExpr = 0;
  3088. break;
  3089. // Indirection unary operator
  3090. case tokUnaryStar:
  3091. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3092. if (*ExprTypeSynPtr < 0 || SyntaxStack0[*ExprTypeSynPtr] == '*')
  3093. {
  3094. // type is a pointer to something,
  3095. // transform it into that something
  3096. if (*ExprTypeSynPtr < 0)
  3097. *ExprTypeSynPtr = -*ExprTypeSynPtr;
  3098. else
  3099. ++*ExprTypeSynPtr;
  3100. nonVoidTypeCheck(*ExprTypeSynPtr);
  3101. if (SyntaxStack0[*ExprTypeSynPtr] == tokStructPtr && !GetDeclSize(*ExprTypeSynPtr, 0))
  3102. // incomplete structure/union type
  3103. errorOpType();
  3104. // remove the dereference if that something is an array or a function
  3105. if (SyntaxStack0[*ExprTypeSynPtr] == '[' ||
  3106. SyntaxStack0[*ExprTypeSynPtr] == '(')
  3107. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  3108. // else attach dereference size in bytes
  3109. else
  3110. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = GetDeclSize(*ExprTypeSynPtr, 1);
  3111. }
  3112. else if (SyntaxStack0[*ExprTypeSynPtr] == '[')
  3113. {
  3114. // type is an array,
  3115. // transform it into the array's first element
  3116. // (a subarray, if type is a multidimensional array)
  3117. (*ExprTypeSynPtr) += 3;
  3118. // remove the dereference if that element is an array
  3119. if (SyntaxStack0[*ExprTypeSynPtr] == '[')
  3120. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  3121. // else attach dereference size in bytes
  3122. else
  3123. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = GetDeclSize(*ExprTypeSynPtr, 1);
  3124. }
  3125. else
  3126. //error("exprval(): pointer/array expected after '*' / before '[]'\n");
  3127. errorOpType();
  3128. *ConstExpr = 0;
  3129. break;
  3130. // Additive binary operators
  3131. case '+':
  3132. case '-':
  3133. // WRONGISH: DONE: replace prefix ++/-- with +=1/-=1
  3134. // WRONG: DONE: replace postfix ++/-- with (+=1)-1/(-=1)+1
  3135. {
  3136. int ptrmask;
  3137. int oldIdxLeft, oldSpLeft;
  3138. int sl, sr;
  3139. int incSize;
  3140. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  3141. oldIdxLeft = *idx;
  3142. oldSpLeft = sp;
  3143. sl = exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  3144. // Decay arrays to pointers to their first elements
  3145. // and ensure that the pointers are suitable for pointer arithmetic
  3146. // (not pointers to functions, sizes of pointees are known and non-zero)
  3147. decayArray(&RightExprTypeSynPtr, 1);
  3148. decayArray(ExprTypeSynPtr, 1);
  3149. // Bar void and struct/union
  3150. scalarTypeCheck(RightExprTypeSynPtr);
  3151. scalarTypeCheck(*ExprTypeSynPtr);
  3152. ptrmask = isAnyPtr(RightExprTypeSynPtr) + isAnyPtr(*ExprTypeSynPtr) * 2;
  3153. // DONE: index/subscript scaling
  3154. if (ptrmask == 1 && tok == '+') // pointer in right-hand expression
  3155. {
  3156. incSize = GetDeclSize(derefAnyPtr(RightExprTypeSynPtr), 0);
  3157. if (constExpr[0]) // integer constant in left-hand expression
  3158. {
  3159. s = (int)((unsigned)sl * incSize);
  3160. stack[oldIdxLeft - (oldSpLeft - sp)][1] = s;
  3161. // optimize a little if possible
  3162. {
  3163. int i = oldIdxRight - (oldSpRight - sp);
  3164. // Skip any type cast markers
  3165. while (stack[i][0] == tokUnaryPlus || stack[i][0] == '+')
  3166. i--;
  3167. // See if the pointer is an integer constant or a local variable offset
  3168. // and if it is, adjust it here instead of generating code for
  3169. // addition/subtraction
  3170. if (stack[i][0] == tokNumInt || stack[i][0] == tokNumUint || stack[i][0] == tokLocalOfs)
  3171. {
  3172. s = (int)((unsigned)stack[i][1] + s);
  3173. stack[i][1] = s; // TBD!!! need extra truncation?
  3174. del(oldIdxLeft - (oldSpLeft - sp), 1);
  3175. del(oldIdxRight - (oldSpRight - sp) + 1, 1);
  3176. }
  3177. }
  3178. }
  3179. else if (incSize != 1)
  3180. {
  3181. ins2(oldIdxLeft + 1 - (oldSpLeft - sp), tokNumInt, incSize);
  3182. ins(oldIdxLeft + 1 - (oldSpLeft - sp), '*');
  3183. }
  3184. *ExprTypeSynPtr = RightExprTypeSynPtr;
  3185. }
  3186. else if (ptrmask == 2) // pointer in left-hand expression
  3187. {
  3188. incSize = GetDeclSize(derefAnyPtr(*ExprTypeSynPtr), 0);
  3189. if (constExpr[1]) // integer constant in right-hand expression
  3190. {
  3191. s = (int)((unsigned)sr * incSize);
  3192. stack[oldIdxRight - (oldSpRight - sp)][1] = s;
  3193. // optimize a little if possible
  3194. {
  3195. int i = oldIdxLeft - (oldSpLeft - sp);
  3196. // Skip any type cast markers
  3197. while (stack[i][0] == tokUnaryPlus || stack[i][0] == '+')
  3198. i--;
  3199. // See if the pointer is an integer constant or a local variable offset
  3200. // and if it is, adjust it here instead of generating code for
  3201. // addition/subtraction
  3202. if (stack[i][0] == tokNumInt || stack[i][0] == tokNumUint || stack[i][0] == tokLocalOfs)
  3203. {
  3204. if (tok == '-')
  3205. s = (int)~(s - 1u);
  3206. s = (int)((unsigned)stack[i][1] + s);
  3207. stack[i][1] = s; // TBD!!! need extra truncation?
  3208. del(oldIdxRight - (oldSpRight - sp), 2);
  3209. }
  3210. }
  3211. }
  3212. else if (incSize != 1)
  3213. {
  3214. ins2(oldIdxRight + 1 - (oldSpRight - sp), tokNumInt, incSize);
  3215. ins(oldIdxRight + 1 - (oldSpRight - sp), '*');
  3216. }
  3217. }
  3218. else if (ptrmask == 3 && tok == '-') // pointers in both expressions
  3219. {
  3220. incSize = GetDeclSize(derefAnyPtr(*ExprTypeSynPtr), 0);
  3221. // TBD!!! "ptr1-ptr2": better pointer type compatibility test needed, like compatCheck()?
  3222. if (incSize != GetDeclSize(derefAnyPtr(RightExprTypeSynPtr), 0))
  3223. //error("exprval(): incompatible pointers\n");
  3224. errorOpType();
  3225. if (incSize != 1)
  3226. {
  3227. ins2(oldIdxRight + 2 - (oldSpRight - sp), tokNumInt, incSize);
  3228. ins(oldIdxRight + 2 - (oldSpRight - sp), '/');
  3229. }
  3230. *ExprTypeSynPtr = SymIntSynPtr;
  3231. }
  3232. else if (ptrmask)
  3233. //error("exprval(): invalid combination of operands for '+' or '-'\n");
  3234. errorOpType();
  3235. // Promote the result from char to int (and from int to unsigned) if necessary
  3236. promoteType(ExprTypeSynPtr, &RightExprTypeSynPtr);
  3237. *ConstExpr = constExpr[0] && constExpr[1];
  3238. {
  3239. if (tok == '+')
  3240. s = (int)((unsigned)sl + sr);
  3241. else
  3242. s = (int)((unsigned)sl - sr);
  3243. }
  3244. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3245. }
  3246. break;
  3247. // Prefix/postfix increment/decrement unary operators
  3248. case tokInc:
  3249. case tokDec:
  3250. case tokPostInc:
  3251. case tokPostDec:
  3252. {
  3253. int incSize = 1;
  3254. int inc = tok == tokInc || tok == tokPostInc;
  3255. int post = tok == tokPostInc || tok == tokPostDec;
  3256. int opSize;
  3257. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3258. lvalueCheck(*ExprTypeSynPtr, oldIdxRight - (oldSpRight - sp));
  3259. // if it's a pointer, ensure that it's suitable for pointer arithmetic
  3260. // (not pointer to function, pointee size is known and non-zero)
  3261. decayArray(ExprTypeSynPtr, 1); // no actual decay here, just a type check
  3262. // Bar void and struct/union
  3263. scalarTypeCheck(*ExprTypeSynPtr);
  3264. // "remove" the lvalue dereference as we don't need
  3265. // to read the value while forgetting its location.
  3266. // We need to keep the lvalue location.
  3267. // Remember the operand size.
  3268. opSize = stack[oldIdxRight - (oldSpRight - sp)][1];
  3269. del(oldIdxRight - (oldSpRight - sp), 1);
  3270. if (isAnyPtr(*ExprTypeSynPtr))
  3271. incSize = GetDeclSize(derefAnyPtr(*ExprTypeSynPtr), 0);
  3272. if (incSize == 1)
  3273. {
  3274. // store the operand size in the operator
  3275. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = opSize;
  3276. }
  3277. else
  3278. {
  3279. // replace ++/-- with "postfix" +=/-= incSize when incSize != 1
  3280. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] =
  3281. inc ? (post ? tokPostAdd : tokAssignAdd) :
  3282. (post ? tokPostSub : tokAssignSub);
  3283. // store the operand size in the operator
  3284. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = opSize;
  3285. ins2(oldIdxRight + 1 - (oldSpRight - sp), tokNumInt, incSize);
  3286. }
  3287. *ConstExpr = 0;
  3288. }
  3289. break;
  3290. // Simple assignment binary operator
  3291. case '=':
  3292. {
  3293. int oldIdxLeft, oldSpLeft;
  3294. int opSize;
  3295. int structs;
  3296. exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  3297. oldIdxLeft = *idx;
  3298. oldSpLeft = sp;
  3299. exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  3300. lvalueCheck(*ExprTypeSynPtr, oldIdxLeft - (oldSpLeft - sp));
  3301. nonVoidTypeCheck(RightExprTypeSynPtr);
  3302. nonVoidTypeCheck(*ExprTypeSynPtr);
  3303. structs = (*ExprTypeSynPtr >= 0 && SyntaxStack0[*ExprTypeSynPtr] == tokStructPtr) * 2 +
  3304. (RightExprTypeSynPtr >= 0 && SyntaxStack0[RightExprTypeSynPtr] == tokStructPtr);
  3305. if (structs)
  3306. {
  3307. int sz;
  3308. if (structs != 3 ||
  3309. SyntaxStack1[RightExprTypeSynPtr] != SyntaxStack1[*ExprTypeSynPtr])
  3310. errorOpType();
  3311. // TBD??? (a = b) should be an rvalue and so &(a = b) and (&(a = b))->c shouldn't be
  3312. // allowed, while (a = b).c should be allowed.
  3313. // transform "*psleft = *psright" into "*fxn(sizeof *psright, psright, psleft)"
  3314. /*
  3315. if (stack[oldIdxLeft - (oldSpLeft - sp)][0] != tokUnaryStar ||
  3316. stack[oldIdxRight - (oldSpRight - sp)][0] != tokUnaryStar)
  3317. errorInternal(18);
  3318. */
  3319. stack[oldIdxLeft - (oldSpLeft - sp)][0] = ','; // replace '*' with ','
  3320. stack[oldIdxRight - (oldSpRight - sp)][0] = ','; // replace '*' with ','
  3321. sz = GetDeclSize(RightExprTypeSynPtr, 0);
  3322. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokNumUint; // replace '=' with "sizeof *psright"
  3323. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = sz;
  3324. ins(oldIdxRight + 2 - (oldSpRight - sp), ',');
  3325. if (!StructCpyLabel)
  3326. StructCpyLabel = LabelCnt++;
  3327. ins2(oldIdxRight + 2 - (oldSpRight - sp), tokIdent, AddNumericIdent(StructCpyLabel));
  3328. ins2(oldIdxRight + 2 - (oldSpRight - sp), ')', SizeOfWord * 3);
  3329. ins2(oldIdxRight + 2 - (oldSpRight - sp), tokUnaryStar, 0); // use 0 deref size to drop meaningless dereferences
  3330. ins2(*idx + 1, '(', SizeOfWord * 3);
  3331. }
  3332. else
  3333. {
  3334. // "remove" the lvalue dereference as we don't need
  3335. // to read the value while forgetting its location.
  3336. // We need to keep the lvalue location.
  3337. // Remember the operand size.
  3338. opSize = stack[oldIdxLeft - (oldSpLeft - sp)][1];
  3339. // store the operand size in the operator
  3340. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = opSize;
  3341. del(oldIdxLeft - (oldSpLeft - sp), 1);
  3342. }
  3343. *ConstExpr = 0;
  3344. }
  3345. break;
  3346. // DONE: other assignment operators
  3347. // Arithmetic and bitwise unary operators
  3348. case '~':
  3349. case tokUnaryPlus:
  3350. case tokUnaryMinus:
  3351. s = exprval(idx, ExprTypeSynPtr, ConstExpr);
  3352. numericTypeCheck(*ExprTypeSynPtr);
  3353. promoteType(ExprTypeSynPtr, ExprTypeSynPtr);
  3354. switch (tok)
  3355. {
  3356. case '~':
  3357. s = ~s;
  3358. break;
  3359. case tokUnaryPlus:
  3360. break;
  3361. case tokUnaryMinus:
  3362. {
  3363. s = (int)~(s - 1u);
  3364. }
  3365. break;
  3366. }
  3367. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3368. break;
  3369. // Arithmetic and bitwise binary operators
  3370. case '*':
  3371. case '/':
  3372. case '%':
  3373. case tokLShift:
  3374. case tokRShift:
  3375. case '&':
  3376. case '^':
  3377. case '|':
  3378. {
  3379. int sr, sl;
  3380. int Unsigned;
  3381. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  3382. sl = exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  3383. numericTypeCheck(RightExprTypeSynPtr);
  3384. numericTypeCheck(*ExprTypeSynPtr);
  3385. *ConstExpr = constExpr[0] && constExpr[1];
  3386. Unsigned = SyntaxStack0[*ExprTypeSynPtr] == tokUnsigned || SyntaxStack0[RightExprTypeSynPtr] == tokUnsigned;
  3387. {
  3388. switch (tok)
  3389. {
  3390. // DONE: check for division overflows
  3391. case '/':
  3392. case '%':
  3393. *ConstExpr &= divCheckAndCalc(tok, &sl, sr, Unsigned, constExpr);
  3394. if (Unsigned)
  3395. {
  3396. if (tok == '/')
  3397. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUDiv;
  3398. else
  3399. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUMod;
  3400. }
  3401. break;
  3402. case '*':
  3403. sl = (int)((unsigned)sl * sr);
  3404. break;
  3405. case tokLShift:
  3406. case tokRShift:
  3407. if (constExpr[1])
  3408. {
  3409. if (SyntaxStack0[RightExprTypeSynPtr] != tokUnsigned)
  3410. sr = truncInt(sr);
  3411. else
  3412. sr = (int)truncUint(sr);
  3413. shiftCountCheck(&sr, oldIdxRight - (oldSpRight - sp), RightExprTypeSynPtr);
  3414. }
  3415. if (*ConstExpr)
  3416. {
  3417. if (tok == tokLShift)
  3418. {
  3419. // left shift is the same for signed and unsigned ints
  3420. sl = (int)((unsigned)sl << sr);
  3421. }
  3422. else
  3423. {
  3424. if (SyntaxStack0[*ExprTypeSynPtr] == tokUnsigned)
  3425. {
  3426. // right shift for unsigned ints
  3427. sl = (int)(truncUint(sl) >> sr);
  3428. }
  3429. else if (sr)
  3430. {
  3431. // right shift for signed ints is arithmetic, sign-bit-preserving
  3432. // don't depend on the compiler's implementation, do it "manually"
  3433. sl = truncInt(sl);
  3434. sl = (int)((truncUint(sl) >> sr) |
  3435. ((sl < 0) * (~0u << (8 * SizeOfWord - sr))));
  3436. }
  3437. }
  3438. }
  3439. if (SyntaxStack0[*ExprTypeSynPtr] == tokUnsigned && tok == tokRShift)
  3440. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokURShift;
  3441. // ignore RightExprTypeSynPtr for the purpose of promotion/conversion of the result of <</>>
  3442. RightExprTypeSynPtr = SymIntSynPtr;
  3443. break;
  3444. case '&': sl &= sr; break;
  3445. case '^': sl ^= sr; break;
  3446. case '|': sl |= sr; break;
  3447. }
  3448. s = sl;
  3449. }
  3450. promoteType(ExprTypeSynPtr, &RightExprTypeSynPtr);
  3451. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3452. }
  3453. break;
  3454. // Relational and equality binary operators
  3455. // DONE: add (sub)tokens for unsigned >, >=, <, <= for pointers
  3456. case '<':
  3457. case '>':
  3458. case tokLEQ:
  3459. case tokGEQ:
  3460. case tokEQ:
  3461. case tokNEQ:
  3462. {
  3463. int ptrmask;
  3464. int sr, sl;
  3465. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  3466. sl = exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  3467. // Bar void and struct/union
  3468. scalarTypeCheck(RightExprTypeSynPtr);
  3469. scalarTypeCheck(*ExprTypeSynPtr);
  3470. ptrmask = isAnyPtr(RightExprTypeSynPtr) + isAnyPtr(*ExprTypeSynPtr) * 2;
  3471. // TBD??? stricter type checks???
  3472. if (tok != tokEQ && tok != tokNEQ)
  3473. {
  3474. // Disallow >, <, >=, <= between a pointer and a number
  3475. if (ptrmask == 1 || ptrmask == 2)
  3476. //error("exprval(): Invalid/unsupported combination of compared operands\n");
  3477. errorOpType();
  3478. // Disallow >, <, >=, <= with pointers to functions
  3479. if (((ptrmask & 1) && SyntaxStack0[derefAnyPtr(RightExprTypeSynPtr)] == '(') ||
  3480. ((ptrmask & 2) && SyntaxStack0[derefAnyPtr(*ExprTypeSynPtr)] == '('))
  3481. errorOpType();
  3482. }
  3483. else
  3484. {
  3485. // Disallow == and != between a pointer and a number other than constant 0 (AKA NULL)
  3486. if ((ptrmask == 1 && !(constExpr[0] && !truncInt(sl))) ||
  3487. (ptrmask == 2 && !(constExpr[1] && !truncInt(sr))))
  3488. errorOpType();
  3489. }
  3490. *ConstExpr = constExpr[0] && constExpr[1];
  3491. {
  3492. int Unsigned = isUint(*ExprTypeSynPtr) || isUint(RightExprTypeSynPtr);
  3493. if (*ConstExpr)
  3494. {
  3495. if (!Unsigned)
  3496. {
  3497. sl = truncInt(sl);
  3498. sr = truncInt(sr);
  3499. switch (tok)
  3500. {
  3501. case '<': sl = sl < sr; break;
  3502. case '>': sl = sl > sr; break;
  3503. case tokLEQ: sl = sl <= sr; break;
  3504. case tokGEQ: sl = sl >= sr; break;
  3505. case tokEQ: sl = sl == sr; break;
  3506. case tokNEQ: sl = sl != sr; break;
  3507. }
  3508. }
  3509. else
  3510. {
  3511. sl = (int)truncUint(sl);
  3512. sr = (int)truncUint(sr);
  3513. switch (tok)
  3514. {
  3515. case '<': sl = (unsigned)sl < (unsigned)sr; break;
  3516. case '>': sl = (unsigned)sl > (unsigned)sr; break;
  3517. case tokLEQ: sl = (unsigned)sl <= (unsigned)sr; break;
  3518. case tokGEQ: sl = (unsigned)sl >= (unsigned)sr; break;
  3519. case tokEQ: sl = sl == sr; break;
  3520. case tokNEQ: sl = sl != sr; break;
  3521. }
  3522. }
  3523. }
  3524. if (ptrmask || Unsigned)
  3525. {
  3526. // Pointer comparison should be unsigned
  3527. int t = tok;
  3528. switch (tok)
  3529. {
  3530. case '<': t = tokULess; break;
  3531. case '>': t = tokUGreater; break;
  3532. case tokLEQ: t = tokULEQ; break;
  3533. case tokGEQ: t = tokUGEQ; break;
  3534. }
  3535. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = t;
  3536. }
  3537. }
  3538. s = sl;
  3539. *ExprTypeSynPtr = SymIntSynPtr;
  3540. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3541. }
  3542. break;
  3543. // implicit pseudo-conversion to _Bool of operands of && and ||
  3544. case tok_Bool:
  3545. s = exprval(idx, ExprTypeSynPtr, ConstExpr);
  3546. // Bar void and struct/union
  3547. scalarTypeCheck(*ExprTypeSynPtr);
  3548. {
  3549. s = truncInt(s) != 0;
  3550. }
  3551. *ExprTypeSynPtr = SymIntSynPtr;
  3552. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3553. break;
  3554. // Logical binary operators
  3555. case tokLogAnd: // DONE: short-circuit
  3556. case tokLogOr: // DONE: short-circuit
  3557. {
  3558. int sr, sl;
  3559. // DONE: think of pushing a special short-circuit (jump-to) token
  3560. // to skip the rhs operand evaluation in && and ||
  3561. // DONE: add implicit "casts to _Bool" of && and || operands,
  3562. // do the same for control statements of if() while() and for(;;).
  3563. int sc = LabelCnt++;
  3564. // tag the logical operator as a numbered short-circuit jump target
  3565. stack[*idx + 1][1] = sc;
  3566. // insert "!= 0" for right-hand operand
  3567. switch (stack[*idx][0])
  3568. {
  3569. case '<':
  3570. case tokULess:
  3571. case '>':
  3572. case tokUGreater:
  3573. case tokLEQ:
  3574. case tokULEQ:
  3575. case tokGEQ:
  3576. case tokUGEQ:
  3577. case tokEQ:
  3578. case tokNEQ:
  3579. break;
  3580. default:
  3581. ins(++*idx, tok_Bool);
  3582. break;
  3583. }
  3584. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  3585. // insert a reference to the short-circuit jump target
  3586. if (tok == tokLogAnd)
  3587. ins2(++*idx, tokShortCirc, sc);
  3588. else
  3589. ins2(++*idx, tokShortCirc, -sc);
  3590. // insert "!= 0" for left-hand operand
  3591. switch (stack[*idx - 1][0])
  3592. {
  3593. case '<':
  3594. case tokULess:
  3595. case '>':
  3596. case tokUGreater:
  3597. case tokLEQ:
  3598. case tokULEQ:
  3599. case tokGEQ:
  3600. case tokUGEQ:
  3601. case tokEQ:
  3602. case tokNEQ:
  3603. --*idx;
  3604. break;
  3605. default:
  3606. ins(*idx, tok_Bool);
  3607. break;
  3608. }
  3609. sl = exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  3610. if (tok == tokLogAnd)
  3611. s = sl && sr;
  3612. else
  3613. s = sl || sr;
  3614. *ExprTypeSynPtr = SymIntSynPtr;
  3615. *ConstExpr = constExpr[0] && constExpr[1];
  3616. if (constExpr[0])
  3617. {
  3618. if (tok == tokLogAnd)
  3619. {
  3620. if (!sl)
  3621. *ConstExpr = 1, s = 0;
  3622. // TBD??? else can drop LHS expression
  3623. }
  3624. else
  3625. {
  3626. if (sl)
  3627. *ConstExpr = s = 1;
  3628. // TBD??? else can drop LHS expression
  3629. }
  3630. }
  3631. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3632. }
  3633. break;
  3634. // Function call
  3635. case ')':
  3636. {
  3637. int tmpSynPtr, c;
  3638. int minParams, maxParams;
  3639. int firstParamSynPtr;
  3640. int oldIdx, oldSp;
  3641. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3642. if (!GetFxnInfo(*ExprTypeSynPtr, &minParams, &maxParams, ExprTypeSynPtr, &firstParamSynPtr))
  3643. //error("exprval(): function or function pointer expected\n");
  3644. errorOpType();
  3645. // DONE: validate the number of function arguments
  3646. // DONE: warnings on int<->pointer substitution in params/args
  3647. // evaluate function arguments
  3648. c = 0;
  3649. while (stack[*idx][0] != '(')
  3650. {
  3651. int ptrmask;
  3652. // add a comma after the first (last to be pushed) argument,
  3653. // so all arguments can be pushed whenever a comma is encountered
  3654. if (!c)
  3655. ins(*idx + 1, ',');
  3656. oldIdx = *idx;
  3657. oldSp = sp;
  3658. (void)oldIdx;
  3659. (void)oldSp;
  3660. exprval(idx, &tmpSynPtr, ConstExpr);
  3661. //error("exprval(): function arguments cannot be of type 'void'\n");
  3662. if (c >= maxParams)
  3663. error("Too many function arguments\n");
  3664. // Find the type of the formal parameter in the function declaration
  3665. if (c < minParams)
  3666. {
  3667. int t;
  3668. while ((t = SyntaxStack0[firstParamSynPtr]) != tokIdent)
  3669. {
  3670. if (t == '(')
  3671. {
  3672. // skip parameters in parameters
  3673. int c = 1;
  3674. while (c)
  3675. {
  3676. t = SyntaxStack0[++firstParamSynPtr];
  3677. c += (t == '(') - (t == ')');
  3678. }
  3679. }
  3680. firstParamSynPtr++;
  3681. }
  3682. firstParamSynPtr++;
  3683. }
  3684. else
  3685. {
  3686. firstParamSynPtr = SymVoidSynPtr;
  3687. }
  3688. ptrmask = isAnyPtr(firstParamSynPtr) * 2 + isAnyPtr(tmpSynPtr);
  3689. (void)ptrmask;
  3690. // Bar void and struct/union
  3691. scalarTypeCheck(tmpSynPtr);
  3692. // if there's a formal parameter for this argument, check the types
  3693. if (c < minParams)
  3694. {
  3695. }
  3696. c++;
  3697. if (stack[*idx][0] == ',')
  3698. --*idx;
  3699. }
  3700. --*idx;
  3701. if (c < minParams)
  3702. error("Too few function arguments\n");
  3703. // store the cumulative argument size in the function call operators
  3704. {
  3705. int i = oldIdxRight + 1 - (oldSpRight - sp);
  3706. stack[1 + *idx][1] = stack[i][1] = c * SizeOfWord;
  3707. }
  3708. *ConstExpr = 0;
  3709. }
  3710. break;
  3711. // Binary comma operator
  3712. case tokComma:
  3713. {
  3714. int oldIdxLeft, oldSpLeft;
  3715. int retStruct = 0;
  3716. s = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  3717. oldIdxLeft = *idx;
  3718. oldSpLeft = sp;
  3719. // Signify uselessness of the result of the left operand's value
  3720. ins(*idx + 1, tokVoid);
  3721. exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  3722. *ConstExpr = constExpr[0] && constExpr[1];
  3723. *ExprTypeSynPtr = RightExprTypeSynPtr;
  3724. retStruct = RightExprTypeSynPtr >= 0 && SyntaxStack0[RightExprTypeSynPtr] == tokStructPtr;
  3725. if (*ConstExpr)
  3726. {
  3727. // both subexprs are const, remove both and comma
  3728. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3729. }
  3730. else if (constExpr[0])
  3731. {
  3732. // only left subexpr is const, remove it
  3733. del(*idx + 1, oldIdxLeft - (oldSpLeft - sp) - *idx);
  3734. if (!retStruct)
  3735. // Ensure non-lvalue-ness of the result by changing comma to unary plus
  3736. // and thus hiding dereference, if any
  3737. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUnaryPlus;
  3738. else
  3739. // However, (something, struct).member should still be allowed,
  3740. // so, comma needs to produce lvalue
  3741. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  3742. }
  3743. else if (retStruct)
  3744. {
  3745. // However, (something, struct).member should still be allowed,
  3746. // so, comma needs to produce lvalue. Swap comma and structure dereference.
  3747. int i = oldIdxRight + 1 - (oldSpRight - sp);
  3748. stack[i][0] = tokUnaryStar;
  3749. stack[i][1] = stack[i - 1][1];
  3750. stack[i - 1][0] = tokComma;
  3751. }
  3752. }
  3753. break;
  3754. // Compound assignment operators
  3755. case tokAssignMul: case tokAssignDiv: case tokAssignMod:
  3756. case tokAssignAdd: case tokAssignSub:
  3757. case tokAssignLSh: case tokAssignRSh:
  3758. case tokAssignAnd: case tokAssignXor: case tokAssignOr:
  3759. {
  3760. int ptrmask;
  3761. int oldIdxLeft, oldSpLeft;
  3762. int incSize;
  3763. int opSize;
  3764. int Unsigned;
  3765. int sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  3766. oldIdxLeft = *idx;
  3767. oldSpLeft = sp;
  3768. exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  3769. lvalueCheck(*ExprTypeSynPtr, oldIdxLeft - (oldSpLeft - sp));
  3770. // if it's a pointer, ensure that it's suitable for pointer arithmetic
  3771. // (not pointer to function, pointee size is known and non-zero)
  3772. decayArray(ExprTypeSynPtr, 1); // no actual decay here, just a type check
  3773. // Bar void and struct/union
  3774. scalarTypeCheck(RightExprTypeSynPtr);
  3775. scalarTypeCheck(*ExprTypeSynPtr);
  3776. // "remove" the lvalue dereference as we don't need
  3777. // to read the value while forgetting its location.
  3778. // We need to keep the lvalue location.
  3779. // Remember the operand size.
  3780. opSize = stack[oldIdxLeft - (oldSpLeft - sp)][1];
  3781. // store the operand size in the operator
  3782. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = opSize;
  3783. del(oldIdxLeft - (oldSpLeft - sp), 1);
  3784. ptrmask = isAnyPtr(*ExprTypeSynPtr) * 2 + isAnyPtr(RightExprTypeSynPtr);
  3785. Unsigned = isUint(*ExprTypeSynPtr) * 2 + isUint(RightExprTypeSynPtr);
  3786. if (tok != tokAssignAdd && tok != tokAssignSub)
  3787. {
  3788. if (ptrmask)
  3789. //error("exprval(): invalid combination of operands for %s\n", GetTokenName(tok));
  3790. errorOpType();
  3791. }
  3792. else
  3793. {
  3794. // No pointer to the right of += and -=
  3795. if (ptrmask & 1)
  3796. //error("exprval(): invalid combination of operands for %s\n", GetTokenName(tok));
  3797. errorOpType();
  3798. }
  3799. if (tok == tokAssignLSh || tok == tokAssignRSh)
  3800. {
  3801. if (constExpr[1])
  3802. {
  3803. if (Unsigned & 1)
  3804. sr = (int)truncUint(sr);
  3805. else
  3806. sr = truncInt(sr);
  3807. shiftCountCheck(&sr, oldIdxRight - (oldSpRight - sp), RightExprTypeSynPtr);
  3808. }
  3809. }
  3810. if (tok == tokAssignDiv || tok == tokAssignMod)
  3811. {
  3812. int t, sl = 0;
  3813. if (tok == tokAssignDiv)
  3814. t = '/';
  3815. else
  3816. t = '%';
  3817. divCheckAndCalc(t, &sl, sr, 1, constExpr);
  3818. }
  3819. // TBD??? replace +=/-= with prefix ++/-- if incSize == 1
  3820. if (ptrmask == 2) // left-hand expression
  3821. {
  3822. incSize = GetDeclSize(derefAnyPtr(*ExprTypeSynPtr), 0);
  3823. if (constExpr[1])
  3824. {
  3825. int t = (int)(stack[oldIdxRight - (oldSpRight - sp)][1] * (unsigned)incSize);
  3826. stack[oldIdxRight - (oldSpRight - sp)][1] = t;
  3827. }
  3828. else if (incSize != 1)
  3829. {
  3830. ins2(oldIdxRight + 1 - (oldSpRight - sp), tokNumInt, incSize);
  3831. ins(oldIdxRight + 1 - (oldSpRight - sp), '*');
  3832. }
  3833. }
  3834. else if (Unsigned)
  3835. {
  3836. int t = tok;
  3837. switch (tok)
  3838. {
  3839. case tokAssignDiv: t = tokAssignUDiv; break;
  3840. case tokAssignMod: t = tokAssignUMod; break;
  3841. case tokAssignRSh:
  3842. if (Unsigned & 2)
  3843. t = tokAssignURSh;
  3844. break;
  3845. }
  3846. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = t;
  3847. }
  3848. *ConstExpr = 0;
  3849. }
  3850. break;
  3851. // Ternary/conditional operator
  3852. case '?':
  3853. {
  3854. int oldIdxLeft, oldSpLeft;
  3855. int oldIdxCond, oldSpCond;
  3856. int sr, sl, smid;
  3857. int condTypeSynPtr;
  3858. int sc = (LabelCnt += 2) - 2;
  3859. int structs;
  3860. // "exprL ? exprMID : exprR" appears on the stack as
  3861. // "exprL exprR exprMID ?"
  3862. // label at the end of ?:
  3863. stack[*idx + 1][0] = tokLogAnd; // piggyback on && for CG (ugly, but simple)
  3864. stack[*idx + 1][1] = sc + 1;
  3865. smid = exprval(idx, ExprTypeSynPtr, &constExpr[1]);
  3866. oldIdxLeft = *idx;
  3867. oldSpLeft = sp;
  3868. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[2]);
  3869. decayArray(&RightExprTypeSynPtr, 0);
  3870. decayArray(ExprTypeSynPtr, 0);
  3871. promoteType(&RightExprTypeSynPtr, ExprTypeSynPtr);
  3872. promoteType(ExprTypeSynPtr, &RightExprTypeSynPtr);
  3873. structs = (*ExprTypeSynPtr >= 0 && SyntaxStack0[*ExprTypeSynPtr] == tokStructPtr) * 2 +
  3874. (RightExprTypeSynPtr >= 0 && SyntaxStack0[RightExprTypeSynPtr] == tokStructPtr);
  3875. // TBD??? move struct/union-related checks into compatChecks()
  3876. if (structs)
  3877. {
  3878. if (structs != 3 ||
  3879. SyntaxStack1[RightExprTypeSynPtr] != SyntaxStack1[*ExprTypeSynPtr])
  3880. errorOpType();
  3881. // transform "cond ? a : b" into "*(cond ? &a : &b)"
  3882. /*
  3883. if (stack[oldIdxLeft - (oldSpLeft - sp)][0] != tokUnaryStar ||
  3884. stack[oldIdxRight - (oldSpRight - sp)][0] != tokUnaryStar)
  3885. errorInternal(19);
  3886. */
  3887. del(oldIdxLeft - (oldSpLeft - sp), 1); // delete '*'
  3888. del(oldIdxRight - (oldSpRight - sp), 1); // delete '*'
  3889. oldSpLeft--;
  3890. // '*' will be inserted at the end
  3891. }
  3892. else
  3893. {
  3894. compatCheck(ExprTypeSynPtr,
  3895. RightExprTypeSynPtr,
  3896. &constExpr[1],
  3897. oldIdxRight - (oldSpRight - sp),
  3898. oldIdxLeft - (oldSpLeft - sp));
  3899. }
  3900. // label at the start of exprMID
  3901. ins2(oldIdxLeft + 1 - (oldSpLeft - sp), tokLogAnd, sc); // piggyback on && for CG (ugly, but simple)
  3902. // jump from the end of exprR over exprMID to the end of ?:
  3903. ins2(oldIdxLeft - (oldSpLeft - sp), tokGoto, sc + 1);
  3904. // jump to exprMID if exprL is non-zero
  3905. ins2(*idx + 1, tokShortCirc, -sc);
  3906. oldIdxCond = *idx;
  3907. oldSpCond = sp;
  3908. sl = exprval(idx, &condTypeSynPtr, &constExpr[0]);
  3909. // Bar void and struct/union
  3910. scalarTypeCheck(condTypeSynPtr);
  3911. *ConstExpr = s = 0;
  3912. if (constExpr[0])
  3913. {
  3914. int c1 = 0, c2 = 0;
  3915. // Stack now: exprL tokShortCirc exprR tokGoto tokLogAnd exprMID ?/tokLogAnd
  3916. if (
  3917. (truncUint(sl) != 0))
  3918. {
  3919. if (constExpr[1])
  3920. {
  3921. *ConstExpr = 1, s = smid;
  3922. }
  3923. else
  3924. {
  3925. // Drop exprL and exprR subexpressions
  3926. c1 = oldIdxLeft - (oldSpLeft - sp) - *idx; // includes tokShortCirc, tokGoto, tokLogAnd
  3927. c2 = 1; // include '?'/tokLogAnd
  3928. }
  3929. }
  3930. else
  3931. {
  3932. if (constExpr[2])
  3933. {
  3934. *ConstExpr = 1, s = sr;
  3935. }
  3936. else
  3937. {
  3938. // Drop exprL and exprMID subexpressions
  3939. c1 = oldIdxCond - (oldSpCond - sp) - *idx + 1; // includes tokShortCirc
  3940. c2 = (oldIdxRight - (oldSpRight - sp)) -
  3941. (oldIdxLeft - (oldSpLeft - sp)) + 3; // includes tokGoto, tokLogAnd, '?'/tokLogAnd
  3942. }
  3943. }
  3944. if (c1)
  3945. {
  3946. int pos = oldIdxRight - (oldSpRight - sp) + 2 - c2;
  3947. if (!structs && stack[pos - 1][0] == tokUnaryStar)
  3948. stack[pos++][0] = tokUnaryPlus, c2--; // ensure non-lvalue-ness by hiding the dereference
  3949. del(pos, c2);
  3950. del(*idx + 1, c1);
  3951. }
  3952. }
  3953. // finish transforming "cond ? a : b" into "*(cond ? &a : &b)", insert '*'
  3954. if (structs)
  3955. ins2(oldIdxRight + 2 - (oldSpRight - sp), tokUnaryStar, 0); // use 0 deref size to drop meaningless dereferences
  3956. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3957. }
  3958. break;
  3959. // Postfix indirect structure/union member selection operator
  3960. case tokArrow:
  3961. {
  3962. int member, i = 0, j = 0, c = 1, ofs = 0;
  3963. stack[*idx + 1][0] = '+'; // replace -> with +
  3964. member = stack[*idx][1]; // keep the member name, it will be replaced with member offset
  3965. stack[*idx][0] = tokNumInt;
  3966. --*idx;
  3967. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3968. if (!isAnyPtr(*ExprTypeSynPtr) ||
  3969. SyntaxStack0[i = derefAnyPtr(*ExprTypeSynPtr)] != tokStructPtr)
  3970. error("Pointer to or structure or union expected\n");
  3971. i = SyntaxStack1[i];
  3972. if (i + 2 > SyntaxStackCnt ||
  3973. (SyntaxStack0[i] != tokStruct && SyntaxStack0[i] != tokUnion) ||
  3974. SyntaxStack0[i + 1] != tokTag)
  3975. errorInternal(20);
  3976. if (!GetDeclSize(i, 0))
  3977. // incomplete structure/union type
  3978. errorOpType();
  3979. i += 5; // step inside the {} body of the struct/union
  3980. while (c)
  3981. {
  3982. int t = SyntaxStack0[i];
  3983. c += (t == '(') - (t == ')') + (t == '{') - (t == '}');
  3984. if (c == 1 &&
  3985. t == tokMemberIdent && SyntaxStack1[i] == member &&
  3986. SyntaxStack0[i + 1] == tokLocalOfs)
  3987. {
  3988. j = i;
  3989. ofs = SyntaxStack1[i + 1];
  3990. break;
  3991. }
  3992. i++;
  3993. }
  3994. if (!j)
  3995. error("Undefined structure or union member '%s'\n", IdentTable + member);
  3996. j += 2;
  3997. // we cannot insert another '*' into the type to make it a pointer,
  3998. // so make the index into the type negative
  3999. *ExprTypeSynPtr = -j; // type: pointer to member's type
  4000. stack[oldIdxRight - (oldSpRight - sp)][1] = ofs; // member offset within structure/union
  4001. // optimize a little, if possible
  4002. {
  4003. int i = oldIdxRight - (oldSpRight - sp) - 1;
  4004. // Skip any type cast markers
  4005. while (stack[i][0] == tokUnaryPlus)
  4006. i--;
  4007. // See if the pointer is an integer constant or a local variable offset
  4008. // and if it is, adjust it here instead of generating code for
  4009. // addition/subtraction
  4010. if (stack[i][0] == tokNumInt || stack[i][0] == tokNumUint || stack[i][0] == tokLocalOfs)
  4011. {
  4012. stack[i][1] = (int)((unsigned)stack[i][1] + ofs); // TBD!!! need extra truncation?
  4013. del(oldIdxRight - (oldSpRight - sp), 2);
  4014. }
  4015. }
  4016. *ConstExpr = 0;
  4017. }
  4018. break;
  4019. default:
  4020. //error("exprval(): Unexpected token %s\n", GetTokenName(tok));
  4021. errorInternal(21);
  4022. }
  4023. return s;
  4024. }
  4025. STATIC
  4026. int ParseExpr(int tok, int* GotUnary, int* ExprTypeSynPtr, int* ConstExpr, int* ConstVal, int option, int option2)
  4027. {
  4028. int identFirst = tok == tokIdent;
  4029. *ConstVal = *ConstExpr = 0;
  4030. *ExprTypeSynPtr = SymVoidSynPtr;
  4031. if (!ExprLevel++)
  4032. {
  4033. opsp = sp = 0;
  4034. }
  4035. if (option == '=')
  4036. push2(tokIdent, option2);
  4037. tok = expr(tok, GotUnary, option == ',' || option == '=');
  4038. if (tok == tokEof || strchr(",;:)]}", tok) == NULL)
  4039. //error("ParseExpr(): Unexpected token %s\n", GetTokenName(tok));
  4040. errorUnexpectedToken(tok);
  4041. if (option == '=')
  4042. {
  4043. push('=');
  4044. }
  4045. else if (option == tokGotoLabel && identFirst && tok == ':' && *GotUnary && sp == 1 && stack[sp - 1][0] == tokIdent)
  4046. {
  4047. // This is a label.
  4048. ExprLevel--;
  4049. return tokGotoLabel;
  4050. }
  4051. if (*GotUnary)
  4052. {
  4053. int j;
  4054. // Do this twice so we can see the stack before
  4055. // and after manipulations
  4056. for (j = 0; j < 2; j++)
  4057. {
  4058. int i;
  4059. GenStartCommentLine();
  4060. if (j) printf2("Expanded");
  4061. else printf2("RPN'ized");
  4062. printf2(" expression: \"");
  4063. for (i = 0; i < sp; i++)
  4064. {
  4065. int tok = stack[i][0];
  4066. switch (tok)
  4067. {
  4068. case tokNumInt:
  4069. printf2("%d", truncInt(stack[i][1]));
  4070. break;
  4071. case tokNumUint:
  4072. printf2("%uu", truncUint(stack[i][1]));
  4073. break;
  4074. case tokIdent:
  4075. {
  4076. char* p = IdentTable + stack[i][1];
  4077. if (isdigit(*p))
  4078. printf2("L");
  4079. printf2("%s", p);
  4080. }
  4081. break;
  4082. case tokShortCirc:
  4083. if (stack[i][1] >= 0)
  4084. printf2("[sh&&->%d]", stack[i][1]);
  4085. else
  4086. printf2("[sh||->%d]", -stack[i][1]);
  4087. break;
  4088. case tokLocalOfs:
  4089. printf2("(@%d)", truncInt(stack[i][1]));
  4090. break;
  4091. case tokUnaryStar:
  4092. if (j) printf2("*(%d)", stack[i][1]);
  4093. else printf2("*u");
  4094. break;
  4095. case '(': case ',':
  4096. if (!j) printf2("%c", tok);
  4097. // else printf2("\b");
  4098. break;
  4099. case ')':
  4100. if (j) printf2("(");
  4101. printf2("%c", tok);
  4102. if (j) printf2("%d", stack[i][1]);
  4103. break;
  4104. default:
  4105. printf2("%s", GetTokenName(tok));
  4106. if (j)
  4107. {
  4108. switch (tok)
  4109. {
  4110. case tokLogOr: case tokLogAnd:
  4111. printf2("[%d]", stack[i][1]);
  4112. break;
  4113. case '=':
  4114. case tokInc: case tokDec:
  4115. case tokPostInc: case tokPostDec:
  4116. case tokAssignAdd: case tokAssignSub:
  4117. case tokPostAdd: case tokPostSub:
  4118. case tokAssignMul:
  4119. case tokAssignDiv: case tokAssignMod:
  4120. case tokAssignUDiv: case tokAssignUMod:
  4121. case tokAssignLSh: case tokAssignRSh: case tokAssignURSh:
  4122. case tokAssignAnd: case tokAssignXor: case tokAssignOr:
  4123. printf2("(%d)", stack[i][1]);
  4124. break;
  4125. }
  4126. }
  4127. break;
  4128. }
  4129. printf2(" ");
  4130. }
  4131. printf2("\"\n");
  4132. if (!j)
  4133. {
  4134. int idx = sp - 1;
  4135. *ConstVal = exprval(&idx, ExprTypeSynPtr, ConstExpr);
  4136. // remove the unneeded unary +'s that have served their cast-substitute purpose
  4137. // also remove dereferences of size 0 (dereferences of pointers to structures)
  4138. for (idx = sp - 1; idx >= 0; idx--)
  4139. if (stack[idx][0] == tokUnaryPlus ||
  4140. (stack[idx][0] == tokUnaryStar && !stack[idx][1]))
  4141. del(idx, 1);
  4142. }
  4143. else if (*ConstExpr)
  4144. {
  4145. GenStartCommentLine();
  4146. switch (SyntaxStack0[*ExprTypeSynPtr])
  4147. {
  4148. case tokChar:
  4149. case tokSChar:
  4150. case tokUChar:
  4151. case tokShort:
  4152. case tokUShort:
  4153. case tokInt:
  4154. printf2("Expression value: %d\n", truncInt(*ConstVal));
  4155. break;
  4156. default:
  4157. case tokUnsigned:
  4158. printf2("Expression value: %uu\n", truncUint(*ConstVal));
  4159. break;
  4160. }
  4161. }
  4162. }
  4163. }
  4164. ExprLevel--;
  4165. return tok;
  4166. }
  4167. // smc.c code
  4168. // Equivalent to puts() but outputs to OutFile.
  4169. STATIC
  4170. int puts2(char* s)
  4171. {
  4172. int res;
  4173. if (!OutFile)
  4174. return 0;
  4175. // Turbo C++ 1.01's fputs() returns EOF if s is empty, which is wrong.
  4176. // Hence the workaround.
  4177. if (*s == '\0' || (res = fputs(s, OutFile)) >= 0)
  4178. {
  4179. // unlike puts(), fputs() doesn't append '\n', append it manually
  4180. res = fputc('\n', OutFile);
  4181. }
  4182. return res;
  4183. }
  4184. // Equivalent to printf() but outputs to OutFile.
  4185. STATIC
  4186. int printf2(char* format, ...)
  4187. {
  4188. int res;
  4189. void* vl = &format + 1;
  4190. if (!OutFile)
  4191. return 0;
  4192. // TBD!!! This is not good. Really need the va_something macros.
  4193. {
  4194. // va_list is a pointer
  4195. res = vfprintf(OutFile, format, vl);
  4196. }
  4197. return res;
  4198. }
  4199. STATIC
  4200. void error(char* format, ...)
  4201. {
  4202. int i, fidx = FileCnt - 1 + !FileCnt;
  4203. void* vl = &format + 1;
  4204. for (i = 0; i < FileCnt; i++)
  4205. if (Files[i])
  4206. fclose(Files[i]);
  4207. puts2("");
  4208. DumpSynDecls();
  4209. DumpMacroTable();
  4210. DumpIdentTable();
  4211. // using stdout implicitly instead of stderr explicitly because:
  4212. // - stderr can be a macro and it's unknown if standard headers
  4213. // aren't included (which is the case when SmallerC is compiled
  4214. // with itself and linked with some other compiler's standard
  4215. // libraries)
  4216. // - output to stderr can interfere/overlap with buffered
  4217. // output to stdout and the result may literally look ugly
  4218. GenStartCommentLine(); printf2("Compilation failed.\n");
  4219. if (OutFile)
  4220. fclose(OutFile);
  4221. printf("Error in \"%s\" (%d:%d)\n", FileNames[fidx], LineNo, LinePos);
  4222. // TBD!!! This is not good. Really need the va_something macros.
  4223. {
  4224. // va_list is a pointer
  4225. vprintf(format, vl);
  4226. }
  4227. va_end(vl);
  4228. exit(EXIT_FAILURE);
  4229. }
  4230. STATIC
  4231. void warning(char* format, ...)
  4232. {
  4233. int fidx = FileCnt - 1 + !FileCnt;
  4234. void* vl = &format + 1;
  4235. warnCnt++;
  4236. if (!warnings)
  4237. return;
  4238. printf("Warning in \"%s\" (%d:%d)\n", FileNames[fidx], LineNo, LinePos);
  4239. // TBD!!! This is not good. Really need the va_something macros.
  4240. {
  4241. // va_list is a pointer
  4242. vprintf(format, vl);
  4243. }
  4244. }
  4245. STATIC
  4246. void errorFile(char* n)
  4247. {
  4248. error("Unable to open, read, write or close file \"%s\"\n", n);
  4249. }
  4250. STATIC
  4251. void errorFileName(void)
  4252. {
  4253. error("Invalid or too long file name or path name\n");
  4254. }
  4255. STATIC
  4256. void errorInternal(int n)
  4257. {
  4258. error("%d (internal)\n", n);
  4259. }
  4260. STATIC
  4261. void errorChrStr(void)
  4262. {
  4263. error("Invalid or unsupported character constant or string literal\n");
  4264. }
  4265. STATIC
  4266. void errorStrLen(void)
  4267. {
  4268. error("String literal too long\n");
  4269. }
  4270. STATIC
  4271. void errorUnexpectedToken(int tok)
  4272. {
  4273. error("Unexpected token %s\n", (tok == tokIdent) ? TokenIdentName : GetTokenName(tok));
  4274. }
  4275. STATIC
  4276. void errorDirective(void)
  4277. {
  4278. error("Invalid or unsupported preprocessor directive\n");
  4279. }
  4280. STATIC
  4281. void errorCtrlOutOfScope(void)
  4282. {
  4283. error("break, continue, case or default in wrong scope\n");
  4284. }
  4285. STATIC
  4286. void errorDecl(void)
  4287. {
  4288. error("Invalid or unsupported declaration\n");
  4289. }
  4290. STATIC
  4291. void errorTagRedef(int ident)
  4292. {
  4293. error("Redefinition of type tagged '%s'\n", IdentTable + ident);
  4294. }
  4295. STATIC
  4296. void errorVarSize(void)
  4297. {
  4298. error("Variable(s) take(s) too much space\n");
  4299. }
  4300. STATIC
  4301. void errorInit(void)
  4302. {
  4303. error("Invalid or unsupported initialization\n");
  4304. }
  4305. STATIC
  4306. void errorUnexpectedVoid(void)
  4307. {
  4308. error("Unexpected declaration or expression of type void\n");
  4309. }
  4310. STATIC
  4311. void errorOpType(void)
  4312. {
  4313. error("Unexpected operand type\n");
  4314. }
  4315. STATIC
  4316. void errorNotLvalue(void)
  4317. {
  4318. error("lvalue expected\n");
  4319. }
  4320. STATIC
  4321. void errorNotConst(void)
  4322. {
  4323. error("Non-constant expression\n");
  4324. }
  4325. STATIC
  4326. void errorLongExpr(void)
  4327. {
  4328. error("Expression too long\n");
  4329. }
  4330. int tsd[] =
  4331. {
  4332. tokVoid, tokChar, tokInt,
  4333. tokSigned, tokUnsigned, tokShort,
  4334. tokStruct, tokUnion,
  4335. };
  4336. STATIC
  4337. int TokenStartsDeclaration(int t, int params)
  4338. {
  4339. unsigned i;
  4340. for (i = 0; i < division(sizeof tsd, sizeof tsd[0]); i++)
  4341. if (tsd[i] == t)
  4342. return 1;
  4343. return
  4344. (SizeOfWord != 2 && t == tokLong) ||
  4345. (!params && (t == tokExtern ||
  4346. t == tokStatic));
  4347. }
  4348. STATIC
  4349. void PushSyntax2(int t, int v)
  4350. {
  4351. if (SyntaxStackCnt >= SYNTAX_STACK_MAX)
  4352. error("Symbol table exhausted\n");
  4353. SyntaxStack0[SyntaxStackCnt] = t;
  4354. SyntaxStack1[SyntaxStackCnt++] = v;
  4355. }
  4356. STATIC
  4357. void PushSyntax(int t)
  4358. {
  4359. PushSyntax2(t, 0);
  4360. }
  4361. STATIC
  4362. void InsertSyntax2(int pos, int t, int v)
  4363. {
  4364. if (SyntaxStackCnt >= SYNTAX_STACK_MAX)
  4365. error("Symbol table exhausted\n");
  4366. memmove(&SyntaxStack0[pos + 1],
  4367. &SyntaxStack0[pos],
  4368. sizeof(SyntaxStack0[0]) * (SyntaxStackCnt - pos));
  4369. memmove(&SyntaxStack1[pos + 1],
  4370. &SyntaxStack1[pos],
  4371. sizeof(SyntaxStack1[0]) * (SyntaxStackCnt - pos));
  4372. SyntaxStack0[pos] = t;
  4373. SyntaxStack1[pos] = v;
  4374. SyntaxStackCnt++;
  4375. }
  4376. STATIC
  4377. void InsertSyntax(int pos, int t)
  4378. {
  4379. InsertSyntax2(pos, t, 0);
  4380. }
  4381. STATIC
  4382. void DeleteSyntax(int pos, int cnt)
  4383. {
  4384. memmove(&SyntaxStack0[pos],
  4385. &SyntaxStack0[pos + cnt],
  4386. sizeof(SyntaxStack0[0]) * (SyntaxStackCnt - (pos + cnt)));
  4387. memmove(&SyntaxStack1[pos],
  4388. &SyntaxStack1[pos + cnt],
  4389. sizeof(SyntaxStack1[0]) * (SyntaxStackCnt - (pos + cnt)));
  4390. SyntaxStackCnt -= cnt;
  4391. }
  4392. STATIC
  4393. int FindSymbol(char* s)
  4394. {
  4395. int i;
  4396. // TBD!!! return declaration scope number so
  4397. // redeclarations can be reported if occur in the same scope.
  4398. // TBD??? Also, I could first use FindIdent() and then just look for the
  4399. // index into IdentTable[] instead of doing strcmp()
  4400. for (i = SyntaxStackCnt - 1; i >= 0; i--)
  4401. {
  4402. int t = SyntaxStack0[i];
  4403. if (t == tokIdent &&
  4404. !strcmp(IdentTable + SyntaxStack1[i], s))
  4405. {
  4406. return i;
  4407. }
  4408. if (t == ')')
  4409. {
  4410. // Skip over the function params
  4411. int c = -1;
  4412. while (c)
  4413. {
  4414. t = SyntaxStack0[--i];
  4415. c += (t == '(') - (t == ')');
  4416. }
  4417. }
  4418. }
  4419. return -1;
  4420. }
  4421. STATIC
  4422. int SymType(int SynPtr)
  4423. {
  4424. int local = 0;
  4425. if (SyntaxStack0[SynPtr] == tokIdent)
  4426. SynPtr++;
  4427. if ((local = SyntaxStack0[SynPtr] == tokLocalOfs) != 0)
  4428. SynPtr++;
  4429. switch (SyntaxStack0[SynPtr])
  4430. {
  4431. case '(':
  4432. return SymFxn;
  4433. case '[':
  4434. if (local)
  4435. return SymLocalArr;
  4436. return SymGlobalArr;
  4437. default:
  4438. if (local)
  4439. return SymLocalVar;
  4440. return SymGlobalVar;
  4441. }
  4442. }
  4443. STATIC
  4444. int FindTaggedDecl(char* s, int start, int* CurScope)
  4445. {
  4446. int i;
  4447. *CurScope = 1;
  4448. for (i = start; i >= 0; i--)
  4449. {
  4450. int t = SyntaxStack0[i];
  4451. if (t == tokTag &&
  4452. !strcmp(IdentTable + SyntaxStack1[i], s))
  4453. {
  4454. return i - 1;
  4455. }
  4456. else if (t == ')')
  4457. {
  4458. // Skip over the function params
  4459. int c = -1;
  4460. while (c)
  4461. {
  4462. t = SyntaxStack0[--i];
  4463. c += (t == '(') - (t == ')');
  4464. }
  4465. }
  4466. else if (t == '#')
  4467. {
  4468. // the scope has changed to the outer scope
  4469. *CurScope = 0;
  4470. }
  4471. }
  4472. return -1;
  4473. }
  4474. STATIC
  4475. int GetDeclSize(int SyntaxPtr, int SizeForDeref)
  4476. {
  4477. int i;
  4478. unsigned size = 1;
  4479. int arr = 0;
  4480. if (SyntaxPtr < 0) // pointer?
  4481. return SizeOfWord;
  4482. for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
  4483. {
  4484. int tok = SyntaxStack0[i];
  4485. switch (tok)
  4486. {
  4487. case tokIdent: // skip leading identifiers, if any
  4488. case tokLocalOfs: // skip local var offset, too
  4489. break;
  4490. case tokChar:
  4491. case tokSChar:
  4492. if (!arr && ((tok == tokSChar) || CharIsSigned) && SizeForDeref)
  4493. return -1; // 1 byte, needing sign extension when converted to int/unsigned int
  4494. // fallthrough
  4495. case tokUChar:
  4496. return (int)size;
  4497. case tokShort:
  4498. if (!arr && SizeForDeref)
  4499. return -2; // 2 bytes, needing sign extension when converted to int/unsigned int
  4500. // fallthrough
  4501. case tokUShort:
  4502. //if (size * 2 / 2 != size)
  4503. //error("Variable too big\n");
  4504. // errorVarSize();
  4505. size *= 2;
  4506. if (size != truncUint(size))
  4507. //error("Variable too big\n");
  4508. errorVarSize();
  4509. return (int)size;
  4510. case tokInt:
  4511. case tokUnsigned:
  4512. case '*':
  4513. case '(': // size of fxn = size of ptr for now
  4514. //if (size * SizeOfWord / SizeOfWord != size)
  4515. //error("Variable too big\n");
  4516. //errorVarSize();
  4517. size *= SizeOfWord;
  4518. if (size != truncUint(size))
  4519. //error("Variable too big\n");
  4520. errorVarSize();
  4521. return (int)size;
  4522. case '[':
  4523. if (SyntaxStack0[i + 1] != tokNumInt && SyntaxStack0[i + 1] != tokNumUint)
  4524. errorInternal(11);
  4525. //if (SyntaxStack1[i + 1] &&
  4526. //size * SyntaxStack1[i + 1] / SyntaxStack1[i + 1] != size)
  4527. //error("Variable too big\n");
  4528. //errorVarSize();
  4529. size *= SyntaxStack1[i + 1];
  4530. if (size != truncUint(size))
  4531. //error("Variable too big\n");
  4532. errorVarSize();
  4533. i += 2;
  4534. arr = 1;
  4535. break;
  4536. case tokStructPtr:
  4537. // follow the "type pointer"
  4538. i = SyntaxStack1[i] - 1;
  4539. break;
  4540. case tokStruct:
  4541. case tokUnion:
  4542. if (i + 2 < SyntaxStackCnt && SyntaxStack0[i + 2] == tokSizeof && !SizeForDeref)
  4543. {
  4544. unsigned s = SyntaxStack1[i + 2];
  4545. //if (s && size * s / s != size)
  4546. // errorVarSize();
  4547. size *= s;
  4548. if (size != truncUint(size))
  4549. errorVarSize();
  4550. return (int)size;
  4551. }
  4552. return 0;
  4553. case tokVoid:
  4554. return 0;
  4555. default:
  4556. errorInternal(12);
  4557. }
  4558. }
  4559. errorInternal(13);
  4560. return 0;
  4561. }
  4562. STATIC
  4563. int GetDeclAlignment(int SyntaxPtr)
  4564. {
  4565. int i;
  4566. if (SyntaxPtr < 0) // pointer?
  4567. return SizeOfWord;
  4568. for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
  4569. {
  4570. int tok = SyntaxStack0[i];
  4571. switch (tok)
  4572. {
  4573. case tokIdent: // skip leading identifiers, if any
  4574. case tokLocalOfs: // skip local var offset, too
  4575. break;
  4576. case tokChar:
  4577. case tokSChar:
  4578. case tokUChar:
  4579. return 1;
  4580. case tokShort:
  4581. case tokUShort:
  4582. return 2;
  4583. case tokInt:
  4584. case tokUnsigned:
  4585. case '*':
  4586. case '(':
  4587. return SizeOfWord;
  4588. case '[':
  4589. if (SyntaxStack0[i + 1] != tokNumInt && SyntaxStack0[i + 1] != tokNumUint)
  4590. errorInternal(15);
  4591. i += 2;
  4592. break;
  4593. case tokStructPtr:
  4594. // follow the "type pointer"
  4595. i = SyntaxStack1[i] - 1;
  4596. break;
  4597. case tokStruct:
  4598. case tokUnion:
  4599. if (i + 3 < SyntaxStackCnt && SyntaxStack0[i + 2] == tokSizeof)
  4600. {
  4601. return SyntaxStack1[i + 3];
  4602. }
  4603. return 1;
  4604. case tokVoid:
  4605. return 1;
  4606. default:
  4607. errorInternal(16);
  4608. }
  4609. }
  4610. errorInternal(17);
  4611. return 0;
  4612. }
  4613. STATIC
  4614. void DumpDecl(int SyntaxPtr, int IsParam)
  4615. {
  4616. int i;
  4617. int icnt = 0;
  4618. if (SyntaxPtr < 0)
  4619. return;
  4620. for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
  4621. {
  4622. int tok = SyntaxStack0[i];
  4623. int v = SyntaxStack1[i];
  4624. switch (tok)
  4625. {
  4626. case tokLocalOfs:
  4627. printf2("(@%d) : ", truncInt(v));
  4628. break;
  4629. case tokIdent:
  4630. if (++icnt > 1 && !IsParam) // show at most one declaration, except params
  4631. return;
  4632. GenStartCommentLine();
  4633. if (ParseLevel == 0)
  4634. printf2("glb ");
  4635. else if (IsParam)
  4636. printf2("prm ");
  4637. else
  4638. printf2("loc ");
  4639. {
  4640. int j;
  4641. for (j = 0; j < ParseLevel * 4; j++)
  4642. printf2(" ");
  4643. }
  4644. if (IsParam && !strcmp(IdentTable + v, "<something>") && (i + 1 < SyntaxStackCnt))
  4645. {
  4646. if (SyntaxStack0[i + 1] == tokEllipsis)
  4647. continue;
  4648. }
  4649. printf2("%s : ", IdentTable + v);
  4650. if (!IsParam && (i + 1 < SyntaxStackCnt) && SyntaxStack0[i + 1] == tokIdent)
  4651. {
  4652. // renamed local static variable
  4653. GenPrintLabel(IdentTable + SyntaxStack1[++i]);
  4654. printf2(" : ");
  4655. }
  4656. break;
  4657. case '[':
  4658. printf2("[");
  4659. break;
  4660. case tokNumInt:
  4661. printf2("%d", truncInt(v));
  4662. break;
  4663. case tokNumUint:
  4664. printf2("%uu", truncUint(v));
  4665. break;
  4666. case ']':
  4667. printf2("] ");
  4668. break;
  4669. case '(':
  4670. {
  4671. int noparams;
  4672. // Skip over the params to the base type
  4673. int j = ++i, c = 1;
  4674. while (c)
  4675. {
  4676. int t = SyntaxStack0[j++];
  4677. c += (t == '(') - (t == ')');
  4678. }
  4679. noparams = (i + 1 == j) || (SyntaxStack0[i + 1] == tokVoid);
  4680. printf2("(");
  4681. // Print the params (recursively)
  4682. if (noparams)
  4683. {
  4684. // Don't recurse if it's "fxn()" or "fxn(void)"
  4685. if (i + 1 != j)
  4686. printf2("void");
  4687. }
  4688. else
  4689. {
  4690. puts2("");
  4691. ParseLevel++;
  4692. DumpDecl(i, 1);
  4693. ParseLevel--;
  4694. }
  4695. // Continue normally
  4696. i = j - 1;
  4697. if (!noparams)
  4698. {
  4699. GenStartCommentLine();
  4700. printf2(" ");
  4701. {
  4702. int j;
  4703. for (j = 0; j < ParseLevel * 4; j++)
  4704. printf2(" ");
  4705. }
  4706. }
  4707. printf2(") ");
  4708. }
  4709. break;
  4710. case ')': // end of param list
  4711. return;
  4712. case tokStructPtr:
  4713. DumpDecl(v, 0);
  4714. break;
  4715. default:
  4716. switch (tok)
  4717. {
  4718. case tokVoid:
  4719. case tokChar:
  4720. case tokSChar:
  4721. case tokUChar:
  4722. case tokShort:
  4723. case tokUShort:
  4724. case tokInt:
  4725. case tokUnsigned:
  4726. case tokEllipsis:
  4727. printf2("%s\n", GetTokenName(tok));
  4728. break;
  4729. default:
  4730. printf2("%s ", GetTokenName(tok));
  4731. break;
  4732. case tokTag:
  4733. printf2("%s\n", IdentTable + v);
  4734. return;
  4735. }
  4736. break;
  4737. }
  4738. }
  4739. }
  4740. STATIC
  4741. void DumpSynDecls(void)
  4742. {
  4743. int used = SyntaxStackCnt * (sizeof SyntaxStack0[0] + sizeof SyntaxStack1[0]);
  4744. int total = SYNTAX_STACK_MAX * (sizeof SyntaxStack0[0] + sizeof SyntaxStack1[0]);
  4745. puts2("");
  4746. GenStartCommentLine(); printf2("Syntax/declaration table/stack:\n");
  4747. GenStartCommentLine(); printf2("Bytes used: %d/%d\n\n", used, total);
  4748. }
  4749. STATIC
  4750. int ParseArrayDimension(int AllowEmptyDimension)
  4751. {
  4752. int tok;
  4753. int gotUnary, synPtr, constExpr, exprVal;
  4754. unsigned exprValU;
  4755. int oldssp, oldesp, undoIdents;
  4756. tok = GetToken();
  4757. // DONE: support arbitrary constant expressions
  4758. oldssp = SyntaxStackCnt;
  4759. oldesp = sp;
  4760. undoIdents = IdentTableLen;
  4761. tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0);
  4762. IdentTableLen = undoIdents; // remove all temporary identifier names from e.g. "sizeof"
  4763. SyntaxStackCnt = oldssp; // undo any temporary declarations from e.g. "sizeof" in the expression
  4764. sp = oldesp;
  4765. if (tok != ']')
  4766. //error("ParseArrayDimension(): Unsupported or invalid array dimension (token %s)\n", GetTokenName(tok));
  4767. errorUnexpectedToken(tok);
  4768. if (!gotUnary)
  4769. {
  4770. if (!AllowEmptyDimension)
  4771. //error("ParseArrayDimension(): missing array dimension\n");
  4772. errorUnexpectedToken(tok);
  4773. // Empty dimension is dimension of 0
  4774. exprVal = 0;
  4775. }
  4776. else
  4777. {
  4778. if (!constExpr)
  4779. //error("ParseArrayDimension(): non-constant array dimension\n");
  4780. errorNotConst();
  4781. exprValU = truncUint(exprVal);
  4782. exprVal = truncInt(exprVal);
  4783. promoteType(&synPtr, &synPtr);
  4784. anyIntTypeCheck(synPtr);
  4785. if ((SyntaxStack0[synPtr] == tokInt && exprVal < 1) || (SyntaxStack0[synPtr] == tokUnsigned && exprValU < 1))
  4786. error("Array dimension less than 1\n");
  4787. exprVal = (int)exprValU;
  4788. }
  4789. PushSyntax2(tokNumUint, exprVal);
  4790. return tok;
  4791. }
  4792. STATIC
  4793. void ParseFxnParams(int tok);
  4794. static int BrkCntTargetFxn[2];
  4795. STATIC
  4796. int ParseBlock(int BrkCntTarget[2], int casesIdx);
  4797. STATIC
  4798. void AddFxnParamSymbols(int SyntaxPtr);
  4799. STATIC
  4800. void CheckRedecl(int lastSyntaxPtr);
  4801. STATIC
  4802. int ParseBase(int tok, int base[2])
  4803. {
  4804. int valid = 1;
  4805. base[1] = 0;
  4806. switch (tok)
  4807. {
  4808. case tokVoid:
  4809. *base = tok;
  4810. tok = GetToken();
  4811. break;
  4812. case tokChar:
  4813. case tokInt:
  4814. case tokShort:
  4815. case tokLong:
  4816. case tokSigned:
  4817. case tokUnsigned:
  4818. {
  4819. int allowedMask = 0x7F; // double:0x40 unsigned:0x20 signed:0x10 long:0x08 int:0x04 short:0x02 char:0x01
  4820. int typeMask = 0;
  4821. int tokMask, disallowedMask;
  4822. lcont:
  4823. switch (tok)
  4824. {
  4825. case tokChar:
  4826. tokMask = 0x01; disallowedMask = 0x4E; break; // disallows double, long, int, short
  4827. case tokShort:
  4828. tokMask = 0x02; disallowedMask = 0x49; break; // disallows double, long, char
  4829. case tokInt:
  4830. tokMask = 0x04; disallowedMask = 0x41; break; // disallows double, char
  4831. case tokLong:
  4832. tokMask = 0x08; disallowedMask = 0x03; break; // disallows short, char
  4833. case tokSigned:
  4834. tokMask = 0x10; disallowedMask = 0x60; break; // disallows double, unsigned
  4835. case tokUnsigned:
  4836. tokMask = 0x20; disallowedMask = 0x50; break; // disallows double, signed
  4837. default:
  4838. tokMask = disallowedMask = 0; break;
  4839. }
  4840. if (allowedMask & tokMask)
  4841. {
  4842. typeMask |= tokMask;
  4843. allowedMask &= ~(disallowedMask | tokMask);
  4844. tok = GetToken();
  4845. goto lcont;
  4846. }
  4847. switch (typeMask)
  4848. {
  4849. case 0x01: typeMask = tokChar; break;
  4850. case 0x11: typeMask = tokSChar; break;
  4851. case 0x21: typeMask = tokUChar; break;
  4852. case 0x02: case 0x12: case 0x06: case 0x16: typeMask = tokShort; break;
  4853. case 0x22: case 0x26: typeMask = tokUShort; break;
  4854. case 0x04: case 0x10: case 0x14: typeMask = tokInt; break;
  4855. case 0x20: case 0x24: typeMask = tokUnsigned; break;
  4856. case 0x08: case 0x18: case 0x0C: case 0x1C: typeMask = tokLong; break;
  4857. case 0x28: case 0x2C: typeMask = tokULong; break;
  4858. default:
  4859. errorDecl();
  4860. }
  4861. *base = typeMask;
  4862. }
  4863. break;
  4864. case tokStruct:
  4865. case tokUnion:
  4866. {
  4867. int structType = tok;
  4868. int empty = 1;
  4869. int typePtr = SyntaxStackCnt;
  4870. int gotTag = 0, tagIdent = 0, declPtr = -1, curScope = 0;
  4871. tok = GetToken();
  4872. if (tok == tokIdent)
  4873. {
  4874. // this is a structure/union/enum tag
  4875. gotTag = 1;
  4876. declPtr = FindTaggedDecl(TokenIdentName, SyntaxStackCnt - 1, &curScope);
  4877. tagIdent = AddIdent(TokenIdentName);
  4878. if (declPtr >= 0)
  4879. {
  4880. // Within the same scope we can't declare more than one union, structure or enum
  4881. // with the same tag.
  4882. // There's one common tag namespace for structures, unions and enumerations.
  4883. if (curScope && SyntaxStack0[declPtr] != structType)
  4884. errorTagRedef(tagIdent);
  4885. }
  4886. else if (ParamLevel)
  4887. {
  4888. // new structure/union/enum declarations aren't supported in function parameters
  4889. errorDecl();
  4890. }
  4891. tok = GetToken();
  4892. }
  4893. else
  4894. {
  4895. // structure/union/enum declarations aren't supported in expressions
  4896. if (ExprLevel)
  4897. errorDecl();
  4898. PushSyntax(structType);
  4899. PushSyntax2(tokTag, AddIdent("<something>"));
  4900. }
  4901. if (tok == '{')
  4902. {
  4903. unsigned structInfo[4], sz, alignment, tmp;
  4904. // new structure/union/enum declarations aren't supported in expressions and function parameters
  4905. if (ExprLevel || ParamLevel)
  4906. errorDecl();
  4907. if (gotTag)
  4908. {
  4909. // Cannot redefine a tagged structure/union/enum within the same scope
  4910. if (declPtr >= 0 &&
  4911. curScope &&
  4912. ((declPtr + 2 < SyntaxStackCnt && SyntaxStack0[declPtr + 2] == tokSizeof)
  4913. ))
  4914. errorTagRedef(tagIdent);
  4915. PushSyntax(structType);
  4916. PushSyntax2(tokTag, tagIdent);
  4917. }
  4918. {
  4919. structInfo[0] = structType;
  4920. structInfo[1] = 1; // initial member alignment
  4921. structInfo[2] = 0; // initial member offset
  4922. structInfo[3] = 0; // initial max member size (for unions)
  4923. PushSyntax(tokSizeof); // 0 = initial structure/union size, to be updated
  4924. PushSyntax2(tokSizeof, 1); // 1 = initial structure/union alignment, to be updated
  4925. PushSyntax('{');
  4926. tok = GetToken();
  4927. while (tok != '}')
  4928. {
  4929. if (!TokenStartsDeclaration(tok, 1))
  4930. errorUnexpectedToken(tok);
  4931. tok = ParseDecl(tok, structInfo, 0, 0);
  4932. empty = 0;
  4933. }
  4934. if (empty)
  4935. errorUnexpectedToken('}');
  4936. PushSyntax('}');
  4937. // Update structure/union alignment
  4938. alignment = structInfo[1];
  4939. SyntaxStack1[typePtr + 3] = alignment;
  4940. // Update structure/union size and include trailing padding if needed
  4941. sz = structInfo[2] + structInfo[3];
  4942. tmp = sz;
  4943. sz = (sz + alignment - 1) & ~(alignment - 1);
  4944. if (sz < tmp || sz != truncUint(sz))
  4945. errorVarSize();
  4946. SyntaxStack1[typePtr + 2] = (int)sz;
  4947. tok = GetToken();
  4948. }
  4949. }
  4950. else
  4951. {
  4952. if (gotTag)
  4953. {
  4954. if (declPtr >= 0 &&
  4955. SyntaxStack0[declPtr] == structType)
  4956. {
  4957. base[0] = tokStructPtr;
  4958. base[1] = declPtr;
  4959. return tok;
  4960. }
  4961. PushSyntax(structType);
  4962. PushSyntax2(tokTag, tagIdent);
  4963. empty = 0;
  4964. }
  4965. }
  4966. if (empty)
  4967. errorDecl();
  4968. base[0] = tokStructPtr;
  4969. base[1] = typePtr;
  4970. // If we've just defined a structure/union and there are
  4971. // preceding references to this tag within this scope,
  4972. // IOW references to an incomplete type, complete the
  4973. // type in the references
  4974. if (gotTag && SyntaxStack0[SyntaxStackCnt - 1] == '}')
  4975. {
  4976. int i;
  4977. for (i = SyntaxStackCnt - 1; i >= 0; i--)
  4978. if (SyntaxStack0[i] == tokStructPtr)
  4979. {
  4980. int j = SyntaxStack1[i];
  4981. if (SyntaxStack1[j + 1] == tagIdent && !GetDeclSize(i, 0))
  4982. SyntaxStack1[i] = typePtr;
  4983. }
  4984. else if (SyntaxStack0[i] == '#')
  4985. {
  4986. // reached the beginning of the current scope
  4987. break;
  4988. }
  4989. }
  4990. }
  4991. break;
  4992. default:
  4993. valid = 0;
  4994. break;
  4995. }
  4996. if (SizeOfWord == 2 &&
  4997. (*base == tokLong || *base == tokULong))
  4998. valid = 0;
  4999. // to simplify matters, treat long and unsigned long as aliases for int and unsigned int
  5000. // in 32-bit and huge mode(l)s
  5001. if (*base == tokLong)
  5002. *base = tokInt;
  5003. if (*base == tokULong)
  5004. *base = tokUnsigned;
  5005. if (SizeOfWord == 2)
  5006. {
  5007. // to simplify matters, treat short and unsigned short as aliases for int and unsigned int
  5008. // in 16-bit mode
  5009. if (*base == tokShort)
  5010. *base = tokInt;
  5011. if (*base == tokUShort)
  5012. *base = tokUnsigned;
  5013. }
  5014. // TBD!!! review/test this fxn
  5015. // if (!valid || !tok || !(strchr("*([,)", tok) || tok == tokIdent))
  5016. if (!valid | !tok)
  5017. //error("ParseBase(): Invalid or unsupported type\n");
  5018. error("Invalid or unsupported type\n");
  5019. return tok;
  5020. }
  5021. /*
  5022. base * name [] -> name : [] * base
  5023. base *2 (*1 name []1) []2 -> name : []1 *1 []2 *2 base
  5024. base *3 (*2 (*1 name []1) []2) []3 -> name : []1 *1 []2 *2 []3 *3 base
  5025. */
  5026. STATIC
  5027. int ParseDerived(int tok)
  5028. {
  5029. int stars = 0;
  5030. int params = 0;
  5031. while (tok == '*')
  5032. {
  5033. stars++;
  5034. tok = GetToken();
  5035. }
  5036. if (tok == '(')
  5037. {
  5038. tok = GetToken();
  5039. if (tok != ')' && !TokenStartsDeclaration(tok, 1))
  5040. {
  5041. tok = ParseDerived(tok);
  5042. if (tok != ')')
  5043. //error("ParseDerived(): ')' expected\n");
  5044. errorUnexpectedToken(tok);
  5045. tok = GetToken();
  5046. }
  5047. else
  5048. {
  5049. params = 1;
  5050. }
  5051. }
  5052. else if (tok == tokIdent)
  5053. {
  5054. PushSyntax2(tok, AddIdent(TokenIdentName));
  5055. tok = GetToken();
  5056. }
  5057. else
  5058. {
  5059. PushSyntax2(tokIdent, AddIdent("<something>"));
  5060. }
  5061. if (params | (tok == '('))
  5062. {
  5063. int t = SyntaxStack0[SyntaxStackCnt - 1];
  5064. if ((t == ')') | (t == ']'))
  5065. errorUnexpectedToken('('); // array of functions or function returning function
  5066. if (!params)
  5067. tok = GetToken();
  5068. else
  5069. PushSyntax2(tokIdent, AddIdent("<something>"));
  5070. PushSyntax('(');
  5071. ParseLevel++;
  5072. ParamLevel++;
  5073. ParseFxnParams(tok);
  5074. ParamLevel--;
  5075. ParseLevel--;
  5076. PushSyntax(')');
  5077. tok = GetToken();
  5078. }
  5079. else if (tok == '[')
  5080. {
  5081. // DONE!!! allow the first [] without the dimension in function parameters
  5082. int allowEmptyDimension = 1;
  5083. if (SyntaxStack0[SyntaxStackCnt - 1] == ')')
  5084. errorUnexpectedToken('['); // function returning array
  5085. while (tok == '[')
  5086. {
  5087. int oldsp = SyntaxStackCnt;
  5088. PushSyntax(tokVoid); // prevent cases like "int arr[arr];" and "int arr[arr[0]];"
  5089. PushSyntax(tok);
  5090. tok = ParseArrayDimension(allowEmptyDimension);
  5091. if (tok != ']')
  5092. //error("ParseDerived(): ']' expected\n");
  5093. errorUnexpectedToken(tok);
  5094. PushSyntax(']');
  5095. tok = GetToken();
  5096. DeleteSyntax(oldsp, 1);
  5097. allowEmptyDimension = 0;
  5098. }
  5099. }
  5100. while (stars--)
  5101. PushSyntax('*');
  5102. if (!tok || !strchr(",;{=)", tok))
  5103. //error("ParseDerived(): unexpected token %s\n", GetTokenName(tok));
  5104. errorUnexpectedToken(tok);
  5105. return tok;
  5106. }
  5107. STATIC
  5108. void PushBase(int base[2])
  5109. {
  5110. {
  5111. PushSyntax2(base[0], base[1]);
  5112. }
  5113. // Cannot have array of void
  5114. if (SyntaxStack0[SyntaxStackCnt - 1] == tokVoid &&
  5115. SyntaxStack0[SyntaxStackCnt - 2] == ']')
  5116. errorUnexpectedVoid();
  5117. }
  5118. STATIC
  5119. int InitScalar(int synPtr, int tok);
  5120. STATIC
  5121. int InitArray(int synPtr, int tok);
  5122. STATIC
  5123. int InitStruct(int synPtr, int tok);
  5124. STATIC
  5125. int InitVar(int synPtr, int tok)
  5126. {
  5127. int p = synPtr, t;
  5128. int undoIdents = IdentTableLen;
  5129. while ((t = SyntaxStack0[p]), (t == tokIdent) | (t == tokLocalOfs))
  5130. p++;
  5131. switch (t)
  5132. {
  5133. case '[':
  5134. // Initializers for aggregates must be enclosed in braces,
  5135. // except for arrays of char initialized with string literals,
  5136. // in which case braces are optional
  5137. if (tok != '{')
  5138. {
  5139. t = SyntaxStack0[p + 3];
  5140. if (((tok != tokLitStr) | ((t != tokChar) & (t != tokUChar) & (t != tokSChar)))
  5141. )
  5142. errorUnexpectedToken(tok);
  5143. }
  5144. tok = InitArray(p, tok);
  5145. break;
  5146. case tokStructPtr:
  5147. // Initializers for aggregates must be enclosed in braces
  5148. if (tok != '{')
  5149. errorUnexpectedToken(tok);
  5150. tok = InitStruct(p, tok);
  5151. break;
  5152. default:
  5153. tok = InitScalar(p, tok);
  5154. break;
  5155. }
  5156. if (!strchr(",;", tok))
  5157. errorUnexpectedToken(tok);
  5158. IdentTableLen = undoIdents; // remove all temporary identifier names from e.g. "sizeof" or "str"
  5159. return tok;
  5160. }
  5161. STATIC
  5162. int InitScalar(int synPtr, int tok)
  5163. {
  5164. unsigned elementSz = GetDeclSize(synPtr, 0);
  5165. int gotUnary, synPtr2, constExpr, exprVal;
  5166. int oldssp = SyntaxStackCnt;
  5167. int undoIdents = IdentTableLen;
  5168. int ttop;
  5169. int braces = 0;
  5170. // Initializers for scalars can be optionally enclosed in braces
  5171. if (tok == '{')
  5172. {
  5173. braces = 1;
  5174. tok = GetToken();
  5175. }
  5176. tok = ParseExpr(tok, &gotUnary, &synPtr2, &constExpr, &exprVal, ',', 0);
  5177. if (!gotUnary)
  5178. errorUnexpectedToken(tok);
  5179. if (braces)
  5180. {
  5181. if (tok != '}')
  5182. errorUnexpectedToken(tok);
  5183. tok = GetToken();
  5184. }
  5185. // Bar void and struct/union
  5186. scalarTypeCheck(synPtr2);
  5187. ttop = stack[sp - 1][0];
  5188. if (ttop == tokNumInt || ttop == tokNumUint)
  5189. {
  5190. int val = stack[sp - 1][1];
  5191. // TBD??? truncate values for types smaller than int (e.g. char and short),
  5192. // so they are always in range for the assembler?
  5193. GenIntData(elementSz, val);
  5194. }
  5195. else if (elementSz == (unsigned)SizeOfWord)
  5196. {
  5197. if (ttop == tokIdent)
  5198. {
  5199. GenAddrData(elementSz, IdentTable + stack[sp - 1][1], 0);
  5200. }
  5201. else if (ttop == '+' || ttop == '-')
  5202. {
  5203. int tleft = stack[sp - 3][0];
  5204. int tright = stack[sp - 2][0];
  5205. if (tleft == tokIdent &&
  5206. (tright == tokNumInt || tright == tokNumUint))
  5207. {
  5208. GenAddrData(elementSz, IdentTable + stack[sp - 3][1], (ttop == '+') ? stack[sp - 2][1] : -stack[sp - 2][1]);
  5209. }
  5210. else if (ttop == '+' &&
  5211. tright == tokIdent &&
  5212. (tleft == tokNumInt || tleft == tokNumUint))
  5213. {
  5214. GenAddrData(elementSz, IdentTable + stack[sp - 2][1], stack[sp - 3][1]);
  5215. }
  5216. else
  5217. errorNotConst();
  5218. }
  5219. else
  5220. errorNotConst();
  5221. // Defer storage of string literal data (if any) until the end.
  5222. // This will let us generate the contiguous array of pointers to
  5223. // string literals unperturbed by the string literal data
  5224. // (e.g. "char* colors[] = { "red", "green", "blue" };").
  5225. }
  5226. else
  5227. //error("ParseDecl(): cannot initialize a global variable with a non-constant expression\n");
  5228. errorNotConst();
  5229. IdentTableLen = undoIdents; // remove all temporary identifier names from e.g. "sizeof" or "str"
  5230. SyntaxStackCnt = oldssp; // undo any temporary declarations from e.g. "sizeof" or "str" in the expression
  5231. return tok;
  5232. }
  5233. STATIC
  5234. int InitArray(int synPtr, int tok)
  5235. {
  5236. int elementTypePtr = synPtr + 3;
  5237. int elementType = SyntaxStack0[elementTypePtr];
  5238. unsigned elementSz = GetDeclSize(elementTypePtr, 0);
  5239. int braces = 0;
  5240. unsigned elementCnt = 0;
  5241. unsigned elementsRequired = SyntaxStack1[synPtr + 1];
  5242. int arrOfChar = (elementType == tokChar) | (elementType == tokUChar) | (elementType == tokSChar);
  5243. if (tok == '{')
  5244. {
  5245. braces = 1;
  5246. tok = GetToken();
  5247. }
  5248. if ((arrOfChar & (tok == tokLitStr))
  5249. )
  5250. {
  5251. int ltok = tok;
  5252. unsigned sz = 0;
  5253. // this is 'someArray[someCountIfAny] = "some string"' or
  5254. // 'someArray[someCountIfAny] = { "some string" }'
  5255. do
  5256. {
  5257. GetString('"', 0, 'd');
  5258. if (sz + TokenStringSize < sz ||
  5259. sz + TokenStringSize >= truncUint(-1))
  5260. errorStrLen();
  5261. sz += TokenStringSize;
  5262. elementCnt += TokenStringLen;
  5263. tok = GetToken();
  5264. } while (tok == ltok); // concatenate adjacent string literals
  5265. if (elementsRequired && elementCnt > elementsRequired)
  5266. errorStrLen();
  5267. if (elementCnt < elementsRequired)
  5268. GenZeroData(elementsRequired - elementCnt, 0);
  5269. if (!elementsRequired)
  5270. GenZeroData(elementSz, 0), elementCnt++;
  5271. if (braces)
  5272. {
  5273. if (tok != '}')
  5274. errorUnexpectedToken(tok);
  5275. tok = GetToken();
  5276. }
  5277. }
  5278. else
  5279. {
  5280. while (tok != '}')
  5281. {
  5282. if (elementType == '[')
  5283. {
  5284. tok = InitArray(elementTypePtr, tok);
  5285. }
  5286. else if (elementType == tokStructPtr)
  5287. {
  5288. tok = InitStruct(elementTypePtr, tok);
  5289. }
  5290. else
  5291. {
  5292. tok = InitScalar(elementTypePtr, tok);
  5293. }
  5294. // Last element?
  5295. if (++elementCnt >= elementsRequired && elementsRequired)
  5296. {
  5297. if (braces & (tok == ','))
  5298. tok = GetToken();
  5299. break;
  5300. }
  5301. if (tok == ',')
  5302. tok = GetToken();
  5303. else if (tok != '}')
  5304. errorUnexpectedToken(tok);
  5305. }
  5306. if (braces)
  5307. {
  5308. if ((!elementCnt) | (tok != '}'))
  5309. errorUnexpectedToken(tok);
  5310. tok = GetToken();
  5311. }
  5312. if (elementCnt < elementsRequired)
  5313. GenZeroData((elementsRequired - elementCnt) * elementSz, 0);
  5314. }
  5315. // Store the element count if it's an incomplete array
  5316. if (!elementsRequired)
  5317. SyntaxStack1[synPtr + 1] = elementCnt;
  5318. return tok;
  5319. }
  5320. STATIC
  5321. int InitStruct(int synPtr, int tok)
  5322. {
  5323. int isUnion;
  5324. unsigned size, ofs = 0;
  5325. int braces = 0;
  5326. int c = 1;
  5327. synPtr = SyntaxStack1[synPtr];
  5328. isUnion = SyntaxStack0[synPtr++] == tokUnion;
  5329. size = SyntaxStack1[++synPtr];
  5330. synPtr += 3; // step inside the {} body of the struct/union
  5331. if (tok == '{')
  5332. {
  5333. braces = 1;
  5334. tok = GetToken();
  5335. }
  5336. // Find the first member
  5337. while (c)
  5338. {
  5339. int t = SyntaxStack0[synPtr];
  5340. c += (t == '(') - (t == ')') + (t == '{') - (t == '}');
  5341. if (c == 1 && t == tokMemberIdent)
  5342. break;
  5343. synPtr++;
  5344. }
  5345. while (tok != '}')
  5346. {
  5347. int c = 1;
  5348. int elementTypePtr, elementType;
  5349. unsigned elementOfs, elementSz;
  5350. elementOfs = SyntaxStack1[++synPtr];
  5351. elementTypePtr = ++synPtr;
  5352. elementType = SyntaxStack0[elementTypePtr];
  5353. elementSz = GetDeclSize(elementTypePtr, 0);
  5354. // Alignment
  5355. if (ofs < elementOfs)
  5356. GenZeroData(elementOfs - ofs, 0);
  5357. if (elementType == '[')
  5358. {
  5359. tok = InitArray(elementTypePtr, tok);
  5360. }
  5361. else if (elementType == tokStructPtr)
  5362. {
  5363. tok = InitStruct(elementTypePtr, tok);
  5364. }
  5365. else
  5366. {
  5367. tok = InitScalar(elementTypePtr, tok);
  5368. }
  5369. ofs = elementOfs + elementSz;
  5370. // Find the next member or the closing brace
  5371. while (c)
  5372. {
  5373. int t = SyntaxStack0[synPtr];
  5374. c += (t == '(') - (t == ')') + (t == '{') - (t == '}');
  5375. if (c == 1 && t == tokMemberIdent)
  5376. break;
  5377. synPtr++;
  5378. }
  5379. // Last member?
  5380. // Only one member (first) is initialized in unions explicitly
  5381. if ((!c) | isUnion)
  5382. {
  5383. if (braces & (tok == ','))
  5384. tok = GetToken();
  5385. break;
  5386. }
  5387. if (tok == ',')
  5388. tok = GetToken();
  5389. else if (tok != '}')
  5390. errorUnexpectedToken(tok);
  5391. }
  5392. if (braces)
  5393. {
  5394. if ((!ofs) | (tok != '}'))
  5395. errorUnexpectedToken(tok);
  5396. tok = GetToken();
  5397. }
  5398. // Implicit initialization of the rest and trailing padding
  5399. if (ofs < size)
  5400. GenZeroData(size - ofs, 0);
  5401. return tok;
  5402. }
  5403. STATIC
  5404. int compatCheck2(int lastSyntaxPtr, int i)
  5405. {
  5406. int res = 0;
  5407. int c = 0;
  5408. int t;
  5409. for (;;)
  5410. {
  5411. t = SyntaxStack0[lastSyntaxPtr];
  5412. if (t != SyntaxStack0[i])
  5413. {
  5414. if (SyntaxStack0[i] == ')' && SyntaxStack0[i - 1] == '(')
  5415. {
  5416. // Complete a previously incomplete parameter specification
  5417. int c1 = 1;
  5418. // Skip over the function params
  5419. do
  5420. {
  5421. t = SyntaxStack0[lastSyntaxPtr++];
  5422. c1 += (t == '(') - (t == ')');
  5423. } while (c1);
  5424. lastSyntaxPtr--;
  5425. }
  5426. else if (t == ')' &&
  5427. SyntaxStack0[i - 1] == '(' && SyntaxStack0[i] == tokIdent &&
  5428. SyntaxStack0[i + 1] == tokVoid && SyntaxStack0[i + 2] == ')')
  5429. {
  5430. // As an exception allow foo(void) to be redeclared as foo()
  5431. // since this happens very often in code.
  5432. // This weakens our redeclaration checks, however. Warn about it.
  5433. i += 2;
  5434. warning("Redeclaration from no parameters to unspecified parameters.\n");
  5435. }
  5436. else
  5437. goto lend;
  5438. }
  5439. if (t != tokIdent &&
  5440. SyntaxStack1[lastSyntaxPtr] != SyntaxStack1[i])
  5441. {
  5442. if (SyntaxStack0[lastSyntaxPtr - 1] == '[')
  5443. {
  5444. // Complete an incomplete array dimension or check for dimension mismatch
  5445. if (SyntaxStack1[lastSyntaxPtr] == 0)
  5446. SyntaxStack1[lastSyntaxPtr] = SyntaxStack1[i];
  5447. else if (SyntaxStack1[i])
  5448. goto lend;
  5449. }
  5450. else
  5451. goto lend;
  5452. }
  5453. c += (t == '(') - (t == ')') + (t == '[') - (t == ']');
  5454. if (!c)
  5455. {
  5456. switch (t)
  5457. {
  5458. case tokVoid:
  5459. case tokChar: case tokSChar: case tokUChar:
  5460. case tokShort: case tokUShort:
  5461. case tokInt: case tokUnsigned:
  5462. case tokStructPtr:
  5463. goto lok;
  5464. }
  5465. }
  5466. lastSyntaxPtr++;
  5467. i++;
  5468. }
  5469. lok:
  5470. res = 1;
  5471. lend:
  5472. return res;
  5473. }
  5474. STATIC
  5475. void CheckRedecl(int lastSyntaxPtr)
  5476. {
  5477. int tid, id, external = 0;
  5478. int i;
  5479. int curScopeOnly;
  5480. int level = ParseLevel;
  5481. tid = SyntaxStack0[lastSyntaxPtr];
  5482. id = SyntaxStack1[lastSyntaxPtr];
  5483. switch (tid)
  5484. {
  5485. case tokIdent:
  5486. switch (SyntaxStack0[lastSyntaxPtr + 1])
  5487. {
  5488. default:
  5489. external = 1;
  5490. // fallthrough
  5491. case tokLocalOfs: // block-scope auto
  5492. case tokIdent: // block-scope static
  5493. ;
  5494. }
  5495. // fallthrough
  5496. case tokTypedef:
  5497. break;
  5498. case tokMemberIdent:
  5499. {
  5500. int c = 1;
  5501. i = lastSyntaxPtr - 1;
  5502. do
  5503. {
  5504. int t = SyntaxStack0[i];
  5505. c -= (t == '(') - (t == ')') + (t == '{') - (t == '}');
  5506. if (c == 1 &&
  5507. t == tokMemberIdent && SyntaxStack1[i] == id &&
  5508. SyntaxStack0[i + 1] == tokLocalOfs)
  5509. errorRedecl(IdentTable + id);
  5510. i--;
  5511. } while (c);
  5512. }
  5513. return;
  5514. default:
  5515. errorInternal(23);
  5516. }
  5517. // limit search to current scope for typedef and enum,
  5518. // ditto for non-external declarations
  5519. curScopeOnly = tid != tokIdent || !external;
  5520. for (i = lastSyntaxPtr - 1; i >= 0; i--)
  5521. {
  5522. int t = SyntaxStack0[i];
  5523. switch (t)
  5524. {
  5525. case ')':
  5526. {
  5527. // Skip over the function params
  5528. int c = -1;
  5529. while (c)
  5530. {
  5531. t = SyntaxStack0[--i];
  5532. c += (t == '(') - (t == ')');
  5533. }
  5534. }
  5535. break;
  5536. case '#':
  5537. // the scope has changed to the outer scope
  5538. if (curScopeOnly)
  5539. return;
  5540. level--;
  5541. break;
  5542. case tokTypedef:
  5543. case tokIdent:
  5544. if (SyntaxStack1[i] == id)
  5545. {
  5546. if (level == ParseLevel)
  5547. {
  5548. // block scope:
  5549. // can differentiate between auto(tokLocalOfs), static(tokIdent),
  5550. // extern/proto(nothing) in SyntaxStack*[], hence dup checks and
  5551. // type match checks needed here
  5552. // file scope:
  5553. // can't differentiate between static(nothing), extern(nothing),
  5554. // neither(nothing) in SyntaxStack*[], but duplicate definitions
  5555. // are taken care of (in CG), hence only type match checks needed
  5556. // here
  5557. if (level) // block scope: check for bad dups
  5558. {
  5559. switch (SyntaxStack0[i + 1])
  5560. {
  5561. case tokLocalOfs: // block-scope auto
  5562. case tokIdent: // block-scope static
  5563. // auto and static can't be redefined in block scope
  5564. errorRedecl(IdentTable + id);
  5565. default:
  5566. // extern can't be redefined as non-extern in block scope
  5567. if (!external)
  5568. errorRedecl(IdentTable + id);
  5569. }
  5570. // extern/proto type match check follows
  5571. }
  5572. if (compatCheck2(lastSyntaxPtr, i))
  5573. return;
  5574. errorRedecl(IdentTable + id);
  5575. }
  5576. else // elseof if (level == ParseLevel)
  5577. {
  5578. // The new decl is extern/proto.
  5579. // Ignore typedef and enum
  5580. if (t == tokIdent)
  5581. {
  5582. switch (SyntaxStack0[i + 1])
  5583. {
  5584. case tokLocalOfs: // block-scope auto
  5585. case tokIdent: // block-scope static
  5586. // Ignore auto and static
  5587. break;
  5588. default:
  5589. // extern/proto
  5590. if (compatCheck2(lastSyntaxPtr, i))
  5591. return;
  5592. errorRedecl(IdentTable + id);
  5593. }
  5594. }
  5595. }
  5596. } // endof if (SyntaxStack1[i] == id)
  5597. break;
  5598. } // endof switch (t)
  5599. } // endof for (i = lastSyntaxPtr - 1; i >= 0; i--)
  5600. }
  5601. // DONE: support extern
  5602. // DONE: support static
  5603. // DONE: support basic initialization
  5604. // DONE: support simple non-array initializations with string literals
  5605. // DONE: support basic 1-d array initialization
  5606. // DONE: global/static data allocations
  5607. STATIC
  5608. int ParseDecl(int tok, unsigned structInfo[4], int cast, int label)
  5609. {
  5610. int base[2];
  5611. int lastSyntaxPtr;
  5612. int external = tok == tokExtern;
  5613. int Static = tok == tokStatic;
  5614. (void)label;
  5615. if (external |
  5616. Static)
  5617. {
  5618. tok = GetToken();
  5619. if (!TokenStartsDeclaration(tok, 1))
  5620. //error("ParseDecl(): unexpected token %s\n", GetTokenName(tok));
  5621. // Implicit int (as in "extern x; static y;") isn't supported
  5622. errorUnexpectedToken(tok);
  5623. }
  5624. tok = ParseBase(tok, base);
  5625. for (;;)
  5626. {
  5627. lastSyntaxPtr = SyntaxStackCnt;
  5628. /* derived type */
  5629. tok = ParseDerived(tok);
  5630. /* base type */
  5631. PushBase(base);
  5632. if ((tok && strchr(",;{=", tok)) || (tok == ')' && ExprLevel))
  5633. {
  5634. int isLocal = 0, isGlobal = 0, isFxn, isStruct, isArray, isIncompleteArr;
  5635. unsigned alignment = 0;
  5636. int staticLabel = 0;
  5637. // Disallow void variables
  5638. if (SyntaxStack0[SyntaxStackCnt - 1] == tokVoid)
  5639. {
  5640. if (SyntaxStack0[SyntaxStackCnt - 2] == tokIdent &&
  5641. !(cast
  5642. ))
  5643. //error("ParseDecl(): Cannot declare a variable ('%s') of type 'void'\n", IdentTable + SyntaxStack1[lastSyntaxPtr]);
  5644. errorUnexpectedVoid();
  5645. }
  5646. isFxn = SyntaxStack0[lastSyntaxPtr + 1] == '(';
  5647. isArray = SyntaxStack0[lastSyntaxPtr + 1] == '[';
  5648. isIncompleteArr = isArray && SyntaxStack1[lastSyntaxPtr + 2] == 0;
  5649. isStruct = SyntaxStack0[lastSyntaxPtr + 1] == tokStructPtr;
  5650. if (!(ExprLevel || structInfo) &&
  5651. !(external |
  5652. Static) &&
  5653. !strcmp(IdentTable + SyntaxStack1[lastSyntaxPtr], "<something>") &&
  5654. tok == ';')
  5655. {
  5656. if (isStruct)
  5657. {
  5658. // This is either an incomplete tagged structure/union declaration, e.g. "struct sometag;",
  5659. // or a tagged complete structure/union declaration, e.g. "struct sometag { ... };", without an instance variable,
  5660. // or an untagged complete structure/union declaration, e.g. "struct { ... };", without an instance variable
  5661. int declPtr, curScope;
  5662. int j = SyntaxStack1[lastSyntaxPtr + 1];
  5663. if (j + 2 < SyntaxStackCnt &&
  5664. IdentTable[SyntaxStack1[j + 1]] == '<' && // without tag
  5665. SyntaxStack0[j + 2] == tokSizeof) // but with the {} "body"
  5666. errorDecl();
  5667. // If a structure/union with this tag has been declared in an outer scope,
  5668. // this new declaration should override it
  5669. declPtr = FindTaggedDecl(IdentTable + SyntaxStack1[j + 1], lastSyntaxPtr - 1, &curScope);
  5670. if (declPtr >= 0 && !curScope)
  5671. {
  5672. // If that's the case, unbind this declaration from the old declaration
  5673. // and make it a new incomplete declaration
  5674. PushSyntax(SyntaxStack0[j]); // tokStruct or tokUnion
  5675. PushSyntax2(tokTag, SyntaxStack1[j + 1]);
  5676. SyntaxStack1[lastSyntaxPtr + 1] = SyntaxStackCnt - 2;
  5677. }
  5678. return GetToken();
  5679. }
  5680. }
  5681. // Structure/union members can't be initialized nor be functions nor
  5682. // be incompletely typed arrays inside structure/union declarations
  5683. if (structInfo && ((tok == '=') | isFxn | (tok == '{') | isIncompleteArr))
  5684. errorDecl();
  5685. // Error conditions in declarations(/definitions/initializations):
  5686. // Legend:
  5687. // + error
  5688. // - no error
  5689. //
  5690. // file scope fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  5691. // - - - - - + +
  5692. // file scope fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  5693. // + - - + - +
  5694. // file scope extern fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  5695. // - - - - - - -
  5696. // file scope extern fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  5697. // + + + + + +
  5698. // file scope static fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  5699. // - - - - - + +
  5700. // file scope static fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  5701. // + - - + - +
  5702. // fxn scope fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  5703. // - + - - - + +
  5704. // fxn scope fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  5705. // + - + + + +
  5706. // fxn scope extern fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  5707. // - + - - - - -
  5708. // fxn scope extern fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  5709. // + + + + + +
  5710. // fxn scope static fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  5711. // + + + + + + +
  5712. // fxn scope static fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  5713. // + + + + + +
  5714. if (isFxn & (tok == '='))
  5715. //error("ParseDecl(): cannot initialize a function\n");
  5716. errorInit();
  5717. if ((isFxn & (tok == '{')) && ParseLevel)
  5718. //error("ParseDecl(): cannot define a nested function\n");
  5719. errorDecl();
  5720. if ((isFxn & Static) && ParseLevel)
  5721. //error("ParseDecl(): cannot declare a static function in this scope\n");
  5722. errorDecl();
  5723. if (external & (tok == '='))
  5724. //error("ParseDecl(): cannot initialize an external variable\n");
  5725. errorInit();
  5726. if (isIncompleteArr & !(external |
  5727. (tok == '=')))
  5728. //error("ParseDecl(): cannot define an array of incomplete type\n");
  5729. errorDecl();
  5730. // TBD!!! de-uglify
  5731. if (!strcmp(IdentTable + SyntaxStack1[lastSyntaxPtr], "<something>"))
  5732. {
  5733. // Disallow nameless variables, prototypes, structure/union members and typedefs.
  5734. if (structInfo ||
  5735. !ExprLevel)
  5736. error("Identifier expected in declaration\n");
  5737. }
  5738. else
  5739. {
  5740. // Disallow named variables and prototypes in sizeof(typedecl) and (typedecl).
  5741. if (ExprLevel && !structInfo)
  5742. error("Identifier unexpected in declaration\n");
  5743. }
  5744. if (!isFxn
  5745. )
  5746. {
  5747. // This is a variable or a variable (member) in a struct/union declaration
  5748. int sz = GetDeclSize(lastSyntaxPtr, 0);
  5749. if (!((sz | isIncompleteArr) || ExprLevel)) // incomplete type
  5750. errorDecl(); // TBD!!! different error when struct/union tag is not found
  5751. if (isArray && !GetDeclSize(lastSyntaxPtr + 4, 0))
  5752. // incomplete type of array element (e.g. struct/union)
  5753. errorDecl();
  5754. alignment = GetDeclAlignment(lastSyntaxPtr);
  5755. if (structInfo)
  5756. {
  5757. // It's a variable (member) in a struct/union declaration
  5758. unsigned tmp;
  5759. unsigned newAlignment = alignment;
  5760. // Update structure/union alignment
  5761. if (structInfo[1] < newAlignment)
  5762. structInfo[1] = newAlignment;
  5763. // Align structure member
  5764. tmp = structInfo[2];
  5765. structInfo[2] = (structInfo[2] + newAlignment - 1) & ~(newAlignment - 1);
  5766. if (structInfo[2] < tmp || structInfo[2] != truncUint(structInfo[2]))
  5767. errorVarSize();
  5768. // Change tokIdent to tokMemberIdent and insert a local var offset token
  5769. SyntaxStack0[lastSyntaxPtr] = tokMemberIdent;
  5770. InsertSyntax2(lastSyntaxPtr + 1, tokLocalOfs, (int)structInfo[2]);
  5771. // Advance member offset for structures, keep it zero for unions
  5772. if (structInfo[0] == tokStruct)
  5773. {
  5774. tmp = structInfo[2];
  5775. structInfo[2] += sz;
  5776. if (structInfo[2] < tmp || structInfo[2] != truncUint(structInfo[2]))
  5777. errorVarSize();
  5778. }
  5779. // Update max member size for unions
  5780. else if (structInfo[3] < (unsigned)sz)
  5781. {
  5782. structInfo[3] = sz;
  5783. }
  5784. }
  5785. else if (ParseLevel && !((external | Static) || ExprLevel))
  5786. {
  5787. // It's a local variable
  5788. isLocal = 1;
  5789. // Defer size calculation until initialization
  5790. // Insert a local var offset token, the offset is to be updated
  5791. InsertSyntax2(lastSyntaxPtr + 1, tokLocalOfs, 0);
  5792. }
  5793. else if (!ExprLevel)
  5794. {
  5795. // It's a global variable (external, static or neither)
  5796. isGlobal = 1;
  5797. if (Static && ParseLevel)
  5798. {
  5799. // It's a static variable in function scope, "rename" it by providing
  5800. // an alternative unique numeric identifier right next to it and use it
  5801. staticLabel = LabelCnt++;
  5802. InsertSyntax2(lastSyntaxPtr + 1, tokIdent, AddNumericIdent(staticLabel));
  5803. }
  5804. }
  5805. }
  5806. // If it's a type declaration in a sizeof(typedecl) expression or
  5807. // in an expression with a cast, e.g. (typedecl)expr, we're done
  5808. if (ExprLevel && !structInfo)
  5809. {
  5810. DumpDecl(lastSyntaxPtr, 0);
  5811. return tok;
  5812. }
  5813. if (isLocal | isGlobal)
  5814. {
  5815. int hasInit = tok == '=';
  5816. int needsGlobalInit = isGlobal & !external;
  5817. int sz = GetDeclSize(lastSyntaxPtr, 0);
  5818. int initLabel = 0;
  5819. int bss = (!hasInit) & UseBss;
  5820. if (isGlobal)
  5821. DumpDecl(lastSyntaxPtr, 0);
  5822. if (hasInit)
  5823. {
  5824. tok = GetToken();
  5825. }
  5826. if (isLocal & hasInit)
  5827. needsGlobalInit = isArray | (isStruct & (tok == '{'));
  5828. if (needsGlobalInit)
  5829. {
  5830. char** oldHeaderFooter = CurHeaderFooter;
  5831. if (oldHeaderFooter)
  5832. puts2(oldHeaderFooter[1]);
  5833. CurHeaderFooter = bss ? BssHeaderFooter : DataHeaderFooter;
  5834. puts2(CurHeaderFooter[0]);
  5835. // DONE: imperfect condition for alignment
  5836. if (alignment != 1)
  5837. GenWordAlignment(bss);
  5838. if (isGlobal)
  5839. {
  5840. if (Static && ParseLevel)
  5841. GenNumLabel(staticLabel);
  5842. else
  5843. GenLabel(IdentTable + SyntaxStack1[lastSyntaxPtr], Static);
  5844. }
  5845. else
  5846. {
  5847. // Generate numeric labels for global initializers of local vars
  5848. GenNumLabel(initLabel = LabelCnt++);
  5849. }
  5850. // Generate global initializers
  5851. if (hasInit)
  5852. {
  5853. if (isGlobal)
  5854. {
  5855. GenStartCommentLine(); printf2("=\n");
  5856. }
  5857. tok = InitVar(lastSyntaxPtr, tok);
  5858. // Update the size in case it's an incomplete array
  5859. sz = GetDeclSize(lastSyntaxPtr, 0);
  5860. }
  5861. else
  5862. {
  5863. GenZeroData(sz, bss);
  5864. }
  5865. puts2(CurHeaderFooter[1]);
  5866. if (oldHeaderFooter)
  5867. puts2(oldHeaderFooter[0]);
  5868. CurHeaderFooter = oldHeaderFooter;
  5869. }
  5870. if (isLocal)
  5871. {
  5872. // Now that the size of the local is certainly known,
  5873. // update its offset in the offset token
  5874. SyntaxStack1[lastSyntaxPtr + 1] = AllocLocal(sz);
  5875. DumpDecl(lastSyntaxPtr, 0);
  5876. }
  5877. // Copy global initializers into local vars
  5878. if (isLocal & needsGlobalInit)
  5879. {
  5880. GenStartCommentLine(); printf2("=\n");
  5881. if (!StructCpyLabel)
  5882. StructCpyLabel = LabelCnt++;
  5883. sp = 0;
  5884. push2('(', SizeOfWord * 3);
  5885. push2(tokLocalOfs, SyntaxStack1[lastSyntaxPtr + 1]);
  5886. push(',');
  5887. push2(tokIdent, AddNumericIdent(initLabel));
  5888. push(',');
  5889. push2(tokNumUint, sz);
  5890. push(',');
  5891. push2(tokIdent, AddNumericIdent(StructCpyLabel));
  5892. push2(')', SizeOfWord * 3);
  5893. GenExpr();
  5894. }
  5895. // Initialize local vars with expressions
  5896. else if (hasInit & !needsGlobalInit)
  5897. {
  5898. int gotUnary, synPtr, constExpr, exprVal;
  5899. int brace = 0;
  5900. // Initializers for scalars can be optionally enclosed in braces
  5901. if ((!isStruct) & (tok == '{'))
  5902. {
  5903. brace = 1;
  5904. tok = GetToken();
  5905. }
  5906. // ParseExpr() will transform the initializer expression into an assignment expression here
  5907. tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, '=', SyntaxStack1[lastSyntaxPtr]);
  5908. if (!gotUnary)
  5909. errorUnexpectedToken(tok);
  5910. if (brace)
  5911. {
  5912. if (tok != '}')
  5913. errorUnexpectedToken(tok);
  5914. tok = GetToken();
  5915. }
  5916. if (!isStruct)
  5917. {
  5918. // This is a special case for initialization of integers smaller than int.
  5919. // Since a local integer variable always takes as much space as a whole int,
  5920. // we can optimize code generation a bit by storing the initializer as an int.
  5921. // This is an old accidental optimization and I preserve it for now.
  5922. // Note, this implies a little-endian CPU.
  5923. stack[sp - 1][1] = SizeOfWord;
  5924. }
  5925. // Storage of string literal data from the initializing expression
  5926. // occurs here.
  5927. GenExpr();
  5928. }
  5929. }
  5930. else if (tok == '{')
  5931. {
  5932. // It's a function body. Let's add function parameters as
  5933. // local variables to the symbol table and parse the body.
  5934. int undoSymbolsPtr = SyntaxStackCnt;
  5935. int undoIdents = IdentTableLen;
  5936. int i;
  5937. int endLabel = 0;
  5938. DumpDecl(lastSyntaxPtr, 0);
  5939. CurFxnName = IdentTable + SyntaxStack1[lastSyntaxPtr];
  5940. IsMain = !strcmp(CurFxnName, "main");
  5941. gotoLabCnt = 0;
  5942. if (verbose)
  5943. printf("%s()\n", CurFxnName);
  5944. ParseLevel++;
  5945. GetFxnInfo(lastSyntaxPtr, &CurFxnParamCntMin, &CurFxnParamCntMax, &CurFxnReturnExprTypeSynPtr, NULL); // get return type
  5946. CurHeaderFooter = CodeHeaderFooter;
  5947. puts2(CurHeaderFooter[0]);
  5948. GenLabel(CurFxnName, Static);
  5949. GenFxnProlog();
  5950. CurFxnEpilogLabel = LabelCnt++;
  5951. // A new scope begins before the function parameters
  5952. PushSyntax('#');
  5953. AddFxnParamSymbols(lastSyntaxPtr);
  5954. // The block doesn't begin yet another new scope.
  5955. // This is to catch redeclarations of the function parameters.
  5956. tok = ParseBlock(BrkCntTargetFxn, 0);
  5957. ParseLevel--;
  5958. if (tok != '}')
  5959. //error("ParseDecl(): '}' expected\n");
  5960. errorUnexpectedToken(tok);
  5961. for (i = 0; i < gotoLabCnt; i++)
  5962. if (gotoLabStat[i] == 2)
  5963. error("Undeclared label '%s'\n", IdentTable + gotoLabels[i][0]);
  5964. // DONE: if execution of main() reaches here, before the epilog (i.e. without using return),
  5965. // main() should return 0.
  5966. if (IsMain)
  5967. {
  5968. sp = 0;
  5969. push(tokNumInt);
  5970. push(tokReturn); // value produced by generated code is used
  5971. GenExpr();
  5972. }
  5973. GenNumLabel(CurFxnEpilogLabel);
  5974. GenFxnEpilog();
  5975. if (GenFxnSizeNeeded())
  5976. GenNumLabel(endLabel = LabelCnt++);
  5977. puts2(CurHeaderFooter[1]);
  5978. CurHeaderFooter = NULL;
  5979. if (GenFxnSizeNeeded())
  5980. GenRecordFxnSize(CurFxnName, endLabel);
  5981. CurFxnName = NULL;
  5982. IdentTableLen = undoIdents; // remove all identifier names
  5983. SyntaxStackCnt = undoSymbolsPtr; // remove all params and locals
  5984. SyntaxStack1[SymFuncPtr] = DummyIdent;
  5985. }
  5986. else if (isFxn)
  5987. {
  5988. // function prototype
  5989. DumpDecl(lastSyntaxPtr, 0);
  5990. }
  5991. CheckRedecl(lastSyntaxPtr);
  5992. if ((tok == ';') | (tok == '}'))
  5993. break;
  5994. tok = GetToken();
  5995. continue;
  5996. }
  5997. //error("ParseDecl(): unexpected token %s\n", GetTokenName(tok));
  5998. errorUnexpectedToken(tok);
  5999. }
  6000. tok = GetToken();
  6001. return tok;
  6002. }
  6003. STATIC
  6004. void ParseFxnParams(int tok)
  6005. {
  6006. int base[2];
  6007. int lastSyntaxPtr;
  6008. int cnt = 0;
  6009. int ellCnt = 0;
  6010. for (;;)
  6011. {
  6012. lastSyntaxPtr = SyntaxStackCnt;
  6013. if (tok == ')') /* unspecified params */
  6014. break;
  6015. if (!TokenStartsDeclaration(tok, 1))
  6016. {
  6017. if (tok == tokEllipsis)
  6018. {
  6019. // "..." cannot be the first parameter and
  6020. // it can be only one
  6021. if (!cnt || ellCnt)
  6022. //error("ParseFxnParams(): '...' unexpected here\n");
  6023. errorUnexpectedToken(tok);
  6024. ellCnt++;
  6025. }
  6026. else
  6027. //error("ParseFxnParams(): Unexpected token %s\n", GetTokenName(tok));
  6028. errorUnexpectedToken(tok);
  6029. base[0] = tok; // "..."
  6030. base[1] = 0;
  6031. PushSyntax2(tokIdent, AddIdent("<something>"));
  6032. tok = GetToken();
  6033. }
  6034. else
  6035. {
  6036. if (ellCnt)
  6037. //error("ParseFxnParams(): '...' must be the last in the parameter list\n");
  6038. errorUnexpectedToken(tok);
  6039. /* base type */
  6040. tok = ParseBase(tok, base);
  6041. /* derived type */
  6042. tok = ParseDerived(tok);
  6043. }
  6044. /* base type */
  6045. PushBase(base);
  6046. /* Decay arrays to pointers */
  6047. lastSyntaxPtr++; /* skip name */
  6048. if (SyntaxStack0[lastSyntaxPtr] == '[')
  6049. {
  6050. int t;
  6051. DeleteSyntax(lastSyntaxPtr, 1);
  6052. t = SyntaxStack0[lastSyntaxPtr];
  6053. if (t == tokNumInt || t == tokNumUint)
  6054. DeleteSyntax(lastSyntaxPtr, 1);
  6055. SyntaxStack0[lastSyntaxPtr] = '*';
  6056. }
  6057. /* "(Un)decay" functions to function pointers */
  6058. else if (SyntaxStack0[lastSyntaxPtr] == '(')
  6059. {
  6060. InsertSyntax(lastSyntaxPtr, '*');
  6061. }
  6062. lastSyntaxPtr--; /* "unskip" name */
  6063. cnt++;
  6064. if (tok == ')' || tok == ',')
  6065. {
  6066. int t = SyntaxStack0[SyntaxStackCnt - 2];
  6067. if (SyntaxStack0[SyntaxStackCnt - 1] == tokVoid)
  6068. {
  6069. // Disallow void variables. TBD!!! de-uglify
  6070. if (t == tokIdent &&
  6071. !(!strcmp(IdentTable + SyntaxStack1[SyntaxStackCnt - 2], "<something>") &&
  6072. cnt == 1 && tok == ')'))
  6073. //error("ParseFxnParams(): Cannot declare a variable ('%s') of type 'void'\n", IdentTable + SyntaxStack1[lastSyntaxPtr]);
  6074. errorUnexpectedVoid();
  6075. }
  6076. if (tok == ')')
  6077. break;
  6078. tok = GetToken();
  6079. continue;
  6080. }
  6081. //error("ParseFxnParams(): Unexpected token %s\n", GetTokenName(tok));
  6082. errorUnexpectedToken(tok);
  6083. }
  6084. }
  6085. STATIC
  6086. void AddFxnParamSymbols(int SyntaxPtr)
  6087. {
  6088. int i;
  6089. unsigned paramOfs = 2 * SizeOfWord; // ret addr, xbp
  6090. if (SyntaxPtr < 0 ||
  6091. SyntaxPtr > SyntaxStackCnt - 3 ||
  6092. SyntaxStack0[SyntaxPtr] != tokIdent ||
  6093. SyntaxStack0[SyntaxPtr + 1] != '(')
  6094. //error("Internal error: AddFxnParamSymbols(): Invalid input\n");
  6095. errorInternal(6);
  6096. CurFxnSyntaxPtr = SyntaxPtr;
  6097. CurFxnLocalOfs = 0;
  6098. CurFxnMinLocalOfs = 0;
  6099. SyntaxPtr += 2; // skip "ident("
  6100. for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
  6101. {
  6102. int tok = SyntaxStack0[i];
  6103. if (tok == tokIdent)
  6104. {
  6105. unsigned sz;
  6106. int paramPtr;
  6107. if (i + 1 >= SyntaxStackCnt)
  6108. //error("Internal error: AddFxnParamSymbols(): Invalid input\n");
  6109. errorInternal(7);
  6110. if (SyntaxStack0[i + 1] == tokVoid) // "ident(void)" = no params
  6111. break;
  6112. if (SyntaxStack0[i + 1] == tokEllipsis) // "ident(something,...)" = no more params
  6113. break;
  6114. // Make sure the parameter is not an incomplete structure
  6115. sz = GetDeclSize(i, 0);
  6116. if (sz == 0)
  6117. //error("Internal error: AddFxnParamSymbols(): GetDeclSize() = 0\n");
  6118. //errorInternal(8);
  6119. errorDecl();
  6120. // Let's calculate this parameter's relative on-stack location
  6121. paramPtr = SyntaxStackCnt;
  6122. PushSyntax2(SyntaxStack0[i], SyntaxStack1[i]);
  6123. PushSyntax2(tokLocalOfs, paramOfs);
  6124. if (sz + SizeOfWord - 1 < sz)
  6125. errorVarSize();
  6126. sz = (sz + SizeOfWord - 1) & ~(SizeOfWord - 1u);
  6127. if (paramOfs + sz < paramOfs)
  6128. errorVarSize();
  6129. paramOfs += sz;
  6130. if (paramOfs > (unsigned)GenMaxLocalsSize())
  6131. errorVarSize();
  6132. // Duplicate this parameter in the symbol table
  6133. i++;
  6134. while (i < SyntaxStackCnt)
  6135. {
  6136. tok = SyntaxStack0[i];
  6137. if (tok == tokIdent || tok == ')')
  6138. {
  6139. DumpDecl(paramPtr, 0);
  6140. if (IdentTable[SyntaxStack1[paramPtr]] == '<')
  6141. error("Parameter name expected\n");
  6142. CheckRedecl(paramPtr);
  6143. i--;
  6144. break;
  6145. }
  6146. else if (tok == '(')
  6147. {
  6148. int c = 1;
  6149. i++;
  6150. PushSyntax(tok);
  6151. while (c && i < SyntaxStackCnt)
  6152. {
  6153. tok = SyntaxStack0[i];
  6154. c += (tok == '(') - (tok == ')');
  6155. PushSyntax2(SyntaxStack0[i], SyntaxStack1[i]);
  6156. i++;
  6157. }
  6158. }
  6159. else
  6160. {
  6161. PushSyntax2(SyntaxStack0[i], SyntaxStack1[i]);
  6162. i++;
  6163. }
  6164. }
  6165. }
  6166. else if (tok == ')') // endof "ident(" ... ")"
  6167. break;
  6168. else
  6169. //error("Internal error: AddFxnParamSymbols(): Unexpected token %s\n", GetTokenName(tok));
  6170. errorInternal(9);
  6171. }
  6172. }
  6173. STATIC
  6174. int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx)
  6175. {
  6176. /*
  6177. labeled statements:
  6178. + ident : statement
  6179. + case const-expr : statement
  6180. + default : statement
  6181. compound statement:
  6182. + { declaration(s)/statement(s)-opt }
  6183. expression statement:
  6184. + expression-opt ;
  6185. selection statements:
  6186. + if ( expression ) statement
  6187. + if ( expression ) statement else statement
  6188. + switch ( expression ) { statement(s)-opt }
  6189. iteration statements:
  6190. + while ( expression ) statement
  6191. + do statement while ( expression ) ;
  6192. + for ( expression-opt ; expression-opt ; expression-opt ) statement
  6193. jump statements:
  6194. + goto ident ;
  6195. + continue ;
  6196. + break ;
  6197. + return expression-opt ;
  6198. */
  6199. int gotUnary, synPtr, constExpr, exprVal;
  6200. int brkCntTarget[2];
  6201. int statementNeeded;
  6202. do
  6203. {
  6204. statementNeeded = 0;
  6205. if (tok == ';')
  6206. {
  6207. tok = GetToken();
  6208. }
  6209. else if (tok == '{')
  6210. {
  6211. // A new {} block begins in the function body
  6212. int undoSymbolsPtr = SyntaxStackCnt;
  6213. int undoLocalOfs = CurFxnLocalOfs;
  6214. int undoIdents = IdentTableLen;
  6215. GenStartCommentLine(); printf2("{\n");
  6216. ParseLevel++;
  6217. tok = ParseBlock(BrkCntTarget, casesIdx);
  6218. ParseLevel--;
  6219. if (tok != '}')
  6220. //error("ParseStatement(): '}' expected. Unexpected token %s\n", GetTokenName(tok));
  6221. errorUnexpectedToken(tok);
  6222. UndoNonLabelIdents(undoIdents); // remove all identifier names, except those of labels
  6223. SyntaxStackCnt = undoSymbolsPtr; // remove all params and locals
  6224. CurFxnLocalOfs = undoLocalOfs; // destroy on-stack local variables
  6225. GenStartCommentLine(); printf2("}\n");
  6226. tok = GetToken();
  6227. }
  6228. else if (tok == tokReturn)
  6229. {
  6230. // DONE: functions returning void vs non-void
  6231. int retVoid = CurFxnReturnExprTypeSynPtr >= 0 &&
  6232. SyntaxStack0[CurFxnReturnExprTypeSynPtr] == tokVoid;
  6233. GenStartCommentLine(); printf2("return\n");
  6234. tok = GetToken();
  6235. if (tok == ';')
  6236. {
  6237. gotUnary = 0;
  6238. if (!retVoid)
  6239. //error("ParseStatement(): missing return value\n");
  6240. errorUnexpectedToken(tok);
  6241. }
  6242. else
  6243. {
  6244. if (retVoid)
  6245. //error("Error: ParseStatement(): cannot return a value from a function returning 'void'\n");
  6246. errorUnexpectedToken(tok);
  6247. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ';')
  6248. //error("ParseStatement(): ';' expected\n");
  6249. errorUnexpectedToken(tok);
  6250. if (gotUnary)
  6251. //error("ParseStatement(): cannot return a value of type 'void'\n");
  6252. // Bar void
  6253. nonVoidTypeCheck(synPtr);
  6254. }
  6255. if (gotUnary)
  6256. {
  6257. decayArray(&synPtr, 0);
  6258. {
  6259. int castSize = GetDeclSize(CurFxnReturnExprTypeSynPtr, 1);
  6260. // If return value (per function declaration) is a scalar type smaller than machine word,
  6261. // properly zero- or sign-extend the returned value to machine word size.
  6262. // TBD??? Move this cast to the caller?
  6263. if (castSize != SizeOfWord && castSize != GetDeclSize(synPtr, 1))
  6264. {
  6265. if (constExpr)
  6266. {
  6267. switch (castSize)
  6268. {
  6269. case 1:
  6270. exprVal &= 0xFFu;
  6271. break;
  6272. case -1:
  6273. if ((exprVal &= 0xFFu) >= 0x80)
  6274. exprVal -= 0x100;
  6275. break;
  6276. case 2:
  6277. exprVal &= 0xFFFFu;
  6278. break;
  6279. case -2:
  6280. if ((exprVal &= 0xFFFFu) >= 0x8000)
  6281. exprVal -= 0x10000;
  6282. break;
  6283. }
  6284. }
  6285. else
  6286. {
  6287. switch (castSize)
  6288. {
  6289. case 1:
  6290. push(tokUChar);
  6291. break;
  6292. case -1:
  6293. push(tokSChar);
  6294. break;
  6295. case 2:
  6296. push(tokUShort);
  6297. break;
  6298. case -2:
  6299. push(tokShort);
  6300. break;
  6301. }
  6302. }
  6303. }
  6304. }
  6305. if (constExpr)
  6306. stack[0][1] = exprVal;
  6307. push(tokReturn); // value produced by generated code is used
  6308. GenExpr();
  6309. }
  6310. tok = GetToken();
  6311. // If this return is the last statement in the function, the epilogue immediately
  6312. // follows and there's no need to jump to it.
  6313. if (!(tok == '}' && ParseLevel == 1 && !IsMain))
  6314. GenJumpUncond(CurFxnEpilogLabel);
  6315. }
  6316. else if (tok == tokWhile)
  6317. {
  6318. int labelBefore = LabelCnt++;
  6319. int labelAfter = LabelCnt++;
  6320. int forever = 0;
  6321. GenStartCommentLine(); printf2("while\n");
  6322. tok = GetToken();
  6323. if (tok != '(')
  6324. //error("ParseStatement(): '(' expected after 'while'\n");
  6325. errorUnexpectedToken(tok);
  6326. tok = GetToken();
  6327. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  6328. //error("ParseStatement(): ')' expected after 'while ( expression'\n");
  6329. errorUnexpectedToken(tok);
  6330. if (!gotUnary)
  6331. //error("ParseStatement(): expression expected in 'while ( expression )'\n");
  6332. errorUnexpectedToken(tok);
  6333. // DONE: void control expressions
  6334. //error("ParseStatement(): unexpected 'void' expression in 'while ( expression )'\n");
  6335. // Bar void and struct/union
  6336. scalarTypeCheck(synPtr);
  6337. GenNumLabel(labelBefore);
  6338. if (constExpr)
  6339. {
  6340. // Special cases for while(0) and while(1)
  6341. if (!(forever = truncInt(exprVal)))
  6342. GenJumpUncond(labelAfter);
  6343. }
  6344. else
  6345. {
  6346. switch (stack[sp - 1][0])
  6347. {
  6348. case '<':
  6349. case '>':
  6350. case tokEQ:
  6351. case tokNEQ:
  6352. case tokLEQ:
  6353. case tokGEQ:
  6354. case tokULess:
  6355. case tokUGreater:
  6356. case tokULEQ:
  6357. case tokUGEQ:
  6358. push2(tokIfNot, labelAfter);
  6359. GenExpr();
  6360. break;
  6361. default:
  6362. push(tokReturn); // value produced by generated code is used
  6363. GenExpr();
  6364. GenJumpIfZero(labelAfter);
  6365. break;
  6366. }
  6367. }
  6368. tok = GetToken();
  6369. brkCntTarget[0] = labelAfter; // break target
  6370. brkCntTarget[1] = labelBefore; // continue target
  6371. tok = ParseStatement(tok, brkCntTarget, casesIdx);
  6372. // Special case for while(0)
  6373. if (!(constExpr && !forever))
  6374. GenJumpUncond(labelBefore);
  6375. GenNumLabel(labelAfter);
  6376. }
  6377. else if (tok == tokDo)
  6378. {
  6379. int labelBefore = LabelCnt++;
  6380. int labelWhile = LabelCnt++;
  6381. int labelAfter = LabelCnt++;
  6382. GenStartCommentLine(); printf2("do\n");
  6383. GenNumLabel(labelBefore);
  6384. tok = GetToken();
  6385. brkCntTarget[0] = labelAfter; // break target
  6386. brkCntTarget[1] = labelWhile; // continue target
  6387. tok = ParseStatement(tok, brkCntTarget, casesIdx);
  6388. if (tok != tokWhile)
  6389. //error("ParseStatement(): 'while' expected after 'do statement'\n");
  6390. errorUnexpectedToken(tok);
  6391. GenStartCommentLine(); printf2("while\n");
  6392. tok = GetToken();
  6393. if (tok != '(')
  6394. //error("ParseStatement(): '(' expected after 'while'\n");
  6395. errorUnexpectedToken(tok);
  6396. tok = GetToken();
  6397. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  6398. //error("ParseStatement(): ')' expected after 'while ( expression'\n");
  6399. errorUnexpectedToken(tok);
  6400. if (!gotUnary)
  6401. //error("ParseStatement(): expression expected in 'while ( expression )'\n");
  6402. errorUnexpectedToken(tok);
  6403. tok = GetToken();
  6404. if (tok != ';')
  6405. //error("ParseStatement(): ';' expected after 'do statement while ( expression )'\n");
  6406. errorUnexpectedToken(tok);
  6407. // DONE: void control expressions
  6408. //error("ParseStatement(): unexpected 'void' expression in 'while ( expression )'\n");
  6409. // Bar void and struct/union
  6410. scalarTypeCheck(synPtr);
  6411. GenNumLabel(labelWhile);
  6412. if (constExpr)
  6413. {
  6414. // Special cases for while(0) and while(1)
  6415. if (truncInt(exprVal))
  6416. GenJumpUncond(labelBefore);
  6417. }
  6418. else
  6419. {
  6420. switch (stack[sp - 1][0])
  6421. {
  6422. case '<':
  6423. case '>':
  6424. case tokEQ:
  6425. case tokNEQ:
  6426. case tokLEQ:
  6427. case tokGEQ:
  6428. case tokULess:
  6429. case tokUGreater:
  6430. case tokULEQ:
  6431. case tokUGEQ:
  6432. push2(tokIf, labelBefore);
  6433. GenExpr();
  6434. break;
  6435. default:
  6436. push(tokReturn); // value produced by generated code is used
  6437. GenExpr();
  6438. GenJumpIfNotZero(labelBefore);
  6439. break;
  6440. }
  6441. }
  6442. GenNumLabel(labelAfter);
  6443. tok = GetToken();
  6444. }
  6445. else if (tok == tokIf)
  6446. {
  6447. int labelAfterIf = LabelCnt++;
  6448. int labelAfterElse = LabelCnt++;
  6449. GenStartCommentLine(); printf2("if\n");
  6450. tok = GetToken();
  6451. if (tok != '(')
  6452. //error("ParseStatement(): '(' expected after 'if'\n");
  6453. errorUnexpectedToken(tok);
  6454. tok = GetToken();
  6455. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  6456. //error("ParseStatement(): ')' expected after 'if ( expression'\n");
  6457. errorUnexpectedToken(tok);
  6458. if (!gotUnary)
  6459. //error("ParseStatement(): expression expected in 'if ( expression )'\n");
  6460. errorUnexpectedToken(tok);
  6461. // DONE: void control expressions
  6462. //error("ParseStatement(): unexpected 'void' expression in 'if ( expression )'\n");
  6463. // Bar void and struct/union
  6464. scalarTypeCheck(synPtr);
  6465. if (constExpr)
  6466. {
  6467. // Special cases for if(0) and if(1)
  6468. if (!truncInt(exprVal))
  6469. GenJumpUncond(labelAfterIf);
  6470. }
  6471. else
  6472. {
  6473. switch (stack[sp - 1][0])
  6474. {
  6475. case '<':
  6476. case '>':
  6477. case tokEQ:
  6478. case tokNEQ:
  6479. case tokLEQ:
  6480. case tokGEQ:
  6481. case tokULess:
  6482. case tokUGreater:
  6483. case tokULEQ:
  6484. case tokUGEQ:
  6485. push2(tokIfNot, labelAfterIf);
  6486. GenExpr();
  6487. break;
  6488. default:
  6489. push(tokReturn); // value produced by generated code is used
  6490. GenExpr();
  6491. GenJumpIfZero(labelAfterIf);
  6492. break;
  6493. }
  6494. }
  6495. tok = GetToken();
  6496. tok = ParseStatement(tok, BrkCntTarget, casesIdx);
  6497. // DONE: else
  6498. if (tok == tokElse)
  6499. {
  6500. GenJumpUncond(labelAfterElse);
  6501. GenNumLabel(labelAfterIf);
  6502. GenStartCommentLine(); printf2("else\n");
  6503. tok = GetToken();
  6504. tok = ParseStatement(tok, BrkCntTarget, casesIdx);
  6505. GenNumLabel(labelAfterElse);
  6506. }
  6507. else
  6508. {
  6509. GenNumLabel(labelAfterIf);
  6510. }
  6511. }
  6512. else if (tok == tokFor)
  6513. {
  6514. int labelBefore = LabelCnt++;
  6515. int labelExpr3 = LabelCnt++;
  6516. int labelBody = LabelCnt++;
  6517. int labelAfter = LabelCnt++;
  6518. int cond = -1;
  6519. static int expr3Stack[STACK_SIZE >> 1][2];
  6520. static int expr3Sp;
  6521. GenStartCommentLine(); printf2("for\n");
  6522. tok = GetToken();
  6523. if (tok != '(')
  6524. //error("ParseStatement(): '(' expected after 'for'\n");
  6525. errorUnexpectedToken(tok);
  6526. tok = GetToken();
  6527. {
  6528. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ';')
  6529. //error("ParseStatement(): ';' expected after 'for ( expression'\n");
  6530. errorUnexpectedToken(tok);
  6531. if (gotUnary)
  6532. {
  6533. GenExpr();
  6534. }
  6535. tok = GetToken();
  6536. }
  6537. GenNumLabel(labelBefore);
  6538. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ';')
  6539. //error("ParseStatement(): ';' expected after 'for ( expression ; expression'\n");
  6540. errorUnexpectedToken(tok);
  6541. if (gotUnary)
  6542. {
  6543. // DONE: void control expressions
  6544. //error("ParseStatement(): unexpected 'void' expression in 'for ( ; expression ; )'\n");
  6545. // Bar void and struct/union
  6546. scalarTypeCheck(synPtr);
  6547. if (constExpr)
  6548. {
  6549. // Special cases for for(...; 0; ...) and for(...; 1; ...)
  6550. cond = truncInt(exprVal) != 0;
  6551. }
  6552. else
  6553. {
  6554. switch (stack[sp - 1][0])
  6555. {
  6556. case '<':
  6557. case '>':
  6558. case tokEQ:
  6559. case tokNEQ:
  6560. case tokLEQ:
  6561. case tokGEQ:
  6562. case tokULess:
  6563. case tokUGreater:
  6564. case tokULEQ:
  6565. case tokUGEQ:
  6566. push2(tokIfNot, labelAfter);
  6567. GenExpr();
  6568. break;
  6569. default:
  6570. push(tokReturn); // value produced by generated code is used
  6571. GenExpr();
  6572. GenJumpIfZero(labelAfter);
  6573. break;
  6574. }
  6575. }
  6576. }
  6577. else
  6578. {
  6579. // Special case for for(...; ; ...)
  6580. cond = 1;
  6581. }
  6582. if (!cond)
  6583. // Special case for for(...; 0; ...)
  6584. GenJumpUncond(labelAfter);
  6585. tok = GetToken();
  6586. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  6587. //error("ParseStatement(): ')' expected after 'for ( expression ; expression ; expression'\n");
  6588. errorUnexpectedToken(tok);
  6589. // Try to reorder expr3 with body to reduce the number of jumps, favor small expr3's
  6590. if (gotUnary && sp <= 16 && (unsigned)sp <= division(sizeof expr3Stack , sizeof expr3Stack[0]) - expr3Sp)
  6591. {
  6592. int cnt = sp;
  6593. // Stash the stack containing expr3
  6594. memcpy(expr3Stack + expr3Sp, stack, cnt * sizeof stack[0]);
  6595. expr3Sp += cnt;
  6596. // Body
  6597. tok = GetToken();
  6598. brkCntTarget[0] = labelAfter; // break target
  6599. brkCntTarget[1] = labelExpr3; // continue target
  6600. tok = ParseStatement(tok, brkCntTarget, casesIdx);
  6601. // Unstash expr3 and generate code for it
  6602. expr3Sp -= cnt;
  6603. memcpy(stack, expr3Stack + expr3Sp, cnt * sizeof stack[0]);
  6604. sp = cnt;
  6605. GenNumLabel(labelExpr3);
  6606. GenExpr();
  6607. // Special case for for(...; 0; ...)
  6608. if (cond)
  6609. GenJumpUncond(labelBefore);
  6610. }
  6611. else
  6612. {
  6613. if (gotUnary)
  6614. {
  6615. GenJumpUncond(labelBody);
  6616. // expr3
  6617. GenNumLabel(labelExpr3);
  6618. GenExpr();
  6619. GenJumpUncond(labelBefore);
  6620. GenNumLabel(labelBody);
  6621. }
  6622. // Body
  6623. tok = GetToken();
  6624. brkCntTarget[0] = labelAfter; // break target
  6625. brkCntTarget[1] = gotUnary ? labelExpr3 : (cond ? labelBefore : labelAfter); // continue target
  6626. tok = ParseStatement(tok, brkCntTarget, casesIdx);
  6627. // Special case for for(...; 0; ...)
  6628. if (brkCntTarget[1] != labelAfter)
  6629. GenJumpUncond(brkCntTarget[1]);
  6630. }
  6631. GenNumLabel(labelAfter);
  6632. }
  6633. else if (tok == tokBreak)
  6634. {
  6635. GenStartCommentLine(); printf2("break\n");
  6636. if ((tok = GetToken()) != ';')
  6637. //error("ParseStatement(): ';' expected\n");
  6638. errorUnexpectedToken(tok);
  6639. tok = GetToken();
  6640. if (BrkCntTarget == NULL)
  6641. //error("ParseStatement(): 'break' must be within 'while', 'for' or 'switch' statement\n");
  6642. errorCtrlOutOfScope();
  6643. GenJumpUncond(BrkCntTarget[0]);
  6644. }
  6645. else if (tok == tokCont)
  6646. {
  6647. GenStartCommentLine(); printf2("continue\n");
  6648. if ((tok = GetToken()) != ';')
  6649. //error("ParseStatement(): ';' expected\n");
  6650. errorUnexpectedToken(tok);
  6651. tok = GetToken();
  6652. if (BrkCntTarget == NULL || BrkCntTarget[1] == 0)
  6653. //error("ParseStatement(): 'continue' must be within 'while' or 'for' statement\n");
  6654. errorCtrlOutOfScope();
  6655. GenJumpUncond(BrkCntTarget[1]);
  6656. }
  6657. else if (tok == tokSwitch)
  6658. {
  6659. int undoCases = CasesCnt;
  6660. int brkLabel = LabelCnt++;
  6661. int lbl = LabelCnt++;
  6662. int i;
  6663. GenStartCommentLine(); printf2("switch\n");
  6664. tok = GetToken();
  6665. if (tok != '(')
  6666. //error("ParseStatement(): '(' expected after 'switch'\n");
  6667. errorUnexpectedToken(tok);
  6668. tok = GetToken();
  6669. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  6670. //error("ParseStatement(): ')' expected after 'switch ( expression'\n");
  6671. errorUnexpectedToken(tok);
  6672. if (!gotUnary)
  6673. //error("ParseStatement(): expression expected in 'switch ( expression )'\n");
  6674. errorUnexpectedToken(tok);
  6675. // DONE: void control expressions
  6676. //error("ParseStatement(): unexpected 'void' expression in 'switch ( expression )'\n");
  6677. anyIntTypeCheck(synPtr);
  6678. push(tokReturn); // value produced by generated code is used
  6679. GenExpr();
  6680. tok = GetToken();
  6681. // Skip the code for the cases
  6682. GenJumpUncond(lbl);
  6683. brkCntTarget[0] = brkLabel; // break target
  6684. brkCntTarget[1] = 0; // continue target
  6685. if (BrkCntTarget)
  6686. {
  6687. // Preserve the continue target
  6688. brkCntTarget[1] = BrkCntTarget[1]; // continue target
  6689. }
  6690. // Reserve a slot in the case table for the default label
  6691. AddCase(0, 0);
  6692. tok = ParseStatement(tok, brkCntTarget, CasesCnt);
  6693. // If there's no default target, will use the break target as default
  6694. if (!Cases[undoCases][1])
  6695. Cases[undoCases][1] = brkLabel;
  6696. // End of switch reached (not via break), skip conditional jumps
  6697. GenJumpUncond(brkLabel);
  6698. // Generate conditional jumps
  6699. GenNumLabel(lbl);
  6700. for (i = undoCases + 1; i < CasesCnt; i++)
  6701. {
  6702. GenJumpIfEqual(Cases[i][0], Cases[i][1]);
  6703. }
  6704. // If none of the cases matches, take the default case
  6705. if (Cases[undoCases][1] != brkLabel)
  6706. GenJumpUncond(Cases[undoCases][1]);
  6707. GenNumLabel(brkLabel); // break label
  6708. CasesCnt = undoCases;
  6709. }
  6710. else if (tok == tokCase)
  6711. {
  6712. int i;
  6713. GenStartCommentLine(); printf2("case\n");
  6714. if (!casesIdx)
  6715. //error("ParseStatement(): 'case' must be within 'switch' statement\n");
  6716. errorCtrlOutOfScope();
  6717. tok = GetToken();
  6718. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ':')
  6719. //error("ParseStatement(): ':' expected after 'case expression'\n");
  6720. errorUnexpectedToken(tok);
  6721. if (!gotUnary)
  6722. errorUnexpectedToken(tok);
  6723. anyIntTypeCheck(synPtr);
  6724. if (!constExpr)
  6725. //error("ParseStatement(): constant integer expression expected in 'case expression :'\n");
  6726. errorNotConst();
  6727. // Check for dups
  6728. exprVal = truncInt(exprVal);
  6729. for (i = casesIdx; i < CasesCnt; i++)
  6730. if (Cases[i][0] == exprVal)
  6731. error("Duplicate case value\n");
  6732. AddCase(exprVal, LabelCnt);
  6733. GenNumLabel(LabelCnt++); // case exprVal:
  6734. tok = GetToken();
  6735. // a statement is needed after "case:"
  6736. statementNeeded = 1;
  6737. }
  6738. else if (tok == tokDefault)
  6739. {
  6740. GenStartCommentLine(); printf2("default\n");
  6741. if (!casesIdx)
  6742. //error("ParseStatement(): 'default' must be within 'switch' statement\n");
  6743. errorCtrlOutOfScope();
  6744. if (Cases[casesIdx - 1][1])
  6745. //error("ParseStatement(): only one 'default' allowed in 'switch'\n");
  6746. errorUnexpectedToken(tok);
  6747. tok = GetToken();
  6748. if (tok != ':')
  6749. //error("ParseStatement(): ':' expected after 'default'\n");
  6750. errorUnexpectedToken(tok);
  6751. tok = GetToken();
  6752. GenNumLabel(Cases[casesIdx - 1][1] = LabelCnt++); // default:
  6753. // a statement is needed after "default:"
  6754. statementNeeded = 1;
  6755. }
  6756. else if (tok == tok_Asm)
  6757. {
  6758. tok = GetToken();
  6759. if (tok != '(')
  6760. //error("ParseStatement(): '(' expected after 'asm'\n");
  6761. errorUnexpectedToken(tok);
  6762. tok = GetToken();
  6763. if (tok != tokLitStr)
  6764. //error("ParseStatement(): string literal expression expected in 'asm ( expression )'\n");
  6765. errorUnexpectedToken(tok);
  6766. do
  6767. {
  6768. GetString('"', 0, 'a');
  6769. tok = GetToken();
  6770. } while (tok == tokLitStr); // concatenate adjacent string literals
  6771. printf2("\n");
  6772. if (tok != ')')
  6773. //error("ParseStatement(): ')' expected after 'asm ( expression'\n");
  6774. errorUnexpectedToken(tok);
  6775. tok = GetToken();
  6776. if (tok != ';')
  6777. //error("ParseStatement(): ';' expected after 'asm ( expression )'\n");
  6778. errorUnexpectedToken(tok);
  6779. tok = GetToken();
  6780. }
  6781. else if (tok == tokGoto)
  6782. {
  6783. if ((tok = GetToken()) != tokIdent)
  6784. errorUnexpectedToken(tok);
  6785. GenStartCommentLine(); printf2("goto %s\n", TokenIdentName);
  6786. GenJumpUncond(AddGotoLabel(TokenIdentName, 0));
  6787. if ((tok = GetToken()) != ';')
  6788. errorUnexpectedToken(tok);
  6789. tok = GetToken();
  6790. }
  6791. else
  6792. {
  6793. tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, tokGotoLabel, 0);
  6794. if (tok == tokGotoLabel)
  6795. {
  6796. // found a label
  6797. GenStartCommentLine(); printf2("%s:\n", IdentTable + stack[0][1]);
  6798. GenNumLabel(AddGotoLabel(IdentTable + stack[0][1], 1));
  6799. // a statement is needed after "label:"
  6800. statementNeeded = 1;
  6801. }
  6802. else
  6803. {
  6804. if (tok != ';')
  6805. //error("ParseStatement(): ';' expected\n");
  6806. errorUnexpectedToken(tok);
  6807. if (gotUnary)
  6808. GenExpr();
  6809. }
  6810. tok = GetToken();
  6811. }
  6812. } while (statementNeeded);
  6813. return tok;
  6814. }
  6815. // TBD!!! think of ways of getting rid of casesIdx
  6816. STATIC
  6817. int ParseBlock(int BrkCntTarget[2], int casesIdx)
  6818. {
  6819. int tok = GetToken();
  6820. // Catch redeclarations of function parameters by not
  6821. // beginning a new scope if this block begins a function
  6822. // (the caller of ParseBlock() must've begun a new scope
  6823. // already, before the function parameters).
  6824. if (BrkCntTarget == BrkCntTargetFxn)
  6825. BrkCntTarget = NULL;
  6826. else
  6827. // Otherwise begin a new scope.
  6828. PushSyntax('#');
  6829. for (;;)
  6830. {
  6831. if (tok == 0)
  6832. return tok;
  6833. if (tok == '}' && ParseLevel > 0)
  6834. return tok;
  6835. if (TokenStartsDeclaration(tok, 0))
  6836. {
  6837. tok = ParseDecl(tok, NULL, 0, 1);
  6838. }
  6839. else if (ParseLevel > 0 || tok == tok_Asm)
  6840. {
  6841. tok = ParseStatement(tok, BrkCntTarget, casesIdx);
  6842. }
  6843. else
  6844. //error("ParseBlock(): Unexpected token %s\n", GetTokenName(tok));
  6845. errorUnexpectedToken(tok);
  6846. }
  6847. }
  6848. int main(int argc, char** argv)
  6849. {
  6850. // gcc/MinGW inserts a call to __main() here.
  6851. int i;
  6852. // Run-time initializer for SyntaxStack0[] to reduce
  6853. // executable file size (SyntaxStack0[] will be in .bss)
  6854. static unsigned char SyntaxStackInit[] =
  6855. {
  6856. tokVoid, // SymVoidSynPtr
  6857. tokInt, // SymIntSynPtr
  6858. tokUnsigned, // SymUintSynPtr
  6859. tokVoid, // SymWideCharSynPtr
  6860. tokFloat, // SymFloatSynPtr
  6861. tokIdent, // SymFuncPtr
  6862. '[',
  6863. tokNumUint,
  6864. ']',
  6865. tokChar
  6866. }; // SyntaxStackCnt must be initialized to the number of elements in SyntaxStackInit[]
  6867. memcpy(SyntaxStack0, SyntaxStackInit, sizeof SyntaxStackInit);
  6868. SyntaxStackCnt = division(sizeof SyntaxStackInit , sizeof SyntaxStackInit[0]);
  6869. SyntaxStack1[SymFuncPtr] = DummyIdent = AddIdent("");
  6870. GenInit();
  6871. // Parse the command line arguments
  6872. for (i = 1; i < argc; i++)
  6873. {
  6874. // DONE: move code-generator-specific options to
  6875. // the code generator
  6876. if (GenInitParams(argc, argv, &i))
  6877. {
  6878. continue;
  6879. }
  6880. else if (!strcmp(argv[i], "--os"))
  6881. {
  6882. compileOS = 1;
  6883. continue;
  6884. }
  6885. else if (!strcmp(argv[i], "--bdos"))
  6886. {
  6887. compileUserBDOS = 1;
  6888. continue;
  6889. }
  6890. else if (!strcmp(argv[i], "-signed-char"))
  6891. {
  6892. // this is the default option
  6893. CharIsSigned = 1;
  6894. continue;
  6895. }
  6896. else if (!strcmp(argv[i], "-unsigned-char"))
  6897. {
  6898. CharIsSigned = 0;
  6899. continue;
  6900. }
  6901. else if (!strcmp(argv[i], "-leading-underscore"))
  6902. {
  6903. // this is the default option for x86
  6904. UseLeadingUnderscores = 1;
  6905. continue;
  6906. }
  6907. else if (!strcmp(argv[i], "-no-leading-underscore"))
  6908. {
  6909. // this is the default option for MIPS
  6910. UseLeadingUnderscores = 0;
  6911. continue;
  6912. }
  6913. else if (!strcmp(argv[i], "-label"))
  6914. {
  6915. if (i + 1 < argc)
  6916. {
  6917. LabelCnt = atoi(argv[++i]);
  6918. continue;
  6919. }
  6920. }
  6921. else if (!strcmp(argv[i], "-no-externs"))
  6922. {
  6923. GenExterns = 0;
  6924. continue;
  6925. }
  6926. else if (!strcmp(argv[i], "-verbose"))
  6927. {
  6928. warnings = verbose = 1;
  6929. continue;
  6930. }
  6931. else if (!strcmp(argv[i], "-Wall"))
  6932. {
  6933. warnings = 1;
  6934. continue;
  6935. }
  6936. else if (!strcmp(argv[i], "-I") || !strcmp(argv[i], "-SI"))
  6937. {
  6938. if (i + 1 < argc)
  6939. {
  6940. int len = strlen(argv[++i]) + 1;
  6941. if (argv[i - 1][1] == 'I')
  6942. {
  6943. if (MAX_SEARCH_PATH - SearchPathsLen < len)
  6944. //error("Path name too long\n");
  6945. errorFileName();
  6946. strcpy(SearchPaths + SearchPathsLen, argv[i]);
  6947. SearchPathsLen += len;
  6948. }
  6949. else
  6950. {
  6951. if (MAX_SEARCH_PATH - SysSearchPathsLen < len)
  6952. //error("Path name too long\n");
  6953. errorFileName();
  6954. strcpy(SysSearchPaths + SysSearchPathsLen, argv[i]);
  6955. SysSearchPathsLen += len;
  6956. }
  6957. continue;
  6958. }
  6959. }
  6960. else if (!strcmp(argv[i], "-nopp"))
  6961. {
  6962. // TBD!!! don't do preprocessing when this option is present
  6963. continue;
  6964. }
  6965. // DONE: '-D macro[=expansion]': '#define macro 1' when there's no '=expansion'
  6966. else if (!strcmp(argv[i], "-D"))
  6967. {
  6968. if (i + 1 < argc)
  6969. {
  6970. char id[MAX_IDENT_LEN + 1];
  6971. char* e = strchr(argv[++i], '=');
  6972. int len;
  6973. if (e)
  6974. {
  6975. len = e - argv[i];
  6976. e++;
  6977. }
  6978. else
  6979. {
  6980. len = strlen(argv[i]);
  6981. e = "1";
  6982. }
  6983. if (len > 0 && len <= MAX_IDENT_LEN)
  6984. {
  6985. int j, bad = 1;
  6986. memcpy(id, argv[i], len);
  6987. id[len] = '\0';
  6988. for (j = 0; j < len; j++)
  6989. if ((bad = !(id[j] == '_' || (!j * isalpha(id[j] & 0xFFu) + j * isalnum(id[j] & 0xFFu)))) != 0)
  6990. break;
  6991. if (!bad)
  6992. {
  6993. DefineMacro(id, e);
  6994. continue;
  6995. }
  6996. }
  6997. }
  6998. }
  6999. else if (argv[i][0] == '-')
  7000. {
  7001. // unknown option
  7002. }
  7003. else if (FileCnt == 0)
  7004. {
  7005. // If it's none of the known options,
  7006. // assume it's the source code file name
  7007. if (strlen(argv[i]) > MAX_FILE_NAME_LEN)
  7008. //error("File name too long\n");
  7009. errorFileName();
  7010. strcpy(FileNames[0], argv[i]);
  7011. if ((Files[0] = fopen(FileNames[0], "r")) == NULL)
  7012. //error("Cannot open file \"%s\"\n", FileNames[0]);
  7013. errorFile(FileNames[0]);
  7014. LineNos[0] = LineNo;
  7015. LinePoss[0] = LinePos;
  7016. FileCnt++;
  7017. continue;
  7018. }
  7019. else if (FileCnt == 1 && OutFile == NULL)
  7020. {
  7021. // This should be the output file name
  7022. if ((OutFile = fopen(argv[i], "w")) == NULL)
  7023. //error("Cannot open output file \"%s\"\n", argv[i]);
  7024. errorFile(argv[i]);
  7025. continue;
  7026. }
  7027. error("Invalid or unsupported command line option\n");
  7028. }
  7029. if (!FileCnt)
  7030. error("Input file not specified\n");
  7031. if (!OutFile)
  7032. error("Output file not specified\n");
  7033. GenInitFinalize();
  7034. // Define a few macros useful for conditional compilation
  7035. DefineMacro("__SMALLER_C__", "0x0100");
  7036. if (SizeOfWord == 2)
  7037. DefineMacro("__SMALLER_C_16__", "");
  7038. else if (SizeOfWord == 4)
  7039. DefineMacro("__SMALLER_C_32__", "");
  7040. if (OutputFormat == FormatSegHuge)
  7041. DefineMacro("__HUGE__", "");
  7042. if (OutputFormat == FormatSegUnreal)
  7043. DefineMacro("__UNREAL__", "");
  7044. if (CharIsSigned)
  7045. DefineMacro("__SMALLER_C_SCHAR__", "");
  7046. else
  7047. DefineMacro("__SMALLER_C_UCHAR__", "");
  7048. // populate CharQueue[] with the initial file characters
  7049. ShiftChar();
  7050. puts2(FileHeader);
  7051. // compile
  7052. ParseBlock(NULL, 0);
  7053. GenFin();
  7054. DumpSynDecls();
  7055. DumpMacroTable();
  7056. DumpIdentTable();
  7057. GenStartCommentLine(); printf2("Next label number: %d\n", LabelCnt);
  7058. if (warnings && warnCnt)
  7059. printf("%d warnings\n", warnCnt);
  7060. GenStartCommentLine(); printf2("Compilation succeeded.\n");
  7061. if (OutFile)
  7062. fclose(OutFile);
  7063. return 0;
  7064. }