bcc.c 268 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296
  1. /*
  2. Copyright (c) 2021-2022, 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 (B32P C Compiler) */
  26. /* */
  27. /* C compiler for B32P */
  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. #ifndef STATIC
  40. #define STATIC
  41. #else
  42. #undef STATIC
  43. #define STATIC static
  44. #endif
  45. #define NO_EXTRAS
  46. #define CAN_COMPILE_32BIT
  47. #define MIPS
  48. #define B322
  49. #ifdef NO_EXTRAS
  50. #define NO_PPACK
  51. #define NO_TYPEDEF_ENUM
  52. #define NO_FUNC_
  53. #define NO_EXTRA_WARNS
  54. #define NO_FOR_DECL
  55. #define NO_STRUCT_BY_VAL
  56. #define NO_FP
  57. #define NO_WCHAR
  58. #endif
  59. #ifndef __SMALLER_C__
  60. //#include <limits.h>
  61. #define CHAR_BIT 8
  62. #define UINT_MAX 4294967295U
  63. #define INT_MIN -2147483648
  64. //#include <ctype.h>
  65. // isalpha
  66. // isalnum
  67. // isdigit
  68. //#include <string.h>
  69. // memmove
  70. // strchr
  71. // strcat
  72. // strlen
  73. // memcpy
  74. // strncmp
  75. #include <stdarg.h> // only used for printf related stuff and warnings/errors. Should be able to remove by replacing ALL(...) occurrences with a normal print function
  76. #include <stdlib.h>
  77. #include <stdio.h> // I/O functions
  78. //#if UINT_MAX >= 0xFFFFFFFF
  79. //#define CAN_COMPILE_32BIT
  80. //#endif
  81. #else // #ifndef __SMALLER_C__
  82. #define NULL 0
  83. #define size_t unsigned int
  84. #define CHAR_BIT (8)
  85. #ifdef __SMALLER_C_SCHAR__
  86. #define CHAR_MIN (-128)
  87. #define CHAR_MAX (127)
  88. #endif
  89. #ifdef __SMALLER_C_UCHAR__
  90. #define CHAR_MIN (0)
  91. #define CHAR_MAX (255)
  92. #endif
  93. #ifndef __SMALLER_C_SCHAR__
  94. #ifndef __SMALLER_C_UCHAR__
  95. #error __SMALLER_C_SCHAR__ or __SMALLER_C_UCHAR__ must be defined
  96. #endif
  97. #endif
  98. #ifdef __SMALLER_C_16__
  99. #define INT_MAX (32767)
  100. #define INT_MIN (-32767-1)
  101. #define UINT_MAX (65535u)
  102. #define UINT_MIN (0u)
  103. #endif
  104. #ifdef __SMALLER_C_32__
  105. #define INT_MAX (2147483647)
  106. #define INT_MIN (-2147483647-1)
  107. #define UINT_MAX (4294967295u)
  108. #define UINT_MIN (0u)
  109. //#define CAN_COMPILE_32BIT
  110. #endif
  111. #ifndef __SMALLER_C_16__
  112. #ifndef __SMALLER_C_32__
  113. #error __SMALLER_C_16__ or __SMALLER_C_32__ must be defined
  114. #endif
  115. #endif
  116. #define EXIT_FAILURE 1
  117. void exit(int);
  118. int atoi(char*);
  119. size_t strlen(char*);
  120. char* strcpy(char*, char*);
  121. char* strchr(char*, int);
  122. int strcmp(char*, char*);
  123. int strncmp(char*, char*, size_t);
  124. void* memmove(void*, void*, size_t);
  125. void* memcpy(void*, void*, size_t);
  126. void* memset(void*, int, size_t);
  127. int memcmp(void*, void*, size_t);
  128. int isspace(int);
  129. int isdigit(int);
  130. int isalpha(int);
  131. int isalnum(int);
  132. #define FILE void
  133. #define EOF (-1)
  134. FILE* fopen(char*, char*);
  135. int fclose(FILE*);
  136. int putchar(int);
  137. int fputc(int, FILE*);
  138. int fgetc(FILE*);
  139. int puts(char*);
  140. int fputs(char*, FILE*);
  141. int sprintf(char*, char*, ...);
  142. //int vsprintf(char*, char*, va_list);
  143. int vsprintf(char*, char*, void*);
  144. int printf(char*, ...);
  145. int fprintf(FILE*, char*, ...);
  146. //int vprintf(char*, va_list);
  147. int vprintf(char*, void*);
  148. //int vfprintf(FILE*, char*, va_list);
  149. int vfprintf(FILE*, char*, void*);
  150. struct fpos_t_
  151. {
  152. union
  153. {
  154. unsigned short halves[2]; // for 16-bit memory models without 32-bit longs
  155. int align; // for alignment on machine word boundary
  156. } u;
  157. }; // keep in sync with stdio.h !!!
  158. #define fpos_t struct fpos_t_
  159. int fgetpos(FILE*, fpos_t*);
  160. int fsetpos(FILE*, fpos_t*);
  161. #endif // #ifndef __SMALLER_C__
  162. // Floating point requires 32 bits
  163. #ifndef CAN_COMPILE_32BIT
  164. #ifndef NO_FP
  165. #define NO_FP
  166. #endif
  167. #endif
  168. ////////////////////////////////////////////////////////////////////////////////
  169. // all public macros
  170. #ifndef MAX_IDENT_LEN
  171. #define MAX_IDENT_LEN 63
  172. #endif
  173. #ifndef MAX_STRING_LEN
  174. #define MAX_STRING_LEN 255
  175. #endif
  176. #define MAX_CHAR_QUEUE_LEN (MAX_STRING_LEN + 1)
  177. #ifndef MAX_MACRO_TABLE_LEN
  178. #define MAX_MACRO_TABLE_LEN (8192+1024)
  179. #endif
  180. #ifndef MAX_IDENT_TABLE_LEN
  181. #define MAX_IDENT_TABLE_LEN (8192+1024+512) // must be greater than MAX_IDENT_LEN
  182. #endif
  183. #ifndef SYNTAX_STACK_MAX
  184. #define SYNTAX_STACK_MAX (4096+1024)
  185. #endif
  186. #ifndef MAX_FILE_NAME_LEN
  187. #define MAX_FILE_NAME_LEN 95
  188. #endif
  189. #ifndef NO_PREPROCESSOR
  190. #define MAX_INCLUDES 8
  191. #define PREP_STACK_SIZE 8
  192. #define MAX_SEARCH_PATH 256
  193. #else
  194. #define MAX_INCLUDES 1
  195. #define PREP_STACK_SIZE 1
  196. #define MAX_SEARCH_PATH 1
  197. #undef MAX_STRING_LEN
  198. #define MAX_STRING_LEN (MAX_FILE_NAME_LEN + 3)
  199. #endif
  200. /* +-~* /% &|^! << >> && || < <= > >= == != () *[] ++ -- = += -= ~= *= /= %= &= |= ^= <<= >>= {} ,;: -> ... */
  201. #define tokEof 0
  202. #define tokNumInt 1
  203. #define tokNumUint 2
  204. #define tokLitStr 3
  205. #define tokLShift 4
  206. #define tokRShift 5
  207. #define tokLogAnd 6
  208. #define tokLogOr 7
  209. #define tokEQ 8
  210. #define tokNEQ 9
  211. #define tokLEQ 10
  212. #define tokGEQ 11
  213. #define tokInc 12
  214. #define tokDec 13
  215. #define tokArrow 14
  216. #define tokEllipsis 15
  217. #define tokIdent 16
  218. #define tokVoid 17
  219. #define tokChar 18
  220. #define tokInt 19
  221. #define tokReturn 20
  222. #define tokGoto 21
  223. #define tokIf 22
  224. #define tokElse 23
  225. #define tokWhile 24
  226. #define tokCont 25
  227. #define tokBreak 26
  228. #define tokSizeof 27
  229. #define tokAssignMul 'A'
  230. #define tokAssignDiv 'B'
  231. #define tokAssignMod 'C'
  232. #define tokAssignAdd 'D'
  233. #define tokAssignSub 'E'
  234. #define tokAssignLSh 'F'
  235. #define tokAssignRSh 'G'
  236. #define tokAssignAnd 'H'
  237. #define tokAssignXor 'I'
  238. #define tokAssignOr 'J'
  239. #define tokFloat 'a'
  240. #define tokDouble 'b'
  241. #define tokLong 'c'
  242. #define tokShort 'd'
  243. #define tokUnsigned 'e'
  244. #define tokSigned 'f'
  245. #define tokConst 'g'
  246. #define tokVolatile 'h'
  247. #define tokRestrict 'i'
  248. #define tokStatic 'j'
  249. #define tokInline 'k'
  250. #define tokExtern 'l'
  251. #define tokAuto 'm'
  252. #define tokRegister 'n'
  253. #define tokTypedef 'o'
  254. #define tokEnum 'p'
  255. #define tokStruct 'q'
  256. #define tokUnion 'r'
  257. #define tokDo 's'
  258. #define tokFor 't'
  259. #define tokSwitch 'u'
  260. #define tokCase 'v'
  261. #define tokDefault 'w'
  262. #define tok_Bool 'x'
  263. #define tok_Complex 'y'
  264. #define tok_Imagin 'z'
  265. #define tok_Asm '`'
  266. /* Pseudo-tokens (converted from others or generated) */
  267. #define tokURShift 28
  268. #define tokUDiv 29
  269. #define tokUMod 30
  270. #define tokAssignURSh 31
  271. #define tokAssignUDiv '@'
  272. #define tokAssignUMod 'K'
  273. #define tokComma '0'
  274. #define tokIfNot 'L'
  275. #define tokUnaryAnd 'M'
  276. #define tokUnaryStar 'N'
  277. #define tokUnaryPlus 'O'
  278. #define tokUnaryMinus 'P'
  279. #define tokPostInc 'Q'
  280. #define tokPostDec 'R'
  281. #define tokPostAdd 'S'
  282. #define tokPostSub 'T'
  283. #define tokULess 'U'
  284. #define tokUGreater 'V'
  285. #define tokULEQ 'W'
  286. #define tokUGEQ 'X'
  287. #define tokLocalOfs 'Y'
  288. #define tokShortCirc 'Z'
  289. #define tokSChar 0x80
  290. #define tokUChar 0x81
  291. #define tokUShort 0x82
  292. #define tokULong 0x83
  293. //#define tokLongLong 0x84
  294. //#define tokULongLong 0x85
  295. //#define tokLongDbl 0x86
  296. #define tokGotoLabel 0x8F
  297. #define tokStructPtr 0x90
  298. #define tokTag 0x91
  299. #define tokMemberIdent 0x92
  300. #define tokEnumPtr 0x93
  301. #define tokIntr 0x94
  302. #define tokNumFloat 0x95
  303. #define tokNumCharWide 0x96
  304. #define tokLitStrWide 0x97
  305. //#define FormatFlat 0
  306. #define FormatSegmented 1
  307. //#define FormatSegTurbo 2
  308. #define FormatSegHuge 3
  309. #define FormatSegUnreal 4
  310. #define SymVoidSynPtr 0
  311. #define SymIntSynPtr 1
  312. #define SymUintSynPtr 2
  313. #define SymWideCharSynPtr 3
  314. #define SymFloatSynPtr 4
  315. #define SymFuncPtr 5
  316. #ifndef STACK_SIZE
  317. #define STACK_SIZE 129
  318. #endif
  319. #define SymFxn 1
  320. #define SymGlobalVar 2
  321. #define SymGlobalArr 3
  322. #define SymLocalVar 4
  323. #define SymLocalArr 5
  324. // Division and Modulo without / and %
  325. STATIC
  326. int divmod(int dividend, int divisor, int* rem)
  327. {
  328. int quotient = 1;
  329. int neg = 1;
  330. if ((dividend>0 &&divisor<0)||(dividend<0 && divisor>0))
  331. neg = -1;
  332. // Convert to positive
  333. int tempdividend = (dividend < 0) ? -dividend : dividend;
  334. int tempdivisor = (divisor < 0) ? -divisor : divisor;
  335. if (tempdivisor == tempdividend) {
  336. *rem = 0;
  337. return 1*neg;
  338. }
  339. else if (tempdividend < tempdivisor) {
  340. if (dividend < 0)
  341. *rem = tempdividend*neg;
  342. else
  343. *rem = tempdividend;
  344. return 0;
  345. }
  346. while (tempdivisor<<1 <= tempdividend)
  347. {
  348. tempdivisor = tempdivisor << 1;
  349. quotient = quotient << 1;
  350. }
  351. // Call division recursively
  352. if(dividend < 0)
  353. quotient = quotient*neg + divmod(-(tempdividend-tempdivisor), divisor, rem);
  354. else
  355. quotient = quotient*neg + divmod(tempdividend-tempdivisor, divisor, rem);
  356. return quotient;
  357. }
  358. STATIC
  359. int division(int dividend, int divisor)
  360. {
  361. int rem = 0;
  362. return divmod(dividend, divisor, &rem);
  363. }
  364. STATIC
  365. int modulo(int dividend, int divisor)
  366. {
  367. int rem = 0;
  368. divmod(dividend, divisor, &rem);
  369. return rem;
  370. }
  371. // isalpha
  372. STATIC
  373. int isalpha(int argument)
  374. {
  375. if (argument >= 'A' && argument <= 'Z')
  376. return 2;
  377. if (argument >= 'a' && argument <= 'z')
  378. return 1;
  379. return 0;
  380. }
  381. // isdigit
  382. STATIC
  383. int isdigit(int argument)
  384. {
  385. if (argument >= '0' && argument <= '9')
  386. return 1;
  387. return 0;
  388. }
  389. // isalnum
  390. STATIC
  391. int isalnum(int argument)
  392. {
  393. if (isdigit(argument) || isalpha(argument))
  394. return 1;
  395. return 0;
  396. }
  397. STATIC
  398. void* memcpy(void *dest, const void *src, size_t len)
  399. {
  400. // Typecast src and dest addresses to (char *)
  401. char *csrc = (char *)src;
  402. char *cdest = (char *)dest;
  403. // Copy contents of src[] to dest[]
  404. int i;
  405. for (i=0; i<len; i++)
  406. cdest[i] = csrc[i];
  407. }
  408. STATIC
  409. void* memmove(void* dest, const void* src, size_t n)
  410. {
  411. unsigned char* from = (unsigned char*) src;
  412. unsigned char* to = (unsigned char*) dest;
  413. if (from == to || n == 0)
  414. return dest;
  415. if (to > from && to-from < (int)n) {
  416. /* to overlaps with from */
  417. /* <from......> */
  418. /* <to........> */
  419. /* copy in reverse, to avoid overwriting from */
  420. int i;
  421. for(i=n-1; i>=0; i--)
  422. to[i] = from[i];
  423. return dest;
  424. }
  425. if (from > to && from-to < (int)n) {
  426. /* to overlaps with from */
  427. /* <from......> */
  428. /* <to........> */
  429. /* copy forwards, to avoid overwriting from */
  430. size_t i;
  431. for(i=0; i<n; i++)
  432. to[i] = from[i];
  433. return dest;
  434. }
  435. memcpy(dest, src, n);
  436. return dest;
  437. }
  438. // Function to implement `strcpy()` function
  439. STATIC
  440. char* strcpy(char* destination, const char* source)
  441. {
  442. // return if no memory is allocated to the destination
  443. if (destination == NULL) {
  444. return NULL;
  445. }
  446. // take a pointer pointing to the beginning of the destination string
  447. char *ptr = destination;
  448. // copy the C-string pointed by source into the array
  449. // pointed by destination
  450. while (*source != '\0')
  451. {
  452. *destination = *source;
  453. destination++;
  454. source++;
  455. }
  456. // include the terminating null character
  457. *destination = '\0';
  458. // the destination is returned by standard `strcpy()`
  459. return ptr;
  460. }
  461. STATIC
  462. size_t strlen(const char *str)
  463. {
  464. const char *s;
  465. for (s = str; *s; ++s);
  466. return (s - str);
  467. }
  468. STATIC
  469. char* strcat (char *dest, const char *src)
  470. {
  471. strcpy (dest + strlen (dest), src);
  472. return dest;
  473. }
  474. STATIC
  475. char* strchr (const char *s, int c)
  476. {
  477. do {
  478. if (*s == c)
  479. {
  480. return (char*)s;
  481. }
  482. } while (*s++);
  483. return (0);
  484. }
  485. STATIC
  486. int strcmp(const char* s1, const char* s2)
  487. {
  488. while(*s1 && (*s1 == *s2))
  489. {
  490. s1++;
  491. s2++;
  492. }
  493. return *(unsigned char*)s1 - *(unsigned char*)s2;
  494. }
  495. //STATIC
  496. int strncmp(const char * s1, const char * s2, size_t n )
  497. {
  498. while ( n && *s1 && ( *s1 == *s2 ) )
  499. {
  500. ++s1;
  501. ++s2;
  502. --n;
  503. }
  504. if ( n == 0 )
  505. {
  506. return 0;
  507. }
  508. else
  509. {
  510. return ( *(unsigned char *)s1 - *(unsigned char *)s2 );
  511. }
  512. }
  513. // all public prototypes
  514. STATIC
  515. unsigned truncUint(unsigned);
  516. STATIC
  517. int truncInt(int);
  518. STATIC
  519. int GetToken(void);
  520. STATIC
  521. char* GetTokenName(int token);
  522. #ifndef NO_PREPROCESSOR
  523. #ifndef NO_ANNOTATIONS
  524. STATIC
  525. void DumpMacroTable(void);
  526. #endif
  527. #endif
  528. STATIC
  529. int AddIdent(char* name);
  530. STATIC
  531. int FindIdent(char* name);
  532. #ifndef NO_ANNOTATIONS
  533. STATIC
  534. void DumpIdentTable(void);
  535. #endif
  536. STATIC
  537. char* lab2str(char* p, int n);
  538. STATIC
  539. void GenInit(void);
  540. STATIC
  541. void GenFin(void);
  542. STATIC
  543. int GenInitParams(int argc, char** argv, int* idx);
  544. STATIC
  545. void GenInitFinalize(void);
  546. STATIC
  547. void GenStartCommentLine(void);
  548. STATIC
  549. void GenWordAlignment(int bss);
  550. STATIC
  551. void GenLabel(char* Label, int Static);
  552. STATIC
  553. void GenNumLabel(int Label);
  554. STATIC
  555. void GenZeroData(unsigned Size, int bss);
  556. STATIC
  557. void GenIntData(int Size, int Val);
  558. STATIC
  559. void GenStartAsciiString(void);
  560. STATIC
  561. void GenAddrData(int Size, char* Label, int ofs);
  562. STATIC
  563. void GenJumpUncond(int Label);
  564. STATIC
  565. void GenJumpIfZero(int Label);
  566. STATIC
  567. void GenJumpIfNotZero(int Label);
  568. STATIC
  569. void GenJumpIfEqual(int val, int Label);
  570. STATIC
  571. void GenFxnProlog(void);
  572. STATIC
  573. void GenFxnEpilog(void);
  574. void GenIsrProlog(void);
  575. void GenIsrEpilog(void);
  576. STATIC
  577. int GenMaxLocalsSize(void);
  578. STATIC
  579. void GenDumpChar(int ch);
  580. STATIC
  581. void GenExpr(void);
  582. STATIC
  583. void PushSyntax(int t);
  584. STATIC
  585. void PushSyntax2(int t, int v);
  586. #ifndef NO_ANNOTATIONS
  587. STATIC
  588. void DumpSynDecls(void);
  589. #endif
  590. STATIC
  591. void push2(int v, int v2);
  592. STATIC
  593. void ins2(int pos, int v, int v2);
  594. STATIC
  595. void ins(int pos, int v);
  596. STATIC
  597. void del(int pos, int cnt);
  598. STATIC
  599. int TokenStartsDeclaration(int t, int params);
  600. STATIC
  601. int ParseDecl(int tok, unsigned structInfo[4], int cast, int label);
  602. STATIC
  603. void ShiftChar(void);
  604. STATIC
  605. int puts2(char*);
  606. STATIC
  607. int printf2(char*, ...);
  608. STATIC
  609. void error(char* format, ...);
  610. STATIC
  611. void warning(char* format, ...);
  612. STATIC
  613. void errorFile(char* n);
  614. STATIC
  615. void errorFileName(void);
  616. STATIC
  617. void errorInternal(int n);
  618. STATIC
  619. void errorChrStr(void);
  620. #ifndef NO_WCHAR
  621. STATIC
  622. void errorWideNonWide(void);
  623. #endif
  624. STATIC
  625. void errorStrLen(void);
  626. STATIC
  627. void errorUnexpectedToken(int tok);
  628. STATIC
  629. void errorDirective(void);
  630. STATIC
  631. void errorCtrlOutOfScope(void);
  632. STATIC
  633. void errorDecl(void);
  634. STATIC
  635. void errorVarSize(void);
  636. STATIC
  637. void errorInit(void);
  638. STATIC
  639. void errorUnexpectedVoid(void);
  640. STATIC
  641. void errorOpType(void);
  642. STATIC
  643. void errorNotLvalue(void);
  644. STATIC
  645. void errorNotConst(void);
  646. STATIC
  647. void errorLongExpr(void);
  648. #ifndef NO_FP
  649. STATIC
  650. void warnFloat2Int(void);
  651. #endif
  652. STATIC
  653. int FindSymbol(char* s);
  654. STATIC
  655. int SymType(int SynPtr);
  656. STATIC
  657. int FindTaggedDecl(char* s, int start, int* CurScope);
  658. #ifndef NO_TYPEDEF_ENUM
  659. STATIC
  660. int FindTypedef(char* s);
  661. #endif
  662. STATIC
  663. int GetDeclSize(int SyntaxPtr, int SizeForDeref);
  664. STATIC
  665. int ParseExpr(int tok, int* GotUnary, int* ExprTypeSynPtr, int* ConstExpr, int* ConstVal, int option, int option2);
  666. STATIC
  667. int GetFxnInfo(int ExprTypeSynPtr, int* MinParams, int* MaxParams, int* ReturnExprTypeSynPtr, int* FirstParamSynPtr);
  668. // all data
  669. int verbose = 0;
  670. int warnings = 0;
  671. int warnCnt = 0;
  672. // custom compiler flags
  673. int compileUserBDOS = 0;
  674. int compileOS = 0;
  675. // prep.c data
  676. // TBD!!! get rid of TokenIdentName[] and TokenValueString[]
  677. // and work with CharQueue[] directly
  678. int TokenValueInt = 0;
  679. char TokenIdentName[MAX_IDENT_LEN + 1];
  680. int TokenIdentNameLen = 0;
  681. char TokenValueString[MAX_STRING_LEN + 1];
  682. unsigned TokenStringLen = 0;
  683. unsigned TokenStringSize = 0; // TokenStringLen * sizeof(char/wchar_t)
  684. int LineNo = 1;
  685. int LinePos = 1;
  686. char CharQueue[MAX_CHAR_QUEUE_LEN];
  687. int CharQueueLen = 0;
  688. #ifndef NO_PREPROCESSOR
  689. /*
  690. Macro table entry format:
  691. idlen char: identifier length (<= 127)
  692. id char[idlen]: identifier (ASCIIZ)
  693. exlen char: length of what the identifier expands into (<= 127)
  694. ex char[exlen]: what the identifier expands into (ASCII)
  695. */
  696. char MacroTable[MAX_MACRO_TABLE_LEN];
  697. int MacroTableLen = 0;
  698. #endif
  699. /*
  700. Identifier table entry format:
  701. id char[idlen]: string (ASCIIZ)
  702. idlen char: string length (<= 127)
  703. */
  704. char IdentTable[MAX_IDENT_TABLE_LEN];
  705. int IdentTableLen = 0;
  706. int DummyIdent; // corresponds to empty string
  707. #ifndef MAX_GOTO_LABELS
  708. #define MAX_GOTO_LABELS 16
  709. #endif
  710. int gotoLabels[MAX_GOTO_LABELS][2];
  711. // gotoLabStat[]: bit 1 = used (by "goto label;"), bit 0 = defined (with "label:")
  712. char gotoLabStat[MAX_GOTO_LABELS];
  713. int gotoLabCnt = 0;
  714. #ifndef MAX_CASES
  715. #define MAX_CASES 128
  716. #endif
  717. int Cases[MAX_CASES][2]; // [0] is case constant, [1] is case label number
  718. int CasesCnt = 0;
  719. // Data structures to support #include
  720. int FileCnt = 0;
  721. char FileNames[MAX_INCLUDES][MAX_FILE_NAME_LEN + 1];
  722. FILE* Files[MAX_INCLUDES];
  723. FILE* OutFile;
  724. char CharQueues[MAX_INCLUDES][3];
  725. int LineNos[MAX_INCLUDES];
  726. int LinePoss[MAX_INCLUDES];
  727. char SysSearchPaths[MAX_SEARCH_PATH];
  728. int SysSearchPathsLen = 0;
  729. char SearchPaths[MAX_SEARCH_PATH];
  730. int SearchPathsLen = 0;
  731. // Data structures to support #ifdef/#ifndef,#else,#endif
  732. int PrepDontSkipTokens = 1;
  733. int PrepStack[PREP_STACK_SIZE][2];
  734. int PrepSp = 0;
  735. // Data structures to support #pragma pack(...)
  736. #ifndef NO_PPACK
  737. #define PPACK_STACK_SIZE 16
  738. int PragmaPackValue;
  739. int PragmaPackValues[PPACK_STACK_SIZE];
  740. int PragmaPackSp = 0;
  741. #endif
  742. // expr.c data
  743. int ExprLevel = 0;
  744. // TBD??? merge expression and operator stacks into one
  745. int stack[STACK_SIZE][2];
  746. int sp = 0;
  747. #define OPERATOR_STACK_SIZE STACK_SIZE
  748. int opstack[OPERATOR_STACK_SIZE][2];
  749. int opsp = 0;
  750. // smc.c data
  751. int OutputFormat = FormatSegmented;
  752. int GenExterns = 1;
  753. int UseBss = 1;
  754. // Names of C functions and variables are usually prefixed with an underscore.
  755. // One notable exception is the ELF format used by gcc in Linux.
  756. // Global C identifiers in the ELF format should not be predixed with an underscore.
  757. int UseLeadingUnderscores = 1;
  758. char* FileHeader = "";
  759. char* CodeHeaderFooter[2] = { "", "" };
  760. char* DataHeaderFooter[2] = { "", "" };
  761. char* RoDataHeaderFooter[2] = { "", "" };
  762. char* BssHeaderFooter[2] = { "", "" };
  763. char** CurHeaderFooter;
  764. int CharIsSigned = 1;
  765. int SizeOfWord = 2; // in chars (char can be a multiple of octets); ints and pointers are of word size
  766. int SizeOfWideChar = 2; // in chars/bytes, 2 or 4
  767. int WideCharIsSigned = 0; // 0 or 1
  768. int WideCharType1;
  769. int WideCharType2; // (un)signed counterpart of WideCharType1
  770. // TBD??? implement a function to allocate N labels with overflow checks
  771. int LabelCnt = 1; // label counter for jumps
  772. int StructCpyLabel = 0; // label of the function to copy structures/unions
  773. int StructPushLabel = 0; // label of the function to push structures/unions onto the stack
  774. // call stack (from higher to lower addresses):
  775. // arg n
  776. // ...
  777. // arg 1
  778. // return address
  779. // saved xbp register
  780. // local var 1
  781. // ...
  782. // local var n
  783. int CurFxnSyntaxPtr = 0;
  784. int CurFxnParamCntMin = 0;
  785. int CurFxnParamCntMax = 0;
  786. int CurFxnLocalOfs = 0; // negative
  787. int CurFxnMinLocalOfs = 0; // negative
  788. int CurFxnReturnExprTypeSynPtr = 0;
  789. int CurFxnEpilogLabel = 0;
  790. char* CurFxnName = NULL;
  791. #ifndef NO_FUNC_
  792. int CurFxnNameLabel = 0;
  793. #endif
  794. int IsMain; // if inside main()
  795. int ParseLevel = 0; // Parse level/scope (file:0, fxn:1+)
  796. int ParamLevel = 0; // 1+ if parsing params, 0 otherwise
  797. unsigned char SyntaxStack0[SYNTAX_STACK_MAX];
  798. int SyntaxStack1[SYNTAX_STACK_MAX];
  799. int SyntaxStackCnt;
  800. // all code
  801. STATIC
  802. unsigned truncUint(unsigned n)
  803. {
  804. // Truncate n to SizeOfWord * 8 bits
  805. if (SizeOfWord == 2)
  806. n &= ~(~0u << 8 << 8);
  807. #ifdef CAN_COMPILE_32BIT
  808. else if (SizeOfWord == 4)
  809. n &= ~(~0u << 8 << 12 << 12);
  810. #endif
  811. return n;
  812. }
  813. STATIC
  814. int truncInt(int n)
  815. {
  816. // Truncate n to SizeOfWord * 8 bits and then sign-extend it
  817. unsigned un = n;
  818. if (SizeOfWord == 2)
  819. {
  820. un &= ~(~0u << 8 << 8);
  821. un |= (((un >> 8 >> 7) & 1) * ~0u) << 8 << 8;
  822. }
  823. #ifdef CAN_COMPILE_32BIT
  824. else if (SizeOfWord == 4)
  825. {
  826. un &= ~(~0u << 8 << 12 << 12);
  827. un |= (((un >> 8 >> 12 >> 11) & 1) * ~0u) << 8 << 12 << 12;
  828. }
  829. #endif
  830. return (int)un;
  831. }
  832. // prep.c code
  833. #ifndef NO_PREPROCESSOR
  834. STATIC
  835. int FindMacro(char* name)
  836. {
  837. int i;
  838. for (i = 0; i < MacroTableLen; )
  839. {
  840. if (!strcmp(MacroTable + i + 1, name))
  841. return i + 1 + MacroTable[i];
  842. i = i + 1 + MacroTable[i]; // skip id
  843. i = i + 1 + MacroTable[i]; // skip ex
  844. }
  845. return -1;
  846. }
  847. STATIC
  848. int UndefineMacro(char* name)
  849. {
  850. int i;
  851. for (i = 0; i < MacroTableLen; )
  852. {
  853. if (!strcmp(MacroTable + i + 1, name))
  854. {
  855. int len = 1 + MacroTable[i]; // id part len
  856. len = len + 1 + MacroTable[i + len]; // + ex part len
  857. memmove(MacroTable + i,
  858. MacroTable + i + len,
  859. MacroTableLen - i - len);
  860. MacroTableLen -= len;
  861. return 1;
  862. }
  863. i = i + 1 + MacroTable[i]; // skip id
  864. i = i + 1 + MacroTable[i]; // skip ex
  865. }
  866. return 0;
  867. }
  868. STATIC
  869. void AddMacroIdent(char* name)
  870. {
  871. int l = strlen(name);
  872. if (l >= 127)
  873. error("Macro identifier too long '%s'\n", name);
  874. if (MAX_MACRO_TABLE_LEN - MacroTableLen < l + 3)
  875. error("Macro table exhausted\n");
  876. MacroTable[MacroTableLen++] = l + 1; // idlen
  877. strcpy(MacroTable + MacroTableLen, name);
  878. MacroTableLen += l + 1;
  879. MacroTable[MacroTableLen] = 0; // exlen
  880. }
  881. STATIC
  882. void AddMacroExpansionChar(char e)
  883. {
  884. if (e == '\0')
  885. {
  886. // finalize macro definition entry
  887. // remove trailing space first
  888. while (MacroTable[MacroTableLen] &&
  889. strchr(" \t", MacroTable[MacroTableLen + MacroTable[MacroTableLen]]))
  890. MacroTable[MacroTableLen]--;
  891. MacroTableLen += 1 + MacroTable[MacroTableLen];
  892. return;
  893. }
  894. if (MacroTableLen + 1 + MacroTable[MacroTableLen] >= MAX_MACRO_TABLE_LEN)
  895. error("Macro table exhausted\n");
  896. if (MacroTable[MacroTableLen] >= 127)
  897. error("Macro definition too long\n");
  898. MacroTable[MacroTableLen + 1 + MacroTable[MacroTableLen]] = e;
  899. MacroTable[MacroTableLen]++;
  900. }
  901. STATIC
  902. void DefineMacro(char* name, char* expansion)
  903. {
  904. AddMacroIdent(name);
  905. do
  906. {
  907. AddMacroExpansionChar(*expansion);
  908. } while (*expansion++ != '\0');
  909. }
  910. #ifndef NO_ANNOTATIONS
  911. STATIC
  912. void DumpMacroTable(void)
  913. {
  914. int i, j;
  915. puts2("");
  916. GenStartCommentLine(); printf2("Macro table:\n");
  917. for (i = 0; i < MacroTableLen; )
  918. {
  919. GenStartCommentLine(); printf2("Macro %s = ", MacroTable + i + 1);
  920. i = i + 1 + MacroTable[i]; // skip id
  921. printf2("`");
  922. j = MacroTable[i++];
  923. while (j--)
  924. printf2("%c", MacroTable[i++]);
  925. printf2("`\n");
  926. }
  927. GenStartCommentLine(); printf2("Bytes used: %d/%d\n\n", MacroTableLen, MAX_MACRO_TABLE_LEN);
  928. }
  929. #endif
  930. #endif // #ifndef NO_PREPROCESSOR
  931. STATIC
  932. int FindIdent(char* name)
  933. {
  934. int i;
  935. for (i = IdentTableLen; i > 0; )
  936. {
  937. i -= 1 + IdentTable[i - 1];
  938. if (!strcmp(IdentTable + i, name))
  939. return i;
  940. }
  941. return -1;
  942. }
  943. STATIC
  944. int AddIdent(char* name)
  945. {
  946. int i, len;
  947. if ((i = FindIdent(name)) >= 0)
  948. return i;
  949. i = IdentTableLen;
  950. len = strlen(name);
  951. if (len >= 127)
  952. error("Identifier too long\n");
  953. if (MAX_IDENT_TABLE_LEN - IdentTableLen < len + 2)
  954. error("Identifier table exhausted\n");
  955. strcpy(IdentTable + IdentTableLen, name);
  956. IdentTableLen += len + 1;
  957. IdentTable[IdentTableLen++] = len + 1;
  958. return i;
  959. }
  960. STATIC
  961. int AddNumericIdent(int n)
  962. {
  963. char s[1 + (2 + CHAR_BIT * sizeof n) / 3];
  964. char *p = s + sizeof s;
  965. *--p = '\0';
  966. p = lab2str(p, n);
  967. return AddIdent(p);
  968. }
  969. STATIC
  970. int AddGotoLabel(char* name, int label)
  971. {
  972. int i;
  973. for (i = 0; i < gotoLabCnt; i++)
  974. {
  975. if (!strcmp(IdentTable + gotoLabels[i][0], name))
  976. {
  977. if (gotoLabStat[i] & label)
  978. error("Redefinition of label '%s'\n", name);
  979. gotoLabStat[i] |= 2*!label + label;
  980. return gotoLabels[i][1];
  981. }
  982. }
  983. if (gotoLabCnt >= MAX_GOTO_LABELS)
  984. error("Goto table exhausted\n");
  985. gotoLabels[gotoLabCnt][0] = AddIdent(name);
  986. gotoLabels[gotoLabCnt][1] = LabelCnt++;
  987. gotoLabStat[gotoLabCnt] = 2*!label + label;
  988. return gotoLabels[gotoLabCnt++][1];
  989. }
  990. STATIC
  991. void UndoNonLabelIdents(int len)
  992. {
  993. int i;
  994. IdentTableLen = len;
  995. for (i = 0; i < gotoLabCnt; i++)
  996. if (gotoLabels[i][0] >= len)
  997. {
  998. char* pfrom = IdentTable + gotoLabels[i][0];
  999. char* pto = IdentTable + IdentTableLen;
  1000. int l = strlen(pfrom) + 2;
  1001. memmove(pto, pfrom, l);
  1002. IdentTableLen += l;
  1003. gotoLabels[i][0] = pto - IdentTable;
  1004. }
  1005. }
  1006. STATIC
  1007. void AddCase(int val, int label)
  1008. {
  1009. if (CasesCnt >= MAX_CASES)
  1010. error("Case table exhausted\n");
  1011. Cases[CasesCnt][0] = val;
  1012. Cases[CasesCnt++][1] = label;
  1013. }
  1014. #ifndef NO_ANNOTATIONS
  1015. STATIC
  1016. void DumpIdentTable(void)
  1017. {
  1018. int i;
  1019. puts2("");
  1020. GenStartCommentLine(); printf2("Identifier table:\n");
  1021. for (i = 0; i < IdentTableLen; )
  1022. {
  1023. GenStartCommentLine(); printf2("Ident %s\n", IdentTable + i);
  1024. i += strlen(IdentTable + i) + 2;
  1025. }
  1026. GenStartCommentLine(); printf2("Bytes used: %d/%d\n\n", IdentTableLen, MAX_IDENT_TABLE_LEN);
  1027. }
  1028. #endif
  1029. char* rws[] =
  1030. {
  1031. "break", "case", "char", "continue", "default", "do", "else",
  1032. "extern", "for", "if", "int", "return", "signed", "sizeof",
  1033. "static", "switch", "unsigned", "void", "while", "asm", "auto",
  1034. "const", "double", "enum", "float", "goto", "inline", "long",
  1035. "register", "restrict", "short", "struct", "typedef", "union",
  1036. "volatile", "_Bool", "_Complex", "_Imaginary",
  1037. "__interrupt"
  1038. };
  1039. unsigned char rwtk[] =
  1040. {
  1041. tokBreak, tokCase, tokChar, tokCont, tokDefault, tokDo, tokElse,
  1042. tokExtern, tokFor, tokIf, tokInt, tokReturn, tokSigned, tokSizeof,
  1043. tokStatic, tokSwitch, tokUnsigned, tokVoid, tokWhile, tok_Asm, tokAuto,
  1044. tokConst, tokDouble, tokEnum, tokFloat, tokGoto, tokInline, tokLong,
  1045. tokRegister, tokRestrict, tokShort, tokStruct, tokTypedef, tokUnion,
  1046. tokVolatile, tok_Bool, tok_Complex, tok_Imagin,
  1047. tokIntr
  1048. };
  1049. STATIC
  1050. int GetTokenByWord(char* word)
  1051. {
  1052. unsigned i;
  1053. for (i = 0; i < division(sizeof rws, sizeof rws[0]); i++)
  1054. if (!strcmp(rws[i], word))
  1055. return rwtk[i];
  1056. return tokIdent;
  1057. }
  1058. unsigned char tktk[] =
  1059. {
  1060. tokEof,
  1061. // Single-character operators and punctuators:
  1062. '+', '-', '~', '*', '/', '%', '&', '|', '^', '!',
  1063. '<', '>', '(', ')', '[', ']',
  1064. '{', '}', '=', ',', ';', ':', '.', '?',
  1065. // Multi-character operators and punctuators:
  1066. tokLShift, tokLogAnd, tokEQ, tokLEQ, tokInc, tokArrow, tokAssignMul,
  1067. tokAssignMod, tokAssignSub, tokAssignRSh, tokAssignXor,
  1068. tokRShift, tokLogOr, tokNEQ, tokGEQ, tokDec, tokEllipsis,
  1069. tokAssignDiv, tokAssignAdd, tokAssignLSh, tokAssignAnd, tokAssignOr,
  1070. // Some of the above tokens get converted into these in the process:
  1071. tokUnaryAnd, tokUnaryPlus, tokPostInc, tokPostAdd,
  1072. tokULess, tokULEQ, tokURShift, tokUDiv, tokUMod, tokComma,
  1073. tokUnaryStar, tokUnaryMinus, tokPostDec, tokPostSub,
  1074. tokUGreater, tokUGEQ, tokAssignURSh, tokAssignUDiv, tokAssignUMod,
  1075. // Helper (pseudo-)tokens:
  1076. tokNumInt, tokLitStr, tokLocalOfs, tokNumUint, tokIdent, tokShortCirc,
  1077. tokSChar, tokShort, tokLong, tokUChar, tokUShort, tokULong, tokNumFloat,
  1078. tokNumCharWide, tokLitStrWide
  1079. };
  1080. char* tks[] =
  1081. {
  1082. "<EOF>",
  1083. // Single-character operators and punctuators:
  1084. "+", "-", "~", "*", "/", "%", "&", "|", "^", "!",
  1085. "<", ">", "(", ")", "[", "]",
  1086. "{", "}", "=", ",", ";", ":", ".", "?",
  1087. // Multi-character operators and punctuators:
  1088. "<<", "&&", "==", "<=", "++", "->", "*=",
  1089. "%=", "-=", ">>=", "^=",
  1090. ">>", "||", "!=", ">=", "--", "...",
  1091. "/=", "+=", "<<=", "&=", "|=",
  1092. // Some of the above tokens get converted into these in the process:
  1093. "&u", "+u", "++p", "+=p",
  1094. "<u", "<=u", ">>u", "/u", "%u", ",b",
  1095. "*u", "-u", "--p", "-=p",
  1096. ">u", ">=u", ">>=u", "/=u", "%=u",
  1097. // Helper (pseudo-)tokens:
  1098. "<NumInt>", "<LitStr>", "<LocalOfs>", "<NumUint>", "<Ident>", "<ShortCirc>",
  1099. "signed char", "short", "long", "unsigned char", "unsigned short", "unsigned long", "float",
  1100. "<NumCharWide>", "<LitStrWide>"
  1101. };
  1102. STATIC
  1103. char* GetTokenName(int token)
  1104. {
  1105. unsigned i;
  1106. /* +-~* /% &|^! << >> && || < <= > >= == != () *[] ++ -- = += -= ~= *= /= %= &= |= ^= <<= >>= {} ,;: -> ... */
  1107. // Tokens other than reserved keywords:
  1108. for (i = 0; i < division(sizeof tktk , sizeof tktk[0]); i++)
  1109. if (tktk[i] == token)
  1110. return tks[i];
  1111. // Reserved keywords:
  1112. for (i = 0; i < division(sizeof rws , sizeof rws[0]); i++)
  1113. if (rwtk[i] == token)
  1114. return rws[i];
  1115. //error("Internal Error: GetTokenName(): Invalid token %d\n", token);
  1116. errorInternal(1);
  1117. return "";
  1118. }
  1119. STATIC
  1120. int GetNextChar(void)
  1121. {
  1122. int ch = EOF;
  1123. if (FileCnt && Files[FileCnt - 1])
  1124. {
  1125. if ((ch = fgetc(Files[FileCnt - 1])) == EOF)
  1126. {
  1127. fclose(Files[FileCnt - 1]);
  1128. Files[FileCnt - 1] = NULL;
  1129. // store the last line/pos, they may still be needed later
  1130. LineNos[FileCnt - 1] = LineNo;
  1131. LinePoss[FileCnt - 1] = LinePos;
  1132. // don't drop the file record just yet
  1133. }
  1134. }
  1135. return ch;
  1136. }
  1137. STATIC
  1138. void ShiftChar(void)
  1139. {
  1140. if (CharQueueLen)
  1141. memmove(CharQueue, CharQueue + 1, --CharQueueLen);
  1142. // make sure there always are at least 3 chars in the queue
  1143. while (CharQueueLen < 3)
  1144. {
  1145. int ch = GetNextChar();
  1146. if (ch == EOF)
  1147. ch = '\0';
  1148. CharQueue[CharQueueLen++] = ch;
  1149. }
  1150. }
  1151. STATIC
  1152. void ShiftCharN(int n)
  1153. {
  1154. while (n-- > 0)
  1155. {
  1156. ShiftChar();
  1157. LinePos++;
  1158. }
  1159. }
  1160. #ifndef NO_PREPROCESSOR
  1161. STATIC
  1162. void IncludeFile(int quot)
  1163. {
  1164. int nlen = strlen(TokenValueString);
  1165. if (CharQueueLen != 3)
  1166. //error("#include parsing error\n");
  1167. errorInternal(2);
  1168. if (FileCnt >= MAX_INCLUDES)
  1169. error("Too many include files\n");
  1170. // store the including file's position and buffered chars
  1171. LineNos[FileCnt - 1] = LineNo;
  1172. LinePoss[FileCnt - 1] = LinePos;
  1173. memcpy(CharQueues[FileCnt - 1], CharQueue, CharQueueLen);
  1174. // open the included file
  1175. if (nlen > MAX_FILE_NAME_LEN)
  1176. //error("File name too long\n");
  1177. errorFileName();
  1178. // DONE: differentiate between quot == '"' and quot == '<'
  1179. // First, try opening "file" in the current directory
  1180. // (Open Watcom C/C++ 1.9, Turbo C++ 1.01 use the current directory,
  1181. // unlike gcc, which uses the same directory as the current file)
  1182. if (quot == '"')
  1183. {
  1184. // Get path from c file to compile, so it can be appended to the include paths
  1185. char cFileDir[255] = "";
  1186. strcpy(cFileDir, FileNames[0]);
  1187. int len = strlen(cFileDir);
  1188. while (len > 0)
  1189. {
  1190. len--;
  1191. if (cFileDir[len] == '/')
  1192. {
  1193. cFileDir[len+1] = '\0'; // keep the slash
  1194. break;
  1195. }
  1196. }
  1197. if (len == 0) // remove directory if there is none
  1198. {
  1199. cFileDir[0] = '\0';
  1200. }
  1201. strcpy(FileNames[FileCnt], TokenValueString);
  1202. strcat(cFileDir, FileNames[FileCnt]);
  1203. Files[FileCnt] = fopen(cFileDir, "r");
  1204. }
  1205. // Next, iterate the search paths trying to open "file" or <file>.
  1206. // "file" is first searched using the list provided by the -I option.
  1207. // "file" is then searched using the list provided by the -SI option.
  1208. // <file> is searched using the list provided by the -SI option.
  1209. if (Files[FileCnt] == NULL)
  1210. {
  1211. int i;
  1212. char *paths = SearchPaths;
  1213. int pl = SearchPathsLen;
  1214. for (;;)
  1215. {
  1216. if (quot == '<')
  1217. {
  1218. paths = SysSearchPaths;
  1219. pl = SysSearchPathsLen;
  1220. }
  1221. for (i = 0; i < pl; )
  1222. {
  1223. int plen = strlen(paths + i);
  1224. if (plen + 1 + nlen < MAX_FILE_NAME_LEN)
  1225. {
  1226. strcpy(FileNames[FileCnt], paths + i);
  1227. strcpy(FileNames[FileCnt] + plen + 1, TokenValueString);
  1228. // Use '/' as a separator, typical for Linux/Unix,
  1229. // but also supported by file APIs in DOS/Windows just as '\\'
  1230. FileNames[FileCnt][plen] = '/';
  1231. if ((Files[FileCnt] = fopen(FileNames[FileCnt], "r")) != NULL)
  1232. break;
  1233. }
  1234. i += plen + 1;
  1235. }
  1236. if (Files[FileCnt] || quot == '<')
  1237. break;
  1238. quot = '<';
  1239. }
  1240. }
  1241. if (Files[FileCnt] == NULL)
  1242. {
  1243. //error("Cannot open file \"%s\"\n", TokenValueString);
  1244. errorFile(TokenValueString);
  1245. }
  1246. // reset line/pos and empty the char queue
  1247. CharQueueLen = 0;
  1248. LineNo = LinePos = 1;
  1249. FileCnt++;
  1250. // fill the char queue with file data
  1251. ShiftChar();
  1252. }
  1253. #endif // #ifndef NO_PREPROCESSOR
  1254. STATIC
  1255. int EndOfFiles(void)
  1256. {
  1257. // if there are no including files, we're done
  1258. if (!--FileCnt)
  1259. return 1;
  1260. // restore the including file's position and buffered chars
  1261. LineNo = LineNos[FileCnt - 1];
  1262. LinePos = LinePoss[FileCnt - 1];
  1263. CharQueueLen = 3;
  1264. memcpy(CharQueue, CharQueues[FileCnt - 1], CharQueueLen);
  1265. return 0;
  1266. }
  1267. STATIC
  1268. void SkipSpace(int SkipNewLines)
  1269. {
  1270. char* p = CharQueue;
  1271. while (*p != '\0')
  1272. {
  1273. if (strchr(" \t\f\v", *p))
  1274. {
  1275. ShiftCharN(1);
  1276. continue;
  1277. }
  1278. if (strchr("\r\n", *p))
  1279. {
  1280. if (!SkipNewLines)
  1281. return;
  1282. if (*p == '\r' && p[1] == '\n')
  1283. ShiftChar();
  1284. ShiftChar();
  1285. LineNo++;
  1286. LinePos = 1;
  1287. continue;
  1288. }
  1289. #ifndef NO_PREPROCESSOR
  1290. if (*p == '/')
  1291. {
  1292. if (p[1] == '/')
  1293. {
  1294. // // comment
  1295. ShiftCharN(2);
  1296. while (!strchr("\r\n", *p))
  1297. ShiftCharN(1);
  1298. continue;
  1299. }
  1300. else if (p[1] == '*')
  1301. {
  1302. // /**/ comment
  1303. ShiftCharN(2);
  1304. while (*p != '\0' && !(*p == '*' && p[1] == '/'))
  1305. {
  1306. if (strchr("\r\n", *p))
  1307. {
  1308. if (!SkipNewLines)
  1309. error("Invalid comment\n");
  1310. if (*p == '\r' && p[1] == '\n')
  1311. ShiftChar();
  1312. ShiftChar();
  1313. LineNo++;
  1314. LinePos = 1;
  1315. }
  1316. else
  1317. {
  1318. ShiftCharN(1);
  1319. }
  1320. }
  1321. if (*p == '\0')
  1322. error("Invalid comment\n");
  1323. ShiftCharN(2);
  1324. continue;
  1325. }
  1326. } // endof if (*p == '/')
  1327. #endif
  1328. break;
  1329. } // endof while (*p != '\0')
  1330. }
  1331. #ifndef NO_PREPROCESSOR
  1332. STATIC
  1333. void SkipLine(void)
  1334. {
  1335. char* p = CharQueue;
  1336. while (*p != '\0')
  1337. {
  1338. if (strchr("\r\n", *p))
  1339. {
  1340. if (*p == '\r' && p[1] == '\n')
  1341. ShiftChar();
  1342. ShiftChar();
  1343. LineNo++;
  1344. LinePos = 1;
  1345. break;
  1346. }
  1347. else
  1348. {
  1349. ShiftCharN(1);
  1350. }
  1351. }
  1352. }
  1353. #endif
  1354. STATIC
  1355. void GetIdent(void)
  1356. {
  1357. char* p = CharQueue;
  1358. if (*p != '_' && !isalpha(*p & 0xFFu))
  1359. error("Identifier expected\n");
  1360. #ifdef NO_WCHAR
  1361. if (*p == 'L' &&
  1362. (p[1] == '\'' || p[1] == '"'))
  1363. //error("Wide characters and strings not supported\n");
  1364. errorChrStr();
  1365. #endif
  1366. TokenIdentNameLen = 0;
  1367. TokenIdentName[TokenIdentNameLen++] = *p;
  1368. TokenIdentName[TokenIdentNameLen] = '\0';
  1369. ShiftCharN(1);
  1370. while (*p == '_' || isalnum(*p & 0xFFu))
  1371. {
  1372. if (TokenIdentNameLen == MAX_IDENT_LEN)
  1373. error("Identifier too long '%s'\n", TokenIdentName);
  1374. TokenIdentName[TokenIdentNameLen++] = *p;
  1375. TokenIdentName[TokenIdentNameLen] = '\0';
  1376. ShiftCharN(1);
  1377. }
  1378. }
  1379. STATIC
  1380. unsigned GetCharValue(int wide)
  1381. {
  1382. char* p = CharQueue;
  1383. unsigned ch = 0;
  1384. int cnt = 0;
  1385. #ifdef NO_WCHAR
  1386. (void)wide;
  1387. #endif
  1388. if (*p == '\\')
  1389. {
  1390. ShiftCharN(1);
  1391. if (strchr("\n\r", *p))
  1392. goto lerr;
  1393. if (*p == 'x')
  1394. {
  1395. // hexadecimal character codes \xN+
  1396. // hexadecimal escape sequence is not limited in length per se
  1397. // (may have many leading zeroes)
  1398. static char digs[] = "0123456789ABCDEFabcdef";
  1399. static char vals[] =
  1400. {
  1401. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  1402. 10, 11, 12, 13, 14, 15,
  1403. 10, 11, 12, 13, 14, 15
  1404. };
  1405. char* pp;
  1406. int zeroes = 0;
  1407. ShiftCharN(1);
  1408. if (strchr("\n\r", *p))
  1409. goto lerr;
  1410. if (*p == '0')
  1411. {
  1412. do
  1413. {
  1414. ShiftCharN(1);
  1415. } while (*p == '0');
  1416. zeroes = 1;
  1417. }
  1418. while (*p && (pp = strchr(digs, *p)) != NULL)
  1419. {
  1420. ch <<= 4;
  1421. ch |= vals[pp - digs];
  1422. ShiftCharN(1);
  1423. #ifndef NO_WCHAR
  1424. if (++cnt > (wide ? SizeOfWideChar * 2 : 2))
  1425. #else
  1426. if (++cnt > 2)
  1427. #endif
  1428. {
  1429. if (PrepDontSkipTokens)
  1430. goto lerr;
  1431. }
  1432. }
  1433. if (zeroes + cnt == 0)
  1434. goto lerr;
  1435. }
  1436. else if (*p >= '0' && *p <= '7')
  1437. {
  1438. // octal character codes \N+
  1439. // octal escape sequence is terminated after three octal digits
  1440. do
  1441. {
  1442. ch <<= 3;
  1443. ch |= *p - '0';
  1444. ShiftCharN(1);
  1445. ++cnt;
  1446. } while (*p >= '0' && *p <= '7' && cnt < 3);
  1447. if (ch >> 8)
  1448. goto lerr;
  1449. }
  1450. else
  1451. {
  1452. switch (*p)
  1453. {
  1454. case 'a': ch = '\a'; ShiftCharN(1); break;
  1455. case 'b': ch = '\b'; ShiftCharN(1); break;
  1456. case 'f': ch = '\f'; ShiftCharN(1); break;
  1457. case 'n': ch = '\n'; ShiftCharN(1); break;
  1458. case 'r': ch = '\r'; ShiftCharN(1); break;
  1459. case 't': ch = '\t'; ShiftCharN(1); break;
  1460. case 'v': ch = '\v'; ShiftCharN(1); break;
  1461. default:
  1462. goto lself;
  1463. }
  1464. }
  1465. }
  1466. else
  1467. {
  1468. lself:
  1469. if (strchr("\n\r", *p))
  1470. {
  1471. lerr:
  1472. //error("Unsupported or invalid character/string constant\n");
  1473. errorChrStr();
  1474. }
  1475. ch = *p & 0xFFu;
  1476. #ifndef NO_WCHAR
  1477. if (wide && ch > 0x7F && PrepDontSkipTokens)
  1478. error("Only ASCII chars supported as wide chars\n");
  1479. #endif
  1480. ShiftCharN(1);
  1481. }
  1482. return ch;
  1483. }
  1484. STATIC
  1485. void GetString(char terminator, int wide, int option)
  1486. {
  1487. char* p = CharQueue;
  1488. unsigned ch = '\0';
  1489. #ifndef NO_WCHAR
  1490. unsigned chsz = wide ? SizeOfWideChar : 1;
  1491. #else
  1492. unsigned chsz = 1;
  1493. #endif
  1494. int i;
  1495. TokenStringLen = 0;
  1496. TokenStringSize = 0;
  1497. TokenValueString[TokenStringLen] = '\0';
  1498. ShiftCharN(1);
  1499. while (!(*p == terminator || strchr("\n\r", *p)))
  1500. {
  1501. ch = GetCharValue(wide);
  1502. switch (option)
  1503. {
  1504. case '#': // string literal (with file name) for #line and #include
  1505. if (TokenStringLen == MAX_STRING_LEN)
  1506. errorStrLen();
  1507. TokenValueString[TokenStringLen++] = ch;
  1508. TokenValueString[TokenStringLen] = '\0';
  1509. TokenStringSize += chsz;
  1510. break;
  1511. case 'a': // string literal for asm()
  1512. printf2("%c", ch);
  1513. break;
  1514. case 'd': // string literal / array of char in expression or initializer
  1515. // Dump the char data to the appropriate data section
  1516. for (i = 0; i < chsz; i++)
  1517. {
  1518. GenDumpChar(ch & 0xFFu);
  1519. ch >>= 8;
  1520. TokenStringLen++; // GenDumpChar() expects it to grow, doesn't know about wchar_t
  1521. }
  1522. TokenStringLen -= chsz;
  1523. // fallthrough
  1524. default: // skipped string literal (we may still need the size)
  1525. if (TokenStringSize > UINT_MAX - chsz)
  1526. errorStrLen();
  1527. TokenStringSize += chsz;
  1528. TokenStringLen++;
  1529. break;
  1530. } // endof switch (option)
  1531. } // endof while (!(*p == '\0' || *p == terminator || strchr("\n\r", *p)))
  1532. if (*p != terminator)
  1533. //error("Unsupported or invalid character/string constant\n");
  1534. errorChrStr();
  1535. if (option == 'd')
  1536. GenDumpChar(-1);
  1537. ShiftCharN(1);
  1538. SkipSpace(option != '#');
  1539. }
  1540. #ifndef NO_PREPROCESSOR
  1541. STATIC
  1542. void pushPrep(int NoSkip)
  1543. {
  1544. if (PrepSp >= PREP_STACK_SIZE)
  1545. error("Too many #if(n)def's\n");
  1546. PrepStack[PrepSp][0] = PrepDontSkipTokens;
  1547. PrepStack[PrepSp++][1] = NoSkip;
  1548. PrepDontSkipTokens &= NoSkip;
  1549. }
  1550. STATIC
  1551. int popPrep(void)
  1552. {
  1553. if (PrepSp <= 0)
  1554. error("#else or #endif without #if(n)def\n");
  1555. PrepDontSkipTokens = PrepStack[--PrepSp][0];
  1556. return PrepStack[PrepSp][1];
  1557. }
  1558. #endif
  1559. #ifndef NO_FP
  1560. #include "fp.c"
  1561. #define FXNI2F 0
  1562. #define FXNU2F 1
  1563. #define FXNF2I 2
  1564. #define FXNF2U 3
  1565. #define FXNFADD 4
  1566. #define FXNFSUB 5
  1567. #define FXNFNEG 6
  1568. #define FXNFMUL 7
  1569. #define FXNFDIV 8
  1570. #define FXNFCMPL 9
  1571. #define FXNFCMPG 10
  1572. // Names of external functions for floating point arithmetic
  1573. char* FpFxnName[] =
  1574. {
  1575. /*FXNI2F */ "__floatsisf",
  1576. /*FXNU2F */ "__floatunsisf",
  1577. /*FXNF2I */ "__fixsfsi",
  1578. /*FXNF2U */ "__fixunssfsi",
  1579. /*FXNFADD */ "__addsf3",
  1580. /*FXNFSUB */ "__subsf3",
  1581. /*FXNFNEG */ "__negsf2",
  1582. /*FXNFMUL */ "__mulsf3",
  1583. /*FXNFDIV */ "__divsf3",
  1584. /*FXNFCMPL*/ "__lesf2",
  1585. /*FXNFCMPG*/ "__gesf2"
  1586. };
  1587. #endif
  1588. STATIC
  1589. int GetNumber(void)
  1590. {
  1591. char* p = CharQueue;
  1592. int ch = *p;
  1593. int leadingZero = (ch == '0');
  1594. unsigned n = 0;
  1595. int type = 0;
  1596. int uSuffix = 0;
  1597. #ifdef CAN_COMPILE_32BIT
  1598. int lSuffix = 0;
  1599. #endif
  1600. #ifndef NO_FP
  1601. int mcnt = 0, eexp = 0;
  1602. #endif
  1603. char* eTooBig = "Constant too big\n";
  1604. // First, detect and handle hex constants. Octals can't be detected immediately
  1605. // because floating-point constants also may begin with the digit 0.
  1606. if (leadingZero && (p[1] == 'x' || p[1] == 'X'))
  1607. {
  1608. // this is a hex constant
  1609. int cnt = 0;
  1610. type = 'h';
  1611. ShiftCharN(1);
  1612. ShiftCharN(1);
  1613. while ((ch = *p) != '\0' && (isdigit(ch & 0xFFu) || strchr("abcdefABCDEF", ch)))
  1614. {
  1615. if (ch >= 'a') ch -= 'a' - 10;
  1616. else if (ch >= 'A') ch -= 'A' - 10;
  1617. else ch -= '0';
  1618. //if (PrepDontSkipTokens && (n * 16 / 16 != n || n * 16 + ch < n * 16))
  1619. // error(eTooBig);
  1620. n = n * 16 + ch;
  1621. ShiftCharN(1);
  1622. cnt++;
  1623. }
  1624. if (!cnt)
  1625. error("Invalid hexadecimal constant\n");
  1626. }
  1627. #ifndef NO_FP
  1628. else
  1629. {
  1630. // this is a decimal (possibly floating-point) or an octal constant, parse as decimal
  1631. int mexp = 0, dot = 0;
  1632. int ecnt = 0;
  1633. type = 'd';
  1634. // skip leading zeroes, if any
  1635. while (*p == '0')
  1636. ShiftCharN(1);
  1637. // get digits of integral part, if any
  1638. while (isdigit((ch = *p) & 0xFFu))
  1639. {
  1640. if (mcnt < MAX_CONST_DIGITS)
  1641. ConstDigits[mcnt++] = ch - '0';
  1642. else
  1643. mexp++; // TBD??? overflow
  1644. ShiftCharN(1);
  1645. }
  1646. // get dot and digits of fractional part, if any
  1647. if (*p == '.')
  1648. {
  1649. dot = 1;
  1650. ShiftCharN(1);
  1651. // if the integral part is 0, skip leading zeroes in the fractional part, if any
  1652. if (!mcnt)
  1653. while (*p == '0')
  1654. ShiftCharN(1), mexp--; // TBD??? overflow
  1655. while (isdigit((ch = *p) & 0xFFu))
  1656. {
  1657. if (mcnt < MAX_CONST_DIGITS)
  1658. ConstDigits[mcnt++] = ch - '0';
  1659. mexp--; // TBD??? overflow
  1660. ShiftCharN(1);
  1661. }
  1662. }
  1663. // get exponent part, if any
  1664. if (*p == 'e' || *p == 'E')
  1665. {
  1666. int esign = '+';
  1667. ShiftCharN(1);
  1668. if (*p == '+' || *p == '-')
  1669. esign = *p, ShiftCharN(1);
  1670. while (isdigit((ch = *p) & 0xFFu))
  1671. {
  1672. ch -= '0';
  1673. if (//n * 10 / 10 != n ||
  1674. n * 10 + ch < n * 10 ||
  1675. n * 10 + ch > UINT_MAX >> 1)
  1676. {
  1677. if (PrepDontSkipTokens)
  1678. error(eTooBig);
  1679. n = 0;
  1680. }
  1681. n = n * 10 + ch;
  1682. ShiftCharN(1);
  1683. ecnt++;
  1684. }
  1685. if (!ecnt)
  1686. error("Invalid float constant\n");
  1687. eexp = n;
  1688. if (esign == '-')
  1689. eexp = -eexp;
  1690. }
  1691. if (dot || ecnt)
  1692. {
  1693. // this is a float constant (has either a dot or an exponent)
  1694. // get float suffix, if any
  1695. type = 'f';
  1696. if (*p == 'f' || *p == 'F' || *p == 'l' || *p == 'L')
  1697. ShiftCharN(1);
  1698. // also drop trailing zeroes, if any
  1699. while (mcnt)
  1700. {
  1701. if (ConstDigits[mcnt - 1])
  1702. break;
  1703. mexp++; // TBD??? overflow
  1704. mcnt--;
  1705. }
  1706. if (!mcnt)
  1707. ConstDigits[mcnt++] = 0, mexp = 0;
  1708. if ((mexp >= 0 && eexp > INT_MAX - mexp) ||
  1709. (mexp < 0 && eexp <= INT_MIN - (mexp + 1)))
  1710. {
  1711. if (PrepDontSkipTokens)
  1712. error(eTooBig);
  1713. }
  1714. else
  1715. eexp += mexp;
  1716. }
  1717. else
  1718. {
  1719. // handle decimal and octal integers
  1720. int base = leadingZero ? 8 : 10;
  1721. int i;
  1722. type = leadingZero ? 'o' : 'd';
  1723. for (i = 0; i < mcnt; i++)
  1724. {
  1725. ch = ConstDigits[i];
  1726. if (ch >= base)
  1727. error("Invalid octal constant\n");
  1728. //if (PrepDontSkipTokens && (n * base / base != n || n * base + ch < n * base))
  1729. // error(eTooBig);
  1730. n = n * base + ch;
  1731. }
  1732. }
  1733. }
  1734. #else
  1735. else
  1736. {
  1737. // handle decimal and octal integers
  1738. int base = leadingZero ? 8 : 10;
  1739. type = leadingZero ? 'o' : 'd';
  1740. while ((ch = *p) >= '0' && ch < base + '0')
  1741. {
  1742. ch -= '0';
  1743. if (PrepDontSkipTokens && (n * base + ch < n * base)) //n * base / base != n ||
  1744. error(eTooBig);
  1745. n = n * base + ch;
  1746. ShiftCharN(1);
  1747. }
  1748. }
  1749. #endif
  1750. // possible combinations of integer suffixes:
  1751. // none
  1752. // U
  1753. // UL
  1754. // L
  1755. // LU
  1756. #ifndef NO_FP
  1757. if (type != 'f')
  1758. #endif
  1759. {
  1760. if ((ch = *p) == 'u' || ch == 'U')
  1761. {
  1762. uSuffix = 1;
  1763. ShiftCharN(1);
  1764. }
  1765. #ifdef CAN_COMPILE_32BIT
  1766. if ((ch = *p) == 'l' || ch == 'L')
  1767. {
  1768. lSuffix = 1;
  1769. ShiftCharN(1);
  1770. if (!uSuffix && ((ch = *p) == 'u' || ch == 'U'))
  1771. {
  1772. uSuffix = 1;
  1773. ShiftCharN(1);
  1774. }
  1775. }
  1776. #endif
  1777. }
  1778. if (!PrepDontSkipTokens)
  1779. {
  1780. // Don't fail on big constants when skipping tokens under #if
  1781. TokenValueInt = 0;
  1782. return tokNumInt;
  1783. }
  1784. #ifndef NO_FP
  1785. if (type == 'f')
  1786. {
  1787. TokenValueInt = d2f(ConstDigits, mcnt, eexp);
  1788. return tokNumFloat;
  1789. }
  1790. #endif
  1791. // Ensure the constant fits into 16(32) bits
  1792. if (
  1793. (SizeOfWord == 2 && n >> 8 >> 8) // equiv. to SizeOfWord == 2 && n > 0xFFFF
  1794. #ifdef CAN_COMPILE_32BIT
  1795. || (SizeOfWord == 2 && lSuffix) // long (which must have at least 32 bits) isn't supported in 16-bit models
  1796. || (SizeOfWord == 4 && n >> 8 >> 12 >> 12) // equiv. to SizeOfWord == 4 && n > 0xFFFFFFFF
  1797. #endif
  1798. )
  1799. error("Constant too big for %d-bit type\n", SizeOfWord * 8);
  1800. TokenValueInt = (int)n;
  1801. // Unsuffixed (with 'u') integer constants (octal, decimal, hex)
  1802. // fitting into 15(31) out of 16(32) bits are signed ints
  1803. if (!uSuffix &&
  1804. (
  1805. (SizeOfWord == 2 && !(n >> 15)) // equiv. to SizeOfWord == 2 && n <= 0x7FFF
  1806. #ifdef CAN_COMPILE_32BIT
  1807. || (SizeOfWord == 4 && !(n >> 8 >> 12 >> 11)) // equiv. to SizeOfWord == 4 && n <= 0x7FFFFFFF
  1808. #endif
  1809. )
  1810. )
  1811. return tokNumInt;
  1812. // Unlike octal and hex constants, decimal constants are always
  1813. // a signed type. Error out when a decimal constant doesn't fit
  1814. // into an int since currently there's no next bigger signed type
  1815. // (e.g. long) to use instead of int.
  1816. if (!uSuffix && type == 'd')
  1817. error("Constant too big for %d-bit signed type\n", SizeOfWord * 8);
  1818. return tokNumUint;
  1819. }
  1820. STATIC
  1821. int GetTokenInner(void)
  1822. {
  1823. char* p = CharQueue;
  1824. int ch = *p;
  1825. int wide = 0;
  1826. // these single-character tokens/operators need no further processing
  1827. if (strchr(",;:()[]{}~?", ch))
  1828. {
  1829. ShiftCharN(1);
  1830. return ch;
  1831. }
  1832. // parse multi-character tokens/operators
  1833. // DONE: other assignment operators
  1834. switch (ch)
  1835. {
  1836. case '+':
  1837. if (p[1] == '+') { ShiftCharN(2); return tokInc; }
  1838. if (p[1] == '=') { ShiftCharN(2); return tokAssignAdd; }
  1839. ShiftCharN(1); return ch;
  1840. case '-':
  1841. if (p[1] == '-') { ShiftCharN(2); return tokDec; }
  1842. if (p[1] == '=') { ShiftCharN(2); return tokAssignSub; }
  1843. if (p[1] == '>') { ShiftCharN(2); return tokArrow; }
  1844. ShiftCharN(1); return ch;
  1845. case '!':
  1846. if (p[1] == '=') { ShiftCharN(2); return tokNEQ; }
  1847. ShiftCharN(1); return ch;
  1848. case '=':
  1849. if (p[1] == '=') { ShiftCharN(2); return tokEQ; }
  1850. ShiftCharN(1); return ch;
  1851. case '<':
  1852. if (p[1] == '=') { ShiftCharN(2); return tokLEQ; }
  1853. if (p[1] == '<') { ShiftCharN(2); if (p[0] != '=') return tokLShift; ShiftCharN(1); return tokAssignLSh; }
  1854. ShiftCharN(1); return ch;
  1855. case '>':
  1856. if (p[1] == '=') { ShiftCharN(2); return tokGEQ; }
  1857. if (p[1] == '>') { ShiftCharN(2); if (p[0] != '=') return tokRShift; ShiftCharN(1); return tokAssignRSh; }
  1858. ShiftCharN(1); return ch;
  1859. case '&':
  1860. if (p[1] == '&') { ShiftCharN(2); return tokLogAnd; }
  1861. if (p[1] == '=') { ShiftCharN(2); return tokAssignAnd; }
  1862. ShiftCharN(1); return ch;
  1863. case '|':
  1864. if (p[1] == '|') { ShiftCharN(2); return tokLogOr; }
  1865. if (p[1] == '=') { ShiftCharN(2); return tokAssignOr; }
  1866. ShiftCharN(1); return ch;
  1867. case '^':
  1868. if (p[1] == '=') { ShiftCharN(2); return tokAssignXor; }
  1869. ShiftCharN(1); return ch;
  1870. case '.':
  1871. if (p[1] == '.' && p[2] == '.') { ShiftCharN(3); return tokEllipsis; }
  1872. #ifndef NO_FP
  1873. if (isdigit(p[1] & 0xFFu)) { return GetNumber(); }
  1874. #endif
  1875. ShiftCharN(1); return ch;
  1876. case '*':
  1877. if (p[1] == '=') { ShiftCharN(2); return tokAssignMul; }
  1878. ShiftCharN(1); return ch;
  1879. case '%':
  1880. if (p[1] == '=') { ShiftCharN(2); return tokAssignMod; }
  1881. ShiftCharN(1); return ch;
  1882. case '/':
  1883. if (p[1] == '=') { ShiftCharN(2); return tokAssignDiv; }
  1884. ShiftCharN(1); return ch;
  1885. }
  1886. // DONE: hex and octal constants
  1887. if (isdigit(ch & 0xFFu))
  1888. return GetNumber();
  1889. // parse character and string constants
  1890. #ifndef NO_WCHAR
  1891. if (ch == 'L' && (p[1] == '\'' || p[1] == '"'))
  1892. {
  1893. wide = 1; ShiftCharN(1); ch = *p;
  1894. }
  1895. #endif
  1896. if (ch == '\'')
  1897. {
  1898. unsigned v = 0;
  1899. int cnt = 0;
  1900. #ifndef NO_WCHAR
  1901. int max_cnt = wide ? 1 : SizeOfWord;
  1902. #else
  1903. int max_cnt = SizeOfWord;
  1904. #endif
  1905. ShiftCharN(1);
  1906. if (strchr("'\n\r", *p))
  1907. //error("Character constant too short\n");
  1908. errorChrStr();
  1909. do
  1910. {
  1911. v <<= 8;
  1912. v |= GetCharValue(wide);
  1913. if (++cnt > max_cnt)
  1914. //error("Character constant too long\n");
  1915. errorChrStr();
  1916. } while (!strchr("'\n\r", *p));
  1917. if (*p != '\'')
  1918. //error("Unsupported or invalid character/string constant\n");
  1919. errorChrStr();
  1920. ShiftCharN(1);
  1921. #ifndef NO_WCHAR
  1922. if (wide)
  1923. {
  1924. TokenValueInt = v;
  1925. #ifdef CAN_COMPILE_32BIT
  1926. TokenValueInt -= (WideCharIsSigned && SizeOfWideChar == 2 &&
  1927. TokenValueInt >= 0x8000) * 0x10000;
  1928. #endif
  1929. return tokNumCharWide;
  1930. }
  1931. else
  1932. #endif
  1933. {
  1934. if (cnt == 1)
  1935. {
  1936. TokenValueInt = v;
  1937. TokenValueInt -= (CharIsSigned && TokenValueInt >= 0x80) * 0x100;
  1938. }
  1939. else
  1940. {
  1941. TokenValueInt = v;
  1942. #ifdef CAN_COMPILE_32BIT
  1943. TokenValueInt -= (SizeOfWord == 2 && TokenValueInt >= 0x8000) * 0x10000;
  1944. #endif
  1945. }
  1946. return tokNumInt;
  1947. }
  1948. }
  1949. else if (ch == '"')
  1950. {
  1951. // The caller of GetTokenInner()/GetToken() will call GetString('"', wide, 'd')
  1952. // to complete string literal parsing and storing as appropriate
  1953. #ifndef NO_WCHAR
  1954. return wide ? tokLitStrWide : tokLitStr;
  1955. #else
  1956. return tokLitStr;
  1957. #endif
  1958. }
  1959. return tokEof;
  1960. }
  1961. #ifndef NO_PREPROCESSOR
  1962. STATIC
  1963. void Reserve4Expansion(char* name, int len)
  1964. {
  1965. if (MAX_CHAR_QUEUE_LEN - CharQueueLen < len + 1)
  1966. error("Too long expansion of macro '%s'\n", name);
  1967. memmove(CharQueue + len + 1, CharQueue, CharQueueLen);
  1968. CharQueue[len] = ' '; // space to avoid concatenation
  1969. CharQueueLen += len + 1;
  1970. }
  1971. #endif
  1972. // TBD??? implement file I/O for input source code and output code (use fxn ptrs/wrappers to make librarization possible)
  1973. // DONE: support string literals
  1974. STATIC
  1975. int GetToken(void)
  1976. {
  1977. char* p = CharQueue;
  1978. int ch;
  1979. int tok;
  1980. for (;;)
  1981. {
  1982. /* +-~* /% &|^! << >> && || < <= > >= == != () *[] ++ -- = += -= ~= *= /= %= &= |= ^= <<= >>= {} ,;: -> ... */
  1983. // skip white space and comments
  1984. SkipSpace(1);
  1985. if ((ch = *p) == '\0')
  1986. {
  1987. // done with the current file, drop its record,
  1988. // pick up the including files (if any) or terminate
  1989. if (EndOfFiles())
  1990. break;
  1991. continue;
  1992. }
  1993. if ((tok = GetTokenInner()) != tokEof)
  1994. {
  1995. if (PrepDontSkipTokens)
  1996. return tok;
  1997. if (tok == tokLitStr)
  1998. GetString('"', 0, 0);
  1999. #ifndef NO_WCHAR
  2000. else if (tok == tokLitStrWide)
  2001. GetString('"', 1, 0);
  2002. #endif
  2003. continue;
  2004. }
  2005. // parse identifiers and reserved keywords
  2006. if (ch == '_' || isalpha(ch & 0xFFu))
  2007. {
  2008. #ifndef NO_PREPROCESSOR
  2009. int midx;
  2010. #endif
  2011. GetIdent();
  2012. if (!PrepDontSkipTokens)
  2013. continue;
  2014. tok = GetTokenByWord(TokenIdentName);
  2015. #ifndef NO_PREPROCESSOR
  2016. // TBD!!! think of expanding macros in the context of concatenating string literals,
  2017. // maybe factor out this piece of code
  2018. if (!strcmp(TokenIdentName, "__FILE__"))
  2019. {
  2020. char* p = FileNames[FileCnt - 1];
  2021. int len = strlen(p);
  2022. Reserve4Expansion(TokenIdentName, len + 2);
  2023. *CharQueue = '"';
  2024. memcpy(CharQueue + 1, p, len);
  2025. CharQueue[len + 1] = '"';
  2026. continue;
  2027. }
  2028. else if (!strcmp(TokenIdentName, "__LINE__"))
  2029. {
  2030. char s[(2 + CHAR_BIT * sizeof LineNo) / 3];
  2031. char *p = lab2str(s + sizeof s, LineNo);
  2032. int len = s + sizeof s - p;
  2033. Reserve4Expansion(TokenIdentName, len);
  2034. memcpy(CharQueue, p, len);
  2035. continue;
  2036. }
  2037. else if ((midx = FindMacro(TokenIdentName)) >= 0)
  2038. {
  2039. // this is a macro identifier, need to expand it
  2040. int len = MacroTable[midx];
  2041. Reserve4Expansion(TokenIdentName, len);
  2042. memcpy(CharQueue, MacroTable + midx + 1, len);
  2043. continue;
  2044. }
  2045. #endif
  2046. // treat keywords auto, const, register, restrict and volatile as white space for now
  2047. if ((tok == tokConst) | (tok == tokVolatile) |
  2048. (tok == tokAuto) | (tok == tokRegister) |
  2049. (tok == tokRestrict))
  2050. continue;
  2051. return tok;
  2052. } // endof if (ch == '_' || isalpha(ch))
  2053. // parse preprocessor directives
  2054. if (ch == '#')
  2055. {
  2056. int line = 0;
  2057. ShiftCharN(1);
  2058. // Skip space
  2059. SkipSpace(0);
  2060. // Allow # not followed by a directive
  2061. if (strchr("\r\n", *p))
  2062. continue;
  2063. // Get preprocessor directive
  2064. if (isdigit(*p & 0xFFu))
  2065. {
  2066. // gcc-style #line directive without "line"
  2067. line = 1;
  2068. }
  2069. else
  2070. {
  2071. GetIdent();
  2072. if (!strcmp(TokenIdentName, "line"))
  2073. {
  2074. // C89-style #line directive
  2075. SkipSpace(0);
  2076. if (!isdigit(*p & 0xFFu))
  2077. errorDirective();
  2078. line = 1;
  2079. }
  2080. }
  2081. if (line)
  2082. {
  2083. // Support for external, gcc-like, preprocessor output:
  2084. // # linenum filename flags
  2085. //
  2086. // no flags, flag = 1 -- start of a file
  2087. // flag = 2 -- return to a file after #include
  2088. // other flags -- uninteresting
  2089. // DONE: should also support the following C89 form:
  2090. // # line linenum filename-opt
  2091. if (GetNumber() != tokNumInt)
  2092. //error("Invalid line number in preprocessor output\n");
  2093. errorDirective();
  2094. line = TokenValueInt;
  2095. SkipSpace(0);
  2096. if (*p == '"' || *p == '<')
  2097. {
  2098. if (*p == '"')
  2099. GetString('"', 0, '#');
  2100. else
  2101. GetString('>', 0, '#');
  2102. if (strlen(TokenValueString) > MAX_FILE_NAME_LEN)
  2103. //error("File name too long in preprocessor output\n");
  2104. errorFileName();
  2105. strcpy(FileNames[FileCnt - 1], TokenValueString);
  2106. }
  2107. // Ignore gcc-style #line's flags, if any
  2108. while (!strchr("\r\n", *p))
  2109. ShiftCharN(1);
  2110. LineNo = line - 1; // "line" is the number of the next line
  2111. LinePos = 1;
  2112. continue;
  2113. } // endof if (line)
  2114. #ifndef NO_PPACK
  2115. if (!strcmp(TokenIdentName, "pragma"))
  2116. {
  2117. int canHaveNumber = 1, hadNumber = 0;
  2118. if (!PrepDontSkipTokens)
  2119. {
  2120. while (!strchr("\r\n", *p))
  2121. ShiftCharN(1);
  2122. continue;
  2123. }
  2124. SkipSpace(0);
  2125. GetIdent();
  2126. if (strcmp(TokenIdentName, "pack"))
  2127. errorDirective();
  2128. // TBD??? fail if inside a structure declaration
  2129. SkipSpace(0);
  2130. if (*p == '(')
  2131. ShiftCharN(1);
  2132. SkipSpace(0);
  2133. if (*p == 'p')
  2134. {
  2135. GetIdent();
  2136. if (!strcmp(TokenIdentName, "push"))
  2137. {
  2138. SkipSpace(0);
  2139. if (*p == ',')
  2140. {
  2141. ShiftCharN(1);
  2142. SkipSpace(0);
  2143. if (!isdigit(*p & 0xFFu) || GetNumber() != tokNumInt)
  2144. errorDirective();
  2145. hadNumber = 1;
  2146. }
  2147. if (PragmaPackSp >= PPACK_STACK_SIZE)
  2148. error("#pragma pack stack overflow\n");
  2149. PragmaPackValues[PragmaPackSp++] = PragmaPackValue;
  2150. }
  2151. else if (!strcmp(TokenIdentName, "pop"))
  2152. {
  2153. if (PragmaPackSp <= 0)
  2154. error("#pragma pack stack underflow\n");
  2155. PragmaPackValue = PragmaPackValues[--PragmaPackSp];
  2156. }
  2157. else
  2158. errorDirective();
  2159. SkipSpace(0);
  2160. canHaveNumber = 0;
  2161. }
  2162. if (canHaveNumber && isdigit(*p & 0xFFu))
  2163. {
  2164. if (GetNumber() != tokNumInt)
  2165. errorDirective();
  2166. hadNumber = 1;
  2167. SkipSpace(0);
  2168. }
  2169. if (hadNumber)
  2170. {
  2171. PragmaPackValue = TokenValueInt;
  2172. if (PragmaPackValue <= 0 ||
  2173. PragmaPackValue > SizeOfWord ||
  2174. PragmaPackValue & (PragmaPackValue - 1))
  2175. error("Invalid alignment value\n");
  2176. }
  2177. else if (canHaveNumber)
  2178. {
  2179. PragmaPackValue = SizeOfWord;
  2180. }
  2181. if (*p != ')')
  2182. errorDirective();
  2183. ShiftCharN(1);
  2184. SkipSpace(0);
  2185. if (!strchr("\r\n", *p))
  2186. errorDirective();
  2187. continue;
  2188. }
  2189. #endif
  2190. #ifndef NO_PREPROCESSOR
  2191. if (!strcmp(TokenIdentName, "define"))
  2192. {
  2193. // Skip space and get macro name
  2194. SkipSpace(0);
  2195. GetIdent();
  2196. if (!PrepDontSkipTokens)
  2197. {
  2198. SkipSpace(0);
  2199. while (!strchr("\r\n", *p))
  2200. ShiftCharN(1);
  2201. continue;
  2202. }
  2203. if (FindMacro(TokenIdentName) >= 0)
  2204. error("Redefinition of macro '%s'\n", TokenIdentName);
  2205. if (*p == '(')
  2206. //error("Unsupported type of macro '%s'\n", TokenIdentName);
  2207. errorDirective();
  2208. AddMacroIdent(TokenIdentName);
  2209. SkipSpace(0);
  2210. // accumulate the macro expansion text
  2211. while (!strchr("\r\n", *p))
  2212. {
  2213. AddMacroExpansionChar(*p);
  2214. ShiftCharN(1);
  2215. if (*p != '\0' && (strchr(" \t", *p) || (*p == '/' && (p[1] == '/' || p[1] == '*'))))
  2216. {
  2217. SkipSpace(0);
  2218. AddMacroExpansionChar(' ');
  2219. }
  2220. }
  2221. AddMacroExpansionChar('\0');
  2222. continue;
  2223. }
  2224. else if (!strcmp(TokenIdentName, "undef"))
  2225. {
  2226. // Skip space and get macro name
  2227. SkipSpace(0);
  2228. GetIdent();
  2229. if (PrepDontSkipTokens)
  2230. UndefineMacro(TokenIdentName);
  2231. SkipSpace(0);
  2232. if (!strchr("\r\n", *p))
  2233. //error("Invalid preprocessor directive\n");
  2234. errorDirective();
  2235. continue;
  2236. }
  2237. else if (!strcmp(TokenIdentName, "include"))
  2238. {
  2239. int quot;
  2240. // Skip space and get file name
  2241. SkipSpace(0);
  2242. quot = *p;
  2243. if (*p == '"')
  2244. GetString('"', 0, '#');
  2245. else if (*p == '<')
  2246. GetString('>', 0, '#');
  2247. else
  2248. //error("Invalid file name\n");
  2249. errorFileName();
  2250. SkipSpace(0);
  2251. if (!strchr("\r\n", *p))
  2252. //error("Unsupported or invalid preprocessor directive\n");
  2253. errorDirective();
  2254. if (PrepDontSkipTokens)
  2255. IncludeFile(quot);
  2256. continue;
  2257. }
  2258. else if (!strcmp(TokenIdentName, "ifdef"))
  2259. {
  2260. int def;
  2261. // Skip space and get macro name
  2262. SkipSpace(0);
  2263. GetIdent();
  2264. def = FindMacro(TokenIdentName) >= 0;
  2265. SkipSpace(0);
  2266. if (!strchr("\r\n", *p))
  2267. //error("Invalid preprocessor directive\n");
  2268. errorDirective();
  2269. pushPrep(def);
  2270. continue;
  2271. }
  2272. else if (!strcmp(TokenIdentName, "ifndef"))
  2273. {
  2274. int def;
  2275. // Skip space and get macro name
  2276. SkipSpace(0);
  2277. GetIdent();
  2278. def = FindMacro(TokenIdentName) >= 0;
  2279. SkipSpace(0);
  2280. if (!strchr("\r\n", *p))
  2281. //error("Invalid preprocessor directive\n");
  2282. errorDirective();
  2283. pushPrep(!def);
  2284. continue;
  2285. }
  2286. else if (!strcmp(TokenIdentName, "else"))
  2287. {
  2288. int def;
  2289. SkipSpace(0);
  2290. if (!strchr("\r\n", *p))
  2291. //error("Invalid preprocessor directive\n");
  2292. errorDirective();
  2293. def = popPrep();
  2294. if (def >= 2)
  2295. error("#else or #endif without #if(n)def\n");
  2296. pushPrep(2 + !def); // #else works in opposite way to its preceding #if(n)def
  2297. continue;
  2298. }
  2299. else if (!strcmp(TokenIdentName, "endif"))
  2300. {
  2301. SkipSpace(0);
  2302. if (!strchr("\r\n", *p))
  2303. //error("Invalid preprocessor directive\n");
  2304. errorDirective();
  2305. popPrep();
  2306. continue;
  2307. }
  2308. if (!PrepDontSkipTokens)
  2309. {
  2310. // If skipping code and directives under #ifdef/#ifndef/#else,
  2311. // ignore unsupported directives #if, #elif, #error (no error checking)
  2312. if (!strcmp(TokenIdentName, "if"))
  2313. pushPrep(0);
  2314. else if (!strcmp(TokenIdentName, "elif"))
  2315. popPrep(), pushPrep(0);
  2316. SkipLine();
  2317. continue;
  2318. }
  2319. #endif // #ifndef NO_PREPROCESSOR
  2320. //error("Unsupported or invalid preprocessor directive\n");
  2321. errorDirective();
  2322. } // endof if (ch == '#')
  2323. error("Invalid or unsupported character with code 0x%02X\n", *p & 0xFFu);
  2324. } // endof for (;;)
  2325. return tokEof;
  2326. }
  2327. STATIC
  2328. void errorRedecl(char* s)
  2329. {
  2330. error("Invalid or unsupported redeclaration of '%s'\n", s);
  2331. }
  2332. #ifndef CAN_COMPILE_32BIT
  2333. #error target requires a 32-bit compiler
  2334. #endif
  2335. #include "backend.c"
  2336. // expr.c code
  2337. STATIC
  2338. void push2(int v, int v2)
  2339. {
  2340. if (sp >= STACK_SIZE)
  2341. //error("expression stack overflow!\n");
  2342. errorLongExpr();
  2343. stack[sp][0] = v;
  2344. stack[sp++][1] = v2;
  2345. }
  2346. STATIC
  2347. void push(int v)
  2348. {
  2349. push2(v, 0);
  2350. }
  2351. STATIC
  2352. int stacktop()
  2353. {
  2354. if (sp == 0)
  2355. //error("expression stack underflow!\n");
  2356. errorInternal(3);
  2357. return stack[sp - 1][0];
  2358. }
  2359. STATIC
  2360. int pop2(int* v2)
  2361. {
  2362. int v = stacktop();
  2363. *v2 = stack[sp - 1][1];
  2364. sp--;
  2365. return v;
  2366. }
  2367. int pop()
  2368. {
  2369. int v2;
  2370. return pop2(&v2);
  2371. }
  2372. STATIC
  2373. void ins2(int pos, int v, int v2)
  2374. {
  2375. if (sp >= STACK_SIZE)
  2376. //error("expression stack overflow!\n");
  2377. errorLongExpr();
  2378. memmove(&stack[pos + 1], &stack[pos], sizeof(stack[0]) * (sp - pos));
  2379. stack[pos][0] = v;
  2380. stack[pos][1] = v2;
  2381. sp++;
  2382. }
  2383. STATIC
  2384. void ins(int pos, int v)
  2385. {
  2386. ins2(pos, v, 0);
  2387. }
  2388. STATIC
  2389. void del(int pos, int cnt)
  2390. {
  2391. memmove(stack[pos],
  2392. stack[pos + cnt],
  2393. sizeof(stack[0]) * (sp - (pos + cnt)));
  2394. sp -= cnt;
  2395. }
  2396. #ifndef NO_FP
  2397. STATIC
  2398. void rev(int pos, int cnt)
  2399. {
  2400. // reverse cnt items at pos on the stack
  2401. int (*p1)[2] = stack + pos, (*p2)[2] = p1 + cnt - 1;
  2402. while (p1 < p2)
  2403. {
  2404. int t0 = **p1;
  2405. int t1 = (*p1)[1];
  2406. **p1 = **p2;
  2407. (*p1++)[1] = (*p2)[1];
  2408. **p2 = t0;
  2409. (*p2--)[1] = t1;
  2410. }
  2411. }
  2412. STATIC
  2413. void swap(int pos, int cntlo, int cnthi)
  2414. {
  2415. // swap cntlo items at pos with cnthi items at pos + cntlo
  2416. rev(pos, cntlo);
  2417. rev(pos + cntlo, cnthi);
  2418. rev(pos, cntlo + cnthi);
  2419. }
  2420. #endif
  2421. STATIC
  2422. void pushop2(int v, int v2)
  2423. {
  2424. if (opsp >= OPERATOR_STACK_SIZE)
  2425. //error("operator stack overflow!\n");
  2426. errorLongExpr();
  2427. opstack[opsp][0] = v;
  2428. opstack[opsp++][1] = v2;
  2429. }
  2430. STATIC
  2431. void pushop(int v)
  2432. {
  2433. pushop2(v, 0);
  2434. }
  2435. STATIC
  2436. int opstacktop()
  2437. {
  2438. if (opsp == 0)
  2439. //error("operator stack underflow!\n");
  2440. errorInternal(4);
  2441. return opstack[opsp - 1][0];
  2442. }
  2443. STATIC
  2444. int popop2(int* v2)
  2445. {
  2446. int v = opstacktop();
  2447. *v2 = opstack[opsp - 1][1];
  2448. opsp--;
  2449. return v;
  2450. }
  2451. STATIC
  2452. int popop()
  2453. {
  2454. int v2;
  2455. return popop2(&v2);
  2456. }
  2457. STATIC
  2458. int isop(int tok)
  2459. {
  2460. static unsigned char toks[] =
  2461. {
  2462. '!',
  2463. '~',
  2464. '&',
  2465. '*',
  2466. '/', '%',
  2467. '+', '-',
  2468. '|', '^',
  2469. '<', '>',
  2470. '=',
  2471. tokLogOr, tokLogAnd,
  2472. tokEQ, tokNEQ,
  2473. tokLEQ, tokGEQ,
  2474. tokLShift, tokRShift,
  2475. tokInc, tokDec,
  2476. tokSizeof,
  2477. tokAssignMul, tokAssignDiv, tokAssignMod,
  2478. tokAssignAdd, tokAssignSub,
  2479. tokAssignLSh, tokAssignRSh,
  2480. tokAssignAnd, tokAssignXor, tokAssignOr,
  2481. tokComma,
  2482. '?'
  2483. };
  2484. unsigned i;
  2485. for (i = 0; i < division(sizeof toks , sizeof toks[0]); i++)
  2486. if (toks[i] == tok)
  2487. return 1;
  2488. return 0;
  2489. }
  2490. STATIC
  2491. int isunary(int tok)
  2492. {
  2493. return (tok == '!') | (tok == '~') | (tok == tokInc) | (tok == tokDec) | (tok == tokSizeof);
  2494. }
  2495. STATIC
  2496. int preced(int tok)
  2497. {
  2498. switch (tok)
  2499. {
  2500. case '*': case '/': case '%': return 13;
  2501. case '+': case '-': return 12;
  2502. case tokLShift: case tokRShift: return 11;
  2503. case '<': case '>': case tokLEQ: case tokGEQ: return 10;
  2504. case tokEQ: case tokNEQ: return 9;
  2505. case '&': return 8;
  2506. case '^': return 7;
  2507. case '|': return 6;
  2508. case tokLogAnd: return 5;
  2509. case tokLogOr: return 4;
  2510. case '?': case ':': return 3;
  2511. case '=':
  2512. case tokAssignMul: case tokAssignDiv: case tokAssignMod:
  2513. case tokAssignAdd: case tokAssignSub:
  2514. case tokAssignLSh: case tokAssignRSh:
  2515. case tokAssignAnd: case tokAssignXor: case tokAssignOr:
  2516. return 2;
  2517. case tokComma:
  2518. return 1;
  2519. }
  2520. return 0;
  2521. }
  2522. STATIC
  2523. int precedGEQ(int lfttok, int rhttok)
  2524. {
  2525. // DONE: rethink the comma operator as it could be implemented similarly
  2526. // DONE: is this correct:???
  2527. int pl = preced(lfttok);
  2528. int pr = preced(rhttok);
  2529. // ternary/conditional operator ?: is right-associative
  2530. if (pl == 3 && pr >= 3)
  2531. pl = 0;
  2532. // assignment is right-associative
  2533. if (pl == 2 && pr >= 2)
  2534. pl = 0;
  2535. return pl >= pr;
  2536. }
  2537. STATIC
  2538. int expr(int tok, int* gotUnary, int commaSeparator);
  2539. STATIC
  2540. char* lab2str(char* p, int n)
  2541. {
  2542. do
  2543. {
  2544. *--p = '0' + modulo(n , 10);
  2545. n = division(n, 10);
  2546. } while (n);
  2547. return p;
  2548. }
  2549. STATIC
  2550. int exprUnary(int tok, int* gotUnary, int commaSeparator, int argOfSizeOf)
  2551. {
  2552. static int sizeofLevel = 0;
  2553. int decl = 0;
  2554. *gotUnary = 0;
  2555. if (isop(tok) && (isunary(tok) || strchr("&*+-", tok)))
  2556. {
  2557. int lastTok = tok;
  2558. int sizeofLevelInc = lastTok == tokSizeof;
  2559. sizeofLevel += sizeofLevelInc;
  2560. tok = exprUnary(GetToken(), gotUnary, commaSeparator, sizeofLevelInc);
  2561. sizeofLevel -= sizeofLevelInc;
  2562. if (!*gotUnary)
  2563. //error("exprUnary(): primary expression expected after token %s\n", GetTokenName(lastTok));
  2564. errorUnexpectedToken(tok);
  2565. switch (lastTok)
  2566. {
  2567. // DONE: remove all collapsing of all unary operators.
  2568. // It's wrong because type checking must occur before any optimizations.
  2569. // WRONG: DONE: collapse alternating & and * (e.g. "*&*&x" "&*&*x")
  2570. // WRONGISH: DONE: replace prefix ++/-- with +=1/-=1
  2571. case '&':
  2572. push(tokUnaryAnd);
  2573. break;
  2574. case '*':
  2575. push(tokUnaryStar);
  2576. break;
  2577. case '+':
  2578. push(tokUnaryPlus);
  2579. break;
  2580. case '-':
  2581. push(tokUnaryMinus);
  2582. break;
  2583. case '!':
  2584. // replace "!" with "== 0"
  2585. push(tokNumInt);
  2586. push(tokEQ);
  2587. break;
  2588. default:
  2589. push(lastTok);
  2590. break;
  2591. }
  2592. }
  2593. else
  2594. {
  2595. int inspos = sp;
  2596. if (tok == tokNumInt ||
  2597. #ifndef NO_FP
  2598. tok == tokNumFloat ||
  2599. #endif
  2600. #ifndef NO_WCHAR
  2601. tok == tokNumCharWide ||
  2602. #endif
  2603. tok == tokNumUint)
  2604. {
  2605. push2(tok, TokenValueInt);
  2606. *gotUnary = 1;
  2607. tok = GetToken();
  2608. }
  2609. else if (tok == tokLitStr
  2610. #ifndef NO_WCHAR
  2611. || tok == tokLitStrWide
  2612. #endif
  2613. )
  2614. {
  2615. int lbl = LabelCnt++;
  2616. int id;
  2617. int ltok = tok;
  2618. #ifndef NO_WCHAR
  2619. int wide = tok == tokLitStrWide;
  2620. unsigned chsz = wide ? SizeOfWideChar : 1;
  2621. #else
  2622. int wide = 0;
  2623. unsigned chsz = 1;
  2624. #endif
  2625. unsigned sz = chsz;
  2626. // imitate definition: char #[len] = "...";
  2627. if (!sizeofLevel)
  2628. {
  2629. if (CurHeaderFooter)
  2630. puts2(CurHeaderFooter[1]);
  2631. puts2(RoDataHeaderFooter[0]);
  2632. #ifndef NO_WCHAR
  2633. if (wide)
  2634. GenWordAlignment(0);
  2635. #endif
  2636. GenNumLabel(lbl);
  2637. }
  2638. do
  2639. {
  2640. GetString('"', wide, sizeofLevel ? 0 : 'd'); // throw away string data inside sizeof, e.g. sizeof "a" or sizeof("a" + 1)
  2641. if (sz + TokenStringSize < sz ||
  2642. sz + TokenStringSize >= truncUint(-1))
  2643. errorStrLen();
  2644. sz += TokenStringSize;
  2645. tok = GetToken();
  2646. } while (tok == ltok); // concatenate adjacent string literals
  2647. #ifndef NO_WCHAR
  2648. if ((ltok ^ (tokLitStr ^ tokLitStrWide)) == tok)
  2649. errorWideNonWide();
  2650. #endif
  2651. if (!sizeofLevel)
  2652. {
  2653. GenZeroData(chsz, 0);
  2654. puts2(RoDataHeaderFooter[1]);
  2655. if (CurHeaderFooter)
  2656. puts2(CurHeaderFooter[0]);
  2657. }
  2658. // DONE: can this break incomplete yet declarations???, e.g.: int x[sizeof("az")][5];
  2659. PushSyntax2(tokIdent, id = AddNumericIdent(lbl));
  2660. PushSyntax('[');
  2661. PushSyntax2(tokNumUint, division(sz, chsz));
  2662. PushSyntax(']');
  2663. #ifndef NO_WCHAR
  2664. PushSyntax(wide ? WideCharType1 : tokChar);
  2665. #else
  2666. PushSyntax(tokChar);
  2667. #endif
  2668. push2(tokIdent, id);
  2669. *gotUnary = 1;
  2670. }
  2671. else if (tok == tokIdent)
  2672. {
  2673. push2(tok, AddIdent(TokenIdentName));
  2674. *gotUnary = 1;
  2675. tok = GetToken();
  2676. }
  2677. else if (tok == '(')
  2678. {
  2679. tok = GetToken();
  2680. decl = TokenStartsDeclaration(tok, 1);
  2681. if (decl)
  2682. {
  2683. int synPtr;
  2684. int lbl = LabelCnt++;
  2685. char s[1 + (2 + CHAR_BIT * sizeof lbl) / 3 + sizeof "<something>" - 1];
  2686. char *p = s + sizeof s;
  2687. tok = ParseDecl(tok, NULL, !argOfSizeOf, 0);
  2688. if (tok != ')')
  2689. //error("exprUnary(): ')' expected, unexpected token %s\n", GetTokenName(tok));
  2690. errorUnexpectedToken(tok);
  2691. synPtr = FindSymbol("<something>");
  2692. // Rename "<something>" to "<something#>", where # is lbl.
  2693. // This makes the nameless declaration uniquely identifiable by name.
  2694. *--p = '\0';
  2695. *--p = ")>"[argOfSizeOf]; // differentiate casts (something#) from not casts <something#>
  2696. p = lab2str(p, lbl);
  2697. p -= sizeof "<something>" - 2 - 1;
  2698. memcpy(p, "something", sizeof "something" - 1);
  2699. *--p = "(<"[argOfSizeOf]; // differentiate casts (something#) from not casts <something#>
  2700. SyntaxStack1[synPtr] = AddIdent(p);
  2701. tok = GetToken();
  2702. if (argOfSizeOf)
  2703. {
  2704. // expression: sizeof(type)
  2705. *gotUnary = 1;
  2706. }
  2707. else
  2708. {
  2709. // unary type cast operator: (type)
  2710. decl = 0;
  2711. tok = exprUnary(tok, gotUnary, commaSeparator, 0);
  2712. if (!*gotUnary)
  2713. //error("exprUnary(): primary expression expected after '(type)'\n");
  2714. errorUnexpectedToken(tok);
  2715. }
  2716. push2(tokIdent, SyntaxStack1[synPtr]);
  2717. }
  2718. else
  2719. {
  2720. tok = expr(tok, gotUnary, 0);
  2721. if (tok != ')')
  2722. //error("exprUnary(): ')' expected, unexpected token %s\n", GetTokenName(tok));
  2723. errorUnexpectedToken(tok);
  2724. if (!*gotUnary)
  2725. //error("exprUnary(): primary expression expected in '()'\n");
  2726. errorUnexpectedToken(tok);
  2727. tok = GetToken();
  2728. }
  2729. }
  2730. while (*gotUnary && !decl)
  2731. {
  2732. // DONE: f(args1)(args2) and the like: need stack order: args2, args1, f, (), ()
  2733. // DONE: reverse the order of evaluation of groups of args in
  2734. // f(args1)(args2)(args3)
  2735. // DONE: reverse the order of function argument evaluation for variadic functions
  2736. // we want 1st arg to be the closest to the stack top.
  2737. // DONE: (args)[index] can be repeated interchangeably indefinitely
  2738. // DONE: (expr)() & (expr)[]
  2739. // DONE: [index] can be followed by ++/--, which can be followed by [index] and so on...
  2740. // DONE: postfix ++/-- & differentiate from prefix ++/--
  2741. if (tok == '(')
  2742. {
  2743. int acnt = 0;
  2744. ins(inspos, '(');
  2745. for (;;)
  2746. {
  2747. int pos2 = sp;
  2748. tok = GetToken();
  2749. tok = expr(tok, gotUnary, 1);
  2750. // Reverse the order of argument evaluation, which is important for
  2751. // variadic functions like printf():
  2752. // we want 1st arg to be the closest to the stack top.
  2753. // This also reverses the order of evaluation of all groups of
  2754. // arguments.
  2755. while (pos2 < sp)
  2756. {
  2757. // TBD??? not quite efficient
  2758. int v, v2;
  2759. v = pop2(&v2);
  2760. ins2(inspos + 1, v, v2);
  2761. pos2++;
  2762. }
  2763. if (tok == ',')
  2764. {
  2765. if (!*gotUnary)
  2766. //error("exprUnary(): primary expression (fxn argument) expected before ','\n");
  2767. errorUnexpectedToken(tok);
  2768. acnt++;
  2769. ins(inspos + 1, ','); // helper argument separator (hint for expression evaluator)
  2770. continue; // off to next arg
  2771. }
  2772. if (tok == ')')
  2773. {
  2774. if (acnt && !*gotUnary)
  2775. //error("exprUnary(): primary expression (fxn argument) expected between ',' and ')'\n");
  2776. errorUnexpectedToken(tok);
  2777. *gotUnary = 1; // don't fail for 0 args in ()
  2778. break; // end of args
  2779. }
  2780. // DONE: think of inserting special arg pseudo tokens for verification purposes
  2781. //error("exprUnary(): ',' or ')' expected, unexpected token %s\n", GetTokenName(tok));
  2782. errorUnexpectedToken(tok);
  2783. } // endof for(;;) for fxn args
  2784. push(')');
  2785. }
  2786. else if (tok == '[')
  2787. {
  2788. tok = GetToken();
  2789. tok = expr(tok, gotUnary, 0);
  2790. if (!*gotUnary)
  2791. //error("exprUnary(): primary expression expected in '[]'\n");
  2792. errorUnexpectedToken(tok);
  2793. if (tok != ']')
  2794. //error("exprUnary(): ']' expected, unexpected token %s\n", GetTokenName(tok));
  2795. errorUnexpectedToken(tok);
  2796. // TBD??? add implicit casts to size_t of array indicies.
  2797. // E1[E2] -> *(E1 + E2)
  2798. // push('[');
  2799. push('+');
  2800. push(tokUnaryStar);
  2801. }
  2802. // WRONG: DONE: replace postfix ++/-- with (+=1)-1/(-=1)+1
  2803. else if (tok == tokInc)
  2804. {
  2805. push(tokPostInc);
  2806. }
  2807. else if (tok == tokDec)
  2808. {
  2809. push(tokPostDec);
  2810. }
  2811. else if (tok == '.' || tok == tokArrow)
  2812. {
  2813. // transform a.b into (&a)->b
  2814. if (tok == '.')
  2815. push(tokUnaryAnd);
  2816. tok = GetToken();
  2817. if (tok != tokIdent)
  2818. errorUnexpectedToken(tok);
  2819. push2(tok, AddIdent(TokenIdentName));
  2820. // "->" in "a->b" will function as "+" in "*(type_of_b*)((char*)a + offset_of_b_in_a)"
  2821. push(tokArrow);
  2822. push(tokUnaryStar);
  2823. }
  2824. else
  2825. {
  2826. break;
  2827. }
  2828. tok = GetToken();
  2829. } // endof while (*gotUnary)
  2830. }
  2831. if (tok == ',' && !commaSeparator)
  2832. tok = tokComma;
  2833. return tok;
  2834. }
  2835. STATIC
  2836. int expr(int tok, int* gotUnary, int commaSeparator)
  2837. {
  2838. *gotUnary = 0;
  2839. pushop(tokEof);
  2840. tok = exprUnary(tok, gotUnary, commaSeparator, 0);
  2841. while (tok != tokEof && strchr(",;:)]}", tok) == NULL && *gotUnary)
  2842. {
  2843. if (isop(tok) && !isunary(tok))
  2844. {
  2845. while (precedGEQ(opstacktop(), tok))
  2846. {
  2847. int v, v2;
  2848. v = popop2(&v2);
  2849. // move ?expr: as a whole to the expression stack as "expr?"
  2850. if (v == '?')
  2851. {
  2852. int cnt = v2;
  2853. while (cnt--)
  2854. {
  2855. v = popop2(&v2);
  2856. push2(v, v2);
  2857. }
  2858. v = '?';
  2859. v2 = 0;
  2860. }
  2861. push2(v, v2);
  2862. }
  2863. // here: preced(postacktop()) < preced(tok)
  2864. // treat the ternary/conditional operator ?expr: as a pseudo binary operator
  2865. if (tok == '?')
  2866. {
  2867. int ssp = sp;
  2868. int cnt;
  2869. tok = expr(GetToken(), gotUnary, 0);
  2870. if (!*gotUnary || tok != ':')
  2871. errorUnexpectedToken(tok);
  2872. // move ?expr: as a whole to the operator stack
  2873. // this is beautiful and ugly at the same time
  2874. cnt = sp - ssp;
  2875. while (sp > ssp)
  2876. {
  2877. int v, v2;
  2878. v = pop2(&v2);
  2879. pushop2(v, v2);
  2880. }
  2881. // remember the length of the expression between ? and :
  2882. pushop2('?', cnt);
  2883. }
  2884. else
  2885. {
  2886. pushop(tok);
  2887. }
  2888. tok = exprUnary(GetToken(), gotUnary, commaSeparator, 0);
  2889. // DONE: figure out a check to see if exprUnary() fails to add a rhs operand
  2890. if (!*gotUnary)
  2891. //error("expr(): primary expression expected after token %s\n", GetTokenName(lastTok));
  2892. errorUnexpectedToken(tok);
  2893. continue;
  2894. }
  2895. //error("expr(): Unexpected token %s\n", GetTokenName(tok));
  2896. errorUnexpectedToken(tok);
  2897. }
  2898. while (opstacktop() != tokEof)
  2899. {
  2900. int v, v2;
  2901. v = popop2(&v2);
  2902. // move ?expr: as a whole to the expression stack as "expr?"
  2903. if (v == '?')
  2904. {
  2905. int cnt = v2;
  2906. while (cnt--)
  2907. {
  2908. v = popop2(&v2);
  2909. push2(v, v2);
  2910. }
  2911. v = '?';
  2912. v2 = 0;
  2913. }
  2914. push2(v, v2);
  2915. }
  2916. popop();
  2917. return tok;
  2918. }
  2919. STATIC
  2920. int isAnyPtr(int ExprTypeSynPtr)
  2921. {
  2922. if (ExprTypeSynPtr < 0)
  2923. return 1;
  2924. switch (SyntaxStack0[ExprTypeSynPtr])
  2925. {
  2926. case '*':
  2927. case '[':
  2928. case '(':
  2929. return 1;
  2930. }
  2931. return 0;
  2932. }
  2933. STATIC
  2934. int derefAnyPtr(int ExprTypeSynPtr)
  2935. {
  2936. if (ExprTypeSynPtr < 0)
  2937. return -ExprTypeSynPtr;
  2938. switch (SyntaxStack0[ExprTypeSynPtr])
  2939. {
  2940. case '*':
  2941. return ExprTypeSynPtr + 1;
  2942. case '[':
  2943. return ExprTypeSynPtr + 3;
  2944. case '(':
  2945. return ExprTypeSynPtr;
  2946. }
  2947. errorInternal(22);
  2948. return -1;
  2949. }
  2950. STATIC
  2951. void decayArray(int* ExprTypeSynPtr, int arithmetic)
  2952. {
  2953. // Dacay arrays to pointers to their first elements
  2954. if (*ExprTypeSynPtr >= 0 && SyntaxStack0[*ExprTypeSynPtr] == '[')
  2955. {
  2956. (*ExprTypeSynPtr) += 3;
  2957. // we cannot insert another '*' into the type to make it a pointer
  2958. // to the first element, so make the index into the type negative
  2959. *ExprTypeSynPtr = -*ExprTypeSynPtr;
  2960. }
  2961. // DONE: disallow arithmetic on pointers to void
  2962. // DONE: disallow function pointers
  2963. if (arithmetic && isAnyPtr(*ExprTypeSynPtr))
  2964. {
  2965. int pointee = derefAnyPtr(*ExprTypeSynPtr);
  2966. switch (SyntaxStack0[pointee])
  2967. {
  2968. case tokVoid:
  2969. //error("decayArray(): cannot do pointer arithmetic on a pointer to 'void'\n");
  2970. errorUnexpectedVoid();
  2971. default:
  2972. //error("decayArray(): cannot do pointer arithmetic on a pointer to an incomplete type\n");
  2973. if (!GetDeclSize(pointee, 0))
  2974. // "fallthrough"
  2975. case '(':
  2976. //error("decayArray(): cannot do pointer arithmetic on a pointer to a function\n");
  2977. errorOpType();
  2978. }
  2979. }
  2980. }
  2981. STATIC
  2982. void lvalueCheck(int ExprTypeSynPtr, int pos)
  2983. {
  2984. if (ExprTypeSynPtr >= 0 &&
  2985. (SyntaxStack0[ExprTypeSynPtr] == '[' || SyntaxStack0[ExprTypeSynPtr] == '('))
  2986. {
  2987. // we can have arrays formed by dereference, e.g.
  2988. // char (*pac)[1]; // *pac is array of 1 char
  2989. // // ++*pac or (*pac)-- are not allowed
  2990. // and likewise functions, e.g.
  2991. // int (*pf)(int); // *pf is a function taking int and returning int
  2992. // // *pf = 0; is not allowed
  2993. // and that dereference shouldn't be confused for lvalue,
  2994. // hence explicitly checking for array and function types
  2995. //error("exprval(): lvalue expected\n");
  2996. errorNotLvalue();
  2997. }
  2998. // lvalue is a dereferenced address, check for a dereference
  2999. if (stack[pos][0] != tokUnaryStar)
  3000. //error("exprval(): lvalue expected\n");
  3001. errorNotLvalue();
  3002. }
  3003. STATIC
  3004. void nonVoidTypeCheck(int ExprTypeSynPtr)
  3005. {
  3006. if (ExprTypeSynPtr >= 0 && SyntaxStack0[ExprTypeSynPtr] == tokVoid)
  3007. //error("nonVoidTypeCheck(): unexpected operand type 'void' for operator '%s'\n", GetTokenName(tok));
  3008. errorUnexpectedVoid();
  3009. }
  3010. STATIC
  3011. void scalarTypeCheck(int ExprTypeSynPtr)
  3012. {
  3013. nonVoidTypeCheck(ExprTypeSynPtr);
  3014. if (ExprTypeSynPtr >= 0 && SyntaxStack0[ExprTypeSynPtr] == tokStructPtr)
  3015. errorOpType();
  3016. }
  3017. STATIC
  3018. void numericTypeCheck(int ExprTypeSynPtr)
  3019. {
  3020. if (ExprTypeSynPtr >= 0)
  3021. switch (SyntaxStack0[ExprTypeSynPtr])
  3022. {
  3023. case tokChar:
  3024. case tokSChar:
  3025. case tokUChar:
  3026. #ifdef CAN_COMPILE_32BIT
  3027. case tokShort:
  3028. case tokUShort:
  3029. #endif
  3030. case tokInt:
  3031. case tokUnsigned:
  3032. #ifndef NO_FP
  3033. case tokFloat:
  3034. #endif
  3035. return;
  3036. }
  3037. //error("numericTypeCheck(): unexpected operand type for operator '%s', numeric type expected\n", GetTokenName(tok));
  3038. errorOpType();
  3039. }
  3040. #ifndef NO_FP
  3041. STATIC
  3042. void nonFloatTypeCheck(int ExprTypeSynPtr)
  3043. {
  3044. if (ExprTypeSynPtr >= 0 && SyntaxStack0[ExprTypeSynPtr] == tokFloat)
  3045. errorOpType();
  3046. }
  3047. #endif
  3048. STATIC
  3049. void anyIntTypeCheck(int ExprTypeSynPtr)
  3050. {
  3051. // Check for any integer type
  3052. numericTypeCheck(ExprTypeSynPtr);
  3053. #ifndef NO_FP
  3054. nonFloatTypeCheck(ExprTypeSynPtr);
  3055. #endif
  3056. }
  3057. #ifndef NO_FP
  3058. STATIC
  3059. int isFloat(int ExprTypeSynPtr)
  3060. {
  3061. return ExprTypeSynPtr >= 0 && SyntaxStack0[ExprTypeSynPtr] == tokFloat;
  3062. }
  3063. #endif
  3064. STATIC
  3065. int isUint(int ExprTypeSynPtr)
  3066. {
  3067. return ExprTypeSynPtr >= 0 && SyntaxStack0[ExprTypeSynPtr] == tokUnsigned;
  3068. }
  3069. STATIC
  3070. void compatCheck(int* ExprTypeSynPtr, int TheOtherExprTypeSynPtr, int ConstExpr[2], int lidx, int ridx)
  3071. {
  3072. int exprTypeSynPtr = *ExprTypeSynPtr;
  3073. int c = 0;
  3074. int lptr, rptr, lnum, rnum;
  3075. // (un)decay/convert functions to pointers to functions
  3076. // and to simplify matters convert all '*' pointers to negative type indices
  3077. if (exprTypeSynPtr >= 0)
  3078. {
  3079. switch (SyntaxStack0[exprTypeSynPtr])
  3080. {
  3081. case '*':
  3082. exprTypeSynPtr++;
  3083. // fallthrough
  3084. case '(':
  3085. exprTypeSynPtr = -exprTypeSynPtr;
  3086. }
  3087. *ExprTypeSynPtr = exprTypeSynPtr;
  3088. }
  3089. if (TheOtherExprTypeSynPtr >= 0)
  3090. {
  3091. switch (SyntaxStack0[TheOtherExprTypeSynPtr])
  3092. {
  3093. case '*':
  3094. TheOtherExprTypeSynPtr++;
  3095. // fallthrough
  3096. case '(':
  3097. TheOtherExprTypeSynPtr = -TheOtherExprTypeSynPtr;
  3098. }
  3099. }
  3100. lptr = exprTypeSynPtr < 0;
  3101. rptr = TheOtherExprTypeSynPtr < 0;
  3102. lnum = !lptr && (SyntaxStack0[exprTypeSynPtr] == tokInt ||
  3103. #ifndef NO_FP
  3104. SyntaxStack0[exprTypeSynPtr] == tokFloat ||
  3105. #endif
  3106. SyntaxStack0[exprTypeSynPtr] == tokUnsigned);
  3107. rnum = !rptr && (SyntaxStack0[TheOtherExprTypeSynPtr] == tokInt ||
  3108. #ifndef NO_FP
  3109. SyntaxStack0[TheOtherExprTypeSynPtr] == tokFloat ||
  3110. #endif
  3111. SyntaxStack0[TheOtherExprTypeSynPtr] == tokUnsigned);
  3112. // both operands have arithmetic type
  3113. // (arithmetic operands have been already promoted):
  3114. if (lnum && rnum)
  3115. return;
  3116. // both operands have void type:
  3117. if (!lptr && SyntaxStack0[exprTypeSynPtr] == tokVoid &&
  3118. !rptr && SyntaxStack0[TheOtherExprTypeSynPtr] == tokVoid)
  3119. return;
  3120. // one operand is a pointer and the other is NULL constant
  3121. // ((void*)0 is also a valid null pointer constant),
  3122. // the type of the expression is that of the pointer:
  3123. if (lptr &&
  3124. ((rnum && ConstExpr[1] && truncInt(stack[ridx][1]) == 0) ||
  3125. (rptr && SyntaxStack0[-TheOtherExprTypeSynPtr] == tokVoid &&
  3126. (stack[ridx][0] == tokNumInt || stack[ridx][0] == tokNumUint) &&
  3127. truncInt(stack[ridx][1]) == 0)))
  3128. return;
  3129. if (rptr &&
  3130. ((lnum && ConstExpr[0] && truncInt(stack[lidx][1]) == 0) ||
  3131. (lptr && SyntaxStack0[-exprTypeSynPtr] == tokVoid &&
  3132. (stack[lidx][0] == tokNumInt || stack[lidx][0] == tokNumUint) &&
  3133. truncInt(stack[lidx][1]) == 0)))
  3134. {
  3135. *ExprTypeSynPtr = TheOtherExprTypeSynPtr;
  3136. return;
  3137. }
  3138. // not expecting non-pointers beyond this point
  3139. if (!(lptr && rptr))
  3140. errorOpType();
  3141. // one operand is a pointer and the other is a pointer to void
  3142. // (except (void*)0 (AKA NULL), which is different from other pointers to void),
  3143. // the type of the expression is pointer to void:
  3144. if (SyntaxStack0[-exprTypeSynPtr] == tokVoid)
  3145. return;
  3146. if (SyntaxStack0[-TheOtherExprTypeSynPtr] == tokVoid)
  3147. {
  3148. *ExprTypeSynPtr = TheOtherExprTypeSynPtr;
  3149. return;
  3150. }
  3151. // both operands are pointers to compatible types:
  3152. if (exprTypeSynPtr == TheOtherExprTypeSynPtr)
  3153. return;
  3154. exprTypeSynPtr = -exprTypeSynPtr;
  3155. TheOtherExprTypeSynPtr = -TheOtherExprTypeSynPtr;
  3156. for (;;)
  3157. {
  3158. int tok = SyntaxStack0[exprTypeSynPtr];
  3159. if (tok != SyntaxStack0[TheOtherExprTypeSynPtr])
  3160. errorOpType();
  3161. if (tok != tokIdent &&
  3162. SyntaxStack1[exprTypeSynPtr] != SyntaxStack1[TheOtherExprTypeSynPtr])
  3163. errorOpType();
  3164. c += (tok == '(') - (tok == ')') + (tok == '[') - (tok == ']');
  3165. if (!c)
  3166. {
  3167. switch (tok)
  3168. {
  3169. case tokVoid:
  3170. case tokChar: case tokSChar: case tokUChar:
  3171. #ifdef CAN_COMPILE_32BIT
  3172. case tokShort: case tokUShort:
  3173. #endif
  3174. case tokInt: case tokUnsigned:
  3175. #ifndef NO_FP
  3176. case tokFloat:
  3177. #endif
  3178. case tokStructPtr:
  3179. return;
  3180. }
  3181. }
  3182. exprTypeSynPtr++;
  3183. TheOtherExprTypeSynPtr++;
  3184. }
  3185. }
  3186. STATIC
  3187. void shiftCountCheck(int *psr, int idx, int ExprTypeSynPtr)
  3188. {
  3189. int sr = *psr;
  3190. // can't shift by a negative count and by a count exceeding
  3191. // the number of bits in int
  3192. if ((SyntaxStack0[ExprTypeSynPtr] != tokUnsigned && sr < 0) ||
  3193. (unsigned)sr >= CHAR_BIT * sizeof(int) ||
  3194. (unsigned)sr >= 8u * SizeOfWord)
  3195. {
  3196. //error("exprval(): Invalid shift count\n");
  3197. warning("Shift count out of range\n");
  3198. // truncate the count, so the assembler doesn't get an invalid count
  3199. sr &= SizeOfWord * 8 - 1;
  3200. *psr = sr;
  3201. stack[idx][1] = sr;
  3202. }
  3203. }
  3204. STATIC
  3205. int divCheckAndCalc(int tok, int* psl, int sr, int Unsigned, int ConstExpr[2])
  3206. {
  3207. int div0 = 0;
  3208. int sl = *psl;
  3209. if (!ConstExpr[1])
  3210. return !div0;
  3211. if (Unsigned)
  3212. {
  3213. sl = (int)truncUint(sl);
  3214. sr = (int)truncUint(sr);
  3215. }
  3216. else
  3217. {
  3218. sl = truncInt(sl);
  3219. sr = truncInt(sr);
  3220. }
  3221. if (sr == 0)
  3222. {
  3223. div0 = 1;
  3224. }
  3225. else if (!ConstExpr[0])
  3226. {
  3227. return !div0;
  3228. }
  3229. else if (!Unsigned && ((sl == INT_MIN && sr == -1) || division(sl , sr) != truncInt(division(sl , sr))))
  3230. {
  3231. div0 = 1;
  3232. }
  3233. else
  3234. {
  3235. if (Unsigned)
  3236. {
  3237. if (tok == '/')
  3238. sl = (int)((unsigned)division(sl , sr));
  3239. else
  3240. sl = (int)((unsigned)modulo(sl , sr));
  3241. }
  3242. else
  3243. {
  3244. // TBD!!! C89 gives freedom in how exactly division of negative integers
  3245. // can be implemented w.r.t. rounding and w.r.t. the sign of the remainder.
  3246. // A stricter, C99-conforming implementation, non-dependent on the
  3247. // compiler used to compile Smaller C is needed.
  3248. if (tok == '/')
  3249. sl = division(sl, sr);
  3250. else
  3251. sl = modulo(sl, sr);
  3252. }
  3253. *psl = sl;
  3254. }
  3255. if (div0)
  3256. warning("Division by 0 or division overflow\n");
  3257. return !div0;
  3258. }
  3259. STATIC
  3260. void promoteType(int* ExprTypeSynPtr, int* TheOtherExprTypeSynPtr)
  3261. {
  3262. // Integer promotion to signed int or unsigned int from smaller types
  3263. // (all kinds of char and short). Promotion to unsigned int occurs
  3264. // only if the other operand (of a binary operator) is already an
  3265. // unsigned int. Effectively, this promotion to unsigned int performs
  3266. // usual arithmetic conversion for integers.
  3267. if (*ExprTypeSynPtr >= 0)
  3268. {
  3269. // chars must be promoted to ints in expressions as the very first thing
  3270. switch (SyntaxStack0[*ExprTypeSynPtr])
  3271. {
  3272. case tokChar:
  3273. #ifdef CAN_COMPILE_32BIT
  3274. case tokShort:
  3275. case tokUShort:
  3276. #endif
  3277. case tokSChar:
  3278. case tokUChar:
  3279. *ExprTypeSynPtr = SymIntSynPtr;
  3280. }
  3281. if (*TheOtherExprTypeSynPtr >= 0)
  3282. {
  3283. // ints must be converted to unsigned ints if they are used in binary
  3284. // operators whose other operand is unsigned int (except <<,>>,<<=,>>=)
  3285. if (SyntaxStack0[*ExprTypeSynPtr] == tokInt &&
  3286. SyntaxStack0[*TheOtherExprTypeSynPtr] == tokUnsigned)
  3287. *ExprTypeSynPtr = SymUintSynPtr;
  3288. }
  3289. }
  3290. }
  3291. STATIC
  3292. int GetFxnInfo(int ExprTypeSynPtr, int* MinParams, int* MaxParams, int* ReturnExprTypeSynPtr, int* FirstParamSynPtr)
  3293. {
  3294. *MaxParams = *MinParams = 0;
  3295. if (ExprTypeSynPtr < 0)
  3296. {
  3297. ExprTypeSynPtr = -ExprTypeSynPtr;
  3298. }
  3299. else
  3300. {
  3301. while (SyntaxStack0[ExprTypeSynPtr] == tokIdent || SyntaxStack0[ExprTypeSynPtr] == tokLocalOfs)
  3302. ExprTypeSynPtr++;
  3303. if (SyntaxStack0[ExprTypeSynPtr] == '*')
  3304. ExprTypeSynPtr++;
  3305. }
  3306. if (SyntaxStack0[ExprTypeSynPtr] != '(')
  3307. return 0;
  3308. // DONE: return syntax pointer to the function's return type
  3309. // Count params
  3310. ExprTypeSynPtr++;
  3311. if (FirstParamSynPtr)
  3312. *FirstParamSynPtr = ExprTypeSynPtr;
  3313. if (SyntaxStack0[ExprTypeSynPtr] == ')')
  3314. {
  3315. // "fxn()": unspecified parameters, so, there can be any number of them
  3316. *MaxParams = 32767; // INT_MAX;
  3317. *ReturnExprTypeSynPtr = ExprTypeSynPtr + 1;
  3318. return 1;
  3319. }
  3320. if (SyntaxStack0[ExprTypeSynPtr + 1] == tokVoid)
  3321. {
  3322. // "fxn(void)": 0 parameters
  3323. *ReturnExprTypeSynPtr = ExprTypeSynPtr + 3;
  3324. return 1;
  3325. }
  3326. for (;;)
  3327. {
  3328. int tok = SyntaxStack0[ExprTypeSynPtr];
  3329. if (tok == tokIdent)
  3330. {
  3331. if (SyntaxStack0[ExprTypeSynPtr + 1] != tokEllipsis)
  3332. {
  3333. ++*MinParams;
  3334. ++*MaxParams;
  3335. }
  3336. else
  3337. {
  3338. *MaxParams = 32767; // INT_MAX;
  3339. }
  3340. }
  3341. else if (tok == '(')
  3342. {
  3343. // skip parameters in parameters
  3344. int c = 1;
  3345. while (c && ExprTypeSynPtr < SyntaxStackCnt)
  3346. {
  3347. tok = SyntaxStack0[++ExprTypeSynPtr];
  3348. c += (tok == '(') - (tok == ')');
  3349. }
  3350. }
  3351. else if (tok == ')')
  3352. {
  3353. ExprTypeSynPtr++;
  3354. break;
  3355. }
  3356. ExprTypeSynPtr++;
  3357. }
  3358. // get the function's return type
  3359. *ReturnExprTypeSynPtr = ExprTypeSynPtr;
  3360. return 1;
  3361. }
  3362. STATIC
  3363. void simplifyConstExpr(int val, int isConst, int* ExprTypeSynPtr, int top, int bottom)
  3364. {
  3365. // If non-const, nothing to do.
  3366. // If const and already a number behind the scenes, nothing to do
  3367. // (val must not differ from the number!).
  3368. if (!isConst || stack[top][0] == tokNumInt || stack[top][0] == tokNumUint)
  3369. return;
  3370. // Const, but not a number yet. Reduce to a number equal val.
  3371. if (SyntaxStack0[*ExprTypeSynPtr] == tokUnsigned)
  3372. stack[top][0] = tokNumUint;
  3373. else
  3374. stack[top][0] = tokNumInt;
  3375. stack[top][1] = val;
  3376. del(bottom, top - bottom);
  3377. }
  3378. STATIC
  3379. int AllocLocal(unsigned size)
  3380. {
  3381. // Let's calculate variable's relative on-stack location
  3382. int oldOfs = CurFxnLocalOfs;
  3383. // Note: local vars are word-aligned on the stack
  3384. CurFxnLocalOfs = (int)((CurFxnLocalOfs - size) & ~(SizeOfWord - 1u));
  3385. if (CurFxnLocalOfs >= oldOfs ||
  3386. CurFxnLocalOfs != truncInt(CurFxnLocalOfs) ||
  3387. CurFxnLocalOfs < -GenMaxLocalsSize())
  3388. //error("AllocLocal(): Local variables take too much space\n");
  3389. errorVarSize();
  3390. if (CurFxnMinLocalOfs > CurFxnLocalOfs)
  3391. CurFxnMinLocalOfs = CurFxnLocalOfs;
  3392. return CurFxnLocalOfs;
  3393. }
  3394. // DONE: sizeof(type)
  3395. // DONE: "sizeof expr"
  3396. // DONE: constant expressions
  3397. // DONE: collapse constant subexpressions into constants
  3398. STATIC
  3399. int exprval(int* idx, int* ExprTypeSynPtr, int* ConstExpr)
  3400. {
  3401. int tok;
  3402. int s;
  3403. int RightExprTypeSynPtr;
  3404. int oldIdxRight;
  3405. int oldSpRight;
  3406. int constExpr[3];
  3407. if (*idx < 0)
  3408. //error("exprval(): idx < 0\n");
  3409. errorInternal(5);
  3410. tok = stack[*idx][0];
  3411. s = stack[*idx][1];
  3412. --*idx;
  3413. oldIdxRight = *idx;
  3414. oldSpRight = sp;
  3415. switch (tok)
  3416. {
  3417. // Constants
  3418. case tokNumInt:
  3419. // return the constant's type: int
  3420. *ExprTypeSynPtr = SymIntSynPtr;
  3421. *ConstExpr = 1;
  3422. break;
  3423. case tokNumUint:
  3424. // return the constant's type: unsigned int
  3425. *ExprTypeSynPtr = SymUintSynPtr;
  3426. *ConstExpr = 1;
  3427. break;
  3428. #ifndef NO_WCHAR
  3429. case tokNumCharWide:
  3430. // recode tokNumCharWide to tokNumInt to minimize changes in the CGs
  3431. stack[*idx + 1][0] = tokNumInt;
  3432. // return the constant's type: wchar_t
  3433. *ExprTypeSynPtr = SymWideCharSynPtr;
  3434. *ConstExpr = 1;
  3435. break;
  3436. #endif
  3437. #ifndef NO_FP
  3438. case tokNumFloat:
  3439. // recode tokNumFloat to tokNumInt to minimize changes in the CGs
  3440. stack[*idx + 1][0] = tokNumInt;
  3441. // return the constant's type: float
  3442. *ExprTypeSynPtr = SymFloatSynPtr;
  3443. *ConstExpr = 1;
  3444. break;
  3445. #endif
  3446. // Identifiers
  3447. case tokIdent:
  3448. {
  3449. // DONE: support __func__
  3450. char* ident = IdentTable + s;
  3451. int synPtr, type;
  3452. #ifndef NO_FUNC_
  3453. if (CurFxnName && !strcmp(ident, "__func__"))
  3454. {
  3455. if (CurFxnNameLabel >= 0)
  3456. CurFxnNameLabel = -CurFxnNameLabel;
  3457. stack[*idx + 1][1] = SyntaxStack1[SymFuncPtr];
  3458. synPtr = SymFuncPtr;
  3459. }
  3460. else
  3461. #endif
  3462. {
  3463. synPtr = FindSymbol(ident);
  3464. // "Rename" static vars in function scope
  3465. if (synPtr >= 0 && synPtr + 1 < SyntaxStackCnt && SyntaxStack0[synPtr + 1] == tokIdent)
  3466. {
  3467. s = stack[*idx + 1][1] = SyntaxStack1[++synPtr];
  3468. ident = IdentTable + s;
  3469. }
  3470. }
  3471. if (synPtr < 0)
  3472. {
  3473. if ((*idx + 2 >= sp) || stack[*idx + 2][0] != ')')
  3474. error("Undeclared identifier '%s'\n", ident);
  3475. else
  3476. {
  3477. warning("Call to undeclared function '%s()'\n", ident);
  3478. // Implicitly declare "extern int ident();"
  3479. PushSyntax2(tokIdent, s);
  3480. PushSyntax('(');
  3481. PushSyntax(')');
  3482. PushSyntax(tokInt);
  3483. synPtr = FindSymbol(ident);
  3484. }
  3485. }
  3486. #ifndef NO_TYPEDEF_ENUM
  3487. if (synPtr + 1 < SyntaxStackCnt &&
  3488. SyntaxStack0[synPtr + 1] == tokNumInt)
  3489. {
  3490. // this is an enum constant
  3491. stack[*idx + 1][0] = tokNumInt;
  3492. s = stack[*idx + 1][1] = SyntaxStack1[synPtr + 1];
  3493. *ExprTypeSynPtr = SymIntSynPtr;
  3494. *ConstExpr = 1;
  3495. break;
  3496. }
  3497. #endif
  3498. // DONE: this declaration is actually a type cast
  3499. if (!strncmp(IdentTable + SyntaxStack1[synPtr], "(something", sizeof "(something)" - 1 - 1))
  3500. {
  3501. #ifndef NO_FP
  3502. int fmask;
  3503. int ptrmask;
  3504. #endif
  3505. int castSize;
  3506. if (SyntaxStack0[++synPtr] == tokLocalOfs) // TBD!!! is this really needed???
  3507. synPtr++;
  3508. s = exprval(idx, ExprTypeSynPtr, ConstExpr);
  3509. // can't cast void or structure/union to anything (except void)
  3510. if (*ExprTypeSynPtr >= 0 &&
  3511. (SyntaxStack0[*ExprTypeSynPtr] == tokVoid ||
  3512. SyntaxStack0[*ExprTypeSynPtr] == tokStructPtr) &&
  3513. SyntaxStack0[synPtr] != tokVoid)
  3514. errorOpType();
  3515. // can't cast to function, array or structure/union
  3516. if (SyntaxStack0[synPtr] == '(' ||
  3517. SyntaxStack0[synPtr] == '[' ||
  3518. SyntaxStack0[synPtr] == tokStructPtr)
  3519. errorOpType();
  3520. #ifndef NO_FP
  3521. ptrmask = isAnyPtr(synPtr) * 2 + isAnyPtr(*ExprTypeSynPtr);
  3522. fmask = isFloat(synPtr) * 2 + isFloat(*ExprTypeSynPtr);
  3523. if (ptrmask && fmask) // pointers and floats don't mix
  3524. errorOpType();
  3525. #endif
  3526. // will try to propagate constants through casts
  3527. if (!*ConstExpr &&
  3528. (stack[oldIdxRight - (oldSpRight - sp)][0] == tokNumInt ||
  3529. stack[oldIdxRight - (oldSpRight - sp)][0] == tokNumUint))
  3530. {
  3531. s = stack[oldIdxRight - (oldSpRight - sp)][1];
  3532. *ConstExpr = 1;
  3533. }
  3534. castSize = GetDeclSize(synPtr, 1); // 0 for cast to void
  3535. #ifndef NO_FP
  3536. if (castSize && fmask == 1)
  3537. {
  3538. // cast from float to any int
  3539. int u = isUint(synPtr);
  3540. if (*ConstExpr)
  3541. {
  3542. s = u ? f2u(s) : f2i(s, castSize);
  3543. }
  3544. else
  3545. {
  3546. // insert a call to convert float to [unsigned] int
  3547. int above = oldIdxRight + 1 - (oldSpRight - sp);
  3548. int below = *idx + 1;
  3549. ins2(above, ')', SizeOfWord);
  3550. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNF2U : FXNF2I]));
  3551. ins(above, ',');
  3552. ins2(below, '(', SizeOfWord);
  3553. }
  3554. }
  3555. #endif
  3556. // insertion of tokUChar, tokSChar and tokUnaryPlus transforms
  3557. // lvalues (values formed by dereferences) into rvalues
  3558. // (by hiding the dereferences), just as casts should do
  3559. switch (castSize)
  3560. {
  3561. case 1:
  3562. // cast to unsigned char
  3563. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUChar;
  3564. s &= 0xFFu;
  3565. break;
  3566. case -1:
  3567. // cast to signed char
  3568. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokSChar;
  3569. if ((s &= 0xFFu) >= 0x80)
  3570. s -= 0x100;
  3571. break;
  3572. default:
  3573. #ifdef CAN_COMPILE_32BIT
  3574. if (castSize && castSize != SizeOfWord)
  3575. {
  3576. // cast not to void and not to word-sized type (int/unsigned/pointer/float)
  3577. if (castSize == 2)
  3578. {
  3579. // cast to unsigned short
  3580. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUShort;
  3581. s &= 0xFFFFu;
  3582. }
  3583. else
  3584. {
  3585. // cast to signed short
  3586. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokShort;
  3587. if ((s &= 0xFFFFu) >= 0x8000)
  3588. s -= 0x10000;
  3589. }
  3590. }
  3591. else // fallthrough
  3592. #endif
  3593. {
  3594. // cast to void or word-sized type (int/unsigned/pointer/float)
  3595. #ifndef NO_FP
  3596. if (fmask == 2)
  3597. {
  3598. // cast from any int to float
  3599. int u = isUint(*ExprTypeSynPtr);
  3600. if (*ConstExpr)
  3601. {
  3602. s = u ? u2f(s) : i2f(s);
  3603. }
  3604. else
  3605. {
  3606. // insert a call to convert [unsigned] int to float
  3607. int above = oldIdxRight + 1 - (oldSpRight - sp);
  3608. int below = *idx + 1;
  3609. ins2(above, ')', SizeOfWord);
  3610. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNU2F : FXNI2F]));
  3611. ins(above, ',');
  3612. ins2(below, '(', SizeOfWord);
  3613. }
  3614. }
  3615. #endif
  3616. if (stack[oldIdxRight - (oldSpRight - sp)][0] == tokUnaryStar)
  3617. // hide the dereference
  3618. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUnaryPlus;
  3619. }
  3620. break;
  3621. }
  3622. if (*ConstExpr)
  3623. stack[oldIdxRight - (oldSpRight - sp)][1] = s;
  3624. *ExprTypeSynPtr = synPtr;
  3625. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3626. if (!*ConstExpr && stack[oldIdxRight + 1 - (oldSpRight - sp)][0] == tokIdent)
  3627. // nothing to hide, remove the cast
  3628. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  3629. switch (SyntaxStack0[synPtr])
  3630. {
  3631. case tokChar:
  3632. case tokSChar:
  3633. case tokUChar:
  3634. #ifdef CAN_COMPILE_32BIT
  3635. case tokShort:
  3636. case tokUShort:
  3637. #endif
  3638. case tokInt:
  3639. case tokUnsigned:
  3640. #ifndef NO_FP
  3641. case tokFloat:
  3642. #endif
  3643. break;
  3644. default:
  3645. // only numeric types can be const
  3646. *ConstExpr = 0;
  3647. break;
  3648. }
  3649. break;
  3650. }
  3651. // Finally, not __func__, not enum, not cast.
  3652. type = SymType(synPtr);
  3653. if (type == SymLocalVar || type == SymLocalArr)
  3654. {
  3655. // replace local variables/arrays with their local addresses
  3656. // (global variables/arrays' addresses are their names)
  3657. stack[*idx + 1][0] = tokLocalOfs;
  3658. stack[*idx + 1][1] = SyntaxStack1[synPtr + 1];
  3659. }
  3660. if (type == SymLocalVar || type == SymGlobalVar)
  3661. {
  3662. // add implicit dereferences for local/global variables
  3663. ins2(*idx + 2, tokUnaryStar, GetDeclSize(synPtr, 1));
  3664. }
  3665. // return the identifier's type
  3666. while (SyntaxStack0[synPtr] == tokIdent || SyntaxStack0[synPtr] == tokLocalOfs)
  3667. synPtr++;
  3668. *ExprTypeSynPtr = synPtr;
  3669. }
  3670. *ConstExpr = 0;
  3671. break;
  3672. // sizeof operator
  3673. case tokSizeof:
  3674. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3675. s = GetDeclSize(*ExprTypeSynPtr, 0);
  3676. if (s == 0)
  3677. error("sizeof of incomplete type\n");
  3678. // replace sizeof with its numeric value
  3679. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokNumUint;
  3680. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = s;
  3681. // remove the sizeof's subexpression
  3682. del(*idx + 1, oldIdxRight - (oldSpRight - sp) - *idx);
  3683. *ExprTypeSynPtr = SymUintSynPtr;
  3684. *ConstExpr = 1;
  3685. break;
  3686. // Address unary operator
  3687. case tokUnaryAnd:
  3688. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3689. if (*ExprTypeSynPtr >= 0 &&
  3690. (SyntaxStack0[*ExprTypeSynPtr] == '[' || SyntaxStack0[*ExprTypeSynPtr] == '('))
  3691. {
  3692. // convert an array into a pointer to the array,
  3693. // convert a function into a pointer to the function,
  3694. // remove the reference
  3695. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  3696. }
  3697. else if (*ExprTypeSynPtr >= 0 &&
  3698. stack[oldIdxRight - (oldSpRight - sp)][0] == tokUnaryStar)
  3699. {
  3700. // it's an lvalue (with implicit or explicit dereference),
  3701. // convert it into its address by
  3702. // collapsing/removing the reference and the dereference
  3703. del(oldIdxRight - (oldSpRight - sp), 2);
  3704. }
  3705. else
  3706. //error("exprval(): lvalue expected after '&'\n");
  3707. errorNotLvalue();
  3708. // we cannot insert another '*' into the type to make it a pointer
  3709. // to an array/function/etc, so make the index into the type negative
  3710. *ExprTypeSynPtr = -*ExprTypeSynPtr;
  3711. *ConstExpr = 0;
  3712. break;
  3713. // Indirection unary operator
  3714. case tokUnaryStar:
  3715. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3716. if (*ExprTypeSynPtr < 0 || SyntaxStack0[*ExprTypeSynPtr] == '*')
  3717. {
  3718. // type is a pointer to something,
  3719. // transform it into that something
  3720. if (*ExprTypeSynPtr < 0)
  3721. *ExprTypeSynPtr = -*ExprTypeSynPtr;
  3722. else
  3723. ++*ExprTypeSynPtr;
  3724. nonVoidTypeCheck(*ExprTypeSynPtr);
  3725. if (SyntaxStack0[*ExprTypeSynPtr] == tokStructPtr && !GetDeclSize(*ExprTypeSynPtr, 0))
  3726. // incomplete structure/union type
  3727. errorOpType();
  3728. // remove the dereference if that something is an array or a function
  3729. if (SyntaxStack0[*ExprTypeSynPtr] == '[' ||
  3730. SyntaxStack0[*ExprTypeSynPtr] == '(')
  3731. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  3732. // else attach dereference size in bytes
  3733. else
  3734. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = GetDeclSize(*ExprTypeSynPtr, 1);
  3735. }
  3736. else if (SyntaxStack0[*ExprTypeSynPtr] == '[')
  3737. {
  3738. // type is an array,
  3739. // transform it into the array's first element
  3740. // (a subarray, if type is a multidimensional array)
  3741. (*ExprTypeSynPtr) += 3;
  3742. // remove the dereference if that element is an array
  3743. if (SyntaxStack0[*ExprTypeSynPtr] == '[')
  3744. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  3745. // else attach dereference size in bytes
  3746. else
  3747. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = GetDeclSize(*ExprTypeSynPtr, 1);
  3748. }
  3749. else
  3750. //error("exprval(): pointer/array expected after '*' / before '[]'\n");
  3751. errorOpType();
  3752. *ConstExpr = 0;
  3753. break;
  3754. // Additive binary operators
  3755. case '+':
  3756. case '-':
  3757. // WRONGISH: DONE: replace prefix ++/-- with +=1/-=1
  3758. // WRONG: DONE: replace postfix ++/-- with (+=1)-1/(-=1)+1
  3759. {
  3760. int ptrmask;
  3761. #ifndef NO_FP
  3762. int fmask;
  3763. #endif
  3764. int oldIdxLeft, oldSpLeft;
  3765. int sl, sr;
  3766. int incSize;
  3767. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  3768. oldIdxLeft = *idx;
  3769. oldSpLeft = sp;
  3770. sl = exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  3771. // Decay arrays to pointers to their first elements
  3772. // and ensure that the pointers are suitable for pointer arithmetic
  3773. // (not pointers to functions, sizes of pointees are known and non-zero)
  3774. decayArray(&RightExprTypeSynPtr, 1);
  3775. decayArray(ExprTypeSynPtr, 1);
  3776. // Bar void and struct/union
  3777. scalarTypeCheck(RightExprTypeSynPtr);
  3778. scalarTypeCheck(*ExprTypeSynPtr);
  3779. ptrmask = isAnyPtr(RightExprTypeSynPtr) + isAnyPtr(*ExprTypeSynPtr) * 2;
  3780. #ifndef NO_FP
  3781. fmask = isFloat(RightExprTypeSynPtr) + isFloat(*ExprTypeSynPtr) * 2;
  3782. if (ptrmask && fmask) // pointers and floats don't mix
  3783. errorOpType();
  3784. #endif
  3785. // DONE: index/subscript scaling
  3786. if (ptrmask == 1 && tok == '+') // pointer in right-hand expression
  3787. {
  3788. incSize = GetDeclSize(derefAnyPtr(RightExprTypeSynPtr), 0);
  3789. if (constExpr[0]) // integer constant in left-hand expression
  3790. {
  3791. s = (int)((unsigned)sl * incSize);
  3792. stack[oldIdxLeft - (oldSpLeft - sp)][1] = s;
  3793. // optimize a little if possible
  3794. {
  3795. int i = oldIdxRight - (oldSpRight - sp);
  3796. // Skip any type cast markers
  3797. while (stack[i][0] == tokUnaryPlus || stack[i][0] == '+')
  3798. i--;
  3799. // See if the pointer is an integer constant or a local variable offset
  3800. // and if it is, adjust it here instead of generating code for
  3801. // addition/subtraction
  3802. if (stack[i][0] == tokNumInt || stack[i][0] == tokNumUint || stack[i][0] == tokLocalOfs)
  3803. {
  3804. s = (int)((unsigned)stack[i][1] + s);
  3805. stack[i][1] = s; // TBD!!! need extra truncation?
  3806. del(oldIdxLeft - (oldSpLeft - sp), 1);
  3807. del(oldIdxRight - (oldSpRight - sp) + 1, 1);
  3808. }
  3809. }
  3810. }
  3811. else if (incSize != 1)
  3812. {
  3813. ins2(oldIdxLeft + 1 - (oldSpLeft - sp), tokNumInt, incSize);
  3814. ins(oldIdxLeft + 1 - (oldSpLeft - sp), '*');
  3815. }
  3816. *ExprTypeSynPtr = RightExprTypeSynPtr;
  3817. }
  3818. else if (ptrmask == 2) // pointer in left-hand expression
  3819. {
  3820. incSize = GetDeclSize(derefAnyPtr(*ExprTypeSynPtr), 0);
  3821. if (constExpr[1]) // integer constant in right-hand expression
  3822. {
  3823. s = (int)((unsigned)sr * incSize);
  3824. stack[oldIdxRight - (oldSpRight - sp)][1] = s;
  3825. // optimize a little if possible
  3826. {
  3827. int i = oldIdxLeft - (oldSpLeft - sp);
  3828. // Skip any type cast markers
  3829. while (stack[i][0] == tokUnaryPlus || stack[i][0] == '+')
  3830. i--;
  3831. // See if the pointer is an integer constant or a local variable offset
  3832. // and if it is, adjust it here instead of generating code for
  3833. // addition/subtraction
  3834. if (stack[i][0] == tokNumInt || stack[i][0] == tokNumUint || stack[i][0] == tokLocalOfs)
  3835. {
  3836. if (tok == '-')
  3837. s = (int)~(s - 1u);
  3838. s = (int)((unsigned)stack[i][1] + s);
  3839. stack[i][1] = s; // TBD!!! need extra truncation?
  3840. del(oldIdxRight - (oldSpRight - sp), 2);
  3841. }
  3842. }
  3843. }
  3844. else if (incSize != 1)
  3845. {
  3846. ins2(oldIdxRight + 1 - (oldSpRight - sp), tokNumInt, incSize);
  3847. ins(oldIdxRight + 1 - (oldSpRight - sp), '*');
  3848. }
  3849. }
  3850. else if (ptrmask == 3 && tok == '-') // pointers in both expressions
  3851. {
  3852. incSize = GetDeclSize(derefAnyPtr(*ExprTypeSynPtr), 0);
  3853. // TBD!!! "ptr1-ptr2": better pointer type compatibility test needed, like compatCheck()?
  3854. if (incSize != GetDeclSize(derefAnyPtr(RightExprTypeSynPtr), 0))
  3855. //error("exprval(): incompatible pointers\n");
  3856. errorOpType();
  3857. if (incSize != 1)
  3858. {
  3859. ins2(oldIdxRight + 2 - (oldSpRight - sp), tokNumInt, incSize);
  3860. ins(oldIdxRight + 2 - (oldSpRight - sp), '/');
  3861. }
  3862. *ExprTypeSynPtr = SymIntSynPtr;
  3863. }
  3864. else if (ptrmask)
  3865. //error("exprval(): invalid combination of operands for '+' or '-'\n");
  3866. errorOpType();
  3867. // Promote the result from char to int (and from int to unsigned) if necessary
  3868. promoteType(ExprTypeSynPtr, &RightExprTypeSynPtr);
  3869. *ConstExpr = constExpr[0] && constExpr[1];
  3870. #ifndef NO_FP
  3871. if (fmask)
  3872. {
  3873. if (fmask == 2)
  3874. {
  3875. int u = isUint(RightExprTypeSynPtr);
  3876. if (constExpr[1])
  3877. {
  3878. // convert int constant to float
  3879. sr = u ? u2f(sr) : i2f(sr);
  3880. stack[oldIdxRight - (oldSpRight - sp)][1] = sr;
  3881. }
  3882. else
  3883. {
  3884. // insert a call to convert int to float
  3885. int above = oldIdxRight + 1 - (oldSpRight - sp);
  3886. int below = oldIdxLeft + 1 - (oldSpLeft - sp);
  3887. ins2(above, ')', SizeOfWord);
  3888. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNU2F : FXNI2F]));
  3889. ins(above, ',');
  3890. ins2(below, '(', SizeOfWord);
  3891. oldSpLeft += 4;
  3892. }
  3893. }
  3894. if (fmask == 1)
  3895. {
  3896. int u = isUint(*ExprTypeSynPtr);
  3897. if (constExpr[0])
  3898. {
  3899. // convert int constant to float
  3900. sl = u ? u2f(sl) : i2f(sl);
  3901. stack[oldIdxLeft - (oldSpLeft - sp)][1] = sl;
  3902. }
  3903. else
  3904. {
  3905. // insert a call to convert int to float
  3906. int above = oldIdxLeft + 1 - (oldSpLeft - sp);
  3907. int below = *idx + 1;
  3908. ins2(above, ')', SizeOfWord);
  3909. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNU2F : FXNI2F]));
  3910. ins(above, ',');
  3911. ins2(below, '(', SizeOfWord);
  3912. }
  3913. }
  3914. if (*ConstExpr)
  3915. {
  3916. if (tok == '+')
  3917. s = fadd(sl, sr);
  3918. else
  3919. s = fsub(sl, sr);
  3920. }
  3921. else
  3922. {
  3923. // insert a call to add/subtract floats
  3924. int above = oldIdxRight + 1 - (oldSpRight - sp);
  3925. int mid = oldIdxLeft + 1 - (oldSpLeft - sp);
  3926. int below = *idx + 1;
  3927. if (tok == '-')
  3928. {
  3929. // minuend must be the first argument, swap
  3930. swap(below, mid - below, above - mid);
  3931. mid = above - mid + below;
  3932. }
  3933. stack[above][0] = ')'; // replace '+'/'-' with function call
  3934. stack[above][1] = SizeOfWord * 2;
  3935. ins2(above, tokIdent, FindIdent(FpFxnName[(tok == '+') ? FXNFADD : FXNFSUB]));
  3936. ins(above, ',');
  3937. ins(mid, ',');
  3938. ins2(below, '(', SizeOfWord * 2);
  3939. }
  3940. *ExprTypeSynPtr = SymFloatSynPtr;
  3941. }
  3942. else
  3943. #endif
  3944. {
  3945. if (tok == '+')
  3946. s = (int)((unsigned)sl + sr);
  3947. else
  3948. s = (int)((unsigned)sl - sr);
  3949. }
  3950. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  3951. }
  3952. break;
  3953. // Prefix/postfix increment/decrement unary operators
  3954. case tokInc:
  3955. case tokDec:
  3956. case tokPostInc:
  3957. case tokPostDec:
  3958. {
  3959. int incSize = 1;
  3960. int inc = tok == tokInc || tok == tokPostInc;
  3961. int post = tok == tokPostInc || tok == tokPostDec;
  3962. int opSize;
  3963. exprval(idx, ExprTypeSynPtr, ConstExpr);
  3964. lvalueCheck(*ExprTypeSynPtr, oldIdxRight - (oldSpRight - sp));
  3965. // if it's a pointer, ensure that it's suitable for pointer arithmetic
  3966. // (not pointer to function, pointee size is known and non-zero)
  3967. decayArray(ExprTypeSynPtr, 1); // no actual decay here, just a type check
  3968. // Bar void and struct/union
  3969. scalarTypeCheck(*ExprTypeSynPtr);
  3970. #ifndef NO_FP
  3971. // TBD!!! support floats with these operators
  3972. if (isFloat(*ExprTypeSynPtr))
  3973. error("Increment/decrement not supported with floats\n");
  3974. #endif
  3975. // "remove" the lvalue dereference as we don't need
  3976. // to read the value while forgetting its location.
  3977. // We need to keep the lvalue location.
  3978. // Remember the operand size.
  3979. opSize = stack[oldIdxRight - (oldSpRight - sp)][1];
  3980. del(oldIdxRight - (oldSpRight - sp), 1);
  3981. if (isAnyPtr(*ExprTypeSynPtr))
  3982. incSize = GetDeclSize(derefAnyPtr(*ExprTypeSynPtr), 0);
  3983. if (incSize == 1)
  3984. {
  3985. // store the operand size in the operator
  3986. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = opSize;
  3987. }
  3988. else
  3989. {
  3990. // replace ++/-- with "postfix" +=/-= incSize when incSize != 1
  3991. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] =
  3992. inc ? (post ? tokPostAdd : tokAssignAdd) :
  3993. (post ? tokPostSub : tokAssignSub);
  3994. // store the operand size in the operator
  3995. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = opSize;
  3996. ins2(oldIdxRight + 1 - (oldSpRight - sp), tokNumInt, incSize);
  3997. }
  3998. *ConstExpr = 0;
  3999. }
  4000. break;
  4001. // Simple assignment binary operator
  4002. case '=':
  4003. {
  4004. int oldIdxLeft, oldSpLeft;
  4005. int opSize;
  4006. int structs;
  4007. #ifndef NO_FP
  4008. int ptrmask;
  4009. int fmask;
  4010. int sr =
  4011. #endif
  4012. exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  4013. oldIdxLeft = *idx;
  4014. oldSpLeft = sp;
  4015. exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  4016. lvalueCheck(*ExprTypeSynPtr, oldIdxLeft - (oldSpLeft - sp));
  4017. nonVoidTypeCheck(RightExprTypeSynPtr);
  4018. nonVoidTypeCheck(*ExprTypeSynPtr);
  4019. structs = (*ExprTypeSynPtr >= 0 && SyntaxStack0[*ExprTypeSynPtr] == tokStructPtr) * 2 +
  4020. (RightExprTypeSynPtr >= 0 && SyntaxStack0[RightExprTypeSynPtr] == tokStructPtr);
  4021. #ifndef NO_FP
  4022. ptrmask = isAnyPtr(*ExprTypeSynPtr) * 2 + isAnyPtr(RightExprTypeSynPtr);
  4023. fmask = isFloat(*ExprTypeSynPtr) * 2 + isFloat(RightExprTypeSynPtr);
  4024. if (fmask && (structs | ptrmask)) // floats don't mix with pointers or structs/unions
  4025. errorOpType();
  4026. #endif
  4027. if (structs)
  4028. {
  4029. int sz;
  4030. if (structs != 3 ||
  4031. SyntaxStack1[RightExprTypeSynPtr] != SyntaxStack1[*ExprTypeSynPtr])
  4032. errorOpType();
  4033. // TBD??? (a = b) should be an rvalue and so &(a = b) and (&(a = b))->c shouldn't be
  4034. // allowed, while (a = b).c should be allowed.
  4035. // transform "*psleft = *psright" into "*fxn(sizeof *psright, psright, psleft)"
  4036. /*
  4037. if (stack[oldIdxLeft - (oldSpLeft - sp)][0] != tokUnaryStar ||
  4038. stack[oldIdxRight - (oldSpRight - sp)][0] != tokUnaryStar)
  4039. errorInternal(18);
  4040. */
  4041. stack[oldIdxLeft - (oldSpLeft - sp)][0] = ','; // replace '*' with ','
  4042. stack[oldIdxRight - (oldSpRight - sp)][0] = ','; // replace '*' with ','
  4043. sz = GetDeclSize(RightExprTypeSynPtr, 0);
  4044. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokNumUint; // replace '=' with "sizeof *psright"
  4045. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = sz;
  4046. ins(oldIdxRight + 2 - (oldSpRight - sp), ',');
  4047. if (!StructCpyLabel)
  4048. StructCpyLabel = LabelCnt++;
  4049. ins2(oldIdxRight + 2 - (oldSpRight - sp), tokIdent, AddNumericIdent(StructCpyLabel));
  4050. ins2(oldIdxRight + 2 - (oldSpRight - sp), ')', SizeOfWord * 3);
  4051. ins2(oldIdxRight + 2 - (oldSpRight - sp), tokUnaryStar, 0); // use 0 deref size to drop meaningless dereferences
  4052. ins2(*idx + 1, '(', SizeOfWord * 3);
  4053. }
  4054. else
  4055. {
  4056. #ifndef NO_FP
  4057. if (fmask == 1 || fmask == 2)
  4058. {
  4059. int u = isUint((fmask == 1) ? *ExprTypeSynPtr : RightExprTypeSynPtr);
  4060. if (constExpr[1])
  4061. {
  4062. // convert between float and [unsigned] int
  4063. if (fmask == 1)
  4064. sr = u ? f2u(sr) : f2i(sr, GetDeclSize(*ExprTypeSynPtr, 1));
  4065. else
  4066. sr = u ? u2f(sr) : i2f(sr);
  4067. stack[oldIdxRight - (oldSpRight - sp)][1] = sr;
  4068. }
  4069. else
  4070. {
  4071. // insert a call to convert between float and [unsigned] int
  4072. int above = oldIdxRight + 1 - (oldSpRight - sp);
  4073. int below = oldIdxLeft + 1 - (oldSpLeft - sp);
  4074. ins2(above, ')', SizeOfWord);
  4075. ins2(above, tokIdent, FindIdent(FpFxnName[(fmask == 1) ? (u ? FXNF2U : FXNF2I) :
  4076. (u ? FXNU2F : FXNI2F)]));
  4077. ins(above, ',');
  4078. ins2(below, '(', SizeOfWord);
  4079. oldSpLeft += 4;
  4080. }
  4081. }
  4082. #endif
  4083. // "remove" the lvalue dereference as we don't need
  4084. // to read the value while forgetting its location.
  4085. // We need to keep the lvalue location.
  4086. // Remember the operand size.
  4087. opSize = stack[oldIdxLeft - (oldSpLeft - sp)][1];
  4088. // store the operand size in the operator
  4089. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = opSize;
  4090. del(oldIdxLeft - (oldSpLeft - sp), 1);
  4091. }
  4092. *ConstExpr = 0;
  4093. }
  4094. break;
  4095. // DONE: other assignment operators
  4096. // Arithmetic and bitwise unary operators
  4097. case '~':
  4098. case tokUnaryPlus:
  4099. case tokUnaryMinus:
  4100. s = exprval(idx, ExprTypeSynPtr, ConstExpr);
  4101. numericTypeCheck(*ExprTypeSynPtr);
  4102. promoteType(ExprTypeSynPtr, ExprTypeSynPtr);
  4103. switch (tok)
  4104. {
  4105. case '~':
  4106. #ifndef NO_FP
  4107. nonFloatTypeCheck(*ExprTypeSynPtr);
  4108. #endif
  4109. s = ~s;
  4110. break;
  4111. case tokUnaryPlus:
  4112. break;
  4113. case tokUnaryMinus:
  4114. #ifndef NO_FP
  4115. if (isFloat(*ExprTypeSynPtr))
  4116. {
  4117. if (*ConstExpr)
  4118. {
  4119. s = fneg(s);
  4120. }
  4121. else
  4122. {
  4123. // insert a call to float negate
  4124. int above = oldIdxRight + 1 - (oldSpRight - sp);
  4125. int below = *idx + 1;
  4126. stack[above][0] = ')'; // replace tokUnaryMinus with function call
  4127. stack[above][1] = SizeOfWord;
  4128. ins2(above, tokIdent, FindIdent(FpFxnName[FXNFNEG]));
  4129. ins(above, ',');
  4130. ins2(below, '(', SizeOfWord);
  4131. }
  4132. }
  4133. else
  4134. #endif
  4135. {
  4136. s = (int)~(s - 1u);
  4137. }
  4138. break;
  4139. }
  4140. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  4141. break;
  4142. // Arithmetic and bitwise binary operators
  4143. case '*':
  4144. case '/':
  4145. case '%':
  4146. case tokLShift:
  4147. case tokRShift:
  4148. case '&':
  4149. case '^':
  4150. case '|':
  4151. {
  4152. #ifndef NO_FP
  4153. int fmask;
  4154. int oldIdxLeft, oldSpLeft;
  4155. #endif
  4156. int sr, sl;
  4157. int Unsigned;
  4158. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  4159. #ifndef NO_FP
  4160. oldIdxLeft = *idx;
  4161. oldSpLeft = sp;
  4162. #endif
  4163. sl = exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  4164. numericTypeCheck(RightExprTypeSynPtr);
  4165. numericTypeCheck(*ExprTypeSynPtr);
  4166. #ifndef NO_FP
  4167. if (tok != '*' && tok != '/')
  4168. {
  4169. nonFloatTypeCheck(RightExprTypeSynPtr);
  4170. nonFloatTypeCheck(*ExprTypeSynPtr);
  4171. }
  4172. #endif
  4173. *ConstExpr = constExpr[0] && constExpr[1];
  4174. Unsigned = SyntaxStack0[*ExprTypeSynPtr] == tokUnsigned || SyntaxStack0[RightExprTypeSynPtr] == tokUnsigned;
  4175. #ifndef NO_FP
  4176. fmask = isFloat(RightExprTypeSynPtr) + isFloat(*ExprTypeSynPtr) * 2;
  4177. if (fmask)
  4178. {
  4179. if (fmask == 2)
  4180. {
  4181. int u = isUint(RightExprTypeSynPtr);
  4182. if (constExpr[1])
  4183. {
  4184. // convert int constant to float
  4185. sr = u ? u2f(sr) : i2f(sr);
  4186. stack[oldIdxRight - (oldSpRight - sp)][1] = sr;
  4187. }
  4188. else
  4189. {
  4190. // insert a call to convert int to float
  4191. int above = oldIdxRight + 1 - (oldSpRight - sp);
  4192. int below = oldIdxLeft + 1 - (oldSpLeft - sp);
  4193. ins2(above, ')', SizeOfWord);
  4194. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNU2F : FXNI2F]));
  4195. ins(above, ',');
  4196. ins2(below, '(', SizeOfWord);
  4197. oldSpLeft += 4;
  4198. }
  4199. }
  4200. if (fmask == 1)
  4201. {
  4202. int u = isUint(*ExprTypeSynPtr);
  4203. if (constExpr[0])
  4204. {
  4205. // convert int constant to float
  4206. sl = u ? u2f(sl) : i2f(sl);
  4207. stack[oldIdxLeft - (oldSpLeft - sp)][1] = sl;
  4208. }
  4209. else
  4210. {
  4211. // insert a call to convert int to float
  4212. int above = oldIdxLeft + 1 - (oldSpLeft - sp);
  4213. int below = *idx + 1;
  4214. ins2(above, ')', SizeOfWord);
  4215. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNU2F : FXNI2F]));
  4216. ins(above, ',');
  4217. ins2(below, '(', SizeOfWord);
  4218. }
  4219. }
  4220. if (*ConstExpr)
  4221. {
  4222. if (tok == '*')
  4223. s = fmul(sl, sr);
  4224. else
  4225. s = fdiv(sl, sr);
  4226. }
  4227. else
  4228. {
  4229. // insert a call to multiply/divide floats
  4230. int above = oldIdxRight + 1 - (oldSpRight - sp);
  4231. int mid = oldIdxLeft + 1 - (oldSpLeft - sp);
  4232. int below = *idx + 1;
  4233. if (tok == '/')
  4234. {
  4235. // dividend must be the first argument, swap
  4236. swap(below, mid - below, above - mid);
  4237. mid = above - mid + below;
  4238. }
  4239. stack[above][0] = ')'; // replace '*'/'/' with function call
  4240. stack[above][1] = SizeOfWord * 2;
  4241. ins2(above, tokIdent, FindIdent(FpFxnName[(tok == '*') ? FXNFMUL : FXNFDIV]));
  4242. ins(above, ',');
  4243. ins(mid, ',');
  4244. ins2(below, '(', SizeOfWord * 2);
  4245. }
  4246. *ExprTypeSynPtr = SymFloatSynPtr;
  4247. }
  4248. else
  4249. #endif
  4250. {
  4251. switch (tok)
  4252. {
  4253. // DONE: check for division overflows
  4254. case '/':
  4255. case '%':
  4256. *ConstExpr &= divCheckAndCalc(tok, &sl, sr, Unsigned, constExpr);
  4257. if (Unsigned)
  4258. {
  4259. if (tok == '/')
  4260. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUDiv;
  4261. else
  4262. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUMod;
  4263. }
  4264. break;
  4265. case '*':
  4266. sl = (int)((unsigned)sl * sr);
  4267. break;
  4268. case tokLShift:
  4269. case tokRShift:
  4270. if (constExpr[1])
  4271. {
  4272. if (SyntaxStack0[RightExprTypeSynPtr] != tokUnsigned)
  4273. sr = truncInt(sr);
  4274. else
  4275. sr = (int)truncUint(sr);
  4276. shiftCountCheck(&sr, oldIdxRight - (oldSpRight - sp), RightExprTypeSynPtr);
  4277. }
  4278. if (*ConstExpr)
  4279. {
  4280. if (tok == tokLShift)
  4281. {
  4282. // left shift is the same for signed and unsigned ints
  4283. sl = (int)((unsigned)sl << sr);
  4284. }
  4285. else
  4286. {
  4287. if (SyntaxStack0[*ExprTypeSynPtr] == tokUnsigned)
  4288. {
  4289. // right shift for unsigned ints
  4290. sl = (int)(truncUint(sl) >> sr);
  4291. }
  4292. else if (sr)
  4293. {
  4294. // right shift for signed ints is arithmetic, sign-bit-preserving
  4295. // don't depend on the compiler's implementation, do it "manually"
  4296. sl = truncInt(sl);
  4297. sl = (int)((truncUint(sl) >> sr) |
  4298. ((sl < 0) * (~0u << (8 * SizeOfWord - sr))));
  4299. }
  4300. }
  4301. }
  4302. if (SyntaxStack0[*ExprTypeSynPtr] == tokUnsigned && tok == tokRShift)
  4303. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokURShift;
  4304. // ignore RightExprTypeSynPtr for the purpose of promotion/conversion of the result of <</>>
  4305. RightExprTypeSynPtr = SymIntSynPtr;
  4306. break;
  4307. case '&': sl &= sr; break;
  4308. case '^': sl ^= sr; break;
  4309. case '|': sl |= sr; break;
  4310. }
  4311. s = sl;
  4312. }
  4313. promoteType(ExprTypeSynPtr, &RightExprTypeSynPtr);
  4314. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  4315. }
  4316. break;
  4317. // Relational and equality binary operators
  4318. // DONE: add (sub)tokens for unsigned >, >=, <, <= for pointers
  4319. case '<':
  4320. case '>':
  4321. case tokLEQ:
  4322. case tokGEQ:
  4323. case tokEQ:
  4324. case tokNEQ:
  4325. {
  4326. int ptrmask;
  4327. #ifndef NO_FP
  4328. int fmask;
  4329. int oldIdxLeft, oldSpLeft;
  4330. #endif
  4331. int sr, sl;
  4332. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  4333. #ifndef NO_FP
  4334. oldIdxLeft = *idx;
  4335. oldSpLeft = sp;
  4336. #endif
  4337. sl = exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  4338. // Bar void and struct/union
  4339. scalarTypeCheck(RightExprTypeSynPtr);
  4340. scalarTypeCheck(*ExprTypeSynPtr);
  4341. ptrmask = isAnyPtr(RightExprTypeSynPtr) + isAnyPtr(*ExprTypeSynPtr) * 2;
  4342. #ifndef NO_FP
  4343. fmask = isFloat(RightExprTypeSynPtr) + isFloat(*ExprTypeSynPtr) * 2;
  4344. if (ptrmask && fmask) // pointers and floats don't mix
  4345. errorOpType();
  4346. #endif
  4347. // TBD??? stricter type checks???
  4348. if (tok != tokEQ && tok != tokNEQ)
  4349. {
  4350. // Disallow >, <, >=, <= between a pointer and a number
  4351. if (ptrmask == 1 || ptrmask == 2)
  4352. //error("exprval(): Invalid/unsupported combination of compared operands\n");
  4353. errorOpType();
  4354. // Disallow >, <, >=, <= with pointers to functions
  4355. if (((ptrmask & 1) && SyntaxStack0[derefAnyPtr(RightExprTypeSynPtr)] == '(') ||
  4356. ((ptrmask & 2) && SyntaxStack0[derefAnyPtr(*ExprTypeSynPtr)] == '('))
  4357. errorOpType();
  4358. }
  4359. else
  4360. {
  4361. // Disallow == and != between a pointer and a number other than constant 0 (AKA NULL)
  4362. if ((ptrmask == 1 && !(constExpr[0] && !truncInt(sl))) ||
  4363. (ptrmask == 2 && !(constExpr[1] && !truncInt(sr))))
  4364. errorOpType();
  4365. }
  4366. *ConstExpr = constExpr[0] && constExpr[1];
  4367. #ifndef NO_FP
  4368. if (fmask)
  4369. {
  4370. if (fmask == 2)
  4371. {
  4372. int u = isUint(RightExprTypeSynPtr);
  4373. if (constExpr[1])
  4374. {
  4375. // convert int constant to float
  4376. sr = u ? u2f(sr) : i2f(sr);
  4377. stack[oldIdxRight - (oldSpRight - sp)][1] = sr;
  4378. }
  4379. else
  4380. {
  4381. // insert a call to convert int to float
  4382. int above = oldIdxRight + 1 - (oldSpRight - sp);
  4383. int below = oldIdxLeft + 1 - (oldSpLeft - sp);
  4384. ins2(above, ')', SizeOfWord);
  4385. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNU2F : FXNI2F]));
  4386. ins(above, ',');
  4387. ins2(below, '(', SizeOfWord);
  4388. oldSpLeft += 4;
  4389. }
  4390. }
  4391. if (fmask == 1)
  4392. {
  4393. int u = isUint(*ExprTypeSynPtr);
  4394. if (constExpr[0])
  4395. {
  4396. // convert int constant to float
  4397. sl = u ? u2f(sl) : i2f(sl);
  4398. stack[oldIdxLeft - (oldSpLeft - sp)][1] = sl;
  4399. }
  4400. else
  4401. {
  4402. // insert a call to convert int to float
  4403. int above = oldIdxLeft + 1 - (oldSpLeft - sp);
  4404. int below = *idx + 1;
  4405. ins2(above, ')', SizeOfWord);
  4406. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNU2F : FXNI2F]));
  4407. ins(above, ',');
  4408. ins2(below, '(', SizeOfWord);
  4409. }
  4410. }
  4411. if (*ConstExpr)
  4412. {
  4413. sl = fcmp(sl, sr, (tok == tokGEQ || tok == '>') ? -1 : +1);
  4414. switch (tok)
  4415. {
  4416. case '<': sl = sl < 0; break;
  4417. case '>': sl = sl > 0; break;
  4418. case tokLEQ: sl = sl <= 0; break;
  4419. case tokGEQ: sl = sl >= 0; break;
  4420. case tokEQ: sl = sl == 0; break;
  4421. case tokNEQ: sl = sl != 0; break;
  4422. }
  4423. }
  4424. else
  4425. {
  4426. // insert a call to compare floats
  4427. int above = oldIdxRight + 1 - (oldSpRight - sp);
  4428. int mid = oldIdxLeft + 1 - (oldSpLeft - sp);
  4429. int below = *idx + 1;
  4430. // left operand must be the first argument, swap
  4431. swap(below, mid - below, above - mid);
  4432. mid = above - mid + below;
  4433. // we'll compare the returned value against 0:
  4434. // -1 if left < right
  4435. // 0 if left == right
  4436. // +1 if left > right
  4437. ins2(above, tokNumInt, 0);
  4438. ins2(above, ')', SizeOfWord * 2);
  4439. ins2(above, tokIdent, FindIdent(FpFxnName[(tok == tokGEQ || tok == '>') ? FXNFCMPG : FXNFCMPL]));
  4440. ins(above, ',');
  4441. ins(mid, ',');
  4442. ins2(below, '(', SizeOfWord * 2);
  4443. }
  4444. }
  4445. else
  4446. #endif
  4447. {
  4448. int Unsigned = isUint(*ExprTypeSynPtr) || isUint(RightExprTypeSynPtr);
  4449. if (*ConstExpr)
  4450. {
  4451. if (!Unsigned)
  4452. {
  4453. sl = truncInt(sl);
  4454. sr = truncInt(sr);
  4455. switch (tok)
  4456. {
  4457. case '<': sl = sl < sr; break;
  4458. case '>': sl = sl > sr; break;
  4459. case tokLEQ: sl = sl <= sr; break;
  4460. case tokGEQ: sl = sl >= sr; break;
  4461. case tokEQ: sl = sl == sr; break;
  4462. case tokNEQ: sl = sl != sr; break;
  4463. }
  4464. }
  4465. else
  4466. {
  4467. sl = (int)truncUint(sl);
  4468. sr = (int)truncUint(sr);
  4469. switch (tok)
  4470. {
  4471. case '<': sl = (unsigned)sl < (unsigned)sr; break;
  4472. case '>': sl = (unsigned)sl > (unsigned)sr; break;
  4473. case tokLEQ: sl = (unsigned)sl <= (unsigned)sr; break;
  4474. case tokGEQ: sl = (unsigned)sl >= (unsigned)sr; break;
  4475. case tokEQ: sl = sl == sr; break;
  4476. case tokNEQ: sl = sl != sr; break;
  4477. }
  4478. }
  4479. }
  4480. if (ptrmask || Unsigned)
  4481. {
  4482. // Pointer comparison should be unsigned
  4483. int t = tok;
  4484. switch (tok)
  4485. {
  4486. case '<': t = tokULess; break;
  4487. case '>': t = tokUGreater; break;
  4488. case tokLEQ: t = tokULEQ; break;
  4489. case tokGEQ: t = tokUGEQ; break;
  4490. }
  4491. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = t;
  4492. }
  4493. }
  4494. s = sl;
  4495. *ExprTypeSynPtr = SymIntSynPtr;
  4496. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  4497. }
  4498. break;
  4499. // implicit pseudo-conversion to _Bool of operands of && and ||
  4500. case tok_Bool:
  4501. s = exprval(idx, ExprTypeSynPtr, ConstExpr);
  4502. // Bar void and struct/union
  4503. scalarTypeCheck(*ExprTypeSynPtr);
  4504. #ifndef NO_FP
  4505. if (isFloat(*ExprTypeSynPtr))
  4506. {
  4507. if (*ConstExpr)
  4508. {
  4509. s = fcmp(s, i2f(0), -1) != 0;
  4510. }
  4511. else
  4512. {
  4513. // insert a call to compare the float with 0.0
  4514. int above = oldIdxRight + 1 - (oldSpRight - sp);
  4515. int below = *idx + 1;
  4516. // the returned value will be one of -1,0,+1, we need its least significant bit
  4517. stack[above][0] = '&';
  4518. ins2(above, tokNumInt, 1);
  4519. ins2(above, ')', SizeOfWord * 2);
  4520. ins2(above, tokIdent, FindIdent(FpFxnName[FXNFCMPL]));
  4521. ins(above, ',');
  4522. ins(below, ',');
  4523. ins2(below, tokNumInt, i2f(0));
  4524. ins2(below, '(', SizeOfWord * 2);
  4525. }
  4526. }
  4527. else
  4528. #endif
  4529. {
  4530. s = truncInt(s) != 0;
  4531. }
  4532. *ExprTypeSynPtr = SymIntSynPtr;
  4533. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  4534. break;
  4535. // Logical binary operators
  4536. case tokLogAnd: // DONE: short-circuit
  4537. case tokLogOr: // DONE: short-circuit
  4538. {
  4539. int sr, sl;
  4540. // DONE: think of pushing a special short-circuit (jump-to) token
  4541. // to skip the rhs operand evaluation in && and ||
  4542. // DONE: add implicit "casts to _Bool" of && and || operands,
  4543. // do the same for control statements of if() while() and for(;;).
  4544. int sc = LabelCnt++;
  4545. // tag the logical operator as a numbered short-circuit jump target
  4546. stack[*idx + 1][1] = sc;
  4547. // insert "!= 0" for right-hand operand
  4548. switch (stack[*idx][0])
  4549. {
  4550. case '<':
  4551. case tokULess:
  4552. case '>':
  4553. case tokUGreater:
  4554. case tokLEQ:
  4555. case tokULEQ:
  4556. case tokGEQ:
  4557. case tokUGEQ:
  4558. case tokEQ:
  4559. case tokNEQ:
  4560. break;
  4561. default:
  4562. ins(++*idx, tok_Bool);
  4563. break;
  4564. }
  4565. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  4566. // insert a reference to the short-circuit jump target
  4567. if (tok == tokLogAnd)
  4568. ins2(++*idx, tokShortCirc, sc);
  4569. else
  4570. ins2(++*idx, tokShortCirc, -sc);
  4571. // insert "!= 0" for left-hand operand
  4572. switch (stack[*idx - 1][0])
  4573. {
  4574. case '<':
  4575. case tokULess:
  4576. case '>':
  4577. case tokUGreater:
  4578. case tokLEQ:
  4579. case tokULEQ:
  4580. case tokGEQ:
  4581. case tokUGEQ:
  4582. case tokEQ:
  4583. case tokNEQ:
  4584. --*idx;
  4585. break;
  4586. default:
  4587. ins(*idx, tok_Bool);
  4588. break;
  4589. }
  4590. sl = exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  4591. if (tok == tokLogAnd)
  4592. s = sl && sr;
  4593. else
  4594. s = sl || sr;
  4595. *ExprTypeSynPtr = SymIntSynPtr;
  4596. *ConstExpr = constExpr[0] && constExpr[1];
  4597. if (constExpr[0])
  4598. {
  4599. if (tok == tokLogAnd)
  4600. {
  4601. if (!sl)
  4602. *ConstExpr = 1, s = 0;
  4603. // TBD??? else can drop LHS expression
  4604. }
  4605. else
  4606. {
  4607. if (sl)
  4608. *ConstExpr = s = 1;
  4609. // TBD??? else can drop LHS expression
  4610. }
  4611. }
  4612. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  4613. }
  4614. break;
  4615. // Function call
  4616. case ')':
  4617. {
  4618. int tmpSynPtr, c;
  4619. int minParams, maxParams;
  4620. int firstParamSynPtr;
  4621. int oldIdx, oldSp;
  4622. #ifndef NO_STRUCT_BY_VAL
  4623. unsigned structSize = 0;
  4624. int retStruct = 0;
  4625. int retOfs = 0;
  4626. #endif
  4627. exprval(idx, ExprTypeSynPtr, ConstExpr);
  4628. if (!GetFxnInfo(*ExprTypeSynPtr, &minParams, &maxParams, ExprTypeSynPtr, &firstParamSynPtr))
  4629. //error("exprval(): function or function pointer expected\n");
  4630. errorOpType();
  4631. // DONE: validate the number of function arguments
  4632. // DONE: warnings on int<->pointer substitution in params/args
  4633. #ifndef NO_STRUCT_BY_VAL
  4634. // If a structure is returned, allocate space for it on the stack
  4635. // and pass its location as the first (implicit) argument.
  4636. if (ParseLevel &&
  4637. *ExprTypeSynPtr >= 0 &&
  4638. SyntaxStack0[*ExprTypeSynPtr] == tokStructPtr)
  4639. {
  4640. unsigned sz = GetDeclSize(*ExprTypeSynPtr, 0);
  4641. // Make sure the return structure type is complete
  4642. if (!sz)
  4643. errorOpType();
  4644. retOfs = AllocLocal(sz);
  4645. // Transform fxn(args) into fxn(pretval, args)
  4646. ins(*idx + 1, ',');
  4647. ins2(*idx + 1, tokLocalOfs, retOfs);
  4648. retStruct = 1;
  4649. }
  4650. #endif
  4651. // evaluate function arguments
  4652. c = 0;
  4653. while (stack[*idx][0] != '(')
  4654. {
  4655. #ifndef NO_FP
  4656. int fmask;
  4657. #endif
  4658. int ptrmask;
  4659. #ifndef NO_STRUCT_BY_VAL
  4660. int gotStructs;
  4661. #endif
  4662. // add a comma after the first (last to be pushed) argument,
  4663. // so all arguments can be pushed whenever a comma is encountered
  4664. if (!c)
  4665. ins(*idx + 1, ',');
  4666. oldIdx = *idx;
  4667. oldSp = sp;
  4668. (void)oldIdx;
  4669. (void)oldSp;
  4670. exprval(idx, &tmpSynPtr, ConstExpr);
  4671. //error("exprval(): function arguments cannot be of type 'void'\n");
  4672. if (c >= maxParams)
  4673. error("Too many function arguments\n");
  4674. // Find the type of the formal parameter in the function declaration
  4675. if (c < minParams)
  4676. {
  4677. int t;
  4678. while ((t = SyntaxStack0[firstParamSynPtr]) != tokIdent)
  4679. {
  4680. if (t == '(')
  4681. {
  4682. // skip parameters in parameters
  4683. int c = 1;
  4684. while (c)
  4685. {
  4686. t = SyntaxStack0[++firstParamSynPtr];
  4687. c += (t == '(') - (t == ')');
  4688. }
  4689. }
  4690. firstParamSynPtr++;
  4691. }
  4692. firstParamSynPtr++;
  4693. }
  4694. else
  4695. {
  4696. firstParamSynPtr = SymVoidSynPtr;
  4697. }
  4698. ptrmask = isAnyPtr(firstParamSynPtr) * 2 + isAnyPtr(tmpSynPtr);
  4699. (void)ptrmask;
  4700. #ifndef NO_FP
  4701. fmask = isFloat(firstParamSynPtr) * 2 + isFloat(tmpSynPtr);
  4702. #endif
  4703. #ifndef NO_STRUCT_BY_VAL
  4704. gotStructs = (SyntaxStack0[firstParamSynPtr] == tokStructPtr) * 2 +
  4705. (tmpSynPtr >= 0 && SyntaxStack0[tmpSynPtr] == tokStructPtr);
  4706. #endif
  4707. #ifndef NO_STRUCT_BY_VAL
  4708. // Bar void
  4709. nonVoidTypeCheck(tmpSynPtr);
  4710. #else
  4711. // Bar void and struct/union
  4712. scalarTypeCheck(tmpSynPtr);
  4713. #endif
  4714. // if there's a formal parameter for this argument, check the types
  4715. if (c < minParams)
  4716. {
  4717. #ifndef NO_FP
  4718. // floats don't mix with pointers
  4719. if (fmask && ptrmask)
  4720. errorOpType();
  4721. #endif
  4722. #ifndef NO_STRUCT_BY_VAL
  4723. // Structures must be of the same type
  4724. if (gotStructs &&
  4725. (gotStructs != 3 || SyntaxStack1[tmpSynPtr] != SyntaxStack1[firstParamSynPtr]))
  4726. errorOpType();
  4727. #endif
  4728. #ifndef NO_EXTRA_WARNS
  4729. // Issue a warning if the argument has to be a pointer but isn't and vice versa.
  4730. // TBD??? Compare pointer types deeply as in compatCheck()???
  4731. // TBD??? Issue a similar warning for return values and initializers???
  4732. if (ptrmask == 1 ||
  4733. (ptrmask == 2 &&
  4734. // Make an exception for integer constants equal to 0, treat them as NULL pointers
  4735. !(*ConstExpr && !truncInt(stack[*idx + 1][1]))))
  4736. warning("Expected %spointer in argument %d\n", (ptrmask == 2) ? "" : "non-", c + 1);
  4737. #endif
  4738. }
  4739. #ifndef NO_STRUCT_BY_VAL
  4740. // If the argument is a structure, push it by calling a dedicated function
  4741. if (gotStructs)
  4742. {
  4743. unsigned sz = GetDeclSize(tmpSynPtr, 0);
  4744. int i = oldIdx - (oldSp - sp);
  4745. stack[i][0] = ')';
  4746. stack[i][1] = SizeOfWord * 2;
  4747. if (!StructPushLabel)
  4748. StructPushLabel = LabelCnt++;
  4749. // The code generator expects functions to return values.
  4750. // If a function argument is a value produced by another function,
  4751. // as is the case here, the code generator will naturally
  4752. // want/need to push something of the size of the machine word.
  4753. // This works perfectly with non-structures.
  4754. // But we only want to push the structure without pushing any other words.
  4755. // In order to avoid involving changes in the code generator,
  4756. // we make the function that pushes structures onto the stack
  4757. // push all words but the first one. The dedicated function will
  4758. // return this word and the code generator will push it.
  4759. // This is ugly.
  4760. ins2(i, tokIdent, AddNumericIdent(StructPushLabel));
  4761. ins(i, ',');
  4762. i = *idx + 1;
  4763. ins(i, ',');
  4764. ins2(i, tokNumUint, (int)sz);
  4765. ins2(i, '(', SizeOfWord * 2);
  4766. if (sz > (unsigned)GenMaxLocalsSize())
  4767. errorVarSize();
  4768. // Structures will be padded to machine word boundary when pushed
  4769. sz = (sz + SizeOfWord - 1) & ~(SizeOfWord - 1u);
  4770. // Count the cumulative size of the pushed structures, excluding
  4771. // the first words that will be pushed by the code generator
  4772. if (structSize + sz < structSize)
  4773. errorVarSize();
  4774. structSize += sz - SizeOfWord;
  4775. if (structSize > (unsigned)GenMaxLocalsSize())
  4776. errorVarSize();
  4777. // TBD??? complete overflow checks (an expression may contain more than one call)?
  4778. }
  4779. #endif
  4780. #ifndef NO_FP
  4781. // if there's a formal parameter for this argument, we may need to convert from/to float
  4782. if (c < minParams && (fmask == 1 || fmask == 2))
  4783. {
  4784. int u = isUint((fmask == 1) ? firstParamSynPtr : tmpSynPtr);
  4785. if (*ConstExpr)
  4786. {
  4787. int val = stack[*idx + 1][1];
  4788. // convert between float and [unsigned] int
  4789. if (fmask == 1)
  4790. val = u ? f2u(val) : f2i(val, GetDeclSize(firstParamSynPtr, 1));
  4791. else
  4792. val = u ? u2f(val) : i2f(val);
  4793. stack[*idx + 1][1] = val;
  4794. }
  4795. else
  4796. {
  4797. // insert a call to convert between float and [unsigned] int
  4798. int above = oldIdx + 1 - (oldSp - sp);
  4799. int below = *idx + 1;
  4800. ins2(above, ')', SizeOfWord);
  4801. ins2(above, tokIdent, FindIdent(FpFxnName[(fmask == 1) ? (u ? FXNF2U : FXNF2I) :
  4802. (u ? FXNU2F : FXNI2F)]));
  4803. ins(above, ',');
  4804. ins2(below, '(', SizeOfWord);
  4805. }
  4806. }
  4807. #endif
  4808. c++;
  4809. if (stack[*idx][0] == ',')
  4810. --*idx;
  4811. }
  4812. --*idx;
  4813. if (c < minParams)
  4814. error("Too few function arguments\n");
  4815. // store the cumulative argument size in the function call operators
  4816. {
  4817. int i = oldIdxRight + 1 - (oldSpRight - sp);
  4818. #ifndef NO_STRUCT_BY_VAL
  4819. // Count the implicit param/arg for returned structure
  4820. c += retStruct;
  4821. // Correct the value by which the stack pointer
  4822. // will be incremented after the call
  4823. c += division(structSize, SizeOfWord);
  4824. #endif
  4825. stack[1 + *idx][1] = stack[i][1] = c * SizeOfWord;
  4826. #ifndef NO_STRUCT_BY_VAL
  4827. // If a structure is returned, transform
  4828. // fxn(pretval, args) into *(fxn(pretval, args), pretval)
  4829. if (retStruct)
  4830. {
  4831. ins(i + 1, tokUnaryStar);
  4832. ins(i + 1, tokComma);
  4833. ins2(i + 1, tokLocalOfs, retOfs);
  4834. ins(i + 1, tokVoid);
  4835. }
  4836. #endif
  4837. }
  4838. *ConstExpr = 0;
  4839. }
  4840. break;
  4841. // Binary comma operator
  4842. case tokComma:
  4843. {
  4844. int oldIdxLeft, oldSpLeft;
  4845. int retStruct = 0;
  4846. s = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  4847. oldIdxLeft = *idx;
  4848. oldSpLeft = sp;
  4849. // Signify uselessness of the result of the left operand's value
  4850. ins(*idx + 1, tokVoid);
  4851. exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  4852. *ConstExpr = constExpr[0] && constExpr[1];
  4853. *ExprTypeSynPtr = RightExprTypeSynPtr;
  4854. retStruct = RightExprTypeSynPtr >= 0 && SyntaxStack0[RightExprTypeSynPtr] == tokStructPtr;
  4855. if (*ConstExpr)
  4856. {
  4857. // both subexprs are const, remove both and comma
  4858. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  4859. }
  4860. else if (constExpr[0])
  4861. {
  4862. // only left subexpr is const, remove it
  4863. del(*idx + 1, oldIdxLeft - (oldSpLeft - sp) - *idx);
  4864. if (!retStruct)
  4865. // Ensure non-lvalue-ness of the result by changing comma to unary plus
  4866. // and thus hiding dereference, if any
  4867. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = tokUnaryPlus;
  4868. else
  4869. // However, (something, struct).member should still be allowed,
  4870. // so, comma needs to produce lvalue
  4871. del(oldIdxRight + 1 - (oldSpRight - sp), 1);
  4872. }
  4873. else if (retStruct)
  4874. {
  4875. // However, (something, struct).member should still be allowed,
  4876. // so, comma needs to produce lvalue. Swap comma and structure dereference.
  4877. int i = oldIdxRight + 1 - (oldSpRight - sp);
  4878. stack[i][0] = tokUnaryStar;
  4879. stack[i][1] = stack[i - 1][1];
  4880. stack[i - 1][0] = tokComma;
  4881. }
  4882. }
  4883. break;
  4884. // Compound assignment operators
  4885. case tokAssignMul: case tokAssignDiv: case tokAssignMod:
  4886. case tokAssignAdd: case tokAssignSub:
  4887. case tokAssignLSh: case tokAssignRSh:
  4888. case tokAssignAnd: case tokAssignXor: case tokAssignOr:
  4889. {
  4890. int ptrmask;
  4891. int oldIdxLeft, oldSpLeft;
  4892. int incSize;
  4893. int opSize;
  4894. int Unsigned;
  4895. int sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[1]);
  4896. oldIdxLeft = *idx;
  4897. oldSpLeft = sp;
  4898. exprval(idx, ExprTypeSynPtr, &constExpr[0]);
  4899. lvalueCheck(*ExprTypeSynPtr, oldIdxLeft - (oldSpLeft - sp));
  4900. // if it's a pointer, ensure that it's suitable for pointer arithmetic
  4901. // (not pointer to function, pointee size is known and non-zero)
  4902. decayArray(ExprTypeSynPtr, 1); // no actual decay here, just a type check
  4903. // Bar void and struct/union
  4904. scalarTypeCheck(RightExprTypeSynPtr);
  4905. scalarTypeCheck(*ExprTypeSynPtr);
  4906. #ifndef NO_FP
  4907. // TBD!!! tokAssignMul, tokAssignDiv, tokAssignAdd, tokAssignSub with floats
  4908. if (isFloat(RightExprTypeSynPtr) || isFloat(*ExprTypeSynPtr))
  4909. {
  4910. switch (tok)
  4911. {
  4912. case tokAssignMul:
  4913. case tokAssignDiv:
  4914. case tokAssignAdd:
  4915. case tokAssignSub:
  4916. error("Compound assignment not supported with floats\n");
  4917. default:
  4918. errorOpType();
  4919. }
  4920. }
  4921. #endif
  4922. // "remove" the lvalue dereference as we don't need
  4923. // to read the value while forgetting its location.
  4924. // We need to keep the lvalue location.
  4925. // Remember the operand size.
  4926. opSize = stack[oldIdxLeft - (oldSpLeft - sp)][1];
  4927. // store the operand size in the operator
  4928. stack[oldIdxRight + 1 - (oldSpRight - sp)][1] = opSize;
  4929. del(oldIdxLeft - (oldSpLeft - sp), 1);
  4930. ptrmask = isAnyPtr(*ExprTypeSynPtr) * 2 + isAnyPtr(RightExprTypeSynPtr);
  4931. Unsigned = isUint(*ExprTypeSynPtr) * 2 + isUint(RightExprTypeSynPtr);
  4932. if (tok != tokAssignAdd && tok != tokAssignSub)
  4933. {
  4934. if (ptrmask)
  4935. //error("exprval(): invalid combination of operands for %s\n", GetTokenName(tok));
  4936. errorOpType();
  4937. }
  4938. else
  4939. {
  4940. // No pointer to the right of += and -=
  4941. if (ptrmask & 1)
  4942. //error("exprval(): invalid combination of operands for %s\n", GetTokenName(tok));
  4943. errorOpType();
  4944. }
  4945. if (tok == tokAssignLSh || tok == tokAssignRSh)
  4946. {
  4947. if (constExpr[1])
  4948. {
  4949. if (Unsigned & 1)
  4950. sr = (int)truncUint(sr);
  4951. else
  4952. sr = truncInt(sr);
  4953. shiftCountCheck(&sr, oldIdxRight - (oldSpRight - sp), RightExprTypeSynPtr);
  4954. }
  4955. }
  4956. if (tok == tokAssignDiv || tok == tokAssignMod)
  4957. {
  4958. int t, sl = 0;
  4959. if (tok == tokAssignDiv)
  4960. t = '/';
  4961. else
  4962. t = '%';
  4963. divCheckAndCalc(t, &sl, sr, 1, constExpr);
  4964. }
  4965. // TBD??? replace +=/-= with prefix ++/-- if incSize == 1
  4966. if (ptrmask == 2) // left-hand expression
  4967. {
  4968. incSize = GetDeclSize(derefAnyPtr(*ExprTypeSynPtr), 0);
  4969. if (constExpr[1])
  4970. {
  4971. int t = (int)(stack[oldIdxRight - (oldSpRight - sp)][1] * (unsigned)incSize);
  4972. stack[oldIdxRight - (oldSpRight - sp)][1] = t;
  4973. }
  4974. else if (incSize != 1)
  4975. {
  4976. ins2(oldIdxRight + 1 - (oldSpRight - sp), tokNumInt, incSize);
  4977. ins(oldIdxRight + 1 - (oldSpRight - sp), '*');
  4978. }
  4979. }
  4980. else if (Unsigned)
  4981. {
  4982. int t = tok;
  4983. switch (tok)
  4984. {
  4985. case tokAssignDiv: t = tokAssignUDiv; break;
  4986. case tokAssignMod: t = tokAssignUMod; break;
  4987. case tokAssignRSh:
  4988. if (Unsigned & 2)
  4989. t = tokAssignURSh;
  4990. break;
  4991. }
  4992. stack[oldIdxRight + 1 - (oldSpRight - sp)][0] = t;
  4993. }
  4994. *ConstExpr = 0;
  4995. }
  4996. break;
  4997. // Ternary/conditional operator
  4998. case '?':
  4999. {
  5000. int oldIdxLeft, oldSpLeft;
  5001. int oldIdxCond, oldSpCond;
  5002. int sr, sl, smid;
  5003. int condTypeSynPtr;
  5004. int sc = (LabelCnt += 2) - 2;
  5005. int structs;
  5006. #ifndef NO_FP
  5007. int ptrmask;
  5008. int fmask;
  5009. #endif
  5010. // "exprL ? exprMID : exprR" appears on the stack as
  5011. // "exprL exprR exprMID ?"
  5012. // label at the end of ?:
  5013. stack[*idx + 1][0] = tokLogAnd; // piggyback on && for CG (ugly, but simple)
  5014. stack[*idx + 1][1] = sc + 1;
  5015. smid = exprval(idx, ExprTypeSynPtr, &constExpr[1]);
  5016. oldIdxLeft = *idx;
  5017. oldSpLeft = sp;
  5018. sr = exprval(idx, &RightExprTypeSynPtr, &constExpr[2]);
  5019. decayArray(&RightExprTypeSynPtr, 0);
  5020. decayArray(ExprTypeSynPtr, 0);
  5021. promoteType(&RightExprTypeSynPtr, ExprTypeSynPtr);
  5022. promoteType(ExprTypeSynPtr, &RightExprTypeSynPtr);
  5023. structs = (*ExprTypeSynPtr >= 0 && SyntaxStack0[*ExprTypeSynPtr] == tokStructPtr) * 2 +
  5024. (RightExprTypeSynPtr >= 0 && SyntaxStack0[RightExprTypeSynPtr] == tokStructPtr);
  5025. #ifndef NO_FP
  5026. ptrmask = isAnyPtr(*ExprTypeSynPtr) * 2 + isAnyPtr(RightExprTypeSynPtr);
  5027. fmask = isFloat(*ExprTypeSynPtr) * 2 + isFloat(RightExprTypeSynPtr);
  5028. if (fmask && (structs | ptrmask)) // floats don't mix with pointers or structs/unions
  5029. errorOpType();
  5030. if (fmask)
  5031. {
  5032. if (fmask == 1)
  5033. {
  5034. int u = isUint(*ExprTypeSynPtr);
  5035. if (constExpr[1])
  5036. {
  5037. // convert int constant to float
  5038. smid = u ? u2f(smid) : i2f(smid);
  5039. stack[oldIdxRight - (oldSpRight - sp)][1] = smid;
  5040. }
  5041. else
  5042. {
  5043. // insert a call to convert int to float
  5044. int above = oldIdxRight + 1 - (oldSpRight - sp);
  5045. int below = oldIdxLeft + 1 - (oldSpLeft - sp);
  5046. ins2(above, ')', SizeOfWord);
  5047. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNU2F : FXNI2F]));
  5048. ins(above, ',');
  5049. ins2(below, '(', SizeOfWord);
  5050. oldSpLeft += 4;
  5051. }
  5052. }
  5053. if (fmask == 2)
  5054. {
  5055. int u = isUint(RightExprTypeSynPtr);
  5056. if (constExpr[2])
  5057. {
  5058. // convert int constant to float
  5059. sr = u ? u2f(sr) : i2f(sr);
  5060. stack[oldIdxLeft - (oldSpLeft - sp)][1] = sr;
  5061. }
  5062. else
  5063. {
  5064. // insert a call to convert int to float
  5065. int above = oldIdxLeft + 1 - (oldSpLeft - sp);
  5066. int below = *idx + 1;
  5067. ins2(above, ')', SizeOfWord);
  5068. ins2(above, tokIdent, FindIdent(FpFxnName[u ? FXNU2F : FXNI2F]));
  5069. ins(above, ',');
  5070. ins2(below, '(', SizeOfWord);
  5071. }
  5072. }
  5073. *ExprTypeSynPtr = SymFloatSynPtr;
  5074. }
  5075. #endif
  5076. // TBD??? move struct/union-related checks into compatChecks()
  5077. if (structs)
  5078. {
  5079. if (structs != 3 ||
  5080. SyntaxStack1[RightExprTypeSynPtr] != SyntaxStack1[*ExprTypeSynPtr])
  5081. errorOpType();
  5082. // transform "cond ? a : b" into "*(cond ? &a : &b)"
  5083. /*
  5084. if (stack[oldIdxLeft - (oldSpLeft - sp)][0] != tokUnaryStar ||
  5085. stack[oldIdxRight - (oldSpRight - sp)][0] != tokUnaryStar)
  5086. errorInternal(19);
  5087. */
  5088. del(oldIdxLeft - (oldSpLeft - sp), 1); // delete '*'
  5089. del(oldIdxRight - (oldSpRight - sp), 1); // delete '*'
  5090. oldSpLeft--;
  5091. // '*' will be inserted at the end
  5092. }
  5093. else
  5094. {
  5095. compatCheck(ExprTypeSynPtr,
  5096. RightExprTypeSynPtr,
  5097. &constExpr[1],
  5098. oldIdxRight - (oldSpRight - sp),
  5099. oldIdxLeft - (oldSpLeft - sp));
  5100. }
  5101. // label at the start of exprMID
  5102. ins2(oldIdxLeft + 1 - (oldSpLeft - sp), tokLogAnd, sc); // piggyback on && for CG (ugly, but simple)
  5103. // jump from the end of exprR over exprMID to the end of ?:
  5104. ins2(oldIdxLeft - (oldSpLeft - sp), tokGoto, sc + 1);
  5105. // jump to exprMID if exprL is non-zero
  5106. ins2(*idx + 1, tokShortCirc, -sc);
  5107. oldIdxCond = *idx;
  5108. oldSpCond = sp;
  5109. sl = exprval(idx, &condTypeSynPtr, &constExpr[0]);
  5110. // Bar void and struct/union
  5111. scalarTypeCheck(condTypeSynPtr);
  5112. #ifndef NO_FP
  5113. if (isFloat(condTypeSynPtr))
  5114. {
  5115. // insert a call to compare the float with 0.0
  5116. int above = oldIdxCond + 1 - (oldSpCond - sp);
  5117. int below = *idx + 1;
  5118. // the returned value will be one of -1,0,+1, that is, 0 if 0, +/-1 otherwise,
  5119. // IOW, suitable for conditional jump on zero/non-zero
  5120. ins2(above, ')', SizeOfWord * 2);
  5121. ins2(above, tokIdent, FindIdent(FpFxnName[FXNFCMPL]));
  5122. ins(above, ',');
  5123. ins(below, ',');
  5124. ins2(below, tokNumInt, i2f(0));
  5125. ins2(below, '(', SizeOfWord * 2);
  5126. }
  5127. #endif
  5128. *ConstExpr = s = 0;
  5129. if (constExpr[0])
  5130. {
  5131. int c1 = 0, c2 = 0;
  5132. // Stack now: exprL tokShortCirc exprR tokGoto tokLogAnd exprMID ?/tokLogAnd
  5133. if (
  5134. #ifndef NO_FP
  5135. isFloat(condTypeSynPtr) ?
  5136. fcmp(sl, i2f(0), -1) != 0 :
  5137. #endif
  5138. (truncUint(sl) != 0))
  5139. {
  5140. if (constExpr[1])
  5141. {
  5142. *ConstExpr = 1, s = smid;
  5143. }
  5144. else
  5145. {
  5146. // Drop exprL and exprR subexpressions
  5147. c1 = oldIdxLeft - (oldSpLeft - sp) - *idx; // includes tokShortCirc, tokGoto, tokLogAnd
  5148. c2 = 1; // include '?'/tokLogAnd
  5149. }
  5150. }
  5151. else
  5152. {
  5153. if (constExpr[2])
  5154. {
  5155. *ConstExpr = 1, s = sr;
  5156. }
  5157. else
  5158. {
  5159. // Drop exprL and exprMID subexpressions
  5160. c1 = oldIdxCond - (oldSpCond - sp) - *idx + 1; // includes tokShortCirc
  5161. c2 = (oldIdxRight - (oldSpRight - sp)) -
  5162. (oldIdxLeft - (oldSpLeft - sp)) + 3; // includes tokGoto, tokLogAnd, '?'/tokLogAnd
  5163. }
  5164. }
  5165. if (c1)
  5166. {
  5167. int pos = oldIdxRight - (oldSpRight - sp) + 2 - c2;
  5168. if (!structs && stack[pos - 1][0] == tokUnaryStar)
  5169. stack[pos++][0] = tokUnaryPlus, c2--; // ensure non-lvalue-ness by hiding the dereference
  5170. del(pos, c2);
  5171. del(*idx + 1, c1);
  5172. }
  5173. }
  5174. // finish transforming "cond ? a : b" into "*(cond ? &a : &b)", insert '*'
  5175. if (structs)
  5176. ins2(oldIdxRight + 2 - (oldSpRight - sp), tokUnaryStar, 0); // use 0 deref size to drop meaningless dereferences
  5177. simplifyConstExpr(s, *ConstExpr, ExprTypeSynPtr, oldIdxRight + 1 - (oldSpRight - sp), *idx + 1);
  5178. }
  5179. break;
  5180. // Postfix indirect structure/union member selection operator
  5181. case tokArrow:
  5182. {
  5183. int member, i = 0, j = 0, c = 1, ofs = 0;
  5184. stack[*idx + 1][0] = '+'; // replace -> with +
  5185. member = stack[*idx][1]; // keep the member name, it will be replaced with member offset
  5186. stack[*idx][0] = tokNumInt;
  5187. --*idx;
  5188. exprval(idx, ExprTypeSynPtr, ConstExpr);
  5189. if (!isAnyPtr(*ExprTypeSynPtr) ||
  5190. SyntaxStack0[i = derefAnyPtr(*ExprTypeSynPtr)] != tokStructPtr)
  5191. error("Pointer to or structure or union expected\n");
  5192. i = SyntaxStack1[i];
  5193. if (i + 2 > SyntaxStackCnt ||
  5194. (SyntaxStack0[i] != tokStruct && SyntaxStack0[i] != tokUnion) ||
  5195. SyntaxStack0[i + 1] != tokTag)
  5196. errorInternal(20);
  5197. if (!GetDeclSize(i, 0))
  5198. // incomplete structure/union type
  5199. errorOpType();
  5200. i += 5; // step inside the {} body of the struct/union
  5201. while (c)
  5202. {
  5203. int t = SyntaxStack0[i];
  5204. c += (t == '(') - (t == ')') + (t == '{') - (t == '}');
  5205. if (c == 1 &&
  5206. t == tokMemberIdent && SyntaxStack1[i] == member &&
  5207. SyntaxStack0[i + 1] == tokLocalOfs)
  5208. {
  5209. j = i;
  5210. ofs = SyntaxStack1[i + 1];
  5211. break;
  5212. }
  5213. i++;
  5214. }
  5215. if (!j)
  5216. error("Undefined structure or union member '%s'\n", IdentTable + member);
  5217. j += 2;
  5218. // we cannot insert another '*' into the type to make it a pointer,
  5219. // so make the index into the type negative
  5220. *ExprTypeSynPtr = -j; // type: pointer to member's type
  5221. stack[oldIdxRight - (oldSpRight - sp)][1] = ofs; // member offset within structure/union
  5222. // optimize a little, if possible
  5223. {
  5224. int i = oldIdxRight - (oldSpRight - sp) - 1;
  5225. // Skip any type cast markers
  5226. while (stack[i][0] == tokUnaryPlus)
  5227. i--;
  5228. // See if the pointer is an integer constant or a local variable offset
  5229. // and if it is, adjust it here instead of generating code for
  5230. // addition/subtraction
  5231. if (stack[i][0] == tokNumInt || stack[i][0] == tokNumUint || stack[i][0] == tokLocalOfs)
  5232. {
  5233. stack[i][1] = (int)((unsigned)stack[i][1] + ofs); // TBD!!! need extra truncation?
  5234. del(oldIdxRight - (oldSpRight - sp), 2);
  5235. }
  5236. }
  5237. *ConstExpr = 0;
  5238. }
  5239. break;
  5240. default:
  5241. //error("exprval(): Unexpected token %s\n", GetTokenName(tok));
  5242. errorInternal(21);
  5243. }
  5244. return s;
  5245. }
  5246. STATIC
  5247. int ParseExpr(int tok, int* GotUnary, int* ExprTypeSynPtr, int* ConstExpr, int* ConstVal, int option, int option2)
  5248. {
  5249. int identFirst = tok == tokIdent;
  5250. #ifndef NO_STRUCT_BY_VAL
  5251. int oldOfs = CurFxnLocalOfs;
  5252. #endif
  5253. *ConstVal = *ConstExpr = 0;
  5254. *ExprTypeSynPtr = SymVoidSynPtr;
  5255. if (!ExprLevel++)
  5256. {
  5257. opsp = sp = 0;
  5258. }
  5259. if (option == '=')
  5260. push2(tokIdent, option2);
  5261. tok = expr(tok, GotUnary, option == ',' || option == '=');
  5262. if (tok == tokEof || strchr(",;:)]}", tok) == NULL)
  5263. //error("ParseExpr(): Unexpected token %s\n", GetTokenName(tok));
  5264. errorUnexpectedToken(tok);
  5265. if (option == '=')
  5266. {
  5267. push('=');
  5268. }
  5269. else if (option == tokGotoLabel && identFirst && tok == ':' && *GotUnary && sp == 1 && stack[sp - 1][0] == tokIdent)
  5270. {
  5271. // This is a label.
  5272. ExprLevel--;
  5273. return tokGotoLabel;
  5274. }
  5275. if (*GotUnary)
  5276. {
  5277. int j;
  5278. // Do this twice so we can see the stack before
  5279. // and after manipulations
  5280. for (j = 0; j < 2; j++)
  5281. {
  5282. #ifndef NO_ANNOTATIONS
  5283. int i;
  5284. GenStartCommentLine();
  5285. if (j) printf2("Expanded");
  5286. else printf2("RPN'ized");
  5287. printf2(" expression: \"");
  5288. for (i = 0; i < sp; i++)
  5289. {
  5290. int tok = stack[i][0];
  5291. switch (tok)
  5292. {
  5293. case tokNumInt:
  5294. printf2("%d", truncInt(stack[i][1]));
  5295. break;
  5296. case tokNumUint:
  5297. printf2("%uu", truncUint(stack[i][1]));
  5298. break;
  5299. #ifndef NO_FP
  5300. case tokNumFloat:
  5301. printf2("%df", truncInt(stack[i][1]));
  5302. break;
  5303. #endif
  5304. case tokIdent:
  5305. {
  5306. char* p = IdentTable + stack[i][1];
  5307. if (isdigit(*p))
  5308. printf2("L");
  5309. printf2("%s", p);
  5310. }
  5311. break;
  5312. case tokShortCirc:
  5313. if (stack[i][1] >= 0)
  5314. printf2("[sh&&->%d]", stack[i][1]);
  5315. else
  5316. printf2("[sh||->%d]", -stack[i][1]);
  5317. break;
  5318. case tokLocalOfs:
  5319. printf2("(@%d)", truncInt(stack[i][1]));
  5320. break;
  5321. case tokUnaryStar:
  5322. if (j) printf2("*(%d)", stack[i][1]);
  5323. else printf2("*u");
  5324. break;
  5325. case '(': case ',':
  5326. if (!j) printf2("%c", tok);
  5327. // else printf2("\b");
  5328. break;
  5329. case ')':
  5330. if (j) printf2("(");
  5331. printf2("%c", tok);
  5332. if (j) printf2("%d", stack[i][1]);
  5333. break;
  5334. default:
  5335. printf2("%s", GetTokenName(tok));
  5336. if (j)
  5337. {
  5338. switch (tok)
  5339. {
  5340. case tokLogOr: case tokLogAnd:
  5341. printf2("[%d]", stack[i][1]);
  5342. break;
  5343. case '=':
  5344. case tokInc: case tokDec:
  5345. case tokPostInc: case tokPostDec:
  5346. case tokAssignAdd: case tokAssignSub:
  5347. case tokPostAdd: case tokPostSub:
  5348. case tokAssignMul:
  5349. case tokAssignDiv: case tokAssignMod:
  5350. case tokAssignUDiv: case tokAssignUMod:
  5351. case tokAssignLSh: case tokAssignRSh: case tokAssignURSh:
  5352. case tokAssignAnd: case tokAssignXor: case tokAssignOr:
  5353. printf2("(%d)", stack[i][1]);
  5354. break;
  5355. }
  5356. }
  5357. break;
  5358. }
  5359. printf2(" ");
  5360. }
  5361. printf2("\"\n");
  5362. #endif
  5363. if (!j)
  5364. {
  5365. int idx = sp - 1;
  5366. *ConstVal = exprval(&idx, ExprTypeSynPtr, ConstExpr);
  5367. // remove the unneeded unary +'s that have served their cast-substitute purpose
  5368. // also remove dereferences of size 0 (dereferences of pointers to structures)
  5369. for (idx = sp - 1; idx >= 0; idx--)
  5370. if (stack[idx][0] == tokUnaryPlus ||
  5371. (stack[idx][0] == tokUnaryStar && !stack[idx][1]))
  5372. del(idx, 1);
  5373. }
  5374. #ifndef NO_ANNOTATIONS
  5375. else if (*ConstExpr)
  5376. {
  5377. GenStartCommentLine();
  5378. switch (SyntaxStack0[*ExprTypeSynPtr])
  5379. {
  5380. case tokChar:
  5381. case tokSChar:
  5382. case tokUChar:
  5383. #ifdef CAN_COMPILE_32BIT
  5384. case tokShort:
  5385. case tokUShort:
  5386. #endif
  5387. case tokInt:
  5388. printf2("Expression value: %d\n", truncInt(*ConstVal));
  5389. break;
  5390. #ifndef NO_FP
  5391. case tokFloat:
  5392. printf2("Expression value: %df\n", truncInt(*ConstVal));
  5393. break;
  5394. #endif
  5395. default:
  5396. case tokUnsigned:
  5397. printf2("Expression value: %uu\n", truncUint(*ConstVal));
  5398. break;
  5399. }
  5400. }
  5401. #endif
  5402. }
  5403. }
  5404. ExprLevel--;
  5405. #ifndef NO_STRUCT_BY_VAL
  5406. // Reclaim stack space used by temporary structure/union objects
  5407. // returned by functions
  5408. CurFxnLocalOfs = oldOfs;
  5409. #endif
  5410. return tok;
  5411. }
  5412. // smc.c code
  5413. #ifdef __SMALLER_C__
  5414. #ifdef DETERMINE_VA_LIST
  5415. // 2 if va_list is a one-element array containing a pointer
  5416. // (typical for x86 Open Watcom C/C++)
  5417. // 1 if va_list is a pointer
  5418. // (typical for Turbo C++, x86 gcc)
  5419. // 0 if va_list is something else, and
  5420. // the code may have long crashed by now
  5421. int VaListType = 0;
  5422. // Attempts to determine the type of va_list as
  5423. // expected by the standard library
  5424. STATIC
  5425. void DetermineVaListType(void)
  5426. {
  5427. void* testptr[2];
  5428. // hopefully enough space to sprintf() 3 pointers using "%p"
  5429. char testbuf[3][CHAR_BIT * sizeof(void*) + 1];
  5430. // TBD!!! This is not good. Really need the va_something macros.
  5431. // Test whether va_list is a pointer to the first optional argument or
  5432. // an array of one element containing said pointer
  5433. testptr[0] = &testptr[1];
  5434. testptr[1] = &testptr[0];
  5435. memset(testbuf, '\0', sizeof(testbuf));
  5436. sprintf(testbuf[0], "%p", testptr[0]);
  5437. sprintf(testbuf[1], "%p", testptr[1]);
  5438. vsprintf(testbuf[2], "%p", &testptr[0]);
  5439. if (!strcmp(testbuf[2], testbuf[0]))
  5440. {
  5441. // va_list is a pointer
  5442. VaListType = 1;
  5443. }
  5444. else if (!strcmp(testbuf[2], testbuf[1]))
  5445. {
  5446. // va_list is a one-element array containing a pointer
  5447. VaListType = 2;
  5448. }
  5449. else
  5450. {
  5451. // va_list is something else, and
  5452. // the code may have long crashed by now
  5453. printf("Internal error: Indeterminate underlying type of va_list\n");
  5454. exit(EXIT_FAILURE);
  5455. }
  5456. }
  5457. #endif // DETERMINE_VA_LIST
  5458. #endif // __SMALLER_C__
  5459. // Equivalent to puts() but outputs to OutFile.
  5460. STATIC
  5461. int puts2(char* s)
  5462. {
  5463. int res;
  5464. if (!OutFile)
  5465. return 0;
  5466. // Turbo C++ 1.01's fputs() returns EOF if s is empty, which is wrong.
  5467. // Hence the workaround.
  5468. if (*s == '\0' || (res = fputs(s, OutFile)) >= 0)
  5469. {
  5470. // unlike puts(), fputs() doesn't append '\n', append it manually
  5471. res = fputc('\n', OutFile);
  5472. }
  5473. return res;
  5474. }
  5475. // Equivalent to printf() but outputs to OutFile.
  5476. STATIC
  5477. int printf2(char* format, ...)
  5478. {
  5479. int res;
  5480. #ifndef __SMALLER_C__
  5481. va_list vl;
  5482. va_start(vl, format);
  5483. #else
  5484. void* vl = &format + 1;
  5485. #endif
  5486. if (!OutFile)
  5487. return 0;
  5488. #ifndef __SMALLER_C__
  5489. res = vfprintf(OutFile, format, vl);
  5490. #else
  5491. // TBD!!! This is not good. Really need the va_something macros.
  5492. #ifdef DETERMINE_VA_LIST
  5493. if (VaListType == 2)
  5494. {
  5495. // va_list is a one-element array containing a pointer
  5496. res = vfprintf(OutFile, format, &vl);
  5497. }
  5498. else // if (VaListType == 1)
  5499. // fallthrough
  5500. #endif // DETERMINE_VA_LIST
  5501. {
  5502. // va_list is a pointer
  5503. res = vfprintf(OutFile, format, vl);
  5504. }
  5505. #endif // __SMALLER_C__
  5506. #ifndef __SMALLER_C__
  5507. va_end(vl);
  5508. #endif
  5509. return res;
  5510. }
  5511. STATIC
  5512. void error(char* format, ...)
  5513. {
  5514. int i, fidx = FileCnt - 1 + !FileCnt;
  5515. #ifndef __SMALLER_C__
  5516. va_list vl;
  5517. va_start(vl, format);
  5518. #else
  5519. void* vl = &format + 1;
  5520. #endif
  5521. for (i = 0; i < FileCnt; i++)
  5522. if (Files[i])
  5523. fclose(Files[i]);
  5524. puts2("");
  5525. #ifndef NO_ANNOTATIONS
  5526. DumpSynDecls();
  5527. #endif
  5528. #ifndef NO_PREPROCESSOR
  5529. #ifndef NO_ANNOTATIONS
  5530. DumpMacroTable();
  5531. #endif
  5532. #endif
  5533. #ifndef NO_ANNOTATIONS
  5534. DumpIdentTable();
  5535. #endif
  5536. // using stdout implicitly instead of stderr explicitly because:
  5537. // - stderr can be a macro and it's unknown if standard headers
  5538. // aren't included (which is the case when SmallerC is compiled
  5539. // with itself and linked with some other compiler's standard
  5540. // libraries)
  5541. // - output to stderr can interfere/overlap with buffered
  5542. // output to stdout and the result may literally look ugly
  5543. GenStartCommentLine(); printf2("Compilation failed.\n");
  5544. if (OutFile)
  5545. fclose(OutFile);
  5546. printf("Error in \"%s\" (%d:%d)\n", FileNames[fidx], LineNo, LinePos);
  5547. #ifndef __SMALLER_C__
  5548. vprintf(format, vl);
  5549. #else
  5550. // TBD!!! This is not good. Really need the va_something macros.
  5551. #ifdef DETERMINE_VA_LIST
  5552. if (VaListType == 2)
  5553. {
  5554. // va_list is a one-element array containing a pointer
  5555. vprintf(format, &vl);
  5556. }
  5557. else // if (VaListType == 1)
  5558. // fallthrough
  5559. #endif // DETERMINE_VA_LIST
  5560. {
  5561. // va_list is a pointer
  5562. vprintf(format, vl);
  5563. }
  5564. #endif // __SMALLER_C__
  5565. #ifndef __SMALLER_C__
  5566. va_end(vl);
  5567. #endif
  5568. exit(EXIT_FAILURE);
  5569. }
  5570. STATIC
  5571. void warning(char* format, ...)
  5572. {
  5573. int fidx = FileCnt - 1 + !FileCnt;
  5574. #ifndef __SMALLER_C__
  5575. va_list vl;
  5576. va_start(vl, format);
  5577. #else
  5578. void* vl = &format + 1;
  5579. #endif
  5580. warnCnt++;
  5581. if (!warnings)
  5582. return;
  5583. printf("Warning in \"%s\" (%d:%d)\n", FileNames[fidx], LineNo, LinePos);
  5584. #ifndef __SMALLER_C__
  5585. vprintf(format, vl);
  5586. #else
  5587. // TBD!!! This is not good. Really need the va_something macros.
  5588. #ifdef DETERMINE_VA_LIST
  5589. if (VaListType == 2)
  5590. {
  5591. // va_list is a one-element array containing a pointer
  5592. vprintf(format, &vl);
  5593. }
  5594. else // if (VaListType == 1)
  5595. // fallthrough
  5596. #endif // DETERMINE_VA_LIST
  5597. {
  5598. // va_list is a pointer
  5599. vprintf(format, vl);
  5600. }
  5601. #endif // __SMALLER_C__
  5602. #ifndef __SMALLER_C__
  5603. va_end(vl);
  5604. #endif
  5605. }
  5606. STATIC
  5607. void errorFile(char* n)
  5608. {
  5609. error("Unable to open, read, write or close file \"%s\"\n", n);
  5610. }
  5611. STATIC
  5612. void errorFileName(void)
  5613. {
  5614. error("Invalid or too long file name or path name\n");
  5615. }
  5616. STATIC
  5617. void errorInternal(int n)
  5618. {
  5619. error("%d (internal)\n", n);
  5620. }
  5621. STATIC
  5622. void errorChrStr(void)
  5623. {
  5624. error("Invalid or unsupported character constant or string literal\n");
  5625. }
  5626. #ifndef NO_WCHAR
  5627. STATIC
  5628. void errorWideNonWide(void)
  5629. {
  5630. error("Unsupported concatenation of wide and non-wide string literals\n");
  5631. }
  5632. #endif
  5633. STATIC
  5634. void errorStrLen(void)
  5635. {
  5636. error("String literal too long\n");
  5637. }
  5638. STATIC
  5639. void errorUnexpectedToken(int tok)
  5640. {
  5641. error("Unexpected token %s\n", (tok == tokIdent) ? TokenIdentName : GetTokenName(tok));
  5642. }
  5643. STATIC
  5644. void errorDirective(void)
  5645. {
  5646. error("Invalid or unsupported preprocessor directive\n");
  5647. }
  5648. STATIC
  5649. void errorCtrlOutOfScope(void)
  5650. {
  5651. error("break, continue, case or default in wrong scope\n");
  5652. }
  5653. STATIC
  5654. void errorDecl(void)
  5655. {
  5656. error("Invalid or unsupported declaration\n");
  5657. }
  5658. STATIC
  5659. void errorTagRedef(int ident)
  5660. {
  5661. error("Redefinition of type tagged '%s'\n", IdentTable + ident);
  5662. }
  5663. STATIC
  5664. void errorVarSize(void)
  5665. {
  5666. error("Variable(s) take(s) too much space\n");
  5667. }
  5668. STATIC
  5669. void errorInit(void)
  5670. {
  5671. error("Invalid or unsupported initialization\n");
  5672. }
  5673. STATIC
  5674. void errorUnexpectedVoid(void)
  5675. {
  5676. error("Unexpected declaration or expression of type void\n");
  5677. }
  5678. STATIC
  5679. void errorOpType(void)
  5680. {
  5681. error("Unexpected operand type\n");
  5682. }
  5683. STATIC
  5684. void errorNotLvalue(void)
  5685. {
  5686. error("lvalue expected\n");
  5687. }
  5688. STATIC
  5689. void errorNotConst(void)
  5690. {
  5691. error("Non-constant expression\n");
  5692. }
  5693. STATIC
  5694. void errorLongExpr(void)
  5695. {
  5696. error("Expression too long\n");
  5697. }
  5698. #ifndef NO_FP
  5699. STATIC
  5700. void warnFloat2Int(void)
  5701. {
  5702. warning("Float constant non-convertible to integer\n");
  5703. }
  5704. #endif
  5705. int tsd[] =
  5706. {
  5707. tokVoid, tokChar, tokInt,
  5708. tokSigned, tokUnsigned, tokShort,
  5709. #ifndef NO_FP
  5710. tokFloat, tokDouble,
  5711. #endif
  5712. tokStruct, tokUnion,
  5713. };
  5714. STATIC
  5715. int TokenStartsDeclaration(int t, int params)
  5716. {
  5717. unsigned i;
  5718. for (i = 0; i < division(sizeof tsd, sizeof tsd[0]); i++)
  5719. if (tsd[i] == t)
  5720. return 1;
  5721. return
  5722. #ifdef CAN_COMPILE_32BIT
  5723. (SizeOfWord != 2 && t == tokLong) ||
  5724. #endif
  5725. #ifndef NO_TYPEDEF_ENUM
  5726. t == tokEnum ||
  5727. (t == tokIdent && FindTypedef(TokenIdentName) >= 0) ||
  5728. #endif
  5729. (!params && (t == tokExtern ||
  5730. #ifndef NO_TYPEDEF_ENUM
  5731. t == tokTypedef ||
  5732. #endif
  5733. t == tokStatic));
  5734. }
  5735. STATIC
  5736. void PushSyntax2(int t, int v)
  5737. {
  5738. if (SyntaxStackCnt >= SYNTAX_STACK_MAX)
  5739. error("Symbol table exhausted\n");
  5740. SyntaxStack0[SyntaxStackCnt] = t;
  5741. SyntaxStack1[SyntaxStackCnt++] = v;
  5742. }
  5743. STATIC
  5744. void PushSyntax(int t)
  5745. {
  5746. PushSyntax2(t, 0);
  5747. }
  5748. STATIC
  5749. void InsertSyntax2(int pos, int t, int v)
  5750. {
  5751. if (SyntaxStackCnt >= SYNTAX_STACK_MAX)
  5752. error("Symbol table exhausted\n");
  5753. memmove(&SyntaxStack0[pos + 1],
  5754. &SyntaxStack0[pos],
  5755. sizeof(SyntaxStack0[0]) * (SyntaxStackCnt - pos));
  5756. memmove(&SyntaxStack1[pos + 1],
  5757. &SyntaxStack1[pos],
  5758. sizeof(SyntaxStack1[0]) * (SyntaxStackCnt - pos));
  5759. SyntaxStack0[pos] = t;
  5760. SyntaxStack1[pos] = v;
  5761. SyntaxStackCnt++;
  5762. }
  5763. STATIC
  5764. void InsertSyntax(int pos, int t)
  5765. {
  5766. InsertSyntax2(pos, t, 0);
  5767. }
  5768. STATIC
  5769. void DeleteSyntax(int pos, int cnt)
  5770. {
  5771. memmove(&SyntaxStack0[pos],
  5772. &SyntaxStack0[pos + cnt],
  5773. sizeof(SyntaxStack0[0]) * (SyntaxStackCnt - (pos + cnt)));
  5774. memmove(&SyntaxStack1[pos],
  5775. &SyntaxStack1[pos + cnt],
  5776. sizeof(SyntaxStack1[0]) * (SyntaxStackCnt - (pos + cnt)));
  5777. SyntaxStackCnt -= cnt;
  5778. }
  5779. STATIC
  5780. int FindSymbol(char* s)
  5781. {
  5782. int i;
  5783. // TBD!!! return declaration scope number so
  5784. // redeclarations can be reported if occur in the same scope.
  5785. // TBD??? Also, I could first use FindIdent() and then just look for the
  5786. // index into IdentTable[] instead of doing strcmp()
  5787. for (i = SyntaxStackCnt - 1; i >= 0; i--)
  5788. {
  5789. int t = SyntaxStack0[i];
  5790. if (t == tokIdent &&
  5791. !strcmp(IdentTable + SyntaxStack1[i], s))
  5792. {
  5793. return i;
  5794. }
  5795. if (t == ')')
  5796. {
  5797. // Skip over the function params
  5798. int c = -1;
  5799. while (c)
  5800. {
  5801. t = SyntaxStack0[--i];
  5802. c += (t == '(') - (t == ')');
  5803. }
  5804. }
  5805. }
  5806. return -1;
  5807. }
  5808. STATIC
  5809. int SymType(int SynPtr)
  5810. {
  5811. int local = 0;
  5812. if (SyntaxStack0[SynPtr] == tokIdent)
  5813. SynPtr++;
  5814. if ((local = SyntaxStack0[SynPtr] == tokLocalOfs) != 0)
  5815. SynPtr++;
  5816. switch (SyntaxStack0[SynPtr])
  5817. {
  5818. case '(':
  5819. return SymFxn;
  5820. case '[':
  5821. if (local)
  5822. return SymLocalArr;
  5823. return SymGlobalArr;
  5824. default:
  5825. if (local)
  5826. return SymLocalVar;
  5827. return SymGlobalVar;
  5828. }
  5829. }
  5830. STATIC
  5831. int FindTaggedDecl(char* s, int start, int* CurScope)
  5832. {
  5833. int i;
  5834. *CurScope = 1;
  5835. for (i = start; i >= 0; i--)
  5836. {
  5837. int t = SyntaxStack0[i];
  5838. if (t == tokTag &&
  5839. !strcmp(IdentTable + SyntaxStack1[i], s))
  5840. {
  5841. return i - 1;
  5842. }
  5843. else if (t == ')')
  5844. {
  5845. // Skip over the function params
  5846. int c = -1;
  5847. while (c)
  5848. {
  5849. t = SyntaxStack0[--i];
  5850. c += (t == '(') - (t == ')');
  5851. }
  5852. }
  5853. else if (t == '#')
  5854. {
  5855. // the scope has changed to the outer scope
  5856. *CurScope = 0;
  5857. }
  5858. }
  5859. return -1;
  5860. }
  5861. #ifndef NO_TYPEDEF_ENUM
  5862. // TBD??? rename this fxn? Cleanup/unify search functions?
  5863. STATIC
  5864. int FindTypedef(char* s)
  5865. {
  5866. int i;
  5867. for (i = SyntaxStackCnt - 1; i >= 0; i--)
  5868. {
  5869. int t = SyntaxStack0[i];
  5870. if ((t == tokTypedef || t == tokIdent) &&
  5871. !strcmp(IdentTable + SyntaxStack1[i], s))
  5872. {
  5873. // if the closest declaration isn't from typedef,
  5874. // (i.e. if it's a variable/function declaration),
  5875. // then the type is unknown for the purpose of
  5876. // declaring a variable of this type
  5877. return (t == tokIdent) ? -1 : i;
  5878. }
  5879. if (t == ')')
  5880. {
  5881. // Skip over the function params
  5882. int c = -1;
  5883. while (c)
  5884. {
  5885. t = SyntaxStack0[--i];
  5886. c += (t == '(') - (t == ')');
  5887. }
  5888. }
  5889. }
  5890. return -1;
  5891. }
  5892. #endif
  5893. STATIC
  5894. int GetDeclSize(int SyntaxPtr, int SizeForDeref)
  5895. {
  5896. int i;
  5897. unsigned size = 1;
  5898. int arr = 0;
  5899. if (SyntaxPtr < 0) // pointer?
  5900. return SizeOfWord;
  5901. for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
  5902. {
  5903. int tok = SyntaxStack0[i];
  5904. switch (tok)
  5905. {
  5906. case tokIdent: // skip leading identifiers, if any
  5907. case tokLocalOfs: // skip local var offset, too
  5908. break;
  5909. case tokChar:
  5910. case tokSChar:
  5911. if (!arr && ((tok == tokSChar) || CharIsSigned) && SizeForDeref)
  5912. return -1; // 1 byte, needing sign extension when converted to int/unsigned int
  5913. // fallthrough
  5914. case tokUChar:
  5915. return (int)size;
  5916. #ifdef CAN_COMPILE_32BIT
  5917. case tokShort:
  5918. if (!arr && SizeForDeref)
  5919. return -2; // 2 bytes, needing sign extension when converted to int/unsigned int
  5920. // fallthrough
  5921. case tokUShort:
  5922. //if (size * 2 / 2 != size)
  5923. //error("Variable too big\n");
  5924. // errorVarSize();
  5925. size *= 2;
  5926. if (size != truncUint(size))
  5927. //error("Variable too big\n");
  5928. errorVarSize();
  5929. return (int)size;
  5930. #endif
  5931. case tokInt:
  5932. case tokUnsigned:
  5933. #ifndef NO_FP
  5934. case tokFloat:
  5935. #endif
  5936. case '*':
  5937. case '(': // size of fxn = size of ptr for now
  5938. //if (size * SizeOfWord / SizeOfWord != size)
  5939. //error("Variable too big\n");
  5940. //errorVarSize();
  5941. size *= SizeOfWord;
  5942. if (size != truncUint(size))
  5943. //error("Variable too big\n");
  5944. errorVarSize();
  5945. return (int)size;
  5946. case '[':
  5947. if (SyntaxStack0[i + 1] != tokNumInt && SyntaxStack0[i + 1] != tokNumUint)
  5948. errorInternal(11);
  5949. //if (SyntaxStack1[i + 1] &&
  5950. //size * SyntaxStack1[i + 1] / SyntaxStack1[i + 1] != size)
  5951. //error("Variable too big\n");
  5952. //errorVarSize();
  5953. size *= SyntaxStack1[i + 1];
  5954. if (size != truncUint(size))
  5955. //error("Variable too big\n");
  5956. errorVarSize();
  5957. i += 2;
  5958. arr = 1;
  5959. break;
  5960. case tokStructPtr:
  5961. // follow the "type pointer"
  5962. i = SyntaxStack1[i] - 1;
  5963. break;
  5964. case tokStruct:
  5965. case tokUnion:
  5966. if (i + 2 < SyntaxStackCnt && SyntaxStack0[i + 2] == tokSizeof && !SizeForDeref)
  5967. {
  5968. unsigned s = SyntaxStack1[i + 2];
  5969. //if (s && size * s / s != size)
  5970. // errorVarSize();
  5971. size *= s;
  5972. if (size != truncUint(size))
  5973. errorVarSize();
  5974. return (int)size;
  5975. }
  5976. return 0;
  5977. case tokVoid:
  5978. return 0;
  5979. default:
  5980. errorInternal(12);
  5981. }
  5982. }
  5983. errorInternal(13);
  5984. return 0;
  5985. }
  5986. STATIC
  5987. int GetDeclAlignment(int SyntaxPtr)
  5988. {
  5989. int i;
  5990. if (SyntaxPtr < 0) // pointer?
  5991. return SizeOfWord;
  5992. for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
  5993. {
  5994. int tok = SyntaxStack0[i];
  5995. switch (tok)
  5996. {
  5997. case tokIdent: // skip leading identifiers, if any
  5998. case tokLocalOfs: // skip local var offset, too
  5999. break;
  6000. case tokChar:
  6001. case tokSChar:
  6002. case tokUChar:
  6003. return 1;
  6004. #ifdef CAN_COMPILE_32BIT
  6005. case tokShort:
  6006. case tokUShort:
  6007. return 2;
  6008. #endif
  6009. case tokInt:
  6010. case tokUnsigned:
  6011. #ifndef NO_FP
  6012. case tokFloat:
  6013. #endif
  6014. case '*':
  6015. case '(':
  6016. return SizeOfWord;
  6017. case '[':
  6018. if (SyntaxStack0[i + 1] != tokNumInt && SyntaxStack0[i + 1] != tokNumUint)
  6019. errorInternal(15);
  6020. i += 2;
  6021. break;
  6022. case tokStructPtr:
  6023. // follow the "type pointer"
  6024. i = SyntaxStack1[i] - 1;
  6025. break;
  6026. case tokStruct:
  6027. case tokUnion:
  6028. if (i + 3 < SyntaxStackCnt && SyntaxStack0[i + 2] == tokSizeof)
  6029. {
  6030. return SyntaxStack1[i + 3];
  6031. }
  6032. return 1;
  6033. case tokVoid:
  6034. return 1;
  6035. default:
  6036. errorInternal(16);
  6037. }
  6038. }
  6039. errorInternal(17);
  6040. return 0;
  6041. }
  6042. #ifndef NO_ANNOTATIONS
  6043. STATIC
  6044. void DumpDecl(int SyntaxPtr, int IsParam)
  6045. {
  6046. int i;
  6047. int icnt = 0;
  6048. if (SyntaxPtr < 0)
  6049. return;
  6050. for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
  6051. {
  6052. int tok = SyntaxStack0[i];
  6053. int v = SyntaxStack1[i];
  6054. switch (tok)
  6055. {
  6056. case tokLocalOfs:
  6057. printf2("(@%d) : ", truncInt(v));
  6058. break;
  6059. case tokIdent:
  6060. if (++icnt > 1 && !IsParam) // show at most one declaration, except params
  6061. return;
  6062. GenStartCommentLine();
  6063. if (ParseLevel == 0)
  6064. printf2("glb ");
  6065. else if (IsParam)
  6066. printf2("prm ");
  6067. else
  6068. printf2("loc ");
  6069. {
  6070. int j;
  6071. for (j = 0; j < ParseLevel * 4; j++)
  6072. printf2(" ");
  6073. }
  6074. if (IsParam && !strcmp(IdentTable + v, "<something>") && (i + 1 < SyntaxStackCnt))
  6075. {
  6076. if (SyntaxStack0[i + 1] == tokEllipsis)
  6077. continue;
  6078. }
  6079. printf2("%s : ", IdentTable + v);
  6080. if (!IsParam && (i + 1 < SyntaxStackCnt) && SyntaxStack0[i + 1] == tokIdent)
  6081. {
  6082. // renamed local static variable
  6083. GenPrintLabel(IdentTable + SyntaxStack1[++i]);
  6084. printf2(" : ");
  6085. }
  6086. break;
  6087. case '[':
  6088. printf2("[");
  6089. break;
  6090. case tokNumInt:
  6091. printf2("%d", truncInt(v));
  6092. break;
  6093. case tokNumUint:
  6094. printf2("%uu", truncUint(v));
  6095. break;
  6096. case ']':
  6097. printf2("] ");
  6098. break;
  6099. case '(':
  6100. {
  6101. int noparams;
  6102. // Skip over the params to the base type
  6103. int j = ++i, c = 1;
  6104. while (c)
  6105. {
  6106. int t = SyntaxStack0[j++];
  6107. c += (t == '(') - (t == ')');
  6108. }
  6109. noparams = (i + 1 == j) || (SyntaxStack0[i + 1] == tokVoid);
  6110. printf2("(");
  6111. // Print the params (recursively)
  6112. if (noparams)
  6113. {
  6114. // Don't recurse if it's "fxn()" or "fxn(void)"
  6115. if (i + 1 != j)
  6116. printf2("void");
  6117. }
  6118. else
  6119. {
  6120. puts2("");
  6121. ParseLevel++;
  6122. DumpDecl(i, 1);
  6123. ParseLevel--;
  6124. }
  6125. // Continue normally
  6126. i = j - 1;
  6127. if (!noparams)
  6128. {
  6129. GenStartCommentLine();
  6130. printf2(" ");
  6131. {
  6132. int j;
  6133. for (j = 0; j < ParseLevel * 4; j++)
  6134. printf2(" ");
  6135. }
  6136. }
  6137. printf2(") ");
  6138. }
  6139. break;
  6140. case ')': // end of param list
  6141. return;
  6142. case tokStructPtr:
  6143. DumpDecl(v, 0);
  6144. break;
  6145. default:
  6146. switch (tok)
  6147. {
  6148. case tokVoid:
  6149. case tokChar:
  6150. case tokSChar:
  6151. case tokUChar:
  6152. #ifdef CAN_COMPILE_32BIT
  6153. case tokShort:
  6154. case tokUShort:
  6155. #endif
  6156. case tokInt:
  6157. case tokUnsigned:
  6158. #ifndef NO_FP
  6159. case tokFloat:
  6160. #endif
  6161. case tokEllipsis:
  6162. printf2("%s\n", GetTokenName(tok));
  6163. break;
  6164. default:
  6165. printf2("%s ", GetTokenName(tok));
  6166. break;
  6167. case tokTag:
  6168. printf2("%s\n", IdentTable + v);
  6169. return;
  6170. }
  6171. break;
  6172. }
  6173. }
  6174. }
  6175. #endif
  6176. #ifndef NO_ANNOTATIONS
  6177. STATIC
  6178. void DumpSynDecls(void)
  6179. {
  6180. int used = SyntaxStackCnt * (sizeof SyntaxStack0[0] + sizeof SyntaxStack1[0]);
  6181. int total = SYNTAX_STACK_MAX * (sizeof SyntaxStack0[0] + sizeof SyntaxStack1[0]);
  6182. puts2("");
  6183. GenStartCommentLine(); printf2("Syntax/declaration table/stack:\n");
  6184. GenStartCommentLine(); printf2("Bytes used: %d/%d\n\n", used, total);
  6185. }
  6186. #endif
  6187. STATIC
  6188. int ParseArrayDimension(int AllowEmptyDimension)
  6189. {
  6190. int tok;
  6191. int gotUnary, synPtr, constExpr, exprVal;
  6192. unsigned exprValU;
  6193. int oldssp, oldesp, undoIdents;
  6194. tok = GetToken();
  6195. // DONE: support arbitrary constant expressions
  6196. oldssp = SyntaxStackCnt;
  6197. oldesp = sp;
  6198. undoIdents = IdentTableLen;
  6199. tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0);
  6200. IdentTableLen = undoIdents; // remove all temporary identifier names from e.g. "sizeof"
  6201. SyntaxStackCnt = oldssp; // undo any temporary declarations from e.g. "sizeof" in the expression
  6202. sp = oldesp;
  6203. if (tok != ']')
  6204. //error("ParseArrayDimension(): Unsupported or invalid array dimension (token %s)\n", GetTokenName(tok));
  6205. errorUnexpectedToken(tok);
  6206. if (!gotUnary)
  6207. {
  6208. if (!AllowEmptyDimension)
  6209. //error("ParseArrayDimension(): missing array dimension\n");
  6210. errorUnexpectedToken(tok);
  6211. // Empty dimension is dimension of 0
  6212. exprVal = 0;
  6213. }
  6214. else
  6215. {
  6216. if (!constExpr)
  6217. //error("ParseArrayDimension(): non-constant array dimension\n");
  6218. errorNotConst();
  6219. exprValU = truncUint(exprVal);
  6220. exprVal = truncInt(exprVal);
  6221. promoteType(&synPtr, &synPtr);
  6222. anyIntTypeCheck(synPtr);
  6223. if ((SyntaxStack0[synPtr] == tokInt && exprVal < 1) || (SyntaxStack0[synPtr] == tokUnsigned && exprValU < 1))
  6224. error("Array dimension less than 1\n");
  6225. exprVal = (int)exprValU;
  6226. }
  6227. PushSyntax2(tokNumUint, exprVal);
  6228. return tok;
  6229. }
  6230. STATIC
  6231. void ParseFxnParams(int tok);
  6232. static int BrkCntTargetFxn[2];
  6233. STATIC
  6234. int ParseBlock(int BrkCntTarget[2], int casesIdx);
  6235. STATIC
  6236. void AddFxnParamSymbols(int SyntaxPtr);
  6237. STATIC
  6238. void CheckRedecl(int lastSyntaxPtr);
  6239. STATIC
  6240. int ParseBase(int tok, int base[2])
  6241. {
  6242. int valid = 1;
  6243. base[1] = 0;
  6244. switch (tok)
  6245. {
  6246. #ifndef NO_FP
  6247. case tokFloat:
  6248. #endif
  6249. case tokVoid:
  6250. *base = tok;
  6251. tok = GetToken();
  6252. break;
  6253. #ifndef NO_FP
  6254. case tokDouble:
  6255. #endif
  6256. case tokChar:
  6257. case tokInt:
  6258. case tokShort:
  6259. #ifdef CAN_COMPILE_32BIT
  6260. case tokLong:
  6261. #endif
  6262. case tokSigned:
  6263. case tokUnsigned:
  6264. {
  6265. int allowedMask = 0x7F; // double:0x40 unsigned:0x20 signed:0x10 long:0x08 int:0x04 short:0x02 char:0x01
  6266. int typeMask = 0;
  6267. int tokMask, disallowedMask;
  6268. lcont:
  6269. switch (tok)
  6270. {
  6271. case tokChar:
  6272. tokMask = 0x01; disallowedMask = 0x4E; break; // disallows double, long, int, short
  6273. case tokShort:
  6274. tokMask = 0x02; disallowedMask = 0x49; break; // disallows double, long, char
  6275. case tokInt:
  6276. tokMask = 0x04; disallowedMask = 0x41; break; // disallows double, char
  6277. #ifdef CAN_COMPILE_32BIT
  6278. case tokLong:
  6279. tokMask = 0x08; disallowedMask = 0x03; break; // disallows short, char
  6280. #endif
  6281. case tokSigned:
  6282. tokMask = 0x10; disallowedMask = 0x60; break; // disallows double, unsigned
  6283. case tokUnsigned:
  6284. tokMask = 0x20; disallowedMask = 0x50; break; // disallows double, signed
  6285. #ifndef NO_FP
  6286. case tokDouble:
  6287. tokMask = 0x40; disallowedMask = 0x37; break; // disallows all except long
  6288. #endif
  6289. default:
  6290. tokMask = disallowedMask = 0; break;
  6291. }
  6292. if (allowedMask & tokMask)
  6293. {
  6294. typeMask |= tokMask;
  6295. allowedMask &= ~(disallowedMask | tokMask);
  6296. tok = GetToken();
  6297. goto lcont;
  6298. }
  6299. switch (typeMask)
  6300. {
  6301. case 0x01: typeMask = tokChar; break;
  6302. case 0x11: typeMask = tokSChar; break;
  6303. case 0x21: typeMask = tokUChar; break;
  6304. case 0x02: case 0x12: case 0x06: case 0x16: typeMask = tokShort; break;
  6305. case 0x22: case 0x26: typeMask = tokUShort; break;
  6306. case 0x04: case 0x10: case 0x14: typeMask = tokInt; break;
  6307. case 0x20: case 0x24: typeMask = tokUnsigned; break;
  6308. #ifdef CAN_COMPILE_32BIT
  6309. case 0x08: case 0x18: case 0x0C: case 0x1C: typeMask = tokLong; break;
  6310. case 0x28: case 0x2C: typeMask = tokULong; break;
  6311. #endif
  6312. #ifndef NO_FP
  6313. case 0x40: case 0x48: typeMask = tokFloat; break; // (long) double is alias for float
  6314. #endif
  6315. default:
  6316. errorDecl();
  6317. }
  6318. *base = typeMask;
  6319. }
  6320. break;
  6321. case tokStruct:
  6322. case tokUnion:
  6323. #ifndef NO_TYPEDEF_ENUM
  6324. case tokEnum:
  6325. #endif
  6326. {
  6327. int structType = tok;
  6328. int empty = 1;
  6329. int typePtr = SyntaxStackCnt;
  6330. int gotTag = 0, tagIdent = 0, declPtr = -1, curScope = 0;
  6331. tok = GetToken();
  6332. if (tok == tokIdent)
  6333. {
  6334. // this is a structure/union/enum tag
  6335. gotTag = 1;
  6336. declPtr = FindTaggedDecl(TokenIdentName, SyntaxStackCnt - 1, &curScope);
  6337. tagIdent = AddIdent(TokenIdentName);
  6338. if (declPtr >= 0)
  6339. {
  6340. // Within the same scope we can't declare more than one union, structure or enum
  6341. // with the same tag.
  6342. // There's one common tag namespace for structures, unions and enumerations.
  6343. if (curScope && SyntaxStack0[declPtr] != structType)
  6344. errorTagRedef(tagIdent);
  6345. }
  6346. else if (ParamLevel)
  6347. {
  6348. // new structure/union/enum declarations aren't supported in function parameters
  6349. errorDecl();
  6350. }
  6351. tok = GetToken();
  6352. }
  6353. else
  6354. {
  6355. // structure/union/enum declarations aren't supported in expressions
  6356. if (ExprLevel)
  6357. errorDecl();
  6358. PushSyntax(structType);
  6359. PushSyntax2(tokTag, AddIdent("<something>"));
  6360. }
  6361. if (tok == '{')
  6362. {
  6363. unsigned structInfo[4], sz, alignment, tmp;
  6364. // new structure/union/enum declarations aren't supported in expressions and function parameters
  6365. if (ExprLevel || ParamLevel)
  6366. errorDecl();
  6367. if (gotTag)
  6368. {
  6369. // Cannot redefine a tagged structure/union/enum within the same scope
  6370. if (declPtr >= 0 &&
  6371. curScope &&
  6372. ((declPtr + 2 < SyntaxStackCnt && SyntaxStack0[declPtr + 2] == tokSizeof)
  6373. #ifndef NO_TYPEDEF_ENUM
  6374. || structType == tokEnum
  6375. #endif
  6376. ))
  6377. errorTagRedef(tagIdent);
  6378. PushSyntax(structType);
  6379. PushSyntax2(tokTag, tagIdent);
  6380. }
  6381. #ifndef NO_TYPEDEF_ENUM
  6382. if (structType == tokEnum)
  6383. {
  6384. int lastVal = -1, val = 0;
  6385. int maxVal = (int)(truncUint(~0u) >> 1); // max positive signed int
  6386. char* erange = "Enumeration constant out of range\n";
  6387. tok = GetToken();
  6388. while (tok != '}')
  6389. {
  6390. char* s;
  6391. int ident;
  6392. int lastSyntaxPtr;
  6393. if (tok != tokIdent)
  6394. errorUnexpectedToken(tok);
  6395. s = TokenIdentName;
  6396. ident = AddIdent(s);
  6397. empty = 0;
  6398. tok = GetToken();
  6399. if (tok == '=')
  6400. {
  6401. int gotUnary, synPtr, constExpr;
  6402. int oldssp, oldesp, undoIdents;
  6403. oldssp = SyntaxStackCnt;
  6404. oldesp = sp;
  6405. undoIdents = IdentTableLen;
  6406. tok = ParseExpr(GetToken(), &gotUnary, &synPtr, &constExpr, &val, ',', 0);
  6407. IdentTableLen = undoIdents; // remove all temporary identifier names from e.g. "sizeof"
  6408. SyntaxStackCnt = oldssp; // undo any temporary declarations from e.g. "sizeof" in the expression
  6409. sp = oldesp;
  6410. if (!gotUnary)
  6411. errorUnexpectedToken(tok);
  6412. anyIntTypeCheck(synPtr);
  6413. if (!constExpr)
  6414. errorNotConst();
  6415. if (SyntaxStack0[synPtr] == tokUnsigned && truncUint(val) > (unsigned)maxVal)
  6416. error(erange);
  6417. lastVal = val = truncInt(val);
  6418. }
  6419. else
  6420. {
  6421. if (lastVal == maxVal)
  6422. error(erange);
  6423. lastVal = val = lastVal + 1;
  6424. }
  6425. lastSyntaxPtr = SyntaxStackCnt;
  6426. PushSyntax2(tokIdent, ident);
  6427. PushSyntax2(tokNumInt, val);
  6428. if (tok == ',')
  6429. tok = GetToken();
  6430. else if (tok != '}')
  6431. errorUnexpectedToken(tok);
  6432. CheckRedecl(lastSyntaxPtr);
  6433. }
  6434. if (empty)
  6435. errorUnexpectedToken('}');
  6436. base[0] = tokEnumPtr;
  6437. base[1] = typePtr;
  6438. tok = GetToken();
  6439. return tok;
  6440. }
  6441. else
  6442. #endif
  6443. {
  6444. structInfo[0] = structType;
  6445. structInfo[1] = 1; // initial member alignment
  6446. structInfo[2] = 0; // initial member offset
  6447. structInfo[3] = 0; // initial max member size (for unions)
  6448. PushSyntax(tokSizeof); // 0 = initial structure/union size, to be updated
  6449. PushSyntax2(tokSizeof, 1); // 1 = initial structure/union alignment, to be updated
  6450. PushSyntax('{');
  6451. tok = GetToken();
  6452. while (tok != '}')
  6453. {
  6454. if (!TokenStartsDeclaration(tok, 1))
  6455. errorUnexpectedToken(tok);
  6456. tok = ParseDecl(tok, structInfo, 0, 0);
  6457. empty = 0;
  6458. }
  6459. if (empty)
  6460. errorUnexpectedToken('}');
  6461. PushSyntax('}');
  6462. // Update structure/union alignment
  6463. alignment = structInfo[1];
  6464. SyntaxStack1[typePtr + 3] = alignment;
  6465. // Update structure/union size and include trailing padding if needed
  6466. sz = structInfo[2] + structInfo[3];
  6467. tmp = sz;
  6468. sz = (sz + alignment - 1) & ~(alignment - 1);
  6469. if (sz < tmp || sz != truncUint(sz))
  6470. errorVarSize();
  6471. SyntaxStack1[typePtr + 2] = (int)sz;
  6472. tok = GetToken();
  6473. }
  6474. }
  6475. else
  6476. {
  6477. #ifndef NO_TYPEDEF_ENUM
  6478. if (structType == tokEnum)
  6479. {
  6480. if (!gotTag || declPtr < 0)
  6481. errorDecl(); // TBD!!! different error when enum tag is not found
  6482. base[0] = tokEnumPtr;
  6483. base[1] = declPtr;
  6484. return tok;
  6485. }
  6486. #endif
  6487. if (gotTag)
  6488. {
  6489. if (declPtr >= 0 &&
  6490. SyntaxStack0[declPtr] == structType)
  6491. {
  6492. base[0] = tokStructPtr;
  6493. base[1] = declPtr;
  6494. return tok;
  6495. }
  6496. PushSyntax(structType);
  6497. PushSyntax2(tokTag, tagIdent);
  6498. empty = 0;
  6499. }
  6500. }
  6501. if (empty)
  6502. errorDecl();
  6503. base[0] = tokStructPtr;
  6504. base[1] = typePtr;
  6505. // If we've just defined a structure/union and there are
  6506. // preceding references to this tag within this scope,
  6507. // IOW references to an incomplete type, complete the
  6508. // type in the references
  6509. if (gotTag && SyntaxStack0[SyntaxStackCnt - 1] == '}')
  6510. {
  6511. int i;
  6512. for (i = SyntaxStackCnt - 1; i >= 0; i--)
  6513. if (SyntaxStack0[i] == tokStructPtr)
  6514. {
  6515. int j = SyntaxStack1[i];
  6516. if (SyntaxStack1[j + 1] == tagIdent && !GetDeclSize(i, 0))
  6517. SyntaxStack1[i] = typePtr;
  6518. }
  6519. else if (SyntaxStack0[i] == '#')
  6520. {
  6521. // reached the beginning of the current scope
  6522. break;
  6523. }
  6524. }
  6525. }
  6526. break;
  6527. #ifndef NO_TYPEDEF_ENUM
  6528. case tokIdent:
  6529. if ((base[1] = FindTypedef(TokenIdentName)) >= 0)
  6530. {
  6531. base[0] = tokTypedef;
  6532. tok = GetToken();
  6533. break;
  6534. }
  6535. // fallthrough to default
  6536. #endif
  6537. default:
  6538. valid = 0;
  6539. break;
  6540. }
  6541. #ifdef CAN_COMPILE_32BIT
  6542. if (SizeOfWord == 2 &&
  6543. (*base == tokLong || *base == tokULong))
  6544. valid = 0;
  6545. // to simplify matters, treat long and unsigned long as aliases for int and unsigned int
  6546. // in 32-bit and huge mode(l)s
  6547. if (*base == tokLong)
  6548. *base = tokInt;
  6549. if (*base == tokULong)
  6550. *base = tokUnsigned;
  6551. #endif
  6552. if (SizeOfWord == 2)
  6553. {
  6554. // to simplify matters, treat short and unsigned short as aliases for int and unsigned int
  6555. // in 16-bit mode
  6556. if (*base == tokShort)
  6557. *base = tokInt;
  6558. if (*base == tokUShort)
  6559. *base = tokUnsigned;
  6560. }
  6561. // TBD!!! review/test this fxn
  6562. // if (!valid || !tok || !(strchr("*([,)", tok) || tok == tokIdent))
  6563. if (!valid | !tok)
  6564. //error("ParseBase(): Invalid or unsupported type\n");
  6565. error("Invalid or unsupported type\n");
  6566. return tok;
  6567. }
  6568. /*
  6569. base * name [] -> name : [] * base
  6570. base *2 (*1 name []1) []2 -> name : []1 *1 []2 *2 base
  6571. base *3 (*2 (*1 name []1) []2) []3 -> name : []1 *1 []2 *2 []3 *3 base
  6572. */
  6573. STATIC
  6574. int ParseDerived(int tok)
  6575. {
  6576. int stars = 0;
  6577. int params = 0;
  6578. #ifndef MIPS
  6579. #ifdef CAN_COMPILE_32BIT
  6580. int isInterrupt = 0;
  6581. #endif
  6582. #endif
  6583. while (tok == '*')
  6584. {
  6585. stars++;
  6586. tok = GetToken();
  6587. }
  6588. #ifndef MIPS
  6589. #ifdef CAN_COMPILE_32BIT
  6590. if (tok == tokIntr)
  6591. {
  6592. // __interrupt is supported in the huge and unreal mode(l)s only
  6593. if (OutputFormat != FormatSegHuge && OutputFormat != FormatSegUnreal)
  6594. errorDecl();
  6595. isInterrupt = 1;
  6596. tok = GetToken();
  6597. }
  6598. #endif
  6599. #endif
  6600. if (tok == '(')
  6601. {
  6602. tok = GetToken();
  6603. if (tok != ')' && !TokenStartsDeclaration(tok, 1))
  6604. {
  6605. tok = ParseDerived(tok);
  6606. if (tok != ')')
  6607. //error("ParseDerived(): ')' expected\n");
  6608. errorUnexpectedToken(tok);
  6609. tok = GetToken();
  6610. }
  6611. else
  6612. {
  6613. params = 1;
  6614. }
  6615. }
  6616. else if (tok == tokIdent)
  6617. {
  6618. PushSyntax2(tok, AddIdent(TokenIdentName));
  6619. tok = GetToken();
  6620. }
  6621. else
  6622. {
  6623. PushSyntax2(tokIdent, AddIdent("<something>"));
  6624. }
  6625. if (params | (tok == '('))
  6626. {
  6627. int t = SyntaxStack0[SyntaxStackCnt - 1];
  6628. if ((t == ')') | (t == ']'))
  6629. errorUnexpectedToken('('); // array of functions or function returning function
  6630. if (!params)
  6631. tok = GetToken();
  6632. else
  6633. PushSyntax2(tokIdent, AddIdent("<something>"));
  6634. #ifndef MIPS
  6635. #ifdef CAN_COMPILE_32BIT
  6636. if (isInterrupt)
  6637. PushSyntax2('(', 1);
  6638. else // fallthrough
  6639. #endif
  6640. #endif
  6641. PushSyntax('(');
  6642. ParseLevel++;
  6643. ParamLevel++;
  6644. ParseFxnParams(tok);
  6645. ParamLevel--;
  6646. ParseLevel--;
  6647. PushSyntax(')');
  6648. tok = GetToken();
  6649. }
  6650. else if (tok == '[')
  6651. {
  6652. // DONE!!! allow the first [] without the dimension in function parameters
  6653. int allowEmptyDimension = 1;
  6654. if (SyntaxStack0[SyntaxStackCnt - 1] == ')')
  6655. errorUnexpectedToken('['); // function returning array
  6656. while (tok == '[')
  6657. {
  6658. int oldsp = SyntaxStackCnt;
  6659. PushSyntax(tokVoid); // prevent cases like "int arr[arr];" and "int arr[arr[0]];"
  6660. PushSyntax(tok);
  6661. tok = ParseArrayDimension(allowEmptyDimension);
  6662. if (tok != ']')
  6663. //error("ParseDerived(): ']' expected\n");
  6664. errorUnexpectedToken(tok);
  6665. PushSyntax(']');
  6666. tok = GetToken();
  6667. DeleteSyntax(oldsp, 1);
  6668. allowEmptyDimension = 0;
  6669. }
  6670. }
  6671. while (stars--)
  6672. PushSyntax('*');
  6673. if (!tok || !strchr(",;{=)", tok))
  6674. //error("ParseDerived(): unexpected token %s\n", GetTokenName(tok));
  6675. errorUnexpectedToken(tok);
  6676. return tok;
  6677. }
  6678. STATIC
  6679. void PushBase(int base[2])
  6680. {
  6681. #ifndef NO_TYPEDEF_ENUM
  6682. if (base[0] == tokTypedef)
  6683. {
  6684. int ptr = base[1];
  6685. int c = 0, copying = 1;
  6686. while (copying)
  6687. {
  6688. int tok = SyntaxStack0[++ptr];
  6689. int t = SyntaxStack0[SyntaxStackCnt - 1];
  6690. // Cannot have:
  6691. // function returning function
  6692. // array of functions
  6693. // function returning array
  6694. if (((t == ')' || t == ']') && tok == '(') ||
  6695. (t == ')' && tok == '['))
  6696. errorDecl();
  6697. PushSyntax2(tok, SyntaxStack1[ptr]);
  6698. c += (tok == '(') - (tok == ')') + (tok == '[') - (tok == ']');
  6699. if (!c)
  6700. {
  6701. switch (tok)
  6702. {
  6703. case tokVoid:
  6704. case tokChar: case tokSChar: case tokUChar:
  6705. #ifdef CAN_COMPILE_32BIT
  6706. case tokShort: case tokUShort:
  6707. #endif
  6708. case tokInt: case tokUnsigned:
  6709. #ifndef NO_FP
  6710. case tokFloat:
  6711. #endif
  6712. case tokStructPtr:
  6713. copying = 0;
  6714. }
  6715. }
  6716. }
  6717. }
  6718. else
  6719. #endif
  6720. {
  6721. PushSyntax2(base[0], base[1]);
  6722. }
  6723. // Cannot have array of void
  6724. if (SyntaxStack0[SyntaxStackCnt - 1] == tokVoid &&
  6725. SyntaxStack0[SyntaxStackCnt - 2] == ']')
  6726. errorUnexpectedVoid();
  6727. }
  6728. STATIC
  6729. int InitScalar(int synPtr, int tok);
  6730. STATIC
  6731. int InitArray(int synPtr, int tok);
  6732. STATIC
  6733. int InitStruct(int synPtr, int tok);
  6734. STATIC
  6735. int InitVar(int synPtr, int tok)
  6736. {
  6737. int p = synPtr, t;
  6738. int undoIdents = IdentTableLen;
  6739. while ((t = SyntaxStack0[p]), (t == tokIdent) | (t == tokLocalOfs))
  6740. p++;
  6741. switch (t)
  6742. {
  6743. case '[':
  6744. // Initializers for aggregates must be enclosed in braces,
  6745. // except for arrays of char initialized with string literals,
  6746. // in which case braces are optional
  6747. if (tok != '{')
  6748. {
  6749. t = SyntaxStack0[p + 3];
  6750. if (((tok != tokLitStr) | ((t != tokChar) & (t != tokUChar) & (t != tokSChar)))
  6751. #ifndef NO_WCHAR
  6752. & ((tok != tokLitStrWide) | ((t != WideCharType1) & (t != WideCharType2)))
  6753. #endif
  6754. )
  6755. errorUnexpectedToken(tok);
  6756. }
  6757. tok = InitArray(p, tok);
  6758. break;
  6759. case tokStructPtr:
  6760. // Initializers for aggregates must be enclosed in braces
  6761. if (tok != '{')
  6762. errorUnexpectedToken(tok);
  6763. tok = InitStruct(p, tok);
  6764. break;
  6765. default:
  6766. tok = InitScalar(p, tok);
  6767. break;
  6768. }
  6769. if (!strchr(",;", tok))
  6770. errorUnexpectedToken(tok);
  6771. IdentTableLen = undoIdents; // remove all temporary identifier names from e.g. "sizeof" or "str"
  6772. return tok;
  6773. }
  6774. STATIC
  6775. int InitScalar(int synPtr, int tok)
  6776. {
  6777. unsigned elementSz = GetDeclSize(synPtr, 0);
  6778. int gotUnary, synPtr2, constExpr, exprVal;
  6779. int oldssp = SyntaxStackCnt;
  6780. int undoIdents = IdentTableLen;
  6781. int ttop;
  6782. int braces = 0;
  6783. #ifndef NO_FP
  6784. int ptrmask;
  6785. int fmask;
  6786. #endif
  6787. // Initializers for scalars can be optionally enclosed in braces
  6788. if (tok == '{')
  6789. {
  6790. braces = 1;
  6791. tok = GetToken();
  6792. }
  6793. tok = ParseExpr(tok, &gotUnary, &synPtr2, &constExpr, &exprVal, ',', 0);
  6794. if (!gotUnary)
  6795. errorUnexpectedToken(tok);
  6796. if (braces)
  6797. {
  6798. if (tok != '}')
  6799. errorUnexpectedToken(tok);
  6800. tok = GetToken();
  6801. }
  6802. // Bar void and struct/union
  6803. scalarTypeCheck(synPtr2);
  6804. #ifndef NO_FP
  6805. ptrmask = isAnyPtr(synPtr) * 2 + isAnyPtr(synPtr2);
  6806. fmask = isFloat(synPtr) * 2 + isFloat(synPtr2);
  6807. if (ptrmask && fmask) // pointers and floats don't mix
  6808. errorOpType();
  6809. #endif
  6810. ttop = stack[sp - 1][0];
  6811. if (ttop == tokNumInt || ttop == tokNumUint)
  6812. {
  6813. int val = stack[sp - 1][1];
  6814. #ifndef NO_FP
  6815. if (fmask == 1 || fmask == 2)
  6816. {
  6817. int u = isUint((fmask == 1) ? synPtr : synPtr2);
  6818. // convert between float and [unsigned] int
  6819. if (fmask == 1)
  6820. val = u ? f2u(val) : f2i(val, GetDeclSize(synPtr, 1));
  6821. else
  6822. val = u ? u2f(val) : i2f(val);
  6823. }
  6824. #endif
  6825. // TBD??? truncate values for types smaller than int (e.g. char and short),
  6826. // so they are always in range for the assembler?
  6827. GenIntData(elementSz, val);
  6828. }
  6829. else if (elementSz == (unsigned)SizeOfWord)
  6830. {
  6831. if (ttop == tokIdent)
  6832. {
  6833. GenAddrData(elementSz, IdentTable + stack[sp - 1][1], 0);
  6834. }
  6835. else if (ttop == '+' || ttop == '-')
  6836. {
  6837. int tleft = stack[sp - 3][0];
  6838. int tright = stack[sp - 2][0];
  6839. if (tleft == tokIdent &&
  6840. (tright == tokNumInt || tright == tokNumUint))
  6841. {
  6842. GenAddrData(elementSz, IdentTable + stack[sp - 3][1], (ttop == '+') ? stack[sp - 2][1] : -stack[sp - 2][1]);
  6843. }
  6844. else if (ttop == '+' &&
  6845. tright == tokIdent &&
  6846. (tleft == tokNumInt || tleft == tokNumUint))
  6847. {
  6848. GenAddrData(elementSz, IdentTable + stack[sp - 2][1], stack[sp - 3][1]);
  6849. }
  6850. else
  6851. errorNotConst();
  6852. }
  6853. else
  6854. errorNotConst();
  6855. // Defer storage of string literal data (if any) until the end.
  6856. // This will let us generate the contiguous array of pointers to
  6857. // string literals unperturbed by the string literal data
  6858. // (e.g. "char* colors[] = { "red", "green", "blue" };").
  6859. }
  6860. else
  6861. //error("ParseDecl(): cannot initialize a global variable with a non-constant expression\n");
  6862. errorNotConst();
  6863. IdentTableLen = undoIdents; // remove all temporary identifier names from e.g. "sizeof" or "str"
  6864. SyntaxStackCnt = oldssp; // undo any temporary declarations from e.g. "sizeof" or "str" in the expression
  6865. return tok;
  6866. }
  6867. STATIC
  6868. int InitArray(int synPtr, int tok)
  6869. {
  6870. int elementTypePtr = synPtr + 3;
  6871. int elementType = SyntaxStack0[elementTypePtr];
  6872. unsigned elementSz = GetDeclSize(elementTypePtr, 0);
  6873. int braces = 0;
  6874. unsigned elementCnt = 0;
  6875. unsigned elementsRequired = SyntaxStack1[synPtr + 1];
  6876. int arrOfChar = (elementType == tokChar) | (elementType == tokUChar) | (elementType == tokSChar);
  6877. #ifndef NO_WCHAR
  6878. int arrOfWideChar = (elementType == WideCharType1) | (elementType == WideCharType2);
  6879. #endif
  6880. if (tok == '{')
  6881. {
  6882. braces = 1;
  6883. tok = GetToken();
  6884. }
  6885. if ((arrOfChar & (tok == tokLitStr))
  6886. #ifndef NO_WCHAR
  6887. | (arrOfWideChar & (tok == tokLitStrWide))
  6888. #endif
  6889. )
  6890. {
  6891. int ltok = tok;
  6892. unsigned sz = 0;
  6893. // this is 'someArray[someCountIfAny] = "some string"' or
  6894. // 'someArray[someCountIfAny] = { "some string" }'
  6895. do
  6896. {
  6897. #ifndef NO_WCHAR
  6898. GetString('"', arrOfWideChar, 'd');
  6899. #else
  6900. GetString('"', 0, 'd');
  6901. #endif
  6902. if (sz + TokenStringSize < sz ||
  6903. sz + TokenStringSize >= truncUint(-1))
  6904. errorStrLen();
  6905. sz += TokenStringSize;
  6906. elementCnt += TokenStringLen;
  6907. tok = GetToken();
  6908. } while (tok == ltok); // concatenate adjacent string literals
  6909. #ifndef NO_WCHAR
  6910. if ((ltok ^ (tokLitStr ^ tokLitStrWide)) == tok)
  6911. errorWideNonWide();
  6912. #endif
  6913. if (elementsRequired && elementCnt > elementsRequired)
  6914. errorStrLen();
  6915. if (elementCnt < elementsRequired)
  6916. #ifndef NO_WCHAR
  6917. GenZeroData((elementsRequired - elementCnt) * elementSz, 0);
  6918. #else
  6919. GenZeroData(elementsRequired - elementCnt, 0);
  6920. #endif
  6921. if (!elementsRequired)
  6922. GenZeroData(elementSz, 0), elementCnt++;
  6923. if (braces)
  6924. {
  6925. if (tok != '}')
  6926. errorUnexpectedToken(tok);
  6927. tok = GetToken();
  6928. }
  6929. }
  6930. else
  6931. {
  6932. while (tok != '}')
  6933. {
  6934. if (elementType == '[')
  6935. {
  6936. tok = InitArray(elementTypePtr, tok);
  6937. }
  6938. else if (elementType == tokStructPtr)
  6939. {
  6940. tok = InitStruct(elementTypePtr, tok);
  6941. }
  6942. else
  6943. {
  6944. tok = InitScalar(elementTypePtr, tok);
  6945. }
  6946. // Last element?
  6947. if (++elementCnt >= elementsRequired && elementsRequired)
  6948. {
  6949. if (braces & (tok == ','))
  6950. tok = GetToken();
  6951. break;
  6952. }
  6953. if (tok == ',')
  6954. tok = GetToken();
  6955. else if (tok != '}')
  6956. errorUnexpectedToken(tok);
  6957. }
  6958. if (braces)
  6959. {
  6960. if ((!elementCnt) | (tok != '}'))
  6961. errorUnexpectedToken(tok);
  6962. tok = GetToken();
  6963. }
  6964. if (elementCnt < elementsRequired)
  6965. GenZeroData((elementsRequired - elementCnt) * elementSz, 0);
  6966. }
  6967. // Store the element count if it's an incomplete array
  6968. if (!elementsRequired)
  6969. SyntaxStack1[synPtr + 1] = elementCnt;
  6970. return tok;
  6971. }
  6972. STATIC
  6973. int InitStruct(int synPtr, int tok)
  6974. {
  6975. int isUnion;
  6976. unsigned size, ofs = 0;
  6977. int braces = 0;
  6978. int c = 1;
  6979. synPtr = SyntaxStack1[synPtr];
  6980. isUnion = SyntaxStack0[synPtr++] == tokUnion;
  6981. size = SyntaxStack1[++synPtr];
  6982. synPtr += 3; // step inside the {} body of the struct/union
  6983. if (tok == '{')
  6984. {
  6985. braces = 1;
  6986. tok = GetToken();
  6987. }
  6988. // Find the first member
  6989. while (c)
  6990. {
  6991. int t = SyntaxStack0[synPtr];
  6992. c += (t == '(') - (t == ')') + (t == '{') - (t == '}');
  6993. if (c == 1 && t == tokMemberIdent)
  6994. break;
  6995. synPtr++;
  6996. }
  6997. while (tok != '}')
  6998. {
  6999. int c = 1;
  7000. int elementTypePtr, elementType;
  7001. unsigned elementOfs, elementSz;
  7002. elementOfs = SyntaxStack1[++synPtr];
  7003. elementTypePtr = ++synPtr;
  7004. elementType = SyntaxStack0[elementTypePtr];
  7005. elementSz = GetDeclSize(elementTypePtr, 0);
  7006. // Alignment
  7007. if (ofs < elementOfs)
  7008. GenZeroData(elementOfs - ofs, 0);
  7009. if (elementType == '[')
  7010. {
  7011. tok = InitArray(elementTypePtr, tok);
  7012. }
  7013. else if (elementType == tokStructPtr)
  7014. {
  7015. tok = InitStruct(elementTypePtr, tok);
  7016. }
  7017. else
  7018. {
  7019. tok = InitScalar(elementTypePtr, tok);
  7020. }
  7021. ofs = elementOfs + elementSz;
  7022. // Find the next member or the closing brace
  7023. while (c)
  7024. {
  7025. int t = SyntaxStack0[synPtr];
  7026. c += (t == '(') - (t == ')') + (t == '{') - (t == '}');
  7027. if (c == 1 && t == tokMemberIdent)
  7028. break;
  7029. synPtr++;
  7030. }
  7031. // Last member?
  7032. // Only one member (first) is initialized in unions explicitly
  7033. if ((!c) | isUnion)
  7034. {
  7035. if (braces & (tok == ','))
  7036. tok = GetToken();
  7037. break;
  7038. }
  7039. if (tok == ',')
  7040. tok = GetToken();
  7041. else if (tok != '}')
  7042. errorUnexpectedToken(tok);
  7043. }
  7044. if (braces)
  7045. {
  7046. if ((!ofs) | (tok != '}'))
  7047. errorUnexpectedToken(tok);
  7048. tok = GetToken();
  7049. }
  7050. // Implicit initialization of the rest and trailing padding
  7051. if (ofs < size)
  7052. GenZeroData(size - ofs, 0);
  7053. return tok;
  7054. }
  7055. STATIC
  7056. int compatCheck2(int lastSyntaxPtr, int i)
  7057. {
  7058. int res = 0;
  7059. int c = 0;
  7060. int t;
  7061. for (;;)
  7062. {
  7063. t = SyntaxStack0[lastSyntaxPtr];
  7064. if (t != SyntaxStack0[i])
  7065. {
  7066. if (SyntaxStack0[i] == ')' && SyntaxStack0[i - 1] == '(')
  7067. {
  7068. // Complete a previously incomplete parameter specification
  7069. int c1 = 1;
  7070. // Skip over the function params
  7071. do
  7072. {
  7073. t = SyntaxStack0[lastSyntaxPtr++];
  7074. c1 += (t == '(') - (t == ')');
  7075. } while (c1);
  7076. lastSyntaxPtr--;
  7077. }
  7078. else if (t == ')' &&
  7079. SyntaxStack0[i - 1] == '(' && SyntaxStack0[i] == tokIdent &&
  7080. SyntaxStack0[i + 1] == tokVoid && SyntaxStack0[i + 2] == ')')
  7081. {
  7082. // As an exception allow foo(void) to be redeclared as foo()
  7083. // since this happens very often in code.
  7084. // This weakens our redeclaration checks, however. Warn about it.
  7085. i += 2;
  7086. warning("Redeclaration from no parameters to unspecified parameters.\n");
  7087. }
  7088. else
  7089. goto lend;
  7090. }
  7091. if (t != tokIdent &&
  7092. SyntaxStack1[lastSyntaxPtr] != SyntaxStack1[i])
  7093. {
  7094. if (SyntaxStack0[lastSyntaxPtr - 1] == '[')
  7095. {
  7096. // Complete an incomplete array dimension or check for dimension mismatch
  7097. if (SyntaxStack1[lastSyntaxPtr] == 0)
  7098. SyntaxStack1[lastSyntaxPtr] = SyntaxStack1[i];
  7099. else if (SyntaxStack1[i])
  7100. goto lend;
  7101. }
  7102. else
  7103. goto lend;
  7104. }
  7105. c += (t == '(') - (t == ')') + (t == '[') - (t == ']');
  7106. if (!c)
  7107. {
  7108. switch (t)
  7109. {
  7110. case tokVoid:
  7111. case tokChar: case tokSChar: case tokUChar:
  7112. #ifdef CAN_COMPILE_32BIT
  7113. case tokShort: case tokUShort:
  7114. #endif
  7115. case tokInt: case tokUnsigned:
  7116. #ifndef NO_FP
  7117. case tokFloat:
  7118. #endif
  7119. case tokStructPtr:
  7120. goto lok;
  7121. }
  7122. }
  7123. lastSyntaxPtr++;
  7124. i++;
  7125. }
  7126. lok:
  7127. res = 1;
  7128. lend:
  7129. return res;
  7130. }
  7131. STATIC
  7132. void CheckRedecl(int lastSyntaxPtr)
  7133. {
  7134. int tid, id, external = 0;
  7135. int i;
  7136. int curScopeOnly;
  7137. int level = ParseLevel;
  7138. tid = SyntaxStack0[lastSyntaxPtr];
  7139. id = SyntaxStack1[lastSyntaxPtr];
  7140. switch (tid)
  7141. {
  7142. case tokIdent:
  7143. switch (SyntaxStack0[lastSyntaxPtr + 1])
  7144. {
  7145. #ifndef NO_TYPEDEF_ENUM
  7146. case tokNumInt:
  7147. tid = tokEnumPtr;
  7148. break;
  7149. #endif
  7150. default:
  7151. external = 1;
  7152. // fallthrough
  7153. case tokLocalOfs: // block-scope auto
  7154. case tokIdent: // block-scope static
  7155. ;
  7156. }
  7157. // fallthrough
  7158. case tokTypedef:
  7159. break;
  7160. case tokMemberIdent:
  7161. {
  7162. int c = 1;
  7163. i = lastSyntaxPtr - 1;
  7164. do
  7165. {
  7166. int t = SyntaxStack0[i];
  7167. c -= (t == '(') - (t == ')') + (t == '{') - (t == '}');
  7168. if (c == 1 &&
  7169. t == tokMemberIdent && SyntaxStack1[i] == id &&
  7170. SyntaxStack0[i + 1] == tokLocalOfs)
  7171. errorRedecl(IdentTable + id);
  7172. i--;
  7173. } while (c);
  7174. }
  7175. return;
  7176. default:
  7177. errorInternal(23);
  7178. }
  7179. // limit search to current scope for typedef and enum,
  7180. // ditto for non-external declarations
  7181. curScopeOnly = tid != tokIdent || !external;
  7182. for (i = lastSyntaxPtr - 1; i >= 0; i--)
  7183. {
  7184. int t = SyntaxStack0[i];
  7185. switch (t)
  7186. {
  7187. case ')':
  7188. {
  7189. // Skip over the function params
  7190. int c = -1;
  7191. while (c)
  7192. {
  7193. t = SyntaxStack0[--i];
  7194. c += (t == '(') - (t == ')');
  7195. }
  7196. }
  7197. break;
  7198. case '#':
  7199. // the scope has changed to the outer scope
  7200. if (curScopeOnly)
  7201. return;
  7202. level--;
  7203. break;
  7204. case tokTypedef:
  7205. case tokIdent:
  7206. if (SyntaxStack1[i] == id)
  7207. {
  7208. #ifndef NO_TYPEDEF_ENUM
  7209. if (t == tokIdent && SyntaxStack0[i + 1] == tokNumInt)
  7210. t = tokEnumPtr;
  7211. #endif
  7212. if (level == ParseLevel)
  7213. {
  7214. #ifndef NO_TYPEDEF_ENUM
  7215. // within the current scope typedefs and enum constants
  7216. // can't be redefined nor can clash with anything else
  7217. if (tid != tokIdent || t != tokIdent)
  7218. errorRedecl(IdentTable + id);
  7219. #endif
  7220. // block scope:
  7221. // can differentiate between auto(tokLocalOfs), static(tokIdent),
  7222. // extern/proto(nothing) in SyntaxStack*[], hence dup checks and
  7223. // type match checks needed here
  7224. // file scope:
  7225. // can't differentiate between static(nothing), extern(nothing),
  7226. // neither(nothing) in SyntaxStack*[], but duplicate definitions
  7227. // are taken care of (in CG), hence only type match checks needed
  7228. // here
  7229. if (level) // block scope: check for bad dups
  7230. {
  7231. switch (SyntaxStack0[i + 1])
  7232. {
  7233. case tokLocalOfs: // block-scope auto
  7234. case tokIdent: // block-scope static
  7235. // auto and static can't be redefined in block scope
  7236. errorRedecl(IdentTable + id);
  7237. default:
  7238. // extern can't be redefined as non-extern in block scope
  7239. if (!external)
  7240. errorRedecl(IdentTable + id);
  7241. }
  7242. // extern/proto type match check follows
  7243. }
  7244. if (compatCheck2(lastSyntaxPtr, i))
  7245. return;
  7246. errorRedecl(IdentTable + id);
  7247. }
  7248. else // elseof if (level == ParseLevel)
  7249. {
  7250. // The new decl is extern/proto.
  7251. // Ignore typedef and enum
  7252. if (t == tokIdent)
  7253. {
  7254. switch (SyntaxStack0[i + 1])
  7255. {
  7256. case tokLocalOfs: // block-scope auto
  7257. case tokIdent: // block-scope static
  7258. // Ignore auto and static
  7259. break;
  7260. default:
  7261. // extern/proto
  7262. if (compatCheck2(lastSyntaxPtr, i))
  7263. return;
  7264. errorRedecl(IdentTable + id);
  7265. }
  7266. }
  7267. }
  7268. } // endof if (SyntaxStack1[i] == id)
  7269. break;
  7270. } // endof switch (t)
  7271. } // endof for (i = lastSyntaxPtr - 1; i >= 0; i--)
  7272. }
  7273. // DONE: support extern
  7274. // DONE: support static
  7275. // DONE: support basic initialization
  7276. // DONE: support simple non-array initializations with string literals
  7277. // DONE: support basic 1-d array initialization
  7278. // DONE: global/static data allocations
  7279. STATIC
  7280. int ParseDecl(int tok, unsigned structInfo[4], int cast, int label)
  7281. {
  7282. int base[2];
  7283. int lastSyntaxPtr;
  7284. int external = tok == tokExtern;
  7285. int Static = tok == tokStatic;
  7286. #ifndef NO_TYPEDEF_ENUM
  7287. int typeDef = tok == tokTypedef;
  7288. #else
  7289. (void)label;
  7290. #endif
  7291. if (external |
  7292. #ifndef NO_TYPEDEF_ENUM
  7293. typeDef |
  7294. #endif
  7295. Static)
  7296. {
  7297. tok = GetToken();
  7298. if (!TokenStartsDeclaration(tok, 1))
  7299. //error("ParseDecl(): unexpected token %s\n", GetTokenName(tok));
  7300. // Implicit int (as in "extern x; static y;") isn't supported
  7301. errorUnexpectedToken(tok);
  7302. }
  7303. tok = ParseBase(tok, base);
  7304. #ifndef NO_TYPEDEF_ENUM
  7305. if (label && tok == ':' && base[0] == tokTypedef &&
  7306. !(external | Static | typeDef) && ParseLevel)
  7307. {
  7308. // This is a label.
  7309. return tokGotoLabel;
  7310. }
  7311. #endif
  7312. for (;;)
  7313. {
  7314. lastSyntaxPtr = SyntaxStackCnt;
  7315. /* derived type */
  7316. tok = ParseDerived(tok);
  7317. /* base type */
  7318. PushBase(base);
  7319. if ((tok && strchr(",;{=", tok)) || (tok == ')' && ExprLevel))
  7320. {
  7321. int isLocal = 0, isGlobal = 0, isFxn, isStruct, isArray, isIncompleteArr;
  7322. unsigned alignment = 0;
  7323. int staticLabel = 0;
  7324. // Disallow void variables
  7325. if (SyntaxStack0[SyntaxStackCnt - 1] == tokVoid)
  7326. {
  7327. if (SyntaxStack0[SyntaxStackCnt - 2] == tokIdent &&
  7328. !(cast
  7329. #ifndef NO_TYPEDEF_ENUM
  7330. | typeDef
  7331. #endif
  7332. ))
  7333. //error("ParseDecl(): Cannot declare a variable ('%s') of type 'void'\n", IdentTable + SyntaxStack1[lastSyntaxPtr]);
  7334. errorUnexpectedVoid();
  7335. }
  7336. isFxn = SyntaxStack0[lastSyntaxPtr + 1] == '(';
  7337. #ifdef NO_STRUCT_BY_VAL
  7338. if (isFxn &&
  7339. SyntaxStack0[SyntaxStackCnt - 1] == tokStructPtr &&
  7340. SyntaxStack0[SyntaxStackCnt - 2] == ')')
  7341. // structure returning isn't supported currently
  7342. errorDecl();
  7343. #endif
  7344. isArray = SyntaxStack0[lastSyntaxPtr + 1] == '[';
  7345. isIncompleteArr = isArray && SyntaxStack1[lastSyntaxPtr + 2] == 0;
  7346. isStruct = SyntaxStack0[lastSyntaxPtr + 1] == tokStructPtr;
  7347. if (!(ExprLevel || structInfo) &&
  7348. !(external |
  7349. #ifndef NO_TYPEDEF_ENUM
  7350. typeDef |
  7351. #endif
  7352. Static) &&
  7353. !strcmp(IdentTable + SyntaxStack1[lastSyntaxPtr], "<something>") &&
  7354. tok == ';')
  7355. {
  7356. if (isStruct)
  7357. {
  7358. // This is either an incomplete tagged structure/union declaration, e.g. "struct sometag;",
  7359. // or a tagged complete structure/union declaration, e.g. "struct sometag { ... };", without an instance variable,
  7360. // or an untagged complete structure/union declaration, e.g. "struct { ... };", without an instance variable
  7361. int declPtr, curScope;
  7362. int j = SyntaxStack1[lastSyntaxPtr + 1];
  7363. if (j + 2 < SyntaxStackCnt &&
  7364. IdentTable[SyntaxStack1[j + 1]] == '<' && // without tag
  7365. SyntaxStack0[j + 2] == tokSizeof) // but with the {} "body"
  7366. errorDecl();
  7367. // If a structure/union with this tag has been declared in an outer scope,
  7368. // this new declaration should override it
  7369. declPtr = FindTaggedDecl(IdentTable + SyntaxStack1[j + 1], lastSyntaxPtr - 1, &curScope);
  7370. if (declPtr >= 0 && !curScope)
  7371. {
  7372. // If that's the case, unbind this declaration from the old declaration
  7373. // and make it a new incomplete declaration
  7374. PushSyntax(SyntaxStack0[j]); // tokStruct or tokUnion
  7375. PushSyntax2(tokTag, SyntaxStack1[j + 1]);
  7376. SyntaxStack1[lastSyntaxPtr + 1] = SyntaxStackCnt - 2;
  7377. }
  7378. return GetToken();
  7379. }
  7380. #ifndef NO_TYPEDEF_ENUM
  7381. else if (SyntaxStack0[lastSyntaxPtr + 1] == tokEnumPtr)
  7382. {
  7383. return GetToken();
  7384. }
  7385. #endif
  7386. }
  7387. #ifndef NO_TYPEDEF_ENUM
  7388. // Convert enums into ints
  7389. if (SyntaxStack0[SyntaxStackCnt - 1] == tokEnumPtr)
  7390. {
  7391. SyntaxStack0[SyntaxStackCnt - 1] = tokInt;
  7392. SyntaxStack1[SyntaxStackCnt - 1] = 0;
  7393. }
  7394. #endif
  7395. // Structure/union members can't be initialized nor be functions nor
  7396. // be incompletely typed arrays inside structure/union declarations
  7397. if (structInfo && ((tok == '=') | isFxn | (tok == '{') | isIncompleteArr))
  7398. errorDecl();
  7399. #ifndef NO_TYPEDEF_ENUM
  7400. if (typeDef & ((tok == '=') | (tok == '{')))
  7401. errorDecl();
  7402. #endif
  7403. // Error conditions in declarations(/definitions/initializations):
  7404. // Legend:
  7405. // + error
  7406. // - no error
  7407. //
  7408. // file scope fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  7409. // - - - - - + +
  7410. // file scope fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  7411. // + - - + - +
  7412. // file scope extern fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  7413. // - - - - - - -
  7414. // file scope extern fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  7415. // + + + + + +
  7416. // file scope static fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  7417. // - - - - - + +
  7418. // file scope static fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  7419. // + - - + - +
  7420. // fxn scope fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  7421. // - + - - - + +
  7422. // fxn scope fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  7423. // + - + + + +
  7424. // fxn scope extern fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  7425. // - + - - - - -
  7426. // fxn scope extern fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  7427. // + + + + + +
  7428. // fxn scope static fxn fxn {} var arr[] arr[]...[] arr[incomplete] arr[incomplete]...[]
  7429. // + + + + + + +
  7430. // fxn scope static fxn= var= arr[]= arr[]...[]= arr[incomplete]= arr[incomplete]...[]=
  7431. // + + + + + +
  7432. if (isFxn & (tok == '='))
  7433. //error("ParseDecl(): cannot initialize a function\n");
  7434. errorInit();
  7435. if ((isFxn & (tok == '{')) && ParseLevel)
  7436. //error("ParseDecl(): cannot define a nested function\n");
  7437. errorDecl();
  7438. if ((isFxn & Static) && ParseLevel)
  7439. //error("ParseDecl(): cannot declare a static function in this scope\n");
  7440. errorDecl();
  7441. if (external & (tok == '='))
  7442. //error("ParseDecl(): cannot initialize an external variable\n");
  7443. errorInit();
  7444. if (isIncompleteArr & !(external |
  7445. #ifndef NO_TYPEDEF_ENUM
  7446. typeDef |
  7447. #endif
  7448. (tok == '=')))
  7449. //error("ParseDecl(): cannot define an array of incomplete type\n");
  7450. errorDecl();
  7451. // TBD!!! de-uglify
  7452. if (!strcmp(IdentTable + SyntaxStack1[lastSyntaxPtr], "<something>"))
  7453. {
  7454. // Disallow nameless variables, prototypes, structure/union members and typedefs.
  7455. if (structInfo ||
  7456. #ifndef NO_TYPEDEF_ENUM
  7457. typeDef ||
  7458. #endif
  7459. !ExprLevel)
  7460. error("Identifier expected in declaration\n");
  7461. }
  7462. else
  7463. {
  7464. // Disallow named variables and prototypes in sizeof(typedecl) and (typedecl).
  7465. if (ExprLevel && !structInfo)
  7466. error("Identifier unexpected in declaration\n");
  7467. }
  7468. if (!isFxn
  7469. #ifndef NO_TYPEDEF_ENUM
  7470. && !typeDef
  7471. #endif
  7472. )
  7473. {
  7474. // This is a variable or a variable (member) in a struct/union declaration
  7475. int sz = GetDeclSize(lastSyntaxPtr, 0);
  7476. if (!((sz | isIncompleteArr) || ExprLevel)) // incomplete type
  7477. errorDecl(); // TBD!!! different error when struct/union tag is not found
  7478. if (isArray && !GetDeclSize(lastSyntaxPtr + 4, 0))
  7479. // incomplete type of array element (e.g. struct/union)
  7480. errorDecl();
  7481. alignment = GetDeclAlignment(lastSyntaxPtr);
  7482. if (structInfo)
  7483. {
  7484. // It's a variable (member) in a struct/union declaration
  7485. unsigned tmp;
  7486. unsigned newAlignment = alignment;
  7487. #ifndef NO_PPACK
  7488. if (alignment > (unsigned)PragmaPackValue)
  7489. newAlignment = PragmaPackValue;
  7490. #endif
  7491. // Update structure/union alignment
  7492. if (structInfo[1] < newAlignment)
  7493. structInfo[1] = newAlignment;
  7494. // Align structure member
  7495. tmp = structInfo[2];
  7496. structInfo[2] = (structInfo[2] + newAlignment - 1) & ~(newAlignment - 1);
  7497. if (structInfo[2] < tmp || structInfo[2] != truncUint(structInfo[2]))
  7498. errorVarSize();
  7499. // Change tokIdent to tokMemberIdent and insert a local var offset token
  7500. SyntaxStack0[lastSyntaxPtr] = tokMemberIdent;
  7501. InsertSyntax2(lastSyntaxPtr + 1, tokLocalOfs, (int)structInfo[2]);
  7502. // Advance member offset for structures, keep it zero for unions
  7503. if (structInfo[0] == tokStruct)
  7504. {
  7505. tmp = structInfo[2];
  7506. structInfo[2] += sz;
  7507. if (structInfo[2] < tmp || structInfo[2] != truncUint(structInfo[2]))
  7508. errorVarSize();
  7509. }
  7510. // Update max member size for unions
  7511. else if (structInfo[3] < (unsigned)sz)
  7512. {
  7513. structInfo[3] = sz;
  7514. }
  7515. }
  7516. else if (ParseLevel && !((external | Static) || ExprLevel))
  7517. {
  7518. // It's a local variable
  7519. isLocal = 1;
  7520. // Defer size calculation until initialization
  7521. // Insert a local var offset token, the offset is to be updated
  7522. InsertSyntax2(lastSyntaxPtr + 1, tokLocalOfs, 0);
  7523. }
  7524. else if (!ExprLevel)
  7525. {
  7526. // It's a global variable (external, static or neither)
  7527. isGlobal = 1;
  7528. if (Static && ParseLevel)
  7529. {
  7530. // It's a static variable in function scope, "rename" it by providing
  7531. // an alternative unique numeric identifier right next to it and use it
  7532. staticLabel = LabelCnt++;
  7533. InsertSyntax2(lastSyntaxPtr + 1, tokIdent, AddNumericIdent(staticLabel));
  7534. }
  7535. }
  7536. }
  7537. // If it's a type declaration in a sizeof(typedecl) expression or
  7538. // in an expression with a cast, e.g. (typedecl)expr, we're done
  7539. if (ExprLevel && !structInfo)
  7540. {
  7541. #ifndef NO_ANNOTATIONS
  7542. DumpDecl(lastSyntaxPtr, 0);
  7543. #endif
  7544. return tok;
  7545. }
  7546. #ifndef NO_TYPEDEF_ENUM
  7547. if (typeDef)
  7548. {
  7549. #ifndef NO_ANNOTATIONS
  7550. DumpDecl(lastSyntaxPtr, 0);
  7551. #endif
  7552. SyntaxStack0[lastSyntaxPtr] = 0; // hide tokIdent for now
  7553. SyntaxStack0[lastSyntaxPtr] = tokTypedef; // change tokIdent to tokTypedef
  7554. }
  7555. else
  7556. // fallthrough
  7557. #endif
  7558. if (isLocal | isGlobal)
  7559. {
  7560. int hasInit = tok == '=';
  7561. int needsGlobalInit = isGlobal & !external;
  7562. int sz = GetDeclSize(lastSyntaxPtr, 0);
  7563. int initLabel = 0;
  7564. int bss = (!hasInit) & UseBss;
  7565. #ifndef NO_ANNOTATIONS
  7566. if (isGlobal)
  7567. DumpDecl(lastSyntaxPtr, 0);
  7568. #endif
  7569. if (hasInit)
  7570. {
  7571. tok = GetToken();
  7572. }
  7573. if (isLocal & hasInit)
  7574. needsGlobalInit = isArray | (isStruct & (tok == '{'));
  7575. if (needsGlobalInit)
  7576. {
  7577. char** oldHeaderFooter = CurHeaderFooter;
  7578. if (oldHeaderFooter)
  7579. puts2(oldHeaderFooter[1]);
  7580. CurHeaderFooter = bss ? BssHeaderFooter : DataHeaderFooter;
  7581. puts2(CurHeaderFooter[0]);
  7582. // DONE: imperfect condition for alignment
  7583. if (alignment != 1)
  7584. GenWordAlignment(bss);
  7585. if (isGlobal)
  7586. {
  7587. if (Static && ParseLevel)
  7588. GenNumLabel(staticLabel);
  7589. else
  7590. GenLabel(IdentTable + SyntaxStack1[lastSyntaxPtr], Static);
  7591. }
  7592. else
  7593. {
  7594. // Generate numeric labels for global initializers of local vars
  7595. GenNumLabel(initLabel = LabelCnt++);
  7596. }
  7597. // Generate global initializers
  7598. if (hasInit)
  7599. {
  7600. #ifndef NO_ANNOTATIONS
  7601. if (isGlobal)
  7602. {
  7603. GenStartCommentLine(); printf2("=\n");
  7604. }
  7605. #endif
  7606. tok = InitVar(lastSyntaxPtr, tok);
  7607. // Update the size in case it's an incomplete array
  7608. sz = GetDeclSize(lastSyntaxPtr, 0);
  7609. }
  7610. else
  7611. {
  7612. GenZeroData(sz, bss);
  7613. }
  7614. puts2(CurHeaderFooter[1]);
  7615. if (oldHeaderFooter)
  7616. puts2(oldHeaderFooter[0]);
  7617. CurHeaderFooter = oldHeaderFooter;
  7618. }
  7619. if (isLocal)
  7620. {
  7621. // Now that the size of the local is certainly known,
  7622. // update its offset in the offset token
  7623. SyntaxStack1[lastSyntaxPtr + 1] = AllocLocal(sz);
  7624. #ifndef NO_ANNOTATIONS
  7625. DumpDecl(lastSyntaxPtr, 0);
  7626. #endif
  7627. }
  7628. // Copy global initializers into local vars
  7629. if (isLocal & needsGlobalInit)
  7630. {
  7631. #ifndef NO_ANNOTATIONS
  7632. GenStartCommentLine(); printf2("=\n");
  7633. #endif
  7634. if (!StructCpyLabel)
  7635. StructCpyLabel = LabelCnt++;
  7636. sp = 0;
  7637. push2('(', SizeOfWord * 3);
  7638. push2(tokLocalOfs, SyntaxStack1[lastSyntaxPtr + 1]);
  7639. push(',');
  7640. push2(tokIdent, AddNumericIdent(initLabel));
  7641. push(',');
  7642. push2(tokNumUint, sz);
  7643. push(',');
  7644. push2(tokIdent, AddNumericIdent(StructCpyLabel));
  7645. push2(')', SizeOfWord * 3);
  7646. GenExpr();
  7647. }
  7648. // Initialize local vars with expressions
  7649. else if (hasInit & !needsGlobalInit)
  7650. {
  7651. int gotUnary, synPtr, constExpr, exprVal;
  7652. int brace = 0;
  7653. // Initializers for scalars can be optionally enclosed in braces
  7654. if ((!isStruct) & (tok == '{'))
  7655. {
  7656. brace = 1;
  7657. tok = GetToken();
  7658. }
  7659. // ParseExpr() will transform the initializer expression into an assignment expression here
  7660. tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, '=', SyntaxStack1[lastSyntaxPtr]);
  7661. if (!gotUnary)
  7662. errorUnexpectedToken(tok);
  7663. if (brace)
  7664. {
  7665. if (tok != '}')
  7666. errorUnexpectedToken(tok);
  7667. tok = GetToken();
  7668. }
  7669. if (!isStruct)
  7670. {
  7671. // This is a special case for initialization of integers smaller than int.
  7672. // Since a local integer variable always takes as much space as a whole int,
  7673. // we can optimize code generation a bit by storing the initializer as an int.
  7674. // This is an old accidental optimization and I preserve it for now.
  7675. // Note, this implies a little-endian CPU.
  7676. stack[sp - 1][1] = SizeOfWord;
  7677. }
  7678. // Storage of string literal data from the initializing expression
  7679. // occurs here.
  7680. GenExpr();
  7681. }
  7682. }
  7683. else if (tok == '{')
  7684. {
  7685. // It's a function body. Let's add function parameters as
  7686. // local variables to the symbol table and parse the body.
  7687. int undoSymbolsPtr = SyntaxStackCnt;
  7688. int undoIdents = IdentTableLen;
  7689. int i;
  7690. int endLabel = 0;
  7691. #ifndef NO_ANNOTATIONS
  7692. DumpDecl(lastSyntaxPtr, 0);
  7693. #endif
  7694. CurFxnName = IdentTable + SyntaxStack1[lastSyntaxPtr];
  7695. IsMain = !strcmp(CurFxnName, "main");
  7696. gotoLabCnt = 0;
  7697. if (verbose)
  7698. printf("%s()\n", CurFxnName);
  7699. ParseLevel++;
  7700. GetFxnInfo(lastSyntaxPtr, &CurFxnParamCntMin, &CurFxnParamCntMax, &CurFxnReturnExprTypeSynPtr, NULL); // get return type
  7701. #ifndef NO_STRUCT_BY_VAL
  7702. // Make sure the return structure type is complete
  7703. if (CurFxnReturnExprTypeSynPtr >= 0 &&
  7704. SyntaxStack0[CurFxnReturnExprTypeSynPtr] == tokStructPtr &&
  7705. !GetDeclSize(CurFxnReturnExprTypeSynPtr, 0))
  7706. errorDecl();
  7707. #endif
  7708. CurHeaderFooter = CodeHeaderFooter;
  7709. puts2(CurHeaderFooter[0]);
  7710. GenLabel(CurFxnName, Static);
  7711. #ifndef MIPS
  7712. #ifdef CAN_COMPILE_32BIT
  7713. if (SyntaxStack1[lastSyntaxPtr + 1] & 1)
  7714. GenIsrProlog();
  7715. else // fallthrough
  7716. #endif
  7717. #endif
  7718. GenFxnProlog();
  7719. CurFxnEpilogLabel = LabelCnt++;
  7720. // A new scope begins before the function parameters
  7721. PushSyntax('#');
  7722. AddFxnParamSymbols(lastSyntaxPtr);
  7723. #ifndef NO_FUNC_
  7724. {
  7725. CurFxnNameLabel = LabelCnt++;
  7726. SyntaxStack1[SymFuncPtr] = AddNumericIdent(CurFxnNameLabel);
  7727. SyntaxStack1[SymFuncPtr + 2] = strlen(CurFxnName) + 1;
  7728. }
  7729. #endif
  7730. // The block doesn't begin yet another new scope.
  7731. // This is to catch redeclarations of the function parameters.
  7732. tok = ParseBlock(BrkCntTargetFxn, 0);
  7733. ParseLevel--;
  7734. if (tok != '}')
  7735. //error("ParseDecl(): '}' expected\n");
  7736. errorUnexpectedToken(tok);
  7737. for (i = 0; i < gotoLabCnt; i++)
  7738. if (gotoLabStat[i] == 2)
  7739. error("Undeclared label '%s'\n", IdentTable + gotoLabels[i][0]);
  7740. // DONE: if execution of main() reaches here, before the epilog (i.e. without using return),
  7741. // main() should return 0.
  7742. if (IsMain)
  7743. {
  7744. sp = 0;
  7745. push(tokNumInt);
  7746. push(tokReturn); // value produced by generated code is used
  7747. GenExpr();
  7748. }
  7749. GenNumLabel(CurFxnEpilogLabel);
  7750. #ifndef MIPS
  7751. #ifdef CAN_COMPILE_32BIT
  7752. if (SyntaxStack1[lastSyntaxPtr + 1] & 1)
  7753. GenIsrEpilog();
  7754. else // fallthrough
  7755. #endif
  7756. #endif
  7757. GenFxnEpilog();
  7758. if (GenFxnSizeNeeded())
  7759. GenNumLabel(endLabel = LabelCnt++);
  7760. puts2(CurHeaderFooter[1]);
  7761. CurHeaderFooter = NULL;
  7762. if (GenFxnSizeNeeded())
  7763. GenRecordFxnSize(CurFxnName, endLabel);
  7764. #ifndef NO_FUNC_
  7765. if (CurFxnNameLabel < 0)
  7766. {
  7767. puts2(RoDataHeaderFooter[0]);
  7768. GenNumLabel(-CurFxnNameLabel);
  7769. GenStartAsciiString();
  7770. printf2("\"%s\"\n", CurFxnName);
  7771. GenZeroData(1, 0);
  7772. puts2(RoDataHeaderFooter[1]);
  7773. CurFxnNameLabel = 0;
  7774. }
  7775. #endif
  7776. CurFxnName = NULL;
  7777. IdentTableLen = undoIdents; // remove all identifier names
  7778. SyntaxStackCnt = undoSymbolsPtr; // remove all params and locals
  7779. SyntaxStack1[SymFuncPtr] = DummyIdent;
  7780. }
  7781. #ifndef NO_ANNOTATIONS
  7782. else if (isFxn)
  7783. {
  7784. // function prototype
  7785. DumpDecl(lastSyntaxPtr, 0);
  7786. }
  7787. #endif
  7788. CheckRedecl(lastSyntaxPtr);
  7789. if ((tok == ';') | (tok == '}'))
  7790. break;
  7791. tok = GetToken();
  7792. continue;
  7793. }
  7794. //error("ParseDecl(): unexpected token %s\n", GetTokenName(tok));
  7795. errorUnexpectedToken(tok);
  7796. }
  7797. tok = GetToken();
  7798. return tok;
  7799. }
  7800. STATIC
  7801. void ParseFxnParams(int tok)
  7802. {
  7803. int base[2];
  7804. int lastSyntaxPtr;
  7805. int cnt = 0;
  7806. int ellCnt = 0;
  7807. for (;;)
  7808. {
  7809. lastSyntaxPtr = SyntaxStackCnt;
  7810. if (tok == ')') /* unspecified params */
  7811. break;
  7812. if (!TokenStartsDeclaration(tok, 1))
  7813. {
  7814. if (tok == tokEllipsis)
  7815. {
  7816. // "..." cannot be the first parameter and
  7817. // it can be only one
  7818. if (!cnt || ellCnt)
  7819. //error("ParseFxnParams(): '...' unexpected here\n");
  7820. errorUnexpectedToken(tok);
  7821. ellCnt++;
  7822. }
  7823. else
  7824. //error("ParseFxnParams(): Unexpected token %s\n", GetTokenName(tok));
  7825. errorUnexpectedToken(tok);
  7826. base[0] = tok; // "..."
  7827. base[1] = 0;
  7828. PushSyntax2(tokIdent, AddIdent("<something>"));
  7829. tok = GetToken();
  7830. }
  7831. else
  7832. {
  7833. if (ellCnt)
  7834. //error("ParseFxnParams(): '...' must be the last in the parameter list\n");
  7835. errorUnexpectedToken(tok);
  7836. /* base type */
  7837. tok = ParseBase(tok, base);
  7838. /* derived type */
  7839. tok = ParseDerived(tok);
  7840. }
  7841. /* base type */
  7842. PushBase(base);
  7843. #ifndef NO_TYPEDEF_ENUM
  7844. // Convert enums into ints
  7845. if (SyntaxStack0[SyntaxStackCnt - 1] == tokEnumPtr)
  7846. {
  7847. SyntaxStack0[SyntaxStackCnt - 1] = tokInt;
  7848. SyntaxStack1[SyntaxStackCnt - 1] = 0;
  7849. }
  7850. #endif
  7851. /* Decay arrays to pointers */
  7852. lastSyntaxPtr++; /* skip name */
  7853. if (SyntaxStack0[lastSyntaxPtr] == '[')
  7854. {
  7855. int t;
  7856. DeleteSyntax(lastSyntaxPtr, 1);
  7857. t = SyntaxStack0[lastSyntaxPtr];
  7858. if (t == tokNumInt || t == tokNumUint)
  7859. DeleteSyntax(lastSyntaxPtr, 1);
  7860. SyntaxStack0[lastSyntaxPtr] = '*';
  7861. }
  7862. /* "(Un)decay" functions to function pointers */
  7863. else if (SyntaxStack0[lastSyntaxPtr] == '(')
  7864. {
  7865. InsertSyntax(lastSyntaxPtr, '*');
  7866. }
  7867. lastSyntaxPtr--; /* "unskip" name */
  7868. cnt++;
  7869. if (tok == ')' || tok == ',')
  7870. {
  7871. int t = SyntaxStack0[SyntaxStackCnt - 2];
  7872. if (SyntaxStack0[SyntaxStackCnt - 1] == tokVoid)
  7873. {
  7874. // Disallow void variables. TBD!!! de-uglify
  7875. if (t == tokIdent &&
  7876. !(!strcmp(IdentTable + SyntaxStack1[SyntaxStackCnt - 2], "<something>") &&
  7877. cnt == 1 && tok == ')'))
  7878. //error("ParseFxnParams(): Cannot declare a variable ('%s') of type 'void'\n", IdentTable + SyntaxStack1[lastSyntaxPtr]);
  7879. errorUnexpectedVoid();
  7880. }
  7881. #ifdef NO_STRUCT_BY_VAL
  7882. if (SyntaxStack0[SyntaxStackCnt - 1] == tokStructPtr &&
  7883. t != '*' &&
  7884. t != ']')
  7885. // structure passing and returning isn't supported currently
  7886. errorDecl();
  7887. #endif
  7888. if (tok == ')')
  7889. break;
  7890. tok = GetToken();
  7891. continue;
  7892. }
  7893. //error("ParseFxnParams(): Unexpected token %s\n", GetTokenName(tok));
  7894. errorUnexpectedToken(tok);
  7895. }
  7896. }
  7897. STATIC
  7898. void AddFxnParamSymbols(int SyntaxPtr)
  7899. {
  7900. int i;
  7901. unsigned paramOfs = 2 * SizeOfWord; // ret addr, xbp
  7902. if (SyntaxPtr < 0 ||
  7903. SyntaxPtr > SyntaxStackCnt - 3 ||
  7904. SyntaxStack0[SyntaxPtr] != tokIdent ||
  7905. SyntaxStack0[SyntaxPtr + 1] != '(')
  7906. //error("Internal error: AddFxnParamSymbols(): Invalid input\n");
  7907. errorInternal(6);
  7908. CurFxnSyntaxPtr = SyntaxPtr;
  7909. CurFxnLocalOfs = 0;
  7910. CurFxnMinLocalOfs = 0;
  7911. #ifndef NO_STRUCT_BY_VAL
  7912. if (CurFxnReturnExprTypeSynPtr >= 0 &&
  7913. SyntaxStack0[CurFxnReturnExprTypeSynPtr] == tokStructPtr)
  7914. {
  7915. // The function returns a struct/union via an implicit param/arg (pointer to struct/union)
  7916. // before its first formal param/arg, add this implicit param/arg
  7917. #ifndef NO_ANNOTATIONS
  7918. int paramPtr = SyntaxStackCnt;
  7919. #endif
  7920. PushSyntax2(tokIdent, AddIdent("@")); // special implicit param/arg (pretval) pointing to structure receptacle
  7921. PushSyntax2(tokLocalOfs, paramOfs);
  7922. PushSyntax('*');
  7923. PushSyntax2(tokStructPtr, SyntaxStack1[CurFxnReturnExprTypeSynPtr]);
  7924. paramOfs += SizeOfWord;
  7925. #ifndef NO_ANNOTATIONS
  7926. DumpDecl(paramPtr, 0);
  7927. #endif
  7928. }
  7929. #endif
  7930. SyntaxPtr += 2; // skip "ident("
  7931. for (i = SyntaxPtr; i < SyntaxStackCnt; i++)
  7932. {
  7933. int tok = SyntaxStack0[i];
  7934. if (tok == tokIdent)
  7935. {
  7936. unsigned sz;
  7937. int paramPtr;
  7938. if (i + 1 >= SyntaxStackCnt)
  7939. //error("Internal error: AddFxnParamSymbols(): Invalid input\n");
  7940. errorInternal(7);
  7941. if (SyntaxStack0[i + 1] == tokVoid) // "ident(void)" = no params
  7942. break;
  7943. if (SyntaxStack0[i + 1] == tokEllipsis) // "ident(something,...)" = no more params
  7944. break;
  7945. // Make sure the parameter is not an incomplete structure
  7946. sz = GetDeclSize(i, 0);
  7947. if (sz == 0)
  7948. //error("Internal error: AddFxnParamSymbols(): GetDeclSize() = 0\n");
  7949. //errorInternal(8);
  7950. errorDecl();
  7951. // Let's calculate this parameter's relative on-stack location
  7952. paramPtr = SyntaxStackCnt;
  7953. PushSyntax2(SyntaxStack0[i], SyntaxStack1[i]);
  7954. PushSyntax2(tokLocalOfs, paramOfs);
  7955. if (sz + SizeOfWord - 1 < sz)
  7956. errorVarSize();
  7957. sz = (sz + SizeOfWord - 1) & ~(SizeOfWord - 1u);
  7958. if (paramOfs + sz < paramOfs)
  7959. errorVarSize();
  7960. paramOfs += sz;
  7961. if (paramOfs > (unsigned)GenMaxLocalsSize())
  7962. errorVarSize();
  7963. // Duplicate this parameter in the symbol table
  7964. i++;
  7965. while (i < SyntaxStackCnt)
  7966. {
  7967. tok = SyntaxStack0[i];
  7968. if (tok == tokIdent || tok == ')')
  7969. {
  7970. #ifndef NO_ANNOTATIONS
  7971. DumpDecl(paramPtr, 0);
  7972. #endif
  7973. if (IdentTable[SyntaxStack1[paramPtr]] == '<')
  7974. error("Parameter name expected\n");
  7975. CheckRedecl(paramPtr);
  7976. i--;
  7977. break;
  7978. }
  7979. else if (tok == '(')
  7980. {
  7981. int c = 1;
  7982. i++;
  7983. PushSyntax(tok);
  7984. while (c && i < SyntaxStackCnt)
  7985. {
  7986. tok = SyntaxStack0[i];
  7987. c += (tok == '(') - (tok == ')');
  7988. PushSyntax2(SyntaxStack0[i], SyntaxStack1[i]);
  7989. i++;
  7990. }
  7991. }
  7992. else
  7993. {
  7994. PushSyntax2(SyntaxStack0[i], SyntaxStack1[i]);
  7995. i++;
  7996. }
  7997. }
  7998. }
  7999. else if (tok == ')') // endof "ident(" ... ")"
  8000. break;
  8001. else
  8002. //error("Internal error: AddFxnParamSymbols(): Unexpected token %s\n", GetTokenName(tok));
  8003. errorInternal(9);
  8004. }
  8005. }
  8006. STATIC
  8007. int ParseStatement(int tok, int BrkCntTarget[2], int casesIdx)
  8008. {
  8009. /*
  8010. labeled statements:
  8011. + ident : statement
  8012. + case const-expr : statement
  8013. + default : statement
  8014. compound statement:
  8015. + { declaration(s)/statement(s)-opt }
  8016. expression statement:
  8017. + expression-opt ;
  8018. selection statements:
  8019. + if ( expression ) statement
  8020. + if ( expression ) statement else statement
  8021. + switch ( expression ) { statement(s)-opt }
  8022. iteration statements:
  8023. + while ( expression ) statement
  8024. + do statement while ( expression ) ;
  8025. + for ( expression-opt ; expression-opt ; expression-opt ) statement
  8026. jump statements:
  8027. + goto ident ;
  8028. + continue ;
  8029. + break ;
  8030. + return expression-opt ;
  8031. */
  8032. int gotUnary, synPtr, constExpr, exprVal;
  8033. int brkCntTarget[2];
  8034. int statementNeeded;
  8035. do
  8036. {
  8037. statementNeeded = 0;
  8038. if (tok == ';')
  8039. {
  8040. tok = GetToken();
  8041. }
  8042. else if (tok == '{')
  8043. {
  8044. // A new {} block begins in the function body
  8045. int undoSymbolsPtr = SyntaxStackCnt;
  8046. int undoLocalOfs = CurFxnLocalOfs;
  8047. int undoIdents = IdentTableLen;
  8048. #ifndef NO_ANNOTATIONS
  8049. GenStartCommentLine(); printf2("{\n");
  8050. #endif
  8051. ParseLevel++;
  8052. tok = ParseBlock(BrkCntTarget, casesIdx);
  8053. ParseLevel--;
  8054. if (tok != '}')
  8055. //error("ParseStatement(): '}' expected. Unexpected token %s\n", GetTokenName(tok));
  8056. errorUnexpectedToken(tok);
  8057. UndoNonLabelIdents(undoIdents); // remove all identifier names, except those of labels
  8058. SyntaxStackCnt = undoSymbolsPtr; // remove all params and locals
  8059. CurFxnLocalOfs = undoLocalOfs; // destroy on-stack local variables
  8060. #ifndef NO_ANNOTATIONS
  8061. GenStartCommentLine(); printf2("}\n");
  8062. #endif
  8063. tok = GetToken();
  8064. }
  8065. else if (tok == tokReturn)
  8066. {
  8067. // DONE: functions returning void vs non-void
  8068. int retVoid = CurFxnReturnExprTypeSynPtr >= 0 &&
  8069. SyntaxStack0[CurFxnReturnExprTypeSynPtr] == tokVoid;
  8070. #ifndef NO_ANNOTATIONS
  8071. GenStartCommentLine(); printf2("return\n");
  8072. #endif
  8073. tok = GetToken();
  8074. if (tok == ';')
  8075. {
  8076. gotUnary = 0;
  8077. if (!retVoid)
  8078. //error("ParseStatement(): missing return value\n");
  8079. errorUnexpectedToken(tok);
  8080. }
  8081. else
  8082. {
  8083. if (retVoid)
  8084. //error("Error: ParseStatement(): cannot return a value from a function returning 'void'\n");
  8085. errorUnexpectedToken(tok);
  8086. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ';')
  8087. //error("ParseStatement(): ';' expected\n");
  8088. errorUnexpectedToken(tok);
  8089. if (gotUnary)
  8090. //error("ParseStatement(): cannot return a value of type 'void'\n");
  8091. #ifdef NO_STRUCT_BY_VAL
  8092. // Bar void and struct/union
  8093. scalarTypeCheck(synPtr);
  8094. #else
  8095. // Bar void
  8096. nonVoidTypeCheck(synPtr);
  8097. #endif
  8098. }
  8099. if (gotUnary)
  8100. {
  8101. #ifndef NO_FP
  8102. int ptrmask;
  8103. int fmask;
  8104. #endif
  8105. #ifndef NO_STRUCT_BY_VAL
  8106. int structs;
  8107. #endif
  8108. decayArray(&synPtr, 0);
  8109. #ifndef NO_FP
  8110. ptrmask = isAnyPtr(CurFxnReturnExprTypeSynPtr) * 2 + isAnyPtr(synPtr);
  8111. fmask = isFloat(CurFxnReturnExprTypeSynPtr) * 2 + isFloat(synPtr);
  8112. if (fmask && ptrmask) // floats don't mix with pointers
  8113. errorOpType();
  8114. #endif
  8115. #ifndef NO_STRUCT_BY_VAL
  8116. structs = (synPtr >= 0 && SyntaxStack0[synPtr] == tokStructPtr) +
  8117. (CurFxnReturnExprTypeSynPtr >= 0 && SyntaxStack0[CurFxnReturnExprTypeSynPtr] == tokStructPtr) * 2;
  8118. if (structs)
  8119. {
  8120. if (structs != 3 ||
  8121. SyntaxStack1[synPtr] != SyntaxStack1[CurFxnReturnExprTypeSynPtr])
  8122. errorOpType();
  8123. // Transform "return *pstruct" into structure assignment ("*pretval = *pstruct")
  8124. // via function call "fxn(sizeof *pretval, pstruct, pretval)".
  8125. // There are a couple of differences to how this is implemented in the assignment operator:
  8126. // - the structure dereference has already been dropped from *pstruct by ParseExpr(),
  8127. // so it isn't removed here
  8128. // - we don't add the structure dereference on top of the value returned by "fxn()"
  8129. // because the return statement is not an expression that can be an operand into another
  8130. // operator
  8131. ins(0, ',');
  8132. ins2(0, tokUnaryStar, SizeOfWord); // dereference to extract the implicit param/arg (pretval) from the stack
  8133. ins2(0, tokLocalOfs, SyntaxStack1[FindSymbol("@") + 1]); // special implicit param/arg (pretval) pointing to structure receptacle
  8134. ins2(0, '(', SizeOfWord * 3);
  8135. push(',');
  8136. push2(tokNumUint, GetDeclSize(synPtr, 0));
  8137. push(',');
  8138. if (!StructCpyLabel)
  8139. StructCpyLabel = LabelCnt++;
  8140. push2(tokIdent, AddNumericIdent(StructCpyLabel));
  8141. push2(')', SizeOfWord * 3);
  8142. }
  8143. else // fallthrough
  8144. #endif
  8145. {
  8146. int castSize = GetDeclSize(CurFxnReturnExprTypeSynPtr, 1);
  8147. #ifndef NO_FP
  8148. if (fmask == 1 || fmask == 2)
  8149. {
  8150. int u = isUint((fmask == 1) ? CurFxnReturnExprTypeSynPtr : synPtr);
  8151. if (constExpr)
  8152. {
  8153. // convert between float and [unsigned] int
  8154. if (fmask == 1)
  8155. exprVal = u ? f2u(exprVal) : f2i(exprVal, castSize);
  8156. else
  8157. exprVal = u ? u2f(exprVal) : i2f(exprVal);
  8158. }
  8159. else
  8160. {
  8161. // insert a call to convert between float and [unsigned] int
  8162. ins2(0, '(', SizeOfWord);
  8163. push(',');
  8164. push2(tokIdent, FindIdent(FpFxnName[(fmask == 1) ? (u ? FXNF2U : FXNF2I) :
  8165. (u ? FXNU2F : FXNI2F)]));
  8166. push2(')', SizeOfWord);
  8167. }
  8168. }
  8169. #endif
  8170. // If return value (per function declaration) is a scalar type smaller than machine word,
  8171. // properly zero- or sign-extend the returned value to machine word size.
  8172. // TBD??? Move this cast to the caller?
  8173. if (castSize != SizeOfWord && castSize != GetDeclSize(synPtr, 1))
  8174. {
  8175. if (constExpr)
  8176. {
  8177. switch (castSize)
  8178. {
  8179. case 1:
  8180. exprVal &= 0xFFu;
  8181. break;
  8182. case -1:
  8183. if ((exprVal &= 0xFFu) >= 0x80)
  8184. exprVal -= 0x100;
  8185. break;
  8186. #ifdef CAN_COMPILE_32BIT
  8187. case 2:
  8188. exprVal &= 0xFFFFu;
  8189. break;
  8190. case -2:
  8191. if ((exprVal &= 0xFFFFu) >= 0x8000)
  8192. exprVal -= 0x10000;
  8193. break;
  8194. #endif
  8195. }
  8196. }
  8197. else
  8198. {
  8199. switch (castSize)
  8200. {
  8201. case 1:
  8202. push(tokUChar);
  8203. break;
  8204. case -1:
  8205. push(tokSChar);
  8206. break;
  8207. #ifdef CAN_COMPILE_32BIT
  8208. case 2:
  8209. push(tokUShort);
  8210. break;
  8211. case -2:
  8212. push(tokShort);
  8213. break;
  8214. #endif
  8215. }
  8216. }
  8217. }
  8218. }
  8219. if (constExpr)
  8220. stack[0][1] = exprVal;
  8221. push(tokReturn); // value produced by generated code is used
  8222. GenExpr();
  8223. }
  8224. tok = GetToken();
  8225. // If this return is the last statement in the function, the epilogue immediately
  8226. // follows and there's no need to jump to it.
  8227. if (!(tok == '}' && ParseLevel == 1 && !IsMain))
  8228. GenJumpUncond(CurFxnEpilogLabel);
  8229. }
  8230. else if (tok == tokWhile)
  8231. {
  8232. int labelBefore = LabelCnt++;
  8233. int labelAfter = LabelCnt++;
  8234. int forever = 0;
  8235. #ifndef NO_ANNOTATIONS
  8236. GenStartCommentLine(); printf2("while\n");
  8237. #endif
  8238. tok = GetToken();
  8239. if (tok != '(')
  8240. //error("ParseStatement(): '(' expected after 'while'\n");
  8241. errorUnexpectedToken(tok);
  8242. tok = GetToken();
  8243. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  8244. //error("ParseStatement(): ')' expected after 'while ( expression'\n");
  8245. errorUnexpectedToken(tok);
  8246. if (!gotUnary)
  8247. //error("ParseStatement(): expression expected in 'while ( expression )'\n");
  8248. errorUnexpectedToken(tok);
  8249. // DONE: void control expressions
  8250. //error("ParseStatement(): unexpected 'void' expression in 'while ( expression )'\n");
  8251. // Bar void and struct/union
  8252. scalarTypeCheck(synPtr);
  8253. GenNumLabel(labelBefore);
  8254. if (constExpr)
  8255. {
  8256. #ifndef NO_FP
  8257. if (isFloat(synPtr))
  8258. exprVal = fcmp(exprVal, i2f(0), -1);
  8259. #endif
  8260. // Special cases for while(0) and while(1)
  8261. if (!(forever = truncInt(exprVal)))
  8262. GenJumpUncond(labelAfter);
  8263. }
  8264. else
  8265. {
  8266. switch (stack[sp - 1][0])
  8267. {
  8268. case '<':
  8269. case '>':
  8270. case tokEQ:
  8271. case tokNEQ:
  8272. case tokLEQ:
  8273. case tokGEQ:
  8274. case tokULess:
  8275. case tokUGreater:
  8276. case tokULEQ:
  8277. case tokUGEQ:
  8278. push2(tokIfNot, labelAfter);
  8279. GenExpr();
  8280. break;
  8281. default:
  8282. #ifndef NO_FP
  8283. if (isFloat(synPtr))
  8284. {
  8285. // insert a call to compare the float with 0.0
  8286. // the returned value will be one of -1,0,+1, that is, 0 if 0, +/-1 otherwise,
  8287. // IOW, suitable for conditional jump on zero/non-zero
  8288. ins(0, ',');
  8289. ins2(0, tokNumInt, i2f(0));
  8290. ins2(0, '(', SizeOfWord * 2);
  8291. push(',');
  8292. push2(tokIdent, FindIdent(FpFxnName[FXNFCMPL]));
  8293. push2(')', SizeOfWord * 2);
  8294. }
  8295. #endif
  8296. push(tokReturn); // value produced by generated code is used
  8297. GenExpr();
  8298. GenJumpIfZero(labelAfter);
  8299. break;
  8300. }
  8301. }
  8302. tok = GetToken();
  8303. brkCntTarget[0] = labelAfter; // break target
  8304. brkCntTarget[1] = labelBefore; // continue target
  8305. tok = ParseStatement(tok, brkCntTarget, casesIdx);
  8306. // Special case for while(0)
  8307. if (!(constExpr && !forever))
  8308. GenJumpUncond(labelBefore);
  8309. GenNumLabel(labelAfter);
  8310. }
  8311. else if (tok == tokDo)
  8312. {
  8313. int labelBefore = LabelCnt++;
  8314. int labelWhile = LabelCnt++;
  8315. int labelAfter = LabelCnt++;
  8316. #ifndef NO_ANNOTATIONS
  8317. GenStartCommentLine(); printf2("do\n");
  8318. #endif
  8319. GenNumLabel(labelBefore);
  8320. tok = GetToken();
  8321. brkCntTarget[0] = labelAfter; // break target
  8322. brkCntTarget[1] = labelWhile; // continue target
  8323. tok = ParseStatement(tok, brkCntTarget, casesIdx);
  8324. if (tok != tokWhile)
  8325. //error("ParseStatement(): 'while' expected after 'do statement'\n");
  8326. errorUnexpectedToken(tok);
  8327. #ifndef NO_ANNOTATIONS
  8328. GenStartCommentLine(); printf2("while\n");
  8329. #endif
  8330. tok = GetToken();
  8331. if (tok != '(')
  8332. //error("ParseStatement(): '(' expected after 'while'\n");
  8333. errorUnexpectedToken(tok);
  8334. tok = GetToken();
  8335. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  8336. //error("ParseStatement(): ')' expected after 'while ( expression'\n");
  8337. errorUnexpectedToken(tok);
  8338. if (!gotUnary)
  8339. //error("ParseStatement(): expression expected in 'while ( expression )'\n");
  8340. errorUnexpectedToken(tok);
  8341. tok = GetToken();
  8342. if (tok != ';')
  8343. //error("ParseStatement(): ';' expected after 'do statement while ( expression )'\n");
  8344. errorUnexpectedToken(tok);
  8345. // DONE: void control expressions
  8346. //error("ParseStatement(): unexpected 'void' expression in 'while ( expression )'\n");
  8347. // Bar void and struct/union
  8348. scalarTypeCheck(synPtr);
  8349. GenNumLabel(labelWhile);
  8350. if (constExpr)
  8351. {
  8352. #ifndef NO_FP
  8353. if (isFloat(synPtr))
  8354. exprVal = fcmp(exprVal, i2f(0), -1);
  8355. #endif
  8356. // Special cases for while(0) and while(1)
  8357. if (truncInt(exprVal))
  8358. GenJumpUncond(labelBefore);
  8359. }
  8360. else
  8361. {
  8362. switch (stack[sp - 1][0])
  8363. {
  8364. case '<':
  8365. case '>':
  8366. case tokEQ:
  8367. case tokNEQ:
  8368. case tokLEQ:
  8369. case tokGEQ:
  8370. case tokULess:
  8371. case tokUGreater:
  8372. case tokULEQ:
  8373. case tokUGEQ:
  8374. push2(tokIf, labelBefore);
  8375. GenExpr();
  8376. break;
  8377. default:
  8378. #ifndef NO_FP
  8379. if (isFloat(synPtr))
  8380. {
  8381. // insert a call to compare the float with 0.0
  8382. // the returned value will be one of -1,0,+1, that is, 0 if 0, +/-1 otherwise,
  8383. // IOW, suitable for conditional jump on zero/non-zero
  8384. ins(0, ',');
  8385. ins2(0, tokNumInt, i2f(0));
  8386. ins2(0, '(', SizeOfWord * 2);
  8387. push(',');
  8388. push2(tokIdent, FindIdent(FpFxnName[FXNFCMPL]));
  8389. push2(')', SizeOfWord * 2);
  8390. }
  8391. #endif
  8392. push(tokReturn); // value produced by generated code is used
  8393. GenExpr();
  8394. GenJumpIfNotZero(labelBefore);
  8395. break;
  8396. }
  8397. }
  8398. GenNumLabel(labelAfter);
  8399. tok = GetToken();
  8400. }
  8401. else if (tok == tokIf)
  8402. {
  8403. int labelAfterIf = LabelCnt++;
  8404. int labelAfterElse = LabelCnt++;
  8405. #ifndef NO_ANNOTATIONS
  8406. GenStartCommentLine(); printf2("if\n");
  8407. #endif
  8408. tok = GetToken();
  8409. if (tok != '(')
  8410. //error("ParseStatement(): '(' expected after 'if'\n");
  8411. errorUnexpectedToken(tok);
  8412. tok = GetToken();
  8413. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  8414. //error("ParseStatement(): ')' expected after 'if ( expression'\n");
  8415. errorUnexpectedToken(tok);
  8416. if (!gotUnary)
  8417. //error("ParseStatement(): expression expected in 'if ( expression )'\n");
  8418. errorUnexpectedToken(tok);
  8419. // DONE: void control expressions
  8420. //error("ParseStatement(): unexpected 'void' expression in 'if ( expression )'\n");
  8421. // Bar void and struct/union
  8422. scalarTypeCheck(synPtr);
  8423. if (constExpr)
  8424. {
  8425. #ifndef NO_FP
  8426. if (isFloat(synPtr))
  8427. exprVal = fcmp(exprVal, i2f(0), -1);
  8428. #endif
  8429. // Special cases for if(0) and if(1)
  8430. if (!truncInt(exprVal))
  8431. GenJumpUncond(labelAfterIf);
  8432. }
  8433. else
  8434. {
  8435. switch (stack[sp - 1][0])
  8436. {
  8437. case '<':
  8438. case '>':
  8439. case tokEQ:
  8440. case tokNEQ:
  8441. case tokLEQ:
  8442. case tokGEQ:
  8443. case tokULess:
  8444. case tokUGreater:
  8445. case tokULEQ:
  8446. case tokUGEQ:
  8447. push2(tokIfNot, labelAfterIf);
  8448. GenExpr();
  8449. break;
  8450. default:
  8451. #ifndef NO_FP
  8452. if (isFloat(synPtr))
  8453. {
  8454. // insert a call to compare the float with 0.0
  8455. // the returned value will be one of -1,0,+1, that is, 0 if 0, +/-1 otherwise,
  8456. // IOW, suitable for conditional jump on zero/non-zero
  8457. ins(0, ',');
  8458. ins2(0, tokNumInt, i2f(0));
  8459. ins2(0, '(', SizeOfWord * 2);
  8460. push(',');
  8461. push2(tokIdent, FindIdent(FpFxnName[FXNFCMPL]));
  8462. push2(')', SizeOfWord * 2);
  8463. }
  8464. #endif
  8465. push(tokReturn); // value produced by generated code is used
  8466. GenExpr();
  8467. GenJumpIfZero(labelAfterIf);
  8468. break;
  8469. }
  8470. }
  8471. tok = GetToken();
  8472. tok = ParseStatement(tok, BrkCntTarget, casesIdx);
  8473. // DONE: else
  8474. if (tok == tokElse)
  8475. {
  8476. GenJumpUncond(labelAfterElse);
  8477. GenNumLabel(labelAfterIf);
  8478. #ifndef NO_ANNOTATIONS
  8479. GenStartCommentLine(); printf2("else\n");
  8480. #endif
  8481. tok = GetToken();
  8482. tok = ParseStatement(tok, BrkCntTarget, casesIdx);
  8483. GenNumLabel(labelAfterElse);
  8484. }
  8485. else
  8486. {
  8487. GenNumLabel(labelAfterIf);
  8488. }
  8489. }
  8490. else if (tok == tokFor)
  8491. {
  8492. int labelBefore = LabelCnt++;
  8493. int labelExpr3 = LabelCnt++;
  8494. int labelBody = LabelCnt++;
  8495. int labelAfter = LabelCnt++;
  8496. int cond = -1;
  8497. static int expr3Stack[STACK_SIZE >> 1][2];
  8498. static int expr3Sp;
  8499. #ifndef NO_FOR_DECL
  8500. int decl = 0;
  8501. int undoSymbolsPtr = 0, undoLocalOfs = 0, undoIdents = 0;
  8502. #endif
  8503. #ifndef NO_ANNOTATIONS
  8504. GenStartCommentLine(); printf2("for\n");
  8505. #endif
  8506. tok = GetToken();
  8507. if (tok != '(')
  8508. //error("ParseStatement(): '(' expected after 'for'\n");
  8509. errorUnexpectedToken(tok);
  8510. tok = GetToken();
  8511. #ifndef NO_FOR_DECL
  8512. if (TokenStartsDeclaration(tok, 1))
  8513. {
  8514. decl = 1;
  8515. undoSymbolsPtr = SyntaxStackCnt;
  8516. undoLocalOfs = CurFxnLocalOfs;
  8517. undoIdents = IdentTableLen;
  8518. // Declarations made in the first clause of for should not:
  8519. // - collide with previous outer declarations
  8520. // - be visible/exist outside for
  8521. // For this reason the declaration gets its own subscope.
  8522. PushSyntax('#'); // mark the beginning of a new scope
  8523. tok = ParseDecl(tok, NULL, 0, 0);
  8524. }
  8525. else
  8526. // fallthrough
  8527. #endif
  8528. {
  8529. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ';')
  8530. //error("ParseStatement(): ';' expected after 'for ( expression'\n");
  8531. errorUnexpectedToken(tok);
  8532. if (gotUnary)
  8533. {
  8534. GenExpr();
  8535. }
  8536. tok = GetToken();
  8537. }
  8538. GenNumLabel(labelBefore);
  8539. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ';')
  8540. //error("ParseStatement(): ';' expected after 'for ( expression ; expression'\n");
  8541. errorUnexpectedToken(tok);
  8542. if (gotUnary)
  8543. {
  8544. // DONE: void control expressions
  8545. //error("ParseStatement(): unexpected 'void' expression in 'for ( ; expression ; )'\n");
  8546. // Bar void and struct/union
  8547. scalarTypeCheck(synPtr);
  8548. if (constExpr)
  8549. {
  8550. #ifndef NO_FP
  8551. if (isFloat(synPtr))
  8552. exprVal = fcmp(exprVal, i2f(0), -1);
  8553. #endif
  8554. // Special cases for for(...; 0; ...) and for(...; 1; ...)
  8555. cond = truncInt(exprVal) != 0;
  8556. }
  8557. else
  8558. {
  8559. switch (stack[sp - 1][0])
  8560. {
  8561. case '<':
  8562. case '>':
  8563. case tokEQ:
  8564. case tokNEQ:
  8565. case tokLEQ:
  8566. case tokGEQ:
  8567. case tokULess:
  8568. case tokUGreater:
  8569. case tokULEQ:
  8570. case tokUGEQ:
  8571. push2(tokIfNot, labelAfter);
  8572. GenExpr();
  8573. break;
  8574. default:
  8575. #ifndef NO_FP
  8576. if (isFloat(synPtr))
  8577. {
  8578. // insert a call to compare the float with 0.0
  8579. // the returned value will be one of -1,0,+1, that is, 0 if 0, +/-1 otherwise,
  8580. // IOW, suitable for conditional jump on zero/non-zero
  8581. ins(0, ',');
  8582. ins2(0, tokNumInt, i2f(0));
  8583. ins2(0, '(', SizeOfWord * 2);
  8584. push(',');
  8585. push2(tokIdent, FindIdent(FpFxnName[FXNFCMPL]));
  8586. push2(')', SizeOfWord * 2);
  8587. }
  8588. #endif
  8589. push(tokReturn); // value produced by generated code is used
  8590. GenExpr();
  8591. GenJumpIfZero(labelAfter);
  8592. break;
  8593. }
  8594. }
  8595. }
  8596. else
  8597. {
  8598. // Special case for for(...; ; ...)
  8599. cond = 1;
  8600. }
  8601. if (!cond)
  8602. // Special case for for(...; 0; ...)
  8603. GenJumpUncond(labelAfter);
  8604. tok = GetToken();
  8605. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  8606. //error("ParseStatement(): ')' expected after 'for ( expression ; expression ; expression'\n");
  8607. errorUnexpectedToken(tok);
  8608. // Try to reorder expr3 with body to reduce the number of jumps, favor small expr3's
  8609. if (gotUnary && sp <= 16 && (unsigned)sp <= division(sizeof expr3Stack , sizeof expr3Stack[0]) - expr3Sp)
  8610. {
  8611. int cnt = sp;
  8612. // Stash the stack containing expr3
  8613. memcpy(expr3Stack + expr3Sp, stack, cnt * sizeof stack[0]);
  8614. expr3Sp += cnt;
  8615. // Body
  8616. tok = GetToken();
  8617. brkCntTarget[0] = labelAfter; // break target
  8618. brkCntTarget[1] = labelExpr3; // continue target
  8619. tok = ParseStatement(tok, brkCntTarget, casesIdx);
  8620. // Unstash expr3 and generate code for it
  8621. expr3Sp -= cnt;
  8622. memcpy(stack, expr3Stack + expr3Sp, cnt * sizeof stack[0]);
  8623. sp = cnt;
  8624. GenNumLabel(labelExpr3);
  8625. GenExpr();
  8626. // Special case for for(...; 0; ...)
  8627. if (cond)
  8628. GenJumpUncond(labelBefore);
  8629. }
  8630. else
  8631. {
  8632. if (gotUnary)
  8633. {
  8634. GenJumpUncond(labelBody);
  8635. // expr3
  8636. GenNumLabel(labelExpr3);
  8637. GenExpr();
  8638. GenJumpUncond(labelBefore);
  8639. GenNumLabel(labelBody);
  8640. }
  8641. // Body
  8642. tok = GetToken();
  8643. brkCntTarget[0] = labelAfter; // break target
  8644. brkCntTarget[1] = gotUnary ? labelExpr3 : (cond ? labelBefore : labelAfter); // continue target
  8645. tok = ParseStatement(tok, brkCntTarget, casesIdx);
  8646. // Special case for for(...; 0; ...)
  8647. if (brkCntTarget[1] != labelAfter)
  8648. GenJumpUncond(brkCntTarget[1]);
  8649. }
  8650. GenNumLabel(labelAfter);
  8651. #ifndef NO_FOR_DECL
  8652. // undo any declarations made in the first clause of for
  8653. if (decl)
  8654. {
  8655. UndoNonLabelIdents(undoIdents); // remove all identifier names, except those of labels
  8656. SyntaxStackCnt = undoSymbolsPtr; // remove all params and locals
  8657. CurFxnLocalOfs = undoLocalOfs; // destroy on-stack local variables
  8658. }
  8659. #endif
  8660. }
  8661. else if (tok == tokBreak)
  8662. {
  8663. #ifndef NO_ANNOTATIONS
  8664. GenStartCommentLine(); printf2("break\n");
  8665. #endif
  8666. if ((tok = GetToken()) != ';')
  8667. //error("ParseStatement(): ';' expected\n");
  8668. errorUnexpectedToken(tok);
  8669. tok = GetToken();
  8670. if (BrkCntTarget == NULL)
  8671. //error("ParseStatement(): 'break' must be within 'while', 'for' or 'switch' statement\n");
  8672. errorCtrlOutOfScope();
  8673. GenJumpUncond(BrkCntTarget[0]);
  8674. }
  8675. else if (tok == tokCont)
  8676. {
  8677. #ifndef NO_ANNOTATIONS
  8678. GenStartCommentLine(); printf2("continue\n");
  8679. #endif
  8680. if ((tok = GetToken()) != ';')
  8681. //error("ParseStatement(): ';' expected\n");
  8682. errorUnexpectedToken(tok);
  8683. tok = GetToken();
  8684. if (BrkCntTarget == NULL || BrkCntTarget[1] == 0)
  8685. //error("ParseStatement(): 'continue' must be within 'while' or 'for' statement\n");
  8686. errorCtrlOutOfScope();
  8687. GenJumpUncond(BrkCntTarget[1]);
  8688. }
  8689. else if (tok == tokSwitch)
  8690. {
  8691. int undoCases = CasesCnt;
  8692. int brkLabel = LabelCnt++;
  8693. int lbl = LabelCnt++;
  8694. int i;
  8695. #ifndef NO_ANNOTATIONS
  8696. GenStartCommentLine(); printf2("switch\n");
  8697. #endif
  8698. tok = GetToken();
  8699. if (tok != '(')
  8700. //error("ParseStatement(): '(' expected after 'switch'\n");
  8701. errorUnexpectedToken(tok);
  8702. tok = GetToken();
  8703. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ')')
  8704. //error("ParseStatement(): ')' expected after 'switch ( expression'\n");
  8705. errorUnexpectedToken(tok);
  8706. if (!gotUnary)
  8707. //error("ParseStatement(): expression expected in 'switch ( expression )'\n");
  8708. errorUnexpectedToken(tok);
  8709. // DONE: void control expressions
  8710. //error("ParseStatement(): unexpected 'void' expression in 'switch ( expression )'\n");
  8711. anyIntTypeCheck(synPtr);
  8712. push(tokReturn); // value produced by generated code is used
  8713. GenExpr();
  8714. tok = GetToken();
  8715. // Skip the code for the cases
  8716. GenJumpUncond(lbl);
  8717. brkCntTarget[0] = brkLabel; // break target
  8718. brkCntTarget[1] = 0; // continue target
  8719. if (BrkCntTarget)
  8720. {
  8721. // Preserve the continue target
  8722. brkCntTarget[1] = BrkCntTarget[1]; // continue target
  8723. }
  8724. // Reserve a slot in the case table for the default label
  8725. AddCase(0, 0);
  8726. tok = ParseStatement(tok, brkCntTarget, CasesCnt);
  8727. // If there's no default target, will use the break target as default
  8728. if (!Cases[undoCases][1])
  8729. Cases[undoCases][1] = brkLabel;
  8730. // End of switch reached (not via break), skip conditional jumps
  8731. GenJumpUncond(brkLabel);
  8732. // Generate conditional jumps
  8733. GenNumLabel(lbl);
  8734. for (i = undoCases + 1; i < CasesCnt; i++)
  8735. {
  8736. GenJumpIfEqual(Cases[i][0], Cases[i][1]);
  8737. }
  8738. // If none of the cases matches, take the default case
  8739. if (Cases[undoCases][1] != brkLabel)
  8740. GenJumpUncond(Cases[undoCases][1]);
  8741. GenNumLabel(brkLabel); // break label
  8742. CasesCnt = undoCases;
  8743. }
  8744. else if (tok == tokCase)
  8745. {
  8746. int i;
  8747. #ifndef NO_ANNOTATIONS
  8748. GenStartCommentLine(); printf2("case\n");
  8749. #endif
  8750. if (!casesIdx)
  8751. //error("ParseStatement(): 'case' must be within 'switch' statement\n");
  8752. errorCtrlOutOfScope();
  8753. tok = GetToken();
  8754. if ((tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, 0, 0)) != ':')
  8755. //error("ParseStatement(): ':' expected after 'case expression'\n");
  8756. errorUnexpectedToken(tok);
  8757. if (!gotUnary)
  8758. errorUnexpectedToken(tok);
  8759. anyIntTypeCheck(synPtr);
  8760. if (!constExpr)
  8761. //error("ParseStatement(): constant integer expression expected in 'case expression :'\n");
  8762. errorNotConst();
  8763. // Check for dups
  8764. exprVal = truncInt(exprVal);
  8765. for (i = casesIdx; i < CasesCnt; i++)
  8766. if (Cases[i][0] == exprVal)
  8767. error("Duplicate case value\n");
  8768. AddCase(exprVal, LabelCnt);
  8769. GenNumLabel(LabelCnt++); // case exprVal:
  8770. tok = GetToken();
  8771. // a statement is needed after "case:"
  8772. statementNeeded = 1;
  8773. }
  8774. else if (tok == tokDefault)
  8775. {
  8776. #ifndef NO_ANNOTATIONS
  8777. GenStartCommentLine(); printf2("default\n");
  8778. #endif
  8779. if (!casesIdx)
  8780. //error("ParseStatement(): 'default' must be within 'switch' statement\n");
  8781. errorCtrlOutOfScope();
  8782. if (Cases[casesIdx - 1][1])
  8783. //error("ParseStatement(): only one 'default' allowed in 'switch'\n");
  8784. errorUnexpectedToken(tok);
  8785. tok = GetToken();
  8786. if (tok != ':')
  8787. //error("ParseStatement(): ':' expected after 'default'\n");
  8788. errorUnexpectedToken(tok);
  8789. tok = GetToken();
  8790. GenNumLabel(Cases[casesIdx - 1][1] = LabelCnt++); // default:
  8791. // a statement is needed after "default:"
  8792. statementNeeded = 1;
  8793. }
  8794. else if (tok == tok_Asm)
  8795. {
  8796. tok = GetToken();
  8797. if (tok != '(')
  8798. //error("ParseStatement(): '(' expected after 'asm'\n");
  8799. errorUnexpectedToken(tok);
  8800. tok = GetToken();
  8801. if (tok != tokLitStr)
  8802. //error("ParseStatement(): string literal expression expected in 'asm ( expression )'\n");
  8803. errorUnexpectedToken(tok);
  8804. do
  8805. {
  8806. GetString('"', 0, 'a');
  8807. tok = GetToken();
  8808. } while (tok == tokLitStr); // concatenate adjacent string literals
  8809. printf2("\n");
  8810. if (tok != ')')
  8811. //error("ParseStatement(): ')' expected after 'asm ( expression'\n");
  8812. errorUnexpectedToken(tok);
  8813. tok = GetToken();
  8814. if (tok != ';')
  8815. //error("ParseStatement(): ';' expected after 'asm ( expression )'\n");
  8816. errorUnexpectedToken(tok);
  8817. tok = GetToken();
  8818. }
  8819. else if (tok == tokGoto)
  8820. {
  8821. if ((tok = GetToken()) != tokIdent)
  8822. errorUnexpectedToken(tok);
  8823. #ifndef NO_ANNOTATIONS
  8824. GenStartCommentLine(); printf2("goto %s\n", TokenIdentName);
  8825. #endif
  8826. GenJumpUncond(AddGotoLabel(TokenIdentName, 0));
  8827. if ((tok = GetToken()) != ';')
  8828. errorUnexpectedToken(tok);
  8829. tok = GetToken();
  8830. }
  8831. else
  8832. {
  8833. tok = ParseExpr(tok, &gotUnary, &synPtr, &constExpr, &exprVal, tokGotoLabel, 0);
  8834. if (tok == tokGotoLabel)
  8835. {
  8836. // found a label
  8837. #ifndef NO_ANNOTATIONS
  8838. GenStartCommentLine(); printf2("%s:\n", IdentTable + stack[0][1]);
  8839. #endif
  8840. GenNumLabel(AddGotoLabel(IdentTable + stack[0][1], 1));
  8841. // a statement is needed after "label:"
  8842. statementNeeded = 1;
  8843. }
  8844. else
  8845. {
  8846. if (tok != ';')
  8847. //error("ParseStatement(): ';' expected\n");
  8848. errorUnexpectedToken(tok);
  8849. if (gotUnary)
  8850. GenExpr();
  8851. }
  8852. tok = GetToken();
  8853. }
  8854. } while (statementNeeded);
  8855. return tok;
  8856. }
  8857. // TBD!!! think of ways of getting rid of casesIdx
  8858. STATIC
  8859. int ParseBlock(int BrkCntTarget[2], int casesIdx)
  8860. {
  8861. int tok = GetToken();
  8862. // Catch redeclarations of function parameters by not
  8863. // beginning a new scope if this block begins a function
  8864. // (the caller of ParseBlock() must've begun a new scope
  8865. // already, before the function parameters).
  8866. if (BrkCntTarget == BrkCntTargetFxn)
  8867. BrkCntTarget = NULL;
  8868. else
  8869. // Otherwise begin a new scope.
  8870. PushSyntax('#');
  8871. for (;;)
  8872. {
  8873. if (tok == 0)
  8874. return tok;
  8875. if (tok == '}' && ParseLevel > 0)
  8876. return tok;
  8877. if (TokenStartsDeclaration(tok, 0))
  8878. {
  8879. tok = ParseDecl(tok, NULL, 0, 1);
  8880. #ifndef NO_TYPEDEF_ENUM
  8881. if (tok == tokGotoLabel)
  8882. {
  8883. // found a label
  8884. #ifndef NO_ANNOTATIONS
  8885. GenStartCommentLine(); printf2("%s:\n", TokenIdentName);
  8886. #endif
  8887. GenNumLabel(AddGotoLabel(TokenIdentName, 1));
  8888. tok = GetToken();
  8889. // a statement is needed after "label:"
  8890. tok = ParseStatement(tok, BrkCntTarget, casesIdx);
  8891. }
  8892. #endif
  8893. }
  8894. else if (ParseLevel > 0 || tok == tok_Asm)
  8895. {
  8896. tok = ParseStatement(tok, BrkCntTarget, casesIdx);
  8897. }
  8898. else
  8899. //error("ParseBlock(): Unexpected token %s\n", GetTokenName(tok));
  8900. errorUnexpectedToken(tok);
  8901. }
  8902. }
  8903. int main(int argc, char** argv)
  8904. {
  8905. // gcc/MinGW inserts a call to __main() here.
  8906. int i;
  8907. // Run-time initializer for SyntaxStack0[] to reduce
  8908. // executable file size (SyntaxStack0[] will be in .bss)
  8909. static unsigned char SyntaxStackInit[] =
  8910. {
  8911. tokVoid, // SymVoidSynPtr
  8912. tokInt, // SymIntSynPtr
  8913. tokUnsigned, // SymUintSynPtr
  8914. tokVoid, // SymWideCharSynPtr
  8915. tokFloat, // SymFloatSynPtr
  8916. tokIdent, // SymFuncPtr
  8917. '[',
  8918. tokNumUint,
  8919. ']',
  8920. tokChar
  8921. }; // SyntaxStackCnt must be initialized to the number of elements in SyntaxStackInit[]
  8922. memcpy(SyntaxStack0, SyntaxStackInit, sizeof SyntaxStackInit);
  8923. SyntaxStackCnt = division(sizeof SyntaxStackInit , sizeof SyntaxStackInit[0]);
  8924. #ifdef __SMALLER_C__
  8925. #ifdef DETERMINE_VA_LIST
  8926. DetermineVaListType();
  8927. #endif
  8928. #endif
  8929. SyntaxStack1[SymFuncPtr] = DummyIdent = AddIdent("");
  8930. #ifndef NO_FP
  8931. {
  8932. static float testFloat = -5915522.0f * 1.5f;
  8933. static unsigned testUint = 0xCB076543; // expected representation of the above
  8934. if (memcmp(&testFloat, &testUint, sizeof testFloat))
  8935. error("IEEE 754 floating point required on host\n");
  8936. }
  8937. for (i = 0; (unsigned)i < division(sizeof FpFxnName , sizeof FpFxnName[0]); i++)
  8938. AddIdent(FpFxnName[i]);
  8939. #endif
  8940. GenInit();
  8941. // Parse the command line arguments
  8942. for (i = 1; i < argc; i++)
  8943. {
  8944. // DONE: move code-generator-specific options to
  8945. // the code generator
  8946. if (GenInitParams(argc, argv, &i))
  8947. {
  8948. continue;
  8949. }
  8950. else if (!strcmp(argv[i], "--os"))
  8951. {
  8952. compileOS = 1;
  8953. continue;
  8954. }
  8955. else if (!strcmp(argv[i], "--bdos"))
  8956. {
  8957. compileUserBDOS = 1;
  8958. continue;
  8959. }
  8960. else if (!strcmp(argv[i], "-signed-char"))
  8961. {
  8962. // this is the default option
  8963. CharIsSigned = 1;
  8964. continue;
  8965. }
  8966. else if (!strcmp(argv[i], "-unsigned-char"))
  8967. {
  8968. CharIsSigned = 0;
  8969. continue;
  8970. }
  8971. #ifndef NO_WCHAR
  8972. else if (!strcmp(argv[i], "-signed-wchar"))
  8973. {
  8974. WideCharIsSigned = 1;
  8975. continue;
  8976. }
  8977. else if (!strcmp(argv[i], "-unsigned-wchar"))
  8978. {
  8979. // this is the default option
  8980. WideCharIsSigned = 0;
  8981. continue;
  8982. }
  8983. else if (!strcmp(argv[i], "-short-wchar"))
  8984. {
  8985. // this is the default option
  8986. SizeOfWideChar = 2;
  8987. continue;
  8988. }
  8989. #ifdef CAN_COMPILE_32BIT
  8990. else if (!strcmp(argv[i], "-long-wchar"))
  8991. {
  8992. SizeOfWideChar = 4;
  8993. continue;
  8994. }
  8995. #endif
  8996. #endif
  8997. else if (!strcmp(argv[i], "-leading-underscore"))
  8998. {
  8999. // this is the default option for x86
  9000. UseLeadingUnderscores = 1;
  9001. continue;
  9002. }
  9003. else if (!strcmp(argv[i], "-no-leading-underscore"))
  9004. {
  9005. // this is the default option for MIPS
  9006. UseLeadingUnderscores = 0;
  9007. continue;
  9008. }
  9009. else if (!strcmp(argv[i], "-label"))
  9010. {
  9011. if (i + 1 < argc)
  9012. {
  9013. LabelCnt = atoi(argv[++i]);
  9014. continue;
  9015. }
  9016. }
  9017. else if (!strcmp(argv[i], "-no-externs"))
  9018. {
  9019. GenExterns = 0;
  9020. continue;
  9021. }
  9022. else if (!strcmp(argv[i], "-verbose"))
  9023. {
  9024. warnings = verbose = 1;
  9025. continue;
  9026. }
  9027. else if (!strcmp(argv[i], "-Wall"))
  9028. {
  9029. warnings = 1;
  9030. continue;
  9031. }
  9032. #ifndef NO_PREPROCESSOR
  9033. else if (!strcmp(argv[i], "-I") || !strcmp(argv[i], "-SI"))
  9034. {
  9035. if (i + 1 < argc)
  9036. {
  9037. int len = strlen(argv[++i]) + 1;
  9038. if (argv[i - 1][1] == 'I')
  9039. {
  9040. if (MAX_SEARCH_PATH - SearchPathsLen < len)
  9041. //error("Path name too long\n");
  9042. errorFileName();
  9043. strcpy(SearchPaths + SearchPathsLen, argv[i]);
  9044. SearchPathsLen += len;
  9045. }
  9046. else
  9047. {
  9048. if (MAX_SEARCH_PATH - SysSearchPathsLen < len)
  9049. //error("Path name too long\n");
  9050. errorFileName();
  9051. strcpy(SysSearchPaths + SysSearchPathsLen, argv[i]);
  9052. SysSearchPathsLen += len;
  9053. }
  9054. continue;
  9055. }
  9056. }
  9057. else if (!strcmp(argv[i], "-nopp"))
  9058. {
  9059. // TBD!!! don't do preprocessing when this option is present
  9060. continue;
  9061. }
  9062. // DONE: '-D macro[=expansion]': '#define macro 1' when there's no '=expansion'
  9063. else if (!strcmp(argv[i], "-D"))
  9064. {
  9065. if (i + 1 < argc)
  9066. {
  9067. char id[MAX_IDENT_LEN + 1];
  9068. char* e = strchr(argv[++i], '=');
  9069. int len;
  9070. if (e)
  9071. {
  9072. len = e - argv[i];
  9073. e++;
  9074. }
  9075. else
  9076. {
  9077. len = strlen(argv[i]);
  9078. e = "1";
  9079. }
  9080. if (len > 0 && len <= MAX_IDENT_LEN)
  9081. {
  9082. int j, bad = 1;
  9083. memcpy(id, argv[i], len);
  9084. id[len] = '\0';
  9085. for (j = 0; j < len; j++)
  9086. if ((bad = !(id[j] == '_' || (!j * isalpha(id[j] & 0xFFu) + j * isalnum(id[j] & 0xFFu)))) != 0)
  9087. break;
  9088. if (!bad)
  9089. {
  9090. DefineMacro(id, e);
  9091. continue;
  9092. }
  9093. }
  9094. }
  9095. }
  9096. #endif // #ifndef NO_PREPROCESSOR
  9097. else if (argv[i][0] == '-')
  9098. {
  9099. // unknown option
  9100. }
  9101. else if (FileCnt == 0)
  9102. {
  9103. // If it's none of the known options,
  9104. // assume it's the source code file name
  9105. if (strlen(argv[i]) > MAX_FILE_NAME_LEN)
  9106. //error("File name too long\n");
  9107. errorFileName();
  9108. strcpy(FileNames[0], argv[i]);
  9109. if ((Files[0] = fopen(FileNames[0], "r")) == NULL)
  9110. //error("Cannot open file \"%s\"\n", FileNames[0]);
  9111. errorFile(FileNames[0]);
  9112. LineNos[0] = LineNo;
  9113. LinePoss[0] = LinePos;
  9114. FileCnt++;
  9115. continue;
  9116. }
  9117. else if (FileCnt == 1 && OutFile == NULL)
  9118. {
  9119. // This should be the output file name
  9120. if ((OutFile = fopen(argv[i], "w")) == NULL)
  9121. //error("Cannot open output file \"%s\"\n", argv[i]);
  9122. errorFile(argv[i]);
  9123. continue;
  9124. }
  9125. error("Invalid or unsupported command line option\n");
  9126. }
  9127. if (!FileCnt)
  9128. error("Input file not specified\n");
  9129. if (!OutFile)
  9130. error("Output file not specified\n");
  9131. #ifndef NO_WCHAR
  9132. WideCharType1 = WideCharIsSigned ? tokInt : tokUnsigned;
  9133. WideCharType2 = WideCharType1 ^ tokInt ^ tokUnsigned;
  9134. #ifdef CAN_COMPILE_32BIT
  9135. if (SizeOfWideChar > SizeOfWord)
  9136. error("Wide char too wide\n");
  9137. if (SizeOfWord == 4 && SizeOfWideChar == 2)
  9138. {
  9139. WideCharType1 = WideCharIsSigned ? tokShort : tokUShort;
  9140. WideCharType2 = WideCharType1 ^ tokShort ^ tokUShort;
  9141. }
  9142. #endif
  9143. SyntaxStack0[SymWideCharSynPtr] = WideCharType1;
  9144. #endif
  9145. GenInitFinalize();
  9146. #ifndef NO_PREPROCESSOR
  9147. // Define a few macros useful for conditional compilation
  9148. DefineMacro("__SMALLER_C__", "0x0100");
  9149. if (SizeOfWord == 2)
  9150. DefineMacro("__SMALLER_C_16__", "");
  9151. #ifdef CAN_COMPILE_32BIT
  9152. else if (SizeOfWord == 4)
  9153. DefineMacro("__SMALLER_C_32__", "");
  9154. #endif
  9155. #ifdef CAN_COMPILE_32BIT
  9156. if (OutputFormat == FormatSegHuge)
  9157. DefineMacro("__HUGE__", "");
  9158. if (OutputFormat == FormatSegUnreal)
  9159. DefineMacro("__UNREAL__", "");
  9160. #endif
  9161. if (CharIsSigned)
  9162. DefineMacro("__SMALLER_C_SCHAR__", "");
  9163. else
  9164. DefineMacro("__SMALLER_C_UCHAR__", "");
  9165. #ifndef NO_WCHAR
  9166. if (WideCharIsSigned)
  9167. DefineMacro("__SMALLER_C_SWCHAR__", "");
  9168. else
  9169. DefineMacro("__SMALLER_C_UWCHAR__", "");
  9170. #ifdef CAN_COMPILE_32BIT
  9171. if (SizeOfWideChar == 4)
  9172. DefineMacro("__SMALLER_C_WCHAR32__", "");
  9173. else
  9174. #endif
  9175. DefineMacro("__SMALLER_C_WCHAR16__", "");
  9176. #endif
  9177. #endif // NO_PREPROCESSOR
  9178. // populate CharQueue[] with the initial file characters
  9179. ShiftChar();
  9180. puts2(FileHeader);
  9181. // compile
  9182. #ifndef NO_PPACK
  9183. PragmaPackValue = SizeOfWord;
  9184. #endif
  9185. ParseBlock(NULL, 0);
  9186. GenFin();
  9187. #ifndef NO_ANNOTATIONS
  9188. DumpSynDecls();
  9189. #endif
  9190. #ifndef NO_PREPROCESSOR
  9191. #ifndef NO_ANNOTATIONS
  9192. DumpMacroTable();
  9193. #endif
  9194. #endif
  9195. #ifndef NO_ANNOTATIONS
  9196. DumpIdentTable();
  9197. #endif
  9198. GenStartCommentLine(); printf2("Next label number: %d\n", LabelCnt);
  9199. if (warnings && warnCnt)
  9200. printf("%d warnings\n", warnCnt);
  9201. GenStartCommentLine(); printf2("Compilation succeeded.\n");
  9202. if (OutFile)
  9203. fclose(OutFile);
  9204. return 0;
  9205. }