1
0

bcc.c 206 KB

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