doxygen.cpp 347 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 1997-2010 by Dimitri van Heesch.
  4. *
  5. * Permission to use, copy, modify, and distribute this software and its
  6. * documentation under the terms of the GNU General Public License is hereby
  7. * granted. No representations are made about the suitability of this software
  8. * for any purpose. It is provided "as is" without express or implied warranty.
  9. * See the GNU General Public License for more details.
  10. *
  11. * Documents produced by Doxygen are derivative works derived from the
  12. * input used in their production; they are not affected by this license.
  13. *
  14. */
  15. #include "qtbc.h"
  16. #include <qfileinfo.h>
  17. #include <qfile.h>
  18. #include <qdir.h>
  19. #include <qdict.h>
  20. #include <qregexp.h>
  21. #include <qstrlist.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <sys/stat.h>
  25. #include <qtextcodec.h>
  26. #include <unistd.h>
  27. #include <errno.h>
  28. #include "version.h"
  29. #include "doxygen.h"
  30. #include "scanner.h"
  31. #include "entry.h"
  32. #include "index.h"
  33. #include "logos.h"
  34. #include "instdox.h"
  35. #include "message.h"
  36. #include "config.h"
  37. #include "util.h"
  38. #include "pre.h"
  39. #include "tagreader.h"
  40. #include "dot.h"
  41. #include "docparser.h"
  42. #include "dirdef.h"
  43. #include "outputlist.h"
  44. #include "declinfo.h"
  45. #include "htmlgen.h"
  46. #include "latexgen.h"
  47. #include "mangen.h"
  48. #include "language.h"
  49. #include "debug.h"
  50. #include "htmlhelp.h"
  51. #include "qhp.h"
  52. #include "indexlog.h"
  53. #include "ftvhelp.h"
  54. #include "defargs.h"
  55. #include "rtfgen.h"
  56. #include "xmlgen.h"
  57. #include "defgen.h"
  58. #include "perlmodgen.h"
  59. #include "reflist.h"
  60. #include "pagedef.h"
  61. #include "bufstr.h"
  62. #include "commentcnv.h"
  63. #include "cmdmapper.h"
  64. #include "searchindex.h"
  65. #include "parserintf.h"
  66. #include "htags.h"
  67. #include "pyscanner.h"
  68. #include "fortranscanner.h"
  69. #include "dbusxmlscanner.h"
  70. #include "code.h"
  71. #include "objcache.h"
  72. #include "store.h"
  73. #include "marshal.h"
  74. #include "portable.h"
  75. #include "vhdlscanner.h"
  76. #include "vhdldocgen.h"
  77. #include "eclipsehelp.h"
  78. #include "layout.h"
  79. #define RECURSE_ENTRYTREE(func,var) \
  80. do { if (var->children()) { \
  81. EntryNavListIterator eli(*var->children()); \
  82. for (;eli.current();++eli) func(eli.current()); \
  83. } } while(0)
  84. #if !defined(_WIN32) || defined(__CYGWIN__)
  85. #include <signal.h>
  86. #define HAS_SIGNALS
  87. #endif
  88. // globally accessible variables
  89. ClassSDict *Doxygen::classSDict = 0;
  90. ClassSDict *Doxygen::hiddenClasses = 0;
  91. NamespaceSDict *Doxygen::namespaceSDict = 0;
  92. MemberNameSDict *Doxygen::memberNameSDict = 0;
  93. MemberNameSDict *Doxygen::functionNameSDict = 0;
  94. FileNameList *Doxygen::inputNameList = 0; // all input files
  95. FileNameDict *Doxygen::inputNameDict = 0;
  96. GroupSDict *Doxygen::groupSDict = 0;
  97. FormulaList Doxygen::formulaList; // all formulas
  98. FormulaDict Doxygen::formulaDict(1009); // all formulas
  99. FormulaDict Doxygen::formulaNameDict(1009); // the label name of all formulas
  100. PageSDict *Doxygen::pageSDict = 0;
  101. PageSDict *Doxygen::exampleSDict = 0;
  102. SectionDict Doxygen::sectionDict(257); // all page sections
  103. StringDict Doxygen::aliasDict(257); // aliases
  104. FileNameDict *Doxygen::includeNameDict = 0; // include names
  105. FileNameDict *Doxygen::exampleNameDict = 0; // examples
  106. FileNameDict *Doxygen::imageNameDict = 0; // images
  107. FileNameDict *Doxygen::dotFileNameDict = 0; // dot files
  108. StringDict Doxygen::namespaceAliasDict(257); // all namespace aliases
  109. StringDict Doxygen::tagDestinationDict(257); // all tag locations
  110. QDict<void> Doxygen::expandAsDefinedDict(257); // all macros that should be expanded
  111. QIntDict<MemberGroupInfo> Doxygen::memGrpInfoDict(1009); // dictionary of the member groups heading
  112. PageDef *Doxygen::mainPage = 0;
  113. bool Doxygen::insideMainPage = FALSE; // are we generating docs for the main page?
  114. QTextStream Doxygen::tagFile;
  115. NamespaceDef *Doxygen::globalScope = 0;
  116. QDict<RefList> *Doxygen::xrefLists = new QDict<RefList>; // dictionary of cross-referenced item lists
  117. bool Doxygen::parseSourcesNeeded = FALSE;
  118. QTime Doxygen::runningTime;
  119. SearchIndex * Doxygen::searchIndex=0;
  120. QDict<DefinitionIntf> *Doxygen::symbolMap;
  121. bool Doxygen::outputToWizard=FALSE;
  122. QDict<int> * Doxygen::htmlDirMap = 0;
  123. QCache<LookupInfo> Doxygen::lookupCache(50000,50000);
  124. DirSDict *Doxygen::directories;
  125. SDict<DirRelation> Doxygen::dirRelations(257);
  126. ParserManager *Doxygen::parserManager = 0;
  127. QCString Doxygen::htmlFileExtension;
  128. bool Doxygen::suppressDocWarnings = FALSE;
  129. ObjCache *Doxygen::symbolCache = 0;
  130. Store *Doxygen::symbolStorage;
  131. QCString Doxygen::objDBFileName;
  132. QCString Doxygen::entryDBFileName;
  133. bool Doxygen::gatherDefines = TRUE;
  134. IndexList Doxygen::indexList;
  135. int Doxygen::subpageNestingLevel = 0;
  136. bool Doxygen::userComments = FALSE;
  137. QCString Doxygen::spaces;
  138. // locally accessible globals
  139. static QDict<EntryNav> g_classEntries(1009);
  140. static StringList g_inputFiles;
  141. static QDict<void> g_compoundKeywordDict(7); // keywords recognised as compounds
  142. static OutputList *g_outputList = 0; // list of output generating objects
  143. static QDict<FileDef> g_usingDeclarations(1009); // used classes
  144. static FileStorage *g_storage = 0;
  145. static bool g_successfulRun = FALSE;
  146. static bool g_dumpSymbolMap = FALSE;
  147. static bool g_dumpConfigAsXML = FALSE;
  148. void clearAll()
  149. {
  150. g_inputFiles.clear();
  151. //g_excludeNameDict.clear();
  152. //delete g_outputList; g_outputList=0;
  153. Doxygen::classSDict->clear();
  154. Doxygen::namespaceSDict->clear();
  155. Doxygen::pageSDict->clear();
  156. Doxygen::exampleSDict->clear();
  157. Doxygen::inputNameList->clear();
  158. Doxygen::formulaList.clear();
  159. Doxygen::sectionDict.clear();
  160. Doxygen::inputNameDict->clear();
  161. Doxygen::includeNameDict->clear();
  162. Doxygen::exampleNameDict->clear();
  163. Doxygen::imageNameDict->clear();
  164. Doxygen::dotFileNameDict->clear();
  165. Doxygen::formulaDict.clear();
  166. Doxygen::formulaNameDict.clear();
  167. Doxygen::tagDestinationDict.clear();
  168. delete Doxygen::mainPage; Doxygen::mainPage=0;
  169. }
  170. void statistics()
  171. {
  172. fprintf(stderr,"--- inputNameDict stats ----\n");
  173. Doxygen::inputNameDict->statistics();
  174. fprintf(stderr,"--- includeNameDict stats ----\n");
  175. Doxygen::includeNameDict->statistics();
  176. fprintf(stderr,"--- exampleNameDict stats ----\n");
  177. Doxygen::exampleNameDict->statistics();
  178. fprintf(stderr,"--- imageNameDict stats ----\n");
  179. Doxygen::imageNameDict->statistics();
  180. fprintf(stderr,"--- dotFileNameDict stats ----\n");
  181. Doxygen::dotFileNameDict->statistics();
  182. //fprintf(stderr,"--- g_excludeNameDict stats ----\n");
  183. //g_excludeNameDict.statistics();
  184. fprintf(stderr,"--- aliasDict stats ----\n");
  185. Doxygen::aliasDict.statistics();
  186. fprintf(stderr,"--- typedefDict stats ----\n");
  187. fprintf(stderr,"--- namespaceAliasDict stats ----\n");
  188. Doxygen::namespaceAliasDict.statistics();
  189. fprintf(stderr,"--- formulaDict stats ----\n");
  190. Doxygen::formulaDict.statistics();
  191. fprintf(stderr,"--- formulaNameDict stats ----\n");
  192. Doxygen::formulaNameDict.statistics();
  193. fprintf(stderr,"--- tagDestinationDict stats ----\n");
  194. Doxygen::tagDestinationDict.statistics();
  195. fprintf(stderr,"--- g_compoundKeywordDict stats ----\n");
  196. g_compoundKeywordDict.statistics();
  197. fprintf(stderr,"--- expandAsDefinedDict stats ----\n");
  198. Doxygen::expandAsDefinedDict.statistics();
  199. fprintf(stderr,"--- memGrpInfoDict stats ----\n");
  200. Doxygen::memGrpInfoDict.statistics();
  201. }
  202. static void addMemberDocs(EntryNav *rootNav,MemberDef *md, const char *funcDecl,
  203. ArgumentList *al,bool over_load,NamespaceSDict *nl=0);
  204. static void findMember(EntryNav *rootNav,
  205. QCString funcDecl,
  206. bool overloaded,
  207. bool isFunc
  208. );
  209. struct STLInfo
  210. {
  211. const char *className;
  212. const char *baseClass1;
  213. const char *baseClass2;
  214. const char *templType1;
  215. const char *templName1;
  216. const char *templType2;
  217. const char *templName2;
  218. bool virtualInheritance;
  219. bool iterators;
  220. };
  221. static STLInfo g_stlinfo[] =
  222. {
  223. // className baseClass1 baseClass2 templType1 templName1 templType2 templName2 virtInheritance // iterators
  224. { "allocator", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
  225. { "auto_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE },
  226. { "ios_base", 0, 0, 0, 0, 0, 0, FALSE, FALSE },
  227. { "basic_ios", "ios_base", 0, "Char", 0, 0, 0, FALSE, FALSE },
  228. { "basic_istream", "basic_ios<Char>", 0, "Char", 0, 0, 0, TRUE, FALSE },
  229. { "basic_ostream", "basic_ios<Char>", 0, "Char", 0, 0, 0, TRUE, FALSE },
  230. { "basic_iostream", "basic_istream<Char>", "basic_ostream<Char>", "Char", 0, 0, 0, FALSE, FALSE },
  231. { "basic_ifstream", "basic_istream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
  232. { "basic_ofstream", "basic_ostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
  233. { "basic_fstream", "basic_iostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
  234. { "basic_istringstream", "basic_istream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
  235. { "basic_ostringstream", "basic_ostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
  236. { "basic_stringstream", "basic_iostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
  237. { "ios", "basic_ios<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
  238. { "wios", "basic_ios<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
  239. { "istream", "basic_istream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
  240. { "wistream", "basic_istream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
  241. { "ostream", "basic_ostream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
  242. { "wostream", "basic_ostream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
  243. { "ifstream", "basic_ifstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
  244. { "wifstream", "basic_ifstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
  245. { "ofstream", "basic_ofstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
  246. { "wofstream", "basic_ofstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
  247. { "fstream", "basic_fstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
  248. { "wfstream", "basic_fstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
  249. { "istringstream", "basic_istringstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
  250. { "wistringstream", "basic_istringstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
  251. { "ostringstream", "basic_ostringstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
  252. { "wostringstream", "basic_ostringstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
  253. { "stringstream", "basic_stringstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
  254. { "wstringstream", "basic_stringstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
  255. { "basic_string", 0, 0, "Char", 0, 0, 0, FALSE, TRUE },
  256. { "string", "basic_string<char>", 0, 0, 0, 0, 0, FALSE, TRUE },
  257. { "wstring", "basic_string<wchar_t>", 0, 0, 0, 0, 0, FALSE, TRUE },
  258. { "complex", 0, 0, 0, 0, 0, 0, FALSE, FALSE },
  259. { "bitset", 0, 0, "Bits", 0, 0, 0, FALSE, FALSE },
  260. { "deque", 0, 0, "T", "elements", 0, 0, FALSE, TRUE },
  261. { "list", 0, 0, "T", "elements", 0, 0, FALSE, TRUE },
  262. { "map", 0, 0, "K", "keys", "T", "elements", FALSE, TRUE },
  263. { "multimap", 0, 0, "K", "keys", "T", "elements", FALSE, TRUE },
  264. { "set", 0, 0, "K", "keys", 0, 0, FALSE, TRUE },
  265. { "multiset", 0, 0, "K", "keys", 0, 0, FALSE, TRUE },
  266. { "vector", 0, 0, "T", "elements", 0, 0, FALSE, TRUE },
  267. { "queue", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
  268. { "priority_queue", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
  269. { "stack", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
  270. { "valarray", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
  271. { "exception", 0, 0, 0, 0, 0, 0, FALSE, FALSE },
  272. { "bad_alloc", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
  273. { "bad_cast", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
  274. { "bad_typeid", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
  275. { "logic_error", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
  276. { "ios_base::failure", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
  277. { "runtime_error", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
  278. { "bad_exception", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
  279. { "domain_error", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
  280. { "invalid_argument", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
  281. { "length_error", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
  282. { "out_of_range", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
  283. { "range_error", "runtime_error", 0, 0, 0, 0, 0, FALSE, FALSE },
  284. { "overflow_error", "runtime_error", 0, 0, 0, 0, 0, FALSE, FALSE },
  285. { "underflow_error", "runtime_error", 0, 0, 0, 0, 0, FALSE, FALSE },
  286. { 0, 0, 0, 0, 0, 0, 0, FALSE, FALSE }
  287. };
  288. static void addSTLMember(EntryNav *rootNav,const char *type,const char *name)
  289. {
  290. Entry *memEntry = new Entry;
  291. memEntry->name = name;
  292. memEntry->type = type;
  293. memEntry->protection = Private;
  294. memEntry->section = Entry::VARIABLE_SEC;
  295. memEntry->brief = "STL member";
  296. memEntry->hidden = FALSE;
  297. memEntry->artificial = TRUE;
  298. //memEntry->parent = root;
  299. //root->addSubEntry(memEntry);
  300. EntryNav *memEntryNav = new EntryNav(rootNav,memEntry);
  301. memEntryNav->setEntry(memEntry);
  302. rootNav->addChild(memEntryNav);
  303. }
  304. static void addSTLIterator(EntryNav *classEntryNav,const char *name)
  305. {
  306. Entry *iteratorClassEntry = new Entry;
  307. iteratorClassEntry->fileName = "[STL]";
  308. iteratorClassEntry->startLine = 1;
  309. iteratorClassEntry->name = name;
  310. iteratorClassEntry->section = Entry::CLASS_SEC;
  311. iteratorClassEntry->brief = "STL iterator class";
  312. iteratorClassEntry->hidden = FALSE;
  313. iteratorClassEntry->artificial= TRUE;
  314. EntryNav *iteratorClassEntryNav = new EntryNav(classEntryNav,iteratorClassEntry);
  315. iteratorClassEntryNav->setEntry(iteratorClassEntry);
  316. classEntryNav->addChild(iteratorClassEntryNav);
  317. }
  318. static void addSTLClasses(EntryNav *rootNav)
  319. {
  320. Entry *namespaceEntry = new Entry;
  321. namespaceEntry->fileName = "[STL]";
  322. namespaceEntry->startLine = 1;
  323. //namespaceEntry->parent = rootNav->entry();
  324. namespaceEntry->name = "std";
  325. namespaceEntry->section = Entry::NAMESPACE_SEC;
  326. namespaceEntry->brief = "STL namespace";
  327. namespaceEntry->hidden = FALSE;
  328. namespaceEntry->artificial= TRUE;
  329. //root->addSubEntry(namespaceEntry);
  330. EntryNav *namespaceEntryNav = new EntryNav(rootNav,namespaceEntry);
  331. namespaceEntryNav->setEntry(namespaceEntry);
  332. rootNav->addChild(namespaceEntryNav);
  333. STLInfo *info = g_stlinfo;
  334. while (info->className)
  335. {
  336. //printf("Adding STL class %s\n",info->className);
  337. QCString fullName = info->className;
  338. fullName.prepend("std::");
  339. // add fake Entry for the class
  340. Entry *classEntry = new Entry;
  341. classEntry->fileName = "[STL]";
  342. classEntry->startLine = 1;
  343. classEntry->name = fullName;
  344. //classEntry->parent = namespaceEntry;
  345. classEntry->section = Entry::CLASS_SEC;
  346. classEntry->brief = "STL class";
  347. classEntry->hidden = FALSE;
  348. classEntry->artificial= TRUE;
  349. //namespaceEntry->addSubEntry(classEntry);
  350. EntryNav *classEntryNav = new EntryNav(namespaceEntryNav,classEntry);
  351. classEntryNav->setEntry(classEntry);
  352. namespaceEntryNav->addChild(classEntryNav);
  353. // add template arguments to class
  354. if (info->templType1)
  355. {
  356. ArgumentList *al = new ArgumentList;
  357. Argument *a=new Argument;
  358. a->type="typename";
  359. a->name=info->templType1;
  360. al->append(a);
  361. if (info->templType2) // another template argument
  362. {
  363. a=new Argument;
  364. a->type="typename";
  365. a->name=info->templType2;
  366. al->append(a);
  367. }
  368. classEntry->tArgLists = new QList<ArgumentList>;
  369. classEntry->tArgLists->setAutoDelete(TRUE);
  370. classEntry->tArgLists->append(al);
  371. }
  372. // add member variables
  373. if (info->templName1)
  374. {
  375. addSTLMember(classEntryNav,info->templType1,info->templName1);
  376. }
  377. if (info->templName2)
  378. {
  379. addSTLMember(classEntryNav,info->templType2,info->templName2);
  380. }
  381. if (info->baseClass1)
  382. {
  383. classEntry->extends->append(new BaseInfo(info->baseClass1,Public,info->virtualInheritance?Virtual:Normal));
  384. }
  385. if (info->baseClass2)
  386. {
  387. classEntry->extends->append(new BaseInfo(info->baseClass2,Public,info->virtualInheritance?Virtual:Normal));
  388. }
  389. if (info->iterators)
  390. {
  391. // add iterator class
  392. addSTLIterator(classEntryNav,fullName+"::iterator");
  393. addSTLIterator(classEntryNav,fullName+"::const_iterator");
  394. addSTLIterator(classEntryNav,fullName+"::reverse_iterator");
  395. addSTLIterator(classEntryNav,fullName+"::const_reverse_iterator");
  396. }
  397. info++;
  398. }
  399. }
  400. //----------------------------------------------------------------------------
  401. static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n,
  402. FileDef *fileScope=0);
  403. static void addPageToContext(PageDef *pd,EntryNav *rootNav)
  404. {
  405. if (rootNav->parent()) // add the page to it's scope
  406. {
  407. QCString scope = rootNav->parent()->name();
  408. if (rootNav->parent()->section()==Entry::PACKAGEDOC_SEC)
  409. {
  410. scope=substitute(scope,".","::");
  411. }
  412. scope = stripAnonymousNamespaceScope(scope);
  413. scope+="::"+pd->name();
  414. Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,scope);
  415. if (d)
  416. {
  417. pd->setPageScope(d);
  418. }
  419. }
  420. }
  421. static void addRelatedPage(EntryNav *rootNav)
  422. {
  423. Entry *root = rootNav->entry();
  424. GroupDef *gd=0;
  425. QListIterator<Grouping> gli(*root->groups);
  426. Grouping *g;
  427. for (;(g=gli.current());++gli)
  428. {
  429. if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname))) break;
  430. }
  431. //printf("---> addRelatedPage() %s gd=%p\n",root->name.data(),gd);
  432. QCString doc;
  433. if (root->brief.isEmpty())
  434. {
  435. doc=root->doc+root->inbodyDocs;
  436. }
  437. else
  438. {
  439. doc=root->brief+"\n\n"+root->doc+root->inbodyDocs;
  440. }
  441. PageDef *pd = addRelatedPage(root->name,root->args,doc,root->anchors,
  442. root->fileName,root->startLine,
  443. root->sli,
  444. gd,rootNav->tagInfo()
  445. );
  446. if (pd)
  447. {
  448. pd->addSectionsToDefinition(root->anchors);
  449. addPageToContext(pd,rootNav);
  450. }
  451. }
  452. static void buildGroupListFiltered(EntryNav *rootNav,bool additional)
  453. {
  454. if (rootNav->section()==Entry::GROUPDOC_SEC && !rootNav->name().isEmpty())
  455. {
  456. //printf("Found group %s title=`%s type=%d'\n",
  457. // root->name.data(),root->type.data(),root->groupDocType);
  458. rootNav->loadEntry(g_storage);
  459. Entry *root = rootNav->entry();
  460. if ((root->groupDocType==Entry::GROUPDOC_NORMAL && !additional) ||
  461. (root->groupDocType!=Entry::GROUPDOC_NORMAL && additional))
  462. {
  463. GroupDef *gd;
  464. if ((gd=Doxygen::groupSDict->find(root->name)))
  465. {
  466. if ( !gd->hasGroupTitle() )
  467. {
  468. gd->setGroupTitle( root->type );
  469. }
  470. else if ( root->type.length() > 0 && root->name != root->type && gd->groupTitle() != root->type )
  471. {
  472. warn( root->fileName,root->startLine,
  473. "group %s: ignoring title \"%s\" that does not match old title \"%s\"\n",
  474. root->name.data(), root->type.data(), gd->groupTitle() );
  475. }
  476. gd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  477. gd->setDocumentation( root->doc, root->docFile, root->docLine );
  478. gd->setInbodyDocumentation( root->inbodyDocs, root->inbodyFile, root->inbodyLine );
  479. gd->addSectionsToDefinition(root->anchors);
  480. gd->setRefItems(root->sli);
  481. }
  482. else
  483. {
  484. if (rootNav->tagInfo())
  485. {
  486. gd = new GroupDef(root->fileName,root->startLine,root->name,root->type,rootNav->tagInfo()->fileName);
  487. gd->setReference(rootNav->tagInfo()->tagName);
  488. }
  489. else
  490. {
  491. gd = new GroupDef(root->fileName,root->startLine,root->name,root->type);
  492. }
  493. gd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  494. gd->setDocumentation(root->doc,root->docFile,root->docLine);
  495. gd->setInbodyDocumentation( root->inbodyDocs, root->inbodyFile, root->inbodyLine );
  496. gd->addSectionsToDefinition(root->anchors);
  497. Doxygen::groupSDict->append(root->name,gd);
  498. gd->setRefItems(root->sli);
  499. }
  500. }
  501. rootNav->releaseEntry();
  502. }
  503. if (rootNav->children())
  504. {
  505. EntryNavListIterator eli(*rootNav->children());
  506. EntryNav *e;
  507. for (;(e=eli.current());++eli)
  508. {
  509. buildGroupListFiltered(e,additional);
  510. }
  511. }
  512. }
  513. static void buildGroupList(EntryNav *rootNav)
  514. {
  515. // first process the @defgroups blocks
  516. buildGroupListFiltered(rootNav,FALSE);
  517. // then process the @addtogroup, @weakgroup blocks
  518. buildGroupListFiltered(rootNav,TRUE);
  519. }
  520. static void findGroupScope(EntryNav *rootNav)
  521. {
  522. if (rootNav->section()==Entry::GROUPDOC_SEC && !rootNav->name().isEmpty() &&
  523. rootNav->parent() && !rootNav->parent()->name().isEmpty())
  524. {
  525. GroupDef *gd;
  526. if ((gd=Doxygen::groupSDict->find(rootNav->name())))
  527. {
  528. QCString scope = rootNav->parent()->name();
  529. if (rootNav->parent()->section()==Entry::PACKAGEDOC_SEC)
  530. {
  531. scope=substitute(scope,".","::");
  532. }
  533. scope = stripAnonymousNamespaceScope(scope);
  534. scope+="::"+gd->name();
  535. Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,scope);
  536. if (d)
  537. {
  538. gd->setGroupScope(d);
  539. }
  540. }
  541. }
  542. RECURSE_ENTRYTREE(findGroupScope,rootNav);
  543. }
  544. static void organizeSubGroupsFiltered(EntryNav *rootNav,bool additional)
  545. {
  546. if (rootNav->section()==Entry::GROUPDOC_SEC && !rootNav->name().isEmpty())
  547. {
  548. rootNav->loadEntry(g_storage);
  549. Entry *root = rootNav->entry();
  550. if ((root->groupDocType==Entry::GROUPDOC_NORMAL && !additional) ||
  551. (root->groupDocType!=Entry::GROUPDOC_NORMAL && additional))
  552. {
  553. GroupDef *gd;
  554. if ((gd=Doxygen::groupSDict->find(root->name)))
  555. {
  556. //printf("adding %s to group %s\n",root->name.data(),gd->name().data());
  557. addGroupToGroups(root,gd);
  558. }
  559. }
  560. rootNav->releaseEntry();
  561. }
  562. if (rootNav->children())
  563. {
  564. EntryNavListIterator eli(*rootNav->children());
  565. EntryNav *e;
  566. for (;(e=eli.current());++eli)
  567. {
  568. organizeSubGroupsFiltered(e,additional);
  569. }
  570. }
  571. }
  572. static void organizeSubGroups(EntryNav *rootNav)
  573. {
  574. //printf("Defining groups\n");
  575. // first process the @defgroups blocks
  576. organizeSubGroupsFiltered(rootNav,FALSE);
  577. //printf("Additional groups\n");
  578. // then process the @addtogroup, @weakgroup blocks
  579. organizeSubGroupsFiltered(rootNav,TRUE);
  580. }
  581. //----------------------------------------------------------------------
  582. static void buildFileList(EntryNav *rootNav)
  583. {
  584. if (((rootNav->section()==Entry::FILEDOC_SEC) ||
  585. ((rootNav->section() & Entry::FILE_MASK) && Config_getBool("EXTRACT_ALL"))) &&
  586. !rootNav->name().isEmpty() && !rootNav->tagInfo() // skip any file coming from tag files
  587. )
  588. {
  589. rootNav->loadEntry(g_storage);
  590. Entry *root = rootNav->entry();
  591. bool ambig;
  592. FileDef *fd=findFileDef(Doxygen::inputNameDict,root->name,ambig);
  593. //printf("**************** root->name=%s fd=%p\n",root->name.data(),fd);
  594. if (fd && !ambig)
  595. {
  596. #if 0
  597. if ((!root->doc.isEmpty() && !fd->documentation().isEmpty()) ||
  598. (!root->brief.isEmpty() && !fd->briefDescription().isEmpty()))
  599. {
  600. warn(
  601. root->fileName,root->startLine,
  602. "Warning: file %s already documented. "
  603. "Skipping documentation.",
  604. root->name.data()
  605. );
  606. }
  607. else
  608. #endif
  609. {
  610. //printf("Adding documentation!\n");
  611. // using FALSE in setDocumentation is small hack to make sure a file
  612. // is documented even if a \file command is used without further
  613. // documentation
  614. fd->setDocumentation(root->doc,root->docFile,root->docLine,FALSE);
  615. fd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  616. fd->addSectionsToDefinition(root->anchors);
  617. fd->setRefItems(root->sli);
  618. QListIterator<Grouping> gli(*root->groups);
  619. Grouping *g;
  620. for (;(g=gli.current());++gli)
  621. {
  622. GroupDef *gd=0;
  623. if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
  624. {
  625. gd->addFile(fd);
  626. //printf("File %s: in group %s\n",fd->name().data(),s->data());
  627. }
  628. }
  629. }
  630. }
  631. else
  632. {
  633. const char *fn = root->fileName.data();
  634. QCString text;
  635. text.sprintf("Warning: the name `%s' supplied as "
  636. "the second argument in the \\file statement ",
  637. root->name.data()
  638. );
  639. if (ambig) // name is ambigious
  640. {
  641. text+="matches the following input files:\n";
  642. text+=showFileDefMatches(Doxygen::inputNameDict,root->name);
  643. text+="Please use a more specific name by "
  644. "including a (larger) part of the path!";
  645. }
  646. else // name is not an input file
  647. {
  648. text+="is not an input file";
  649. }
  650. warn(fn,root->startLine,text);
  651. }
  652. rootNav->releaseEntry();
  653. }
  654. RECURSE_ENTRYTREE(buildFileList,rootNav);
  655. }
  656. static void addIncludeFile(ClassDef *cd,FileDef *ifd,Entry *root)
  657. {
  658. if (
  659. (!root->doc.stripWhiteSpace().isEmpty() ||
  660. !root->brief.stripWhiteSpace().isEmpty() ||
  661. Config_getBool("EXTRACT_ALL")
  662. ) && root->protection!=Private
  663. )
  664. {
  665. //printf(">>>>>> includeFile=%s\n",root->includeFile.data());
  666. bool local=Config_getBool("FORCE_LOCAL_INCLUDES");
  667. QCString includeFile = root->includeFile;
  668. if (!includeFile.isEmpty() && includeFile.at(0)=='"')
  669. {
  670. local = TRUE;
  671. includeFile=includeFile.mid(1,includeFile.length()-2);
  672. }
  673. else if (!includeFile.isEmpty() && includeFile.at(0)=='<')
  674. {
  675. local = FALSE;
  676. includeFile=includeFile.mid(1,includeFile.length()-2);
  677. }
  678. bool ambig;
  679. FileDef *fd=0;
  680. // see if we need to include a verbatim copy of the header file
  681. //printf("root->includeFile=%s\n",root->includeFile.data());
  682. if (!includeFile.isEmpty() &&
  683. (fd=findFileDef(Doxygen::inputNameDict,includeFile,ambig))==0
  684. )
  685. { // explicit request
  686. QCString text;
  687. text.sprintf("Warning: the name `%s' supplied as "
  688. "the argument of the \\class, \\struct, \\union, or \\include command ",
  689. includeFile.data()
  690. );
  691. if (ambig) // name is ambigious
  692. {
  693. text+="matches the following input files:\n";
  694. text+=showFileDefMatches(Doxygen::inputNameDict,root->includeFile);
  695. text+="Please use a more specific name by "
  696. "including a (larger) part of the path!";
  697. }
  698. else // name is not an input file
  699. {
  700. text+="is not an input file";
  701. }
  702. warn(root->fileName,root->startLine,text);
  703. }
  704. else if (includeFile.isEmpty() && ifd &&
  705. // see if the file extension makes sense
  706. guessSection(ifd->name())==Entry::HEADER_SEC)
  707. { // implicit assumption
  708. fd=ifd;
  709. }
  710. // if a file is found, we mark it as a source file.
  711. if (fd)
  712. {
  713. QCString iName = !root->includeName.isEmpty() ?
  714. root->includeName : includeFile;
  715. if (!iName.isEmpty()) // user specified include file
  716. {
  717. if (iName.at(0)=='<') local=FALSE; // explicit override
  718. if (iName.at(0)=='"' || iName.at(0)=='<')
  719. {
  720. iName=iName.mid(1,iName.length()-2); // strip quotes or brackets
  721. }
  722. if (iName.isEmpty())
  723. {
  724. iName=fd->name();
  725. }
  726. }
  727. else if (!Config_getList("STRIP_FROM_INC_PATH").isEmpty())
  728. {
  729. iName=stripFromIncludePath(fd->absFilePath());
  730. }
  731. else // use name of the file containing the class definition
  732. {
  733. iName=fd->name();
  734. }
  735. if (fd->generateSourceFile()) // generate code for header
  736. {
  737. cd->setIncludeFile(fd,iName,local,!root->includeName.isEmpty());
  738. }
  739. else // put #include in the class documentation without link
  740. {
  741. cd->setIncludeFile(0,iName,local,TRUE);
  742. }
  743. }
  744. }
  745. }
  746. #if 0
  747. static bool addNamespace(Entry *root,ClassDef *cd)
  748. {
  749. // see if this class is defined inside a namespace
  750. if (root->section & Entry::COMPOUND_MASK)
  751. {
  752. Entry *e = root->parent;
  753. while (e)
  754. {
  755. if (e->section==Entry::NAMESPACE_SEC)
  756. {
  757. NamespaceDef *nd=0;
  758. QCString nsName = stripAnonymousNamespaceScope(e->name);
  759. //printf("addNameSpace() trying: %s\n",nsName.data());
  760. if (!nsName.isEmpty() && nsName.at(0)!='@' &&
  761. (nd=getResolvedNamespace(nsName))
  762. )
  763. {
  764. cd->setNamespace(nd);
  765. cd->setOuterScope(nd);
  766. nd->insertClass(cd);
  767. return TRUE;
  768. }
  769. }
  770. e=e->parent;
  771. }
  772. }
  773. return FALSE;
  774. }
  775. #endif
  776. #if 0
  777. static Definition *findScope(Entry *root,int level=0)
  778. {
  779. if (root==0) return 0;
  780. //printf("start findScope name=%s\n",root->name.data());
  781. Definition *result=0;
  782. if (root->section&Entry::SCOPE_MASK)
  783. {
  784. result = findScope(root->parent,level+1); // traverse to the root of the tree
  785. if (result)
  786. {
  787. //printf("Found %s inside %s at level %d\n",root->name.data(),result->name().data(),level);
  788. // TODO: look at template arguments
  789. result = result->findInnerCompound(root->name);
  790. }
  791. else // reached the global scope
  792. {
  793. // TODO: look at template arguments
  794. result = Doxygen::globalScope->findInnerCompound(root->name);
  795. //printf("Found in globalScope %s at level %d\n",result->name().data(),level);
  796. }
  797. }
  798. //printf("end findScope(%s,%d)=%s\n",root->name.data(),
  799. // level,result==0 ? "<none>" : result->name().data());
  800. return result;
  801. }
  802. #endif
  803. /*! returns the Definition object belonging to the first \a level levels of
  804. * full qualified name \a name. Creates an artificial scope if the scope is
  805. * not found and set the parent/child scope relation if the scope is found.
  806. */
  807. static Definition *buildScopeFromQualifiedName(const QCString name,int level)
  808. {
  809. int i=0;
  810. int p=0,l;
  811. Definition *prevScope=Doxygen::globalScope;
  812. QCString fullScope;
  813. while (i<level)
  814. {
  815. int idx=getScopeFragment(name,p,&l);
  816. QCString nsName = name.mid(idx,l);
  817. if (nsName.isEmpty()) return prevScope;
  818. if (!fullScope.isEmpty()) fullScope+="::";
  819. fullScope+=nsName;
  820. NamespaceDef *nd=Doxygen::namespaceSDict->find(fullScope);
  821. Definition *innerScope = nd;
  822. ClassDef *cd=0;
  823. if (nd==0) cd = getClass(fullScope);
  824. if (nd==0 && cd) // scope is a class
  825. {
  826. innerScope = cd;
  827. }
  828. else if (nd==0 && cd==0) // scope is not known!
  829. {
  830. // introduce bogus namespace
  831. //printf("++ adding dummy namespace %s to %s\n",nsName.data(),prevScope->name().data());
  832. nd=new NamespaceDef(
  833. "[generated]",1,fullScope);
  834. // add namespace to the list
  835. Doxygen::namespaceSDict->inSort(fullScope,nd);
  836. innerScope = nd;
  837. }
  838. else // scope is a namespace
  839. {
  840. }
  841. // make the parent/child scope relation
  842. prevScope->addInnerCompound(innerScope);
  843. innerScope->setOuterScope(prevScope);
  844. // proceed to the next scope fragment
  845. p=idx+l+2;
  846. prevScope=innerScope;
  847. i++;
  848. }
  849. return prevScope;
  850. }
  851. static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n,
  852. FileDef *fileScope)
  853. {
  854. //printf("<findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data());
  855. Definition *resultScope=startScope;
  856. if (resultScope==0) resultScope=Doxygen::globalScope;
  857. QCString scope=stripTemplateSpecifiersFromScope(n,FALSE);
  858. int l1=0,i1;
  859. i1=getScopeFragment(scope,0,&l1);
  860. if (i1==-1)
  861. {
  862. //printf(">no fragments!\n");
  863. return resultScope;
  864. }
  865. int p=i1+l1,l2=0,i2;
  866. while ((i2=getScopeFragment(scope,p,&l2))!=-1)
  867. {
  868. QCString nestedNameSpecifier = scope.mid(i1,l1);
  869. Definition *orgScope = resultScope;
  870. //printf(" nestedNameSpecifier=%s\n",nestedNameSpecifier.data());
  871. resultScope = resultScope->findInnerCompound(nestedNameSpecifier);
  872. //printf(" resultScope=%p\n",resultScope);
  873. if (resultScope==0)
  874. {
  875. NamespaceSDict *usedNamespaces;
  876. if (orgScope==Doxygen::globalScope && fileScope &&
  877. (usedNamespaces = fileScope->getUsedNamespaces()))
  878. // also search for used namespaces
  879. {
  880. NamespaceSDict::Iterator ni(*usedNamespaces);
  881. NamespaceDef *nd;
  882. for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni)
  883. {
  884. // restart search within the used namespace
  885. resultScope = findScopeFromQualifiedName(nd,n,fileScope);
  886. }
  887. if (resultScope)
  888. {
  889. // for a nested class A::I in used namespace N, we get
  890. // N::A::I while looking for A, so we should compare
  891. // resultScope->name() against scope.left(i2+l2)
  892. //printf(" -> result=%s scope=%s\n",resultScope->name().data(),scope.data());
  893. if (rightScopeMatch(resultScope->name(),scope.left(i2+l2)))
  894. {
  895. break;
  896. }
  897. goto nextFragment;
  898. }
  899. }
  900. // also search for used classes. Complication: we haven't been able
  901. // to put them in the right scope yet, because we are still resolving
  902. // the scope relations!
  903. // Therefore loop through all used classes and see if there is a right
  904. // scope match between the used class and nestedNameSpecifier.
  905. QDictIterator<FileDef> ui(g_usingDeclarations);
  906. FileDef *usedFd;
  907. for (ui.toFirst();(usedFd=ui.current());++ui)
  908. {
  909. //printf("Checking using class %s\n",ui.currentKey());
  910. if (rightScopeMatch(ui.currentKey(),nestedNameSpecifier))
  911. {
  912. // ui.currentKey() is the fully qualified name of nestedNameSpecifier
  913. // so use this instead.
  914. QCString fqn = QCString(ui.currentKey())+
  915. scope.right(scope.length()-p);
  916. resultScope = buildScopeFromQualifiedName(fqn,fqn.contains("::"));
  917. //printf("Creating scope from fqn=%s result %p\n",fqn.data(),resultScope);
  918. if (resultScope)
  919. {
  920. //printf("> Match! resultScope=%s\n",resultScope->name().data());
  921. return resultScope;
  922. }
  923. }
  924. }
  925. //printf("> name %s not found in scope %s\n",nestedNameSpecifier.data(),orgScope->name().data());
  926. return 0;
  927. }
  928. nextFragment:
  929. i1=i2;
  930. l1=l2;
  931. p=i2+l2;
  932. }
  933. //printf(">findScopeFromQualifiedName scope %s\n",resultScope->name().data());
  934. return resultScope;
  935. }
  936. ArgumentList *getTemplateArgumentsFromName(
  937. const QCString &name,
  938. const QList<ArgumentList> *tArgLists)
  939. {
  940. if (tArgLists==0) return 0;
  941. QListIterator<ArgumentList> ali(*tArgLists);
  942. // for each scope fragment, check if it is a template and advance through
  943. // the list if so.
  944. int i,p=0;
  945. while ((i=name.find("::",p))!=-1)
  946. {
  947. NamespaceDef *nd = Doxygen::namespaceSDict->find(name.left(i));
  948. if (nd==0)
  949. {
  950. ClassDef *cd = getClass(name.left(i));
  951. if (cd)
  952. {
  953. if (cd->templateArguments())
  954. {
  955. ++ali;
  956. }
  957. }
  958. }
  959. p=i+2;
  960. }
  961. return ali.current();
  962. }
  963. static ClassDef::CompoundType convertToCompoundType(int section,int specifier)
  964. {
  965. ClassDef::CompoundType sec=ClassDef::Class;
  966. if (specifier&Entry::Struct)
  967. sec=ClassDef::Struct;
  968. else if (specifier&Entry::Union)
  969. sec=ClassDef::Union;
  970. else if (specifier&Entry::Interface)
  971. sec=ClassDef::Interface;
  972. else if (specifier&Entry::Protocol)
  973. sec=ClassDef::Protocol;
  974. else if (specifier&Entry::Category)
  975. sec=ClassDef::Category;
  976. else if (specifier&Entry::Exception)
  977. sec=ClassDef::Exception;
  978. switch(section)
  979. {
  980. //case Entry::UNION_SEC:
  981. case Entry::UNIONDOC_SEC:
  982. sec=ClassDef::Union;
  983. break;
  984. //case Entry::STRUCT_SEC:
  985. case Entry::STRUCTDOC_SEC:
  986. sec=ClassDef::Struct;
  987. break;
  988. //case Entry::INTERFACE_SEC:
  989. case Entry::INTERFACEDOC_SEC:
  990. sec=ClassDef::Interface;
  991. break;
  992. //case Entry::PROTOCOL_SEC:
  993. case Entry::PROTOCOLDOC_SEC:
  994. sec=ClassDef::Protocol;
  995. break;
  996. //case Entry::CATEGORY_SEC:
  997. case Entry::CATEGORYDOC_SEC:
  998. sec=ClassDef::Category;
  999. break;
  1000. //case Entry::EXCEPTION_SEC:
  1001. case Entry::EXCEPTIONDOC_SEC:
  1002. sec=ClassDef::Exception;
  1003. break;
  1004. }
  1005. return sec;
  1006. }
  1007. static void addClassToContext(EntryNav *rootNav)
  1008. {
  1009. //printf("Loading entry for rootNav=%p name=%s\n",rootNav,rootNav->name().data());
  1010. rootNav->loadEntry(g_storage);
  1011. Entry *root = rootNav->entry();
  1012. //NamespaceDef *nd = 0;
  1013. FileDef *fd = rootNav->fileDef();
  1014. QCString scName;
  1015. if (rootNav->parent()->section()&Entry::SCOPE_MASK)
  1016. {
  1017. scName=rootNav->parent()->name();
  1018. }
  1019. // name without parent's scope
  1020. QCString fullName = root->name;
  1021. // strip off any template parameters (but not those for specializations)
  1022. fullName=stripTemplateSpecifiersFromScope(fullName);
  1023. // name with scope (if not present already)
  1024. QCString qualifiedName = fullName;
  1025. if (!scName.isEmpty() && !leftScopeMatch(fullName,scName))
  1026. {
  1027. qualifiedName.prepend(scName+"::");
  1028. }
  1029. // see if we already found the class before
  1030. ClassDef *cd = getClass(qualifiedName);
  1031. Debug::print(Debug::Classes,0, " Found class with name %s (qualifiedName=%s -> cd=%p)\n",
  1032. cd ? cd->name().data() : root->name.data(), qualifiedName.data(),cd);
  1033. if (cd)
  1034. {
  1035. fullName=cd->name();
  1036. Debug::print(Debug::Classes,0," Existing class %s!\n",cd->name().data());
  1037. //if (cd->templateArguments()==0)
  1038. //{
  1039. // //printf("existing ClassDef tempArgList=%p specScope=%s\n",root->tArgList,root->scopeSpec.data());
  1040. // cd->setTemplateArguments(tArgList);
  1041. //}
  1042. cd->setDocumentation(root->doc,root->docFile,root->docLine);
  1043. cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1044. if (root->bodyLine!=-1 && cd->getStartBodyLine()==-1)
  1045. {
  1046. cd->setBodySegment(root->bodyLine,root->endBodyLine);
  1047. cd->setBodyDef(fd);
  1048. }
  1049. //cd->setName(fullName); // change name to match docs
  1050. if (cd->templateArguments()==0)
  1051. {
  1052. // this happens if a template class declared with @class is found
  1053. // before the actual definition.
  1054. ArgumentList *tArgList =
  1055. getTemplateArgumentsFromName(cd->name(),root->tArgLists);
  1056. cd->setTemplateArguments(tArgList);
  1057. }
  1058. cd->setCompoundType(convertToCompoundType(root->section,root->spec));
  1059. }
  1060. else // new class
  1061. {
  1062. ClassDef::CompoundType sec = convertToCompoundType(root->section,root->spec);
  1063. QCString className;
  1064. QCString namespaceName;
  1065. extractNamespaceName(fullName,className,namespaceName);
  1066. //printf("New class: fullname %s namespace `%s' name=`%s' brief=`%s' docs=`%s'\n",
  1067. // fullName.data(),namespaceName.data(),className.data(),root->brief.data(),root->doc.data());
  1068. QCString tagName;
  1069. QCString refFileName;
  1070. if (rootNav->tagInfo())
  1071. {
  1072. tagName = rootNav->tagInfo()->tagName;
  1073. refFileName = rootNav->tagInfo()->fileName;
  1074. }
  1075. cd=new ClassDef(root->fileName,root->startLine,fullName,sec,
  1076. tagName,refFileName);
  1077. Debug::print(Debug::Classes,0," New class `%s' (sec=0x%08x)! #tArgLists=%d\n",
  1078. fullName.data(),root->section,root->tArgLists ? (int)root->tArgLists->count() : -1);
  1079. cd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
  1080. cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1081. cd->setIsObjectiveC(root->objc);
  1082. cd->setHidden(root->hidden);
  1083. cd->setArtificial(root->artificial);
  1084. cd->setTypeConstraints(root->typeConstr);
  1085. //printf("new ClassDef %s tempArgList=%p specScope=%s\n",fullName.data(),root->tArgList,root->scopeSpec.data());
  1086. ArgumentList *tArgList =
  1087. getTemplateArgumentsFromName(fullName,root->tArgLists);
  1088. //printf("class %s template args=%s\n",fullName.data(),
  1089. // tArgList ? tempArgListToString(tArgList).data() : "<none>");
  1090. cd->setTemplateArguments(tArgList);
  1091. cd->setProtection(root->protection);
  1092. cd->setIsStatic(root->stat);
  1093. // file definition containing the class cd
  1094. cd->setBodySegment(root->bodyLine,root->endBodyLine);
  1095. cd->setBodyDef(fd);
  1096. // see if the class is found inside a namespace
  1097. //bool found=addNamespace(root,cd);
  1098. // the empty string test is needed for extract all case
  1099. cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1100. cd->insertUsedFile(root->fileName);
  1101. // add class to the list
  1102. //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data());
  1103. Doxygen::classSDict->append(fullName,cd);
  1104. }
  1105. cd->addSectionsToDefinition(root->anchors);
  1106. if (!root->subGrouping) cd->setSubGrouping(FALSE);
  1107. if (cd->hasDocumentation())
  1108. {
  1109. addIncludeFile(cd,fd,root);
  1110. }
  1111. if (fd && (root->section & Entry::COMPOUND_MASK))
  1112. {
  1113. //printf(">> Inserting class `%s' in file `%s' (root->fileName=`%s')\n",
  1114. // cd->name().data(),
  1115. // fd->name().data(),
  1116. // root->fileName.data()
  1117. // );
  1118. cd->setFileDef(fd);
  1119. fd->insertClass(cd);
  1120. }
  1121. addClassToGroups(root,cd);
  1122. cd->setRefItems(root->sli);
  1123. rootNav->releaseEntry();
  1124. }
  1125. //----------------------------------------------------------------------
  1126. // build a list of all classes mentioned in the documentation
  1127. // and all classes that have a documentation block before their definition.
  1128. static void buildClassList(EntryNav *rootNav)
  1129. {
  1130. if (
  1131. ((rootNav->section() & Entry::COMPOUND_MASK) ||
  1132. rootNav->section()==Entry::OBJCIMPL_SEC) && !rootNav->name().isEmpty()
  1133. )
  1134. {
  1135. addClassToContext(rootNav);
  1136. }
  1137. RECURSE_ENTRYTREE(buildClassList,rootNav);
  1138. }
  1139. static void buildClassDocList(EntryNav *rootNav)
  1140. {
  1141. if (
  1142. (rootNav->section() & Entry::COMPOUNDDOC_MASK) && !rootNav->name().isEmpty()
  1143. )
  1144. {
  1145. addClassToContext(rootNav);
  1146. }
  1147. RECURSE_ENTRYTREE(buildClassDocList,rootNav);
  1148. }
  1149. static void resolveClassNestingRelations()
  1150. {
  1151. ClassSDict::Iterator cli(*Doxygen::classSDict);
  1152. for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
  1153. bool done=FALSE;
  1154. int iteration=0;
  1155. while (!done)
  1156. {
  1157. done=TRUE;
  1158. ++iteration;
  1159. ClassDef *cd=0;
  1160. for (cli.toFirst();(cd=cli.current());++cli)
  1161. {
  1162. if (!cd->visited)
  1163. {
  1164. QCString name = stripAnonymousNamespaceScope(cd->name());
  1165. //printf("processing=%s, iteration=%d\n",cd->name().data(),iteration);
  1166. // also add class to the correct structural context
  1167. Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,
  1168. name,cd->getFileDef());
  1169. if (d)
  1170. {
  1171. //printf("****** adding %s to scope %s in iteration %d\n",cd->name().data(),d->name().data(),iteration);
  1172. d->addInnerCompound(cd);
  1173. cd->setOuterScope(d);
  1174. cd->visited=TRUE;
  1175. done=FALSE;
  1176. }
  1177. //else
  1178. //{
  1179. // printf("****** ignoring %s: scope not (yet) found in iteration %d\n",cd->name().data(),iteration);
  1180. //}
  1181. }
  1182. }
  1183. }
  1184. //give warnings for unresolved compounds
  1185. ClassDef *cd=0;
  1186. for (cli.toFirst();(cd=cli.current());++cli)
  1187. {
  1188. if (!cd->visited)
  1189. {
  1190. QCString name = stripAnonymousNamespaceScope(cd->name());
  1191. //printf("processing unresolved=%s, iteration=%d\n",cd->name().data(),iteration);
  1192. /// create the scope artificially
  1193. // anyway, so we can at least relate scopes properly.
  1194. Definition *d = buildScopeFromQualifiedName(name,name.contains("::"));
  1195. if (d!=cd && !cd->getDefFileName().isEmpty())
  1196. // avoid recursion in case of redundant scopes, i.e: namespace N { class N::C {}; }
  1197. // for this case doxygen assumes the exitance of a namespace N::N in which C is to be found!
  1198. // also avoid warning for stuff imported via a tagfile.
  1199. {
  1200. d->addInnerCompound(cd);
  1201. cd->setOuterScope(d);
  1202. warn(cd->getDefFileName(),cd->getDefLine(),
  1203. "Warning: Internal inconsistency: scope for class %s not "
  1204. "found!",name.data()
  1205. );
  1206. }
  1207. }
  1208. }
  1209. }
  1210. //----------------------------------------------------------------------
  1211. // build a list of all namespaces mentioned in the documentation
  1212. // and all namespaces that have a documentation block before their definition.
  1213. static void buildNamespaceList(EntryNav *rootNav)
  1214. {
  1215. if (
  1216. (rootNav->section()==Entry::NAMESPACE_SEC ||
  1217. rootNav->section()==Entry::NAMESPACEDOC_SEC ||
  1218. rootNav->section()==Entry::PACKAGEDOC_SEC
  1219. ) &&
  1220. !rootNav->name().isEmpty()
  1221. )
  1222. {
  1223. rootNav->loadEntry(g_storage);
  1224. Entry *root = rootNav->entry();
  1225. //printf("** buildNamespaceList(%s)\n",root->name.data());
  1226. QCString fName = root->name;
  1227. if (root->section==Entry::PACKAGEDOC_SEC)
  1228. {
  1229. fName=substitute(fName,".","::");
  1230. }
  1231. QCString fullName = stripAnonymousNamespaceScope(fName);
  1232. if (!fullName.isEmpty())
  1233. {
  1234. //printf("Found namespace %s in %s at line %d\n",root->name.data(),
  1235. // root->fileName.data(), root->startLine);
  1236. NamespaceDef *nd;
  1237. if ((nd=Doxygen::namespaceSDict->find(fullName))) // existing namespace
  1238. {
  1239. #if 0
  1240. if (!root->doc.isEmpty() || !root->brief.isEmpty()) // block contains docs
  1241. {
  1242. if (nd->documentation().isEmpty() && !root->doc.isEmpty())
  1243. {
  1244. #endif
  1245. nd->setDocumentation(root->doc,root->docFile,root->docLine);
  1246. nd->setName(fullName); // change name to match docs
  1247. nd->addSectionsToDefinition(root->anchors);
  1248. #if 0
  1249. }
  1250. else if (!nd->documentation().isEmpty() && !root->doc.isEmpty())
  1251. {
  1252. warn(
  1253. root->fileName,root->startLine,
  1254. "Warning: namespace %s already has a detailed description found in file %s at line %d. "
  1255. "Skipping the documentation found here.",
  1256. fullName.data(),nd->docFile().data(),nd->docLine());
  1257. }
  1258. if (nd->briefDescription().isEmpty() && !root->brief.isEmpty())
  1259. {
  1260. #endif
  1261. nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1262. #if 0
  1263. nd->setName(fullName); // change name to match docs
  1264. }
  1265. else if (!nd->briefDescription().isEmpty() && !root->brief.isEmpty())
  1266. {
  1267. warn(root->fileName,root->startLine,
  1268. "Warning: namespace %s already has a brief description found in file %s at line %d. "
  1269. "Skipping the documentation found here.",
  1270. fullName.data(),nd->docFile().data(),nd->docLine()
  1271. );
  1272. }
  1273. }
  1274. #endif
  1275. // file definition containing the namespace nd
  1276. FileDef *fd=rootNav->fileDef();
  1277. // insert the namespace in the file definition
  1278. if (fd) fd->insertNamespace(nd);
  1279. addNamespaceToGroups(root,nd);
  1280. nd->setRefItems(root->sli);
  1281. }
  1282. else // fresh namespace
  1283. {
  1284. QCString tagName;
  1285. QCString tagFileName;
  1286. if (rootNav->tagInfo())
  1287. {
  1288. tagName=rootNav->tagInfo()->tagName;
  1289. tagFileName=rootNav->tagInfo()->fileName;
  1290. }
  1291. //printf("++ new namespace %d\n",fullName.data());
  1292. NamespaceDef *nd=new NamespaceDef(root->fileName,root->startLine,fullName,tagName,tagFileName);
  1293. nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
  1294. nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1295. nd->addSectionsToDefinition(root->anchors);
  1296. nd->setHidden(root->hidden);
  1297. nd->setArtificial(root->artificial);
  1298. //printf("Adding namespace to group\n");
  1299. addNamespaceToGroups(root,nd);
  1300. nd->setRefItems(root->sli);
  1301. // file definition containing the namespace nd
  1302. FileDef *fd=rootNav->fileDef();
  1303. // insert the namespace in the file definition
  1304. if (fd) fd->insertNamespace(nd);
  1305. // the empty string test is needed for extract all case
  1306. nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1307. nd->insertUsedFile(root->fileName);
  1308. nd->setBodySegment(root->bodyLine,root->endBodyLine);
  1309. nd->setBodyDef(fd);
  1310. // add class to the list
  1311. Doxygen::namespaceSDict->inSort(fullName,nd);
  1312. // also add namespace to the correct structural context
  1313. Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,fullName);
  1314. //printf("adding namespace %s to context %s\n",nd->name().data(),d?d->name().data():"<none>");
  1315. if (d==0) // we didn't find anything, create the scope artificially
  1316. // anyway, so we can at least relate scopes properly.
  1317. {
  1318. Definition *d = buildScopeFromQualifiedName(fullName,fullName.contains("::"));
  1319. d->addInnerCompound(nd);
  1320. nd->setOuterScope(d);
  1321. // TODO: Due to the order in which the tag file is written
  1322. // a nested class can be found before its parent!
  1323. }
  1324. else
  1325. {
  1326. d->addInnerCompound(nd);
  1327. nd->setOuterScope(d);
  1328. }
  1329. }
  1330. }
  1331. rootNav->releaseEntry();
  1332. }
  1333. RECURSE_ENTRYTREE(buildNamespaceList,rootNav);
  1334. }
  1335. //----------------------------------------------------------------------
  1336. static NamespaceDef *findUsedNamespace(NamespaceSDict *unl,
  1337. const QCString &name)
  1338. {
  1339. NamespaceDef *usingNd =0;
  1340. if (unl)
  1341. {
  1342. //printf("Found namespace dict %d\n",unl->count());
  1343. NamespaceSDict::Iterator unli(*unl);
  1344. NamespaceDef *und;
  1345. for (unli.toFirst();(und=unli.current());++unli)
  1346. {
  1347. QCString uScope=und->name()+"::";
  1348. usingNd = getResolvedNamespace(uScope+name);
  1349. //printf("Also trying with scope=`%s' usingNd=%p\n",(uScope+name).data(),usingNd);
  1350. }
  1351. }
  1352. return usingNd;
  1353. }
  1354. static void findUsingDirectives(EntryNav *rootNav)
  1355. {
  1356. if (rootNav->section()==Entry::USINGDIR_SEC)
  1357. {
  1358. rootNav->loadEntry(g_storage);
  1359. Entry *root = rootNav->entry();
  1360. //printf("Found using directive %s at line %d of %s\n",
  1361. // root->name.data(),root->startLine,root->fileName.data());
  1362. QCString name=substitute(root->name,".","::");
  1363. if (!name.isEmpty())
  1364. {
  1365. NamespaceDef *usingNd = 0;
  1366. NamespaceDef *nd = 0;
  1367. FileDef *fd = rootNav->fileDef();
  1368. QCString nsName;
  1369. // see if the using statement was found inside a namespace or inside
  1370. // the global file scope.
  1371. if (rootNav->parent() && rootNav->parent()->section()==Entry::NAMESPACE_SEC &&
  1372. (fd==0 || !fd->isJava()) // not a .java file
  1373. )
  1374. {
  1375. nsName=stripAnonymousNamespaceScope(rootNav->parent()->name());
  1376. if (!nsName.isEmpty())
  1377. {
  1378. nd = getResolvedNamespace(nsName);
  1379. }
  1380. }
  1381. // find the scope in which the `using' namespace is defined by prepending
  1382. // the possible scopes in which the using statement was found, starting
  1383. // with the most inner scope and going to the most outer scope (i.e.
  1384. // file scope).
  1385. int scopeOffset = nsName.length();
  1386. do
  1387. {
  1388. QCString scope=scopeOffset>0 ?
  1389. nsName.left(scopeOffset)+"::" : QCString();
  1390. usingNd = getResolvedNamespace(scope+name);
  1391. //printf("Trying with scope=`%s' usingNd=%p\n",(scope+name).data(),usingNd);
  1392. if (scopeOffset==0)
  1393. {
  1394. scopeOffset=-1;
  1395. }
  1396. else if ((scopeOffset=nsName.findRev("::",scopeOffset-1))==-1)
  1397. {
  1398. scopeOffset=0;
  1399. }
  1400. } while (scopeOffset>=0 && usingNd==0);
  1401. if (usingNd==0 && nd) // not found, try used namespaces in this scope
  1402. // or in one of the parent namespace scopes
  1403. {
  1404. NamespaceDef *pnd = nd;
  1405. while (pnd && usingNd==0)
  1406. {
  1407. // also try with one of the used namespaces found earlier
  1408. usingNd = findUsedNamespace(pnd->getUsedNamespaces(),name);
  1409. // goto the parent
  1410. Definition *s = pnd->getOuterScope();
  1411. if (s && s->definitionType()==Definition::TypeNamespace)
  1412. {
  1413. pnd = (NamespaceDef*)s;
  1414. }
  1415. else
  1416. {
  1417. pnd = 0;
  1418. }
  1419. }
  1420. }
  1421. if (usingNd==0 && fd) // still nothing, also try used namespace in the
  1422. // global scope
  1423. {
  1424. usingNd = findUsedNamespace(fd->getUsedNamespaces(),name);
  1425. }
  1426. //printf("%s -> %s\n",name.data(),usingNd?usingNd->name().data():"<none>");
  1427. // add the namespace the correct scope
  1428. if (usingNd)
  1429. {
  1430. //printf("using fd=%p nd=%p\n",fd,nd);
  1431. if (nd)
  1432. {
  1433. //printf("Inside namespace %s\n",nd->name().data());
  1434. nd->addUsingDirective(usingNd);
  1435. }
  1436. else if (fd)
  1437. {
  1438. //printf("Inside file %s\n",fd->name().data());
  1439. fd->addUsingDirective(usingNd);
  1440. }
  1441. }
  1442. else // unknown namespace, but add it anyway.
  1443. {
  1444. //printf("++ new unknown namespace %s\n",name.data());
  1445. NamespaceDef *nd=new NamespaceDef(root->fileName,root->startLine,name);
  1446. nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
  1447. nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1448. nd->addSectionsToDefinition(root->anchors);
  1449. //printf("** Adding namespace %s hidden=%d\n",name.data(),root->hidden);
  1450. nd->setHidden(root->hidden);
  1451. nd->setArtificial(TRUE);
  1452. QListIterator<Grouping> gli(*root->groups);
  1453. Grouping *g;
  1454. for (;(g=gli.current());++gli)
  1455. {
  1456. GroupDef *gd=0;
  1457. if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
  1458. gd->addNamespace(nd);
  1459. }
  1460. // insert the namespace in the file definition
  1461. if (fd)
  1462. {
  1463. fd->insertNamespace(nd);
  1464. fd->addUsingDirective(nd);
  1465. }
  1466. // the empty string test is needed for extract all case
  1467. nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1468. nd->insertUsedFile(root->fileName);
  1469. // add class to the list
  1470. Doxygen::namespaceSDict->inSort(name,nd);
  1471. nd->setRefItems(root->sli);
  1472. }
  1473. }
  1474. rootNav->releaseEntry();
  1475. }
  1476. RECURSE_ENTRYTREE(findUsingDirectives,rootNav);
  1477. }
  1478. //----------------------------------------------------------------------
  1479. static void buildListOfUsingDecls(EntryNav *rootNav)
  1480. {
  1481. if (rootNav->section()==Entry::USINGDECL_SEC &&
  1482. !(rootNav->parent()->section()&Entry::COMPOUND_MASK) // not a class/struct member
  1483. )
  1484. {
  1485. rootNav->loadEntry(g_storage);
  1486. Entry *root = rootNav->entry();
  1487. QCString name = substitute(root->name,".","::");
  1488. if (g_usingDeclarations.find(name)==0)
  1489. {
  1490. FileDef *fd = rootNav->fileDef();
  1491. if (fd)
  1492. {
  1493. g_usingDeclarations.insert(name,fd);
  1494. }
  1495. }
  1496. rootNav->releaseEntry();
  1497. }
  1498. RECURSE_ENTRYTREE(buildListOfUsingDecls,rootNav);
  1499. }
  1500. static void findUsingDeclarations(EntryNav *rootNav)
  1501. {
  1502. if (rootNav->section()==Entry::USINGDECL_SEC &&
  1503. !(rootNav->parent()->section()&Entry::COMPOUND_MASK) // not a class/struct member
  1504. )
  1505. {
  1506. rootNav->loadEntry(g_storage);
  1507. Entry *root = rootNav->entry();
  1508. //printf("Found using declaration %s at line %d of %s inside section %x\n",
  1509. // root->name.data(),root->startLine,root->fileName.data(),
  1510. // rootNav->parent()->section());
  1511. if (!root->name.isEmpty())
  1512. {
  1513. ClassDef *usingCd = 0;
  1514. NamespaceDef *nd = 0;
  1515. FileDef *fd = rootNav->fileDef();
  1516. QCString scName;
  1517. // see if the using statement was found inside a namespace or inside
  1518. // the global file scope.
  1519. if (rootNav->parent()->section() == Entry::NAMESPACE_SEC)
  1520. {
  1521. scName=rootNav->parent()->name();
  1522. if (!scName.isEmpty())
  1523. {
  1524. nd = getResolvedNamespace(scName);
  1525. }
  1526. }
  1527. // Assume the using statement was used to import a class.
  1528. // Find the scope in which the `using' namespace is defined by prepending
  1529. // the possible scopes in which the using statement was found, starting
  1530. // with the most inner scope and going to the most outer scope (i.e.
  1531. // file scope).
  1532. QCString name = substitute(root->name,".","::"); //Java/C# scope->internal
  1533. usingCd = getClass(name);
  1534. if (usingCd==0)
  1535. {
  1536. usingCd = Doxygen::hiddenClasses->find(name);
  1537. }
  1538. //printf("%s -> %p\n",root->name.data(),usingCd);
  1539. if (usingCd==0) // definition not in the input => add an artificial class
  1540. {
  1541. Debug::print(Debug::Classes,0," New using class `%s' (sec=0x%08x)! #tArgLists=%d\n",
  1542. name.data(),root->section,root->tArgLists ? (int)root->tArgLists->count() : -1);
  1543. usingCd = new ClassDef(
  1544. "<using>",1,
  1545. name,ClassDef::Class);
  1546. Doxygen::hiddenClasses->append(root->name,usingCd);
  1547. usingCd->setArtificial(TRUE);
  1548. }
  1549. else
  1550. {
  1551. Debug::print(Debug::Classes,0," Found used class %s in scope=%s\n",
  1552. usingCd->name().data(),nd?nd->name().data():fd->name().data());
  1553. }
  1554. if (usingCd) // add the class to the correct scope
  1555. {
  1556. if (nd)
  1557. {
  1558. //printf("Inside namespace %s\n",nd->name().data());
  1559. nd->addUsingDeclaration(usingCd);
  1560. }
  1561. else if (fd)
  1562. {
  1563. //printf("Inside file %s\n",fd->name().data());
  1564. fd->addUsingDeclaration(usingCd);
  1565. }
  1566. }
  1567. }
  1568. rootNav->releaseEntry();
  1569. }
  1570. RECURSE_ENTRYTREE(findUsingDeclarations,rootNav);
  1571. }
  1572. //----------------------------------------------------------------------
  1573. static void findUsingDeclImports(EntryNav *rootNav)
  1574. {
  1575. if (rootNav->section()==Entry::USINGDECL_SEC &&
  1576. (rootNav->parent()->section()&Entry::COMPOUND_MASK) // in a class/struct member
  1577. )
  1578. {
  1579. //printf("Found using declaration %s at line %d of %s inside section %x\n",
  1580. // root->name.data(),root->startLine,root->fileName.data(),
  1581. // root->parent->section);
  1582. QCString fullName=removeRedundantWhiteSpace(rootNav->parent()->name());
  1583. fullName=stripAnonymousNamespaceScope(fullName);
  1584. fullName=stripTemplateSpecifiersFromScope(fullName);
  1585. ClassDef *cd = getClass(fullName);
  1586. if (cd)
  1587. {
  1588. //printf("found class %s\n",cd->name().data());
  1589. int i=rootNav->name().find("::");
  1590. if (i!=-1)
  1591. {
  1592. QCString scope=rootNav->name().left(i);
  1593. QCString memName=rootNav->name().right(rootNav->name().length()-i-2);
  1594. ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter
  1595. if (bcd)
  1596. {
  1597. //printf("found class %s\n",bcd->name().data());
  1598. MemberNameInfoSDict *mndict=bcd->memberNameInfoSDict();
  1599. if (mndict)
  1600. {
  1601. MemberNameInfo *mni = mndict->find(memName);
  1602. if (mni)
  1603. {
  1604. MemberNameInfoIterator mnii(*mni);
  1605. MemberInfo *mi;
  1606. for ( ; (mi=mnii.current()) ; ++mnii )
  1607. {
  1608. MemberDef *md = mi->memberDef;
  1609. if (md && md->protection()!=Private)
  1610. {
  1611. rootNav->loadEntry(g_storage);
  1612. Entry *root = rootNav->entry();
  1613. //printf("found member %s\n",mni->memberName());
  1614. MemberDef *newMd = 0;
  1615. {
  1616. LockingPtr<ArgumentList> templAl = md->templateArguments();
  1617. LockingPtr<ArgumentList> al = md->templateArguments();
  1618. newMd = new MemberDef(
  1619. root->fileName,root->startLine,
  1620. md->typeString(),memName,md->argsString(),
  1621. md->excpString(),root->protection,root->virt,
  1622. md->isStatic(),Member,md->memberType(),
  1623. templAl.pointer(),al.pointer()
  1624. );
  1625. }
  1626. newMd->setMemberClass(cd);
  1627. cd->insertMember(newMd);
  1628. if (!root->doc.isEmpty() || !root->brief.isEmpty())
  1629. {
  1630. newMd->setDocumentation(root->doc,root->docFile,root->docLine);
  1631. newMd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1632. newMd->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  1633. }
  1634. else
  1635. {
  1636. newMd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
  1637. newMd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
  1638. newMd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine());
  1639. }
  1640. newMd->setDefinition(md->definition());
  1641. newMd->enableCallGraph(root->callGraph);
  1642. newMd->enableCallerGraph(root->callerGraph);
  1643. newMd->setBitfields(md->bitfieldString());
  1644. newMd->addSectionsToDefinition(root->anchors);
  1645. newMd->setBodySegment(md->getStartBodyLine(),md->getEndBodyLine());
  1646. newMd->setBodyDef(md->getBodyDef());
  1647. newMd->setInitializer(md->initializer());
  1648. newMd->setMaxInitLines(md->initializerLines());
  1649. newMd->setMemberGroupId(root->mGrpId);
  1650. newMd->setMemberSpecifiers(md->getMemberSpecifiers());
  1651. rootNav->releaseEntry();
  1652. }
  1653. }
  1654. }
  1655. }
  1656. }
  1657. }
  1658. }
  1659. }
  1660. RECURSE_ENTRYTREE(findUsingDeclImports,rootNav);
  1661. }
  1662. //----------------------------------------------------------------------
  1663. static void findIncludedUsingDirectives()
  1664. {
  1665. // first mark all files as not visited
  1666. FileNameListIterator fnli(*Doxygen::inputNameList);
  1667. FileName *fn;
  1668. for (fnli.toFirst();(fn=fnli.current());++fnli)
  1669. {
  1670. FileNameIterator fni(*fn);
  1671. FileDef *fd;
  1672. for (;(fd=fni.current());++fni)
  1673. {
  1674. fd->visited=FALSE;
  1675. }
  1676. }
  1677. // then recursively add using directives found in #include files
  1678. // to files that have not been visited.
  1679. for (fnli.toFirst();(fn=fnli.current());++fnli)
  1680. {
  1681. FileNameIterator fni(*fn);
  1682. FileDef *fd;
  1683. for (fni.toFirst();(fd=fni.current());++fni)
  1684. {
  1685. if (!fd->visited)
  1686. {
  1687. //printf("----- adding using directives for file %s\n",fd->name().data());
  1688. fd->addIncludedUsingDirectives();
  1689. }
  1690. }
  1691. }
  1692. }
  1693. //----------------------------------------------------------------------
  1694. static MemberDef *addVariableToClass(
  1695. EntryNav *rootNav,
  1696. ClassDef *cd,
  1697. MemberDef::MemberType mtype,
  1698. const QCString &name,
  1699. bool fromAnnScope,
  1700. MemberDef *fromAnnMemb,
  1701. Protection prot,
  1702. Relationship related)
  1703. {
  1704. Entry *root = rootNav->entry();
  1705. QCString qualScope = cd->qualifiedNameWithTemplateParameters();
  1706. QCString scopeSeparator="::";
  1707. if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
  1708. {
  1709. qualScope = substitute(qualScope,"::",".");
  1710. scopeSeparator=".";
  1711. }
  1712. Debug::print(Debug::Variables,0,
  1713. " class variable:\n"
  1714. " `%s' `%s'::`%s' `%s' prot=`%d ann=%d init=`%s'\n",
  1715. root->type.data(),
  1716. qualScope.data(),
  1717. name.data(),
  1718. root->args.data(),
  1719. root->protection,
  1720. fromAnnScope,
  1721. root->initializer.data()
  1722. );
  1723. QCString def;
  1724. if (!root->type.isEmpty())
  1725. {
  1726. if (related || mtype==MemberDef::Friend || Config_getBool("HIDE_SCOPE_NAMES"))
  1727. {
  1728. def=root->type+" "+name+root->args;
  1729. }
  1730. else
  1731. {
  1732. def=root->type+" "+qualScope+scopeSeparator+name+root->args;
  1733. }
  1734. }
  1735. else
  1736. {
  1737. if (Config_getBool("HIDE_SCOPE_NAMES"))
  1738. {
  1739. def=name+root->args;
  1740. }
  1741. else
  1742. {
  1743. def=qualScope+scopeSeparator+name+root->args;
  1744. }
  1745. }
  1746. def.stripPrefix("static ");
  1747. // see if the member is already found in the same scope
  1748. // (this may be the case for a static member that is initialized
  1749. // outside the class)
  1750. MemberName *mn=Doxygen::memberNameSDict->find(name);
  1751. if (mn)
  1752. {
  1753. MemberNameIterator mni(*mn);
  1754. MemberDef *md;
  1755. for (mni.toFirst();(md=mni.current());++mni)
  1756. {
  1757. //printf("md->getClassDef()=%p cd=%p type=[%s] md->typeString()=[%s]\n",
  1758. // md->getClassDef(),cd,root->type.data(),md->typeString());
  1759. if (md->getClassDef()==cd &&
  1760. removeRedundantWhiteSpace(root->type)==md->typeString())
  1761. // member already in the scope
  1762. {
  1763. if (root->objc &&
  1764. root->mtype==Property &&
  1765. md->memberType()==MemberDef::Variable)
  1766. { // Objective-C 2.0 property
  1767. // turn variable into a property
  1768. md->setProtection(root->protection);
  1769. cd->reclassifyMember(md,MemberDef::Property);
  1770. }
  1771. addMemberDocs(rootNav,md,def,0,FALSE);
  1772. //printf(" Member already found!\n");
  1773. return md;
  1774. }
  1775. }
  1776. }
  1777. // new member variable, typedef or enum value
  1778. MemberDef *md=new MemberDef(
  1779. root->fileName,root->startLine,
  1780. root->type,name,root->args,0,
  1781. prot,Normal,root->stat,related,
  1782. mtype,0,0);
  1783. md->setTagInfo(rootNav->tagInfo());
  1784. md->setMemberClass(cd); // also sets outer scope (i.e. getOuterScope())
  1785. //md->setDefFile(root->fileName);
  1786. //md->setDefLine(root->startLine);
  1787. md->setDocumentation(root->doc,root->docFile,root->docLine);
  1788. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1789. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  1790. md->setDefinition(def);
  1791. md->setBitfields(root->bitfields);
  1792. md->addSectionsToDefinition(root->anchors);
  1793. md->setFromAnonymousScope(fromAnnScope);
  1794. md->setFromAnonymousMember(fromAnnMemb);
  1795. //md->setIndentDepth(indentDepth);
  1796. md->setBodySegment(root->bodyLine,root->endBodyLine);
  1797. md->setInitializer(root->initializer);
  1798. md->setMaxInitLines(root->initLines);
  1799. md->setMemberGroupId(root->mGrpId);
  1800. md->setMemberSpecifiers(root->spec);
  1801. md->setReadAccessor(root->read);
  1802. md->setWriteAccessor(root->write);
  1803. md->enableCallGraph(root->callGraph);
  1804. md->enableCallerGraph(root->callerGraph);
  1805. md->setHidden(root->hidden);
  1806. md->setArtificial(root->artificial);
  1807. addMemberToGroups(root,md);
  1808. //if (root->mGrpId!=-1)
  1809. //{
  1810. // printf("memberdef %s in memberGroup %d\n",name.data(),root->mGrpId);
  1811. // md->setMemberGroup(memberGroupDict[root->mGrpId]);
  1812. //
  1813. md->setBodyDef(rootNav->fileDef());
  1814. //printf(" Adding member=%s\n",md->name().data());
  1815. // add the member to the global list
  1816. if (mn)
  1817. {
  1818. mn->append(md);
  1819. }
  1820. else // new variable name
  1821. {
  1822. mn = new MemberName(name);
  1823. mn->append(md);
  1824. //printf("Adding memberName=%s\n",mn->memberName());
  1825. //Doxygen::memberNameDict.insert(name,mn);
  1826. //Doxygen::memberNameList.append(mn);
  1827. Doxygen::memberNameSDict->append(name,mn);
  1828. // add the member to the class
  1829. }
  1830. //printf(" New member adding to %s (%p)!\n",cd->name().data(),cd);
  1831. cd->insertMember(md);
  1832. md->setRefItems(root->sli);
  1833. //TODO: insert FileDef instead of filename strings.
  1834. cd->insertUsedFile(root->fileName);
  1835. rootNav->changeSection(Entry::EMPTY_SEC);
  1836. return md;
  1837. }
  1838. //----------------------------------------------------------------------
  1839. static MemberDef *addVariableToFile(
  1840. EntryNav *rootNav,
  1841. MemberDef::MemberType mtype,
  1842. const QCString &scope,
  1843. const QCString &name,
  1844. bool fromAnnScope,
  1845. /*int indentDepth,*/
  1846. MemberDef *fromAnnMemb)
  1847. {
  1848. Entry *root = rootNav->entry();
  1849. Debug::print(Debug::Variables,0,
  1850. " global variable:\n"
  1851. " type=`%s' scope=`%s' name=`%s' args=`%s' prot=`%d mtype=%d\n",
  1852. root->type.data(),
  1853. scope.data(),
  1854. name.data(),
  1855. root->args.data(),
  1856. root->protection,
  1857. mtype
  1858. );
  1859. FileDef *fd = rootNav->fileDef();
  1860. // see if we have a typedef that should hide a struct or union
  1861. if (mtype==MemberDef::Typedef && Config_getBool("TYPEDEF_HIDES_STRUCT"))
  1862. {
  1863. QCString type = root->type;
  1864. type.stripPrefix("typedef ");
  1865. if (type.left(7)=="struct " || type.left(6)=="union ")
  1866. {
  1867. type.stripPrefix("struct ");
  1868. type.stripPrefix("union ");
  1869. static QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*");
  1870. int l,s;
  1871. s = re.match(type,0,&l);
  1872. if (s>=0)
  1873. {
  1874. QCString typeValue = type.mid(s,l);
  1875. ClassDef *cd = getClass(typeValue);
  1876. if (cd)
  1877. {
  1878. // this typedef should hide compound name cd, so we
  1879. // change the name that is displayed from cd.
  1880. cd->setClassName(name);
  1881. cd->setDocumentation(root->doc,root->docFile,root->docLine);
  1882. cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1883. return 0;
  1884. }
  1885. }
  1886. }
  1887. }
  1888. // see if the function is inside a namespace
  1889. NamespaceDef *nd = 0;
  1890. QCString nscope;
  1891. if (!scope.isEmpty())
  1892. {
  1893. if (scope.find('@')!=-1) return 0; // anonymous scope!
  1894. //nscope=removeAnonymousScopes(scope);
  1895. //if (!nscope.isEmpty())
  1896. //{
  1897. nd = getResolvedNamespace(scope);
  1898. //}
  1899. }
  1900. QCString def;
  1901. // determine the definition of the global variable
  1902. if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@' &&
  1903. !Config_getBool("HIDE_SCOPE_NAMES")
  1904. )
  1905. // variable is inside a namespace, so put the scope before the name
  1906. {
  1907. static bool optimizeForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
  1908. QCString sep="::";
  1909. if (optimizeForJava) sep=".";
  1910. if (!root->type.isEmpty())
  1911. {
  1912. def=root->type+" "+nd->name()+sep+name+root->args;
  1913. }
  1914. else
  1915. {
  1916. def=nd->name()+sep+name+root->args;
  1917. }
  1918. }
  1919. else
  1920. {
  1921. if (!root->type.isEmpty() && !root->name.isEmpty())
  1922. {
  1923. if (name.at(0)=='@') // dummy variable representing annonymous union
  1924. def=root->type;
  1925. else
  1926. def=root->type+" "+name+root->args;
  1927. }
  1928. else
  1929. {
  1930. def=name+root->args;
  1931. }
  1932. }
  1933. def.stripPrefix("static ");
  1934. MemberName *mn=Doxygen::functionNameSDict->find(name);
  1935. if (mn)
  1936. {
  1937. //QCString nscope=removeAnonymousScopes(scope);
  1938. //NamespaceDef *nd=0;
  1939. //if (!nscope.isEmpty())
  1940. if (!scope.isEmpty())
  1941. {
  1942. nd = getResolvedNamespace(scope);
  1943. }
  1944. MemberNameIterator mni(*mn);
  1945. MemberDef *md;
  1946. for (mni.toFirst();(md=mni.current());++mni)
  1947. {
  1948. if (
  1949. ((nd==0 && md->getNamespaceDef()==0 && md->getFileDef() &&
  1950. root->fileName==md->getFileDef()->absFilePath()
  1951. ) // both variable names in the same file
  1952. || (nd!=0 && md->getNamespaceDef()==nd) // both in same namespace
  1953. )
  1954. && !md->isDefine() // function style #define's can be "overloaded" by typedefs or variables
  1955. && !md->isEnumerate() // in C# an enum value and enum can have the same name
  1956. )
  1957. // variable already in the scope
  1958. {
  1959. if (md->getFileDef() &&
  1960. ! // not a php array
  1961. (
  1962. (getLanguageFromFileName(md->getFileDef()->name())==SrcLangExt_PHP) &&
  1963. (md->argsString()!=root->args && root->args.find('[')!=-1)
  1964. )
  1965. )
  1966. // not a php array variable
  1967. {
  1968. Debug::print(Debug::Variables,0,
  1969. " variable already found: scope=%s\n",md->getOuterScope()->name().data());
  1970. addMemberDocs(rootNav,md,def,0,FALSE);
  1971. md->setRefItems(root->sli);
  1972. return md;
  1973. }
  1974. }
  1975. }
  1976. }
  1977. Debug::print(Debug::Variables,0,
  1978. " new variable, nd=%s!\n",nd?nd->name().data():"<global>");
  1979. // new global variable, enum value or typedef
  1980. MemberDef *md=new MemberDef(
  1981. root->fileName,root->startLine,
  1982. root->type,name,root->args,0,
  1983. Public, Normal,root->stat,Member,
  1984. mtype,0,0);
  1985. md->setTagInfo(rootNav->tagInfo());
  1986. md->setDocumentation(root->doc,root->docFile,root->docLine);
  1987. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  1988. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  1989. md->addSectionsToDefinition(root->anchors);
  1990. md->setFromAnonymousScope(fromAnnScope);
  1991. md->setFromAnonymousMember(fromAnnMemb);
  1992. md->setInitializer(root->initializer);
  1993. md->setMaxInitLines(root->initLines);
  1994. md->setMemberGroupId(root->mGrpId);
  1995. md->setDefinition(def);
  1996. md->enableCallGraph(root->callGraph);
  1997. md->enableCallerGraph(root->callerGraph);
  1998. md->setExplicitExternal(root->explicitExternal);
  1999. //md->setOuterScope(fd);
  2000. if (!root->explicitExternal)
  2001. {
  2002. md->setBodySegment(root->bodyLine,root->endBodyLine);
  2003. md->setBodyDef(fd);
  2004. }
  2005. addMemberToGroups(root,md);
  2006. md->setRefItems(root->sli);
  2007. if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
  2008. {
  2009. md->setNamespace(nd);
  2010. nd->insertMember(md);
  2011. }
  2012. // add member to the file (we do this even if we have already inserted
  2013. // it into the namespace.
  2014. if (fd)
  2015. {
  2016. md->setFileDef(fd);
  2017. fd->insertMember(md);
  2018. }
  2019. // add member definition to the list of globals
  2020. if (mn)
  2021. {
  2022. mn->append(md);
  2023. }
  2024. else
  2025. {
  2026. mn = new MemberName(name);
  2027. mn->append(md);
  2028. Doxygen::functionNameSDict->append(name,mn);
  2029. }
  2030. rootNav->changeSection(Entry::EMPTY_SEC);
  2031. return md;
  2032. }
  2033. /*! See if the return type string \a type is that of a function pointer
  2034. * \returns -1 if this is not a function pointer variable or
  2035. * the index at which the brace of (...*name) was found.
  2036. */
  2037. static int findFunctionPtr(const QCString &type,int *pLength=0)
  2038. {
  2039. static const QRegExp re("([^)]*\\*[^)]*)");
  2040. int i=-1,l;
  2041. if (!type.isEmpty() && // return type is non-empty
  2042. (i=re.match(type,0,&l))!=-1 && // contains (...*...)
  2043. type.find("operator")==-1 && // not an operator
  2044. (type.find(")(")==-1 || type.find("typedef ")!=-1)
  2045. // not a function pointer return type
  2046. )
  2047. {
  2048. if (pLength) *pLength=l;
  2049. return i;
  2050. }
  2051. else
  2052. {
  2053. return -1;
  2054. }
  2055. }
  2056. /*! Returns TRUE iff \a type is a class within scope \a context.
  2057. * Used to detect variable declarations that look like function prototypes.
  2058. */
  2059. static bool isVarWithConstructor(EntryNav *rootNav)
  2060. {
  2061. static QRegExp initChars("[0-9\"'&*!^]+");
  2062. static QRegExp idChars("[a-z_A-Z][a-z_A-Z0-9]*");
  2063. bool result=FALSE;
  2064. bool typeIsClass;
  2065. QCString type;
  2066. Definition *ctx = 0;
  2067. FileDef *fd = 0;
  2068. int ti;
  2069. //printf("isVarWithConstructor(%s)\n",rootNav->name().data());
  2070. rootNav->loadEntry(g_storage);
  2071. Entry *root = rootNav->entry();
  2072. if (rootNav->parent()->section() & Entry::COMPOUND_MASK)
  2073. { // inside a class
  2074. result=FALSE;
  2075. goto done;
  2076. }
  2077. else if ((fd = rootNav->fileDef()) &&
  2078. (fd->name().right(2)==".c" || fd->name().right(2)==".h")
  2079. )
  2080. { // inside a .c file
  2081. result=FALSE;
  2082. goto done;
  2083. }
  2084. if (root->type.isEmpty())
  2085. {
  2086. result=FALSE;
  2087. goto done;
  2088. }
  2089. if (!rootNav->parent()->name().isEmpty())
  2090. {
  2091. ctx=Doxygen::namespaceSDict->find(rootNav->parent()->name());
  2092. }
  2093. type = root->type;
  2094. // remove qualifiers
  2095. findAndRemoveWord(type,"const");
  2096. findAndRemoveWord(type,"static");
  2097. findAndRemoveWord(type,"volatile");
  2098. //if (type.left(6)=="const ") type=type.right(type.length()-6);
  2099. typeIsClass=getResolvedClass(ctx,fd,type)!=0;
  2100. if (!typeIsClass && (ti=type.find('<'))!=-1)
  2101. {
  2102. typeIsClass=getResolvedClass(ctx,fd,type.left(ti))!=0;
  2103. }
  2104. if (typeIsClass) // now we still have to check if the arguments are
  2105. // types or values. Since we do not have complete type info
  2106. // we need to rely on heuristics :-(
  2107. {
  2108. //printf("typeIsClass\n");
  2109. ArgumentList *al = root->argList;
  2110. if (al==0 || al->isEmpty())
  2111. {
  2112. result=FALSE; // empty arg list -> function prototype.
  2113. goto done;
  2114. }
  2115. ArgumentListIterator ali(*al);
  2116. Argument *a;
  2117. for (ali.toFirst();(a=ali.current());++ali)
  2118. {
  2119. if (!a->name.isEmpty() || !a->defval.isEmpty())
  2120. {
  2121. if (a->name.find(initChars)==0)
  2122. {
  2123. result=TRUE;
  2124. }
  2125. else
  2126. {
  2127. result=FALSE; // arg has (type,name) pair -> function prototype
  2128. }
  2129. goto done;
  2130. }
  2131. if (a->type.isEmpty() || getResolvedClass(ctx,fd,a->type)!=0)
  2132. {
  2133. result=FALSE; // arg type is a known type
  2134. goto done;
  2135. }
  2136. if (checkIfTypedef(ctx,fd,a->type))
  2137. {
  2138. //printf("%s:%d: false (arg is typedef)\n",__FILE__,__LINE__);
  2139. result=FALSE; // argument is a typedef
  2140. goto done;
  2141. }
  2142. if (a->type.at(a->type.length()-1)=='*' ||
  2143. a->type.at(a->type.length()-1)=='&')
  2144. // type ends with * or & => pointer or reference
  2145. {
  2146. result=FALSE;
  2147. goto done;
  2148. }
  2149. if (a->type.find(initChars)==0)
  2150. {
  2151. result=TRUE; // argument type starts with typical initializer char
  2152. goto done;
  2153. }
  2154. QCString resType=resolveTypeDef(ctx,a->type);
  2155. if (resType.isEmpty()) resType=a->type;
  2156. int len;
  2157. if (idChars.match(resType,0,&len)==0) // resType starts with identifier
  2158. {
  2159. resType=resType.left(len);
  2160. //printf("resType=%s\n",resType.data());
  2161. if (resType=="int" || resType=="long" || resType=="float" ||
  2162. resType=="double" || resType=="char" || resType=="signed" ||
  2163. resType=="const" || resType=="unsigned" || resType=="void")
  2164. {
  2165. result=FALSE; // type keyword -> function prototype
  2166. goto done;
  2167. }
  2168. }
  2169. }
  2170. result=TRUE;
  2171. }
  2172. done:
  2173. //printf("isVarWithConstructor(%s,%s)=%d\n",rootNav->parent()->name().data(),
  2174. // root->type.data(),result);
  2175. rootNav->releaseEntry();
  2176. return result;
  2177. }
  2178. static void addVariable(EntryNav *rootNav,int isFuncPtr=-1)
  2179. {
  2180. rootNav->loadEntry(g_storage);
  2181. Entry *root = rootNav->entry();
  2182. Debug::print(Debug::Variables,0,
  2183. "VARIABLE_SEC: \n"
  2184. " type=`%s' name=`%s' args=`%s' bodyLine=`%d' mGrpId=%d\n",
  2185. root->type.data(),
  2186. root->name.data(),
  2187. root->args.data(),
  2188. root->bodyLine,
  2189. root->mGrpId
  2190. );
  2191. //printf("root->parent->name=%s\n",root->parent->name.data());
  2192. if (root->type.isEmpty() && root->name.find("operator")==-1 &&
  2193. (root->name.find('*')!=-1 || root->name.find('&')!=-1))
  2194. {
  2195. // recover from parse error caused by redundant braces
  2196. // like in "int *(var[10]);", which is parsed as
  2197. // type="" name="int *" args="(var[10])"
  2198. root->type=root->name;
  2199. static const QRegExp reName("[a-z_A-Z][a-z_A-Z0-9]*");
  2200. int l;
  2201. int i=root->args.isEmpty() ? -1 : reName.match(root->args,0,&l);
  2202. root->name=root->args.mid(i,l);
  2203. root->args=root->args.mid(i+l,root->args.find(')',i+l)-i-l);
  2204. //printf("new: type=`%s' name=`%s' args=`%s'\n",
  2205. // root->type.data(),root->name.data(),root->args.data());
  2206. }
  2207. else
  2208. {
  2209. int i=isFuncPtr;
  2210. if (i==-1) i=findFunctionPtr(root->type); // for typedefs isFuncPtr is not yet set
  2211. if (i!=-1) // function pointer
  2212. {
  2213. int ai = root->type.find('[',i);
  2214. if (ai>i) // function pointer array
  2215. {
  2216. root->args.prepend(root->type.right(root->type.length()-ai));
  2217. root->type=root->type.left(ai);
  2218. }
  2219. else if (root->type.find(')',i)!=-1) // function ptr, not variable like "int (*bla)[10]"
  2220. {
  2221. root->type=root->type.left(root->type.length()-1);
  2222. root->args.prepend(")");
  2223. //printf("root->type=%s root->args=%s\n",root->type.data(),root->args.data());
  2224. }
  2225. }
  2226. else if (root->type.find("typedef ")!=-1 && root->type.right(2)=="()") // typedef void (func)(int)
  2227. {
  2228. root->type=root->type.left(root->type.length()-1);
  2229. root->args.prepend(")");
  2230. }
  2231. }
  2232. QCString scope,name=removeRedundantWhiteSpace(root->name);
  2233. // find the scope of this variable
  2234. EntryNav *p = rootNav->parent();
  2235. while ((p->section() & Entry::SCOPE_MASK))
  2236. {
  2237. QCString scopeName = p->name();
  2238. if (!scopeName.isEmpty())
  2239. {
  2240. scope.prepend(scopeName);
  2241. break;
  2242. }
  2243. p=p->parent();
  2244. }
  2245. MemberDef::MemberType mtype;
  2246. QCString type=root->type.stripWhiteSpace();
  2247. ClassDef *cd=0;
  2248. bool isRelated=FALSE;
  2249. bool isMemberOf=FALSE;
  2250. QCString classScope=stripAnonymousNamespaceScope(scope);
  2251. classScope=stripTemplateSpecifiersFromScope(classScope,FALSE);
  2252. QCString annScopePrefix=scope.left(scope.length()-classScope.length());
  2253. if (root->name.findRev("::")!=-1)
  2254. {
  2255. if (root->type=="friend class" || root->type=="friend struct" ||
  2256. root->type=="friend union")
  2257. {
  2258. cd=getClass(scope);
  2259. if (cd)
  2260. {
  2261. addVariableToClass(rootNav, // entry
  2262. cd, // class to add member to
  2263. MemberDef::Friend, // type of member
  2264. name, // name of the member
  2265. FALSE, // from Anonymous scope
  2266. 0, // anonymous member
  2267. Public, // protection
  2268. Member // related to a class
  2269. );
  2270. }
  2271. }
  2272. goto nextMember;
  2273. /* skip this member, because it is a
  2274. * static variable definition (always?), which will be
  2275. * found in a class scope as well, but then we know the
  2276. * correct protection level, so only then it will be
  2277. * inserted in the correct list!
  2278. */
  2279. }
  2280. if (type=="@")
  2281. mtype=MemberDef::EnumValue;
  2282. else if (type.left(8)=="typedef ")
  2283. mtype=MemberDef::Typedef;
  2284. else if (type.left(7)=="friend ")
  2285. mtype=MemberDef::Friend;
  2286. else if (root->mtype==Property)
  2287. mtype=MemberDef::Property;
  2288. else if (root->mtype==Event)
  2289. mtype=MemberDef::Event;
  2290. else
  2291. mtype=MemberDef::Variable;
  2292. if (!root->relates.isEmpty()) // related variable
  2293. {
  2294. isRelated=TRUE;
  2295. isMemberOf=(root->relatesType == MemberOf);
  2296. if (getClass(root->relates)==0 && !scope.isEmpty())
  2297. scope=mergeScopes(scope,root->relates);
  2298. else
  2299. scope=root->relates;
  2300. }
  2301. cd=getClass(scope);
  2302. if (cd==0 && classScope!=scope) cd=getClass(classScope);
  2303. if (cd)
  2304. {
  2305. MemberDef *md=0;
  2306. // if cd is an annonymous scope we insert the member
  2307. // into a non-annonymous scope as well. This is needed to
  2308. // be able to refer to it using \var or \fn
  2309. //int indentDepth=0;
  2310. int si=scope.find('@');
  2311. //int anonyScopes = 0;
  2312. bool added=FALSE;
  2313. if (si!=-1) // anonymous scope
  2314. {
  2315. QCString pScope;
  2316. ClassDef *pcd=0;
  2317. pScope = scope.left(QMAX(si-2,0));
  2318. if (!pScope.isEmpty())
  2319. pScope.prepend(annScopePrefix);
  2320. else if (annScopePrefix.length()>2)
  2321. pScope=annScopePrefix.left(annScopePrefix.length()-2);
  2322. if (name.at(0)!='@')
  2323. {
  2324. if (!pScope.isEmpty() && (pcd=getClass(pScope)))
  2325. {
  2326. md=addVariableToClass(rootNav, // entry
  2327. pcd, // class to add member to
  2328. mtype, // member type
  2329. name, // member name
  2330. TRUE, // from anonymous scope
  2331. 0, // from anonymous member
  2332. root->protection,
  2333. isMemberOf ? Foreign : isRelated ? Related : Member
  2334. );
  2335. added=TRUE;
  2336. }
  2337. else // anonymous scope inside namespace or file => put variable in the global scope
  2338. {
  2339. if (mtype==MemberDef::Variable)
  2340. {
  2341. md=addVariableToFile(rootNav,mtype,pScope,name,TRUE,0);
  2342. }
  2343. added=TRUE;
  2344. }
  2345. }
  2346. }
  2347. //printf("name=`%s' scope=%s scope.right=%s\n",
  2348. // name.data(),scope.data(),
  2349. // scope.right(scope.length()-si).data());
  2350. addVariableToClass(rootNav, // entry
  2351. cd, // class to add member to
  2352. mtype, // member type
  2353. name, // name of the member
  2354. FALSE, // from anonymous scope
  2355. md, // from anonymous member
  2356. root->protection,
  2357. isMemberOf ? Foreign : isRelated ? Related : Member);
  2358. }
  2359. else if (!name.isEmpty()) // global variable
  2360. {
  2361. //printf("Inserting member in global scope %s!\n",scope.data());
  2362. addVariableToFile(rootNav,mtype,scope,name,FALSE,/*0,*/0);
  2363. }
  2364. nextMember:
  2365. rootNav->releaseEntry();
  2366. }
  2367. //----------------------------------------------------------------------
  2368. // Searches the Entry tree for typedef documentation sections.
  2369. // If found they are stored in their class or in the global list.
  2370. static void buildTypedefList(EntryNav *rootNav)
  2371. {
  2372. //printf("buildVarList(%s)\n",rootNav->name().data());
  2373. if (!rootNav->name().isEmpty() &&
  2374. rootNav->section()==Entry::VARIABLE_SEC &&
  2375. rootNav->type().find("typedef ")!=-1 // its a typedef
  2376. )
  2377. {
  2378. addVariable(rootNav);
  2379. }
  2380. if (rootNav->children())
  2381. {
  2382. EntryNavListIterator eli(*rootNav->children());
  2383. EntryNav *e;
  2384. for (;(e=eli.current());++eli)
  2385. {
  2386. if (e->section()!=Entry::ENUM_SEC)
  2387. {
  2388. buildTypedefList(e);
  2389. }
  2390. }
  2391. }
  2392. }
  2393. //----------------------------------------------------------------------
  2394. // Searches the Entry tree for Variable documentation sections.
  2395. // If found they are stored in their class or in the global list.
  2396. static void buildVarList(EntryNav *rootNav)
  2397. {
  2398. //printf("buildVarList(%s)\n",rootNav->name().data());
  2399. int isFuncPtr=-1;
  2400. if (!rootNav->name().isEmpty() &&
  2401. (rootNav->type().isEmpty() || g_compoundKeywordDict.find(rootNav->type())==0) &&
  2402. (
  2403. (rootNav->section()==Entry::VARIABLE_SEC // it's a variable
  2404. ) ||
  2405. (rootNav->section()==Entry::FUNCTION_SEC && // or maybe a function pointer variable
  2406. (isFuncPtr=findFunctionPtr(rootNav->type()))!=-1
  2407. ) ||
  2408. (rootNav->section()==Entry::FUNCTION_SEC && // class variable initialized by constructor
  2409. isVarWithConstructor(rootNav)
  2410. )
  2411. )
  2412. ) // documented variable
  2413. {
  2414. addVariable(rootNav,isFuncPtr);
  2415. }
  2416. if (rootNav->children())
  2417. {
  2418. EntryNavListIterator eli(*rootNav->children());
  2419. EntryNav *e;
  2420. for (;(e=eli.current());++eli)
  2421. {
  2422. if (e->section()!=Entry::ENUM_SEC)
  2423. {
  2424. buildVarList(e);
  2425. }
  2426. }
  2427. }
  2428. }
  2429. //----------------------------------------------------------------------
  2430. // Searches the Entry tree for Function sections.
  2431. // If found they are stored in their class or in the global list.
  2432. static void addMethodToClass(EntryNav *rootNav,ClassDef *cd,
  2433. const QCString &rname,bool isFriend)
  2434. {
  2435. Entry *root = rootNav->entry();
  2436. FileDef *fd=rootNav->fileDef();
  2437. int l,i=-1;
  2438. static QRegExp re("([a-z_A-Z0-9: ]*[ &*]+[ ]*");
  2439. if (!root->type.isEmpty() && (i=re.match(root->type,0,&l))!=-1) // function variable
  2440. {
  2441. root->args+=root->type.right(root->type.length()-i-l);
  2442. root->type=root->type.left(i+l);
  2443. }
  2444. QCString name=removeRedundantWhiteSpace(rname);
  2445. if (name.left(2)=="::") name=name.right(name.length()-2);
  2446. MemberDef::MemberType mtype;
  2447. if (isFriend) mtype=MemberDef::Friend;
  2448. else if (root->mtype==Signal) mtype=MemberDef::Signal;
  2449. else if (root->mtype==Slot) mtype=MemberDef::Slot;
  2450. else if (root->mtype==DCOP) mtype=MemberDef::DCOP;
  2451. else mtype=MemberDef::Function;
  2452. // strip redundant template specifier for constructors
  2453. if ((fd==0 || getLanguageFromFileName(fd->name())==SrcLangExt_Cpp) &&
  2454. name.left(9)!="operator " && (i=name.find('<'))!=-1 && name.find('>')!=-1)
  2455. {
  2456. name=name.left(i);
  2457. }
  2458. //printf("root->name=`%s; root->args=`%s' root->argList=`%s'\n",
  2459. // root->name.data(),root->args.data(),argListToString(root->argList).data()
  2460. // );
  2461. // adding class member
  2462. MemberDef *md=new MemberDef(
  2463. root->fileName,root->startLine,
  2464. root->type,name,root->args,root->exception,
  2465. root->protection,root->virt,
  2466. root->stat && root->relatesType != MemberOf,
  2467. root->relates.isEmpty() ? Member :
  2468. root->relatesType == MemberOf ? Foreign : Related,
  2469. mtype,root->tArgLists ? root->tArgLists->last() : 0,root->argList);
  2470. md->setTagInfo(rootNav->tagInfo());
  2471. md->setMemberClass(cd);
  2472. md->setDocumentation(root->doc,root->docFile,root->docLine);
  2473. md->setDocsForDefinition(!root->proto);
  2474. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  2475. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  2476. md->setBodySegment(root->bodyLine,root->endBodyLine);
  2477. md->setMemberSpecifiers(root->spec);
  2478. md->setMemberGroupId(root->mGrpId);
  2479. md->setTypeConstraints(root->typeConstr);
  2480. md->setBodyDef(fd);
  2481. md->setFileDef(fd);
  2482. //md->setScopeTemplateArguments(root->tArgList);
  2483. md->addSectionsToDefinition(root->anchors);
  2484. QCString def;
  2485. QCString qualScope = cd->qualifiedNameWithTemplateParameters();
  2486. QCString scopeSeparator="::";
  2487. if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
  2488. {
  2489. qualScope = substitute(qualScope,"::",".");
  2490. scopeSeparator=".";
  2491. }
  2492. if (!root->relates.isEmpty() || isFriend || Config_getBool("HIDE_SCOPE_NAMES"))
  2493. {
  2494. if (!root->type.isEmpty())
  2495. {
  2496. if (root->argList)
  2497. {
  2498. def=root->type+" "+name;
  2499. }
  2500. else
  2501. {
  2502. def=root->type+" "+name+root->args;
  2503. }
  2504. }
  2505. else
  2506. {
  2507. if (root->argList)
  2508. {
  2509. def=name;
  2510. }
  2511. else
  2512. {
  2513. def=name+root->args;
  2514. }
  2515. }
  2516. }
  2517. else
  2518. {
  2519. if (!root->type.isEmpty())
  2520. {
  2521. if (root->argList)
  2522. {
  2523. def=root->type+" "+qualScope+scopeSeparator+name;
  2524. }
  2525. else
  2526. {
  2527. def=root->type+" "+qualScope+scopeSeparator+name+root->args;
  2528. }
  2529. }
  2530. else
  2531. {
  2532. if (root->argList)
  2533. {
  2534. def=qualScope+scopeSeparator+name;
  2535. }
  2536. else
  2537. {
  2538. def=qualScope+scopeSeparator+name+root->args;
  2539. }
  2540. }
  2541. }
  2542. if (def.left(7)=="friend ") def=def.right(def.length()-7);
  2543. md->setDefinition(def);
  2544. md->enableCallGraph(root->callGraph);
  2545. md->enableCallerGraph(root->callerGraph);
  2546. Debug::print(Debug::Functions,0,
  2547. " Func Member:\n"
  2548. " `%s' `%s'::`%s' `%s' proto=%d\n"
  2549. " def=`%s'\n",
  2550. root->type.data(),
  2551. qualScope.data(),
  2552. rname.data(),
  2553. root->args.data(),
  2554. root->proto,
  2555. def.data()
  2556. );
  2557. // add member to the global list of all members
  2558. //printf("Adding member=%s class=%s\n",md->name().data(),cd->name().data());
  2559. MemberName *mn;
  2560. if ((mn=Doxygen::memberNameSDict->find(name)))
  2561. {
  2562. mn->append(md);
  2563. }
  2564. else
  2565. {
  2566. mn = new MemberName(name);
  2567. mn->append(md);
  2568. Doxygen::memberNameSDict->append(name,mn);
  2569. }
  2570. // add member to the class cd
  2571. cd->insertMember(md);
  2572. // add file to list of used files
  2573. cd->insertUsedFile(root->fileName);
  2574. addMemberToGroups(root,md);
  2575. rootNav->changeSection(Entry::EMPTY_SEC);
  2576. md->setRefItems(root->sli);
  2577. }
  2578. static void buildFunctionList(EntryNav *rootNav)
  2579. {
  2580. if (rootNav->section()==Entry::FUNCTION_SEC)
  2581. {
  2582. rootNav->loadEntry(g_storage);
  2583. Entry *root = rootNav->entry();
  2584. Debug::print(Debug::Functions,0,
  2585. "FUNCTION_SEC:\n"
  2586. " `%s' `%s'::`%s' `%s' relates=`%s' relatesType=`%d' file=`%s' line=`%d' bodyLine=`%d' #tArgLists=%d mGrpId=%d spec=%d proto=%d docFile=%s\n",
  2587. root->type.data(),
  2588. rootNav->parent()->name().data(),
  2589. root->name.data(),
  2590. root->args.data(),
  2591. root->relates.data(),
  2592. root->relatesType,
  2593. root->fileName.data(),
  2594. root->startLine,
  2595. root->bodyLine,
  2596. root->tArgLists ? (int)root->tArgLists->count() : -1,
  2597. root->mGrpId,
  2598. root->spec,
  2599. root->proto,
  2600. root->docFile.data()
  2601. );
  2602. bool isFriend=root->type.find("friend ")!=-1;
  2603. QCString rname = removeRedundantWhiteSpace(root->name);
  2604. //printf("rname=%s\n",rname.data());
  2605. QCString scope=rootNav->parent()->name(); //stripAnonymousNamespaceScope(root->parent->name);
  2606. if (!rname.isEmpty() && scope.find('@')==-1)
  2607. {
  2608. ClassDef *cd=0;
  2609. // check if this function's parent is a class
  2610. scope=stripTemplateSpecifiersFromScope(scope,FALSE);
  2611. FileDef *rfd=rootNav->fileDef();
  2612. int memIndex=rname.findRev("::");
  2613. cd=getClass(scope);
  2614. if (cd && scope+"::"==rname.left(scope.length()+2)) // found A::f inside A
  2615. {
  2616. // strip scope from name
  2617. rname=rname.right(rname.length()-rootNav->parent()->name().length()-2);
  2618. }
  2619. NamespaceDef *nd = 0;
  2620. bool isMember=FALSE;
  2621. if (memIndex!=-1)
  2622. {
  2623. int ts=rname.find('<');
  2624. int te=rname.find('>');
  2625. if (memIndex>0 && (ts==-1 || te==-1))
  2626. {
  2627. // note: the following code was replaced by inMember=TRUE to deal with a
  2628. // function rname='X::foo' of class X inside a namespace also called X...
  2629. // bug id 548175
  2630. //nd = Doxygen::namespaceSDict->find(rname.left(memIndex));
  2631. //isMember = nd==0;
  2632. //if (nd)
  2633. //{
  2634. // // strip namespace scope from name
  2635. // scope=rname.left(memIndex);
  2636. // rname=rname.right(rname.length()-memIndex-2);
  2637. //}
  2638. isMember = TRUE;
  2639. }
  2640. else
  2641. {
  2642. isMember=memIndex<ts || memIndex>te;
  2643. }
  2644. }
  2645. static QRegExp re("([a-z_A-Z0-9: ]*[ &*]+[ ]*");
  2646. if (!rootNav->parent()->name().isEmpty() &&
  2647. (rootNav->parent()->section() & Entry::COMPOUND_MASK) &&
  2648. cd &&
  2649. // do some fuzzy things to exclude function pointers
  2650. (root->type.isEmpty() ||
  2651. (root->type.find(re,0)==-1 || root->args.find(")[")!=-1) || // type contains ..(..* and args not )[.. -> function pointer
  2652. root->type.find(")(")!=-1 || root->type.find("operator")!=-1 // type contains ..)(.. and not "operator"
  2653. )
  2654. )
  2655. {
  2656. Debug::print(Debug::Functions,0," --> member %s of class %s!\n",
  2657. rname.data(),cd->name().data());
  2658. addMethodToClass(rootNav,cd,rname,isFriend);
  2659. }
  2660. else if (!((rootNav->parent()->section() & Entry::COMPOUND_MASK)
  2661. || rootNav->parent()->section()==Entry::OBJCIMPL_SEC
  2662. ) &&
  2663. !isMember &&
  2664. (root->relates.isEmpty() || root->relatesType == Duplicate) &&
  2665. root->type.left(7)!="extern " && root->type.left(8)!="typedef "
  2666. )
  2667. // no member => unrelated function
  2668. {
  2669. /* check the uniqueness of the function name in the file.
  2670. * A file could contain a function prototype and a function definition
  2671. * or even multiple function prototypes.
  2672. */
  2673. bool found=FALSE;
  2674. MemberName *mn;
  2675. MemberDef *md=0;
  2676. if ((mn=Doxygen::functionNameSDict->find(rname)))
  2677. {
  2678. Debug::print(Debug::Functions,0," --> function %s already found!\n",rname.data());
  2679. MemberNameIterator mni(*mn);
  2680. for (mni.toFirst();(!found && (md=mni.current()));++mni)
  2681. {
  2682. NamespaceDef *mnd = md->getNamespaceDef();
  2683. NamespaceDef *rnd = 0;
  2684. //printf("root namespace=%s\n",rootNav->parent()->name().data());
  2685. QCString fullScope = scope;
  2686. QCString parentScope = rootNav->parent()->name();
  2687. if (!parentScope.isEmpty() && !leftScopeMatch(parentScope,scope))
  2688. {
  2689. if (!scope.isEmpty()) fullScope.prepend("::");
  2690. fullScope.prepend(parentScope);
  2691. }
  2692. //printf("fullScope=%s\n",fullScope.data());
  2693. rnd = getResolvedNamespace(fullScope);
  2694. FileDef *mfd = md->getFileDef();
  2695. QCString nsName,rnsName;
  2696. if (mnd) nsName = mnd->name().copy();
  2697. if (rnd) rnsName = rnd->name().copy();
  2698. //printf("matching arguments for %s%s %s%s\n",
  2699. // md->name().data(),md->argsString(),rname.data(),argListToString(root->argList).data());
  2700. LockingPtr<ArgumentList> mdAl = md->argumentList();
  2701. LockingPtr<ArgumentList> mdTempl = md->templateArguments();
  2702. // in case of template functions, we need to check if the
  2703. // functions have the same number of template parameters
  2704. bool sameNumTemplateArgs = TRUE;
  2705. if (mdTempl!=0 && root->tArgLists)
  2706. {
  2707. if (mdTempl->count()!=root->tArgLists->getLast()->count())
  2708. {
  2709. sameNumTemplateArgs = FALSE;
  2710. }
  2711. }
  2712. if (
  2713. matchArguments2(md->getOuterScope(),mfd,mdAl.pointer(),
  2714. rnd ? rnd : Doxygen::globalScope,rfd,root->argList,
  2715. FALSE) &&
  2716. sameNumTemplateArgs
  2717. )
  2718. {
  2719. GroupDef *gd=0;
  2720. if (root->groups->first()!=0)
  2721. {
  2722. gd = Doxygen::groupSDict->find(root->groups->first()->groupname.data());
  2723. }
  2724. //printf("match!\n");
  2725. //printf("mnd=%p rnd=%p nsName=%s rnsName=%s\n",mnd,rnd,nsName.data(),rnsName.data());
  2726. // see if we need to create a new member
  2727. found=(mnd && rnd && nsName==rnsName) || // members are in the same namespace
  2728. ((mnd==0 && rnd==0 && mfd!=0 && // no external reference and
  2729. mfd->absFilePath()==root->fileName // prototype in the same file
  2730. )
  2731. );
  2732. // otherwise, allow a duplicate global member with the same argument list
  2733. if (!found && gd && gd==md->getGroupDef())
  2734. {
  2735. // member is already in the group, so we don't want to add it again.
  2736. found=TRUE;
  2737. }
  2738. //printf("combining function with prototype found=%d in namespace %s\n",
  2739. // found,nsName.data());
  2740. if (found)
  2741. {
  2742. // merge argument lists
  2743. mergeArguments(mdAl.pointer(),root->argList,!root->doc.isEmpty());
  2744. // merge documentation
  2745. if (md->documentation().isEmpty() && !root->doc.isEmpty())
  2746. {
  2747. ArgumentList *argList = new ArgumentList;
  2748. stringToArgumentList(root->args,argList);
  2749. if (root->proto)
  2750. {
  2751. //printf("setDeclArgumentList to %p\n",argList);
  2752. md->setDeclArgumentList(argList);
  2753. }
  2754. else
  2755. {
  2756. md->setArgumentList(argList);
  2757. }
  2758. }
  2759. md->setDocumentation(root->doc,root->docFile,root->docLine);
  2760. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  2761. md->setDocsForDefinition(!root->proto);
  2762. md->setBodySegment(root->bodyLine,root->endBodyLine);
  2763. md->setBodyDef(rfd);
  2764. if (md->briefDescription().isEmpty() && !root->brief.isEmpty())
  2765. {
  2766. md->setArgsString(root->args);
  2767. }
  2768. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  2769. md->addSectionsToDefinition(root->anchors);
  2770. md->enableCallGraph(md->hasCallGraph() || root->callGraph);
  2771. md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
  2772. // merge ingroup specifiers
  2773. if (md->getGroupDef()==0 && root->groups->first()!=0)
  2774. {
  2775. addMemberToGroups(root,md);
  2776. }
  2777. else if (md->getGroupDef()!=0 && root->groups->count()==0)
  2778. {
  2779. //printf("existing member is grouped, new member not\n");
  2780. root->groups->append(new Grouping(md->getGroupDef()->name(), md->getGroupPri()));
  2781. }
  2782. else if (md->getGroupDef()!=0 && root->groups->first()!=0)
  2783. {
  2784. //printf("both members are grouped\n");
  2785. }
  2786. // if md is a declaration and root is the corresponding
  2787. // definition, then turn md into a definition.
  2788. if (md->isPrototype() && !root->proto)
  2789. {
  2790. md->setPrototype(FALSE);
  2791. }
  2792. }
  2793. }
  2794. }
  2795. }
  2796. if (!found) /* global function is unique with respect to the file */
  2797. {
  2798. Debug::print(Debug::Functions,0," --> new function %s found!\n",rname.data());
  2799. //printf("New function type=`%s' name=`%s' args=`%s' bodyLine=%d\n",
  2800. // root->type.data(),rname.data(),root->args.data(),root->bodyLine);
  2801. // new global function
  2802. ArgumentList *tArgList = root->tArgLists ? root->tArgLists->last() : 0;
  2803. QCString name=removeRedundantWhiteSpace(rname);
  2804. md=new MemberDef(
  2805. root->fileName,root->startLine,
  2806. root->type,name,root->args,root->exception,
  2807. root->protection,root->virt,root->stat,Member,
  2808. MemberDef::Function,tArgList,root->argList);
  2809. md->setTagInfo(rootNav->tagInfo());
  2810. //md->setDefFile(root->fileName);
  2811. //md->setDefLine(root->startLine);
  2812. md->setDocumentation(root->doc,root->docFile,root->docLine);
  2813. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  2814. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  2815. md->setPrototype(root->proto);
  2816. md->setDocsForDefinition(!root->proto);
  2817. md->setTypeConstraints(root->typeConstr);
  2818. //md->setBody(root->body);
  2819. md->setBodySegment(root->bodyLine,root->endBodyLine);
  2820. FileDef *fd=rootNav->fileDef();
  2821. md->setBodyDef(fd);
  2822. md->addSectionsToDefinition(root->anchors);
  2823. md->setMemberSpecifiers(root->spec);
  2824. md->setMemberGroupId(root->mGrpId);
  2825. // see if the function is inside a namespace that was not part of
  2826. // the name already (in that case nd should be non-zero already)
  2827. if (nd==0 && rootNav->parent()->section() == Entry::NAMESPACE_SEC )
  2828. {
  2829. //QCString nscope=removeAnonymousScopes(rootNav->parent()->name());
  2830. QCString nscope=rootNav->parent()->name();
  2831. if (!nscope.isEmpty())
  2832. {
  2833. nd = getResolvedNamespace(nscope);
  2834. }
  2835. }
  2836. if (!scope.isEmpty())
  2837. {
  2838. if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
  2839. {
  2840. scope = substitute(scope,"::",".")+".";
  2841. }
  2842. else
  2843. {
  2844. scope+="::";
  2845. }
  2846. }
  2847. QCString def;
  2848. if (!root->type.isEmpty())
  2849. {
  2850. if (root->argList)
  2851. {
  2852. def=root->type+" "+scope+name;
  2853. }
  2854. else
  2855. {
  2856. def=root->type+" "+scope+name+root->args;
  2857. }
  2858. }
  2859. else
  2860. {
  2861. if (root->argList)
  2862. {
  2863. def=scope+name.copy();
  2864. }
  2865. else
  2866. {
  2867. def=scope+name+root->args;
  2868. }
  2869. }
  2870. Debug::print(Debug::Functions,0,
  2871. " Global Function:\n"
  2872. " `%s' `%s'::`%s' `%s' proto=%d\n"
  2873. " def=`%s'\n",
  2874. root->type.data(),
  2875. rootNav->parent()->name().data(),
  2876. rname.data(),
  2877. root->args.data(),
  2878. root->proto,
  2879. def.data()
  2880. );
  2881. md->setDefinition(def);
  2882. md->enableCallGraph(root->callGraph);
  2883. md->enableCallerGraph(root->callerGraph);
  2884. //if (root->mGrpId!=-1)
  2885. //{
  2886. // md->setMemberGroup(memberGroupDict[root->mGrpId]);
  2887. //}
  2888. md->setRefItems(root->sli);
  2889. if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
  2890. {
  2891. // add member to namespace
  2892. md->setNamespace(nd);
  2893. nd->insertMember(md);
  2894. }
  2895. if (fd)
  2896. {
  2897. // add member to the file (we do this even if we have already
  2898. // inserted it into the namespace)
  2899. md->setFileDef(fd);
  2900. fd->insertMember(md);
  2901. }
  2902. // add member to the list of file members
  2903. //printf("Adding member=%s\n",md->name().data());
  2904. MemberName *mn;
  2905. if ((mn=Doxygen::functionNameSDict->find(name)))
  2906. {
  2907. mn->append(md);
  2908. }
  2909. else
  2910. {
  2911. mn = new MemberName(name);
  2912. mn->append(md);
  2913. Doxygen::functionNameSDict->append(name,mn);
  2914. }
  2915. addMemberToGroups(root,md);
  2916. if (root->relatesType == Simple) // if this is a relatesalso command,
  2917. // allow find Member to pick it up
  2918. {
  2919. rootNav->changeSection(Entry::EMPTY_SEC); // Otherwise we have finished
  2920. // with this entry.
  2921. }
  2922. }
  2923. else
  2924. {
  2925. FileDef *fd=rootNav->fileDef();
  2926. if (fd)
  2927. {
  2928. // add member to the file (we do this even if we have already
  2929. // inserted it into the namespace)
  2930. fd->insertMember(md);
  2931. }
  2932. }
  2933. //printf("unrelated function %d `%s' `%s' `%s'\n",
  2934. // root->parent->section,root->type.data(),rname.data(),root->args.data());
  2935. }
  2936. else
  2937. {
  2938. Debug::print(Debug::Functions,0," --> %s not processed!\n",rname.data());
  2939. }
  2940. }
  2941. else if (rname.isEmpty())
  2942. {
  2943. warn(root->fileName,root->startLine,
  2944. "Warning: Illegal member name found."
  2945. );
  2946. }
  2947. rootNav->releaseEntry();
  2948. }
  2949. RECURSE_ENTRYTREE(buildFunctionList,rootNav);
  2950. }
  2951. //----------------------------------------------------------------------
  2952. static void findFriends()
  2953. {
  2954. //printf("findFriends()\n");
  2955. MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
  2956. MemberName *fn;
  2957. for (;(fn=fnli.current());++fnli) // for each global function name
  2958. {
  2959. //printf("Function name=`%s'\n",fn->memberName());
  2960. MemberName *mn;
  2961. if ((mn=Doxygen::memberNameSDict->find(fn->memberName())))
  2962. { // there are members with the same name
  2963. //printf("Function name is also a member name\n");
  2964. MemberNameIterator fni(*fn);
  2965. MemberDef *fmd;
  2966. for (;(fmd=fni.current());++fni) // for each function with that name
  2967. {
  2968. MemberNameIterator mni(*mn);
  2969. MemberDef *mmd;
  2970. for (;(mmd=mni.current());++mni) // for each member with that name
  2971. {
  2972. //printf("Checking for matching arguments
  2973. // mmd->isRelated()=%d mmd->isFriend()=%d mmd->isFunction()=%d\n",
  2974. // mmd->isRelated(),mmd->isFriend(),mmd->isFunction());
  2975. LockingPtr<ArgumentList> mmdAl = mmd->argumentList();
  2976. LockingPtr<ArgumentList> fmdAl = fmd->argumentList();
  2977. if ((mmd->isFriend() || (mmd->isRelated() && mmd->isFunction())) &&
  2978. matchArguments2(mmd->getOuterScope(), mmd->getFileDef(), mmdAl.pointer(),
  2979. fmd->getOuterScope(), fmd->getFileDef(), fmdAl.pointer(),
  2980. TRUE
  2981. )
  2982. ) // if the member is related and the arguments match then the
  2983. // function is actually a friend.
  2984. {
  2985. mergeArguments(mmdAl.pointer(),fmdAl.pointer());
  2986. if (!fmd->documentation().isEmpty())
  2987. {
  2988. mmd->setDocumentation(fmd->documentation(),fmd->docFile(),fmd->docLine());
  2989. }
  2990. else if (!mmd->documentation().isEmpty())
  2991. {
  2992. fmd->setDocumentation(mmd->documentation(),mmd->docFile(),mmd->docLine());
  2993. }
  2994. if (mmd->briefDescription().isEmpty() && !fmd->briefDescription().isEmpty())
  2995. {
  2996. mmd->setBriefDescription(fmd->briefDescription(),fmd->briefFile(),fmd->briefLine());
  2997. }
  2998. else if (!mmd->briefDescription().isEmpty() && !fmd->briefDescription().isEmpty())
  2999. {
  3000. fmd->setBriefDescription(mmd->briefDescription(),mmd->briefFile(),mmd->briefLine());
  3001. }
  3002. if (!fmd->inbodyDocumentation().isEmpty())
  3003. {
  3004. mmd->setInbodyDocumentation(fmd->inbodyDocumentation(),fmd->inbodyFile(),fmd->inbodyLine());
  3005. }
  3006. else if (!mmd->inbodyDocumentation().isEmpty())
  3007. {
  3008. fmd->setInbodyDocumentation(mmd->inbodyDocumentation(),mmd->inbodyFile(),mmd->inbodyLine());
  3009. }
  3010. //printf("body mmd %d fmd %d\n",mmd->getStartBodyLine(),fmd->getStartBodyLine());
  3011. if (mmd->getStartBodyLine()==-1 && fmd->getStartBodyLine()!=-1)
  3012. {
  3013. mmd->setBodySegment(fmd->getStartBodyLine(),fmd->getEndBodyLine());
  3014. mmd->setBodyDef(fmd->getBodyDef());
  3015. //mmd->setBodyMember(fmd);
  3016. }
  3017. else if (mmd->getStartBodyLine()!=-1 && fmd->getStartBodyLine()==-1)
  3018. {
  3019. fmd->setBodySegment(mmd->getStartBodyLine(),mmd->getEndBodyLine());
  3020. fmd->setBodyDef(mmd->getBodyDef());
  3021. //fmd->setBodyMember(mmd);
  3022. }
  3023. mmd->setDocsForDefinition(fmd->isDocsForDefinition());
  3024. mmd->enableCallGraph(mmd->hasCallGraph() || fmd->hasCallGraph());
  3025. mmd->enableCallerGraph(mmd->hasCallerGraph() || fmd->hasCallerGraph());
  3026. fmd->enableCallGraph(mmd->hasCallGraph() || fmd->hasCallGraph());
  3027. fmd->enableCallerGraph(mmd->hasCallerGraph() || fmd->hasCallerGraph());
  3028. }
  3029. }
  3030. }
  3031. }
  3032. }
  3033. }
  3034. //----------------------------------------------------------------------
  3035. static void transferArgumentDocumentation(ArgumentList *decAl,ArgumentList *defAl)
  3036. {
  3037. if (decAl && defAl)
  3038. {
  3039. ArgumentListIterator decAli(*decAl);
  3040. ArgumentListIterator defAli(*defAl);
  3041. Argument *decA,*defA;
  3042. for (decAli.toFirst(),defAli.toFirst();
  3043. (decA=decAli.current()) && (defA=defAli.current());
  3044. ++decAli,++defAli)
  3045. {
  3046. //printf("Argument decA->name=%s (doc=%s) defA->name=%s (doc=%s)\n",
  3047. // decA->name.data(),decA->docs.data(),
  3048. // defA->name.data(),defA->docs.data()
  3049. // );
  3050. if (decA->docs.isEmpty() && !defA->docs.isEmpty())
  3051. {
  3052. decA->docs = defA->docs.copy();
  3053. }
  3054. else if (defA->docs.isEmpty() && !decA->docs.isEmpty())
  3055. {
  3056. defA->docs = decA->docs.copy();
  3057. }
  3058. }
  3059. }
  3060. }
  3061. static void transferFunctionDocumentation()
  3062. {
  3063. //printf("---- transferFunctionDocumentation()\n");
  3064. // find matching function declaration and definitions.
  3065. MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict);
  3066. MemberName *mn;
  3067. for (;(mn=mnli.current());++mnli)
  3068. {
  3069. //printf("memberName=%s count=%d\n",mn->memberName(),mn->count());
  3070. MemberDef *mdef=0,*mdec=0;
  3071. MemberNameIterator mni1(*mn);
  3072. /* find a matching function declaration and definition for this function */
  3073. for (;(mdec=mni1.current());++mni1)
  3074. {
  3075. //printf("mdec=%s isPrototype()=%d\n",mdec->name().data(),mdec->isPrototype());
  3076. if (mdec->isPrototype() ||
  3077. (mdec->isVariable() && mdec->isExternal())
  3078. )
  3079. {
  3080. MemberNameIterator mni2(*mn);
  3081. for (;(mdef=mni2.current());++mni2)
  3082. {
  3083. if (
  3084. (mdef->isFunction() && !mdef->isStatic() && !mdef->isPrototype()) ||
  3085. (mdef->isVariable() && !mdef->isExternal() && !mdef->isStatic())
  3086. )
  3087. {
  3088. //printf("mdef=(%p,%s) mdec=(%p,%s)\n",
  3089. // mdef, mdef ? mdef->name().data() : "",
  3090. // mdec, mdec ? mdec->name().data() : "");
  3091. LockingPtr<ArgumentList> mdefAl = mdef->argumentList();
  3092. LockingPtr<ArgumentList> mdecAl = mdec->argumentList();
  3093. if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl.pointer(),
  3094. mdec->getOuterScope(),mdec->getFileDef(),mdecAl.pointer(),
  3095. TRUE
  3096. )
  3097. ) /* match found */
  3098. {
  3099. //printf("Found member %s: definition in %s (doc=`%s') and declaration in %s (doc=`%s')\n",
  3100. // mn->memberName(),
  3101. // mdef->getFileDef()->name().data(),mdef->documentation().data(),
  3102. // mdec->getFileDef()->name().data(),mdec->documentation().data()
  3103. // );
  3104. // first merge argument documentation
  3105. transferArgumentDocumentation(mdecAl.pointer(),mdefAl.pointer());
  3106. /* copy documentation between function definition and declaration */
  3107. if (!mdec->briefDescription().isEmpty())
  3108. {
  3109. mdef->setBriefDescription(mdec->briefDescription(),mdec->briefFile(),mdec->briefLine());
  3110. }
  3111. else if (!mdef->briefDescription().isEmpty())
  3112. {
  3113. mdec->setBriefDescription(mdef->briefDescription(),mdef->briefFile(),mdef->briefLine());
  3114. }
  3115. if (!mdef->documentation().isEmpty())
  3116. {
  3117. //printf("transfering docs mdef->mdec (%s->%s)\n",mdef->argsString(),mdec->argsString());
  3118. mdec->setDocumentation(mdef->documentation(),mdef->docFile(),mdef->docLine());
  3119. mdec->setDocsForDefinition(mdef->isDocsForDefinition());
  3120. if (mdefAl!=0)
  3121. {
  3122. ArgumentList *mdefAlComb = new ArgumentList;
  3123. stringToArgumentList(mdef->argsString(),mdefAlComb);
  3124. transferArgumentDocumentation(mdefAl.pointer(),mdefAlComb);
  3125. mdec->setArgumentList(mdefAlComb);
  3126. }
  3127. }
  3128. else if (!mdec->documentation().isEmpty())
  3129. {
  3130. //printf("transfering docs mdec->mdef (%s->%s)\n",mdec->argsString(),mdef->argsString());
  3131. mdef->setDocumentation(mdec->documentation(),mdec->docFile(),mdec->docLine());
  3132. mdef->setDocsForDefinition(mdec->isDocsForDefinition());
  3133. if (mdecAl!=0)
  3134. {
  3135. ArgumentList *mdecAlComb = new ArgumentList;
  3136. stringToArgumentList(mdec->argsString(),mdecAlComb);
  3137. transferArgumentDocumentation(mdecAl.pointer(),mdecAlComb);
  3138. mdef->setDeclArgumentList(mdecAlComb);
  3139. }
  3140. }
  3141. if (!mdef->inbodyDocumentation().isEmpty())
  3142. {
  3143. mdec->setInbodyDocumentation(mdef->inbodyDocumentation(),mdef->inbodyFile(),mdef->inbodyLine());
  3144. }
  3145. else if (!mdec->inbodyDocumentation().isEmpty())
  3146. {
  3147. mdef->setInbodyDocumentation(mdec->inbodyDocumentation(),mdec->inbodyFile(),mdec->inbodyLine());
  3148. }
  3149. if (mdec->getStartBodyLine()!=-1 && mdef->getStartBodyLine()==-1)
  3150. {
  3151. //printf("body mdec->mdef %d-%d\n",mdec->getStartBodyLine(),mdef->getEndBodyLine());
  3152. mdef->setBodySegment(mdec->getStartBodyLine(),mdec->getEndBodyLine());
  3153. mdef->setBodyDef(mdec->getBodyDef());
  3154. //mdef->setBodyMember(mdec);
  3155. }
  3156. else if (mdef->getStartBodyLine()!=-1 && mdec->getStartBodyLine()==-1)
  3157. {
  3158. //printf("body mdef->mdec %d-%d\n",mdef->getStartBodyLine(),mdec->getEndBodyLine());
  3159. mdec->setBodySegment(mdef->getStartBodyLine(),mdef->getEndBodyLine());
  3160. mdec->setBodyDef(mdef->getBodyDef());
  3161. //mdec->setBodyMember(mdef);
  3162. }
  3163. mdec->mergeMemberSpecifiers(mdef->getMemberSpecifiers());
  3164. mdef->mergeMemberSpecifiers(mdec->getMemberSpecifiers());
  3165. // copy group info.
  3166. if (mdec->getGroupDef()==0 && mdef->getGroupDef()!=0)
  3167. {
  3168. mdec->setGroupDef(mdef->getGroupDef(),
  3169. mdef->getGroupPri(),
  3170. mdef->docFile(),
  3171. mdef->docLine(),
  3172. mdef->hasDocumentation(),
  3173. mdef
  3174. );
  3175. }
  3176. else if (mdef->getGroupDef()==0 && mdec->getGroupDef()!=0)
  3177. {
  3178. mdef->setGroupDef(mdec->getGroupDef(),
  3179. mdec->getGroupPri(),
  3180. mdec->docFile(),
  3181. mdec->docLine(),
  3182. mdec->hasDocumentation(),
  3183. mdec
  3184. );
  3185. }
  3186. mdec->mergeRefItems(mdef);
  3187. mdef->mergeRefItems(mdec);
  3188. mdef->setMemberDeclaration(mdec);
  3189. mdec->setMemberDefinition(mdef);
  3190. mdef->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
  3191. mdef->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
  3192. mdec->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
  3193. mdec->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
  3194. }
  3195. }
  3196. }
  3197. }
  3198. }
  3199. }
  3200. }
  3201. //----------------------------------------------------------------------
  3202. static void transferFunctionReferences()
  3203. {
  3204. MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict);
  3205. MemberName *mn;
  3206. for (;(mn=mnli.current());++mnli)
  3207. {
  3208. MemberDef *md,*mdef=0,*mdec=0;
  3209. MemberNameIterator mni(*mn);
  3210. /* find a matching function declaration and definition for this function */
  3211. for (;(md=mni.current());++mni)
  3212. {
  3213. if (md->isPrototype())
  3214. mdec=md;
  3215. else if (md->isVariable() && md->isExternal())
  3216. mdec=md;
  3217. if (md->isFunction() && !md->isStatic() && !md->isPrototype())
  3218. mdef=md;
  3219. else if (md->isVariable() && !md->isExternal() && !md->isStatic())
  3220. mdef=md;
  3221. }
  3222. if (mdef && mdec)
  3223. {
  3224. LockingPtr<ArgumentList> mdefAl = mdef->argumentList();
  3225. LockingPtr<ArgumentList> mdecAl = mdec->argumentList();
  3226. if (
  3227. matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl.pointer(),
  3228. mdec->getOuterScope(),mdec->getFileDef(),mdecAl.pointer(),
  3229. TRUE
  3230. )
  3231. ) /* match found */
  3232. {
  3233. LockingPtr<MemberSDict> defDict = mdef->getReferencesMembers();
  3234. LockingPtr<MemberSDict> decDict = mdec->getReferencesMembers();
  3235. if (defDict!=0)
  3236. {
  3237. MemberSDict::Iterator msdi(*defDict);
  3238. MemberDef *rmd;
  3239. for (msdi.toFirst();(rmd=msdi.current());++msdi)
  3240. {
  3241. if (decDict==0 || decDict->find(rmd->name())==0)
  3242. {
  3243. mdec->addSourceReferences(rmd);
  3244. }
  3245. }
  3246. }
  3247. if (decDict!=0)
  3248. {
  3249. MemberSDict::Iterator msdi(*decDict);
  3250. MemberDef *rmd;
  3251. for (msdi.toFirst();(rmd=msdi.current());++msdi)
  3252. {
  3253. if (defDict==0 || defDict->find(rmd->name())==0)
  3254. {
  3255. mdef->addSourceReferences(rmd);
  3256. }
  3257. }
  3258. }
  3259. defDict = mdef->getReferencedByMembers();
  3260. decDict = mdec->getReferencedByMembers();
  3261. if (defDict!=0)
  3262. {
  3263. MemberSDict::Iterator msdi(*defDict);
  3264. MemberDef *rmd;
  3265. for (msdi.toFirst();(rmd=msdi.current());++msdi)
  3266. {
  3267. if (decDict==0 || decDict->find(rmd->name())==0)
  3268. {
  3269. mdec->addSourceReferencedBy(rmd);
  3270. }
  3271. }
  3272. }
  3273. if (decDict!=0)
  3274. {
  3275. MemberSDict::Iterator msdi(*decDict);
  3276. MemberDef *rmd;
  3277. for (msdi.toFirst();(rmd=msdi.current());++msdi)
  3278. {
  3279. if (defDict==0 || defDict->find(rmd->name())==0)
  3280. {
  3281. mdef->addSourceReferencedBy(rmd);
  3282. }
  3283. }
  3284. }
  3285. }
  3286. }
  3287. }
  3288. }
  3289. //----------------------------------------------------------------------
  3290. static void transferRelatedFunctionDocumentation()
  3291. {
  3292. // find match between function declaration and definition for
  3293. // related functions
  3294. MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict);
  3295. MemberName *mn;
  3296. for (mnli.toFirst();(mn=mnli.current());++mnli)
  3297. {
  3298. MemberDef *md;
  3299. MemberNameIterator mni(*mn);
  3300. /* find a matching function declaration and definition for this function */
  3301. for (mni.toFirst();(md=mni.current());++mni) // for each global function
  3302. {
  3303. //printf(" Function `%s'\n",md->name().data());
  3304. MemberName *rmn;
  3305. if ((rmn=Doxygen::memberNameSDict->find(md->name()))) // check if there is a member with the same name
  3306. {
  3307. //printf(" Member name found\n");
  3308. MemberDef *rmd;
  3309. MemberNameIterator rmni(*rmn);
  3310. for (rmni.toFirst();(rmd=rmni.current());++rmni) // for each member with the same name
  3311. {
  3312. LockingPtr<ArgumentList> mdAl = md->argumentList();
  3313. LockingPtr<ArgumentList> rmdAl = rmd->argumentList();
  3314. //printf(" Member found: related=`%d'\n",rmd->isRelated());
  3315. if ((rmd->isRelated() || rmd->isForeign()) && // related function
  3316. matchArguments2( md->getOuterScope(), md->getFileDef(), mdAl.pointer(),
  3317. rmd->getOuterScope(),rmd->getFileDef(),rmdAl.pointer(),
  3318. TRUE
  3319. )
  3320. )
  3321. {
  3322. //printf(" Found related member `%s'\n",md->name().data());
  3323. if (rmd->relatedAlso())
  3324. md->setRelatedAlso(rmd->relatedAlso());
  3325. else if (rmd->isForeign())
  3326. md->makeForeign();
  3327. else
  3328. md->makeRelated();
  3329. }
  3330. }
  3331. }
  3332. }
  3333. }
  3334. }
  3335. //----------------------------------------------------------------------
  3336. /*! make a dictionary of all template arguments of class cd
  3337. * that are part of the base class name.
  3338. * Example: A template class A with template arguments <R,S,T>
  3339. * that inherits from B<T,T,S> will have T and S in the dictionary.
  3340. */
  3341. static QDict<int> *getTemplateArgumentsInName(ArgumentList *templateArguments,const QCString &name)
  3342. {
  3343. QDict<int> *templateNames = new QDict<int>(17);
  3344. templateNames->setAutoDelete(TRUE);
  3345. static QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*");
  3346. if (templateArguments)
  3347. {
  3348. ArgumentListIterator ali(*templateArguments);
  3349. Argument *arg;
  3350. int count=0;
  3351. for (ali.toFirst();(arg=ali.current());++ali,count++)
  3352. {
  3353. int i,p=0,l;
  3354. while ((i=re.match(name,p,&l))!=-1)
  3355. {
  3356. QCString n = name.mid(i,l);
  3357. if (n==arg->name)
  3358. {
  3359. if (templateNames->find(n)==0)
  3360. {
  3361. templateNames->insert(n,new int(count));
  3362. }
  3363. }
  3364. p=i+l;
  3365. }
  3366. }
  3367. }
  3368. return templateNames;
  3369. }
  3370. /*! Searches a class from within \a context and \a cd and returns its
  3371. * definition if found (otherwise 0 is returned).
  3372. */
  3373. static ClassDef *findClassWithinClassContext(Definition *context,ClassDef *cd,const QCString &name)
  3374. {
  3375. FileDef *fd=cd->getFileDef();
  3376. ClassDef *result=0;
  3377. if (context && cd!=context)
  3378. {
  3379. result = getResolvedClass(context,0,name,0,0,TRUE,TRUE);
  3380. }
  3381. if (result==0)
  3382. {
  3383. result = getResolvedClass(cd,fd,name,0,0,TRUE,TRUE);
  3384. }
  3385. //printf("** Trying to find %s within context %s class %s result=%s lookup=%p\n",
  3386. // name.data(),
  3387. // context ? context->name().data() : "<none>",
  3388. // cd ? cd->name().data() : "<none>",
  3389. // result ? result->name().data() : "<none>",
  3390. // Doxygen::classSDict.find(name)
  3391. // );
  3392. return result;
  3393. }
  3394. enum FindBaseClassRelation_Mode
  3395. {
  3396. TemplateInstances,
  3397. DocumentedOnly,
  3398. Undocumented
  3399. };
  3400. static bool findClassRelation(
  3401. EntryNav *rootNav,
  3402. Definition *context,
  3403. ClassDef *cd,
  3404. BaseInfo *bi,
  3405. QDict<int> *templateNames,
  3406. /*bool insertUndocumented*/
  3407. FindBaseClassRelation_Mode mode,
  3408. bool isArtificial
  3409. );
  3410. static void findUsedClassesForClass(EntryNav *rootNav,
  3411. Definition *context,
  3412. ClassDef *masterCd,
  3413. ClassDef *instanceCd,
  3414. bool isArtificial,
  3415. ArgumentList *actualArgs=0,
  3416. QDict<int> *templateNames=0
  3417. )
  3418. {
  3419. masterCd->visited=TRUE;
  3420. ArgumentList *formalArgs = masterCd->templateArguments();
  3421. if (masterCd->memberNameInfoSDict())
  3422. {
  3423. MemberNameInfoSDict::Iterator mnili(*masterCd->memberNameInfoSDict());
  3424. MemberNameInfo *mni;
  3425. for (;(mni=mnili.current());++mnili)
  3426. {
  3427. MemberNameInfoIterator mnii(*mni);
  3428. MemberInfo *mi;
  3429. for (mnii.toFirst();(mi=mnii.current());++mnii)
  3430. {
  3431. MemberDef *md=mi->memberDef;
  3432. if (md->isVariable()) // for each member variable in this class
  3433. {
  3434. //printf(" Found variable %s in class %s\n",md->name().data(),masterCd->name().data());
  3435. QCString type=removeRedundantWhiteSpace(md->typeString());
  3436. QCString typedefValue = resolveTypeDef(masterCd,type);
  3437. if (!typedefValue.isEmpty())
  3438. {
  3439. type = typedefValue;
  3440. }
  3441. int pos=0;
  3442. QCString usedClassName;
  3443. QCString templSpec;
  3444. bool found=FALSE;
  3445. // the type can contain template variables, replace them if present
  3446. if (actualArgs)
  3447. {
  3448. type = substituteTemplateArgumentsInString(type,formalArgs,actualArgs);
  3449. }
  3450. //printf(" template substitution gives=%s\n",type.data());
  3451. while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec)!=-1)
  3452. {
  3453. // find the type (if any) that matches usedClassName
  3454. ClassDef *typeCd = getResolvedClass(masterCd,
  3455. masterCd->getFileDef(),
  3456. usedClassName,
  3457. 0,0,
  3458. FALSE,TRUE
  3459. );
  3460. //printf("====> usedClassName=%s -> typeCd=%s\n",
  3461. // usedClassName.data(),typeCd?typeCd->name().data():"<none>");
  3462. if (typeCd)
  3463. {
  3464. usedClassName = typeCd->name();
  3465. }
  3466. int sp=usedClassName.find('<');
  3467. if (sp==-1) sp=0;
  3468. int si=usedClassName.findRev("::",sp);
  3469. if (si!=-1)
  3470. {
  3471. // replace any namespace aliases
  3472. replaceNamespaceAliases(usedClassName,si);
  3473. }
  3474. // add any template arguments to the class
  3475. QCString usedName = removeRedundantWhiteSpace(usedClassName+templSpec);
  3476. //printf(" usedName=%s\n",usedName.data());
  3477. bool delTempNames=FALSE;
  3478. if (templateNames==0)
  3479. {
  3480. templateNames = getTemplateArgumentsInName(formalArgs,usedName);
  3481. delTempNames=TRUE;
  3482. }
  3483. BaseInfo bi(usedName,Public,Normal);
  3484. findClassRelation(rootNav,context,instanceCd,&bi,templateNames,TemplateInstances,isArtificial);
  3485. if (masterCd->templateArguments())
  3486. {
  3487. ArgumentListIterator ali(*masterCd->templateArguments());
  3488. Argument *arg;
  3489. int count=0;
  3490. for (ali.toFirst();(arg=ali.current());++ali,++count)
  3491. {
  3492. if (arg->name==usedName) // type is a template argument
  3493. {
  3494. found=TRUE;
  3495. Debug::print(Debug::Classes,0," New used class `%s'\n", usedName.data());
  3496. ClassDef *usedCd = Doxygen::hiddenClasses->find(usedName);
  3497. if (usedCd==0)
  3498. {
  3499. usedCd = new ClassDef(
  3500. masterCd->getDefFileName(),masterCd->getDefLine(),
  3501. usedName,ClassDef::Class);
  3502. //printf("making %s a template argument!!!\n",usedCd->name().data());
  3503. usedCd->makeTemplateArgument();
  3504. usedCd->setUsedOnly(TRUE);
  3505. Doxygen::hiddenClasses->append(usedName,usedCd);
  3506. }
  3507. if (usedCd)
  3508. {
  3509. if (isArtificial) usedCd->setArtificial(TRUE);
  3510. Debug::print(Debug::Classes,0," Adding used class `%s' (1)\n", usedCd->name().data());
  3511. instanceCd->addUsedClass(usedCd,md->name());
  3512. usedCd->addUsedByClass(instanceCd,md->name());
  3513. }
  3514. }
  3515. }
  3516. }
  3517. if (!found)
  3518. {
  3519. ClassDef *usedCd=findClassWithinClassContext(context,masterCd,usedName);
  3520. //printf("Looking for used class %s: result=%s master=%s\n",
  3521. // usedName.data(),usedCd?usedCd->name().data():"<none>",masterCd?masterCd->name().data():"<none>");
  3522. if (usedCd)
  3523. {
  3524. found=TRUE;
  3525. Debug::print(Debug::Classes,0," Adding used class `%s' (2)\n", usedCd->name().data());
  3526. instanceCd->addUsedClass(usedCd,md->name()); // class exists
  3527. usedCd->addUsedByClass(instanceCd,md->name());
  3528. }
  3529. }
  3530. if (delTempNames)
  3531. {
  3532. delete templateNames;
  3533. templateNames=0;
  3534. }
  3535. }
  3536. if (!found && !type.isEmpty()) // used class is not documented in any scope
  3537. {
  3538. ClassDef *usedCd = Doxygen::hiddenClasses->find(type);
  3539. if (usedCd==0 && !Config_getBool("HIDE_UNDOC_RELATIONS"))
  3540. {
  3541. if (type.right(2)=="(*") // type is a function pointer
  3542. {
  3543. type+=md->argsString();
  3544. }
  3545. Debug::print(Debug::Classes,0," New undocumented used class `%s'\n", type.data());
  3546. usedCd = new ClassDef(
  3547. masterCd->getDefFileName(),masterCd->getDefLine(),
  3548. type,ClassDef::Class);
  3549. usedCd->setUsedOnly(TRUE);
  3550. Doxygen::hiddenClasses->append(type,usedCd);
  3551. }
  3552. if (usedCd)
  3553. {
  3554. if (isArtificial) usedCd->setArtificial(TRUE);
  3555. Debug::print(Debug::Classes,0," Adding used class `%s' (3)\n", usedCd->name().data());
  3556. instanceCd->addUsedClass(usedCd,md->name());
  3557. usedCd->addUsedByClass(instanceCd,md->name());
  3558. }
  3559. }
  3560. }
  3561. }
  3562. }
  3563. }
  3564. else
  3565. {
  3566. //printf("no members for class %s (%p)\n",masterCd->name().data(),masterCd);
  3567. }
  3568. }
  3569. static void findBaseClassesForClass(
  3570. EntryNav *rootNav,
  3571. Definition *context,
  3572. ClassDef *masterCd,
  3573. ClassDef *instanceCd,
  3574. FindBaseClassRelation_Mode mode,
  3575. bool isArtificial,
  3576. ArgumentList *actualArgs=0,
  3577. QDict<int> *templateNames=0
  3578. )
  3579. {
  3580. Entry *root = rootNav->entry();
  3581. //if (masterCd->visited) return;
  3582. masterCd->visited=TRUE;
  3583. // The base class could ofcouse also be a non-nested class
  3584. ArgumentList *formalArgs = masterCd->templateArguments();
  3585. QListIterator<BaseInfo> bii(*root->extends);
  3586. BaseInfo *bi=0;
  3587. for (bii.toFirst();(bi=bii.current());++bii)
  3588. {
  3589. //printf("masterCd=%s bi->name='%s' #actualArgs=%d\n",
  3590. // masterCd->localName().data(),bi->name.data(),actualArgs?(int)actualArgs->count():-1);
  3591. bool delTempNames=FALSE;
  3592. if (templateNames==0)
  3593. {
  3594. templateNames = getTemplateArgumentsInName(formalArgs,bi->name);
  3595. delTempNames=TRUE;
  3596. }
  3597. BaseInfo tbi(bi->name,bi->prot,bi->virt);
  3598. if (actualArgs) // substitute the formal template arguments of the base class
  3599. {
  3600. tbi.name = substituteTemplateArgumentsInString(bi->name,formalArgs,actualArgs);
  3601. }
  3602. //printf("bi->name=%s tbi.name=%s\n",bi->name.data(),tbi.name.data());
  3603. if (mode==DocumentedOnly)
  3604. {
  3605. // find a documented base class in the correct scope
  3606. if (!findClassRelation(rootNav,context,instanceCd,&tbi,templateNames,DocumentedOnly,isArtificial))
  3607. {
  3608. if (!Config_getBool("HIDE_UNDOC_RELATIONS"))
  3609. {
  3610. // no documented base class -> try to find an undocumented one
  3611. findClassRelation(rootNav,context,instanceCd,&tbi,templateNames,Undocumented,isArtificial);
  3612. }
  3613. }
  3614. }
  3615. else if (mode==TemplateInstances)
  3616. {
  3617. findClassRelation(rootNav,context,instanceCd,&tbi,templateNames,TemplateInstances,isArtificial);
  3618. }
  3619. if (delTempNames)
  3620. {
  3621. delete templateNames;
  3622. templateNames=0;
  3623. }
  3624. }
  3625. }
  3626. //----------------------------------------------------------------------
  3627. static bool findTemplateInstanceRelation(Entry *root,
  3628. Definition *context,
  3629. ClassDef *templateClass,const QCString &templSpec,
  3630. QDict<int> *templateNames,
  3631. bool isArtificial)
  3632. {
  3633. Debug::print(Debug::Classes,0," derived from template %s with parameters %s\n",
  3634. templateClass->name().data(),templSpec.data());
  3635. //printf("findTemplateInstanceRelation(base=%s templSpec=%s templateNames=",
  3636. // templateClass->name().data(),templSpec.data());
  3637. //if (templateNames)
  3638. //{
  3639. // QDictIterator<int> qdi(*templateNames);
  3640. // int *tempArgIndex;
  3641. // for (;(tempArgIndex=qdi.current());++qdi)
  3642. // {
  3643. // printf("(%s->%d) ",qdi.currentKey().data(),*tempArgIndex);
  3644. // }
  3645. //}
  3646. //printf("\n");
  3647. bool existingClass = (templSpec ==
  3648. tempArgListToString(templateClass->templateArguments())
  3649. );
  3650. if (existingClass) return TRUE;
  3651. bool freshInstance=FALSE;
  3652. ClassDef *instanceClass = templateClass->insertTemplateInstance(
  3653. root->fileName,root->startLine,templSpec,freshInstance);
  3654. if (isArtificial) instanceClass->setArtificial(TRUE);
  3655. instanceClass->setIsObjectiveC(root->objc);
  3656. if (freshInstance)
  3657. {
  3658. Debug::print(Debug::Classes,0," found fresh instance '%s'!\n",instanceClass->name().data());
  3659. Doxygen::classSDict->append(instanceClass->name(),instanceClass);
  3660. instanceClass->setTemplateBaseClassNames(templateNames);
  3661. // search for new template instances caused by base classes of
  3662. // instanceClass
  3663. EntryNav *templateRootNav = g_classEntries.find(templateClass->name());
  3664. if (templateRootNav)
  3665. {
  3666. bool unloadNeeded=FALSE;
  3667. Entry *templateRoot = templateRootNav->entry();
  3668. if (templateRoot==0) // not yet loaded
  3669. {
  3670. templateRootNav->loadEntry(g_storage);
  3671. templateRoot = templateRootNav->entry();
  3672. ASSERT(templateRoot!=0); // now it should really be loaded
  3673. unloadNeeded=TRUE;
  3674. }
  3675. Debug::print(Debug::Classes,0," template root found %s templSpec=%s!\n",
  3676. templateRoot->name.data(),templSpec.data());
  3677. ArgumentList *templArgs = new ArgumentList;
  3678. stringToArgumentList(templSpec,templArgs);
  3679. findBaseClassesForClass(templateRootNav,context,templateClass,instanceClass,
  3680. TemplateInstances,isArtificial,templArgs,templateNames);
  3681. findUsedClassesForClass(templateRootNav,context,templateClass,instanceClass,
  3682. isArtificial,templArgs,templateNames);
  3683. delete templArgs;
  3684. if (unloadNeeded) // still cleanup to do
  3685. {
  3686. templateRootNav->releaseEntry();
  3687. }
  3688. }
  3689. else
  3690. {
  3691. Debug::print(Debug::Classes,0," no template root entry found!\n");
  3692. // TODO: what happened if we get here?
  3693. }
  3694. //Debug::print(Debug::Classes,0," Template instance %s : \n",instanceClass->name().data());
  3695. //ArgumentList *tl = templateClass->templateArguments();
  3696. }
  3697. else
  3698. {
  3699. Debug::print(Debug::Classes,0," instance already exists!\n");
  3700. }
  3701. return TRUE;
  3702. }
  3703. static bool isRecursiveBaseClass(const QCString &scope,const QCString &name)
  3704. {
  3705. QCString n=name;
  3706. int index=n.find('<');
  3707. if (index!=-1)
  3708. {
  3709. n=n.left(index);
  3710. }
  3711. bool result = rightScopeMatch(scope,n);
  3712. return result;
  3713. }
  3714. /*! Searches for the end of a template in prototype \a s starting from
  3715. * character position \a startPos. If the end was found the position
  3716. * of the closing \> is returned, otherwise -1 is returned.
  3717. *
  3718. * Handles exotic cases such as
  3719. * \code
  3720. * Class<(id<0)>
  3721. * Class<bits<<2>
  3722. * Class<"<">
  3723. * Class<'<'>
  3724. * Class<(")<")>
  3725. * \endcode
  3726. */
  3727. static int findEndOfTemplate(const QCString &s,int startPos)
  3728. {
  3729. // locate end of template
  3730. int e=startPos;
  3731. int brCount=1;
  3732. int roundCount=0;
  3733. int len = s.length();
  3734. bool insideString=FALSE;
  3735. bool insideChar=FALSE;
  3736. char pc = 0;
  3737. while (e<len && brCount!=0)
  3738. {
  3739. char c=s.at(e);
  3740. switch(c)
  3741. {
  3742. case '<':
  3743. if (!insideString && !insideChar)
  3744. {
  3745. if (e<len-1 && s.at(e+1)=='<')
  3746. e++;
  3747. else if (roundCount==0)
  3748. brCount++;
  3749. }
  3750. break;
  3751. case '>':
  3752. if (!insideString && !insideChar)
  3753. {
  3754. if (e<len-1 && s.at(e+1)=='>')
  3755. e++;
  3756. else if (roundCount==0)
  3757. brCount--;
  3758. }
  3759. break;
  3760. case '(':
  3761. if (!insideString && !insideChar)
  3762. roundCount++;
  3763. break;
  3764. case ')':
  3765. if (!insideString && !insideChar)
  3766. roundCount--;
  3767. break;
  3768. case '"':
  3769. if (!insideChar)
  3770. {
  3771. if (insideString && pc!='\\')
  3772. insideString=FALSE;
  3773. else
  3774. insideString=TRUE;
  3775. }
  3776. break;
  3777. case '\'':
  3778. if (!insideString)
  3779. {
  3780. if (insideChar && pc!='\\')
  3781. insideChar=FALSE;
  3782. else
  3783. insideChar=TRUE;
  3784. }
  3785. break;
  3786. }
  3787. pc = c;
  3788. e++;
  3789. }
  3790. return brCount==0 ? e : -1;
  3791. }
  3792. static bool findClassRelation(
  3793. EntryNav *rootNav,
  3794. Definition *context,
  3795. ClassDef *cd,
  3796. BaseInfo *bi,
  3797. QDict<int> *templateNames,
  3798. FindBaseClassRelation_Mode mode,
  3799. bool isArtificial
  3800. )
  3801. {
  3802. //printf("findClassRelation(class=%s base=%s templateNames=",
  3803. // cd->name().data(),bi->name.data());
  3804. //if (templateNames)
  3805. //{
  3806. // QDictIterator<int> qdi(*templateNames);
  3807. // int *tempArgIndex;
  3808. // for (;(tempArgIndex=qdi.current());++qdi)
  3809. // {
  3810. // printf("(%s->%d) ",qdi.currentKey(),*tempArgIndex);
  3811. // }
  3812. //}
  3813. //printf("\n");
  3814. Entry *root = rootNav->entry();
  3815. QCString biName=bi->name;
  3816. bool explicitGlobalScope=FALSE;
  3817. //printf("findClassRelation: biName=`%s'\n",biName.data());
  3818. if (biName.left(2)=="::") // explicit global scope
  3819. {
  3820. biName=biName.right(biName.length()-2);
  3821. explicitGlobalScope=TRUE;
  3822. }
  3823. EntryNav *parentNode=rootNav->parent();
  3824. bool lastParent=FALSE;
  3825. do // for each parent scope, starting with the largest scope
  3826. // (in case of nested classes)
  3827. {
  3828. QCString scopeName= parentNode ? parentNode->name().data() : "";
  3829. int scopeOffset=explicitGlobalScope ? 0 : scopeName.length();
  3830. do // try all parent scope prefixes, starting with the largest scope
  3831. {
  3832. //printf("scopePrefix=`%s' biName=`%s'\n",
  3833. // scopeName.left(scopeOffset).data(),biName.data());
  3834. QCString baseClassName=biName;
  3835. if (scopeOffset>0)
  3836. {
  3837. baseClassName.prepend(scopeName.left(scopeOffset)+"::");
  3838. }
  3839. //QCString stripped;
  3840. //baseClassName=stripTemplateSpecifiersFromScope
  3841. // (removeRedundantWhiteSpace(baseClassName),TRUE,
  3842. // &stripped);
  3843. MemberDef *baseClassTypeDef=0;
  3844. QCString templSpec;
  3845. ClassDef *baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
  3846. cd->getFileDef(),
  3847. baseClassName,
  3848. &baseClassTypeDef,
  3849. &templSpec,
  3850. mode==Undocumented,
  3851. TRUE
  3852. );
  3853. //printf("baseClassName=%s baseClass=%p cd=%p explicitGlobalScope=%d\n",
  3854. // baseClassName.data(),baseClass,cd,explicitGlobalScope);
  3855. //printf(" scope=`%s' baseClassName=`%s' baseClass=%s templSpec=%s\n",
  3856. // cd ? cd->name().data():"<none>",
  3857. // baseClassName.data(),
  3858. // baseClass?baseClass->name().data():"<none>",
  3859. // templSpec.data()
  3860. // );
  3861. //if (baseClassName.left(root->name.length())!=root->name ||
  3862. // baseClassName.at(root->name.length())!='<'
  3863. // ) // Check for base class with the same name.
  3864. // // If found then look in the outer scope for a match
  3865. // // and prevent recursion.
  3866. if (!isRecursiveBaseClass(rootNav->name(),baseClassName) || explicitGlobalScope)
  3867. {
  3868. Debug::print(
  3869. Debug::Classes,0," class relation %s inherited/used by %s found (%s and %s) templSpec='%s'\n",
  3870. baseClassName.data(),
  3871. rootNav->name().data(),
  3872. (bi->prot==Private)?"private":((bi->prot==Protected)?"protected":"public"),
  3873. (bi->virt==Normal)?"normal":"virtual",
  3874. templSpec.data()
  3875. );
  3876. int i=baseClassName.find('<');
  3877. int si=baseClassName.findRev("::",i==-1 ? baseClassName.length() : i);
  3878. if (si==-1) si=0;
  3879. if (baseClass==0 && i!=-1)
  3880. // base class has template specifiers
  3881. {
  3882. // TODO: here we should try to find the correct template specialization
  3883. // but for now, we only look for the unspecializated base class.
  3884. int e=findEndOfTemplate(baseClassName,i+1);
  3885. //printf("baseClass==0 i=%d e=%d\n",i,e);
  3886. if (e!=-1) // end of template was found at e
  3887. {
  3888. templSpec=removeRedundantWhiteSpace(baseClassName.mid(i,e-i));
  3889. baseClassName=baseClassName.left(i)+baseClassName.right(baseClassName.length()-e);
  3890. baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
  3891. cd->getFileDef(),
  3892. baseClassName,
  3893. &baseClassTypeDef,
  3894. 0, //&templSpec,
  3895. mode==Undocumented,
  3896. TRUE
  3897. );
  3898. //printf("baseClass=%p -> baseClass=%s templSpec=%s\n",
  3899. // baseClass,baseClassName.data(),templSpec.data());
  3900. }
  3901. }
  3902. else if (baseClass && !templSpec.isEmpty()) // we have a known class, but also
  3903. // know it is a template, so see if
  3904. // we can also link to the explicit
  3905. // instance (for instance if a class
  3906. // derived from a template argument)
  3907. {
  3908. //printf("baseClass=%p templSpec=%s\n",baseClass,templSpec.data());
  3909. ClassDef *templClass=getClass(baseClass->name()+templSpec);
  3910. if (templClass)
  3911. {
  3912. // use the template instance instead of the template base.
  3913. baseClass = templClass;
  3914. templSpec.resize(0);
  3915. }
  3916. }
  3917. //printf("cd=%p baseClass=%p\n",cd,baseClass);
  3918. bool found=baseClass!=0 && (baseClass!=cd || mode==TemplateInstances);
  3919. //printf("1. found=%d\n",found);
  3920. if (!found && si!=-1)
  3921. {
  3922. QCString tmpTemplSpec;
  3923. // replace any namespace aliases
  3924. replaceNamespaceAliases(baseClassName,si);
  3925. baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
  3926. cd->getFileDef(),
  3927. baseClassName,
  3928. &baseClassTypeDef,
  3929. &tmpTemplSpec,
  3930. mode==Undocumented,
  3931. TRUE
  3932. );
  3933. found=baseClass!=0 && baseClass!=cd;
  3934. if (found) templSpec = tmpTemplSpec;
  3935. }
  3936. //printf("2. found=%d\n",found);
  3937. //printf("root->name=%s biName=%s baseClassName=%s\n",
  3938. // root->name.data(),biName.data(),baseClassName.data());
  3939. if (!found)
  3940. {
  3941. baseClass=findClassWithinClassContext(context,cd,baseClassName);
  3942. //printf("findClassWithinClassContext(%s,%s)=%p\n",
  3943. // cd->name().data(),baseClassName.data(),baseClass);
  3944. found = baseClass!=0 && baseClass!=cd;
  3945. }
  3946. bool isATemplateArgument = templateNames!=0 && templateNames->find(biName)!=0;
  3947. // make templSpec canonical
  3948. // Warning: the following line doesn't work for Mixin classes (see bug 560623)
  3949. // templSpec = getCanonicalTemplateSpec(cd, cd->getFileDef(), templSpec);
  3950. //printf("3. found=%d\n",found);
  3951. if (found)
  3952. {
  3953. Debug::print(Debug::Classes,0," Documented base class `%s' templSpec=%s\n",biName.data(),templSpec.isEmpty()?"":templSpec.data());
  3954. // add base class to this class
  3955. // if templSpec is not empty then we should "instantiate"
  3956. // the template baseClass. A new ClassDef should be created
  3957. // to represent the instance. To be able to add the (instantiated)
  3958. // members and documentation of a template class
  3959. // (inserted in that template class at a later stage),
  3960. // the template should know about its instances.
  3961. // the instantiation process, should be done in a recursive way,
  3962. // since instantiating a template may introduce new inheritance
  3963. // relations.
  3964. if (!templSpec.isEmpty() && mode==TemplateInstances)
  3965. {
  3966. // if baseClass is actually a typedef then we should not
  3967. // instantiate it, since typedefs are in a different namespace
  3968. // see bug531637 for an example where this would otherwise hang
  3969. // doxygen
  3970. if (baseClassTypeDef==0)
  3971. {
  3972. //printf(" => findTemplateInstanceRelation: %p\n",baseClassTypeDef);
  3973. findTemplateInstanceRelation(root,context,baseClass,templSpec,templateNames,isArtificial);
  3974. }
  3975. }
  3976. else if (mode==DocumentedOnly || mode==Undocumented)
  3977. {
  3978. //printf(" => insert base class\n");
  3979. QCString usedName;
  3980. if (baseClassTypeDef)
  3981. {
  3982. usedName=biName;
  3983. //printf("***** usedName=%s templSpec=%s\n",usedName.data(),templSpec.data());
  3984. }
  3985. if (Config_getBool("SIP_SUPPORT")) bi->prot=Public;
  3986. cd->insertBaseClass(baseClass,usedName,bi->prot,bi->virt,templSpec);
  3987. // add this class as super class to the base class
  3988. baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec);
  3989. }
  3990. return TRUE;
  3991. }
  3992. else if (mode==Undocumented && (scopeOffset==0 || isATemplateArgument))
  3993. {
  3994. Debug::print(Debug::Classes,0,
  3995. " New undocumented base class `%s' baseClassName=%s\n",
  3996. biName.data(),baseClassName.data()
  3997. );
  3998. baseClass=0;
  3999. if (isATemplateArgument)
  4000. {
  4001. baseClass=Doxygen::hiddenClasses->find(baseClassName);
  4002. if (baseClass==0)
  4003. {
  4004. baseClass=new ClassDef(root->fileName,root->startLine,
  4005. baseClassName,ClassDef::Class);
  4006. Doxygen::hiddenClasses->append(baseClassName,baseClass);
  4007. if (isArtificial) baseClass->setArtificial(TRUE);
  4008. }
  4009. }
  4010. else
  4011. {
  4012. baseClass=Doxygen::classSDict->find(baseClassName);
  4013. //printf("*** classDDict->find(%s)=%p biName=%s templSpec=%s\n",
  4014. // baseClassName.data(),baseClass,biName.data(),templSpec.data());
  4015. if (baseClass==0)
  4016. {
  4017. baseClass=new ClassDef(root->fileName,root->startLine,
  4018. baseClassName,ClassDef::Class);
  4019. Doxygen::classSDict->append(baseClassName,baseClass);
  4020. if (isArtificial) baseClass->setArtificial(TRUE);
  4021. }
  4022. }
  4023. // add base class to this class
  4024. cd->insertBaseClass(baseClass,biName,bi->prot,bi->virt,templSpec);
  4025. // add this class as super class to the base class
  4026. baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec);
  4027. // the undocumented base was found in this file
  4028. baseClass->insertUsedFile(root->fileName);
  4029. baseClass->setOuterScope(Doxygen::globalScope);
  4030. return TRUE;
  4031. }
  4032. else
  4033. {
  4034. Debug::print(Debug::Classes,0," Base class `%s' not found\n",biName.data());
  4035. }
  4036. }
  4037. else
  4038. {
  4039. if (mode!=TemplateInstances)
  4040. {
  4041. warn(root->fileName,root->startLine,
  4042. "Detected potential recursive class relation "
  4043. "between class %s and base class %s!\n",
  4044. root->name.data(),baseClassName.data()
  4045. );
  4046. }
  4047. // for mode==TemplateInstance this case is quite common and
  4048. // indicates a relation between a template class and a template
  4049. // instance with the same name.
  4050. }
  4051. if (scopeOffset==0)
  4052. {
  4053. scopeOffset=-1;
  4054. }
  4055. else if ((scopeOffset=scopeName.findRev("::",scopeOffset-1))==-1)
  4056. {
  4057. scopeOffset=0;
  4058. }
  4059. //printf("new scopeOffset=`%d'",scopeOffset);
  4060. } while (scopeOffset>=0);
  4061. if (parentNode==0)
  4062. {
  4063. lastParent=TRUE;
  4064. }
  4065. else
  4066. {
  4067. parentNode=parentNode->parent();
  4068. }
  4069. } while (lastParent);
  4070. return FALSE;
  4071. }
  4072. //----------------------------------------------------------------------
  4073. // Computes the base and super classes for each class in the tree
  4074. static bool isClassSection(EntryNav *rootNav)
  4075. {
  4076. if ( !rootNav->name().isEmpty() )
  4077. {
  4078. if (rootNav->section() & Entry::COMPOUND_MASK)
  4079. // is it a compound (class, struct, union, interface ...)
  4080. {
  4081. return TRUE;
  4082. }
  4083. else if (rootNav->section() & Entry::COMPOUNDDOC_MASK)
  4084. // is it a documentation block with inheritance info.
  4085. {
  4086. rootNav->loadEntry(g_storage);
  4087. Entry *root = rootNav->entry();
  4088. bool extends = root->extends->count()>0;
  4089. rootNav->releaseEntry();
  4090. if (extends) return TRUE;
  4091. }
  4092. }
  4093. return FALSE;
  4094. }
  4095. /*! Builds a dictionary of all entry nodes in the tree starting with \a root
  4096. */
  4097. static void findClassEntries(EntryNav *rootNav)
  4098. {
  4099. if (isClassSection(rootNav))
  4100. {
  4101. g_classEntries.insert(rootNav->name(),rootNav);
  4102. }
  4103. RECURSE_ENTRYTREE(findClassEntries,rootNav);
  4104. }
  4105. /*! Using the dictionary build by findClassEntries(), this
  4106. * function will look for additional template specialization that
  4107. * exists as inheritance relations only. These instances will be
  4108. * added to the template they are derived from.
  4109. */
  4110. static void findInheritedTemplateInstances()
  4111. {
  4112. ClassSDict::Iterator cli(*Doxygen::classSDict);
  4113. for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
  4114. QDictIterator<EntryNav> edi(g_classEntries);
  4115. EntryNav *rootNav;
  4116. for (;(rootNav=edi.current());++edi)
  4117. {
  4118. ClassDef *cd;
  4119. // strip any annonymous scopes first
  4120. QCString bName=stripAnonymousNamespaceScope(rootNav->name());
  4121. bName=stripTemplateSpecifiersFromScope(bName);
  4122. Debug::print(Debug::Classes,0," Inheritance: Class %s : \n",bName.data());
  4123. if ((cd=getClass(bName)))
  4124. {
  4125. rootNav->loadEntry(g_storage);
  4126. //printf("Class %s %d\n",cd->name().data(),root->extends->count());
  4127. findBaseClassesForClass(rootNav,cd,cd,cd,TemplateInstances,FALSE);
  4128. rootNav->releaseEntry();
  4129. }
  4130. }
  4131. }
  4132. static void findUsedTemplateInstances()
  4133. {
  4134. ClassSDict::Iterator cli(*Doxygen::classSDict);
  4135. for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
  4136. QDictIterator<EntryNav> edi(g_classEntries);
  4137. EntryNav *rootNav;
  4138. for (;(rootNav=edi.current());++edi)
  4139. {
  4140. ClassDef *cd;
  4141. // strip any annonymous scopes first
  4142. QCString bName=stripAnonymousNamespaceScope(rootNav->name());
  4143. bName=stripTemplateSpecifiersFromScope(bName);
  4144. Debug::print(Debug::Classes,0," Usage: Class %s : \n",bName.data());
  4145. if ((cd=getClass(bName)))
  4146. {
  4147. rootNav->loadEntry(g_storage);
  4148. findUsedClassesForClass(rootNav,cd,cd,cd,TRUE);
  4149. rootNav->releaseEntry();
  4150. }
  4151. }
  4152. }
  4153. static void computeClassRelations()
  4154. {
  4155. ClassSDict::Iterator cli(*Doxygen::classSDict);
  4156. for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
  4157. QDictIterator<EntryNav> edi(g_classEntries);
  4158. EntryNav *rootNav;
  4159. for (;(rootNav=edi.current());++edi)
  4160. {
  4161. ClassDef *cd;
  4162. rootNav->loadEntry(g_storage);
  4163. Entry *root = rootNav->entry();
  4164. // strip any annonymous scopes first
  4165. QCString bName=stripAnonymousNamespaceScope(rootNav->name());
  4166. bName=stripTemplateSpecifiersFromScope(bName);
  4167. Debug::print(Debug::Classes,0," Relations: Class %s : \n",bName.data());
  4168. if ((cd=getClass(bName)))
  4169. {
  4170. findBaseClassesForClass(rootNav,cd,cd,cd,DocumentedOnly,FALSE);
  4171. }
  4172. if ((cd==0 || (!cd->hasDocumentation() && !cd->isReference())) &&
  4173. bName.right(2)!="::")
  4174. {
  4175. if (!root->name.isEmpty() && root->name.find('@')==-1 && // normal name
  4176. (guessSection(root->fileName)==Entry::HEADER_SEC ||
  4177. Config_getBool("EXTRACT_LOCAL_CLASSES")) && // not defined in source file
  4178. (root->protection!=Private || Config_getBool("EXTRACT_PRIVATE")) && // hidden by protection
  4179. !Config_getBool("HIDE_UNDOC_CLASSES") // undocumented class are visible
  4180. )
  4181. warn_undoc(
  4182. root->fileName,root->startLine,
  4183. "Warning: Compound %s is not documented.",
  4184. root->name.data()
  4185. );
  4186. }
  4187. rootNav->releaseEntry();
  4188. }
  4189. }
  4190. static void computeTemplateClassRelations()
  4191. {
  4192. QDictIterator<EntryNav> edi(g_classEntries);
  4193. EntryNav *rootNav;
  4194. for (;(rootNav=edi.current());++edi)
  4195. {
  4196. rootNav->loadEntry(g_storage);
  4197. Entry *root = rootNav->entry();
  4198. QCString bName=stripAnonymousNamespaceScope(root->name);
  4199. bName=stripTemplateSpecifiersFromScope(bName);
  4200. ClassDef *cd=getClass(bName);
  4201. // strip any annonymous scopes first
  4202. QDict<ClassDef> *templInstances = 0;
  4203. if (cd && (templInstances=cd->getTemplateInstances()))
  4204. {
  4205. Debug::print(Debug::Classes,0," Template class %s : \n",cd->name().data());
  4206. QDictIterator<ClassDef> tdi(*templInstances);
  4207. ClassDef *tcd;
  4208. for (tdi.toFirst();(tcd=tdi.current());++tdi) // for each template instance
  4209. {
  4210. Debug::print(Debug::Classes,0," Template instance %s : \n",tcd->name().data());
  4211. QCString templSpec = tdi.currentKey();
  4212. ArgumentList *templArgs = new ArgumentList;
  4213. stringToArgumentList(templSpec,templArgs);
  4214. QList<BaseInfo> *baseList=root->extends;
  4215. BaseInfo *bi=baseList->first();
  4216. while (bi) // for each base class of the template
  4217. {
  4218. // check if the base class is a template argument
  4219. BaseInfo tbi(bi->name,bi->prot,bi->virt);
  4220. ArgumentList *tl = cd->templateArguments();
  4221. if (tl)
  4222. {
  4223. QDict<int> *baseClassNames = tcd->getTemplateBaseClassNames();
  4224. QDict<int> *templateNames = getTemplateArgumentsInName(tl,bi->name);
  4225. // for each template name that we inherit from we need to
  4226. // substitute the formal with the actual arguments
  4227. QDict<int> *actualTemplateNames = new QDict<int>(17);
  4228. actualTemplateNames->setAutoDelete(TRUE);
  4229. QDictIterator<int> qdi(*templateNames);
  4230. for (qdi.toFirst();qdi.current();++qdi)
  4231. {
  4232. int templIndex = *qdi.current();
  4233. Argument *actArg = 0;
  4234. if (templIndex<(int)templArgs->count())
  4235. {
  4236. actArg=templArgs->at(templIndex);
  4237. }
  4238. if (actArg!=0 &&
  4239. baseClassNames!=0 &&
  4240. baseClassNames->find(actArg->type)!=0 &&
  4241. actualTemplateNames->find(actArg->type)==0
  4242. )
  4243. {
  4244. actualTemplateNames->insert(actArg->type,new int(templIndex));
  4245. }
  4246. }
  4247. delete templateNames;
  4248. tbi.name = substituteTemplateArgumentsInString(bi->name,tl,templArgs);
  4249. // find a documented base class in the correct scope
  4250. if (!findClassRelation(rootNav,cd,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE))
  4251. {
  4252. // no documented base class -> try to find an undocumented one
  4253. findClassRelation(rootNav,cd,tcd,&tbi,actualTemplateNames,Undocumented,FALSE);
  4254. }
  4255. delete actualTemplateNames;
  4256. }
  4257. bi=baseList->next();
  4258. }
  4259. delete templArgs;
  4260. } // class has no base classes
  4261. }
  4262. rootNav->releaseEntry();
  4263. }
  4264. }
  4265. //-----------------------------------------------------------------------
  4266. // compute the references (anchors in HTML) for each function in the file
  4267. static void computeMemberReferences()
  4268. {
  4269. ClassSDict::Iterator cli(*Doxygen::classSDict);
  4270. ClassDef *cd=0;
  4271. for (cli.toFirst();(cd=cli.current());++cli)
  4272. {
  4273. cd->computeAnchors();
  4274. }
  4275. FileName *fn=Doxygen::inputNameList->first();
  4276. while (fn)
  4277. {
  4278. FileDef *fd=fn->first();
  4279. while (fd)
  4280. {
  4281. fd->computeAnchors();
  4282. fd=fn->next();
  4283. }
  4284. fn=Doxygen::inputNameList->next();
  4285. }
  4286. NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
  4287. NamespaceDef *nd=0;
  4288. for (nli.toFirst();(nd=nli.current());++nli)
  4289. {
  4290. nd->computeAnchors();
  4291. }
  4292. GroupSDict::Iterator gli(*Doxygen::groupSDict);
  4293. GroupDef *gd;
  4294. for (gli.toFirst();(gd=gli.current());++gli)
  4295. {
  4296. gd->computeAnchors();
  4297. }
  4298. }
  4299. //----------------------------------------------------------------------
  4300. static void addListReferences()
  4301. {
  4302. MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
  4303. MemberName *mn=0;
  4304. for (mnli.toFirst();(mn=mnli.current());++mnli)
  4305. {
  4306. MemberNameIterator mni(*mn);
  4307. MemberDef *md=0;
  4308. for (mni.toFirst();(md=mni.current());++mni)
  4309. {
  4310. md->visited=FALSE;
  4311. }
  4312. }
  4313. MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
  4314. for (fnli.toFirst();(mn=fnli.current());++fnli)
  4315. {
  4316. MemberNameIterator mni(*mn);
  4317. MemberDef *md=0;
  4318. for (mni.toFirst();(md=mni.current());++mni)
  4319. {
  4320. md->visited=FALSE;
  4321. }
  4322. }
  4323. ClassSDict::Iterator cli(*Doxygen::classSDict);
  4324. ClassDef *cd=0;
  4325. for (cli.toFirst();(cd=cli.current());++cli)
  4326. {
  4327. cd->addListReferences();
  4328. }
  4329. FileName *fn=Doxygen::inputNameList->first();
  4330. while (fn)
  4331. {
  4332. FileDef *fd=fn->first();
  4333. while (fd)
  4334. {
  4335. fd->addListReferences();
  4336. fd=fn->next();
  4337. }
  4338. fn=Doxygen::inputNameList->next();
  4339. }
  4340. NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
  4341. NamespaceDef *nd=0;
  4342. for (nli.toFirst();(nd=nli.current());++nli)
  4343. {
  4344. nd->addListReferences();
  4345. }
  4346. GroupSDict::Iterator gli(*Doxygen::groupSDict);
  4347. GroupDef *gd;
  4348. for (gli.toFirst();(gd=gli.current());++gli)
  4349. {
  4350. gd->addListReferences();
  4351. }
  4352. PageSDict::Iterator pdi(*Doxygen::pageSDict);
  4353. PageDef *pd=0;
  4354. for (pdi.toFirst();(pd=pdi.current());++pdi)
  4355. {
  4356. QCString name = pd->name();
  4357. if (pd->getGroupDef())
  4358. {
  4359. name = pd->getGroupDef()->getOutputFileBase();
  4360. }
  4361. {
  4362. LockingPtr< QList<ListItemInfo> > xrefItems = pd->xrefListItems();
  4363. addRefItem(xrefItems.pointer(),
  4364. name,
  4365. theTranslator->trPage(TRUE,TRUE),
  4366. name,pd->title(),0);
  4367. }
  4368. }
  4369. DirSDict::Iterator ddi(*Doxygen::directories);
  4370. DirDef *dd = 0;
  4371. for (ddi.toFirst();(dd=ddi.current());++ddi)
  4372. {
  4373. QCString name = dd->getOutputFileBase();
  4374. //if (dd->getGroupDef())
  4375. //{
  4376. // name = dd->getGroupDef()->getOutputFileBase();
  4377. //}
  4378. LockingPtr< QList<ListItemInfo> > xrefItems = dd->xrefListItems();
  4379. addRefItem(xrefItems.pointer(),
  4380. name,
  4381. theTranslator->trDir(TRUE,TRUE),
  4382. name,dd->displayName(),0);
  4383. }
  4384. }
  4385. //----------------------------------------------------------------------
  4386. static void generateXRefPages()
  4387. {
  4388. QDictIterator<RefList> di(*Doxygen::xrefLists);
  4389. RefList *rl;
  4390. for (di.toFirst();(rl=di.current());++di)
  4391. {
  4392. rl->generatePage();
  4393. }
  4394. }
  4395. //----------------------------------------------------------------------
  4396. // Copy the documentation in entry `root' to member definition `md' and
  4397. // set the function declaration of the member to `funcDecl'. If the boolean
  4398. // over_load is set the standard overload text is added.
  4399. static void addMemberDocs(EntryNav *rootNav,
  4400. MemberDef *md, const char *funcDecl,
  4401. ArgumentList *al,
  4402. bool over_load,
  4403. NamespaceSDict *
  4404. )
  4405. {
  4406. Entry *root = rootNav->entry();
  4407. //printf("addMemberDocs: `%s'::`%s' `%s' funcDecl=`%s' mSpec=%d\n",
  4408. // root->parent->name.data(),md->name().data(),md->argsString(),funcDecl,root->spec);
  4409. QCString fDecl=funcDecl;
  4410. // strip extern specifier
  4411. fDecl.stripPrefix("extern ");
  4412. md->setDefinition(fDecl);
  4413. md->enableCallGraph(root->callGraph);
  4414. md->enableCallerGraph(root->callerGraph);
  4415. ClassDef *cd=md->getClassDef();
  4416. NamespaceDef *nd=md->getNamespaceDef();
  4417. QCString fullName;
  4418. if (cd)
  4419. fullName = cd->name();
  4420. else if (nd)
  4421. fullName = nd->name();
  4422. if (!fullName.isEmpty()) fullName+="::";
  4423. fullName+=md->name();
  4424. FileDef *rfd=rootNav->fileDef();
  4425. // TODO determine scope based on root not md
  4426. Definition *rscope = md->getOuterScope();
  4427. LockingPtr<ArgumentList> mdAl = md->argumentList();
  4428. if (al)
  4429. {
  4430. //printf("merging arguments (1) docs=%d\n",root->doc.isEmpty());
  4431. mergeArguments(mdAl.pointer(),al,!root->doc.isEmpty());
  4432. }
  4433. else
  4434. {
  4435. if (
  4436. matchArguments2( md->getOuterScope(), md->getFileDef(), mdAl.pointer(),
  4437. rscope,rfd,root->argList,
  4438. TRUE
  4439. )
  4440. )
  4441. {
  4442. //printf("merging arguments (2)\n");
  4443. mergeArguments(mdAl.pointer(),root->argList,!root->doc.isEmpty());
  4444. }
  4445. }
  4446. if (over_load) // the \overload keyword was used
  4447. {
  4448. QCString doc=getOverloadDocs();
  4449. if (!root->doc.isEmpty())
  4450. {
  4451. doc+="<p>";
  4452. doc+=root->doc;
  4453. }
  4454. md->setDocumentation(doc,root->docFile,root->docLine);
  4455. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  4456. md->setDocsForDefinition(!root->proto);
  4457. }
  4458. else
  4459. {
  4460. //printf("overwrite!\n");
  4461. md->setDocumentation(root->doc,root->docFile,root->docLine);
  4462. md->setDocsForDefinition(!root->proto);
  4463. //printf("overwrite!\n");
  4464. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  4465. if (
  4466. (md->inbodyDocumentation().isEmpty() ||
  4467. !rootNav->parent()->name().isEmpty()
  4468. ) && !root->inbodyDocs.isEmpty()
  4469. )
  4470. {
  4471. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  4472. }
  4473. }
  4474. //printf("initializer: '%s'(isEmpty=%d) '%s'(isEmpty=%d)\n",
  4475. // md->initializer().data(),md->initializer().isEmpty(),
  4476. // root->initializer.data(),root->initializer.isEmpty()
  4477. // );
  4478. if (md->initializer().isEmpty() && !root->initializer.isEmpty())
  4479. {
  4480. //printf("setInitializer\n");
  4481. md->setInitializer(root->initializer);
  4482. }
  4483. md->setMaxInitLines(root->initLines);
  4484. if (rfd)
  4485. {
  4486. if ((md->getStartBodyLine()==-1 && root->bodyLine!=-1)
  4487. )
  4488. {
  4489. //printf("Setting new body segment [%d,%d]\n",root->bodyLine,root->endBodyLine);
  4490. md->setBodySegment(root->bodyLine,root->endBodyLine);
  4491. md->setBodyDef(rfd);
  4492. }
  4493. md->setRefItems(root->sli);
  4494. }
  4495. md->enableCallGraph(md->hasCallGraph() || root->callGraph);
  4496. md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
  4497. md->mergeMemberSpecifiers(root->spec);
  4498. md->addSectionsToDefinition(root->anchors);
  4499. addMemberToGroups(root,md);
  4500. if (cd) cd->insertUsedFile(root->fileName);
  4501. //printf("root->mGrpId=%d\n",root->mGrpId);
  4502. if (root->mGrpId!=-1)
  4503. {
  4504. if (md->getMemberGroupId()!=-1)
  4505. {
  4506. if (md->getMemberGroupId()!=root->mGrpId)
  4507. {
  4508. warn(
  4509. root->fileName,root->startLine,
  4510. "Warning: member %s belongs to two different groups. The second "
  4511. "one found here will be ignored.",
  4512. md->name().data()
  4513. );
  4514. }
  4515. }
  4516. else // set group id
  4517. {
  4518. //printf("setMemberGroupId=%d md=%s\n",root->mGrpId,md->name().data());
  4519. md->setMemberGroupId(root->mGrpId);
  4520. }
  4521. }
  4522. }
  4523. //----------------------------------------------------------------------
  4524. // find a class definition given the scope name and (optionally) a
  4525. // template list specifier
  4526. static ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd,
  4527. const char *scopeName)
  4528. {
  4529. ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE);
  4530. return tcd;
  4531. }
  4532. //----------------------------------------------------------------------
  4533. // Adds the documentation contained in `root' to a global function
  4534. // with name `name' and argument list `args' (for overloading) and
  4535. // function declaration `decl' to the corresponding member definition.
  4536. static bool findGlobalMember(EntryNav *rootNav,
  4537. const QCString &namespaceName,
  4538. const char *name,
  4539. const char *tempArg,
  4540. const char *,
  4541. const char *decl)
  4542. {
  4543. Entry *root = rootNav->entry();
  4544. Debug::print(Debug::FindMembers,0,
  4545. "2. findGlobalMember(namespace=%s,name=%s,tempArg=%s,decl=%s)\n",
  4546. namespaceName.data(),name,tempArg,decl);
  4547. QCString n=name;
  4548. if (n.isEmpty()) return FALSE;
  4549. if (n.find("::")!=-1) return FALSE; // skip undefined class members
  4550. MemberName *mn=Doxygen::functionNameSDict->find(n+tempArg); // look in function dictionary
  4551. if (mn==0)
  4552. {
  4553. mn=Doxygen::functionNameSDict->find(n); // try without template arguments
  4554. }
  4555. if (mn) // function name defined
  4556. {
  4557. Debug::print(Debug::FindMembers,0,"3. Found function scope\n");
  4558. //int count=0;
  4559. MemberNameIterator mni(*mn);
  4560. MemberDef *md;
  4561. bool found=FALSE;
  4562. for (mni.toFirst();(md=mni.current()) && !found;++mni)
  4563. {
  4564. NamespaceDef *nd=md->getNamespaceDef();
  4565. //printf("Namespace namespaceName=%s nd=%s\n",
  4566. // namespaceName.data(),nd ? nd->name().data() : "<none>");
  4567. FileDef *fd=rootNav->fileDef();
  4568. //printf("File %s\n",fd ? fd->name().data() : "<none>");
  4569. NamespaceSDict *nl = fd ? fd->getUsedNamespaces() : 0;
  4570. //SDict<Definition> *cl = fd ? fd->getUsedClasses() : 0;
  4571. //printf("NamespaceList %p\n",nl);
  4572. // search in the list of namespaces that are imported via a
  4573. // using declaration
  4574. bool viaUsingDirective = nl && nd && nl->find(nd->qualifiedName())!=0;
  4575. if ((namespaceName.isEmpty() && nd==0) || // not in a namespace
  4576. (nd && nd->name()==namespaceName) || // or in the same namespace
  4577. viaUsingDirective // member in `using' namespace
  4578. )
  4579. {
  4580. Debug::print(Debug::FindMembers,0,"4. Try to add member `%s' to scope `%s'\n",
  4581. md->name().data(),namespaceName.data());
  4582. QCString nsName = nd ? nd->name().data() : "";
  4583. NamespaceDef *rnd = 0;
  4584. if (!namespaceName.isEmpty()) rnd = Doxygen::namespaceSDict->find(namespaceName);
  4585. LockingPtr<ArgumentList> mdAl = md->argumentList();
  4586. bool matching=
  4587. (mdAl==0 && root->argList->count()==0) ||
  4588. md->isVariable() || md->isTypedef() || /* in case of function pointers */
  4589. matchArguments2(md->getOuterScope(),md->getFileDef(),mdAl.pointer(),
  4590. rnd ? rnd : Doxygen::globalScope,fd,root->argList,
  4591. FALSE);
  4592. // for template members we need to check if the number of
  4593. // template arguments is the same, otherwise we are dealing with
  4594. // different functions.
  4595. if (matching && root->tArgLists)
  4596. {
  4597. LockingPtr<ArgumentList> mdTempl = md->templateArguments();
  4598. if (mdTempl!=0)
  4599. {
  4600. if (root->tArgLists->getLast()->count()!=mdTempl->count())
  4601. {
  4602. matching=FALSE;
  4603. }
  4604. }
  4605. }
  4606. //printf("%s<->%s\n",
  4607. // argListToString(md->argumentList()).data(),
  4608. // argListToString(root->argList).data());
  4609. // for static members we also check if the comment block was found in
  4610. // the same file. This is needed because static members with the same
  4611. // name can be in different files. Thus it would be wrong to just
  4612. // put the comment block at the first syntactically matching member.
  4613. if (matching && md->isStatic() &&
  4614. md->getDefFileName()!=root->fileName &&
  4615. mn->count()>1)
  4616. {
  4617. matching = FALSE;
  4618. }
  4619. if (matching) // add docs to the member
  4620. {
  4621. Debug::print(Debug::FindMembers,0,"5. Match found\n");
  4622. addMemberDocs(rootNav,md,decl,root->argList,FALSE);
  4623. found=TRUE;
  4624. }
  4625. }
  4626. }
  4627. if (!found && root->relatesType != Duplicate) // no match
  4628. {
  4629. QCString fullFuncDecl=decl;
  4630. if (root->argList) fullFuncDecl+=argListToString(root->argList,TRUE);
  4631. warn(root->fileName,root->startLine,
  4632. "Warning: no matching file member found for \n%s",fullFuncDecl.data());
  4633. if (mn->count()>0)
  4634. {
  4635. warn_cont("Possible candidates:\n");
  4636. for (mni.toFirst();(md=mni.current());++mni)
  4637. {
  4638. warn_cont(" %s\n",md->declaration());
  4639. }
  4640. }
  4641. }
  4642. }
  4643. else // got docs for an undefined member!
  4644. {
  4645. if (root->type!="friend class" &&
  4646. root->type!="friend struct" &&
  4647. root->type!="friend union" &&
  4648. (!Config_getBool("TYPEDEF_HIDES_STRUCT") ||
  4649. root->type.find("typedef ")==-1)
  4650. )
  4651. {
  4652. warn(root->fileName,root->startLine,
  4653. "Warning: documented function `%s' was not declared or defined.",decl
  4654. );
  4655. }
  4656. }
  4657. return TRUE;
  4658. }
  4659. static bool isSpecialization(
  4660. const QList<ArgumentList> &srcTempArgLists,
  4661. const QList<ArgumentList> &dstTempArgLists
  4662. )
  4663. {
  4664. QListIterator<ArgumentList> srclali(srcTempArgLists);
  4665. QListIterator<ArgumentList> dstlali(dstTempArgLists);
  4666. for (;srclali.current();++srclali,++dstlali)
  4667. {
  4668. ArgumentList *sal = srclali.current();
  4669. ArgumentList *dal = dstlali.current();
  4670. if (!(sal && dal && sal->count()==dal->count())) return TRUE;
  4671. }
  4672. return FALSE;
  4673. }
  4674. static QCString substituteTemplatesInString(
  4675. const QList<ArgumentList> &srcTempArgLists,
  4676. const QList<ArgumentList> &dstTempArgLists,
  4677. ArgumentList *funcTempArgList, // can be used to match template specializations
  4678. const QCString &src
  4679. )
  4680. {
  4681. QCString dst;
  4682. QRegExp re( "[A-Za-z_][A-Za-z_0-9]*");
  4683. //printf("type=%s\n",sa->type.data());
  4684. int i,p=0,l;
  4685. while ((i=re.match(src,p,&l))!=-1) // for each word in srcType
  4686. {
  4687. bool found=FALSE;
  4688. dst+=src.mid(p,i-p);
  4689. QCString name=src.mid(i,l);
  4690. QListIterator<ArgumentList> srclali(srcTempArgLists);
  4691. QListIterator<ArgumentList> dstlali(dstTempArgLists);
  4692. for (;srclali.current() && !found;++srclali,++dstlali)
  4693. {
  4694. ArgumentListIterator tsali(*srclali.current());
  4695. ArgumentListIterator tdali(*dstlali.current());
  4696. Argument *tsa =0,*tda=0, *fa=0;
  4697. if (funcTempArgList)
  4698. {
  4699. fa=funcTempArgList->first();
  4700. }
  4701. for (tsali.toFirst();(tsa=tsali.current()) && !found;++tsali)
  4702. {
  4703. tda = tdali.current();
  4704. //if (tda) printf("tsa=%s|%s tda=%s|%s\n",
  4705. // tsa->type.data(),tsa->name.data(),
  4706. // tda->type.data(),tda->name.data());
  4707. if (name==tsa->name)
  4708. {
  4709. if (tda && tda->name.isEmpty())
  4710. {
  4711. int vc=0;
  4712. if (tda->type.left(6)=="class ") vc=6;
  4713. else if (tda->type.left(9)=="typename ") vc=9;
  4714. if (vc>0) // convert type=="class T" to type=="class" name=="T"
  4715. {
  4716. tda->name = tda->type.mid(vc);
  4717. tda->type = tda->type.left(vc-1);
  4718. }
  4719. }
  4720. if (tda && !tda->name.isEmpty())
  4721. {
  4722. name=tda->name; // substitute
  4723. found=TRUE;
  4724. }
  4725. else if (fa)
  4726. {
  4727. name=fa->type;
  4728. found=TRUE;
  4729. }
  4730. }
  4731. if (tda)
  4732. ++tdali;
  4733. else if (fa)
  4734. fa=funcTempArgList->next();
  4735. }
  4736. //printf(" srcList='%s' dstList='%s faList='%s'\n",
  4737. // argListToString(srclali.current()).data(),
  4738. // argListToString(dstlali.current()).data(),
  4739. // funcTempArgList ? argListToString(funcTempArgList).data() : "<none>");
  4740. }
  4741. dst+=name;
  4742. p=i+l;
  4743. }
  4744. dst+=src.right(src.length()-p);
  4745. //printf(" substituteTemplatesInString(%s)=%s\n",
  4746. // src.data(),dst.data());
  4747. return dst;
  4748. }
  4749. static void substituteTemplatesInArgList(
  4750. const QList<ArgumentList> &srcTempArgLists,
  4751. const QList<ArgumentList> &dstTempArgLists,
  4752. ArgumentList *src,
  4753. ArgumentList *dst,
  4754. ArgumentList *funcTempArgs = 0
  4755. )
  4756. {
  4757. ArgumentListIterator sali(*src);
  4758. Argument *sa=0;
  4759. Argument *da=dst->first();
  4760. for (sali.toFirst();(sa=sali.current());++sali) // for each member argument
  4761. {
  4762. QCString dstType = substituteTemplatesInString(
  4763. srcTempArgLists,dstTempArgLists,funcTempArgs,
  4764. sa->type);
  4765. QCString dstArray = substituteTemplatesInString(
  4766. srcTempArgLists,dstTempArgLists,funcTempArgs,
  4767. sa->array);
  4768. if (da==0)
  4769. {
  4770. da=new Argument(*sa);
  4771. dst->append(da);
  4772. da->type=dstType;
  4773. da->array=dstArray;
  4774. da=0;
  4775. }
  4776. else
  4777. {
  4778. da->type=dstType;
  4779. da->type=dstArray;
  4780. da=dst->next();
  4781. }
  4782. }
  4783. dst->constSpecifier = src->constSpecifier;
  4784. dst->volatileSpecifier = src->volatileSpecifier;
  4785. dst->pureSpecifier = src->pureSpecifier;
  4786. //printf("substituteTemplatesInArgList: replacing %s with %s\n",
  4787. // argListToString(src).data(),argListToString(dst).data()
  4788. // );
  4789. }
  4790. /*! This function tries to find a member (in a documented class/file/namespace)
  4791. * that corresponds to the function/variable declaration given in \a funcDecl.
  4792. *
  4793. * The boolean \a overloaded is used to specify whether or not a standard
  4794. * overload documentation line should be generated.
  4795. *
  4796. * The boolean \a isFunc is a hint that indicates that this is a function
  4797. * instead of a variable or typedef.
  4798. */
  4799. static void findMember(EntryNav *rootNav,
  4800. QCString funcDecl,
  4801. bool overloaded,
  4802. bool isFunc
  4803. )
  4804. {
  4805. Entry *root = rootNav->entry();
  4806. Debug::print(Debug::FindMembers,0,
  4807. "findMember(root=%p,funcDecl=`%s',related=`%s',overload=%d,"
  4808. "isFunc=%d mGrpId=%d tArgList=%p (#=%d) "
  4809. "spec=%d isObjC=%d\n",
  4810. root,funcDecl.data(),root->relates.data(),overloaded,isFunc,root->mGrpId,
  4811. root->tArgLists,root->tArgLists ? root->tArgLists->count() : 0,
  4812. root->spec,root->objc
  4813. );
  4814. QCString scopeName;
  4815. QCString className;
  4816. QCString namespaceName;
  4817. QCString funcType;
  4818. QCString funcName;
  4819. QCString funcArgs;
  4820. QCString funcTempList;
  4821. QCString exceptions;
  4822. QCString funcSpec;
  4823. bool isRelated=FALSE;
  4824. bool isMemberOf=FALSE;
  4825. bool isFriend=FALSE;
  4826. bool done;
  4827. do
  4828. {
  4829. done=TRUE;
  4830. if (funcDecl.stripPrefix("friend ")) // treat friends as related members
  4831. {
  4832. isFriend=TRUE;
  4833. done=FALSE;
  4834. }
  4835. if (funcDecl.stripPrefix("inline "))
  4836. {
  4837. root->spec|=Entry::Inline;
  4838. done=FALSE;
  4839. }
  4840. if (funcDecl.stripPrefix("explicit "))
  4841. {
  4842. root->spec|=Entry::Explicit;
  4843. done=FALSE;
  4844. }
  4845. if (funcDecl.stripPrefix("mutable "))
  4846. {
  4847. root->spec|=Entry::Mutable;
  4848. done=FALSE;
  4849. }
  4850. if (funcDecl.stripPrefix("virtual "))
  4851. {
  4852. done=FALSE;
  4853. }
  4854. } while (!done);
  4855. // delete any ; from the function declaration
  4856. int sep;
  4857. while ((sep=funcDecl.find(';'))!=-1)
  4858. {
  4859. funcDecl=(funcDecl.left(sep)+funcDecl.right(funcDecl.length()-sep-1)).stripWhiteSpace();
  4860. }
  4861. // make sure the first character is a space to simplify searching.
  4862. if (!funcDecl.isEmpty() && funcDecl[0]!=' ') funcDecl.prepend(" ");
  4863. // remove some superfluous spaces
  4864. funcDecl= substitute(
  4865. substitute(
  4866. substitute(funcDecl,"~ ","~"),
  4867. ":: ","::"
  4868. ),
  4869. " ::","::"
  4870. ).stripWhiteSpace();
  4871. //printf("funcDecl=`%s'\n",funcDecl.data());
  4872. if (isFriend && funcDecl.left(6)=="class ")
  4873. {
  4874. //printf("friend class\n");
  4875. funcDecl=funcDecl.right(funcDecl.length()-6);
  4876. funcName = funcDecl.copy();
  4877. }
  4878. else if (isFriend && funcDecl.left(7)=="struct ")
  4879. {
  4880. funcDecl=funcDecl.right(funcDecl.length()-7);
  4881. funcName = funcDecl.copy();
  4882. }
  4883. else
  4884. {
  4885. // extract information from the declarations
  4886. parseFuncDecl(funcDecl,root->objc,scopeName,funcType,funcName,
  4887. funcArgs,funcTempList,exceptions
  4888. );
  4889. }
  4890. //printf("scopeName=`%s' funcType=`%s' funcName=`%s' funcArgs=`%s'\n",
  4891. // scopeName.data(),funcType.data(),funcName.data(),funcArgs.data());
  4892. // the class name can also be a namespace name, we decide this later.
  4893. // if a related class name is specified and the class name could
  4894. // not be derived from the function declaration, then use the
  4895. // related field.
  4896. //printf("scopeName=`%s' className=`%s' namespaceName=`%s'\n",
  4897. // scopeName.data(),className.data(),namespaceName.data());
  4898. if (!root->relates.isEmpty())
  4899. { // related member, prefix user specified scope
  4900. isRelated=TRUE;
  4901. isMemberOf=(root->relatesType == MemberOf);
  4902. if (getClass(root->relates)==0 && !scopeName.isEmpty())
  4903. {
  4904. scopeName= mergeScopes(scopeName,root->relates);
  4905. }
  4906. else
  4907. {
  4908. scopeName = root->relates;
  4909. }
  4910. }
  4911. if (root->relates.isEmpty() && rootNav->parent() &&
  4912. ((rootNav->parent()->section()&Entry::SCOPE_MASK) ||
  4913. (rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
  4914. ) &&
  4915. !rootNav->parent()->name().isEmpty()) // see if we can combine scopeName
  4916. // with the scope in which it was found
  4917. {
  4918. QCString joinedName = rootNav->parent()->name()+"::"+scopeName;
  4919. if (!scopeName.isEmpty() &&
  4920. (getClass(joinedName) || Doxygen::namespaceSDict->find(joinedName)))
  4921. {
  4922. scopeName = joinedName;
  4923. }
  4924. else
  4925. {
  4926. scopeName = mergeScopes(rootNav->parent()->name(),scopeName);
  4927. }
  4928. }
  4929. else // see if we can prefix a namespace or class that is used from the file
  4930. {
  4931. FileDef *fd=rootNav->fileDef();
  4932. if (fd)
  4933. {
  4934. NamespaceSDict *fnl = fd->getUsedNamespaces();
  4935. if (fnl)
  4936. {
  4937. QCString joinedName;
  4938. NamespaceDef *fnd;
  4939. NamespaceSDict::Iterator nsdi(*fnl);
  4940. for (nsdi.toFirst();(fnd=nsdi.current());++nsdi)
  4941. {
  4942. joinedName = fnd->name()+"::"+scopeName;
  4943. if (Doxygen::namespaceSDict->find(joinedName))
  4944. {
  4945. scopeName=joinedName;
  4946. break;
  4947. }
  4948. }
  4949. }
  4950. }
  4951. }
  4952. scopeName=stripTemplateSpecifiersFromScope(
  4953. removeRedundantWhiteSpace(scopeName),FALSE,&funcSpec);
  4954. // funcSpec contains the last template specifiers of the given scope.
  4955. // If this method does not have any template arguments or they are
  4956. // empty while funcSpec is not empty we assume this is a
  4957. // specialization of a method. If not, we clear the funcSpec and treat
  4958. // this as a normal method of a template class.
  4959. if (!(root->tArgLists &&
  4960. root->tArgLists->count()>0 &&
  4961. root->tArgLists->first()->count()==0
  4962. )
  4963. )
  4964. {
  4965. funcSpec.resize(0);
  4966. }
  4967. // split scope into a namespace and a class part
  4968. extractNamespaceName(scopeName,className,namespaceName,TRUE);
  4969. //printf("scopeName=`%s' className=`%s' namespaceName=`%s'\n",
  4970. // scopeName.data(),className.data(),namespaceName.data());
  4971. //namespaceName=removeAnonymousScopes(namespaceName);
  4972. if (namespaceName.find('@')!=-1) return; // skip stuff in anonymous namespace...
  4973. //printf("namespaceName=`%s' className=`%s'\n",namespaceName.data(),className.data());
  4974. // merge class and namespace scopes again
  4975. scopeName.resize(0);
  4976. if (!namespaceName.isEmpty())
  4977. {
  4978. if (className.isEmpty())
  4979. {
  4980. scopeName=namespaceName;
  4981. }
  4982. else if (!root->relates.isEmpty() || // relates command with explicit scope
  4983. !getClass(className)) // class name only exists in a namespace
  4984. {
  4985. scopeName=namespaceName+"::"+className;
  4986. }
  4987. else
  4988. {
  4989. scopeName=className;
  4990. }
  4991. }
  4992. else if (!className.isEmpty())
  4993. {
  4994. scopeName=className;
  4995. }
  4996. //printf("new scope=`%s'\n",scopeName.data());
  4997. QCString tempScopeName=scopeName;
  4998. ClassDef *cd=getClass(scopeName);
  4999. if (cd)
  5000. {
  5001. if (root->tArgLists) root->tArgLists->first();
  5002. if (funcSpec.isEmpty())
  5003. {
  5004. tempScopeName=cd->qualifiedNameWithTemplateParameters(root->tArgLists);
  5005. }
  5006. else
  5007. {
  5008. tempScopeName=scopeName+funcSpec;
  5009. }
  5010. }
  5011. //printf("scopeName=%s cd=%p root->tArgLists=%p result=%s\n",
  5012. // scopeName.data(),cd,root->tArgLists,tempScopeName.data());
  5013. //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
  5014. // rebuild the function declaration (needed to get the scope right).
  5015. if (!scopeName.isEmpty() && !isRelated && !isFriend && !Config_getBool("HIDE_SCOPE_NAMES"))
  5016. {
  5017. if (!funcType.isEmpty())
  5018. {
  5019. if (isFunc) // a function -> we use argList for the arguments
  5020. {
  5021. funcDecl=funcType+" "+tempScopeName+"::"+funcName+funcTempList;
  5022. }
  5023. else
  5024. {
  5025. funcDecl=funcType+" "+tempScopeName+"::"+funcName+funcArgs;
  5026. }
  5027. }
  5028. else
  5029. {
  5030. if (isFunc) // a function => we use argList for the arguments
  5031. {
  5032. funcDecl=tempScopeName+"::"+funcName+funcTempList;
  5033. }
  5034. else // variable => add `argument' list
  5035. {
  5036. funcDecl=tempScopeName+"::"+funcName+funcArgs;
  5037. }
  5038. }
  5039. }
  5040. else // build declaration without scope
  5041. {
  5042. if (!funcType.isEmpty()) // but with a type
  5043. {
  5044. if (isFunc) // function => omit argument list
  5045. {
  5046. funcDecl=funcType+" "+funcName+funcTempList;
  5047. }
  5048. else // variable => add `argument' list
  5049. {
  5050. funcDecl=funcType+" "+funcName+funcArgs;
  5051. }
  5052. }
  5053. else // no type
  5054. {
  5055. if (isFunc)
  5056. {
  5057. funcDecl=funcName+funcTempList;
  5058. }
  5059. else
  5060. {
  5061. funcDecl=funcName+funcArgs;
  5062. }
  5063. }
  5064. }
  5065. if (funcType=="template class" && !funcTempList.isEmpty())
  5066. return; // ignore explicit template instantiations
  5067. Debug::print(Debug::FindMembers,0,
  5068. "findMember() Parse results:\n"
  5069. " namespaceName=`%s'\n"
  5070. " className=`%s`\n"
  5071. " funcType=`%s'\n"
  5072. " funcSpec=`%s'\n"
  5073. " funcName=`%s'\n"
  5074. " funcArgs=`%s'\n"
  5075. " funcTempList=`%s'\n"
  5076. " funcDecl=`%s'\n"
  5077. " related=`%s'\n"
  5078. " exceptions=`%s'\n"
  5079. " isRelated=%d\n"
  5080. " isMemberOf=%d\n"
  5081. " isFriend=%d\n"
  5082. " isFunc=%d\n\n",
  5083. namespaceName.data(),className.data(),
  5084. funcType.data(),funcSpec.data(),funcName.data(),funcArgs.data(),funcTempList.data(),
  5085. funcDecl.data(),root->relates.data(),exceptions.data(),isRelated,isMemberOf,isFriend,
  5086. isFunc
  5087. );
  5088. MemberName *mn=0;
  5089. if (!funcName.isEmpty()) // function name is valid
  5090. {
  5091. Debug::print(Debug::FindMembers,0,
  5092. "1. funcName=`%s'\n",funcName.data());
  5093. if (funcName.left(9)=="operator ") // strip class scope from cast operator
  5094. {
  5095. funcName = substitute(funcName,className+"::","");
  5096. }
  5097. if (!funcTempList.isEmpty()) // try with member specialization
  5098. {
  5099. mn=Doxygen::memberNameSDict->find(funcName+funcTempList);
  5100. }
  5101. if (mn==0) // try without specialization
  5102. {
  5103. mn=Doxygen::memberNameSDict->find(funcName);
  5104. }
  5105. if (!isRelated && mn) // function name already found
  5106. {
  5107. Debug::print(Debug::FindMembers,0,
  5108. "2. member name exists (%d members with this name)\n",mn->count());
  5109. if (!className.isEmpty()) // class name is valid
  5110. {
  5111. if (funcSpec.isEmpty()) // not a member specialization
  5112. {
  5113. int count=0;
  5114. int noMatchCount=0;
  5115. MemberNameIterator mni(*mn);
  5116. MemberDef *md;
  5117. bool memFound=FALSE;
  5118. for (mni.toFirst();!memFound && (md=mni.current());++mni)
  5119. {
  5120. ClassDef *cd=md->getClassDef();
  5121. Debug::print(Debug::FindMembers,0,
  5122. "3. member definition found, "
  5123. "scope needed=`%s' scope=`%s' args=`%s' fileName=%s\n",
  5124. scopeName.data(),cd ? cd->name().data() : "<none>",
  5125. md->argsString(),
  5126. root->fileName.data());
  5127. //printf("Member %s (member scopeName=%s) (this scopeName=%s) classTempList=%s\n",md->name().data(),cd->name().data(),scopeName.data(),classTempList.data());
  5128. FileDef *fd=rootNav->fileDef();
  5129. NamespaceDef *nd=0;
  5130. if (!namespaceName.isEmpty()) nd=getResolvedNamespace(namespaceName);
  5131. //printf("scopeName %s->%s\n",scopeName.data(),
  5132. // stripTemplateSpecifiersFromScope(scopeName,FALSE).data());
  5133. ClassDef *tcd=findClassDefinition(fd,nd,scopeName);
  5134. if (tcd==0 && stripAnonymousNamespaceScope(cd->name())==scopeName)
  5135. {
  5136. // don't be fooled by anonymous scopes
  5137. tcd=cd;
  5138. }
  5139. //printf("Looking for %s inside nd=%s result=%p (%s) cd=%p\n",
  5140. // scopeName.data(),nd?nd->name().data():"<none>",tcd,tcd?tcd->name().data():"",cd);
  5141. if (cd && tcd==cd) // member's classes match
  5142. {
  5143. Debug::print(Debug::FindMembers,0,
  5144. "4. class definition %s found\n",cd->name().data());
  5145. // get the template parameter lists found at the member declaration
  5146. QList<ArgumentList> declTemplArgs;
  5147. cd->getTemplateParameterLists(declTemplArgs);
  5148. LockingPtr<ArgumentList> templAl = md->templateArguments();
  5149. if (templAl!=0)
  5150. {
  5151. declTemplArgs.append(templAl.pointer());
  5152. }
  5153. // get the template parameter lists found at the member definition
  5154. QList<ArgumentList> *defTemplArgs = root->tArgLists;
  5155. //printf("defTemplArgs=%p\n",defTemplArgs);
  5156. // do we replace the decl argument lists with the def argument lists?
  5157. bool substDone=FALSE;
  5158. ArgumentList *argList=0;
  5159. /* substitute the occurrences of class template names in the
  5160. * argument list before matching
  5161. */
  5162. LockingPtr<ArgumentList> mdAl = md->argumentList();
  5163. if (declTemplArgs.count()>0 && defTemplArgs &&
  5164. declTemplArgs.count()==defTemplArgs->count() &&
  5165. mdAl.pointer()
  5166. )
  5167. {
  5168. /* the function definition has template arguments
  5169. * and the class definition also has template arguments, so
  5170. * we must substitute the template names of the class by that
  5171. * of the function definition before matching.
  5172. */
  5173. argList = new ArgumentList;
  5174. substituteTemplatesInArgList(declTemplArgs,*defTemplArgs,
  5175. mdAl.pointer(),argList);
  5176. substDone=TRUE;
  5177. }
  5178. else /* no template arguments, compare argument lists directly */
  5179. {
  5180. argList = mdAl.pointer();
  5181. }
  5182. Debug::print(Debug::FindMembers,0,
  5183. "5. matching `%s'<=>`%s' className=%s namespaceName=%s\n",
  5184. argListToString(argList,TRUE).data(),argListToString(root->argList,TRUE).data(),
  5185. className.data(),namespaceName.data()
  5186. );
  5187. bool matching=
  5188. md->isVariable() || md->isTypedef() || // needed for function pointers
  5189. (mdAl.pointer()==0 && root->argList->count()==0) ||
  5190. matchArguments2(
  5191. md->getClassDef(),md->getFileDef(),argList,
  5192. cd,fd,root->argList,
  5193. TRUE);
  5194. Debug::print(Debug::FindMembers,0,
  5195. "6. match results of matchArguments2 = %d\n",matching);
  5196. if (substDone) // found a new argument list
  5197. {
  5198. if (matching) // replace member's argument list
  5199. {
  5200. md->setDefinitionTemplateParameterLists(root->tArgLists);
  5201. md->setArgumentList(argList); // new owner of the list => no delete
  5202. }
  5203. else // no match
  5204. {
  5205. if (!funcTempList.isEmpty() &&
  5206. isSpecialization(declTemplArgs,*defTemplArgs))
  5207. {
  5208. // check if we are dealing with a partial template
  5209. // specialization. In this case we add it to the class
  5210. // even though the member arguments do not match.
  5211. // TODO: copy other aspects?
  5212. root->protection=md->protection(); // copy protection level
  5213. addMethodToClass(rootNav,cd,md->name(),isFriend);
  5214. return;
  5215. }
  5216. delete argList;
  5217. }
  5218. }
  5219. if (matching)
  5220. {
  5221. addMemberDocs(rootNav,md,funcDecl,0,overloaded,0/* TODO */);
  5222. count++;
  5223. memFound=TRUE;
  5224. }
  5225. }
  5226. else if (cd && cd!=tcd) // we did find a class with the same name as cd
  5227. // but in a different namespace
  5228. {
  5229. noMatchCount++;
  5230. }
  5231. }
  5232. if (count==0 && rootNav->parent() &&
  5233. rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
  5234. {
  5235. goto localObjCMethod;
  5236. }
  5237. if (count==0 && !(isFriend && funcType=="class"))
  5238. {
  5239. int candidates=0;
  5240. if (mn->count()>0)
  5241. {
  5242. //printf("Assume template class\n");
  5243. for (mni.toFirst();(md=mni.current());++mni)
  5244. {
  5245. ClassDef *cd=md->getClassDef();
  5246. //printf("cd->name()==%s className=%s\n",cd->name().data(),className.data());
  5247. if (cd!=0 && rightScopeMatch(cd->name(),className))
  5248. {
  5249. LockingPtr<ArgumentList> templAl = md->templateArguments();
  5250. if (root->tArgLists && templAl!=0 &&
  5251. root->tArgLists->getLast()->count()<=templAl->count())
  5252. {
  5253. addMethodToClass(rootNav,cd,md->name(),isFriend);
  5254. return;
  5255. }
  5256. candidates++;
  5257. }
  5258. }
  5259. }
  5260. warn(root->fileName,root->startLine,
  5261. "Warning: no %smatching class member found for",
  5262. noMatchCount>1 ? "uniquely " : ""
  5263. );
  5264. if (root->tArgLists)
  5265. {
  5266. QListIterator<ArgumentList> alli(*root->tArgLists);
  5267. ArgumentList *al;
  5268. for (;(al=alli.current());++alli)
  5269. {
  5270. warn_cont(" template %s\n",tempArgListToString(al).data());
  5271. }
  5272. }
  5273. QCString fullFuncDecl=funcDecl.copy();
  5274. if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE);
  5275. warn_cont(" %s\n",fullFuncDecl.data());
  5276. if (candidates>0)
  5277. {
  5278. warn_cont("Possible candidates:\n");
  5279. for (mni.toFirst();(md=mni.current());++mni)
  5280. {
  5281. ClassDef *cd=md->getClassDef();
  5282. if (cd!=0 && rightScopeMatch(cd->name(),className))
  5283. {
  5284. LockingPtr<ArgumentList> templAl = md->templateArguments();
  5285. if (templAl!=0)
  5286. {
  5287. warn_cont(" template %s\n",tempArgListToString(templAl.pointer()).data());
  5288. }
  5289. warn_cont(" ");
  5290. if (md->typeString())
  5291. {
  5292. warn_cont("%s ",md->typeString());
  5293. }
  5294. QCString qScope = cd->qualifiedNameWithTemplateParameters();
  5295. if (!qScope.isEmpty()) warn_cont("%s::%s",qScope.data(),md->name().data());
  5296. if (md->argsString()) warn_cont("%s",md->argsString());
  5297. if (noMatchCount>1) warn_cont(" at line %d of file %s",md->getDefLine(),md->getDefFileName().data());
  5298. warn_cont("\n");
  5299. }
  5300. }
  5301. }
  5302. }
  5303. }
  5304. else if (cd) // member specialization
  5305. {
  5306. MemberDef::MemberType mtype=MemberDef::Function;
  5307. ArgumentList *tArgList = new ArgumentList;
  5308. // getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists);
  5309. MemberDef *md=new MemberDef(
  5310. root->fileName,root->startLine,
  5311. funcType,funcName,funcArgs,exceptions,
  5312. root->protection,root->virt,root->stat,Member,
  5313. mtype,tArgList,root->argList);
  5314. //printf("new specialized member %s args=`%s'\n",md->name().data(),funcArgs.data());
  5315. md->setTagInfo(rootNav->tagInfo());
  5316. md->setMemberClass(cd);
  5317. md->setTemplateSpecialization(TRUE);
  5318. md->setTypeConstraints(root->typeConstr);
  5319. md->setDefinition(funcDecl);
  5320. md->enableCallGraph(root->callGraph);
  5321. md->enableCallerGraph(root->callerGraph);
  5322. md->setDocumentation(root->doc,root->docFile,root->docLine);
  5323. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  5324. md->setDocsForDefinition(!root->proto);
  5325. md->setPrototype(root->proto);
  5326. md->addSectionsToDefinition(root->anchors);
  5327. md->setBodySegment(root->bodyLine,root->endBodyLine);
  5328. FileDef *fd=rootNav->fileDef();
  5329. md->setBodyDef(fd);
  5330. md->setMemberSpecifiers(root->spec);
  5331. md->setMemberGroupId(root->mGrpId);
  5332. mn->append(md);
  5333. cd->insertMember(md);
  5334. md->setRefItems(root->sli);
  5335. delete tArgList;
  5336. }
  5337. else
  5338. {
  5339. //printf("*** Specialized member %s of unknown scope %s%s found!\n",
  5340. // scopeName.data(),funcName.data(),funcArgs.data());
  5341. }
  5342. }
  5343. else if (overloaded) // check if the function belongs to only one class
  5344. {
  5345. // for unique overloaded member we allow the class to be
  5346. // omitted, this is to be Qt compatable. Using this should
  5347. // however be avoided, because it is error prone
  5348. MemberNameIterator mni(*mn);
  5349. MemberDef *md=mni.toFirst();
  5350. ASSERT(md);
  5351. ClassDef *cd=md->getClassDef();
  5352. ASSERT(cd);
  5353. QCString className=cd->name().copy();
  5354. ++mni;
  5355. bool unique=TRUE;
  5356. for (;(md=mni.current());++mni)
  5357. {
  5358. ClassDef *cd=md->getClassDef();
  5359. if (className!=cd->name()) unique=FALSE;
  5360. }
  5361. if (unique)
  5362. {
  5363. MemberDef::MemberType mtype;
  5364. if (root->mtype==Signal) mtype=MemberDef::Signal;
  5365. else if (root->mtype==Slot) mtype=MemberDef::Slot;
  5366. else if (root->mtype==DCOP) mtype=MemberDef::DCOP;
  5367. else mtype=MemberDef::Function;
  5368. // new overloaded member function
  5369. ArgumentList *tArgList =
  5370. getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists);
  5371. //printf("new related member %s args=`%s'\n",md->name().data(),funcArgs.data());
  5372. MemberDef *md=new MemberDef(
  5373. root->fileName,root->startLine,
  5374. funcType,funcName,funcArgs,exceptions,
  5375. root->protection,root->virt,root->stat,Related,
  5376. mtype,tArgList,root->argList);
  5377. md->setTagInfo(rootNav->tagInfo());
  5378. md->setTypeConstraints(root->typeConstr);
  5379. md->setMemberClass(cd);
  5380. md->setDefinition(funcDecl);
  5381. md->enableCallGraph(root->callGraph);
  5382. md->enableCallerGraph(root->callerGraph);
  5383. QCString doc=getOverloadDocs();
  5384. doc+="<p>";
  5385. doc+=root->doc;
  5386. md->setDocumentation(doc,root->docFile,root->docLine);
  5387. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  5388. md->setDocsForDefinition(!root->proto);
  5389. md->setPrototype(root->proto);
  5390. md->addSectionsToDefinition(root->anchors);
  5391. md->setBodySegment(root->bodyLine,root->endBodyLine);
  5392. FileDef *fd=rootNav->fileDef();
  5393. md->setBodyDef(fd);
  5394. md->setMemberSpecifiers(root->spec);
  5395. md->setMemberGroupId(root->mGrpId);
  5396. mn->append(md);
  5397. cd->insertMember(md);
  5398. cd->insertUsedFile(root->fileName);
  5399. md->setRefItems(root->sli);
  5400. }
  5401. }
  5402. else // unrelated function with the same name as a member
  5403. {
  5404. if (!findGlobalMember(rootNav,namespaceName,funcName,funcTempList,funcArgs,funcDecl))
  5405. {
  5406. QCString fullFuncDecl=funcDecl.copy();
  5407. if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE);
  5408. warn(root->fileName,root->startLine,
  5409. "Warning: Cannot determine class for function\n%s",
  5410. fullFuncDecl.data()
  5411. );
  5412. }
  5413. }
  5414. }
  5415. else if (isRelated && !root->relates.isEmpty())
  5416. {
  5417. Debug::print(Debug::FindMembers,0,"2. related function\n"
  5418. " scopeName=%s className=%s\n",scopeName.data(),className.data());
  5419. if (className.isEmpty()) className=root->relates;
  5420. ClassDef *cd;
  5421. //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
  5422. if ((cd=getClass(scopeName)))
  5423. {
  5424. bool newMember=TRUE; // assume we have a new member
  5425. bool newMemberName=FALSE;
  5426. bool isDefine=FALSE;
  5427. {
  5428. MemberName *mn = Doxygen::functionNameSDict->find(funcName);
  5429. if (mn)
  5430. {
  5431. MemberDef *md = mn->first();
  5432. while (md && !isDefine)
  5433. {
  5434. isDefine = isDefine || md->isDefine();
  5435. md = mn->next();
  5436. }
  5437. }
  5438. }
  5439. FileDef *fd=rootNav->fileDef();
  5440. if ((mn=Doxygen::memberNameSDict->find(funcName))==0)
  5441. {
  5442. mn=new MemberName(funcName);
  5443. newMemberName=TRUE; // we create a new member name
  5444. }
  5445. else
  5446. {
  5447. MemberDef *rmd=mn->first();
  5448. while (rmd && newMember) // see if we got another member with matching arguments
  5449. {
  5450. LockingPtr<ArgumentList> rmdAl = rmd->argumentList();
  5451. newMember=newMember &&
  5452. !matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl.pointer(),
  5453. cd,fd,root->argList,
  5454. TRUE);
  5455. if (newMember) rmd=mn->next();
  5456. }
  5457. if (!newMember && rmd) // member already exists as rmd -> add docs
  5458. {
  5459. //printf("addMemberDocs for related member %s\n",root->name.data());
  5460. //rmd->setMemberDefTemplateArguments(root->mtArgList);
  5461. addMemberDocs(rootNav,rmd,funcDecl,0,overloaded);
  5462. }
  5463. }
  5464. if (newMember) // need to create a new member
  5465. {
  5466. MemberDef::MemberType mtype;
  5467. if (isDefine)
  5468. mtype=MemberDef::Define;
  5469. else if (root->mtype==Signal)
  5470. mtype=MemberDef::Signal;
  5471. else if (root->mtype==Slot)
  5472. mtype=MemberDef::Slot;
  5473. else if (root->mtype==DCOP)
  5474. mtype=MemberDef::DCOP;
  5475. else
  5476. mtype=MemberDef::Function;
  5477. //printf("New related name `%s' `%d'\n",funcName.data(),
  5478. // root->argList ? (int)root->argList->count() : -1);
  5479. // new related (member) function
  5480. #if 0 // removed as it doesn't handle related template functions correctly
  5481. ArgumentList *tArgList =
  5482. getTemplateArgumentsFromName(scopeName+"::"+funcName,root->tArgLists);
  5483. MemberDef *md=new MemberDef(
  5484. root->fileName,root->startLine,
  5485. funcType,funcName,funcArgs,exceptions,
  5486. root->protection,root->virt,root->stat,TRUE,
  5487. mtype,tArgList,funcArgs.isEmpty() ? 0 : root->argList);
  5488. #endif
  5489. // first note that we pass:
  5490. // (root->tArgLists ? root->tArgLists->last() : 0)
  5491. // for the template arguments fo the new "member."
  5492. // this accurately reflects the template arguments of
  5493. // the related function, which don't have to do with
  5494. // those of the related class.
  5495. MemberDef *md=new MemberDef(
  5496. root->fileName,root->startLine,
  5497. funcType,funcName,funcArgs,exceptions,
  5498. root->protection,root->virt,
  5499. root->stat && !isMemberOf,
  5500. isMemberOf ? Foreign : isRelated ? Related : Member,
  5501. mtype,
  5502. (root->tArgLists ? root->tArgLists->last() : 0),
  5503. funcArgs.isEmpty() ? 0 : root->argList);
  5504. //
  5505. // we still have the problem that
  5506. // MemberDef::writeDocumentation() in memberdef.cpp
  5507. // writes the template argument list for the class,
  5508. // as if this member is a member of the class.
  5509. // fortunately, MemberDef::writeDocumentation() has
  5510. // a special mechanism that allows us to totally
  5511. // override the set of template argument lists that
  5512. // are printed. We use that and set it to the
  5513. // template argument lists of the related function.
  5514. //
  5515. md->setDefinitionTemplateParameterLists(root->tArgLists);
  5516. md->setTagInfo(rootNav->tagInfo());
  5517. //printf("Related member name=`%s' decl=`%s' bodyLine=`%d'\n",
  5518. // funcName.data(),funcDecl.data(),root->bodyLine);
  5519. // try to find the matching line number of the body from the
  5520. // global function list
  5521. bool found=FALSE;
  5522. if (root->bodyLine==-1)
  5523. {
  5524. MemberName *rmn=Doxygen::functionNameSDict->find(funcName);
  5525. if (rmn)
  5526. {
  5527. MemberDef *rmd=rmn->first();
  5528. while (rmd && !found) // see if we got another member with matching arguments
  5529. {
  5530. LockingPtr<ArgumentList> rmdAl = rmd->argumentList();
  5531. // check for matching argument lists
  5532. if (
  5533. matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl.pointer(),
  5534. cd,fd,root->argList,
  5535. TRUE)
  5536. )
  5537. {
  5538. found=TRUE;
  5539. }
  5540. if (!found) rmd=rmn->next();
  5541. }
  5542. if (rmd) // member found -> copy line number info
  5543. {
  5544. md->setBodySegment(rmd->getStartBodyLine(),rmd->getEndBodyLine());
  5545. md->setBodyDef(rmd->getBodyDef());
  5546. //md->setBodyMember(rmd);
  5547. }
  5548. }
  5549. }
  5550. if (!found) // line number could not be found or is available in this
  5551. // entry
  5552. {
  5553. md->setBodySegment(root->bodyLine,root->endBodyLine);
  5554. md->setBodyDef(fd);
  5555. }
  5556. //if (root->mGrpId!=-1)
  5557. //{
  5558. // md->setMemberGroup(memberGroupDict[root->mGrpId]);
  5559. //}
  5560. md->setMemberClass(cd);
  5561. md->setMemberSpecifiers(root->spec);
  5562. md->setDefinition(funcDecl);
  5563. md->enableCallGraph(root->callGraph);
  5564. md->enableCallerGraph(root->callerGraph);
  5565. md->setDocumentation(root->doc,root->docFile,root->docLine);
  5566. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  5567. md->setDocsForDefinition(!root->proto);
  5568. md->setPrototype(root->proto);
  5569. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  5570. md->addSectionsToDefinition(root->anchors);
  5571. md->setMemberGroupId(root->mGrpId);
  5572. //md->setMemberDefTemplateArguments(root->mtArgList);
  5573. mn->append(md);
  5574. cd->insertMember(md);
  5575. cd->insertUsedFile(root->fileName);
  5576. md->setRefItems(root->sli);
  5577. if (root->relatesType == Duplicate) md->setRelatedAlso(cd);
  5578. addMemberToGroups(root,md);
  5579. //printf("Adding member=%s\n",md->name().data());
  5580. if (newMemberName)
  5581. {
  5582. //Doxygen::memberNameList.append(mn);
  5583. //Doxygen::memberNameDict.insert(funcName,mn);
  5584. Doxygen::memberNameSDict->append(funcName,mn);
  5585. }
  5586. }
  5587. if (root->relatesType == Duplicate)
  5588. {
  5589. if (!findGlobalMember(rootNav,namespaceName,funcName,funcTempList,funcArgs,funcDecl))
  5590. {
  5591. QCString fullFuncDecl=funcDecl.copy();
  5592. if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE);
  5593. warn(root->fileName,root->startLine,
  5594. "Warning: Cannot determine file/namespace for relatedalso function\n%s",
  5595. fullFuncDecl.data()
  5596. );
  5597. }
  5598. }
  5599. }
  5600. else
  5601. {
  5602. warn_undoc(root->fileName,root->startLine,
  5603. "Warning: class `%s' for related function `%s' is not "
  5604. "documented.",
  5605. className.data(),funcName.data()
  5606. );
  5607. }
  5608. }
  5609. else if (rootNav->parent() && rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
  5610. {
  5611. localObjCMethod:
  5612. ClassDef *cd;
  5613. //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
  5614. if (Config_getBool("EXTRACT_LOCAL_METHODS") && (cd=getClass(scopeName)))
  5615. {
  5616. //printf("Local objective C method `%s' of class `%s' found\n",root->name.data(),cd->name().data());
  5617. MemberDef *md=new MemberDef(
  5618. root->fileName,root->startLine,
  5619. funcType,funcName,funcArgs,exceptions,
  5620. root->protection,root->virt,root->stat,Member,
  5621. MemberDef::Function,0,root->argList);
  5622. md->setTagInfo(rootNav->tagInfo());
  5623. md->makeImplementationDetail();
  5624. md->setMemberClass(cd);
  5625. md->setDefinition(funcDecl);
  5626. md->enableCallGraph(root->callGraph);
  5627. md->enableCallerGraph(root->callerGraph);
  5628. md->setDocumentation(root->doc,root->docFile,root->docLine);
  5629. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  5630. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  5631. md->setDocsForDefinition(!root->proto);
  5632. md->setPrototype(root->proto);
  5633. md->addSectionsToDefinition(root->anchors);
  5634. md->setBodySegment(root->bodyLine,root->endBodyLine);
  5635. FileDef *fd=rootNav->fileDef();
  5636. md->setBodyDef(fd);
  5637. md->setMemberSpecifiers(root->spec);
  5638. md->setMemberGroupId(root->mGrpId);
  5639. cd->insertMember(md);
  5640. cd->insertUsedFile(root->fileName);
  5641. md->setRefItems(root->sli);
  5642. if ((mn=Doxygen::memberNameSDict->find(root->name)))
  5643. {
  5644. mn->append(md);
  5645. }
  5646. else
  5647. {
  5648. mn = new MemberName(root->name);
  5649. mn->append(md);
  5650. Doxygen::memberNameSDict->append(root->name,mn);
  5651. }
  5652. }
  5653. else
  5654. {
  5655. // local objective C method found for class without interface
  5656. }
  5657. }
  5658. else // unrelated not overloaded member found
  5659. {
  5660. bool globMem = findGlobalMember(rootNav,namespaceName,funcName,funcTempList,funcArgs,funcDecl);
  5661. if (className.isEmpty() && !globMem)
  5662. {
  5663. warn(root->fileName,root->startLine,
  5664. "Warning: class for member `%s' cannot "
  5665. "be found.", funcName.data()
  5666. );
  5667. }
  5668. else if (!className.isEmpty() && !globMem)
  5669. {
  5670. warn(root->fileName,root->startLine,
  5671. "Warning: member `%s' of class `%s' cannot be found",
  5672. funcName.data(),className.data());
  5673. }
  5674. }
  5675. }
  5676. else
  5677. {
  5678. // this should not be called
  5679. warn(root->fileName,root->startLine,
  5680. "Warning: member with no name found.");
  5681. }
  5682. return;
  5683. }
  5684. //----------------------------------------------------------------------
  5685. // find the members corresponding to the different documentation blocks
  5686. // that are extracted from the sources.
  5687. static void filterMemberDocumentation(EntryNav *rootNav)
  5688. {
  5689. Entry *root = rootNav->entry();
  5690. int i=-1,l;
  5691. Debug::print(Debug::FindMembers,0,
  5692. "findMemberDocumentation(): root->type=`%s' root->inside=`%s' root->name=`%s' root->args=`%s' section=%x root->spec=%d root->mGrpId=%d\n",
  5693. root->type.data(),root->inside.data(),root->name.data(),root->args.data(),root->section,root->spec,root->mGrpId
  5694. );
  5695. //printf("rootNav->parent()->name()=%s\n",rootNav->parent()->name().data());
  5696. bool isFunc=TRUE;
  5697. if (root->relatesType == Duplicate && !root->relates.isEmpty())
  5698. {
  5699. QCString tmp = root->relates;
  5700. root->relates.resize(0);
  5701. filterMemberDocumentation(rootNav);
  5702. root->relates = tmp;
  5703. }
  5704. if ( // detect func variable/typedef to func ptr
  5705. (i=findFunctionPtr(root->type,&l))!=-1
  5706. )
  5707. {
  5708. //printf("Fixing function pointer!\n");
  5709. // fix type and argument
  5710. root->args.prepend(root->type.right(root->type.length()-i-l));
  5711. root->type=root->type.left(i+l);
  5712. //printf("Results type=%s,name=%s,args=%s\n",root->type.data(),root->name.data(),root->args.data());
  5713. isFunc=FALSE;
  5714. }
  5715. else if ((root->type.left(8)=="typedef " && root->args.find('(')!=-1))
  5716. // detect function types marked as functions
  5717. {
  5718. isFunc=FALSE;
  5719. }
  5720. //printf("Member %s isFunc=%d\n",root->name.data(),isFunc);
  5721. if (root->section==Entry::MEMBERDOC_SEC)
  5722. {
  5723. //printf("Documentation for inline member `%s' found args=`%s'\n",
  5724. // root->name.data(),root->args.data());
  5725. //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
  5726. if (root->type.isEmpty())
  5727. {
  5728. findMember(rootNav,root->name+root->args+root->exception,FALSE,isFunc);
  5729. }
  5730. else
  5731. {
  5732. findMember(rootNav,root->type+" "+root->name+root->args+root->exception,FALSE,isFunc);
  5733. }
  5734. }
  5735. else if (root->section==Entry::OVERLOADDOC_SEC)
  5736. {
  5737. //printf("Overloaded member %s found\n",root->name.data());
  5738. findMember(rootNav,root->name,TRUE,isFunc);
  5739. }
  5740. else if
  5741. ((root->section==Entry::FUNCTION_SEC // function
  5742. ||
  5743. (root->section==Entry::VARIABLE_SEC && // variable
  5744. !root->type.isEmpty() && // with a type
  5745. g_compoundKeywordDict.find(root->type)==0 // that is not a keyword
  5746. // (to skip forward declaration of class etc.)
  5747. )
  5748. )
  5749. )
  5750. {
  5751. //printf("Documentation for member `%s' found args=`%s' excp=`%s'\n",
  5752. // root->name.data(),root->args.data(),root->exception.data());
  5753. //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
  5754. //printf("Inside=%s\n Relates=%s\n",root->inside.data(),root->relates.data());
  5755. if (root->type=="friend class" || root->type=="friend struct" ||
  5756. root->type=="friend union")
  5757. {
  5758. findMember(rootNav,
  5759. root->type+" "+
  5760. root->name,
  5761. FALSE,FALSE);
  5762. }
  5763. else if (!root->type.isEmpty())
  5764. {
  5765. findMember(rootNav,
  5766. root->type+" "+
  5767. root->inside+
  5768. root->name+
  5769. root->args+
  5770. root->exception,
  5771. FALSE,isFunc);
  5772. }
  5773. else
  5774. {
  5775. findMember(rootNav,
  5776. root->inside+
  5777. root->name+
  5778. root->args+
  5779. root->exception,
  5780. FALSE,isFunc);
  5781. }
  5782. }
  5783. else if (root->section==Entry::DEFINE_SEC && !root->relates.isEmpty())
  5784. {
  5785. findMember(rootNav,root->name+root->args,FALSE,!root->args.isEmpty());
  5786. }
  5787. else if (root->section==Entry::VARIABLEDOC_SEC)
  5788. {
  5789. //printf("Documentation for variable %s found\n",root->name.data());
  5790. //if (!root->relates.isEmpty()) printf(" Relates %s\n",root->relates.data());
  5791. findMember(rootNav,root->name,FALSE,FALSE);
  5792. }
  5793. else
  5794. {
  5795. // skip section
  5796. //printf("skip section\n");
  5797. }
  5798. }
  5799. static void findMemberDocumentation(EntryNav *rootNav)
  5800. {
  5801. if (rootNav->section()==Entry::MEMBERDOC_SEC ||
  5802. rootNav->section()==Entry::OVERLOADDOC_SEC ||
  5803. rootNav->section()==Entry::FUNCTION_SEC ||
  5804. rootNav->section()==Entry::VARIABLE_SEC ||
  5805. rootNav->section()==Entry::VARIABLEDOC_SEC ||
  5806. rootNav->section()==Entry::DEFINE_SEC
  5807. )
  5808. {
  5809. rootNav->loadEntry(g_storage);
  5810. filterMemberDocumentation(rootNav);
  5811. rootNav->releaseEntry();
  5812. }
  5813. if (rootNav->children())
  5814. {
  5815. EntryNavListIterator eli(*rootNav->children());
  5816. EntryNav *e;
  5817. for (;(e=eli.current());++eli)
  5818. {
  5819. if (e->section()!=Entry::ENUM_SEC) findMemberDocumentation(e);
  5820. }
  5821. }
  5822. }
  5823. //----------------------------------------------------------------------
  5824. static void findObjCMethodDefinitions(EntryNav *rootNav)
  5825. {
  5826. if (rootNav->children())
  5827. {
  5828. EntryNavListIterator eli(*rootNav->children());
  5829. EntryNav *objCImplNav;
  5830. for (;(objCImplNav=eli.current());++eli)
  5831. {
  5832. if (objCImplNav->section()==Entry::OBJCIMPL_SEC && objCImplNav->children())
  5833. {
  5834. EntryNavListIterator seli(*objCImplNav->children());
  5835. EntryNav *objCMethodNav;
  5836. for (;(objCMethodNav=seli.current());++seli)
  5837. {
  5838. if (objCMethodNav->section()==Entry::FUNCTION_SEC)
  5839. {
  5840. objCMethodNav->loadEntry(g_storage);
  5841. Entry *objCMethod = objCMethodNav->entry();
  5842. //Printf(" Found ObjC method definition %s\n",objCMethod->name.data());
  5843. findMember(objCMethodNav, objCMethod->type+" "+objCImplNav->name()+"::"+
  5844. objCMethod->name+" "+objCMethod->args, FALSE,TRUE);
  5845. objCMethod->section=Entry::EMPTY_SEC;
  5846. objCMethodNav->releaseEntry();
  5847. }
  5848. }
  5849. }
  5850. }
  5851. }
  5852. }
  5853. //----------------------------------------------------------------------
  5854. // find and add the enumeration to their classes, namespaces or files
  5855. static void findEnums(EntryNav *rootNav)
  5856. {
  5857. if (rootNav->section()==Entry::ENUM_SEC)
  5858. // non anonymous enumeration
  5859. {
  5860. rootNav->loadEntry(g_storage);
  5861. Entry *root = rootNav->entry();
  5862. MemberDef *md=0;
  5863. ClassDef *cd=0;
  5864. FileDef *fd=0;
  5865. NamespaceDef *nd=0;
  5866. MemberNameSDict *mnsd=0;
  5867. bool isGlobal;
  5868. bool isRelated=FALSE;
  5869. bool isMemberOf=FALSE;
  5870. //printf("Found enum with name `%s' relates=%s\n",root->name.data(),root->relates.data());
  5871. int i;
  5872. QCString name;
  5873. QCString scope;
  5874. if ((i=root->name.findRev("::"))!=-1) // scope is specified
  5875. {
  5876. scope=root->name.left(i); // extract scope
  5877. name=root->name.right(root->name.length()-i-2); // extract name
  5878. if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
  5879. }
  5880. else // no scope, check the scope in which the docs where found
  5881. {
  5882. if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
  5883. && !rootNav->parent()->name().isEmpty()
  5884. ) // found enum docs inside a compound
  5885. {
  5886. scope=rootNav->parent()->name();
  5887. if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
  5888. }
  5889. name=root->name;
  5890. }
  5891. if (!root->relates.isEmpty())
  5892. { // related member, prefix user specified scope
  5893. isRelated=TRUE;
  5894. isMemberOf=(root->relatesType == MemberOf);
  5895. if (getClass(root->relates)==0 && !scope.isEmpty())
  5896. scope=mergeScopes(scope,root->relates);
  5897. else
  5898. scope=root->relates.copy();
  5899. if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
  5900. }
  5901. if (cd && !name.isEmpty()) // found a enum inside a compound
  5902. {
  5903. //printf("Enum `%s'::`%s'\n",cd->name(),name.data());
  5904. fd=0;
  5905. mnsd=Doxygen::memberNameSDict;
  5906. isGlobal=FALSE;
  5907. }
  5908. else if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') // found enum inside namespace
  5909. {
  5910. mnsd=Doxygen::functionNameSDict;
  5911. isGlobal=TRUE;
  5912. }
  5913. else // found a global enum
  5914. {
  5915. fd=rootNav->fileDef();
  5916. mnsd=Doxygen::functionNameSDict;
  5917. isGlobal=TRUE;
  5918. }
  5919. if (!name.isEmpty())
  5920. {
  5921. // new enum type
  5922. md = new MemberDef(
  5923. root->fileName,root->startLine,
  5924. 0,name,0,0,
  5925. root->protection,Normal,FALSE,
  5926. isMemberOf ? Foreign : isRelated ? Related : Member,
  5927. MemberDef::Enumeration,
  5928. 0,0);
  5929. md->setTagInfo(rootNav->tagInfo());
  5930. if (!isGlobal) md->setMemberClass(cd); else md->setFileDef(fd);
  5931. md->setBodySegment(root->bodyLine,root->endBodyLine);
  5932. md->setBodyDef(rootNav->fileDef());
  5933. //printf("Enum %s definition at line %d of %s: protection=%d\n",
  5934. // root->name.data(),root->bodyLine,root->fileName.data(),root->protection);
  5935. md->addSectionsToDefinition(root->anchors);
  5936. md->setMemberGroupId(root->mGrpId);
  5937. md->enableCallGraph(root->callGraph);
  5938. md->enableCallerGraph(root->callerGraph);
  5939. //printf("%s::setRefItems(%d)\n",md->name().data(),root->sli?root->sli->count():-1);
  5940. md->setRefItems(root->sli);
  5941. //printf("found enum %s nd=%p\n",name.data(),nd);
  5942. bool defSet=FALSE;
  5943. if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
  5944. {
  5945. if (isRelated || Config_getBool("HIDE_SCOPE_NAMES"))
  5946. {
  5947. md->setDefinition(name);
  5948. }
  5949. else
  5950. {
  5951. md->setDefinition(nd->name()+"::"+name);
  5952. }
  5953. //printf("definition=%s\n",md->definition());
  5954. defSet=TRUE;
  5955. md->setNamespace(nd);
  5956. nd->insertMember(md);
  5957. }
  5958. // even if we have already added the enum to a namespace, we still
  5959. // also want to add it to other appropriate places such as file
  5960. // or class.
  5961. if (isGlobal)
  5962. {
  5963. if (!defSet) md->setDefinition(name);
  5964. if (fd==0 && rootNav->parent())
  5965. {
  5966. fd=rootNav->parent()->fileDef();
  5967. }
  5968. if (fd)
  5969. {
  5970. md->setFileDef(fd);
  5971. fd->insertMember(md);
  5972. }
  5973. }
  5974. else if (cd)
  5975. {
  5976. if (isRelated || Config_getBool("HIDE_SCOPE_NAMES"))
  5977. {
  5978. md->setDefinition(name);
  5979. }
  5980. else
  5981. {
  5982. md->setDefinition(cd->name()+"::"+name);
  5983. }
  5984. cd->insertMember(md);
  5985. cd->insertUsedFile(root->fileName);
  5986. }
  5987. md->setDocumentation(root->doc,root->docFile,root->docLine);
  5988. md->setDocsForDefinition(!root->proto);
  5989. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  5990. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  5991. //printf("Adding member=%s\n",md->name().data());
  5992. MemberName *mn;
  5993. if ((mn=(*mnsd)[name]))
  5994. {
  5995. // this is used if the same enum is in multiple namespaces/classes
  5996. mn->append(md);
  5997. }
  5998. else // new enum name
  5999. {
  6000. mn = new MemberName(name);
  6001. mn->append(md);
  6002. mnsd->append(name,mn);
  6003. //printf("add %s to new memberName. Now %d members\n",
  6004. // name.data(),mn->count());
  6005. }
  6006. addMemberToGroups(root,md);
  6007. #if 0
  6008. if (rootNav->children())
  6009. {
  6010. EntryNavListIterator eli(*rootNav->children());
  6011. EntryNav *e;
  6012. for (;(e=eli.current());++eli)
  6013. {
  6014. //printf("e->name=%s isRelated=%d\n",e->name.data(),isRelated);
  6015. MemberName *fmn=0;
  6016. MemberNameSDict *emnsd = isRelated ? Doxygen::functionNameSDict : mnsd;
  6017. if (!e->name().isEmpty() && (fmn=(*emnsd)[e->name()]))
  6018. // get list of members with the same name as the field
  6019. {
  6020. MemberNameIterator fmni(*fmn);
  6021. MemberDef *fmd;
  6022. for (fmni.toFirst(); (fmd=fmni.current()) ; ++fmni)
  6023. {
  6024. if (fmd->isEnumValue())
  6025. {
  6026. //printf("found enum value with same name\n");
  6027. if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
  6028. {
  6029. NamespaceDef *fnd=fmd->getNamespaceDef();
  6030. if (fnd==nd) // enum value is inside a namespace
  6031. {
  6032. md->insertEnumField(fmd);
  6033. fmd->setEnumScope(md);
  6034. }
  6035. }
  6036. else if (isGlobal)
  6037. {
  6038. FileDef *ffd=fmd->getFileDef();
  6039. if (ffd==fd) // enum value has file scope
  6040. {
  6041. md->insertEnumField(fmd);
  6042. fmd->setEnumScope(md);
  6043. }
  6044. }
  6045. else if (isRelated && cd) // reparent enum value to
  6046. // match the enum's scope
  6047. {
  6048. md->insertEnumField(fmd); // add field def to list
  6049. fmd->setEnumScope(md); // cross ref with enum name
  6050. fmd->setEnumClassScope(cd); // cross ref with enum name
  6051. fmd->setOuterScope(cd);
  6052. fmd->makeRelated();
  6053. cd->insertMember(fmd);
  6054. }
  6055. else
  6056. {
  6057. ClassDef *fcd=fmd->getClassDef();
  6058. if (fcd==cd) // enum value is inside a class
  6059. {
  6060. //printf("Inserting enum field %s in enum scope %s\n",
  6061. // fmd->name().data(),md->name().data());
  6062. md->insertEnumField(fmd); // add field def to list
  6063. fmd->setEnumScope(md); // cross ref with enum name
  6064. }
  6065. }
  6066. }
  6067. }
  6068. }
  6069. }
  6070. }
  6071. #endif
  6072. }
  6073. rootNav->releaseEntry();
  6074. }
  6075. else
  6076. {
  6077. RECURSE_ENTRYTREE(findEnums,rootNav);
  6078. }
  6079. }
  6080. //----------------------------------------------------------------------
  6081. static void addEnumValuesToEnums(EntryNav *rootNav)
  6082. {
  6083. if (rootNav->section()==Entry::ENUM_SEC)
  6084. // non anonymous enumeration
  6085. {
  6086. rootNav->loadEntry(g_storage);
  6087. Entry *root = rootNav->entry();
  6088. ClassDef *cd=0;
  6089. FileDef *fd=0;
  6090. NamespaceDef *nd=0;
  6091. MemberNameSDict *mnsd=0;
  6092. bool isGlobal;
  6093. bool isRelated=FALSE;
  6094. //printf("Found enum with name `%s' relates=%s\n",root->name.data(),root->relates.data());
  6095. int i;
  6096. QCString name;
  6097. QCString scope;
  6098. if ((i=root->name.findRev("::"))!=-1) // scope is specified
  6099. {
  6100. scope=root->name.left(i); // extract scope
  6101. name=root->name.right(root->name.length()-i-2); // extract name
  6102. if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
  6103. }
  6104. else // no scope, check the scope in which the docs where found
  6105. {
  6106. if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
  6107. && !rootNav->parent()->name().isEmpty()
  6108. ) // found enum docs inside a compound
  6109. {
  6110. scope=rootNav->parent()->name();
  6111. if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
  6112. }
  6113. name=root->name;
  6114. }
  6115. if (!root->relates.isEmpty())
  6116. { // related member, prefix user specified scope
  6117. isRelated=TRUE;
  6118. if (getClass(root->relates)==0 && !scope.isEmpty())
  6119. scope=mergeScopes(scope,root->relates);
  6120. else
  6121. scope=root->relates.copy();
  6122. if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
  6123. }
  6124. if (cd && !name.isEmpty()) // found a enum inside a compound
  6125. {
  6126. //printf("Enum in class `%s'::`%s'\n",cd->name().data(),name.data());
  6127. fd=0;
  6128. mnsd=Doxygen::memberNameSDict;
  6129. isGlobal=FALSE;
  6130. }
  6131. else if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') // found enum inside namespace
  6132. {
  6133. //printf("Enum in namespace `%s'::`%s'\n",nd->name().data(),name.data());
  6134. mnsd=Doxygen::functionNameSDict;
  6135. isGlobal=TRUE;
  6136. }
  6137. else // found a global enum
  6138. {
  6139. fd=rootNav->fileDef();
  6140. //printf("Enum in file `%s': `%s'\n",fd->name().data(),name.data());
  6141. mnsd=Doxygen::functionNameSDict;
  6142. isGlobal=TRUE;
  6143. }
  6144. if (!name.isEmpty())
  6145. {
  6146. MemberName *mn = mnsd->find(name); // for all members with this name
  6147. if (mn)
  6148. {
  6149. MemberNameIterator mni(*mn);
  6150. MemberDef *md;
  6151. for (mni.toFirst(); (md=mni.current()) ; ++mni) // for each enum in this list
  6152. {
  6153. if (md->isEnumerate() && rootNav->children())
  6154. {
  6155. EntryNavListIterator eli(*rootNav->children()); // for each enum value
  6156. EntryNav *e;
  6157. for (;(e=eli.current());++eli)
  6158. {
  6159. SrcLangExt sle;
  6160. if (rootNav->fileDef() //&&
  6161. //( (sle=getLanguageFromFileName(rootNav->fileDef()->name()))==SrcLangExt_CSharp
  6162. //|| sle==SrcLangExt_Java || sle==SrcLangExt_XML
  6163. //)
  6164. )
  6165. {
  6166. // Unlike C++, for C# enum value are only inside the enum
  6167. // scope, so we must create them here and only add them to the
  6168. // enum
  6169. e->loadEntry(g_storage);
  6170. Entry *root = e->entry();
  6171. if (md->qualifiedName()==rootNav->name()) // enum value scope matches that of the enum
  6172. {
  6173. MemberDef *fmd=new MemberDef(
  6174. root->fileName,root->startLine,
  6175. root->type,root->name,root->args,0,
  6176. Public, Normal,root->stat,Member,
  6177. MemberDef::EnumValue,0,0);
  6178. if (md->getClassDef()) fmd->setMemberClass(md->getClassDef());
  6179. else if (md->getNamespaceDef()) fmd->setNamespace(md->getNamespaceDef());
  6180. else if (md->getFileDef()) fmd->setFileDef(md->getFileDef());
  6181. fmd->setOuterScope(md->getOuterScope());
  6182. fmd->setTagInfo(e->tagInfo());
  6183. fmd->setDocumentation(root->doc,root->docFile,root->docLine);
  6184. fmd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  6185. fmd->addSectionsToDefinition(root->anchors);
  6186. fmd->setInitializer(root->initializer);
  6187. fmd->setMaxInitLines(root->initLines);
  6188. fmd->setMemberGroupId(root->mGrpId);
  6189. fmd->setExplicitExternal(root->explicitExternal);
  6190. fmd->setRefItems(root->sli);
  6191. if (fmd)
  6192. {
  6193. md->insertEnumField(fmd);
  6194. fmd->setEnumScope(md);
  6195. }
  6196. }
  6197. e->releaseEntry();
  6198. }
  6199. else
  6200. {
  6201. //printf("e->name=%s isRelated=%d\n",e->name().data(),isRelated);
  6202. MemberName *fmn=0;
  6203. MemberNameSDict *emnsd = isRelated ? Doxygen::functionNameSDict : mnsd;
  6204. if (!e->name().isEmpty() && (fmn=(*emnsd)[e->name()]))
  6205. // get list of members with the same name as the field
  6206. {
  6207. MemberNameIterator fmni(*fmn);
  6208. MemberDef *fmd;
  6209. for (fmni.toFirst(); (fmd=fmni.current()) ; ++fmni)
  6210. {
  6211. if (fmd->isEnumValue() && fmd->getOuterScope()==md->getOuterScope()) // in same scope
  6212. {
  6213. //printf("found enum value with same name %s in scope %s\n",
  6214. // fmd->name().data(),fmd->getOuterScope()->name().data());
  6215. if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
  6216. {
  6217. NamespaceDef *fnd=fmd->getNamespaceDef();
  6218. if (fnd==nd) // enum value is inside a namespace
  6219. {
  6220. md->insertEnumField(fmd);
  6221. fmd->setEnumScope(md);
  6222. }
  6223. }
  6224. else if (isGlobal)
  6225. {
  6226. FileDef *ffd=fmd->getFileDef();
  6227. if (ffd==fd) // enum value has file scope
  6228. {
  6229. md->insertEnumField(fmd);
  6230. fmd->setEnumScope(md);
  6231. }
  6232. }
  6233. else if (isRelated && cd) // reparent enum value to
  6234. // match the enum's scope
  6235. {
  6236. md->insertEnumField(fmd); // add field def to list
  6237. fmd->setEnumScope(md); // cross ref with enum name
  6238. fmd->setEnumClassScope(cd); // cross ref with enum name
  6239. fmd->setOuterScope(cd);
  6240. fmd->makeRelated();
  6241. cd->insertMember(fmd);
  6242. }
  6243. else
  6244. {
  6245. ClassDef *fcd=fmd->getClassDef();
  6246. if (fcd==cd) // enum value is inside a class
  6247. {
  6248. //printf("Inserting enum field %s in enum scope %s\n",
  6249. // fmd->name().data(),md->name().data());
  6250. md->insertEnumField(fmd); // add field def to list
  6251. fmd->setEnumScope(md); // cross ref with enum name
  6252. }
  6253. }
  6254. }
  6255. }
  6256. }
  6257. }
  6258. }
  6259. }
  6260. }
  6261. }
  6262. }
  6263. rootNav->releaseEntry();
  6264. }
  6265. else
  6266. {
  6267. RECURSE_ENTRYTREE(addEnumValuesToEnums,rootNav);
  6268. }
  6269. }
  6270. //----------------------------------------------------------------------
  6271. // find the documentation blocks for the enumerations
  6272. static void findEnumDocumentation(EntryNav *rootNav)
  6273. {
  6274. if (rootNav->section()==Entry::ENUMDOC_SEC
  6275. && !rootNav->name().isEmpty()
  6276. && rootNav->name().at(0)!='@' // skip anonymous enums
  6277. )
  6278. {
  6279. rootNav->loadEntry(g_storage);
  6280. Entry *root = rootNav->entry();
  6281. //printf("Found docs for enum with name `%s' in context %s\n",
  6282. // root->name.data(),root->parent->name.data());
  6283. int i;
  6284. QCString name;
  6285. QCString scope;
  6286. if ((i=root->name.findRev("::"))!=-1) // scope is specified as part of the name
  6287. {
  6288. name=root->name.right(root->name.length()-i-2); // extract name
  6289. scope=root->name.left(i); // extract scope
  6290. //printf("Scope=`%s' Name=`%s'\n",scope.data(),name.data());
  6291. }
  6292. else // just the name
  6293. {
  6294. name=root->name;
  6295. }
  6296. if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
  6297. && !rootNav->parent()->name().isEmpty()
  6298. ) // found enum docs inside a compound
  6299. {
  6300. if (!scope.isEmpty()) scope.prepend("::");
  6301. scope.prepend(rootNav->parent()->name());
  6302. }
  6303. ClassDef *cd=getClass(scope);
  6304. if (!name.isEmpty())
  6305. {
  6306. bool found=FALSE;
  6307. if (cd)
  6308. {
  6309. //printf("Enum: scope=`%s' name=`%s'\n",cd->name(),name.data());
  6310. QCString className=cd->name().copy();
  6311. MemberName *mn=Doxygen::memberNameSDict->find(name);
  6312. if (mn)
  6313. {
  6314. MemberNameIterator mni(*mn);
  6315. MemberDef *md;
  6316. for (mni.toFirst();(md=mni.current()) && !found;++mni)
  6317. {
  6318. ClassDef *cd=md->getClassDef();
  6319. if (cd && cd->name()==className && md->isEnumerate())
  6320. {
  6321. // documentation outside a compound overrides the documentation inside it
  6322. #if 0
  6323. if (!md->documentation() || rootNav->parent()->name().isEmpty())
  6324. #endif
  6325. {
  6326. md->setDocumentation(root->doc,root->docFile,root->docLine);
  6327. md->setDocsForDefinition(!root->proto);
  6328. }
  6329. // brief descriptions inside a compound override the documentation
  6330. // outside it
  6331. #if 0
  6332. if (!md->briefDescription() || !rootNav->parent()->name().isEmpty())
  6333. #endif
  6334. {
  6335. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  6336. }
  6337. if (!md->inbodyDocumentation() || !rootNav->parent()->name().isEmpty())
  6338. {
  6339. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  6340. }
  6341. if (root->mGrpId!=-1 && md->getMemberGroupId()==-1)
  6342. {
  6343. md->setMemberGroupId(root->mGrpId);
  6344. }
  6345. md->addSectionsToDefinition(root->anchors);
  6346. md->setRefItems(root->sli);
  6347. GroupDef *gd=md->getGroupDef();
  6348. if (gd==0 &&root->groups->first()!=0) // member not grouped but out-of-line documentation is
  6349. {
  6350. addMemberToGroups(root,md);
  6351. }
  6352. found=TRUE;
  6353. }
  6354. }
  6355. }
  6356. else
  6357. {
  6358. //printf("MemberName %s not found!\n",name.data());
  6359. }
  6360. }
  6361. else // enum outside class
  6362. {
  6363. //printf("Enum outside class: %s grpId=%d\n",name.data(),root->mGrpId);
  6364. MemberName *mn=Doxygen::functionNameSDict->find(name);
  6365. if (mn)
  6366. {
  6367. MemberNameIterator mni(*mn);
  6368. MemberDef *md;
  6369. for (mni.toFirst();(md=mni.current()) && !found;++mni)
  6370. {
  6371. if (md->isEnumerate())
  6372. {
  6373. md->setDocumentation(root->doc,root->docFile,root->docLine);
  6374. md->setDocsForDefinition(!root->proto);
  6375. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  6376. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  6377. md->addSectionsToDefinition(root->anchors);
  6378. md->setMemberGroupId(root->mGrpId);
  6379. GroupDef *gd=md->getGroupDef();
  6380. if (gd==0 && root->groups->first()!=0) // member not grouped but out-of-line documentation is
  6381. {
  6382. addMemberToGroups(root,md);
  6383. }
  6384. found=TRUE;
  6385. }
  6386. }
  6387. }
  6388. }
  6389. if (!found)
  6390. {
  6391. warn(root->fileName,root->startLine,
  6392. "Warning: Documentation for undefined enum `%s' found.",
  6393. name.data()
  6394. );
  6395. }
  6396. }
  6397. rootNav->releaseEntry();
  6398. }
  6399. RECURSE_ENTRYTREE(findEnumDocumentation,rootNav);
  6400. }
  6401. // seach for each enum (member or function) in mnl if it has documented
  6402. // enum values.
  6403. static void findDEV(const MemberNameSDict &mnsd)
  6404. {
  6405. MemberName *mn;
  6406. MemberNameSDict::Iterator mnli(mnsd);
  6407. // for each member name
  6408. for (mnli.toFirst();(mn=mnli.current());++mnli)
  6409. {
  6410. MemberDef *md;
  6411. MemberNameIterator mni(*mn);
  6412. // for each member definition
  6413. for (mni.toFirst();(md=mni.current());++mni)
  6414. {
  6415. if (md->isEnumerate()) // member is an enum
  6416. {
  6417. LockingPtr<MemberList> fmdl = md->enumFieldList();
  6418. int documentedEnumValues=0;
  6419. if (fmdl!=0) // enum has values
  6420. {
  6421. MemberListIterator fmni(*fmdl);
  6422. MemberDef *fmd;
  6423. // for each enum value
  6424. for (fmni.toFirst();(fmd=fmni.current());++fmni)
  6425. {
  6426. if (fmd->isLinkableInProject()) documentedEnumValues++;
  6427. }
  6428. }
  6429. // at least one enum value is documented
  6430. if (documentedEnumValues>0) md->setDocumentedEnumValues(TRUE);
  6431. }
  6432. }
  6433. }
  6434. }
  6435. // seach for each enum (member or function) if it has documented enum
  6436. // values.
  6437. static void findDocumentedEnumValues()
  6438. {
  6439. findDEV(*Doxygen::memberNameSDict);
  6440. findDEV(*Doxygen::functionNameSDict);
  6441. }
  6442. //----------------------------------------------------------------------
  6443. static void addMembersToIndex()
  6444. {
  6445. MemberName *mn;
  6446. MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
  6447. // for each member name
  6448. for (mnli.toFirst();(mn=mnli.current());++mnli)
  6449. {
  6450. MemberDef *md;
  6451. MemberNameIterator mni(*mn);
  6452. // for each member definition
  6453. for (mni.toFirst();(md=mni.current());++mni)
  6454. {
  6455. addClassMemberNameToIndex(md);
  6456. }
  6457. }
  6458. MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
  6459. // for each member name
  6460. for (fnli.toFirst();(mn=fnli.current());++fnli)
  6461. {
  6462. MemberDef *md;
  6463. MemberNameIterator mni(*mn);
  6464. // for each member definition
  6465. for (mni.toFirst();(md=mni.current());++mni)
  6466. {
  6467. if (md->getNamespaceDef())
  6468. {
  6469. addNamespaceMemberNameToIndex(md);
  6470. }
  6471. else
  6472. {
  6473. addFileMemberNameToIndex(md);
  6474. }
  6475. }
  6476. }
  6477. }
  6478. //----------------------------------------------------------------------
  6479. // computes the relation between all members. For each member `m'
  6480. // the members that override the implementation of `m' are searched and
  6481. // the member that `m' overrides is searched.
  6482. static void computeMemberRelations()
  6483. {
  6484. MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
  6485. MemberName *mn;
  6486. for ( ; (mn=mnli.current()) ; ++mnli ) // for each member name
  6487. {
  6488. MemberNameIterator mdi(*mn);
  6489. MemberDef *md;
  6490. for ( ; (md=mdi.current()) ; ++mdi ) // for each member with a specific name
  6491. {
  6492. MemberDef *bmd = mn->first(); // for each other member with the same name
  6493. while (bmd)
  6494. {
  6495. ClassDef *mcd = md->getClassDef();
  6496. if (mcd && mcd->baseClasses())
  6497. {
  6498. ClassDef *bmcd = bmd->getClassDef();
  6499. //printf("Check relation between `%s'::`%s' (%p) and `%s'::`%s' (%p)\n",
  6500. // mcd->name().data(),md->name().data(),md,
  6501. // bmcd->name().data(),bmd->name().data(),bmd
  6502. // );
  6503. if (md!=bmd && bmcd && mcd && bmcd!=mcd && mcd->isBaseClass(bmcd,TRUE))
  6504. {
  6505. LockingPtr<ArgumentList> bmdAl = bmd->argumentList();
  6506. LockingPtr<ArgumentList> mdAl = md->argumentList();
  6507. //printf(" Base argList=`%s'\n Super argList=`%s'\n",
  6508. // argListToString(bmdAl.pointer()).data(),
  6509. // argListToString(mdAl.pointer()).data()
  6510. // );
  6511. if (
  6512. matchArguments2(bmd->getOuterScope(),bmd->getFileDef(),bmdAl.pointer(),
  6513. md->getOuterScope(), md->getFileDef(), mdAl.pointer(),
  6514. TRUE
  6515. )
  6516. )
  6517. {
  6518. //printf(" match found!\n");
  6519. if (mcd && bmcd &&
  6520. mcd->isLinkable() && bmcd->isLinkable()
  6521. )
  6522. {
  6523. MemberDef *rmd;
  6524. if ((rmd=md->reimplements())==0 ||
  6525. minClassDistance(mcd,bmcd)<minClassDistance(mcd,rmd->getClassDef())
  6526. )
  6527. {
  6528. //printf("setting (new) reimplements member\n");
  6529. md->setReimplements(bmd);
  6530. }
  6531. //printf("%s: add reimplements member %s\n",mcd->name().data(),bmcd->name().data());
  6532. //md->setImplements(bmd);
  6533. //printf("%s: add reimplementedBy member %s\n",bmcd->name().data(),mcd->name().data());
  6534. bmd->insertReimplementedBy(md);
  6535. }
  6536. }
  6537. }
  6538. }
  6539. bmd = mn->next();
  6540. }
  6541. }
  6542. }
  6543. }
  6544. //----------------------------------------------------------------------------
  6545. //static void computeClassImplUsageRelations()
  6546. //{
  6547. // ClassDef *cd;
  6548. // ClassSDict::Iterator cli(*Doxygen::classSDict);
  6549. // for (;(cd=cli.current());++cli)
  6550. // {
  6551. // cd->determineImplUsageRelation();
  6552. // }
  6553. //}
  6554. //----------------------------------------------------------------------------
  6555. static void createTemplateInstanceMembers()
  6556. {
  6557. ClassSDict::Iterator cli(*Doxygen::classSDict);
  6558. ClassDef *cd;
  6559. // for each class
  6560. for (cli.toFirst();(cd=cli.current());++cli)
  6561. {
  6562. // that is a template
  6563. QDict<ClassDef> *templInstances = cd->getTemplateInstances();
  6564. if (templInstances)
  6565. {
  6566. QDictIterator<ClassDef> qdi(*templInstances);
  6567. ClassDef *tcd=0;
  6568. // for each instance of the template
  6569. for (qdi.toFirst();(tcd=qdi.current());++qdi)
  6570. {
  6571. tcd->addMembersToTemplateInstance(cd,qdi.currentKey());
  6572. }
  6573. }
  6574. }
  6575. }
  6576. //----------------------------------------------------------------------------
  6577. // builds the list of all members for each class
  6578. static void buildCompleteMemberLists()
  6579. {
  6580. ClassDef *cd;
  6581. // merge members of categories into the class they extend
  6582. ClassSDict::Iterator cli(*Doxygen::classSDict);
  6583. for (cli.toFirst();(cd=cli.current());++cli)
  6584. {
  6585. int i=cd->name().find('(');
  6586. if (i!=-1) // it is an Objective-C category
  6587. {
  6588. QCString baseName=cd->name().left(i);
  6589. ClassDef *baseClass=Doxygen::classSDict->find(baseName);
  6590. if (baseClass)
  6591. {
  6592. //printf("*** merging members of category %s into %s\n",
  6593. // cd->name().data(),baseClass->name().data());
  6594. baseClass->mergeCategory(cd);
  6595. }
  6596. }
  6597. }
  6598. // merge the member list of base classes into the inherited classes.
  6599. for (cli.toFirst();(cd=cli.current());++cli)
  6600. {
  6601. if (// !cd->isReference() && // not an external class
  6602. cd->subClasses()==0 && // is a root of the hierarchy
  6603. cd->baseClasses()) // and has at least one base class
  6604. {
  6605. //printf("*** merging members for %s\n",cd->name().data());
  6606. cd->mergeMembers();
  6607. }
  6608. }
  6609. // now sort the member list of all classes.
  6610. for (cli.toFirst();(cd=cli.current());++cli)
  6611. {
  6612. if (cd->memberNameInfoSDict()) cd->memberNameInfoSDict()->sort();
  6613. }
  6614. }
  6615. //----------------------------------------------------------------------------
  6616. static void generateFileSources()
  6617. {
  6618. if (documentedHtmlFiles==0) return;
  6619. if (Doxygen::inputNameList->count()>0)
  6620. {
  6621. FileNameListIterator fnli(*Doxygen::inputNameList);
  6622. FileName *fn;
  6623. for (;(fn=fnli.current());++fnli)
  6624. {
  6625. FileNameIterator fni(*fn);
  6626. FileDef *fd;
  6627. for (;(fd=fni.current());++fni)
  6628. {
  6629. if (fd->generateSourceFile()) // sources need to be shown in the output
  6630. {
  6631. msg("Generating code for file %s...\n",fd->docName().data());
  6632. fd->writeSource(*g_outputList);
  6633. }
  6634. else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
  6635. // we needed to parse the sources even if we do not show them
  6636. {
  6637. msg("Parsing code for file %s...\n",fd->docName().data());
  6638. fd->parseSource();
  6639. }
  6640. }
  6641. }
  6642. }
  6643. }
  6644. //----------------------------------------------------------------------------
  6645. static void generateFileDocs()
  6646. {
  6647. if (documentedHtmlFiles==0) return;
  6648. if (Doxygen::inputNameList->count()>0)
  6649. {
  6650. FileNameListIterator fnli(*Doxygen::inputNameList);
  6651. FileName *fn;
  6652. for (fnli.toFirst();(fn=fnli.current());++fnli)
  6653. {
  6654. FileNameIterator fni(*fn);
  6655. FileDef *fd;
  6656. for (fni.toFirst();(fd=fni.current());++fni)
  6657. {
  6658. bool doc = fd->isLinkableInProject();
  6659. if (doc)
  6660. {
  6661. msg("Generating docs for file %s...\n",fd->docName().data());
  6662. fd->writeDocumentation(*g_outputList);
  6663. }
  6664. }
  6665. }
  6666. }
  6667. }
  6668. //----------------------------------------------------------------------------
  6669. static void addSourceReferences()
  6670. {
  6671. // add source references for class definitions
  6672. ClassSDict::Iterator cli(*Doxygen::classSDict);
  6673. ClassDef *cd=0;
  6674. for (cli.toFirst();(cd=cli.current());++cli)
  6675. {
  6676. FileDef *fd=cd->getBodyDef();
  6677. if (fd && cd->isLinkableInProject() && cd->getStartBodyLine()!=-1)
  6678. {
  6679. fd->addSourceRef(cd->getStartBodyLine(),cd,0);
  6680. }
  6681. }
  6682. // add source references for namespace definitions
  6683. NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
  6684. NamespaceDef *nd=0;
  6685. for (nli.toFirst();(nd=nli.current());++nli)
  6686. {
  6687. FileDef *fd=nd->getBodyDef();
  6688. if (fd && nd->isLinkableInProject() && nd->getStartBodyLine()!=-1)
  6689. {
  6690. fd->addSourceRef(nd->getStartBodyLine(),nd,0);
  6691. }
  6692. }
  6693. // add source references for member names
  6694. MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
  6695. MemberName *mn=0;
  6696. for (mnli.toFirst();(mn=mnli.current());++mnli)
  6697. {
  6698. MemberNameIterator mni(*mn);
  6699. MemberDef *md=0;
  6700. for (mni.toFirst();(md=mni.current());++mni)
  6701. {
  6702. //printf("class member %s\n",md->name().data());
  6703. FileDef *fd=md->getBodyDef();
  6704. if (fd &&
  6705. md->getStartBodyLine()!=-1 &&
  6706. md->isLinkableInProject() &&
  6707. (fd->generateSourceFile() || Doxygen::parseSourcesNeeded)
  6708. )
  6709. {
  6710. //printf("Found member `%s' in file `%s' at line `%d' def=%s\n",
  6711. // md->name().data(),fd->name().data(),md->getStartBodyLine(),md->getOuterScope()->name().data());
  6712. fd->addSourceRef(md->getStartBodyLine(),md->getOuterScope(),md);
  6713. }
  6714. }
  6715. }
  6716. MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
  6717. for (fnli.toFirst();(mn=fnli.current());++fnli)
  6718. {
  6719. MemberNameIterator mni(*mn);
  6720. MemberDef *md=0;
  6721. for (mni.toFirst();(md=mni.current());++mni)
  6722. {
  6723. FileDef *fd=md->getBodyDef();
  6724. //printf("member %s body=[%d,%d] fd=%p link=%d parseSources=%d\n",
  6725. // md->name().data(),
  6726. // md->getStartBodyLine(),md->getEndBodyLine(),fd,
  6727. // md->isLinkableInProject(),
  6728. // Doxygen::parseSourcesNeeded);
  6729. if (fd &&
  6730. md->getStartBodyLine()!=-1 &&
  6731. md->isLinkableInProject() &&
  6732. (fd->generateSourceFile() || Doxygen::parseSourcesNeeded)
  6733. )
  6734. {
  6735. //printf("Found member `%s' in file `%s' at line `%d' def=%s\n",
  6736. // md->name().data(),fd->name().data(),md->getStartBodyLine(),md->getOuterScope()->name().data());
  6737. fd->addSourceRef(md->getStartBodyLine(),md->getOuterScope(),md);
  6738. }
  6739. }
  6740. }
  6741. }
  6742. //----------------------------------------------------------------------------
  6743. // generate the documentation of all classes
  6744. static void generateClassList(ClassSDict &classSDict)
  6745. {
  6746. ClassSDict::Iterator cli(classSDict);
  6747. for ( ; cli.current() ; ++cli )
  6748. {
  6749. ClassDef *cd=cli.current();
  6750. //printf("cd=%s getOuterScope=%p global=%p\n",cd->name().data(),cd->getOuterScope(),Doxygen::globalScope);
  6751. if ((cd->getOuterScope()==0 || // <-- should not happen, but can if we read an old tag file
  6752. cd->getOuterScope()==Doxygen::globalScope // only look at global classes
  6753. ) && !cd->isHidden()
  6754. )
  6755. {
  6756. // skip external references, anonymous compounds and
  6757. // template instances
  6758. if ( cd->isLinkableInProject() && cd->templateMaster()==0)
  6759. {
  6760. msg("Generating docs for compound %s...\n",cd->name().data());
  6761. cd->writeDocumentation(*g_outputList);
  6762. cd->writeMemberList(*g_outputList);
  6763. }
  6764. // even for undocumented classes, the inner classes can be documented.
  6765. cd->writeDocumentationForInnerClasses(*g_outputList);
  6766. }
  6767. }
  6768. }
  6769. static void generateClassDocs()
  6770. {
  6771. // write the installdox script if necessary
  6772. if (Config_getBool("GENERATE_HTML") &&
  6773. (Config_getList("TAGFILES").count()>0 ||
  6774. Config_getBool("SEARCHENGINE")
  6775. )
  6776. )
  6777. {
  6778. writeInstallScript();
  6779. }
  6780. msg("Generating annotated compound index...\n");
  6781. writeAnnotatedIndex(*g_outputList);
  6782. //if (Config_getBool("ALPHABETICAL_INDEX"))
  6783. //{
  6784. msg("Generating alphabetical compound index...\n");
  6785. writeAlphabeticalIndex(*g_outputList);
  6786. //}
  6787. msg("Generating hierarchical class index...\n");
  6788. writeHierarchicalIndex(*g_outputList);
  6789. msg("Generating member index...\n");
  6790. writeClassMemberIndex(*g_outputList);
  6791. if (Doxygen::exampleSDict->count()>0)
  6792. {
  6793. msg("Generating example index...\n");
  6794. }
  6795. generateClassList(*Doxygen::classSDict);
  6796. generateClassList(*Doxygen::hiddenClasses);
  6797. }
  6798. //----------------------------------------------------------------------------
  6799. static void inheritDocumentation()
  6800. {
  6801. MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
  6802. MemberName *mn;
  6803. //int count=0;
  6804. for (;(mn=mnli.current());++mnli)
  6805. {
  6806. MemberNameIterator mni(*mn);
  6807. MemberDef *md;
  6808. for (;(md=mni.current());++mni)
  6809. {
  6810. //printf("%04d Member `%s'\n",count++,md->name().data());
  6811. if (md->documentation().isEmpty() && md->briefDescription().isEmpty())
  6812. { // no documentation yet
  6813. MemberDef *bmd = md->reimplements();
  6814. while (bmd && bmd->documentation().isEmpty() &&
  6815. bmd->briefDescription().isEmpty()
  6816. )
  6817. { // search up the inheritance tree for a documentation member
  6818. //printf("bmd=%s class=%s\n",bmd->name().data(),bmd->getClassDef()->name().data());
  6819. bmd = bmd->reimplements();
  6820. }
  6821. if (bmd) // copy the documentation from the reimplemented member
  6822. {
  6823. md->setInheritsDocsFrom(bmd);
  6824. md->setDocumentation(bmd->documentation(),bmd->docFile(),bmd->docLine());
  6825. md->setDocsForDefinition(bmd->isDocsForDefinition());
  6826. md->setBriefDescription(bmd->briefDescription(),bmd->briefFile(),bmd->briefLine());
  6827. md->copyArgumentNames(bmd);
  6828. md->setInbodyDocumentation(bmd->inbodyDocumentation(),bmd->inbodyFile(),bmd->inbodyLine());
  6829. }
  6830. }
  6831. }
  6832. }
  6833. }
  6834. //----------------------------------------------------------------------------
  6835. static void combineUsingRelations()
  6836. {
  6837. // for each file
  6838. FileNameListIterator fnli(*Doxygen::inputNameList);
  6839. FileName *fn;
  6840. for (fnli.toFirst();(fn=fnli.current());++fnli)
  6841. {
  6842. FileNameIterator fni(*fn);
  6843. FileDef *fd;
  6844. for (fni.toFirst();(fd=fni.current());++fni)
  6845. {
  6846. fd->visited=FALSE;
  6847. }
  6848. }
  6849. for (fnli.toFirst();(fn=fnli.current());++fnli)
  6850. {
  6851. FileNameIterator fni(*fn);
  6852. FileDef *fd;
  6853. for (fni.toFirst();(fd=fni.current());++fni)
  6854. {
  6855. fd->combineUsingRelations();
  6856. }
  6857. }
  6858. // for each namespace
  6859. NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
  6860. NamespaceDef *nd;
  6861. for (nli.toFirst() ; (nd=nli.current()) ; ++nli )
  6862. {
  6863. nd->visited=FALSE;
  6864. }
  6865. for (nli.toFirst() ; (nd=nli.current()) ; ++nli )
  6866. {
  6867. nd->combineUsingRelations();
  6868. }
  6869. }
  6870. //----------------------------------------------------------------------------
  6871. static void addMembersToMemberGroup()
  6872. {
  6873. // for each class
  6874. ClassSDict::Iterator cli(*Doxygen::classSDict);
  6875. ClassDef *cd;
  6876. for ( ; (cd=cli.current()) ; ++cli )
  6877. {
  6878. cd->addMembersToMemberGroup();
  6879. }
  6880. // for each file
  6881. FileName *fn=Doxygen::inputNameList->first();
  6882. while (fn)
  6883. {
  6884. FileDef *fd=fn->first();
  6885. while (fd)
  6886. {
  6887. fd->addMembersToMemberGroup();
  6888. fd=fn->next();
  6889. }
  6890. fn=Doxygen::inputNameList->next();
  6891. }
  6892. // for each namespace
  6893. NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
  6894. NamespaceDef *nd;
  6895. for ( ; (nd=nli.current()) ; ++nli )
  6896. {
  6897. nd->addMembersToMemberGroup();
  6898. }
  6899. // for each group
  6900. GroupSDict::Iterator gli(*Doxygen::groupSDict);
  6901. GroupDef *gd;
  6902. for (gli.toFirst();(gd=gli.current());++gli)
  6903. {
  6904. gd->addMembersToMemberGroup();
  6905. }
  6906. }
  6907. //----------------------------------------------------------------------------
  6908. static void distributeMemberGroupDocumentation()
  6909. {
  6910. // for each class
  6911. ClassSDict::Iterator cli(*Doxygen::classSDict);
  6912. ClassDef *cd;
  6913. for ( ; (cd=cli.current()) ; ++cli )
  6914. {
  6915. cd->distributeMemberGroupDocumentation();
  6916. }
  6917. // for each file
  6918. FileName *fn=Doxygen::inputNameList->first();
  6919. while (fn)
  6920. {
  6921. FileDef *fd=fn->first();
  6922. while (fd)
  6923. {
  6924. fd->distributeMemberGroupDocumentation();
  6925. fd=fn->next();
  6926. }
  6927. fn=Doxygen::inputNameList->next();
  6928. }
  6929. // for each namespace
  6930. NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
  6931. NamespaceDef *nd;
  6932. for ( ; (nd=nli.current()) ; ++nli )
  6933. {
  6934. nd->distributeMemberGroupDocumentation();
  6935. }
  6936. // for each group
  6937. GroupSDict::Iterator gli(*Doxygen::groupSDict);
  6938. GroupDef *gd;
  6939. for (gli.toFirst();(gd=gli.current());++gli)
  6940. {
  6941. gd->distributeMemberGroupDocumentation();
  6942. }
  6943. }
  6944. //----------------------------------------------------------------------------
  6945. static void findSectionsInDocumentation()
  6946. {
  6947. // for each class
  6948. ClassSDict::Iterator cli(*Doxygen::classSDict);
  6949. ClassDef *cd;
  6950. for ( ; (cd=cli.current()) ; ++cli )
  6951. {
  6952. cd->findSectionsInDocumentation();
  6953. }
  6954. // for each file
  6955. FileName *fn=Doxygen::inputNameList->first();
  6956. while (fn)
  6957. {
  6958. FileDef *fd=fn->first();
  6959. while (fd)
  6960. {
  6961. fd->findSectionsInDocumentation();
  6962. fd=fn->next();
  6963. }
  6964. fn=Doxygen::inputNameList->next();
  6965. }
  6966. // for each namespace
  6967. NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
  6968. NamespaceDef *nd;
  6969. for ( ; (nd=nli.current()) ; ++nli )
  6970. {
  6971. nd->findSectionsInDocumentation();
  6972. }
  6973. // for each group
  6974. GroupSDict::Iterator gli(*Doxygen::groupSDict);
  6975. GroupDef *gd;
  6976. for (gli.toFirst();(gd=gli.current());++gli)
  6977. {
  6978. gd->findSectionsInDocumentation();
  6979. }
  6980. // for each page
  6981. PageSDict::Iterator pdi(*Doxygen::pageSDict);
  6982. PageDef *pd=0;
  6983. for (pdi.toFirst();(pd=pdi.current());++pdi)
  6984. {
  6985. pd->findSectionsInDocumentation();
  6986. }
  6987. if (Doxygen::mainPage) Doxygen::mainPage->findSectionsInDocumentation();
  6988. }
  6989. static void flushCachedTemplateRelations()
  6990. {
  6991. // remove all references to classes from the cache
  6992. // as there can be new template instances in the inheritance path
  6993. // to this class. Optimization: only remove those classes that
  6994. // have inheritance instances as direct or indirect sub classes.
  6995. QCacheIterator<LookupInfo> ci(Doxygen::lookupCache);
  6996. LookupInfo *li=0;
  6997. for (ci.toFirst();(li=ci.current());++ci)
  6998. {
  6999. if (li->classDef)
  7000. {
  7001. Doxygen::lookupCache.remove(ci.currentKey());
  7002. }
  7003. }
  7004. // remove all cached typedef resolutions whose target is a
  7005. // template class as this may now be a template instance
  7006. MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
  7007. MemberName *fn;
  7008. for (;(fn=fnli.current());++fnli) // for each global function name
  7009. {
  7010. MemberNameIterator fni(*fn);
  7011. MemberDef *fmd;
  7012. for (;(fmd=fni.current());++fni) // for each function with that name
  7013. {
  7014. if (fmd->isTypedefValCached())
  7015. {
  7016. ClassDef *cd = fmd->getCachedTypedefVal();
  7017. if (cd->isTemplate()) fmd->invalidateTypedefValCache();
  7018. }
  7019. }
  7020. }
  7021. MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
  7022. for (;(fn=mnli.current());++mnli) // for each class method name
  7023. {
  7024. MemberNameIterator mni(*fn);
  7025. MemberDef *fmd;
  7026. for (;(fmd=mni.current());++mni) // for each function with that name
  7027. {
  7028. if (fmd->isTypedefValCached())
  7029. {
  7030. ClassDef *cd = fmd->getCachedTypedefVal();
  7031. if (cd->isTemplate()) fmd->invalidateTypedefValCache();
  7032. }
  7033. }
  7034. }
  7035. }
  7036. //----------------------------------------------------------------------------
  7037. static void flushUnresolvedRelations()
  7038. {
  7039. // Remove all unresolved references to classes from the cache.
  7040. // This is needed before resolving the inheritance relations, since
  7041. // it would otherwise not find the inheritance relation
  7042. // for C in the example below, as B::I was already found to be unresolvable
  7043. // (which is correct if you igore the inheritance relation between A and B).
  7044. //
  7045. // class A { class I {} };
  7046. // class B : public A {};
  7047. // class C : public B::I {};
  7048. //
  7049. QCacheIterator<LookupInfo> ci(Doxygen::lookupCache);
  7050. LookupInfo *li=0;
  7051. for (ci.toFirst();(li=ci.current());++ci)
  7052. {
  7053. if (li->classDef==0 && li->typeDef==0)
  7054. {
  7055. Doxygen::lookupCache.remove(ci.currentKey());
  7056. }
  7057. }
  7058. MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
  7059. MemberName *fn;
  7060. for (;(fn=fnli.current());++fnli) // for each global function name
  7061. {
  7062. MemberNameIterator fni(*fn);
  7063. MemberDef *fmd;
  7064. for (;(fmd=fni.current());++fni) // for each function with that name
  7065. {
  7066. fmd->invalidateCachedArgumentTypes();
  7067. }
  7068. }
  7069. MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
  7070. for (;(fn=mnli.current());++mnli) // for each class method name
  7071. {
  7072. MemberNameIterator mni(*fn);
  7073. MemberDef *fmd;
  7074. for (;(fmd=mni.current());++mni) // for each function with that name
  7075. {
  7076. fmd->invalidateCachedArgumentTypes();
  7077. }
  7078. }
  7079. }
  7080. //----------------------------------------------------------------------------
  7081. static void findDefineDocumentation(EntryNav *rootNav)
  7082. {
  7083. if ((rootNav->section()==Entry::DEFINEDOC_SEC ||
  7084. rootNav->section()==Entry::DEFINE_SEC) && !rootNav->name().isEmpty()
  7085. )
  7086. {
  7087. rootNav->loadEntry(g_storage);
  7088. Entry *root = rootNav->entry();
  7089. //printf("found define `%s' `%s' brief=`%s' doc=`%s'\n",
  7090. // root->name.data(),root->args.data(),root->brief.data(),root->doc.data());
  7091. if (rootNav->tagInfo() && !root->name.isEmpty()) // define read from a tag file
  7092. {
  7093. MemberDef *md=new MemberDef("<tagfile>",1,
  7094. "#define",root->name,root->args,0,
  7095. Public,Normal,FALSE,Member,MemberDef::Define,0,0);
  7096. md->setTagInfo(rootNav->tagInfo());
  7097. //printf("Searching for `%s' fd=%p\n",filePathName.data(),fd);
  7098. md->setFileDef(rootNav->parent()->fileDef());
  7099. //printf("Adding member=%s\n",md->name().data());
  7100. MemberName *mn;
  7101. if ((mn=Doxygen::functionNameSDict->find(root->name)))
  7102. {
  7103. mn->append(md);
  7104. }
  7105. else
  7106. {
  7107. mn = new MemberName(root->name);
  7108. mn->append(md);
  7109. Doxygen::functionNameSDict->append(root->name,mn);
  7110. }
  7111. }
  7112. MemberName *mn=Doxygen::functionNameSDict->find(root->name);
  7113. if (mn)
  7114. {
  7115. int count=0;
  7116. MemberDef *md=mn->first();
  7117. while (md)
  7118. {
  7119. if (md->memberType()==MemberDef::Define) count++;
  7120. md=mn->next();
  7121. }
  7122. if (count==1)
  7123. {
  7124. md=mn->first();
  7125. while (md)
  7126. {
  7127. if (md->memberType()==MemberDef::Define)
  7128. {
  7129. #if 0
  7130. if (md->documentation().isEmpty())
  7131. #endif
  7132. {
  7133. md->setDocumentation(root->doc,root->docFile,root->docLine);
  7134. md->setDocsForDefinition(!root->proto);
  7135. }
  7136. #if 0
  7137. if (md->briefDescription().isEmpty())
  7138. #endif
  7139. {
  7140. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  7141. }
  7142. if (md->inbodyDocumentation().isEmpty())
  7143. {
  7144. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  7145. }
  7146. md->setBodySegment(root->bodyLine,root->endBodyLine);
  7147. md->setBodyDef(rootNav->fileDef());
  7148. md->addSectionsToDefinition(root->anchors);
  7149. md->setMaxInitLines(root->initLines);
  7150. md->setRefItems(root->sli);
  7151. if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId);
  7152. addMemberToGroups(root,md);
  7153. }
  7154. md=mn->next();
  7155. }
  7156. }
  7157. else if (count>1 &&
  7158. (!root->doc.isEmpty() ||
  7159. !root->brief.isEmpty() ||
  7160. root->bodyLine!=-1
  7161. )
  7162. )
  7163. // multiple defines don't know where to add docs
  7164. // but maybe they are in different files together with their documentation
  7165. {
  7166. md=mn->first();
  7167. while (md)
  7168. {
  7169. if (md->memberType()==MemberDef::Define)
  7170. {
  7171. FileDef *fd=md->getFileDef();
  7172. if (fd && fd->absFilePath()==root->fileName)
  7173. // doc and define in the same file assume they belong together.
  7174. {
  7175. #if 0
  7176. if (md->documentation().isEmpty())
  7177. #endif
  7178. {
  7179. md->setDocumentation(root->doc,root->docFile,root->docLine);
  7180. md->setDocsForDefinition(!root->proto);
  7181. }
  7182. #if 0
  7183. if (md->briefDescription().isEmpty())
  7184. #endif
  7185. {
  7186. md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  7187. }
  7188. if (md->inbodyDocumentation().isEmpty())
  7189. {
  7190. md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
  7191. }
  7192. md->setBodySegment(root->bodyLine,root->endBodyLine);
  7193. md->setBodyDef(rootNav->fileDef());
  7194. md->addSectionsToDefinition(root->anchors);
  7195. md->setRefItems(root->sli);
  7196. if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId);
  7197. addMemberToGroups(root,md);
  7198. }
  7199. }
  7200. md=mn->next();
  7201. }
  7202. //warn("Warning: define %s found in the following files:\n",root->name.data());
  7203. //warn("Cannot determine where to add the documentation found "
  7204. // "at line %d of file %s. \n",
  7205. // root->startLine,root->fileName.data());
  7206. }
  7207. }
  7208. else if (!root->doc.isEmpty() || !root->brief.isEmpty()) // define not found
  7209. {
  7210. static bool preEnabled = Config_getBool("ENABLE_PREPROCESSING");
  7211. if (preEnabled)
  7212. {
  7213. warn(root->fileName,root->startLine,
  7214. "Warning: documentation for unknown define %s found.\n",
  7215. root->name.data()
  7216. );
  7217. }
  7218. else
  7219. {
  7220. warn(root->fileName,root->startLine,
  7221. "Warning: found documented #define but ignoring it because "
  7222. "ENABLE_PREPROCESSING is NO.\n",
  7223. root->name.data()
  7224. );
  7225. }
  7226. }
  7227. rootNav->releaseEntry();
  7228. }
  7229. RECURSE_ENTRYTREE(findDefineDocumentation,rootNav);
  7230. }
  7231. //----------------------------------------------------------------------------
  7232. static void findDirDocumentation(EntryNav *rootNav)
  7233. {
  7234. if (rootNav->section() == Entry::DIRDOC_SEC)
  7235. {
  7236. rootNav->loadEntry(g_storage);
  7237. Entry *root = rootNav->entry();
  7238. QCString normalizedName = root->name;
  7239. normalizedName = substitute(normalizedName,"\\","/");
  7240. //printf("root->docFile=%s normalizedName=%s\n",
  7241. // root->docFile.data(),normalizedName.data());
  7242. if (root->docFile==normalizedName) // current dir?
  7243. {
  7244. int lastSlashPos=normalizedName.findRev('/');
  7245. if (lastSlashPos!=-1) // strip file name
  7246. {
  7247. normalizedName=normalizedName.left(lastSlashPos);
  7248. }
  7249. }
  7250. if (normalizedName.at(normalizedName.length()-1)!='/')
  7251. {
  7252. normalizedName+='/';
  7253. }
  7254. DirDef *dir,*matchingDir=0;
  7255. SDict<DirDef>::Iterator sdi(*Doxygen::directories);
  7256. for (sdi.toFirst();(dir=sdi.current());++sdi)
  7257. {
  7258. //printf("Dir: %s<->%s\n",dir->name().data(),normalizedName.data());
  7259. if (dir->name().right(normalizedName.length())==normalizedName)
  7260. {
  7261. if (matchingDir)
  7262. {
  7263. warn(root->fileName,root->startLine,
  7264. "Warning: \\dir command matches multiple directories.\n"
  7265. " Applying the command for directory %s\n"
  7266. " Ignoring the command for directory %s\n",
  7267. matchingDir->name().data(),dir->name().data()
  7268. );
  7269. }
  7270. else
  7271. {
  7272. matchingDir=dir;
  7273. }
  7274. }
  7275. }
  7276. if (matchingDir)
  7277. {
  7278. //printf("Match for with dir %s\n",matchingDir->name().data());
  7279. matchingDir->setBriefDescription(root->brief,root->briefFile,root->briefLine);
  7280. matchingDir->setDocumentation(root->doc,root->docFile,root->docLine);
  7281. matchingDir->setRefItems(root->sli);
  7282. addDirToGroups(root,matchingDir);
  7283. }
  7284. else
  7285. {
  7286. warn(root->fileName,root->startLine,"Warning: No matching "
  7287. "directory found for command \\dir %s\n",normalizedName.data());
  7288. }
  7289. rootNav->releaseEntry();
  7290. }
  7291. RECURSE_ENTRYTREE(findDirDocumentation,rootNav);
  7292. }
  7293. //----------------------------------------------------------------------------
  7294. // create a (sorted) list of separate documentation pages
  7295. static void buildPageList(EntryNav *rootNav)
  7296. {
  7297. if (rootNav->section() == Entry::PAGEDOC_SEC)
  7298. {
  7299. rootNav->loadEntry(g_storage);
  7300. Entry *root = rootNav->entry();
  7301. if (!root->name.isEmpty())
  7302. {
  7303. addRelatedPage(rootNav);
  7304. }
  7305. rootNav->releaseEntry();
  7306. }
  7307. else if (rootNav->section() == Entry::MAINPAGEDOC_SEC)
  7308. {
  7309. rootNav->loadEntry(g_storage);
  7310. Entry *root = rootNav->entry();
  7311. QCString title=root->args.stripWhiteSpace();
  7312. if (title.isEmpty()) title=theTranslator->trMainPage();
  7313. QCString name = Config_getBool("GENERATE_TREEVIEW")?"main":"index";
  7314. addRefItem(root->sli,
  7315. name,
  7316. "page",
  7317. name,
  7318. title,
  7319. 0
  7320. );
  7321. rootNav->releaseEntry();
  7322. }
  7323. RECURSE_ENTRYTREE(buildPageList,rootNav);
  7324. }
  7325. static void findMainPage(EntryNav *rootNav)
  7326. {
  7327. if (rootNav->section() == Entry::MAINPAGEDOC_SEC)
  7328. {
  7329. rootNav->loadEntry(g_storage);
  7330. Entry *root = rootNav->entry();
  7331. if (Doxygen::mainPage==0)
  7332. {
  7333. //printf("Found main page! \n======\n%s\n=======\n",root->doc.data());
  7334. QCString title=root->args.stripWhiteSpace();
  7335. QCString indexName=Config_getBool("GENERATE_TREEVIEW")?"main":"index";
  7336. Doxygen::mainPage = new PageDef(root->fileName,root->startLine,
  7337. indexName, root->brief+root->doc+root->inbodyDocs,title);
  7338. //setFileNameForSections(root->anchors,"index",Doxygen::mainPage);
  7339. Doxygen::mainPage->setFileName(indexName);
  7340. addPageToContext(Doxygen::mainPage,rootNav);
  7341. // a page name is a label as well!
  7342. SectionInfo *si=new SectionInfo(
  7343. indexName,
  7344. Doxygen::mainPage->name(),
  7345. Doxygen::mainPage->title(),
  7346. SectionInfo::Page);
  7347. Doxygen::sectionDict.insert(indexName,si);
  7348. Doxygen::mainPage->addSectionsToDefinition(root->anchors);
  7349. }
  7350. else
  7351. {
  7352. warn(root->fileName,root->startLine,
  7353. "Warning: found more than one \\mainpage comment block! Skipping this "
  7354. "block."
  7355. );
  7356. }
  7357. rootNav->releaseEntry();
  7358. }
  7359. RECURSE_ENTRYTREE(findMainPage,rootNav);
  7360. }
  7361. static void computePageRelations(EntryNav *rootNav)
  7362. {
  7363. if ((rootNav->section()==Entry::PAGEDOC_SEC ||
  7364. rootNav->section()==Entry::MAINPAGEDOC_SEC
  7365. )
  7366. && !rootNav->name().isEmpty()
  7367. )
  7368. {
  7369. rootNav->loadEntry(g_storage);
  7370. Entry *root = rootNav->entry();
  7371. PageDef *pd = root->section==Entry::PAGEDOC_SEC ?
  7372. Doxygen::pageSDict->find(root->name) :
  7373. Doxygen::mainPage;
  7374. if (pd)
  7375. {
  7376. QListIterator<BaseInfo> bii(*root->extends);
  7377. BaseInfo *bi;
  7378. for (bii.toFirst();(bi=bii.current());++bii)
  7379. {
  7380. PageDef *subPd = Doxygen::pageSDict->find(bi->name);
  7381. if (subPd)
  7382. {
  7383. pd->addInnerCompound(subPd);
  7384. //printf("*** Added subpage relation: %s->%s\n",
  7385. // pd->name().data(),subPd->name().data());
  7386. }
  7387. }
  7388. }
  7389. rootNav->releaseEntry();
  7390. }
  7391. RECURSE_ENTRYTREE(computePageRelations,rootNav);
  7392. }
  7393. static void checkPageRelations()
  7394. {
  7395. PageSDict::Iterator pdi(*Doxygen::pageSDict);
  7396. PageDef *pd=0;
  7397. for (pdi.toFirst();(pd=pdi.current());++pdi)
  7398. {
  7399. Definition *ppd = pd->getOuterScope();
  7400. while (ppd)
  7401. {
  7402. if (ppd==pd)
  7403. {
  7404. err("Warning: page defined at line %d of file %s with label %s is a subpage "
  7405. "of itself! Please remove this cyclic dependency.\n",
  7406. pd->docLine(),pd->docFile().data(),pd->name().data());
  7407. exit(1);
  7408. }
  7409. ppd=ppd->getOuterScope();
  7410. }
  7411. }
  7412. }
  7413. //----------------------------------------------------------------------------
  7414. static void resolveUserReferences()
  7415. {
  7416. QDictIterator<SectionInfo> sdi(Doxygen::sectionDict);
  7417. SectionInfo *si;
  7418. for (;(si=sdi.current());++sdi)
  7419. {
  7420. //printf("si->label=`%s' si->definition=%s si->fileName=`%s'\n",
  7421. // si->label.data(),si->definition?si->definition->name().data():"<none>",
  7422. // si->fileName.data());
  7423. PageDef *pd=0;
  7424. // hack: the items of a todo/test/bug/deprecated list are all fragments from
  7425. // different files, so the resulting section's all have the wrong file
  7426. // name (not from the todo/test/bug/deprecated list, but from the file in
  7427. // which they are defined). We correct this here by looking at the
  7428. // generated section labels!
  7429. QDictIterator<RefList> rli(*Doxygen::xrefLists);
  7430. RefList *rl;
  7431. for (rli.toFirst();(rl=rli.current());++rli)
  7432. {
  7433. QCString label="_"+rl->listName(); // "_todo", "_test", ...
  7434. if (si->label.left(label.length())==label)
  7435. {
  7436. si->fileName=rl->listName();
  7437. si->generated=TRUE;
  7438. break;
  7439. }
  7440. }
  7441. //printf("start: si->label=%s si->fileName=%s\n",si->label.data(),si->fileName.data());
  7442. if (!si->generated)
  7443. {
  7444. // if this section is in a page and the page is in a group, then we
  7445. // have to adjust the link file name to point to the group.
  7446. if (!si->fileName.isEmpty() &&
  7447. (pd=Doxygen::pageSDict->find(si->fileName)) &&
  7448. pd->getGroupDef())
  7449. {
  7450. si->fileName=pd->getGroupDef()->getOutputFileBase().copy();
  7451. }
  7452. if (si->definition)
  7453. {
  7454. // TODO: there should be one function in Definition that returns
  7455. // the file to link to, so we can avoid the following tests.
  7456. GroupDef *gd=0;
  7457. if (si->definition->definitionType()==Definition::TypeMember)
  7458. {
  7459. gd = ((MemberDef *)si->definition)->getGroupDef();
  7460. }
  7461. if (gd)
  7462. {
  7463. si->fileName=gd->getOutputFileBase().copy();
  7464. }
  7465. else
  7466. {
  7467. //si->fileName=si->definition->getOutputFileBase().copy();
  7468. //printf("Setting si->fileName to %s\n",si->fileName.data());
  7469. }
  7470. }
  7471. }
  7472. //printf("end: si->label=%s si->fileName=%s\n",si->label.data(),si->fileName.data());
  7473. }
  7474. }
  7475. //----------------------------------------------------------------------------
  7476. // generate all separate documentation pages
  7477. static void generatePageDocs()
  7478. {
  7479. //printf("documentedPages=%d real=%d\n",documentedPages,Doxygen::pageSDict->count());
  7480. if (documentedPages==0) return;
  7481. PageSDict::Iterator pdi(*Doxygen::pageSDict);
  7482. PageDef *pd=0;
  7483. for (pdi.toFirst();(pd=pdi.current());++pdi)
  7484. {
  7485. if (!pd->getGroupDef() && !pd->isReference())
  7486. {
  7487. msg("Generating docs for page %s...\n",pd->name().data());
  7488. Doxygen::insideMainPage=TRUE;
  7489. pd->writeDocumentation(*g_outputList);
  7490. Doxygen::insideMainPage=FALSE;
  7491. }
  7492. }
  7493. }
  7494. //----------------------------------------------------------------------------
  7495. // create a (sorted) list & dictionary of example pages
  7496. static void buildExampleList(EntryNav *rootNav)
  7497. {
  7498. if (rootNav->section()==Entry::EXAMPLE_SEC && !rootNav->name().isEmpty())
  7499. {
  7500. rootNav->loadEntry(g_storage);
  7501. Entry *root = rootNav->entry();
  7502. if (Doxygen::exampleSDict->find(root->name))
  7503. {
  7504. warn(root->fileName,root->startLine,
  7505. "Warning: Example %s was already documented. Ignoring "
  7506. "documentation found here.",
  7507. root->name.data()
  7508. );
  7509. }
  7510. else
  7511. {
  7512. PageDef *pd=new PageDef(root->fileName,root->startLine,
  7513. root->name,root->brief+root->doc+root->inbodyDocs,root->args);
  7514. pd->setFileName(convertNameToFile(pd->name()+"-example",TRUE,FALSE));
  7515. pd->addSectionsToDefinition(root->anchors);
  7516. //pi->addSections(root->anchors);
  7517. Doxygen::exampleSDict->inSort(root->name,pd);
  7518. //we don't add example to groups
  7519. //addExampleToGroups(root,pd);
  7520. }
  7521. rootNav->releaseEntry();
  7522. }
  7523. RECURSE_ENTRYTREE(buildExampleList,rootNav);
  7524. }
  7525. //----------------------------------------------------------------------------
  7526. // prints the Entry tree (for debugging)
  7527. void printNavTree(EntryNav *rootNav,int indent)
  7528. {
  7529. QCString indentStr;
  7530. indentStr.fill(' ',indent);
  7531. msg("%s%s (sec=0x%x)\n",
  7532. indentStr.isEmpty()?"":indentStr.data(),
  7533. rootNav->name().isEmpty()?"<empty>":rootNav->name().data(),
  7534. rootNav->section());
  7535. if (rootNav->children())
  7536. {
  7537. EntryNavListIterator eli(*rootNav->children());
  7538. for (;eli.current();++eli) printNavTree(eli.current(),indent+2);
  7539. }
  7540. }
  7541. //----------------------------------------------------------------------------
  7542. // generate the example documentation
  7543. static void generateExampleDocs()
  7544. {
  7545. g_outputList->disable(OutputGenerator::Man);
  7546. PageSDict::Iterator pdi(*Doxygen::exampleSDict);
  7547. PageDef *pd=0;
  7548. for (pdi.toFirst();(pd=pdi.current());++pdi)
  7549. {
  7550. msg("Generating docs for example %s...\n",pd->name().data());
  7551. resetCCodeParserState();
  7552. QCString n=pd->getOutputFileBase();
  7553. startFile(*g_outputList,n,n,pd->name());
  7554. startTitle(*g_outputList,n);
  7555. g_outputList->docify(pd->name());
  7556. endTitle(*g_outputList,n,0);
  7557. g_outputList->parseDoc(pd->docFile(), // file
  7558. pd->docLine(), // startLine
  7559. pd, // context
  7560. 0, // memberDef
  7561. pd->documentation()+"\n\n\\include "+pd->name(), // docs
  7562. TRUE, // index words
  7563. TRUE, // is example
  7564. pd->name()
  7565. );
  7566. endFile(*g_outputList);
  7567. }
  7568. g_outputList->enable(OutputGenerator::Man);
  7569. }
  7570. //----------------------------------------------------------------------------
  7571. // generate module pages
  7572. static void generateGroupDocs()
  7573. {
  7574. GroupSDict::Iterator gli(*Doxygen::groupSDict);
  7575. GroupDef *gd;
  7576. for (gli.toFirst();(gd=gli.current());++gli)
  7577. {
  7578. if (!gd->isReference())
  7579. {
  7580. gd->writeDocumentation(*g_outputList);
  7581. }
  7582. }
  7583. }
  7584. //----------------------------------------------------------------------------
  7585. //static void generatePackageDocs()
  7586. //{
  7587. // writePackageIndex(*g_outputList);
  7588. //
  7589. // if (Doxygen::packageDict.count()>0)
  7590. // {
  7591. // PackageSDict::Iterator pdi(Doxygen::packageDict);
  7592. // PackageDef *pd;
  7593. // for (pdi.toFirst();(pd=pdi.current());++pdi)
  7594. // {
  7595. // pd->writeDocumentation(*g_outputList);
  7596. // }
  7597. // }
  7598. //}
  7599. //----------------------------------------------------------------------------
  7600. // generate module pages
  7601. static void generateNamespaceDocs()
  7602. {
  7603. writeNamespaceIndex(*g_outputList);
  7604. NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
  7605. NamespaceDef *nd;
  7606. // for each namespace...
  7607. for (;(nd=nli.current());++nli)
  7608. {
  7609. if (nd->isLinkableInProject())
  7610. {
  7611. msg("Generating docs for namespace %s\n",nd->name().data());
  7612. nd->writeDocumentation(*g_outputList);
  7613. }
  7614. // for each class in the namespace...
  7615. ClassSDict::Iterator cli(*nd->getClassSDict());
  7616. for ( ; cli.current() ; ++cli )
  7617. {
  7618. ClassDef *cd=cli.current();
  7619. if ( ( cd->isLinkableInProject() &&
  7620. cd->templateMaster()==0
  7621. ) // skip external references, anonymous compounds and
  7622. // template instances and nested classes
  7623. && !cd->isHidden()
  7624. )
  7625. {
  7626. msg("Generating docs for compound %s...\n",cd->name().data());
  7627. cd->writeDocumentation(*g_outputList);
  7628. cd->writeMemberList(*g_outputList);
  7629. }
  7630. cd->writeDocumentationForInnerClasses(*g_outputList);
  7631. }
  7632. }
  7633. }
  7634. #if defined(_WIN32)
  7635. static QCString fixSlashes(QCString &s)
  7636. {
  7637. QCString result;
  7638. uint i;
  7639. for (i=0;i<s.length();i++)
  7640. {
  7641. switch(s.at(i))
  7642. {
  7643. case '/':
  7644. case '\\':
  7645. result+="\\\\";
  7646. break;
  7647. default:
  7648. result+=s.at(i);
  7649. }
  7650. }
  7651. return result;
  7652. }
  7653. #endif
  7654. //----------------------------------------------------------------------------
  7655. // generate files for the search engine
  7656. //static void generateSearchIndex()
  7657. //{
  7658. // if (Config_getBool("SEARCHENGINE") && Config_getBool("GENERATE_HTML"))
  7659. // {
  7660. // // create search index
  7661. // QCString fileName;
  7662. // writeSearchButton(Config_getString("HTML_OUTPUT"));
  7663. //
  7664. //#if !defined(_WIN32)
  7665. // // create cgi script
  7666. // fileName = Config_getString("HTML_OUTPUT")+"/"+Config_getString("CGI_NAME");
  7667. // QFile f(fileName);
  7668. // if (f.open(IO_WriteOnly))
  7669. // {
  7670. // QTextStream t(&f);
  7671. // t << "#!/bin/sh" << endl
  7672. // << "DOXYSEARCH=" << Config_getString("BIN_ABSPATH") << "/doxysearch" << endl
  7673. // << "DOXYPATH=\"" << Config_getString("DOC_ABSPATH") << " ";
  7674. //
  7675. // QStrList &extDocPaths=Config_getList("EXT_DOC_PATHS");
  7676. // char *s= extDocPaths.first();
  7677. // while (s)
  7678. // {
  7679. // t << s << " ";
  7680. // s=extDocPaths.next();
  7681. // }
  7682. //
  7683. // t << "\"" << endl
  7684. // << "if [ -f $DOXYSEARCH ]" << endl
  7685. // << "then" << endl
  7686. // << " $DOXYSEARCH $DOXYPATH" << endl
  7687. // << "else" << endl
  7688. // << " echo \"Content-Type: text/html\"" << endl
  7689. // << " echo \"\"" << endl
  7690. // << " echo \"<h2>Error: $DOXYSEARCH not found. Check cgi script!</h2>\"" << endl
  7691. // << "fi" << endl;
  7692. //
  7693. // f.close();
  7694. // struct stat stat_struct;
  7695. // stat(fileName,&stat_struct);
  7696. // chmod(fileName,stat_struct.st_mode|S_IXUSR|S_IXGRP|S_IXOTH);
  7697. // }
  7698. // else
  7699. // {
  7700. // err("Error: Cannot open file %s for writing\n",fileName.data());
  7701. // }
  7702. //#else /* Windows platform */
  7703. // // create cgi program
  7704. // fileName = Config_getString("CGI_NAME").copy();
  7705. // if (fileName.right(4)==".cgi")
  7706. // fileName=fileName.left(fileName.length()-4);
  7707. // fileName+=".c";
  7708. // fileName.prepend(Config_getString("HTML_OUTPUT")+"/");
  7709. // QFile f(fileName);
  7710. // if (f.open(IO_WriteOnly))
  7711. // {
  7712. // QTextStream t(&f);
  7713. // t << "#include <stdio.h>" << endl;
  7714. // t << "#include <stdlib.h>" << endl;
  7715. // t << "#include <process.h>" << endl;
  7716. // t << endl;
  7717. // t << "const char *DOXYSEARCH = \"" <<
  7718. // fixSlashes(Config_getString("BIN_ABSPATH")) << "\\\\doxysearch.exe\";" << endl;
  7719. // t << "const char *DOXYPATH = \"" <<
  7720. // fixSlashes(Config_getString("DOC_ABSPATH")) << "\";" << endl;
  7721. // t << endl;
  7722. // t << "int main(void)" << endl;
  7723. // t << "{" << endl;
  7724. // t << " char buf[1024];" << endl;
  7725. // t << " sprintf(buf,\"%s %s\",DOXYSEARCH,DOXYPATH);" << endl;
  7726. // t << " if (system(buf))" << endl;
  7727. // t << " {" << endl;
  7728. // t << " printf(\"Content-Type: text/html\\n\\n\");" << endl;
  7729. // t << " printf(\"<h2>Error: failed to execute %s</h2>\\n\",DOXYSEARCH);" << endl;
  7730. // t << " exit(1);" << endl;
  7731. // t << " }" << endl;
  7732. // t << " return 0;" << endl;
  7733. // t << "}" << endl;
  7734. // f.close();
  7735. // }
  7736. // else
  7737. // {
  7738. // err("Error: Cannot open file %s for writing\n",fileName.data());
  7739. // }
  7740. //#endif /* !defined(_WIN32) */
  7741. //
  7742. // // create config file
  7743. // fileName = Config_getString("HTML_OUTPUT")+"/search.cfg";
  7744. // f.setName(fileName);
  7745. // if (f.open(IO_WriteOnly))
  7746. // {
  7747. // QTextStream t(&f);
  7748. // t << Config_getString("DOC_URL") << "/" << endl
  7749. // << Config_getString("CGI_URL") << "/" << Config_getString("CGI_NAME") << endl;
  7750. // f.close();
  7751. // }
  7752. // else
  7753. // {
  7754. // err("Error: Cannot open file %s for writing\n",fileName.data());
  7755. // }
  7756. // //g_outputList->generateExternalIndex();
  7757. // g_outputList->pushGeneratorState();
  7758. // g_outputList->disableAllBut(OutputGenerator::Html);
  7759. // startFile(*g_outputList,"header"+Doxygen::htmlFileExtension,0,"Search Engine",TRUE);
  7760. // g_outputList->endPlainFile();
  7761. // g_outputList->startPlainFile("footer"+Doxygen::htmlFileExtension);
  7762. // endFile(*g_outputList,TRUE);
  7763. // g_outputList->popGeneratorState();
  7764. // }
  7765. //}
  7766. //----------------------------------------------------------------------------
  7767. static bool openOutputFile(const char *outFile,QFile &f)
  7768. {
  7769. bool fileOpened=FALSE;
  7770. bool writeToStdout=(outFile[0]=='-' && outFile[1]=='\0');
  7771. if (writeToStdout) // write to stdout
  7772. {
  7773. fileOpened = f.open(IO_WriteOnly,stdout);
  7774. }
  7775. else // write to file
  7776. {
  7777. QFileInfo fi(outFile);
  7778. if (fi.exists()) // create a backup
  7779. {
  7780. QDir dir=fi.dir();
  7781. QFileInfo backup(fi.fileName()+".bak");
  7782. if (backup.exists()) // remove existing backup
  7783. dir.remove(backup.fileName());
  7784. dir.rename(fi.fileName(),fi.fileName()+".bak");
  7785. }
  7786. f.setName(outFile);
  7787. fileOpened = f.open(IO_WriteOnly|IO_Translate);
  7788. }
  7789. return fileOpened;
  7790. }
  7791. /*! Generate a template version of the configuration file.
  7792. * If the \a shortList parameter is TRUE a configuration file without
  7793. * comments will be generated.
  7794. */
  7795. static void generateConfigFile(const char *configFile,bool shortList,
  7796. bool updateOnly=FALSE)
  7797. {
  7798. QFile f;
  7799. bool fileOpened=openOutputFile(configFile,f);
  7800. bool writeToStdout=(configFile[0]=='-' && configFile[1]=='\0');
  7801. if (fileOpened)
  7802. {
  7803. QTextStream t(&f);
  7804. t.setEncoding(QTextStream::UnicodeUTF8);
  7805. Config::instance()->writeTemplate(t,shortList,updateOnly);
  7806. if (!writeToStdout)
  7807. {
  7808. if (!updateOnly)
  7809. {
  7810. msg("\n\nConfiguration file `%s' created.\n\n",configFile);
  7811. msg("Now edit the configuration file and enter\n\n");
  7812. if (strcmp(configFile,"Doxyfile") || strcmp(configFile,"doxyfile"))
  7813. msg(" doxygen %s\n\n",configFile);
  7814. else
  7815. msg(" doxygen\n\n");
  7816. msg("to generate the documentation for your project\n\n");
  7817. }
  7818. else
  7819. {
  7820. msg("\n\nConfiguration file `%s' updated.\n\n",configFile);
  7821. }
  7822. }
  7823. }
  7824. else
  7825. {
  7826. err("Error: Cannot open file %s for writing\n",configFile);
  7827. exit(1);
  7828. }
  7829. }
  7830. //----------------------------------------------------------------------------
  7831. // read and parse a tag file
  7832. //static bool readLineFromFile(QFile &f,QCString &s)
  7833. //{
  7834. // char c=0;
  7835. // s.resize(0);
  7836. // while (!f.atEnd() && (c=f.getch())!='\n') s+=c;
  7837. // return f.atEnd();
  7838. //}
  7839. //----------------------------------------------------------------------------
  7840. static void readTagFile(Entry *root,const char *tl)
  7841. {
  7842. QCString tagLine = tl;
  7843. QCString fileName;
  7844. QCString destName;
  7845. int eqPos = tagLine.find('=');
  7846. if (eqPos!=-1) // tag command contains a destination
  7847. {
  7848. fileName = tagLine.left(eqPos).stripWhiteSpace();
  7849. destName = tagLine.right(tagLine.length()-eqPos-1).stripWhiteSpace();
  7850. QFileInfo fi(fileName);
  7851. Doxygen::tagDestinationDict.insert(fi.fileName(),new QCString(destName));
  7852. //printf("insert tagDestination %s->%s\n",fi.fileName().data(),destName.data());
  7853. }
  7854. else
  7855. {
  7856. fileName = tagLine;
  7857. }
  7858. QFileInfo fi(fileName);
  7859. if (!fi.exists() || !fi.isFile())
  7860. {
  7861. err("Error: Tag file `%s' does not exist or is not a file. Skipping it...\n",
  7862. fileName.data());
  7863. return;
  7864. }
  7865. if (!destName.isEmpty())
  7866. msg("Reading tag file `%s', location `%s'...\n",fileName.data(),destName.data());
  7867. else
  7868. msg("Reading tag file `%s'...\n",fileName.data());
  7869. parseTagFile(root,fi.absFilePath(),fi.fileName());
  7870. }
  7871. //----------------------------------------------------------------------------
  7872. static void copyStyleSheet()
  7873. {
  7874. QCString &htmlStyleSheet = Config_getString("HTML_STYLESHEET");
  7875. if (!htmlStyleSheet.isEmpty())
  7876. {
  7877. QFile cssf(htmlStyleSheet);
  7878. QFileInfo cssfi(htmlStyleSheet);
  7879. if (cssf.open(IO_ReadOnly))
  7880. {
  7881. QCString destFileName = Config_getString("HTML_OUTPUT")+"/"+cssfi.fileName().data();
  7882. QFile df(destFileName);
  7883. if (df.open(IO_WriteOnly))
  7884. {
  7885. char *buffer = new char[cssf.size()];
  7886. cssf.readBlock(buffer,cssf.size());
  7887. df.writeBlock(buffer,cssf.size());
  7888. df.flush();
  7889. delete[] buffer;
  7890. }
  7891. else
  7892. {
  7893. err("Error: could not write to style sheet %s\n",destFileName.data());
  7894. }
  7895. }
  7896. else
  7897. {
  7898. err("Error: could not open user specified style sheet %s\n",Config_getString("HTML_STYLESHEET").data());
  7899. htmlStyleSheet.resize(0); // revert to the default
  7900. }
  7901. }
  7902. }
  7903. //! parse the list of input files
  7904. static void parseFiles(Entry *root,EntryNav *rootNav)
  7905. {
  7906. #if 0
  7907. void *cd = 0;
  7908. QCString inpEncoding = Config_getString("INPUT_ENCODING");
  7909. bool needsTranscoding = !inpEncoding.isEmpty();
  7910. if (needsTranscoding)
  7911. {
  7912. if (!(cd = portable_iconv_open("UTF-8", inpEncoding)))
  7913. {
  7914. err("Error: unsupported character enconding: '%s'",inpEncoding.data());
  7915. exit(1);
  7916. }
  7917. }
  7918. #endif
  7919. QCString *s=g_inputFiles.first();
  7920. while (s)
  7921. {
  7922. QCString fileName=*s;
  7923. QCString extension;
  7924. int ei = fileName.findRev('.');
  7925. if (ei!=-1) extension=fileName.right(fileName.length()-ei);
  7926. ParserInterface *parser = Doxygen::parserManager->getParser(extension);
  7927. QFileInfo fi(fileName);
  7928. BufStr preBuf(fi.size()+4096);
  7929. if (Config_getBool("ENABLE_PREPROCESSING") &&
  7930. parser->needsPreprocessing(extension))
  7931. {
  7932. BufStr inBuf(fi.size()+4096);
  7933. msg("Preprocessing %s...\n",s->data());
  7934. readInputFile(fileName,inBuf);
  7935. preprocessFile(fileName,inBuf,preBuf);
  7936. }
  7937. else // no preprocessing
  7938. {
  7939. msg("Reading %s...\n",s->data());
  7940. readInputFile(fileName,preBuf);
  7941. }
  7942. BufStr convBuf(preBuf.curPos()+1024);
  7943. // convert multi-line C++ comments to C style comments
  7944. convertCppComments(&preBuf,&convBuf,fileName);
  7945. convBuf.addChar('\0');
  7946. // use language parse to parse the file
  7947. parser->parseInput(fileName,convBuf.data(),root);
  7948. // store the Entry tree in a file and create an index to
  7949. // navigate/load entries
  7950. bool ambig;
  7951. FileDef *fd=findFileDef(Doxygen::inputNameDict,fileName,ambig);
  7952. ASSERT(fd!=0);
  7953. root->createNavigationIndex(rootNav,g_storage,fd);
  7954. s=g_inputFiles.next();
  7955. }
  7956. }
  7957. // resolves a path that may include symlinks, if a recursive symlink is
  7958. // found an empty string is returned.
  7959. static QCString resolveSymlink(QCString path)
  7960. {
  7961. int sepPos=0;
  7962. QFileInfo fi;
  7963. QDict<void> nonSymlinks;
  7964. QDict<void> known;
  7965. QCString result = path;
  7966. QCString oldPrefix = "/";
  7967. do
  7968. {
  7969. #ifdef WIN32
  7970. // UNC path, skip server and share name
  7971. if (sepPos==0 && (result.left(2)=="//" || result.left(2)=="\\\\"))
  7972. sepPos = result.find('/',2);
  7973. if (sepPos!=-1)
  7974. sepPos = result.find('/',sepPos+1);
  7975. #else
  7976. sepPos = result.find('/',sepPos+1);
  7977. #endif
  7978. QCString prefix = sepPos==-1 ? result : result.left(sepPos);
  7979. if (nonSymlinks.find(prefix)==0)
  7980. {
  7981. fi.setFile(prefix);
  7982. if (fi.isSymLink())
  7983. {
  7984. QString target = fi.readLink();
  7985. if (QFileInfo(target).isRelative())
  7986. {
  7987. target = QDir::cleanDirPath(oldPrefix+"/"+target.data());
  7988. }
  7989. if (sepPos!=-1)
  7990. {
  7991. if (fi.isDir() && target.length()>0 && target.at(target.length()-1)!='/')
  7992. {
  7993. target+='/';
  7994. }
  7995. target+=result.mid(sepPos);
  7996. }
  7997. result = QDir::cleanDirPath(target).data();
  7998. sepPos = 0;
  7999. if (known.find(result)) return QCString(); // recursive symlink!
  8000. known.insert(result,(void*)0x8);
  8001. }
  8002. else
  8003. {
  8004. nonSymlinks.insert(prefix,(void*)0x8);
  8005. }
  8006. oldPrefix = prefix;
  8007. }
  8008. }
  8009. while (sepPos!=-1);
  8010. return QDir::cleanDirPath(result).data();
  8011. }
  8012. static QDict<void> g_pathsVisited(1009);
  8013. //----------------------------------------------------------------------------
  8014. // Read all files matching at least one pattern in `patList' in the
  8015. // directory represented by `fi'.
  8016. // The directory is read iff the recusiveFlag is set.
  8017. // The contents of all files is append to the input string
  8018. int readDir(QFileInfo *fi,
  8019. FileNameList *fnList,
  8020. FileNameDict *fnDict,
  8021. StringDict *exclDict,
  8022. QStrList *patList,
  8023. QStrList *exclPatList,
  8024. StringList *resultList,
  8025. StringDict *resultDict,
  8026. bool errorIfNotExist,
  8027. bool recursive,
  8028. QDict<void> *killDict
  8029. )
  8030. {
  8031. QString dirName = fi->absFilePath();
  8032. if (fi->isSymLink())
  8033. {
  8034. dirName = resolveSymlink(dirName.data());
  8035. if (dirName.isEmpty()) return 0; // recusive symlink
  8036. if (g_pathsVisited.find(dirName)) return 0; // already visited path
  8037. g_pathsVisited.insert(dirName,(void*)0x8);
  8038. }
  8039. QDir dir(dirName);
  8040. dir.setFilter( QDir::Files | QDir::Dirs | QDir::Hidden );
  8041. int totalSize=0;
  8042. msg("Searching for files in directory %s\n", fi->absFilePath().data());
  8043. //printf("killDict=%p count=%d\n",killDict,killDict->count());
  8044. const QFileInfoList *list = dir.entryInfoList();
  8045. if (list)
  8046. {
  8047. QFileInfoListIterator it( *list );
  8048. QFileInfo *cfi;
  8049. while ((cfi=it.current()))
  8050. {
  8051. if (exclDict==0 || exclDict->find(cfi->absFilePath())==0)
  8052. { // file should not be excluded
  8053. //printf("killDict->find(%s)\n",cfi->absFilePath().data());
  8054. if (!cfi->exists() || !cfi->isReadable())
  8055. {
  8056. if (errorIfNotExist)
  8057. {
  8058. err("Warning: source %s is not a readable file or directory... skipping.\n",cfi->absFilePath().data());
  8059. }
  8060. }
  8061. else if (cfi->isFile() &&
  8062. (!Config_getBool("EXCLUDE_SYMLINKS") || !cfi->isSymLink()) &&
  8063. (patList==0 || patternMatch(*cfi,patList)) &&
  8064. !patternMatch(*cfi,exclPatList) &&
  8065. (killDict==0 || killDict->find(cfi->absFilePath())==0)
  8066. )
  8067. {
  8068. totalSize+=cfi->size()+cfi->absFilePath().length()+4;
  8069. QCString name=convertToQCString(cfi->fileName());
  8070. //printf("New file %s\n",name.data());
  8071. if (fnDict)
  8072. {
  8073. FileDef *fd=new FileDef(cfi->dirPath()+"/",name);
  8074. FileName *fn=0;
  8075. if (!name.isEmpty() && (fn=(*fnDict)[name]))
  8076. {
  8077. fn->append(fd);
  8078. }
  8079. else
  8080. {
  8081. fn = new FileName(cfi->absFilePath(),name);
  8082. fn->append(fd);
  8083. if (fnList) fnList->inSort(fn);
  8084. fnDict->insert(name,fn);
  8085. }
  8086. }
  8087. QCString *rs=0;
  8088. if (resultList || resultDict)
  8089. {
  8090. rs=new QCString(cfi->absFilePath());
  8091. }
  8092. if (resultList) resultList->append(rs);
  8093. if (resultDict) resultDict->insert(cfi->absFilePath(),rs);
  8094. if (killDict) killDict->insert(cfi->absFilePath(),(void *)0x8);
  8095. }
  8096. else if (recursive &&
  8097. (!Config_getBool("EXCLUDE_SYMLINKS") || !cfi->isSymLink()) &&
  8098. cfi->isDir() && cfi->fileName()!="." &&
  8099. !patternMatch(*cfi,exclPatList) &&
  8100. cfi->fileName()!="..")
  8101. {
  8102. cfi->setFile(cfi->absFilePath());
  8103. totalSize+=readDir(cfi,fnList,fnDict,exclDict,
  8104. patList,exclPatList,resultList,resultDict,errorIfNotExist,
  8105. recursive,killDict);
  8106. }
  8107. }
  8108. ++it;
  8109. }
  8110. }
  8111. return totalSize;
  8112. }
  8113. //----------------------------------------------------------------------------
  8114. // read a file or all files in a directory and append their contents to the
  8115. // input string. The names of the files are appended to the `fiList' list.
  8116. int readFileOrDirectory(const char *s,
  8117. FileNameList *fnList,
  8118. FileNameDict *fnDict,
  8119. StringDict *exclDict,
  8120. QStrList *patList,
  8121. QStrList *exclPatList,
  8122. StringList *resultList,
  8123. StringDict *resultDict,
  8124. bool recursive,
  8125. bool errorIfNotExist,
  8126. QDict<void> *killDict
  8127. )
  8128. {
  8129. //printf("killDict=%p count=%d\n",killDict,killDict->count());
  8130. // strip trailing slashes
  8131. if (s==0) return 0;
  8132. QCString fs = s;
  8133. char lc = fs.at(fs.length()-1);
  8134. if (lc=='/' || lc=='\\') fs = fs.left(fs.length()-1);
  8135. QFileInfo fi(fs);
  8136. //printf("readFileOrDirectory(%s)\n",s);
  8137. int totalSize=0;
  8138. {
  8139. if (exclDict==0 || exclDict->find(fi.absFilePath())==0)
  8140. {
  8141. if (!fi.exists() || !fi.isReadable())
  8142. {
  8143. if (errorIfNotExist)
  8144. {
  8145. err("Warning: source %s is not a readable file or directory... skipping.\n",s);
  8146. }
  8147. }
  8148. else if (!Config_getBool("EXCLUDE_SYMLINKS") || !fi.isSymLink())
  8149. {
  8150. if (fi.isFile())
  8151. {
  8152. //printf("killDict->find(%s)\n",fi.absFilePath().data());
  8153. if (killDict==0 || killDict->find(fi.absFilePath())==0)
  8154. {
  8155. totalSize+=fi.size()+fi.absFilePath().length()+4; //readFile(&fi,fiList,input);
  8156. //fiList->inSort(new FileInfo(fi));
  8157. QCString name=convertToQCString(fi.fileName());
  8158. //printf("New file %s\n",name.data());
  8159. if (fnDict)
  8160. {
  8161. FileDef *fd=new FileDef(fi.dirPath(TRUE)+"/",name);
  8162. FileName *fn=0;
  8163. if (!name.isEmpty() && (fn=(*fnDict)[name]))
  8164. {
  8165. fn->append(fd);
  8166. }
  8167. else
  8168. {
  8169. fn = new FileName(fi.absFilePath(),name);
  8170. fn->append(fd);
  8171. if (fnList) fnList->inSort(fn);
  8172. fnDict->insert(name,fn);
  8173. }
  8174. }
  8175. QCString *rs=0;
  8176. if (resultList || resultDict)
  8177. {
  8178. rs=new QCString(fi.absFilePath());
  8179. if (resultList) resultList->append(rs);
  8180. if (resultDict) resultDict->insert(fi.absFilePath(),rs);
  8181. }
  8182. if (killDict) killDict->insert(fi.absFilePath(),(void *)0x8);
  8183. }
  8184. }
  8185. else if (fi.isDir()) // readable dir
  8186. {
  8187. totalSize+=readDir(&fi,fnList,fnDict,exclDict,patList,
  8188. exclPatList,resultList,resultDict,errorIfNotExist,
  8189. recursive,killDict);
  8190. }
  8191. }
  8192. }
  8193. }
  8194. return totalSize;
  8195. }
  8196. //----------------------------------------------------------------------------
  8197. void readFormulaRepository()
  8198. {
  8199. QFile f(Config_getString("HTML_OUTPUT")+"/formula.repository");
  8200. if (f.open(IO_ReadOnly)) // open repository
  8201. {
  8202. msg("Reading formula repository...\n");
  8203. QTextStream t(&f);
  8204. QCString line;
  8205. while (!t.eof())
  8206. {
  8207. line=t.readLine();
  8208. int se=line.find(':'); // find name and text separator.
  8209. if (se==-1)
  8210. {
  8211. err("Warning: formula.repository is corrupted!\n");
  8212. break;
  8213. }
  8214. else
  8215. {
  8216. QCString formName = line.left(se);
  8217. QCString formText = line.right(line.length()-se-1);
  8218. Formula *f=new Formula(formText);
  8219. Doxygen::formulaList.append(f);
  8220. Doxygen::formulaDict.insert(formText,f);
  8221. Doxygen::formulaNameDict.insert(formName,f);
  8222. }
  8223. }
  8224. }
  8225. }
  8226. //----------------------------------------------------------------------------
  8227. static void expandAliases()
  8228. {
  8229. QDictIterator<QCString> adi(Doxygen::aliasDict);
  8230. QCString *s;
  8231. for (adi.toFirst();(s=adi.current());++adi)
  8232. {
  8233. *s = expandAlias(adi.currentKey(),*s);
  8234. }
  8235. }
  8236. //----------------------------------------------------------------------------
  8237. static void escapeAliases()
  8238. {
  8239. QDictIterator<QCString> adi(Doxygen::aliasDict);
  8240. QCString *s;
  8241. for (adi.toFirst();(s=adi.current());++adi)
  8242. {
  8243. QCString value=*s,newValue;
  8244. int in,p=0;
  8245. // for each \n in the alias command value
  8246. while ((in=value.find("\\n",p))!=-1)
  8247. {
  8248. newValue+=value.mid(p,in-p);
  8249. // expand \n's except if \n is part of a built-in command.
  8250. if (value.mid(in,5)!="\\note" &&
  8251. value.mid(in,5)!="\\name" &&
  8252. value.mid(in,10)!="\\namespace" &&
  8253. value.mid(in,14)!="\\nosubgrouping"
  8254. )
  8255. {
  8256. newValue+="\\_linebr ";
  8257. }
  8258. else
  8259. {
  8260. newValue+="\\n";
  8261. }
  8262. p=in+2;
  8263. }
  8264. newValue+=value.mid(p,value.length()-p);
  8265. *s=newValue;
  8266. //printf("Alias %s has value %s\n",adi.currentKey().data(),s->data());
  8267. }
  8268. }
  8269. //----------------------------------------------------------------------------
  8270. void readAliases()
  8271. {
  8272. // add aliases to a dictionary
  8273. Doxygen::aliasDict.setAutoDelete(TRUE);
  8274. QStrList &aliasList = Config_getList("ALIASES");
  8275. const char *s=aliasList.first();
  8276. while (s)
  8277. {
  8278. if (Doxygen::aliasDict[s]==0)
  8279. {
  8280. QCString alias=s;
  8281. int i=alias.find('=');
  8282. if (i>0)
  8283. {
  8284. QCString name=alias.left(i).stripWhiteSpace();
  8285. QCString value=alias.right(alias.length()-i-1);
  8286. //printf("Alias: found name=`%s' value=`%s'\n",name.data(),value.data());
  8287. if (!name.isEmpty())
  8288. {
  8289. QCString *dn=Doxygen::aliasDict[name];
  8290. if (dn==0) // insert new alias
  8291. {
  8292. Doxygen::aliasDict.insert(name,new QCString(value));
  8293. }
  8294. else // overwrite previous alias
  8295. {
  8296. *dn=value;
  8297. }
  8298. }
  8299. }
  8300. }
  8301. s=aliasList.next();
  8302. }
  8303. expandAliases();
  8304. escapeAliases();
  8305. }
  8306. //----------------------------------------------------------------------------
  8307. static void dumpSymbol(QTextStream &t,Definition *d)
  8308. {
  8309. QCString anchor;
  8310. if (d->definitionType()==Definition::TypeMember)
  8311. {
  8312. MemberDef *md = (MemberDef *)d;
  8313. anchor=":"+md->anchor();
  8314. }
  8315. QCString scope;
  8316. if (d->getOuterScope() && d->getOuterScope()!=Doxygen::globalScope)
  8317. {
  8318. scope = d->getOuterScope()->getOutputFileBase()+Doxygen::htmlFileExtension;
  8319. }
  8320. t << "REPLACE INTO symbols (symbol_id,scope_id,name,file,line) VALUES('"
  8321. << d->getOutputFileBase()+Doxygen::htmlFileExtension+anchor << "','"
  8322. << scope << "','"
  8323. << d->name() << "','"
  8324. << d->getDefFileName() << "','"
  8325. << d->getDefLine()
  8326. << "');" << endl;
  8327. }
  8328. static void dumpSymbolMap()
  8329. {
  8330. QFile f("symbols.sql");
  8331. if (f.open(IO_WriteOnly))
  8332. {
  8333. QTextStream t(&f);
  8334. QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap);
  8335. DefinitionIntf *intf;
  8336. for (;(intf=di.current());++di)
  8337. {
  8338. if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols
  8339. {
  8340. DefinitionListIterator dli(*(DefinitionList*)intf);
  8341. Definition *d;
  8342. // for each symbol
  8343. for (dli.toFirst();(d=dli.current());++dli)
  8344. {
  8345. dumpSymbol(t,d);
  8346. }
  8347. }
  8348. else // single symbol
  8349. {
  8350. Definition *d = (Definition *)intf;
  8351. if (d!=Doxygen::globalScope) dumpSymbol(t,d);
  8352. }
  8353. }
  8354. }
  8355. }
  8356. //----------------------------------------------------------------------------
  8357. void dumpConfigAsXML()
  8358. {
  8359. QFile f("config.xml");
  8360. if (f.open(IO_WriteOnly))
  8361. {
  8362. QTextStream t(&f);
  8363. Config::instance()->writeXML(t);
  8364. }
  8365. }
  8366. //----------------------------------------------------------------------------
  8367. // print the usage of doxygen
  8368. static void usage(const char *name)
  8369. {
  8370. msg("Doxygen version %s\nCopyright Dimitri van Heesch 1997-2010\n\n",versionString);
  8371. msg("You can use doxygen in a number of ways:\n\n");
  8372. msg("1) Use doxygen to generate a template configuration file:\n");
  8373. msg(" %s [-s] -g [configName]\n\n",name);
  8374. msg(" If - is used for configName doxygen will write to standard output.\n\n");
  8375. msg("2) Use doxygen to update an old configuration file:\n");
  8376. msg(" %s [-s] -u [configName]\n\n",name);
  8377. msg("3) Use doxygen to generate documentation using an existing ");
  8378. msg("configuration file:\n");
  8379. msg(" %s [configName]\n\n",name);
  8380. msg(" If - is used for configName doxygen will read from standard input.\n\n");
  8381. msg("4) Use doxygen to generate a template file controlling the layout of the\n");
  8382. msg(" generated documentation:\n");
  8383. msg(" %s -l layoutFileName.xml\n\n",name);
  8384. msg("5) Use doxygen to generate a template style sheet file for RTF, HTML or Latex.\n");
  8385. msg(" RTF: %s -w rtf styleSheetFile\n",name);
  8386. msg(" HTML: %s -w html headerFile footerFile styleSheetFile [configFile]\n",name);
  8387. msg(" LaTeX: %s -w latex headerFile styleSheetFile [configFile]\n\n",name);
  8388. msg("6) Use doxygen to generate an rtf extensions file\n");
  8389. msg(" RTF: %s -e rtf extensionsFile\n\n",name);
  8390. msg("If -s is specified the comments in the config file will be omitted.\n");
  8391. msg("If configName is omitted `Doxyfile' will be used as a default.\n\n");
  8392. exit(1);
  8393. }
  8394. //----------------------------------------------------------------------------
  8395. // read the argument of option `c' from the comment argument list and
  8396. // update the option index `optind'.
  8397. static const char *getArg(int argc,char **argv,int &optind)
  8398. {
  8399. char *s=0;
  8400. if (strlen(&argv[optind][2])>0)
  8401. s=&argv[optind][2];
  8402. else if (optind+1<argc && argv[optind+1][0]!='-')
  8403. s=argv[++optind];
  8404. return s;
  8405. }
  8406. //----------------------------------------------------------------------------
  8407. extern void commentScanTest();
  8408. void initDoxygen()
  8409. {
  8410. setlocale(LC_ALL,"");
  8411. setlocale(LC_CTYPE,"C"); // to get isspace(0xA0)==0, needed for UTF-8
  8412. setlocale(LC_NUMERIC,"C");
  8413. //Doxygen::symbolMap->setAutoDelete(TRUE);
  8414. Doxygen::runningTime.start();
  8415. initPreprocessor();
  8416. Doxygen::parserManager = new ParserManager;
  8417. Doxygen::parserManager->registerParser("c", new CLanguageScanner, TRUE);
  8418. Doxygen::parserManager->registerParser("python", new PythonLanguageScanner);
  8419. Doxygen::parserManager->registerParser("fortran", new FortranLanguageScanner);
  8420. Doxygen::parserManager->registerParser("vhdl", new VHDLLanguageScanner);
  8421. Doxygen::parserManager->registerParser("dbusxml", new DBusXMLScanner);
  8422. // register any additional parsers here...
  8423. initDefaultExtensionMapping();
  8424. initClassMemberIndices();
  8425. initNamespaceMemberIndices();
  8426. initFileMemberIndices();
  8427. Doxygen::symbolMap = new QDict<DefinitionIntf>(1000);
  8428. Doxygen::inputNameList = new FileNameList;
  8429. Doxygen::inputNameList->setAutoDelete(TRUE);
  8430. Doxygen::memberNameSDict = new MemberNameSDict(10000);
  8431. Doxygen::memberNameSDict->setAutoDelete(TRUE);
  8432. Doxygen::functionNameSDict = new MemberNameSDict(10000);
  8433. Doxygen::functionNameSDict->setAutoDelete(TRUE);
  8434. Doxygen::groupSDict = new GroupSDict(17);
  8435. Doxygen::groupSDict->setAutoDelete(TRUE);
  8436. Doxygen::globalScope = new NamespaceDef("<globalScope>",1,"<globalScope>");
  8437. Doxygen::namespaceSDict = new NamespaceSDict(20);
  8438. Doxygen::namespaceSDict->setAutoDelete(TRUE);
  8439. Doxygen::classSDict = new ClassSDict(1009);
  8440. Doxygen::classSDict->setAutoDelete(TRUE);
  8441. Doxygen::hiddenClasses = new ClassSDict(257);
  8442. Doxygen::hiddenClasses->setAutoDelete(TRUE);
  8443. Doxygen::directories = new DirSDict(17);
  8444. Doxygen::directories->setAutoDelete(TRUE);
  8445. Doxygen::pageSDict = new PageSDict(1009); // all doc pages
  8446. Doxygen::pageSDict->setAutoDelete(TRUE);
  8447. Doxygen::exampleSDict = new PageSDict(1009); // all examples
  8448. Doxygen::exampleSDict->setAutoDelete(TRUE);
  8449. Doxygen::inputNameDict = new FileNameDict(10007);
  8450. Doxygen::includeNameDict = new FileNameDict(10007);
  8451. Doxygen::exampleNameDict = new FileNameDict(1009);
  8452. Doxygen::exampleNameDict->setAutoDelete(TRUE);
  8453. Doxygen::imageNameDict = new FileNameDict(257);
  8454. Doxygen::dotFileNameDict = new FileNameDict(257);
  8455. Doxygen::sectionDict.setAutoDelete(TRUE);
  8456. Doxygen::memGrpInfoDict.setAutoDelete(TRUE);
  8457. Doxygen::tagDestinationDict.setAutoDelete(TRUE);
  8458. Doxygen::lookupCache.setAutoDelete(TRUE);
  8459. Doxygen::dirRelations.setAutoDelete(TRUE);
  8460. }
  8461. void cleanUpDoxygen()
  8462. {
  8463. delete Doxygen::inputNameDict;
  8464. delete Doxygen::includeNameDict;
  8465. delete Doxygen::exampleNameDict;
  8466. delete Doxygen::imageNameDict;
  8467. delete Doxygen::dotFileNameDict;
  8468. delete Doxygen::mainPage;
  8469. delete Doxygen::pageSDict;
  8470. delete Doxygen::exampleSDict;
  8471. delete Doxygen::globalScope;
  8472. delete Doxygen::xrefLists;
  8473. delete Doxygen::parserManager;
  8474. cleanUpPreprocessor();
  8475. delete theTranslator;
  8476. delete g_outputList;
  8477. Mappers::freeMappers();
  8478. codeFreeScanner();
  8479. if (Doxygen::symbolMap)
  8480. {
  8481. // iterate through Doxygen::symbolMap and delete all
  8482. // DefinitionList objects, since they have no owner
  8483. QDictIterator<DefinitionIntf> dli(*Doxygen::symbolMap);
  8484. DefinitionIntf *di;
  8485. for (dli.toFirst();(di=dli.current());)
  8486. {
  8487. if (di->definitionType()==DefinitionIntf::TypeSymbolList)
  8488. {
  8489. DefinitionIntf *tmp = Doxygen::symbolMap->take(dli.currentKey());
  8490. delete (DefinitionList *)tmp;
  8491. }
  8492. else
  8493. {
  8494. ++dli;
  8495. }
  8496. }
  8497. }
  8498. delete Doxygen::inputNameList;
  8499. delete Doxygen::memberNameSDict;
  8500. delete Doxygen::functionNameSDict;
  8501. delete Doxygen::groupSDict;
  8502. delete Doxygen::classSDict;
  8503. delete Doxygen::hiddenClasses;
  8504. delete Doxygen::namespaceSDict;
  8505. delete Doxygen::directories;
  8506. //delete Doxygen::symbolMap; <- we cannot do this unless all static lists
  8507. // (such as Doxygen::namespaceSDict)
  8508. // with objects based on Definition are made
  8509. // dynamic first
  8510. }
  8511. void readConfiguration(int argc, char **argv)
  8512. {
  8513. /**************************************************************************
  8514. * Handle arguments *
  8515. **************************************************************************/
  8516. int optind=1;
  8517. const char *configName=0;
  8518. const char *layoutName=0;
  8519. const char *debugLabel;
  8520. const char *formatName;
  8521. bool genConfig=FALSE;
  8522. bool shortList=FALSE;
  8523. bool updateConfig=FALSE;
  8524. bool genLayout=FALSE;
  8525. while (optind<argc && argv[optind][0]=='-' &&
  8526. (isalpha(argv[optind][1]) || argv[optind][1]=='?' ||
  8527. argv[optind][1]=='-')
  8528. )
  8529. {
  8530. switch(argv[optind][1])
  8531. {
  8532. case 'g':
  8533. genConfig=TRUE;
  8534. configName=getArg(argc,argv,optind);
  8535. if (strcmp(argv[optind+1],"-")==0)
  8536. { configName="-"; optind++; }
  8537. if (!configName)
  8538. { configName="Doxyfile"; }
  8539. break;
  8540. case 'l':
  8541. genLayout=TRUE;
  8542. layoutName=getArg(argc,argv,optind);
  8543. if (!layoutName)
  8544. { layoutName="DoxygenLayout.xml"; }
  8545. break;
  8546. case 'd':
  8547. debugLabel=getArg(argc,argv,optind);
  8548. Debug::setFlag(debugLabel);
  8549. break;
  8550. case 's':
  8551. shortList=TRUE;
  8552. break;
  8553. case 'u':
  8554. updateConfig=TRUE;
  8555. break;
  8556. case 'e':
  8557. formatName=getArg(argc,argv,optind);
  8558. if (!formatName)
  8559. {
  8560. err("Error:option -e is missing format specifier rtf.\n");
  8561. cleanUpDoxygen();
  8562. exit(1);
  8563. }
  8564. if (stricmp(formatName,"rtf")==0)
  8565. {
  8566. if (optind+1>=argc)
  8567. {
  8568. err("Error: option \"-e rtf\" is missing an extensions file name\n");
  8569. cleanUpDoxygen();
  8570. exit(1);
  8571. }
  8572. QFile f;
  8573. if (openOutputFile(argv[optind+1],f))
  8574. {
  8575. RTFGenerator::writeExtensionsFile(f);
  8576. }
  8577. cleanUpDoxygen();
  8578. exit(1);
  8579. }
  8580. err("Error: option \"-e\" has invalid format specifier.\n");
  8581. cleanUpDoxygen();
  8582. exit(1);
  8583. break;
  8584. case 'w':
  8585. formatName=getArg(argc,argv,optind);
  8586. if (!formatName)
  8587. {
  8588. err("Error: option -w is missing format specifier rtf, html or latex\n");
  8589. cleanUpDoxygen();
  8590. exit(1);
  8591. }
  8592. if (stricmp(formatName,"rtf")==0)
  8593. {
  8594. if (optind+1>=argc)
  8595. {
  8596. err("Error: option \"-w rtf\" is missing a style sheet file name\n");
  8597. cleanUpDoxygen();
  8598. exit(1);
  8599. }
  8600. QFile f;
  8601. if (openOutputFile(argv[optind+1],f))
  8602. {
  8603. RTFGenerator::writeStyleSheetFile(f);
  8604. }
  8605. cleanUpDoxygen();
  8606. exit(1);
  8607. }
  8608. else if (stricmp(formatName,"html")==0)
  8609. {
  8610. if (optind+4<argc)
  8611. {
  8612. if (!Config::instance()->parse(argv[optind+4]))
  8613. {
  8614. err("Error opening or reading configuration file %s!\n",argv[optind+4]);
  8615. cleanUpDoxygen();
  8616. exit(1);
  8617. }
  8618. Config::instance()->substituteEnvironmentVars();
  8619. Config::instance()->convertStrToVal();
  8620. Config::instance()->check();
  8621. }
  8622. else
  8623. {
  8624. Config::instance()->init();
  8625. }
  8626. if (optind+3>=argc)
  8627. {
  8628. err("Error: option \"-w html\" does not have enough arguments\n");
  8629. cleanUpDoxygen();
  8630. exit(1);
  8631. }
  8632. QCString outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
  8633. if (!setTranslator(outputLanguage))
  8634. {
  8635. err("Warning: Output language %s not supported! Using English instead.\n", outputLanguage.data());
  8636. }
  8637. QFile f;
  8638. if (openOutputFile(argv[optind+1],f))
  8639. {
  8640. HtmlGenerator::writeHeaderFile(f);
  8641. }
  8642. f.close();
  8643. if (openOutputFile(argv[optind+2],f))
  8644. {
  8645. HtmlGenerator::writeFooterFile(f);
  8646. }
  8647. f.close();
  8648. if (openOutputFile(argv[optind+3],f))
  8649. {
  8650. HtmlGenerator::writeStyleSheetFile(f);
  8651. }
  8652. cleanUpDoxygen();
  8653. exit(0);
  8654. }
  8655. else if (stricmp(formatName,"latex")==0)
  8656. {
  8657. if (optind+3<argc) // use config file to get settings
  8658. {
  8659. if (!Config::instance()->parse(argv[optind+3]))
  8660. {
  8661. err("Error opening or reading configuration file %s!\n",argv[optind+3]);
  8662. exit(1);
  8663. }
  8664. Config::instance()->substituteEnvironmentVars();
  8665. Config::instance()->convertStrToVal();
  8666. Config::instance()->check();
  8667. }
  8668. else // use default config
  8669. {
  8670. Config::instance()->init();
  8671. }
  8672. if (optind+2>=argc)
  8673. {
  8674. err("Error: option \"-w latex\" does not have enough arguments\n");
  8675. cleanUpDoxygen();
  8676. exit(1);
  8677. }
  8678. QCString outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
  8679. if (!setTranslator(outputLanguage))
  8680. {
  8681. err("Warning: Output language %s not supported! Using English instead.\n", outputLanguage.data());
  8682. }
  8683. QFile f;
  8684. if (openOutputFile(argv[optind+1],f))
  8685. {
  8686. LatexGenerator::writeHeaderFile(f);
  8687. }
  8688. f.close();
  8689. if (openOutputFile(argv[optind+2],f))
  8690. {
  8691. LatexGenerator::writeStyleSheetFile(f);
  8692. }
  8693. cleanUpDoxygen();
  8694. exit(0);
  8695. }
  8696. else
  8697. {
  8698. err("Error: Illegal format specifier %s: should be one of rtf, html, or latex\n",formatName);
  8699. cleanUpDoxygen();
  8700. exit(1);
  8701. }
  8702. break;
  8703. case 'm':
  8704. g_dumpSymbolMap = TRUE;
  8705. break;
  8706. case 'x':
  8707. g_dumpConfigAsXML = TRUE;
  8708. break;
  8709. case '-':
  8710. if (strcmp(&argv[optind][2],"help")==0)
  8711. {
  8712. usage(argv[0]);
  8713. }
  8714. else if (strcmp(&argv[optind][2],"version")==0)
  8715. {
  8716. msg("%s\n",versionString);
  8717. cleanUpDoxygen();
  8718. exit(0);
  8719. }
  8720. break;
  8721. case 'b':
  8722. setvbuf(stdout,NULL,_IONBF,0);
  8723. Doxygen::outputToWizard=TRUE;
  8724. break;
  8725. case 'h':
  8726. case '?':
  8727. usage(argv[0]);
  8728. break;
  8729. default:
  8730. err("Unknown option -%c\n",argv[optind][1]);
  8731. usage(argv[0]);
  8732. }
  8733. optind++;
  8734. }
  8735. /**************************************************************************
  8736. * Parse or generate the config file *
  8737. **************************************************************************/
  8738. Config::instance()->init();
  8739. if (genConfig)
  8740. {
  8741. if (g_dumpConfigAsXML)
  8742. {
  8743. checkConfiguration();
  8744. generateConfigFile(configName,shortList);
  8745. dumpConfigAsXML();
  8746. exit(0);
  8747. }
  8748. else
  8749. {
  8750. generateConfigFile(configName,shortList);
  8751. }
  8752. cleanUpDoxygen();
  8753. exit(0);
  8754. }
  8755. if (genLayout)
  8756. {
  8757. writeDefaultLayoutFile(layoutName);
  8758. cleanUpDoxygen();
  8759. exit(0);
  8760. }
  8761. QFileInfo configFileInfo1("Doxyfile"),configFileInfo2("doxyfile");
  8762. if (optind>=argc)
  8763. {
  8764. if (configFileInfo1.exists())
  8765. {
  8766. configName="Doxyfile";
  8767. }
  8768. else if (configFileInfo2.exists())
  8769. {
  8770. configName="doxyfile";
  8771. }
  8772. else
  8773. {
  8774. err("Doxyfile not found and no input file specified!\n");
  8775. usage(argv[0]);
  8776. }
  8777. }
  8778. else
  8779. {
  8780. QFileInfo fi(argv[optind]);
  8781. if (fi.exists() || strcmp(argv[optind],"-")==0)
  8782. {
  8783. configName=argv[optind];
  8784. }
  8785. else
  8786. {
  8787. err("Error: configuration file %s not found!\n",argv[optind]);
  8788. usage(argv[0]);
  8789. }
  8790. }
  8791. if (!Config::instance()->parse(configName))
  8792. {
  8793. err("Error: could not open or read configuration file %s!\n",configName);
  8794. cleanUpDoxygen();
  8795. exit(1);
  8796. }
  8797. if (updateConfig)
  8798. {
  8799. generateConfigFile(configName,shortList,TRUE);
  8800. cleanUpDoxygen();
  8801. exit(0);
  8802. }
  8803. /* Perlmod wants to know the path to the config file.*/
  8804. QFileInfo configFileInfo(configName);
  8805. setPerlModDoxyfile(configFileInfo.absFilePath());
  8806. }
  8807. /** check and resolve config options */
  8808. void checkConfiguration()
  8809. {
  8810. Config::instance()->substituteEnvironmentVars();
  8811. Config::instance()->convertStrToVal();
  8812. Config::instance()->check();
  8813. initWarningFormat();
  8814. }
  8815. /** adjust globals that depend on configuration settings. */
  8816. void adjustConfiguration()
  8817. {
  8818. QCString outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
  8819. if (!setTranslator(outputLanguage))
  8820. {
  8821. err("Warning: Output language %s not supported! Using English instead.\n",
  8822. outputLanguage.data());
  8823. }
  8824. QStrList &includePath = Config_getList("INCLUDE_PATH");
  8825. char *s=includePath.first();
  8826. while (s)
  8827. {
  8828. QFileInfo fi(s);
  8829. addSearchDir(fi.absFilePath());
  8830. s=includePath.next();
  8831. }
  8832. /* Set the global html file extension. */
  8833. Doxygen::htmlFileExtension = Config_getString("HTML_FILE_EXTENSION");
  8834. Doxygen::xrefLists->setAutoDelete(TRUE);
  8835. Doxygen::parseSourcesNeeded = Config_getBool("CALL_GRAPH") ||
  8836. Config_getBool("CALLER_GRAPH") ||
  8837. Config_getBool("REFERENCES_RELATION") ||
  8838. Config_getBool("REFERENCED_BY_RELATION");
  8839. /**************************************************************************
  8840. * Add custom extension mappings
  8841. **************************************************************************/
  8842. QStrList &extMaps = Config_getList("EXTENSION_MAPPING");
  8843. char *mapping = extMaps.first();
  8844. while (mapping)
  8845. {
  8846. QCString mapStr = mapping;
  8847. int i;
  8848. if ((i=mapStr.find('='))!=-1)
  8849. {
  8850. QCString ext=mapStr.left(i).stripWhiteSpace().lower();
  8851. QCString language=mapStr.mid(i+1).stripWhiteSpace().lower();
  8852. if (!updateLanguageMapping(ext,language))
  8853. {
  8854. err("Failed to map file extension '%s' to unsupported language '%s'.\n"
  8855. "Check the EXTENSION_MAPPING setting in the config file.\n",
  8856. ext.data(),language.data());
  8857. }
  8858. else
  8859. {
  8860. msg("Adding custom extension mapping: .%s will be treated as language %s\n",
  8861. ext.data(),language.data());
  8862. }
  8863. }
  8864. mapping = extMaps.next();
  8865. }
  8866. // add predefined macro name to a dictionary
  8867. QStrList &expandAsDefinedList =Config_getList("EXPAND_AS_DEFINED");
  8868. s=expandAsDefinedList.first();
  8869. while (s)
  8870. {
  8871. if (Doxygen::expandAsDefinedDict[s]==0)
  8872. {
  8873. Doxygen::expandAsDefinedDict.insert(s,(void *)666);
  8874. }
  8875. s=expandAsDefinedList.next();
  8876. }
  8877. // read aliases and store them in a dictionary
  8878. readAliases();
  8879. // store number of spaces in a tab into Doxygen::spaces
  8880. int &tabSize = Config_getInt("TAB_SIZE");
  8881. Doxygen::spaces.resize(tabSize+1);
  8882. int sp;for (sp=0;sp<tabSize;sp++) Doxygen::spaces.at(sp)=' ';
  8883. Doxygen::spaces.at(tabSize)='\0';
  8884. }
  8885. #ifdef HAS_SIGNALS
  8886. static void stopDoxygen(int)
  8887. {
  8888. QDir thisDir;
  8889. msg("Cleaning up...\n");
  8890. if (!Doxygen::entryDBFileName.isEmpty())
  8891. {
  8892. thisDir.remove(Doxygen::entryDBFileName);
  8893. }
  8894. if (!Doxygen::objDBFileName.isEmpty())
  8895. {
  8896. thisDir.remove(Doxygen::objDBFileName);
  8897. }
  8898. exit(1);
  8899. }
  8900. #endif
  8901. static void exitDoxygen()
  8902. {
  8903. if (!g_successfulRun) // premature exit
  8904. {
  8905. QDir thisDir;
  8906. msg("Exiting...\n");
  8907. if (!Doxygen::entryDBFileName.isEmpty())
  8908. {
  8909. thisDir.remove(Doxygen::entryDBFileName);
  8910. }
  8911. if (!Doxygen::objDBFileName.isEmpty())
  8912. {
  8913. thisDir.remove(Doxygen::objDBFileName);
  8914. }
  8915. }
  8916. }
  8917. static QCString createOutputDirectory(const QCString &baseDirName,
  8918. const char *formatDirOption,
  8919. const char *defaultDirName)
  8920. {
  8921. // Note the & on the next line, we modify the formatDirOption!
  8922. QCString &formatDirName = Config_getString(formatDirOption);
  8923. if (formatDirName.isEmpty())
  8924. {
  8925. formatDirName = baseDirName + defaultDirName;
  8926. }
  8927. else if (formatDirName[0]!='/' && (formatDirName.length()==1 || formatDirName[1]!=':'))
  8928. {
  8929. formatDirName.prepend(baseDirName+'/');
  8930. }
  8931. QDir formatDir(formatDirName);
  8932. if (!formatDir.exists() && !formatDir.mkdir(formatDirName))
  8933. {
  8934. err("Could not create output directory %s\n", formatDirName.data());
  8935. cleanUpDoxygen();
  8936. exit(1);
  8937. }
  8938. return formatDirName;
  8939. }
  8940. static QCString getQchFileName()
  8941. {
  8942. QCString const & qchFile = Config_getString("QCH_FILE");
  8943. if (!qchFile.isEmpty())
  8944. {
  8945. return qchFile;
  8946. }
  8947. QCString const & projectName = Config_getString("PROJECT_NAME");
  8948. QCString const & versionText = Config_getString("PROJECT_NUMBER");
  8949. return QCString("../qch/")
  8950. + (projectName.isEmpty() ? QCString("index") : projectName)
  8951. + (versionText.isEmpty() ? QCString("") : QCString("-") + versionText)
  8952. + QCString(".qch");
  8953. }
  8954. void searchInputFiles(StringList &inputFiles)
  8955. {
  8956. QStrList &exclPatterns = Config_getList("EXCLUDE_PATTERNS");
  8957. bool alwaysRecursive = Config_getBool("RECURSIVE");
  8958. StringDict excludeNameDict(1009);
  8959. excludeNameDict.setAutoDelete(TRUE);
  8960. // gather names of all files in the include path
  8961. msg("Searching for include files...\n");
  8962. QStrList &includePathList = Config_getList("INCLUDE_PATH");
  8963. char *s=includePathList.first();
  8964. while (s)
  8965. {
  8966. QStrList &pl = Config_getList("INCLUDE_FILE_PATTERNS");
  8967. if (pl.count()==0)
  8968. {
  8969. pl = Config_getList("FILE_PATTERNS");
  8970. }
  8971. readFileOrDirectory(s,0,Doxygen::includeNameDict,0,&pl,
  8972. &exclPatterns,0,0,
  8973. alwaysRecursive);
  8974. s=includePathList.next();
  8975. }
  8976. msg("Searching for example files...\n");
  8977. QStrList &examplePathList = Config_getList("EXAMPLE_PATH");
  8978. s=examplePathList.first();
  8979. while (s)
  8980. {
  8981. readFileOrDirectory(s,0,Doxygen::exampleNameDict,0,
  8982. &Config_getList("EXAMPLE_PATTERNS"),
  8983. 0,0,0,
  8984. (alwaysRecursive || Config_getBool("EXAMPLE_RECURSIVE")));
  8985. s=examplePathList.next();
  8986. }
  8987. msg("Searching for images...\n");
  8988. QStrList &imagePathList=Config_getList("IMAGE_PATH");
  8989. s=imagePathList.first();
  8990. while (s)
  8991. {
  8992. readFileOrDirectory(s,0,Doxygen::imageNameDict,0,0,
  8993. 0,0,0,
  8994. alwaysRecursive);
  8995. s=imagePathList.next();
  8996. }
  8997. msg("Searching for dot files...\n");
  8998. QStrList &dotFileList=Config_getList("DOTFILE_DIRS");
  8999. s=dotFileList.first();
  9000. while (s)
  9001. {
  9002. readFileOrDirectory(s,0,Doxygen::dotFileNameDict,0,0,
  9003. 0,0,0,
  9004. alwaysRecursive);
  9005. s=dotFileList.next();
  9006. }
  9007. msg("Searching for files to exclude\n");
  9008. QStrList &excludeList = Config_getList("EXCLUDE");
  9009. s=excludeList.first();
  9010. while (s)
  9011. {
  9012. readFileOrDirectory(s,0,0,0,&Config_getList("FILE_PATTERNS"),
  9013. 0,0,&excludeNameDict,
  9014. alwaysRecursive,
  9015. FALSE);
  9016. s=excludeList.next();
  9017. }
  9018. /**************************************************************************
  9019. * Determine Input Files *
  9020. **************************************************************************/
  9021. msg("Searching for files to process...\n");
  9022. QDict<void> *killDict = new QDict<void>(10007);
  9023. int inputSize=0;
  9024. QStrList &inputList=Config_getList("INPUT");
  9025. inputFiles.setAutoDelete(TRUE);
  9026. s=inputList.first();
  9027. while (s)
  9028. {
  9029. QCString path=s;
  9030. uint l = path.length();
  9031. // strip trailing slashes
  9032. if (path.at(l-1)=='\\' || path.at(l-1)=='/') path=path.left(l-1);
  9033. inputSize+=readFileOrDirectory(
  9034. path,
  9035. Doxygen::inputNameList,
  9036. Doxygen::inputNameDict,
  9037. &excludeNameDict,
  9038. &Config_getList("FILE_PATTERNS"),
  9039. &exclPatterns,
  9040. &inputFiles,0,
  9041. alwaysRecursive,
  9042. TRUE,
  9043. killDict);
  9044. s=inputList.next();
  9045. }
  9046. delete killDict;
  9047. }
  9048. void parseInput()
  9049. {
  9050. atexit(exitDoxygen);
  9051. /**************************************************************************
  9052. * Make sure the output directory exists
  9053. **************************************************************************/
  9054. QCString &outputDirectory = Config_getString("OUTPUT_DIRECTORY");
  9055. if (outputDirectory.isEmpty())
  9056. {
  9057. outputDirectory=QDir::currentDirPath();
  9058. }
  9059. else
  9060. {
  9061. QDir dir(outputDirectory);
  9062. if (!dir.exists())
  9063. {
  9064. dir.setPath(QDir::currentDirPath());
  9065. if (!dir.mkdir(outputDirectory))
  9066. {
  9067. err("Error: tag OUTPUT_DIRECTORY: Output directory `%s' does not "
  9068. "exist and cannot be created\n",outputDirectory.data());
  9069. cleanUpDoxygen();
  9070. exit(1);
  9071. }
  9072. else if (!Config_getBool("QUIET"))
  9073. {
  9074. err("Notice: Output directory `%s' does not exist. "
  9075. "I have created it for you.\n", outputDirectory.data());
  9076. }
  9077. dir.cd(outputDirectory);
  9078. }
  9079. outputDirectory=dir.absPath();
  9080. }
  9081. /**************************************************************************
  9082. * Initialize global lists and dictionaries
  9083. **************************************************************************/
  9084. int cacheSize = Config_getInt("SYMBOL_CACHE_SIZE");
  9085. if (cacheSize<0) cacheSize=0;
  9086. if (cacheSize>9) cacheSize=9;
  9087. Doxygen::symbolCache = new ObjCache(16+cacheSize); // 16 -> room for 65536 elements,
  9088. // ~2.0 MByte "overhead"
  9089. Doxygen::symbolStorage = new Store;
  9090. #ifdef HAS_SIGNALS
  9091. signal(SIGINT, stopDoxygen);
  9092. #endif
  9093. uint pid = portable_pid();
  9094. Doxygen::objDBFileName.sprintf("doxygen_objdb_%d.tmp",pid);
  9095. Doxygen::objDBFileName.prepend(outputDirectory+"/");
  9096. Doxygen::entryDBFileName.sprintf("doxygen_entrydb_%d.tmp",pid);
  9097. Doxygen::entryDBFileName.prepend(outputDirectory+"/");
  9098. if (Doxygen::symbolStorage->open(Doxygen::objDBFileName)==-1)
  9099. {
  9100. err("Failed to open temporary file %s\n",Doxygen::objDBFileName.data());
  9101. exit(1);
  9102. }
  9103. /**************************************************************************
  9104. * Initialize some global constants
  9105. **************************************************************************/
  9106. g_compoundKeywordDict.insert("template class",(void *)8);
  9107. g_compoundKeywordDict.insert("template struct",(void *)8);
  9108. g_compoundKeywordDict.insert("class",(void *)8);
  9109. g_compoundKeywordDict.insert("struct",(void *)8);
  9110. g_compoundKeywordDict.insert("union",(void *)8);
  9111. g_compoundKeywordDict.insert("interface",(void *)8);
  9112. g_compoundKeywordDict.insert("exception",(void *)8);
  9113. /**************************************************************************
  9114. * Check/create output directorties *
  9115. **************************************************************************/
  9116. QCString htmlOutput;
  9117. bool &generateHtml = Config_getBool("GENERATE_HTML");
  9118. if (generateHtml)
  9119. htmlOutput = createOutputDirectory(outputDirectory,"HTML_OUTPUT","/html");
  9120. QCString xmlOutput;
  9121. bool &generateXml = Config_getBool("GENERATE_XML");
  9122. if (generateXml)
  9123. xmlOutput = createOutputDirectory(outputDirectory,"XML_OUTPUT","/xml");
  9124. QCString latexOutput;
  9125. bool &generateLatex = Config_getBool("GENERATE_LATEX");
  9126. if (generateLatex)
  9127. latexOutput = createOutputDirectory(outputDirectory,"LATEX_OUTPUT","/latex");
  9128. QCString rtfOutput;
  9129. bool &generateRtf = Config_getBool("GENERATE_RTF");
  9130. if (generateRtf)
  9131. rtfOutput = createOutputDirectory(outputDirectory,"RTF_OUTPUT","/rtf");
  9132. QCString manOutput;
  9133. bool &generateMan = Config_getBool("GENERATE_MAN");
  9134. if (generateMan)
  9135. manOutput = createOutputDirectory(outputDirectory,"MAN_OUTPUT","/man");
  9136. if (Config_getBool("HAVE_DOT"))
  9137. {
  9138. QCString curFontPath = Config_getString("DOT_FONTPATH");
  9139. if (curFontPath.isEmpty())
  9140. {
  9141. portable_getenv("DOTFONTPATH");
  9142. QCString newFontPath = ".";
  9143. if (!curFontPath.isEmpty())
  9144. {
  9145. newFontPath+=portable_pathListSeparator();
  9146. newFontPath+=curFontPath;
  9147. }
  9148. portable_setenv("DOTFONTPATH",newFontPath);
  9149. }
  9150. else
  9151. {
  9152. portable_setenv("DOTFONTPATH",curFontPath);
  9153. }
  9154. }
  9155. /**************************************************************************
  9156. * Handle layout file *
  9157. **************************************************************************/
  9158. LayoutDocManager::instance().init();
  9159. QCString layoutFileName = Config_getString("LAYOUT_FILE");
  9160. bool defaultLayoutUsed = FALSE;
  9161. if (layoutFileName.isEmpty())
  9162. {
  9163. layoutFileName = "DoxygenLayout.xml";
  9164. defaultLayoutUsed = TRUE;
  9165. }
  9166. QFile layoutFile(layoutFileName);
  9167. if (layoutFile.open(IO_ReadOnly))
  9168. {
  9169. msg("Parsing layout file %s...\n",layoutFileName.data());
  9170. QTextStream t(&layoutFile);
  9171. LayoutDocManager::instance().parse(t);
  9172. }
  9173. else if (!defaultLayoutUsed)
  9174. {
  9175. err("Warning: failed to open layout file '%s' for reading!\n",layoutFileName.data());
  9176. }
  9177. /**************************************************************************
  9178. * Read and preprocess input *
  9179. **************************************************************************/
  9180. // prevent search in the output directories
  9181. QStrList &exclPatterns = Config_getList("EXCLUDE_PATTERNS");
  9182. if (generateHtml) exclPatterns.append(htmlOutput);
  9183. if (generateXml) exclPatterns.append(xmlOutput);
  9184. if (generateLatex) exclPatterns.append(latexOutput);
  9185. if (generateRtf) exclPatterns.append(rtfOutput);
  9186. if (generateMan) exclPatterns.append(manOutput);
  9187. searchInputFiles(g_inputFiles);
  9188. // Notice: the order of the function calls below is very important!
  9189. if (Config_getBool("GENERATE_HTML"))
  9190. {
  9191. readFormulaRepository();
  9192. }
  9193. /**************************************************************************
  9194. * Handle Tag Files *
  9195. **************************************************************************/
  9196. g_storage = new FileStorage;
  9197. g_storage->setName(Doxygen::entryDBFileName);
  9198. if (!g_storage->open(IO_WriteOnly))
  9199. {
  9200. err("Failed to create temporary storage file %s\n",
  9201. Doxygen::entryDBFileName.data());
  9202. exit(1);
  9203. }
  9204. Entry *root=new Entry;
  9205. EntryNav *rootNav = new EntryNav(0,root);
  9206. rootNav->setEntry(root);
  9207. msg("Reading and parsing tag files\n");
  9208. QStrList &tagFileList = Config_getList("TAGFILES");
  9209. char *s=tagFileList.first();
  9210. while (s)
  9211. {
  9212. readTagFile(root,s);
  9213. root->createNavigationIndex(rootNav,g_storage,0);
  9214. s=tagFileList.next();
  9215. }
  9216. /**************************************************************************
  9217. * Parse source files *
  9218. **************************************************************************/
  9219. parseFiles(root,rootNav);
  9220. g_storage->close();
  9221. if (!g_storage->open(IO_ReadOnly))
  9222. {
  9223. err("Failed to open temporary storage file %s for reading",
  9224. Doxygen::entryDBFileName.data());
  9225. exit(1);
  9226. }
  9227. //printNavTree(rootNav,0);
  9228. // we are done with input scanning now, so free up the buffers used by flex
  9229. // (can be around 4MB)
  9230. preFreeScanner();
  9231. scanFreeScanner();
  9232. pyscanFreeScanner();
  9233. //delete rootNav;
  9234. //g_storage.close();
  9235. //exit(1);
  9236. /**************************************************************************
  9237. * Gather information *
  9238. **************************************************************************/
  9239. msg("Building group list...\n");
  9240. buildGroupList(rootNav);
  9241. organizeSubGroups(rootNav);
  9242. msg("Building directory list...\n");
  9243. buildDirectories();
  9244. findDirDocumentation(rootNav);
  9245. if (Config_getBool("BUILTIN_STL_SUPPORT"))
  9246. {
  9247. addSTLClasses(rootNav);
  9248. }
  9249. msg("Building namespace list...\n");
  9250. buildNamespaceList(rootNav);
  9251. findUsingDirectives(rootNav);
  9252. msg("Building file list...\n");
  9253. buildFileList(rootNav);
  9254. //generateFileTree();
  9255. msg("Building class list...\n");
  9256. buildClassList(rootNav);
  9257. msg("Associating documentation with classes...\n");
  9258. buildClassDocList(rootNav);
  9259. // build list of using declarations here (global list)
  9260. buildListOfUsingDecls(rootNav);
  9261. msg("Computing nesting relations for classes...\n");
  9262. resolveClassNestingRelations();
  9263. // calling buildClassList may result in cached relations that
  9264. // become invalid after resolveClassNestingRelations(), that's why
  9265. // we need to clear the cache here
  9266. Doxygen::lookupCache.clear();
  9267. // we don't need the list of using declaration anymore
  9268. g_usingDeclarations.clear();
  9269. msg("Building example list...\n");
  9270. buildExampleList(rootNav);
  9271. msg("Searching for enumerations...\n");
  9272. findEnums(rootNav);
  9273. // Since buildVarList calls isVarWithConstructor
  9274. // and this calls getResolvedClass we need to process
  9275. // typedefs first so the relations between classes via typedefs
  9276. // are properly resolved. See bug 536385 for an example.
  9277. msg("Searching for documented typedefs...\n");
  9278. buildTypedefList(rootNav);
  9279. msg("Searching for members imported via using declarations...\n");
  9280. findUsingDeclImports(rootNav);
  9281. // this should be after buildTypedefList in order to properly import
  9282. // used typedefs
  9283. findUsingDeclarations(rootNav);
  9284. msg("Searching for included using directives...\n");
  9285. findIncludedUsingDirectives();
  9286. msg("Searching for documented variables...\n");
  9287. buildVarList(rootNav);
  9288. msg("Building member list...\n"); // using class info only !
  9289. buildFunctionList(rootNav);
  9290. msg("Searching for friends...\n");
  9291. findFriends();
  9292. msg("Searching for documented defines...\n");
  9293. findDefineDocumentation(rootNav);
  9294. findClassEntries(rootNav);
  9295. msg("Computing class inheritance relations...\n");
  9296. findInheritedTemplateInstances();
  9297. msg("Computing class usage relations...\n");
  9298. findUsedTemplateInstances();
  9299. msg("Flushing cached template relations that have become invalid...\n");
  9300. flushCachedTemplateRelations();
  9301. msg("Creating members for template instances...\n");
  9302. createTemplateInstanceMembers();
  9303. msg("Computing class relations...\n");
  9304. computeTemplateClassRelations();
  9305. flushUnresolvedRelations();
  9306. computeClassRelations();
  9307. if (Config_getBool("OPTIMIZE_OUTPUT_VHDL"))
  9308. VhdlDocGen::computeVhdlComponentRelations();
  9309. g_classEntries.clear();
  9310. msg("Add enum values to enums...\n");
  9311. addEnumValuesToEnums(rootNav);
  9312. findEnumDocumentation(rootNav);
  9313. msg("Searching for member function documentation...\n");
  9314. findObjCMethodDefinitions(rootNav);
  9315. findMemberDocumentation(rootNav); // may introduce new members !
  9316. transferRelatedFunctionDocumentation();
  9317. transferFunctionDocumentation();
  9318. msg("Building page list...\n");
  9319. buildPageList(rootNav);
  9320. msg("Search for main page...\n");
  9321. findMainPage(rootNav);
  9322. msg("Computing page relations...\n");
  9323. computePageRelations(rootNav);
  9324. checkPageRelations();
  9325. msg("Determining the scope of groups...\n");
  9326. findGroupScope(rootNav);
  9327. msg("Sorting lists...\n");
  9328. Doxygen::memberNameSDict->sort();
  9329. Doxygen::functionNameSDict->sort();
  9330. Doxygen::hiddenClasses->sort();
  9331. Doxygen::classSDict->sort();
  9332. msg("Freeing entry tree\n");
  9333. delete rootNav;
  9334. g_storage->close();
  9335. delete g_storage;
  9336. g_storage=0;
  9337. QDir thisDir;
  9338. thisDir.remove(Doxygen::entryDBFileName);
  9339. msg("Determining which enums are documented\n");
  9340. findDocumentedEnumValues();
  9341. msg("Computing member relations...\n");
  9342. computeMemberRelations();
  9343. msg("Building full member lists recursively...\n");
  9344. buildCompleteMemberLists();
  9345. msg("Adding members to member groups.\n");
  9346. addMembersToMemberGroup();
  9347. if (Config_getBool("DISTRIBUTE_GROUP_DOC"))
  9348. {
  9349. msg("Distributing member group documentation.\n");
  9350. distributeMemberGroupDocumentation();
  9351. }
  9352. msg("Computing member references...\n");
  9353. computeMemberReferences();
  9354. if (Config_getBool("INHERIT_DOCS"))
  9355. {
  9356. msg("Inheriting documentation...\n");
  9357. inheritDocumentation();
  9358. }
  9359. // compute the shortest possible names of all files
  9360. // without loosing the uniqueness of the file names.
  9361. msg("Generating disk names...\n");
  9362. Doxygen::inputNameList->generateDiskNames();
  9363. msg("Adding source references...\n");
  9364. addSourceReferences();
  9365. msg("Adding xrefitems...\n");
  9366. addListReferences();
  9367. generateXRefPages();
  9368. if (Config_getBool("SHOW_DIRECTORIES") && Config_getBool("DIRECTORY_GRAPH"))
  9369. {
  9370. msg("Computing dependencies between directories...\n");
  9371. computeDirDependencies();
  9372. }
  9373. msg("Counting data structures...\n");
  9374. countDataStructures();
  9375. msg("Resolving user defined references...\n");
  9376. resolveUserReferences();
  9377. msg("Finding anchors and sections in the documentation...\n");
  9378. findSectionsInDocumentation();
  9379. transferFunctionReferences();
  9380. msg("Combining using relations...\n");
  9381. combineUsingRelations();
  9382. msg("Adding members to index pages...\n");
  9383. addMembersToIndex();
  9384. }
  9385. void generateOutput()
  9386. {
  9387. /**************************************************************************
  9388. * Initialize output generators *
  9389. **************************************************************************/
  9390. //// dump all symbols
  9391. //SDict<DefinitionList>::Iterator sdi(Doxygen::symbolMap);
  9392. //DefinitionList *dl;
  9393. //for (sdi.toFirst();(dl=sdi.current());++sdi)
  9394. //{
  9395. // DefinitionListIterator dli(*dl);
  9396. // Definition *d;
  9397. // printf("Symbol: ");
  9398. // for (dli.toFirst();(d=dli.current());++dli)
  9399. // {
  9400. // printf("%s ",d->qualifiedName().data());
  9401. // }
  9402. // printf("\n");
  9403. //}
  9404. if (g_dumpSymbolMap)
  9405. {
  9406. dumpSymbolMap();
  9407. exit(0);
  9408. }
  9409. initDocParser();
  9410. g_outputList = new OutputList(TRUE);
  9411. if (Config_getBool("GENERATE_HTML"))
  9412. {
  9413. g_outputList->add(new HtmlGenerator);
  9414. HtmlGenerator::init();
  9415. #if 0
  9416. if (Config_getBool("GENERATE_INDEXLOG")) Doxygen::indexList.addIndex(new IndexLog);
  9417. #endif
  9418. bool generateHtmlHelp = Config_getBool("GENERATE_HTMLHELP");
  9419. bool generateEclipseHelp = Config_getBool("GENERATE_ECLIPSEHELP");
  9420. bool generateQhp = Config_getBool("GENERATE_QHP");
  9421. bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");
  9422. bool generateDocSet = Config_getBool("GENERATE_DOCSET");
  9423. if (generateEclipseHelp) Doxygen::indexList.addIndex(new EclipseHelp);
  9424. if (generateHtmlHelp) Doxygen::indexList.addIndex(new HtmlHelp);
  9425. if (generateQhp) Doxygen::indexList.addIndex(new Qhp);
  9426. if (generateTreeView) Doxygen::indexList.addIndex(new FTVHelp);
  9427. if (generateDocSet) Doxygen::indexList.addIndex(new DocSets);
  9428. Doxygen::indexList.initialize();
  9429. Doxygen::indexList.addImageFile("tab_r.gif");
  9430. Doxygen::indexList.addImageFile("tab_l.gif");
  9431. Doxygen::indexList.addImageFile("tab_b.gif");
  9432. Doxygen::indexList.addStyleSheetFile("tabs.css");
  9433. Doxygen::indexList.addImageFile("doxygen.png");
  9434. if (Config_getBool("HTML_DYNAMIC_SECTIONS")) HtmlGenerator::generateSectionImages();
  9435. copyStyleSheet();
  9436. }
  9437. if (Config_getBool("GENERATE_LATEX"))
  9438. {
  9439. g_outputList->add(new LatexGenerator);
  9440. LatexGenerator::init();
  9441. }
  9442. if (Config_getBool("GENERATE_MAN"))
  9443. {
  9444. g_outputList->add(new ManGenerator);
  9445. ManGenerator::init();
  9446. }
  9447. if (Config_getBool("GENERATE_RTF"))
  9448. {
  9449. g_outputList->add(new RTFGenerator);
  9450. RTFGenerator::init();
  9451. }
  9452. if (Config_getBool("USE_HTAGS"))
  9453. {
  9454. Htags::useHtags = TRUE;
  9455. QCString htmldir = Config_getString("HTML_OUTPUT");
  9456. if (!Htags::execute(htmldir))
  9457. err("Error: USE_HTAGS is YES but htags(1) failed. \n");
  9458. if (!Htags::loadFilemap(htmldir))
  9459. err("Error: htags(1) ended normally but failed to load the filemap. \n");
  9460. }
  9461. /**************************************************************************
  9462. * Generate documentation *
  9463. **************************************************************************/
  9464. QFile *tag=0;
  9465. QCString &generateTagFile = Config_getString("GENERATE_TAGFILE");
  9466. if (!generateTagFile.isEmpty())
  9467. {
  9468. tag=new QFile(generateTagFile);
  9469. if (!tag->open(IO_WriteOnly))
  9470. {
  9471. err("Error: cannot open tag file %s for writing\n",
  9472. generateTagFile.data()
  9473. );
  9474. cleanUpDoxygen();
  9475. exit(1);
  9476. }
  9477. Doxygen::tagFile.setDevice(tag);
  9478. Doxygen::tagFile.setEncoding(QTextStream::UnicodeUTF8);
  9479. Doxygen::tagFile << "<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?>" << endl;
  9480. Doxygen::tagFile << "<tagfile>" << endl;
  9481. }
  9482. if (Config_getBool("GENERATE_HTML")) writeDoxFont(Config_getString("HTML_OUTPUT"));
  9483. if (Config_getBool("GENERATE_LATEX")) writeDoxFont(Config_getString("LATEX_OUTPUT"));
  9484. if (Config_getBool("GENERATE_RTF")) writeDoxFont(Config_getString("RTF_OUTPUT"));
  9485. msg("Generating style sheet...\n");
  9486. //printf("writing style info\n");
  9487. QCString genString =
  9488. theTranslator->trGeneratedAt(dateToString(TRUE),Config_getString("PROJECT_NAME"));
  9489. g_outputList->writeStyleInfo(0); // write first part
  9490. g_outputList->disableAllBut(OutputGenerator::Latex);
  9491. g_outputList->parseText(genString);
  9492. g_outputList->writeStyleInfo(1); // write second part
  9493. //parseText(*g_outputList,theTranslator->trWrittenBy());
  9494. g_outputList->writeStyleInfo(2); // write third part
  9495. g_outputList->parseText(genString);
  9496. g_outputList->writeStyleInfo(3); // write fourth part
  9497. //parseText(*g_outputList,theTranslator->trWrittenBy());
  9498. g_outputList->writeStyleInfo(4); // write last part
  9499. g_outputList->enableAll();
  9500. static bool searchEngine = Config_getBool("SEARCHENGINE");
  9501. static bool serverBasedSearch = Config_getBool("SERVER_BASED_SEARCH");
  9502. // generate search indices (need to do this before writing other HTML
  9503. // pages as these contain a drop down menu with options depending on
  9504. // what categories we find in this function.
  9505. if (Config_getBool("GENERATE_HTML") && searchEngine)
  9506. {
  9507. QCString searchDirName = Config_getString("HTML_OUTPUT")+"/search";
  9508. QDir searchDir(searchDirName);
  9509. if (!searchDir.exists() && !searchDir.mkdir(searchDirName))
  9510. {
  9511. err("Error: Could not create search results directory '%s' $PWD='%s'\n",
  9512. searchDirName.data(),QDir::currentDirPath().data());
  9513. exit(1);
  9514. }
  9515. HtmlGenerator::writeSearchData(searchDirName);
  9516. writeSearchStyleSheet();
  9517. if (!serverBasedSearch) // client side search index
  9518. {
  9519. writeJavascriptSearchIndex();
  9520. }
  9521. }
  9522. //statistics();
  9523. // count the number of documented elements in the lists we have built.
  9524. // If the result is 0 we do not generate the lists and omit the
  9525. // corresponding links in the index.
  9526. msg("Generating index page...\n");
  9527. writeIndex(*g_outputList);
  9528. msg("Generating page index...\n");
  9529. writePageIndex(*g_outputList);
  9530. msg("Generating example documentation...\n");
  9531. generateExampleDocs();
  9532. msg("Generating file sources...\n");
  9533. if (!Htags::useHtags)
  9534. {
  9535. generateFileSources();
  9536. }
  9537. msg("Generating file documentation...\n");
  9538. generateFileDocs();
  9539. msg("Generating page documentation...\n");
  9540. generatePageDocs();
  9541. msg("Generating group documentation...\n");
  9542. generateGroupDocs();
  9543. msg("Generating group index...\n");
  9544. writeGroupIndex(*g_outputList);
  9545. msg("Generating class documentation...\n");
  9546. generateClassDocs();
  9547. if (Config_getBool("HAVE_DOT") && Config_getBool("GRAPHICAL_HIERARCHY"))
  9548. {
  9549. msg("Generating graphical class hierarchy...\n");
  9550. writeGraphicalClassHierarchy(*g_outputList);
  9551. }
  9552. msg("Generating namespace index...\n");
  9553. generateNamespaceDocs();
  9554. msg("Generating namespace member index...\n");
  9555. writeNamespaceMemberIndex(*g_outputList);
  9556. if (Config_getBool("GENERATE_LEGEND"))
  9557. {
  9558. msg("Generating graph info page...\n");
  9559. writeGraphInfo(*g_outputList);
  9560. }
  9561. if (Config_getBool("SHOW_DIRECTORIES"))
  9562. {
  9563. msg("Generating directory documentation...\n");
  9564. generateDirDocs(*g_outputList);
  9565. }
  9566. msg("Generating file index...\n");
  9567. writeFileIndex(*g_outputList);
  9568. if (Config_getBool("SHOW_DIRECTORIES"))
  9569. {
  9570. msg("Generating directory index...\n");
  9571. writeDirIndex(*g_outputList);
  9572. }
  9573. msg("Generating example index...\n");
  9574. writeExampleIndex(*g_outputList);
  9575. msg("Generating file member index...\n");
  9576. writeFileMemberIndex(*g_outputList);
  9577. //writeDirDependencyGraph(Config_getString("HTML_OUTPUT"));
  9578. if (Config_getBool("GENERATE_RTF"))
  9579. {
  9580. msg("Combining RTF output...\n");
  9581. if (!RTFGenerator::preProcessFileInplace(Config_getString("RTF_OUTPUT"),"refman.rtf"))
  9582. {
  9583. err("An error occurred during post-processing the RTF files!\n");
  9584. }
  9585. }
  9586. if (Doxygen::formulaList.count()>0 && Config_getBool("GENERATE_HTML"))
  9587. {
  9588. msg("Generating bitmaps for formulas in HTML...\n");
  9589. Doxygen::formulaList.generateBitmaps(Config_getString("HTML_OUTPUT"));
  9590. }
  9591. //if (Config_getBool("GENERATE_HTML") && Config_getBool("GENERATE_HTMLHELP"))
  9592. //{
  9593. // HtmlHelp::getInstance()->finalize();
  9594. //}
  9595. //if (Config_getBool("GENERATE_HTML") && Config_getBool("GENERATE_TREEVIEW"))
  9596. //{
  9597. // FTVHelp::getInstance()->finalize();
  9598. //}
  9599. Doxygen::indexList.finalize();
  9600. if (!Config_getString("GENERATE_TAGFILE").isEmpty())
  9601. {
  9602. Doxygen::tagFile << "</tagfile>" << endl;
  9603. delete tag;
  9604. }
  9605. if (Config_getBool("DOT_CLEANUP"))
  9606. {
  9607. if (Config_getBool("GENERATE_HTML"))
  9608. removeDoxFont(Config_getString("HTML_OUTPUT"));
  9609. if (Config_getBool("GENERATE_RTF"))
  9610. removeDoxFont(Config_getString("RTF_OUTPUT"));
  9611. if (Config_getBool("GENERATE_LATEX"))
  9612. removeDoxFont(Config_getString("LATEX_OUTPUT"));
  9613. }
  9614. if (Config_getBool("GENERATE_XML"))
  9615. {
  9616. msg("Generating XML output...\n");
  9617. generateXML();
  9618. }
  9619. if (Config_getBool("GENERATE_AUTOGEN_DEF"))
  9620. {
  9621. msg("Generating AutoGen DEF output...\n");
  9622. generateDEF();
  9623. }
  9624. if (Config_getBool("GENERATE_PERLMOD"))
  9625. {
  9626. msg("Generating Perl module output...\n");
  9627. generatePerlMod();
  9628. }
  9629. if (Config_getBool("GENERATE_HTML") &&
  9630. Config_getBool("GENERATE_HTMLHELP") &&
  9631. !Config_getString("HHC_LOCATION").isEmpty())
  9632. {
  9633. msg("Running html help compiler...\n");
  9634. QString oldDir = QDir::currentDirPath();
  9635. QDir::setCurrent(Config_getString("HTML_OUTPUT"));
  9636. if (portable_system(Config_getString("HHC_LOCATION"), "index.hhp", FALSE))
  9637. {
  9638. err("Error: failed to run html help compiler on index.hhp\n");
  9639. }
  9640. QDir::setCurrent(oldDir);
  9641. }
  9642. if ( Config_getBool("GENERATE_HTML") &&
  9643. Config_getBool("GENERATE_QHP") &&
  9644. !Config_getString("QHG_LOCATION").isEmpty())
  9645. {
  9646. msg("Running qhelpgenerator...\n");
  9647. QCString const qhpFileName = Qhp::getQhpFileName();
  9648. QCString const qchFileName = getQchFileName();
  9649. QCString const args = QCString().sprintf("%s -o \"%s\"", qhpFileName.data(), qchFileName.data());
  9650. QString const oldDir = QDir::currentDirPath();
  9651. QDir::setCurrent(Config_getString("HTML_OUTPUT"));
  9652. if (portable_system(Config_getString("QHG_LOCATION"), args.data(), FALSE))
  9653. {
  9654. err("Error: failed to run qhelpgenerator on index.qhp\n");
  9655. }
  9656. QDir::setCurrent(oldDir);
  9657. }
  9658. if (Config_getBool("GENERATE_HTML") && searchEngine && serverBasedSearch)
  9659. {
  9660. msg("Generating search index\n");
  9661. HtmlGenerator::writeSearchPage();
  9662. Doxygen::searchIndex->write(Config_getString("HTML_OUTPUT")+"/search/search.idx");
  9663. }
  9664. if (Debug::isFlagSet(Debug::Time))
  9665. {
  9666. msg("Total elapsed time: %.3f seconds\n(of which %.3f seconds waiting for external tools to finish)\n",
  9667. ((double)Doxygen::runningTime.elapsed())/1000.0,
  9668. portable_getSysElapsedTime()
  9669. );
  9670. }
  9671. /**************************************************************************
  9672. * Start cleaning up *
  9673. **************************************************************************/
  9674. //Doxygen::symbolCache->printStats();
  9675. //Doxygen::symbolStorage->printStats();
  9676. cleanUpDoxygen();
  9677. finializeDocParser();
  9678. Doxygen::symbolStorage->close();
  9679. QDir thisDir;
  9680. thisDir.remove(Doxygen::objDBFileName);
  9681. Config::deleteInstance();
  9682. QTextCodec::deleteAllCodecs();
  9683. delete Doxygen::symbolCache;
  9684. delete Doxygen::symbolMap;
  9685. delete Doxygen::symbolStorage;
  9686. g_successfulRun=TRUE;
  9687. }