123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485 |
- /******************************************************************************
- *
- * Copyright (C) 1997-2010 by Dimitri van Heesch.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation under the terms of the GNU General Public License is hereby
- * granted. No representations are made about the suitability of this software
- * for any purpose. It is provided "as is" without express or implied warranty.
- * See the GNU General Public License for more details.
- *
- * Documents produced by Doxygen are derivative works derived from the
- * input used in their production; they are not affected by this license.
- *
- */
- #include "qtbc.h"
- #include <qfileinfo.h>
- #include <qfile.h>
- #include <qdir.h>
- #include <qdict.h>
- #include <qregexp.h>
- #include <qstrlist.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/stat.h>
- #include <qtextcodec.h>
- #include <unistd.h>
- #include <errno.h>
- #include "version.h"
- #include "doxygen.h"
- #include "scanner.h"
- #include "entry.h"
- #include "index.h"
- #include "logos.h"
- #include "instdox.h"
- #include "message.h"
- #include "config.h"
- #include "util.h"
- #include "pre.h"
- #include "tagreader.h"
- #include "dot.h"
- #include "docparser.h"
- #include "dirdef.h"
- #include "outputlist.h"
- #include "declinfo.h"
- #include "htmlgen.h"
- #include "latexgen.h"
- #include "mangen.h"
- #include "language.h"
- #include "debug.h"
- #include "htmlhelp.h"
- #include "qhp.h"
- #include "indexlog.h"
- #include "ftvhelp.h"
- #include "defargs.h"
- #include "rtfgen.h"
- #include "xmlgen.h"
- #include "defgen.h"
- #include "perlmodgen.h"
- #include "reflist.h"
- #include "pagedef.h"
- #include "bufstr.h"
- #include "commentcnv.h"
- #include "cmdmapper.h"
- #include "searchindex.h"
- #include "parserintf.h"
- #include "htags.h"
- #include "pyscanner.h"
- #include "fortranscanner.h"
- #include "dbusxmlscanner.h"
- #include "code.h"
- #include "objcache.h"
- #include "store.h"
- #include "marshal.h"
- #include "portable.h"
- #include "vhdlscanner.h"
- #include "vhdldocgen.h"
- #include "eclipsehelp.h"
- #include "layout.h"
- #define RECURSE_ENTRYTREE(func,var) \
- do { if (var->children()) { \
- EntryNavListIterator eli(*var->children()); \
- for (;eli.current();++eli) func(eli.current()); \
- } } while(0)
- #if !defined(_WIN32) || defined(__CYGWIN__)
- #include <signal.h>
- #define HAS_SIGNALS
- #endif
- // globally accessible variables
- ClassSDict *Doxygen::classSDict = 0;
- ClassSDict *Doxygen::hiddenClasses = 0;
- NamespaceSDict *Doxygen::namespaceSDict = 0;
- MemberNameSDict *Doxygen::memberNameSDict = 0;
- MemberNameSDict *Doxygen::functionNameSDict = 0;
- FileNameList *Doxygen::inputNameList = 0; // all input files
- FileNameDict *Doxygen::inputNameDict = 0;
- GroupSDict *Doxygen::groupSDict = 0;
- FormulaList Doxygen::formulaList; // all formulas
- FormulaDict Doxygen::formulaDict(1009); // all formulas
- FormulaDict Doxygen::formulaNameDict(1009); // the label name of all formulas
- PageSDict *Doxygen::pageSDict = 0;
- PageSDict *Doxygen::exampleSDict = 0;
- SectionDict Doxygen::sectionDict(257); // all page sections
- StringDict Doxygen::aliasDict(257); // aliases
- FileNameDict *Doxygen::includeNameDict = 0; // include names
- FileNameDict *Doxygen::exampleNameDict = 0; // examples
- FileNameDict *Doxygen::imageNameDict = 0; // images
- FileNameDict *Doxygen::dotFileNameDict = 0; // dot files
- StringDict Doxygen::namespaceAliasDict(257); // all namespace aliases
- StringDict Doxygen::tagDestinationDict(257); // all tag locations
- QDict<void> Doxygen::expandAsDefinedDict(257); // all macros that should be expanded
- QIntDict<MemberGroupInfo> Doxygen::memGrpInfoDict(1009); // dictionary of the member groups heading
- PageDef *Doxygen::mainPage = 0;
- bool Doxygen::insideMainPage = FALSE; // are we generating docs for the main page?
- QTextStream Doxygen::tagFile;
- NamespaceDef *Doxygen::globalScope = 0;
- QDict<RefList> *Doxygen::xrefLists = new QDict<RefList>; // dictionary of cross-referenced item lists
- bool Doxygen::parseSourcesNeeded = FALSE;
- QTime Doxygen::runningTime;
- SearchIndex * Doxygen::searchIndex=0;
- QDict<DefinitionIntf> *Doxygen::symbolMap;
- bool Doxygen::outputToWizard=FALSE;
- QDict<int> * Doxygen::htmlDirMap = 0;
- QCache<LookupInfo> Doxygen::lookupCache(50000,50000);
- DirSDict *Doxygen::directories;
- SDict<DirRelation> Doxygen::dirRelations(257);
- ParserManager *Doxygen::parserManager = 0;
- QCString Doxygen::htmlFileExtension;
- bool Doxygen::suppressDocWarnings = FALSE;
- ObjCache *Doxygen::symbolCache = 0;
- Store *Doxygen::symbolStorage;
- QCString Doxygen::objDBFileName;
- QCString Doxygen::entryDBFileName;
- bool Doxygen::gatherDefines = TRUE;
- IndexList Doxygen::indexList;
- int Doxygen::subpageNestingLevel = 0;
- bool Doxygen::userComments = FALSE;
- QCString Doxygen::spaces;
- // locally accessible globals
- static QDict<EntryNav> g_classEntries(1009);
- static StringList g_inputFiles;
- static QDict<void> g_compoundKeywordDict(7); // keywords recognised as compounds
- static OutputList *g_outputList = 0; // list of output generating objects
- static QDict<FileDef> g_usingDeclarations(1009); // used classes
- static FileStorage *g_storage = 0;
- static bool g_successfulRun = FALSE;
- static bool g_dumpSymbolMap = FALSE;
- static bool g_dumpConfigAsXML = FALSE;
- void clearAll()
- {
- g_inputFiles.clear();
- //g_excludeNameDict.clear();
- //delete g_outputList; g_outputList=0;
- Doxygen::classSDict->clear();
- Doxygen::namespaceSDict->clear();
- Doxygen::pageSDict->clear();
- Doxygen::exampleSDict->clear();
- Doxygen::inputNameList->clear();
- Doxygen::formulaList.clear();
- Doxygen::sectionDict.clear();
- Doxygen::inputNameDict->clear();
- Doxygen::includeNameDict->clear();
- Doxygen::exampleNameDict->clear();
- Doxygen::imageNameDict->clear();
- Doxygen::dotFileNameDict->clear();
- Doxygen::formulaDict.clear();
- Doxygen::formulaNameDict.clear();
- Doxygen::tagDestinationDict.clear();
- delete Doxygen::mainPage; Doxygen::mainPage=0;
- }
- void statistics()
- {
- fprintf(stderr,"--- inputNameDict stats ----\n");
- Doxygen::inputNameDict->statistics();
- fprintf(stderr,"--- includeNameDict stats ----\n");
- Doxygen::includeNameDict->statistics();
- fprintf(stderr,"--- exampleNameDict stats ----\n");
- Doxygen::exampleNameDict->statistics();
- fprintf(stderr,"--- imageNameDict stats ----\n");
- Doxygen::imageNameDict->statistics();
- fprintf(stderr,"--- dotFileNameDict stats ----\n");
- Doxygen::dotFileNameDict->statistics();
- //fprintf(stderr,"--- g_excludeNameDict stats ----\n");
- //g_excludeNameDict.statistics();
- fprintf(stderr,"--- aliasDict stats ----\n");
- Doxygen::aliasDict.statistics();
- fprintf(stderr,"--- typedefDict stats ----\n");
- fprintf(stderr,"--- namespaceAliasDict stats ----\n");
- Doxygen::namespaceAliasDict.statistics();
- fprintf(stderr,"--- formulaDict stats ----\n");
- Doxygen::formulaDict.statistics();
- fprintf(stderr,"--- formulaNameDict stats ----\n");
- Doxygen::formulaNameDict.statistics();
- fprintf(stderr,"--- tagDestinationDict stats ----\n");
- Doxygen::tagDestinationDict.statistics();
- fprintf(stderr,"--- g_compoundKeywordDict stats ----\n");
- g_compoundKeywordDict.statistics();
- fprintf(stderr,"--- expandAsDefinedDict stats ----\n");
- Doxygen::expandAsDefinedDict.statistics();
- fprintf(stderr,"--- memGrpInfoDict stats ----\n");
- Doxygen::memGrpInfoDict.statistics();
- }
- static void addMemberDocs(EntryNav *rootNav,MemberDef *md, const char *funcDecl,
- ArgumentList *al,bool over_load,NamespaceSDict *nl=0);
- static void findMember(EntryNav *rootNav,
- QCString funcDecl,
- bool overloaded,
- bool isFunc
- );
- struct STLInfo
- {
- const char *className;
- const char *baseClass1;
- const char *baseClass2;
- const char *templType1;
- const char *templName1;
- const char *templType2;
- const char *templName2;
- bool virtualInheritance;
- bool iterators;
- };
- static STLInfo g_stlinfo[] =
- {
- // className baseClass1 baseClass2 templType1 templName1 templType2 templName2 virtInheritance // iterators
- { "allocator", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
- { "auto_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE },
- { "ios_base", 0, 0, 0, 0, 0, 0, FALSE, FALSE },
- { "basic_ios", "ios_base", 0, "Char", 0, 0, 0, FALSE, FALSE },
- { "basic_istream", "basic_ios<Char>", 0, "Char", 0, 0, 0, TRUE, FALSE },
- { "basic_ostream", "basic_ios<Char>", 0, "Char", 0, 0, 0, TRUE, FALSE },
- { "basic_iostream", "basic_istream<Char>", "basic_ostream<Char>", "Char", 0, 0, 0, FALSE, FALSE },
- { "basic_ifstream", "basic_istream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
- { "basic_ofstream", "basic_ostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
- { "basic_fstream", "basic_iostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
- { "basic_istringstream", "basic_istream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
- { "basic_ostringstream", "basic_ostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
- { "basic_stringstream", "basic_iostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
- { "ios", "basic_ios<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "wios", "basic_ios<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "istream", "basic_istream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "wistream", "basic_istream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "ostream", "basic_ostream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "wostream", "basic_ostream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "ifstream", "basic_ifstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "wifstream", "basic_ifstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "ofstream", "basic_ofstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "wofstream", "basic_ofstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "fstream", "basic_fstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "wfstream", "basic_fstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "istringstream", "basic_istringstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "wistringstream", "basic_istringstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "ostringstream", "basic_ostringstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "wostringstream", "basic_ostringstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "stringstream", "basic_stringstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "wstringstream", "basic_stringstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "basic_string", 0, 0, "Char", 0, 0, 0, FALSE, TRUE },
- { "string", "basic_string<char>", 0, 0, 0, 0, 0, FALSE, TRUE },
- { "wstring", "basic_string<wchar_t>", 0, 0, 0, 0, 0, FALSE, TRUE },
- { "complex", 0, 0, 0, 0, 0, 0, FALSE, FALSE },
- { "bitset", 0, 0, "Bits", 0, 0, 0, FALSE, FALSE },
- { "deque", 0, 0, "T", "elements", 0, 0, FALSE, TRUE },
- { "list", 0, 0, "T", "elements", 0, 0, FALSE, TRUE },
- { "map", 0, 0, "K", "keys", "T", "elements", FALSE, TRUE },
- { "multimap", 0, 0, "K", "keys", "T", "elements", FALSE, TRUE },
- { "set", 0, 0, "K", "keys", 0, 0, FALSE, TRUE },
- { "multiset", 0, 0, "K", "keys", 0, 0, FALSE, TRUE },
- { "vector", 0, 0, "T", "elements", 0, 0, FALSE, TRUE },
- { "queue", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
- { "priority_queue", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
- { "stack", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
- { "valarray", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
- { "exception", 0, 0, 0, 0, 0, 0, FALSE, FALSE },
- { "bad_alloc", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "bad_cast", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "bad_typeid", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "logic_error", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "ios_base::failure", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "runtime_error", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "bad_exception", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "domain_error", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "invalid_argument", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "length_error", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "out_of_range", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "range_error", "runtime_error", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "overflow_error", "runtime_error", 0, 0, 0, 0, 0, FALSE, FALSE },
- { "underflow_error", "runtime_error", 0, 0, 0, 0, 0, FALSE, FALSE },
- { 0, 0, 0, 0, 0, 0, 0, FALSE, FALSE }
- };
- static void addSTLMember(EntryNav *rootNav,const char *type,const char *name)
- {
- Entry *memEntry = new Entry;
- memEntry->name = name;
- memEntry->type = type;
- memEntry->protection = Private;
- memEntry->section = Entry::VARIABLE_SEC;
- memEntry->brief = "STL member";
- memEntry->hidden = FALSE;
- memEntry->artificial = TRUE;
- //memEntry->parent = root;
- //root->addSubEntry(memEntry);
- EntryNav *memEntryNav = new EntryNav(rootNav,memEntry);
- memEntryNav->setEntry(memEntry);
- rootNav->addChild(memEntryNav);
- }
- static void addSTLIterator(EntryNav *classEntryNav,const char *name)
- {
- Entry *iteratorClassEntry = new Entry;
- iteratorClassEntry->fileName = "[STL]";
- iteratorClassEntry->startLine = 1;
- iteratorClassEntry->name = name;
- iteratorClassEntry->section = Entry::CLASS_SEC;
- iteratorClassEntry->brief = "STL iterator class";
- iteratorClassEntry->hidden = FALSE;
- iteratorClassEntry->artificial= TRUE;
- EntryNav *iteratorClassEntryNav = new EntryNav(classEntryNav,iteratorClassEntry);
- iteratorClassEntryNav->setEntry(iteratorClassEntry);
- classEntryNav->addChild(iteratorClassEntryNav);
- }
- static void addSTLClasses(EntryNav *rootNav)
- {
- Entry *namespaceEntry = new Entry;
- namespaceEntry->fileName = "[STL]";
- namespaceEntry->startLine = 1;
- //namespaceEntry->parent = rootNav->entry();
- namespaceEntry->name = "std";
- namespaceEntry->section = Entry::NAMESPACE_SEC;
- namespaceEntry->brief = "STL namespace";
- namespaceEntry->hidden = FALSE;
- namespaceEntry->artificial= TRUE;
- //root->addSubEntry(namespaceEntry);
- EntryNav *namespaceEntryNav = new EntryNav(rootNav,namespaceEntry);
- namespaceEntryNav->setEntry(namespaceEntry);
- rootNav->addChild(namespaceEntryNav);
-
- STLInfo *info = g_stlinfo;
- while (info->className)
- {
- //printf("Adding STL class %s\n",info->className);
- QCString fullName = info->className;
- fullName.prepend("std::");
- // add fake Entry for the class
- Entry *classEntry = new Entry;
- classEntry->fileName = "[STL]";
- classEntry->startLine = 1;
- classEntry->name = fullName;
- //classEntry->parent = namespaceEntry;
- classEntry->section = Entry::CLASS_SEC;
- classEntry->brief = "STL class";
- classEntry->hidden = FALSE;
- classEntry->artificial= TRUE;
- //namespaceEntry->addSubEntry(classEntry);
- EntryNav *classEntryNav = new EntryNav(namespaceEntryNav,classEntry);
- classEntryNav->setEntry(classEntry);
- namespaceEntryNav->addChild(classEntryNav);
- // add template arguments to class
- if (info->templType1)
- {
- ArgumentList *al = new ArgumentList;
- Argument *a=new Argument;
- a->type="typename";
- a->name=info->templType1;
- al->append(a);
- if (info->templType2) // another template argument
- {
- a=new Argument;
- a->type="typename";
- a->name=info->templType2;
- al->append(a);
- }
- classEntry->tArgLists = new QList<ArgumentList>;
- classEntry->tArgLists->setAutoDelete(TRUE);
- classEntry->tArgLists->append(al);
- }
- // add member variables
- if (info->templName1)
- {
- addSTLMember(classEntryNav,info->templType1,info->templName1);
- }
- if (info->templName2)
- {
- addSTLMember(classEntryNav,info->templType2,info->templName2);
- }
- if (info->baseClass1)
- {
- classEntry->extends->append(new BaseInfo(info->baseClass1,Public,info->virtualInheritance?Virtual:Normal));
- }
- if (info->baseClass2)
- {
- classEntry->extends->append(new BaseInfo(info->baseClass2,Public,info->virtualInheritance?Virtual:Normal));
- }
- if (info->iterators)
- {
- // add iterator class
- addSTLIterator(classEntryNav,fullName+"::iterator");
- addSTLIterator(classEntryNav,fullName+"::const_iterator");
- addSTLIterator(classEntryNav,fullName+"::reverse_iterator");
- addSTLIterator(classEntryNav,fullName+"::const_reverse_iterator");
- }
- info++;
- }
- }
- //----------------------------------------------------------------------------
- static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n,
- FileDef *fileScope=0);
- static void addPageToContext(PageDef *pd,EntryNav *rootNav)
- {
- if (rootNav->parent()) // add the page to it's scope
- {
- QCString scope = rootNav->parent()->name();
- if (rootNav->parent()->section()==Entry::PACKAGEDOC_SEC)
- {
- scope=substitute(scope,".","::");
- }
- scope = stripAnonymousNamespaceScope(scope);
- scope+="::"+pd->name();
- Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,scope);
- if (d)
- {
- pd->setPageScope(d);
- }
- }
- }
- static void addRelatedPage(EntryNav *rootNav)
- {
- Entry *root = rootNav->entry();
- GroupDef *gd=0;
- QListIterator<Grouping> gli(*root->groups);
- Grouping *g;
- for (;(g=gli.current());++gli)
- {
- if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname))) break;
- }
- //printf("---> addRelatedPage() %s gd=%p\n",root->name.data(),gd);
- QCString doc;
- if (root->brief.isEmpty())
- {
- doc=root->doc+root->inbodyDocs;
- }
- else
- {
- doc=root->brief+"\n\n"+root->doc+root->inbodyDocs;
- }
- PageDef *pd = addRelatedPage(root->name,root->args,doc,root->anchors,
- root->fileName,root->startLine,
- root->sli,
- gd,rootNav->tagInfo()
- );
- if (pd)
- {
- pd->addSectionsToDefinition(root->anchors);
- addPageToContext(pd,rootNav);
- }
- }
- static void buildGroupListFiltered(EntryNav *rootNav,bool additional)
- {
- if (rootNav->section()==Entry::GROUPDOC_SEC && !rootNav->name().isEmpty())
- {
- //printf("Found group %s title=`%s type=%d'\n",
- // root->name.data(),root->type.data(),root->groupDocType);
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
-
- if ((root->groupDocType==Entry::GROUPDOC_NORMAL && !additional) ||
- (root->groupDocType!=Entry::GROUPDOC_NORMAL && additional))
- {
- GroupDef *gd;
- if ((gd=Doxygen::groupSDict->find(root->name)))
- {
- if ( !gd->hasGroupTitle() )
- {
- gd->setGroupTitle( root->type );
- }
- else if ( root->type.length() > 0 && root->name != root->type && gd->groupTitle() != root->type )
- {
- warn( root->fileName,root->startLine,
- "group %s: ignoring title \"%s\" that does not match old title \"%s\"\n",
- root->name.data(), root->type.data(), gd->groupTitle() );
- }
- gd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- gd->setDocumentation( root->doc, root->docFile, root->docLine );
- gd->setInbodyDocumentation( root->inbodyDocs, root->inbodyFile, root->inbodyLine );
- gd->addSectionsToDefinition(root->anchors);
- gd->setRefItems(root->sli);
- }
- else
- {
- if (rootNav->tagInfo())
- {
- gd = new GroupDef(root->fileName,root->startLine,root->name,root->type,rootNav->tagInfo()->fileName);
- gd->setReference(rootNav->tagInfo()->tagName);
- }
- else
- {
- gd = new GroupDef(root->fileName,root->startLine,root->name,root->type);
- }
- gd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- gd->setDocumentation(root->doc,root->docFile,root->docLine);
- gd->setInbodyDocumentation( root->inbodyDocs, root->inbodyFile, root->inbodyLine );
- gd->addSectionsToDefinition(root->anchors);
- Doxygen::groupSDict->append(root->name,gd);
- gd->setRefItems(root->sli);
- }
- }
- rootNav->releaseEntry();
- }
- if (rootNav->children())
- {
- EntryNavListIterator eli(*rootNav->children());
- EntryNav *e;
- for (;(e=eli.current());++eli)
- {
- buildGroupListFiltered(e,additional);
- }
- }
- }
- static void buildGroupList(EntryNav *rootNav)
- {
- // first process the @defgroups blocks
- buildGroupListFiltered(rootNav,FALSE);
- // then process the @addtogroup, @weakgroup blocks
- buildGroupListFiltered(rootNav,TRUE);
- }
- static void findGroupScope(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::GROUPDOC_SEC && !rootNav->name().isEmpty() &&
- rootNav->parent() && !rootNav->parent()->name().isEmpty())
- {
- GroupDef *gd;
- if ((gd=Doxygen::groupSDict->find(rootNav->name())))
- {
- QCString scope = rootNav->parent()->name();
- if (rootNav->parent()->section()==Entry::PACKAGEDOC_SEC)
- {
- scope=substitute(scope,".","::");
- }
- scope = stripAnonymousNamespaceScope(scope);
- scope+="::"+gd->name();
- Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,scope);
- if (d)
- {
- gd->setGroupScope(d);
- }
- }
- }
- RECURSE_ENTRYTREE(findGroupScope,rootNav);
- }
- static void organizeSubGroupsFiltered(EntryNav *rootNav,bool additional)
- {
- if (rootNav->section()==Entry::GROUPDOC_SEC && !rootNav->name().isEmpty())
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- if ((root->groupDocType==Entry::GROUPDOC_NORMAL && !additional) ||
- (root->groupDocType!=Entry::GROUPDOC_NORMAL && additional))
- {
- GroupDef *gd;
- if ((gd=Doxygen::groupSDict->find(root->name)))
- {
- //printf("adding %s to group %s\n",root->name.data(),gd->name().data());
- addGroupToGroups(root,gd);
- }
- }
- rootNav->releaseEntry();
- }
- if (rootNav->children())
- {
- EntryNavListIterator eli(*rootNav->children());
- EntryNav *e;
- for (;(e=eli.current());++eli)
- {
- organizeSubGroupsFiltered(e,additional);
- }
- }
- }
- static void organizeSubGroups(EntryNav *rootNav)
- {
- //printf("Defining groups\n");
- // first process the @defgroups blocks
- organizeSubGroupsFiltered(rootNav,FALSE);
- //printf("Additional groups\n");
- // then process the @addtogroup, @weakgroup blocks
- organizeSubGroupsFiltered(rootNav,TRUE);
- }
- //----------------------------------------------------------------------
- static void buildFileList(EntryNav *rootNav)
- {
- if (((rootNav->section()==Entry::FILEDOC_SEC) ||
- ((rootNav->section() & Entry::FILE_MASK) && Config_getBool("EXTRACT_ALL"))) &&
- !rootNav->name().isEmpty() && !rootNav->tagInfo() // skip any file coming from tag files
- )
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- bool ambig;
- FileDef *fd=findFileDef(Doxygen::inputNameDict,root->name,ambig);
- //printf("**************** root->name=%s fd=%p\n",root->name.data(),fd);
- if (fd && !ambig)
- {
- #if 0
- if ((!root->doc.isEmpty() && !fd->documentation().isEmpty()) ||
- (!root->brief.isEmpty() && !fd->briefDescription().isEmpty()))
- {
- warn(
- root->fileName,root->startLine,
- "Warning: file %s already documented. "
- "Skipping documentation.",
- root->name.data()
- );
- }
- else
- #endif
- {
- //printf("Adding documentation!\n");
- // using FALSE in setDocumentation is small hack to make sure a file
- // is documented even if a \file command is used without further
- // documentation
- fd->setDocumentation(root->doc,root->docFile,root->docLine,FALSE);
- fd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- fd->addSectionsToDefinition(root->anchors);
- fd->setRefItems(root->sli);
- QListIterator<Grouping> gli(*root->groups);
- Grouping *g;
- for (;(g=gli.current());++gli)
- {
- GroupDef *gd=0;
- if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
- {
- gd->addFile(fd);
- //printf("File %s: in group %s\n",fd->name().data(),s->data());
- }
- }
- }
- }
- else
- {
- const char *fn = root->fileName.data();
- QCString text;
- text.sprintf("Warning: the name `%s' supplied as "
- "the second argument in the \\file statement ",
- root->name.data()
- );
- if (ambig) // name is ambigious
- {
- text+="matches the following input files:\n";
- text+=showFileDefMatches(Doxygen::inputNameDict,root->name);
- text+="Please use a more specific name by "
- "including a (larger) part of the path!";
- }
- else // name is not an input file
- {
- text+="is not an input file";
- }
- warn(fn,root->startLine,text);
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(buildFileList,rootNav);
- }
- static void addIncludeFile(ClassDef *cd,FileDef *ifd,Entry *root)
- {
- if (
- (!root->doc.stripWhiteSpace().isEmpty() ||
- !root->brief.stripWhiteSpace().isEmpty() ||
- Config_getBool("EXTRACT_ALL")
- ) && root->protection!=Private
- )
- {
- //printf(">>>>>> includeFile=%s\n",root->includeFile.data());
- bool local=Config_getBool("FORCE_LOCAL_INCLUDES");
- QCString includeFile = root->includeFile;
- if (!includeFile.isEmpty() && includeFile.at(0)=='"')
- {
- local = TRUE;
- includeFile=includeFile.mid(1,includeFile.length()-2);
- }
- else if (!includeFile.isEmpty() && includeFile.at(0)=='<')
- {
- local = FALSE;
- includeFile=includeFile.mid(1,includeFile.length()-2);
- }
- bool ambig;
- FileDef *fd=0;
- // see if we need to include a verbatim copy of the header file
- //printf("root->includeFile=%s\n",root->includeFile.data());
- if (!includeFile.isEmpty() &&
- (fd=findFileDef(Doxygen::inputNameDict,includeFile,ambig))==0
- )
- { // explicit request
- QCString text;
- text.sprintf("Warning: the name `%s' supplied as "
- "the argument of the \\class, \\struct, \\union, or \\include command ",
- includeFile.data()
- );
- if (ambig) // name is ambigious
- {
- text+="matches the following input files:\n";
- text+=showFileDefMatches(Doxygen::inputNameDict,root->includeFile);
- text+="Please use a more specific name by "
- "including a (larger) part of the path!";
- }
- else // name is not an input file
- {
- text+="is not an input file";
- }
- warn(root->fileName,root->startLine,text);
- }
- else if (includeFile.isEmpty() && ifd &&
- // see if the file extension makes sense
- guessSection(ifd->name())==Entry::HEADER_SEC)
- { // implicit assumption
- fd=ifd;
- }
- // if a file is found, we mark it as a source file.
- if (fd)
- {
- QCString iName = !root->includeName.isEmpty() ?
- root->includeName : includeFile;
- if (!iName.isEmpty()) // user specified include file
- {
- if (iName.at(0)=='<') local=FALSE; // explicit override
- if (iName.at(0)=='"' || iName.at(0)=='<')
- {
- iName=iName.mid(1,iName.length()-2); // strip quotes or brackets
- }
- if (iName.isEmpty())
- {
- iName=fd->name();
- }
- }
- else if (!Config_getList("STRIP_FROM_INC_PATH").isEmpty())
- {
- iName=stripFromIncludePath(fd->absFilePath());
- }
- else // use name of the file containing the class definition
- {
- iName=fd->name();
- }
- if (fd->generateSourceFile()) // generate code for header
- {
- cd->setIncludeFile(fd,iName,local,!root->includeName.isEmpty());
- }
- else // put #include in the class documentation without link
- {
- cd->setIncludeFile(0,iName,local,TRUE);
- }
- }
- }
- }
- #if 0
- static bool addNamespace(Entry *root,ClassDef *cd)
- {
- // see if this class is defined inside a namespace
- if (root->section & Entry::COMPOUND_MASK)
- {
- Entry *e = root->parent;
- while (e)
- {
- if (e->section==Entry::NAMESPACE_SEC)
- {
- NamespaceDef *nd=0;
- QCString nsName = stripAnonymousNamespaceScope(e->name);
- //printf("addNameSpace() trying: %s\n",nsName.data());
- if (!nsName.isEmpty() && nsName.at(0)!='@' &&
- (nd=getResolvedNamespace(nsName))
- )
- {
- cd->setNamespace(nd);
- cd->setOuterScope(nd);
- nd->insertClass(cd);
- return TRUE;
- }
- }
- e=e->parent;
- }
- }
- return FALSE;
- }
- #endif
- #if 0
- static Definition *findScope(Entry *root,int level=0)
- {
- if (root==0) return 0;
- //printf("start findScope name=%s\n",root->name.data());
- Definition *result=0;
- if (root->section&Entry::SCOPE_MASK)
- {
- result = findScope(root->parent,level+1); // traverse to the root of the tree
- if (result)
- {
- //printf("Found %s inside %s at level %d\n",root->name.data(),result->name().data(),level);
- // TODO: look at template arguments
- result = result->findInnerCompound(root->name);
- }
- else // reached the global scope
- {
- // TODO: look at template arguments
- result = Doxygen::globalScope->findInnerCompound(root->name);
- //printf("Found in globalScope %s at level %d\n",result->name().data(),level);
- }
- }
- //printf("end findScope(%s,%d)=%s\n",root->name.data(),
- // level,result==0 ? "<none>" : result->name().data());
- return result;
- }
- #endif
- /*! returns the Definition object belonging to the first \a level levels of
- * full qualified name \a name. Creates an artificial scope if the scope is
- * not found and set the parent/child scope relation if the scope is found.
- */
- static Definition *buildScopeFromQualifiedName(const QCString name,int level)
- {
- int i=0;
- int p=0,l;
- Definition *prevScope=Doxygen::globalScope;
- QCString fullScope;
- while (i<level)
- {
- int idx=getScopeFragment(name,p,&l);
- QCString nsName = name.mid(idx,l);
- if (nsName.isEmpty()) return prevScope;
- if (!fullScope.isEmpty()) fullScope+="::";
- fullScope+=nsName;
- NamespaceDef *nd=Doxygen::namespaceSDict->find(fullScope);
- Definition *innerScope = nd;
- ClassDef *cd=0;
- if (nd==0) cd = getClass(fullScope);
- if (nd==0 && cd) // scope is a class
- {
- innerScope = cd;
- }
- else if (nd==0 && cd==0) // scope is not known!
- {
- // introduce bogus namespace
- //printf("++ adding dummy namespace %s to %s\n",nsName.data(),prevScope->name().data());
- nd=new NamespaceDef(
- "[generated]",1,fullScope);
- // add namespace to the list
- Doxygen::namespaceSDict->inSort(fullScope,nd);
- innerScope = nd;
- }
- else // scope is a namespace
- {
- }
- // make the parent/child scope relation
- prevScope->addInnerCompound(innerScope);
- innerScope->setOuterScope(prevScope);
- // proceed to the next scope fragment
- p=idx+l+2;
- prevScope=innerScope;
- i++;
- }
- return prevScope;
- }
- static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n,
- FileDef *fileScope)
- {
- //printf("<findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data());
- Definition *resultScope=startScope;
- if (resultScope==0) resultScope=Doxygen::globalScope;
- QCString scope=stripTemplateSpecifiersFromScope(n,FALSE);
- int l1=0,i1;
- i1=getScopeFragment(scope,0,&l1);
- if (i1==-1)
- {
- //printf(">no fragments!\n");
- return resultScope;
- }
- int p=i1+l1,l2=0,i2;
- while ((i2=getScopeFragment(scope,p,&l2))!=-1)
- {
- QCString nestedNameSpecifier = scope.mid(i1,l1);
- Definition *orgScope = resultScope;
- //printf(" nestedNameSpecifier=%s\n",nestedNameSpecifier.data());
- resultScope = resultScope->findInnerCompound(nestedNameSpecifier);
- //printf(" resultScope=%p\n",resultScope);
- if (resultScope==0)
- {
- NamespaceSDict *usedNamespaces;
- if (orgScope==Doxygen::globalScope && fileScope &&
- (usedNamespaces = fileScope->getUsedNamespaces()))
- // also search for used namespaces
- {
- NamespaceSDict::Iterator ni(*usedNamespaces);
- NamespaceDef *nd;
- for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni)
- {
- // restart search within the used namespace
- resultScope = findScopeFromQualifiedName(nd,n,fileScope);
- }
- if (resultScope)
- {
- // for a nested class A::I in used namespace N, we get
- // N::A::I while looking for A, so we should compare
- // resultScope->name() against scope.left(i2+l2)
- //printf(" -> result=%s scope=%s\n",resultScope->name().data(),scope.data());
- if (rightScopeMatch(resultScope->name(),scope.left(i2+l2)))
- {
- break;
- }
- goto nextFragment;
- }
- }
- // also search for used classes. Complication: we haven't been able
- // to put them in the right scope yet, because we are still resolving
- // the scope relations!
- // Therefore loop through all used classes and see if there is a right
- // scope match between the used class and nestedNameSpecifier.
- QDictIterator<FileDef> ui(g_usingDeclarations);
- FileDef *usedFd;
- for (ui.toFirst();(usedFd=ui.current());++ui)
- {
- //printf("Checking using class %s\n",ui.currentKey());
- if (rightScopeMatch(ui.currentKey(),nestedNameSpecifier))
- {
- // ui.currentKey() is the fully qualified name of nestedNameSpecifier
- // so use this instead.
- QCString fqn = QCString(ui.currentKey())+
- scope.right(scope.length()-p);
- resultScope = buildScopeFromQualifiedName(fqn,fqn.contains("::"));
- //printf("Creating scope from fqn=%s result %p\n",fqn.data(),resultScope);
- if (resultScope)
- {
- //printf("> Match! resultScope=%s\n",resultScope->name().data());
- return resultScope;
- }
- }
- }
-
- //printf("> name %s not found in scope %s\n",nestedNameSpecifier.data(),orgScope->name().data());
- return 0;
- }
- nextFragment:
- i1=i2;
- l1=l2;
- p=i2+l2;
- }
- //printf(">findScopeFromQualifiedName scope %s\n",resultScope->name().data());
- return resultScope;
- }
- ArgumentList *getTemplateArgumentsFromName(
- const QCString &name,
- const QList<ArgumentList> *tArgLists)
- {
- if (tArgLists==0) return 0;
-
- QListIterator<ArgumentList> ali(*tArgLists);
- // for each scope fragment, check if it is a template and advance through
- // the list if so.
- int i,p=0;
- while ((i=name.find("::",p))!=-1)
- {
- NamespaceDef *nd = Doxygen::namespaceSDict->find(name.left(i));
- if (nd==0)
- {
- ClassDef *cd = getClass(name.left(i));
- if (cd)
- {
- if (cd->templateArguments())
- {
- ++ali;
- }
- }
- }
- p=i+2;
- }
- return ali.current();
- }
- static ClassDef::CompoundType convertToCompoundType(int section,int specifier)
- {
- ClassDef::CompoundType sec=ClassDef::Class;
- if (specifier&Entry::Struct)
- sec=ClassDef::Struct;
- else if (specifier&Entry::Union)
- sec=ClassDef::Union;
- else if (specifier&Entry::Interface)
- sec=ClassDef::Interface;
- else if (specifier&Entry::Protocol)
- sec=ClassDef::Protocol;
- else if (specifier&Entry::Category)
- sec=ClassDef::Category;
- else if (specifier&Entry::Exception)
- sec=ClassDef::Exception;
- switch(section)
- {
- //case Entry::UNION_SEC:
- case Entry::UNIONDOC_SEC:
- sec=ClassDef::Union;
- break;
- //case Entry::STRUCT_SEC:
- case Entry::STRUCTDOC_SEC:
- sec=ClassDef::Struct;
- break;
- //case Entry::INTERFACE_SEC:
- case Entry::INTERFACEDOC_SEC:
- sec=ClassDef::Interface;
- break;
- //case Entry::PROTOCOL_SEC:
- case Entry::PROTOCOLDOC_SEC:
- sec=ClassDef::Protocol;
- break;
- //case Entry::CATEGORY_SEC:
- case Entry::CATEGORYDOC_SEC:
- sec=ClassDef::Category;
- break;
- //case Entry::EXCEPTION_SEC:
- case Entry::EXCEPTIONDOC_SEC:
- sec=ClassDef::Exception;
- break;
- }
- return sec;
- }
- static void addClassToContext(EntryNav *rootNav)
- {
- //printf("Loading entry for rootNav=%p name=%s\n",rootNav,rootNav->name().data());
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- //NamespaceDef *nd = 0;
- FileDef *fd = rootNav->fileDef();
- QCString scName;
- if (rootNav->parent()->section()&Entry::SCOPE_MASK)
- {
- scName=rootNav->parent()->name();
- }
- // name without parent's scope
- QCString fullName = root->name;
- // strip off any template parameters (but not those for specializations)
- fullName=stripTemplateSpecifiersFromScope(fullName);
- // name with scope (if not present already)
- QCString qualifiedName = fullName;
- if (!scName.isEmpty() && !leftScopeMatch(fullName,scName))
- {
- qualifiedName.prepend(scName+"::");
- }
- // see if we already found the class before
- ClassDef *cd = getClass(qualifiedName);
- Debug::print(Debug::Classes,0, " Found class with name %s (qualifiedName=%s -> cd=%p)\n",
- cd ? cd->name().data() : root->name.data(), qualifiedName.data(),cd);
-
- if (cd)
- {
- fullName=cd->name();
- Debug::print(Debug::Classes,0," Existing class %s!\n",cd->name().data());
- //if (cd->templateArguments()==0)
- //{
- // //printf("existing ClassDef tempArgList=%p specScope=%s\n",root->tArgList,root->scopeSpec.data());
- // cd->setTemplateArguments(tArgList);
- //}
- cd->setDocumentation(root->doc,root->docFile,root->docLine);
- cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- if (root->bodyLine!=-1 && cd->getStartBodyLine()==-1)
- {
- cd->setBodySegment(root->bodyLine,root->endBodyLine);
- cd->setBodyDef(fd);
- }
- //cd->setName(fullName); // change name to match docs
- if (cd->templateArguments()==0)
- {
- // this happens if a template class declared with @class is found
- // before the actual definition.
- ArgumentList *tArgList =
- getTemplateArgumentsFromName(cd->name(),root->tArgLists);
- cd->setTemplateArguments(tArgList);
- }
- cd->setCompoundType(convertToCompoundType(root->section,root->spec));
- }
- else // new class
- {
- ClassDef::CompoundType sec = convertToCompoundType(root->section,root->spec);
- QCString className;
- QCString namespaceName;
- extractNamespaceName(fullName,className,namespaceName);
- //printf("New class: fullname %s namespace `%s' name=`%s' brief=`%s' docs=`%s'\n",
- // fullName.data(),namespaceName.data(),className.data(),root->brief.data(),root->doc.data());
- QCString tagName;
- QCString refFileName;
- if (rootNav->tagInfo())
- {
- tagName = rootNav->tagInfo()->tagName;
- refFileName = rootNav->tagInfo()->fileName;
- }
- cd=new ClassDef(root->fileName,root->startLine,fullName,sec,
- tagName,refFileName);
- Debug::print(Debug::Classes,0," New class `%s' (sec=0x%08x)! #tArgLists=%d\n",
- fullName.data(),root->section,root->tArgLists ? (int)root->tArgLists->count() : -1);
- cd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
- cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- cd->setIsObjectiveC(root->objc);
- cd->setHidden(root->hidden);
- cd->setArtificial(root->artificial);
- cd->setTypeConstraints(root->typeConstr);
- //printf("new ClassDef %s tempArgList=%p specScope=%s\n",fullName.data(),root->tArgList,root->scopeSpec.data());
- ArgumentList *tArgList =
- getTemplateArgumentsFromName(fullName,root->tArgLists);
- //printf("class %s template args=%s\n",fullName.data(),
- // tArgList ? tempArgListToString(tArgList).data() : "<none>");
- cd->setTemplateArguments(tArgList);
- cd->setProtection(root->protection);
- cd->setIsStatic(root->stat);
- // file definition containing the class cd
- cd->setBodySegment(root->bodyLine,root->endBodyLine);
- cd->setBodyDef(fd);
- // see if the class is found inside a namespace
- //bool found=addNamespace(root,cd);
- // the empty string test is needed for extract all case
- cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- cd->insertUsedFile(root->fileName);
- // add class to the list
- //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data());
- Doxygen::classSDict->append(fullName,cd);
- }
- cd->addSectionsToDefinition(root->anchors);
- if (!root->subGrouping) cd->setSubGrouping(FALSE);
- if (cd->hasDocumentation())
- {
- addIncludeFile(cd,fd,root);
- }
- if (fd && (root->section & Entry::COMPOUND_MASK))
- {
- //printf(">> Inserting class `%s' in file `%s' (root->fileName=`%s')\n",
- // cd->name().data(),
- // fd->name().data(),
- // root->fileName.data()
- // );
- cd->setFileDef(fd);
- fd->insertClass(cd);
- }
- addClassToGroups(root,cd);
- cd->setRefItems(root->sli);
- rootNav->releaseEntry();
- }
-
- //----------------------------------------------------------------------
- // build a list of all classes mentioned in the documentation
- // and all classes that have a documentation block before their definition.
- static void buildClassList(EntryNav *rootNav)
- {
- if (
- ((rootNav->section() & Entry::COMPOUND_MASK) ||
- rootNav->section()==Entry::OBJCIMPL_SEC) && !rootNav->name().isEmpty()
- )
- {
- addClassToContext(rootNav);
- }
- RECURSE_ENTRYTREE(buildClassList,rootNav);
- }
- static void buildClassDocList(EntryNav *rootNav)
- {
- if (
- (rootNav->section() & Entry::COMPOUNDDOC_MASK) && !rootNav->name().isEmpty()
- )
- {
- addClassToContext(rootNav);
- }
- RECURSE_ENTRYTREE(buildClassDocList,rootNav);
- }
- static void resolveClassNestingRelations()
- {
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
- bool done=FALSE;
- int iteration=0;
- while (!done)
- {
- done=TRUE;
- ++iteration;
- ClassDef *cd=0;
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- if (!cd->visited)
- {
- QCString name = stripAnonymousNamespaceScope(cd->name());
- //printf("processing=%s, iteration=%d\n",cd->name().data(),iteration);
- // also add class to the correct structural context
- Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,
- name,cd->getFileDef());
- if (d)
- {
- //printf("****** adding %s to scope %s in iteration %d\n",cd->name().data(),d->name().data(),iteration);
- d->addInnerCompound(cd);
- cd->setOuterScope(d);
- cd->visited=TRUE;
- done=FALSE;
- }
- //else
- //{
- // printf("****** ignoring %s: scope not (yet) found in iteration %d\n",cd->name().data(),iteration);
- //}
- }
- }
- }
- //give warnings for unresolved compounds
- ClassDef *cd=0;
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- if (!cd->visited)
- {
- QCString name = stripAnonymousNamespaceScope(cd->name());
- //printf("processing unresolved=%s, iteration=%d\n",cd->name().data(),iteration);
- /// create the scope artificially
- // anyway, so we can at least relate scopes properly.
- Definition *d = buildScopeFromQualifiedName(name,name.contains("::"));
- if (d!=cd && !cd->getDefFileName().isEmpty())
- // avoid recursion in case of redundant scopes, i.e: namespace N { class N::C {}; }
- // for this case doxygen assumes the exitance of a namespace N::N in which C is to be found!
- // also avoid warning for stuff imported via a tagfile.
- {
- d->addInnerCompound(cd);
- cd->setOuterScope(d);
- warn(cd->getDefFileName(),cd->getDefLine(),
- "Warning: Internal inconsistency: scope for class %s not "
- "found!",name.data()
- );
- }
- }
- }
- }
- //----------------------------------------------------------------------
- // build a list of all namespaces mentioned in the documentation
- // and all namespaces that have a documentation block before their definition.
- static void buildNamespaceList(EntryNav *rootNav)
- {
- if (
- (rootNav->section()==Entry::NAMESPACE_SEC ||
- rootNav->section()==Entry::NAMESPACEDOC_SEC ||
- rootNav->section()==Entry::PACKAGEDOC_SEC
- ) &&
- !rootNav->name().isEmpty()
- )
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- //printf("** buildNamespaceList(%s)\n",root->name.data());
- QCString fName = root->name;
- if (root->section==Entry::PACKAGEDOC_SEC)
- {
- fName=substitute(fName,".","::");
- }
- QCString fullName = stripAnonymousNamespaceScope(fName);
- if (!fullName.isEmpty())
- {
- //printf("Found namespace %s in %s at line %d\n",root->name.data(),
- // root->fileName.data(), root->startLine);
- NamespaceDef *nd;
- if ((nd=Doxygen::namespaceSDict->find(fullName))) // existing namespace
- {
- #if 0
- if (!root->doc.isEmpty() || !root->brief.isEmpty()) // block contains docs
- {
- if (nd->documentation().isEmpty() && !root->doc.isEmpty())
- {
- #endif
- nd->setDocumentation(root->doc,root->docFile,root->docLine);
- nd->setName(fullName); // change name to match docs
- nd->addSectionsToDefinition(root->anchors);
- #if 0
- }
- else if (!nd->documentation().isEmpty() && !root->doc.isEmpty())
- {
- warn(
- root->fileName,root->startLine,
- "Warning: namespace %s already has a detailed description found in file %s at line %d. "
- "Skipping the documentation found here.",
- fullName.data(),nd->docFile().data(),nd->docLine());
- }
- if (nd->briefDescription().isEmpty() && !root->brief.isEmpty())
- {
- #endif
- nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- #if 0
- nd->setName(fullName); // change name to match docs
- }
- else if (!nd->briefDescription().isEmpty() && !root->brief.isEmpty())
- {
- warn(root->fileName,root->startLine,
- "Warning: namespace %s already has a brief description found in file %s at line %d. "
- "Skipping the documentation found here.",
- fullName.data(),nd->docFile().data(),nd->docLine()
- );
- }
- }
- #endif
- // file definition containing the namespace nd
- FileDef *fd=rootNav->fileDef();
- // insert the namespace in the file definition
- if (fd) fd->insertNamespace(nd);
- addNamespaceToGroups(root,nd);
- nd->setRefItems(root->sli);
- }
- else // fresh namespace
- {
- QCString tagName;
- QCString tagFileName;
- if (rootNav->tagInfo())
- {
- tagName=rootNav->tagInfo()->tagName;
- tagFileName=rootNav->tagInfo()->fileName;
- }
- //printf("++ new namespace %d\n",fullName.data());
- NamespaceDef *nd=new NamespaceDef(root->fileName,root->startLine,fullName,tagName,tagFileName);
- nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
- nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- nd->addSectionsToDefinition(root->anchors);
- nd->setHidden(root->hidden);
- nd->setArtificial(root->artificial);
- //printf("Adding namespace to group\n");
- addNamespaceToGroups(root,nd);
- nd->setRefItems(root->sli);
- // file definition containing the namespace nd
- FileDef *fd=rootNav->fileDef();
- // insert the namespace in the file definition
- if (fd) fd->insertNamespace(nd);
- // the empty string test is needed for extract all case
- nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- nd->insertUsedFile(root->fileName);
- nd->setBodySegment(root->bodyLine,root->endBodyLine);
- nd->setBodyDef(fd);
- // add class to the list
- Doxygen::namespaceSDict->inSort(fullName,nd);
- // also add namespace to the correct structural context
- Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,fullName);
- //printf("adding namespace %s to context %s\n",nd->name().data(),d?d->name().data():"<none>");
- if (d==0) // we didn't find anything, create the scope artificially
- // anyway, so we can at least relate scopes properly.
- {
- Definition *d = buildScopeFromQualifiedName(fullName,fullName.contains("::"));
- d->addInnerCompound(nd);
- nd->setOuterScope(d);
- // TODO: Due to the order in which the tag file is written
- // a nested class can be found before its parent!
- }
- else
- {
- d->addInnerCompound(nd);
- nd->setOuterScope(d);
- }
- }
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(buildNamespaceList,rootNav);
- }
- //----------------------------------------------------------------------
- static NamespaceDef *findUsedNamespace(NamespaceSDict *unl,
- const QCString &name)
- {
- NamespaceDef *usingNd =0;
- if (unl)
- {
- //printf("Found namespace dict %d\n",unl->count());
- NamespaceSDict::Iterator unli(*unl);
- NamespaceDef *und;
- for (unli.toFirst();(und=unli.current());++unli)
- {
- QCString uScope=und->name()+"::";
- usingNd = getResolvedNamespace(uScope+name);
- //printf("Also trying with scope=`%s' usingNd=%p\n",(uScope+name).data(),usingNd);
- }
- }
- return usingNd;
- }
- static void findUsingDirectives(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::USINGDIR_SEC)
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- //printf("Found using directive %s at line %d of %s\n",
- // root->name.data(),root->startLine,root->fileName.data());
- QCString name=substitute(root->name,".","::");
- if (!name.isEmpty())
- {
- NamespaceDef *usingNd = 0;
- NamespaceDef *nd = 0;
- FileDef *fd = rootNav->fileDef();
- QCString nsName;
- // see if the using statement was found inside a namespace or inside
- // the global file scope.
- if (rootNav->parent() && rootNav->parent()->section()==Entry::NAMESPACE_SEC &&
- (fd==0 || !fd->isJava()) // not a .java file
- )
- {
- nsName=stripAnonymousNamespaceScope(rootNav->parent()->name());
- if (!nsName.isEmpty())
- {
- nd = getResolvedNamespace(nsName);
- }
- }
- // find the scope in which the `using' namespace is defined by prepending
- // the possible scopes in which the using statement was found, starting
- // with the most inner scope and going to the most outer scope (i.e.
- // file scope).
- int scopeOffset = nsName.length();
- do
- {
- QCString scope=scopeOffset>0 ?
- nsName.left(scopeOffset)+"::" : QCString();
- usingNd = getResolvedNamespace(scope+name);
- //printf("Trying with scope=`%s' usingNd=%p\n",(scope+name).data(),usingNd);
- if (scopeOffset==0)
- {
- scopeOffset=-1;
- }
- else if ((scopeOffset=nsName.findRev("::",scopeOffset-1))==-1)
- {
- scopeOffset=0;
- }
- } while (scopeOffset>=0 && usingNd==0);
- if (usingNd==0 && nd) // not found, try used namespaces in this scope
- // or in one of the parent namespace scopes
- {
- NamespaceDef *pnd = nd;
- while (pnd && usingNd==0)
- {
- // also try with one of the used namespaces found earlier
- usingNd = findUsedNamespace(pnd->getUsedNamespaces(),name);
- // goto the parent
- Definition *s = pnd->getOuterScope();
- if (s && s->definitionType()==Definition::TypeNamespace)
- {
- pnd = (NamespaceDef*)s;
- }
- else
- {
- pnd = 0;
- }
- }
- }
- if (usingNd==0 && fd) // still nothing, also try used namespace in the
- // global scope
- {
- usingNd = findUsedNamespace(fd->getUsedNamespaces(),name);
- }
- //printf("%s -> %s\n",name.data(),usingNd?usingNd->name().data():"<none>");
- // add the namespace the correct scope
- if (usingNd)
- {
- //printf("using fd=%p nd=%p\n",fd,nd);
- if (nd)
- {
- //printf("Inside namespace %s\n",nd->name().data());
- nd->addUsingDirective(usingNd);
- }
- else if (fd)
- {
- //printf("Inside file %s\n",fd->name().data());
- fd->addUsingDirective(usingNd);
- }
- }
- else // unknown namespace, but add it anyway.
- {
- //printf("++ new unknown namespace %s\n",name.data());
- NamespaceDef *nd=new NamespaceDef(root->fileName,root->startLine,name);
- nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
- nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- nd->addSectionsToDefinition(root->anchors);
- //printf("** Adding namespace %s hidden=%d\n",name.data(),root->hidden);
- nd->setHidden(root->hidden);
- nd->setArtificial(TRUE);
- QListIterator<Grouping> gli(*root->groups);
- Grouping *g;
- for (;(g=gli.current());++gli)
- {
- GroupDef *gd=0;
- if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
- gd->addNamespace(nd);
- }
- // insert the namespace in the file definition
- if (fd)
- {
- fd->insertNamespace(nd);
- fd->addUsingDirective(nd);
- }
- // the empty string test is needed for extract all case
- nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- nd->insertUsedFile(root->fileName);
- // add class to the list
- Doxygen::namespaceSDict->inSort(name,nd);
- nd->setRefItems(root->sli);
- }
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(findUsingDirectives,rootNav);
- }
- //----------------------------------------------------------------------
- static void buildListOfUsingDecls(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::USINGDECL_SEC &&
- !(rootNav->parent()->section()&Entry::COMPOUND_MASK) // not a class/struct member
- )
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- QCString name = substitute(root->name,".","::");
- if (g_usingDeclarations.find(name)==0)
- {
- FileDef *fd = rootNav->fileDef();
- if (fd)
- {
- g_usingDeclarations.insert(name,fd);
- }
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(buildListOfUsingDecls,rootNav);
- }
-
- static void findUsingDeclarations(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::USINGDECL_SEC &&
- !(rootNav->parent()->section()&Entry::COMPOUND_MASK) // not a class/struct member
- )
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- //printf("Found using declaration %s at line %d of %s inside section %x\n",
- // root->name.data(),root->startLine,root->fileName.data(),
- // rootNav->parent()->section());
- if (!root->name.isEmpty())
- {
- ClassDef *usingCd = 0;
- NamespaceDef *nd = 0;
- FileDef *fd = rootNav->fileDef();
- QCString scName;
- // see if the using statement was found inside a namespace or inside
- // the global file scope.
- if (rootNav->parent()->section() == Entry::NAMESPACE_SEC)
- {
- scName=rootNav->parent()->name();
- if (!scName.isEmpty())
- {
- nd = getResolvedNamespace(scName);
- }
- }
- // Assume the using statement was used to import a class.
- // Find the scope in which the `using' namespace is defined by prepending
- // the possible scopes in which the using statement was found, starting
- // with the most inner scope and going to the most outer scope (i.e.
- // file scope).
- QCString name = substitute(root->name,".","::"); //Java/C# scope->internal
- usingCd = getClass(name);
- if (usingCd==0)
- {
- usingCd = Doxygen::hiddenClasses->find(name);
- }
- //printf("%s -> %p\n",root->name.data(),usingCd);
- if (usingCd==0) // definition not in the input => add an artificial class
- {
- Debug::print(Debug::Classes,0," New using class `%s' (sec=0x%08x)! #tArgLists=%d\n",
- name.data(),root->section,root->tArgLists ? (int)root->tArgLists->count() : -1);
- usingCd = new ClassDef(
- "<using>",1,
- name,ClassDef::Class);
- Doxygen::hiddenClasses->append(root->name,usingCd);
- usingCd->setArtificial(TRUE);
- }
- else
- {
- Debug::print(Debug::Classes,0," Found used class %s in scope=%s\n",
- usingCd->name().data(),nd?nd->name().data():fd->name().data());
- }
- if (usingCd) // add the class to the correct scope
- {
- if (nd)
- {
- //printf("Inside namespace %s\n",nd->name().data());
- nd->addUsingDeclaration(usingCd);
- }
- else if (fd)
- {
- //printf("Inside file %s\n",fd->name().data());
- fd->addUsingDeclaration(usingCd);
- }
- }
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(findUsingDeclarations,rootNav);
- }
- //----------------------------------------------------------------------
- static void findUsingDeclImports(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::USINGDECL_SEC &&
- (rootNav->parent()->section()&Entry::COMPOUND_MASK) // in a class/struct member
- )
- {
- //printf("Found using declaration %s at line %d of %s inside section %x\n",
- // root->name.data(),root->startLine,root->fileName.data(),
- // root->parent->section);
- QCString fullName=removeRedundantWhiteSpace(rootNav->parent()->name());
- fullName=stripAnonymousNamespaceScope(fullName);
- fullName=stripTemplateSpecifiersFromScope(fullName);
- ClassDef *cd = getClass(fullName);
- if (cd)
- {
- //printf("found class %s\n",cd->name().data());
- int i=rootNav->name().find("::");
- if (i!=-1)
- {
- QCString scope=rootNav->name().left(i);
- QCString memName=rootNav->name().right(rootNav->name().length()-i-2);
- ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter
- if (bcd)
- {
- //printf("found class %s\n",bcd->name().data());
- MemberNameInfoSDict *mndict=bcd->memberNameInfoSDict();
- if (mndict)
- {
- MemberNameInfo *mni = mndict->find(memName);
- if (mni)
- {
- MemberNameInfoIterator mnii(*mni);
- MemberInfo *mi;
- for ( ; (mi=mnii.current()) ; ++mnii )
- {
- MemberDef *md = mi->memberDef;
- if (md && md->protection()!=Private)
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- //printf("found member %s\n",mni->memberName());
- MemberDef *newMd = 0;
- {
- LockingPtr<ArgumentList> templAl = md->templateArguments();
- LockingPtr<ArgumentList> al = md->templateArguments();
- newMd = new MemberDef(
- root->fileName,root->startLine,
- md->typeString(),memName,md->argsString(),
- md->excpString(),root->protection,root->virt,
- md->isStatic(),Member,md->memberType(),
- templAl.pointer(),al.pointer()
- );
- }
- newMd->setMemberClass(cd);
- cd->insertMember(newMd);
- if (!root->doc.isEmpty() || !root->brief.isEmpty())
- {
- newMd->setDocumentation(root->doc,root->docFile,root->docLine);
- newMd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- newMd->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- }
- else
- {
- newMd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
- newMd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
- newMd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine());
- }
- newMd->setDefinition(md->definition());
- newMd->enableCallGraph(root->callGraph);
- newMd->enableCallerGraph(root->callerGraph);
- newMd->setBitfields(md->bitfieldString());
- newMd->addSectionsToDefinition(root->anchors);
- newMd->setBodySegment(md->getStartBodyLine(),md->getEndBodyLine());
- newMd->setBodyDef(md->getBodyDef());
- newMd->setInitializer(md->initializer());
- newMd->setMaxInitLines(md->initializerLines());
- newMd->setMemberGroupId(root->mGrpId);
- newMd->setMemberSpecifiers(md->getMemberSpecifiers());
- rootNav->releaseEntry();
- }
- }
- }
- }
- }
- }
- }
- }
- RECURSE_ENTRYTREE(findUsingDeclImports,rootNav);
- }
- //----------------------------------------------------------------------
- static void findIncludedUsingDirectives()
- {
- // first mark all files as not visited
- FileNameListIterator fnli(*Doxygen::inputNameList);
- FileName *fn;
- for (fnli.toFirst();(fn=fnli.current());++fnli)
- {
- FileNameIterator fni(*fn);
- FileDef *fd;
- for (;(fd=fni.current());++fni)
- {
- fd->visited=FALSE;
- }
- }
- // then recursively add using directives found in #include files
- // to files that have not been visited.
- for (fnli.toFirst();(fn=fnli.current());++fnli)
- {
- FileNameIterator fni(*fn);
- FileDef *fd;
- for (fni.toFirst();(fd=fni.current());++fni)
- {
- if (!fd->visited)
- {
- //printf("----- adding using directives for file %s\n",fd->name().data());
- fd->addIncludedUsingDirectives();
- }
- }
- }
- }
- //----------------------------------------------------------------------
- static MemberDef *addVariableToClass(
- EntryNav *rootNav,
- ClassDef *cd,
- MemberDef::MemberType mtype,
- const QCString &name,
- bool fromAnnScope,
- MemberDef *fromAnnMemb,
- Protection prot,
- Relationship related)
- {
- Entry *root = rootNav->entry();
- QCString qualScope = cd->qualifiedNameWithTemplateParameters();
- QCString scopeSeparator="::";
- if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
- {
- qualScope = substitute(qualScope,"::",".");
- scopeSeparator=".";
- }
- Debug::print(Debug::Variables,0,
- " class variable:\n"
- " `%s' `%s'::`%s' `%s' prot=`%d ann=%d init=`%s'\n",
- root->type.data(),
- qualScope.data(),
- name.data(),
- root->args.data(),
- root->protection,
- fromAnnScope,
- root->initializer.data()
- );
- QCString def;
- if (!root->type.isEmpty())
- {
- if (related || mtype==MemberDef::Friend || Config_getBool("HIDE_SCOPE_NAMES"))
- {
- def=root->type+" "+name+root->args;
- }
- else
- {
- def=root->type+" "+qualScope+scopeSeparator+name+root->args;
- }
- }
- else
- {
- if (Config_getBool("HIDE_SCOPE_NAMES"))
- {
- def=name+root->args;
- }
- else
- {
- def=qualScope+scopeSeparator+name+root->args;
- }
- }
- def.stripPrefix("static ");
- // see if the member is already found in the same scope
- // (this may be the case for a static member that is initialized
- // outside the class)
- MemberName *mn=Doxygen::memberNameSDict->find(name);
- if (mn)
- {
- MemberNameIterator mni(*mn);
- MemberDef *md;
- for (mni.toFirst();(md=mni.current());++mni)
- {
- //printf("md->getClassDef()=%p cd=%p type=[%s] md->typeString()=[%s]\n",
- // md->getClassDef(),cd,root->type.data(),md->typeString());
- if (md->getClassDef()==cd &&
- removeRedundantWhiteSpace(root->type)==md->typeString())
- // member already in the scope
- {
- if (root->objc &&
- root->mtype==Property &&
- md->memberType()==MemberDef::Variable)
- { // Objective-C 2.0 property
- // turn variable into a property
- md->setProtection(root->protection);
- cd->reclassifyMember(md,MemberDef::Property);
- }
- addMemberDocs(rootNav,md,def,0,FALSE);
- //printf(" Member already found!\n");
- return md;
- }
- }
- }
- // new member variable, typedef or enum value
- MemberDef *md=new MemberDef(
- root->fileName,root->startLine,
- root->type,name,root->args,0,
- prot,Normal,root->stat,related,
- mtype,0,0);
- md->setTagInfo(rootNav->tagInfo());
- md->setMemberClass(cd); // also sets outer scope (i.e. getOuterScope())
- //md->setDefFile(root->fileName);
- //md->setDefLine(root->startLine);
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setDefinition(def);
- md->setBitfields(root->bitfields);
- md->addSectionsToDefinition(root->anchors);
- md->setFromAnonymousScope(fromAnnScope);
- md->setFromAnonymousMember(fromAnnMemb);
- //md->setIndentDepth(indentDepth);
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setInitializer(root->initializer);
- md->setMaxInitLines(root->initLines);
- md->setMemberGroupId(root->mGrpId);
- md->setMemberSpecifiers(root->spec);
- md->setReadAccessor(root->read);
- md->setWriteAccessor(root->write);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- md->setHidden(root->hidden);
- md->setArtificial(root->artificial);
- addMemberToGroups(root,md);
- //if (root->mGrpId!=-1)
- //{
- // printf("memberdef %s in memberGroup %d\n",name.data(),root->mGrpId);
- // md->setMemberGroup(memberGroupDict[root->mGrpId]);
- //
- md->setBodyDef(rootNav->fileDef());
- //printf(" Adding member=%s\n",md->name().data());
- // add the member to the global list
- if (mn)
- {
- mn->append(md);
- }
- else // new variable name
- {
- mn = new MemberName(name);
- mn->append(md);
- //printf("Adding memberName=%s\n",mn->memberName());
- //Doxygen::memberNameDict.insert(name,mn);
- //Doxygen::memberNameList.append(mn);
- Doxygen::memberNameSDict->append(name,mn);
- // add the member to the class
- }
- //printf(" New member adding to %s (%p)!\n",cd->name().data(),cd);
- cd->insertMember(md);
- md->setRefItems(root->sli);
- //TODO: insert FileDef instead of filename strings.
- cd->insertUsedFile(root->fileName);
- rootNav->changeSection(Entry::EMPTY_SEC);
- return md;
- }
- //----------------------------------------------------------------------
- static MemberDef *addVariableToFile(
- EntryNav *rootNav,
- MemberDef::MemberType mtype,
- const QCString &scope,
- const QCString &name,
- bool fromAnnScope,
- /*int indentDepth,*/
- MemberDef *fromAnnMemb)
- {
- Entry *root = rootNav->entry();
- Debug::print(Debug::Variables,0,
- " global variable:\n"
- " type=`%s' scope=`%s' name=`%s' args=`%s' prot=`%d mtype=%d\n",
- root->type.data(),
- scope.data(),
- name.data(),
- root->args.data(),
- root->protection,
- mtype
- );
- FileDef *fd = rootNav->fileDef();
- // see if we have a typedef that should hide a struct or union
- if (mtype==MemberDef::Typedef && Config_getBool("TYPEDEF_HIDES_STRUCT"))
- {
- QCString type = root->type;
- type.stripPrefix("typedef ");
- if (type.left(7)=="struct " || type.left(6)=="union ")
- {
- type.stripPrefix("struct ");
- type.stripPrefix("union ");
- static QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*");
- int l,s;
- s = re.match(type,0,&l);
- if (s>=0)
- {
- QCString typeValue = type.mid(s,l);
- ClassDef *cd = getClass(typeValue);
- if (cd)
- {
- // this typedef should hide compound name cd, so we
- // change the name that is displayed from cd.
- cd->setClassName(name);
- cd->setDocumentation(root->doc,root->docFile,root->docLine);
- cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- return 0;
- }
- }
- }
- }
- // see if the function is inside a namespace
- NamespaceDef *nd = 0;
- QCString nscope;
- if (!scope.isEmpty())
- {
- if (scope.find('@')!=-1) return 0; // anonymous scope!
- //nscope=removeAnonymousScopes(scope);
- //if (!nscope.isEmpty())
- //{
- nd = getResolvedNamespace(scope);
- //}
- }
- QCString def;
- // determine the definition of the global variable
- if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@' &&
- !Config_getBool("HIDE_SCOPE_NAMES")
- )
- // variable is inside a namespace, so put the scope before the name
- {
- static bool optimizeForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
- QCString sep="::";
- if (optimizeForJava) sep=".";
-
- if (!root->type.isEmpty())
- {
- def=root->type+" "+nd->name()+sep+name+root->args;
- }
- else
- {
- def=nd->name()+sep+name+root->args;
- }
- }
- else
- {
- if (!root->type.isEmpty() && !root->name.isEmpty())
- {
- if (name.at(0)=='@') // dummy variable representing annonymous union
- def=root->type;
- else
- def=root->type+" "+name+root->args;
- }
- else
- {
- def=name+root->args;
- }
- }
- def.stripPrefix("static ");
- MemberName *mn=Doxygen::functionNameSDict->find(name);
- if (mn)
- {
- //QCString nscope=removeAnonymousScopes(scope);
- //NamespaceDef *nd=0;
- //if (!nscope.isEmpty())
- if (!scope.isEmpty())
- {
- nd = getResolvedNamespace(scope);
- }
- MemberNameIterator mni(*mn);
- MemberDef *md;
- for (mni.toFirst();(md=mni.current());++mni)
- {
- if (
- ((nd==0 && md->getNamespaceDef()==0 && md->getFileDef() &&
- root->fileName==md->getFileDef()->absFilePath()
- ) // both variable names in the same file
- || (nd!=0 && md->getNamespaceDef()==nd) // both in same namespace
- )
- && !md->isDefine() // function style #define's can be "overloaded" by typedefs or variables
- && !md->isEnumerate() // in C# an enum value and enum can have the same name
- )
- // variable already in the scope
- {
- if (md->getFileDef() &&
- ! // not a php array
- (
- (getLanguageFromFileName(md->getFileDef()->name())==SrcLangExt_PHP) &&
- (md->argsString()!=root->args && root->args.find('[')!=-1)
- )
- )
- // not a php array variable
- {
- Debug::print(Debug::Variables,0,
- " variable already found: scope=%s\n",md->getOuterScope()->name().data());
- addMemberDocs(rootNav,md,def,0,FALSE);
- md->setRefItems(root->sli);
- return md;
- }
- }
- }
- }
- Debug::print(Debug::Variables,0,
- " new variable, nd=%s!\n",nd?nd->name().data():"<global>");
- // new global variable, enum value or typedef
- MemberDef *md=new MemberDef(
- root->fileName,root->startLine,
- root->type,name,root->args,0,
- Public, Normal,root->stat,Member,
- mtype,0,0);
- md->setTagInfo(rootNav->tagInfo());
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->addSectionsToDefinition(root->anchors);
- md->setFromAnonymousScope(fromAnnScope);
- md->setFromAnonymousMember(fromAnnMemb);
- md->setInitializer(root->initializer);
- md->setMaxInitLines(root->initLines);
- md->setMemberGroupId(root->mGrpId);
- md->setDefinition(def);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- md->setExplicitExternal(root->explicitExternal);
- //md->setOuterScope(fd);
- if (!root->explicitExternal)
- {
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setBodyDef(fd);
- }
- addMemberToGroups(root,md);
- md->setRefItems(root->sli);
- if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
- {
- md->setNamespace(nd);
- nd->insertMember(md);
- }
- // add member to the file (we do this even if we have already inserted
- // it into the namespace.
- if (fd)
- {
- md->setFileDef(fd);
- fd->insertMember(md);
- }
- // add member definition to the list of globals
- if (mn)
- {
- mn->append(md);
- }
- else
- {
- mn = new MemberName(name);
- mn->append(md);
- Doxygen::functionNameSDict->append(name,mn);
- }
- rootNav->changeSection(Entry::EMPTY_SEC);
- return md;
- }
- /*! See if the return type string \a type is that of a function pointer
- * \returns -1 if this is not a function pointer variable or
- * the index at which the brace of (...*name) was found.
- */
- static int findFunctionPtr(const QCString &type,int *pLength=0)
- {
- static const QRegExp re("([^)]*\\*[^)]*)");
- int i=-1,l;
- if (!type.isEmpty() && // return type is non-empty
- (i=re.match(type,0,&l))!=-1 && // contains (...*...)
- type.find("operator")==-1 && // not an operator
- (type.find(")(")==-1 || type.find("typedef ")!=-1)
- // not a function pointer return type
- )
- {
- if (pLength) *pLength=l;
- return i;
- }
- else
- {
- return -1;
- }
- }
- /*! Returns TRUE iff \a type is a class within scope \a context.
- * Used to detect variable declarations that look like function prototypes.
- */
- static bool isVarWithConstructor(EntryNav *rootNav)
- {
- static QRegExp initChars("[0-9\"'&*!^]+");
- static QRegExp idChars("[a-z_A-Z][a-z_A-Z0-9]*");
- bool result=FALSE;
- bool typeIsClass;
- QCString type;
- Definition *ctx = 0;
- FileDef *fd = 0;
- int ti;
- //printf("isVarWithConstructor(%s)\n",rootNav->name().data());
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- if (rootNav->parent()->section() & Entry::COMPOUND_MASK)
- { // inside a class
- result=FALSE;
- goto done;
- }
- else if ((fd = rootNav->fileDef()) &&
- (fd->name().right(2)==".c" || fd->name().right(2)==".h")
- )
- { // inside a .c file
- result=FALSE;
- goto done;
- }
- if (root->type.isEmpty())
- {
- result=FALSE;
- goto done;
- }
- if (!rootNav->parent()->name().isEmpty())
- {
- ctx=Doxygen::namespaceSDict->find(rootNav->parent()->name());
- }
- type = root->type;
- // remove qualifiers
- findAndRemoveWord(type,"const");
- findAndRemoveWord(type,"static");
- findAndRemoveWord(type,"volatile");
- //if (type.left(6)=="const ") type=type.right(type.length()-6);
- typeIsClass=getResolvedClass(ctx,fd,type)!=0;
- if (!typeIsClass && (ti=type.find('<'))!=-1)
- {
- typeIsClass=getResolvedClass(ctx,fd,type.left(ti))!=0;
- }
- if (typeIsClass) // now we still have to check if the arguments are
- // types or values. Since we do not have complete type info
- // we need to rely on heuristics :-(
- {
- //printf("typeIsClass\n");
- ArgumentList *al = root->argList;
- if (al==0 || al->isEmpty())
- {
- result=FALSE; // empty arg list -> function prototype.
- goto done;
- }
- ArgumentListIterator ali(*al);
- Argument *a;
- for (ali.toFirst();(a=ali.current());++ali)
- {
- if (!a->name.isEmpty() || !a->defval.isEmpty())
- {
- if (a->name.find(initChars)==0)
- {
- result=TRUE;
- }
- else
- {
- result=FALSE; // arg has (type,name) pair -> function prototype
- }
- goto done;
- }
- if (a->type.isEmpty() || getResolvedClass(ctx,fd,a->type)!=0)
- {
- result=FALSE; // arg type is a known type
- goto done;
- }
- if (checkIfTypedef(ctx,fd,a->type))
- {
- //printf("%s:%d: false (arg is typedef)\n",__FILE__,__LINE__);
- result=FALSE; // argument is a typedef
- goto done;
- }
- if (a->type.at(a->type.length()-1)=='*' ||
- a->type.at(a->type.length()-1)=='&')
- // type ends with * or & => pointer or reference
- {
- result=FALSE;
- goto done;
- }
- if (a->type.find(initChars)==0)
- {
- result=TRUE; // argument type starts with typical initializer char
- goto done;
- }
- QCString resType=resolveTypeDef(ctx,a->type);
- if (resType.isEmpty()) resType=a->type;
- int len;
- if (idChars.match(resType,0,&len)==0) // resType starts with identifier
- {
- resType=resType.left(len);
- //printf("resType=%s\n",resType.data());
- if (resType=="int" || resType=="long" || resType=="float" ||
- resType=="double" || resType=="char" || resType=="signed" ||
- resType=="const" || resType=="unsigned" || resType=="void")
- {
- result=FALSE; // type keyword -> function prototype
- goto done;
- }
- }
- }
- result=TRUE;
- }
- done:
- //printf("isVarWithConstructor(%s,%s)=%d\n",rootNav->parent()->name().data(),
- // root->type.data(),result);
- rootNav->releaseEntry();
- return result;
- }
- static void addVariable(EntryNav *rootNav,int isFuncPtr=-1)
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- Debug::print(Debug::Variables,0,
- "VARIABLE_SEC: \n"
- " type=`%s' name=`%s' args=`%s' bodyLine=`%d' mGrpId=%d\n",
- root->type.data(),
- root->name.data(),
- root->args.data(),
- root->bodyLine,
- root->mGrpId
- );
- //printf("root->parent->name=%s\n",root->parent->name.data());
- if (root->type.isEmpty() && root->name.find("operator")==-1 &&
- (root->name.find('*')!=-1 || root->name.find('&')!=-1))
- {
- // recover from parse error caused by redundant braces
- // like in "int *(var[10]);", which is parsed as
- // type="" name="int *" args="(var[10])"
- root->type=root->name;
- static const QRegExp reName("[a-z_A-Z][a-z_A-Z0-9]*");
- int l;
- int i=root->args.isEmpty() ? -1 : reName.match(root->args,0,&l);
- root->name=root->args.mid(i,l);
- root->args=root->args.mid(i+l,root->args.find(')',i+l)-i-l);
- //printf("new: type=`%s' name=`%s' args=`%s'\n",
- // root->type.data(),root->name.data(),root->args.data());
- }
- else
- {
- int i=isFuncPtr;
- if (i==-1) i=findFunctionPtr(root->type); // for typedefs isFuncPtr is not yet set
- if (i!=-1) // function pointer
- {
- int ai = root->type.find('[',i);
- if (ai>i) // function pointer array
- {
- root->args.prepend(root->type.right(root->type.length()-ai));
- root->type=root->type.left(ai);
- }
- else if (root->type.find(')',i)!=-1) // function ptr, not variable like "int (*bla)[10]"
- {
- root->type=root->type.left(root->type.length()-1);
- root->args.prepend(")");
- //printf("root->type=%s root->args=%s\n",root->type.data(),root->args.data());
- }
- }
- else if (root->type.find("typedef ")!=-1 && root->type.right(2)=="()") // typedef void (func)(int)
- {
- root->type=root->type.left(root->type.length()-1);
- root->args.prepend(")");
- }
- }
-
- QCString scope,name=removeRedundantWhiteSpace(root->name);
- // find the scope of this variable
- EntryNav *p = rootNav->parent();
- while ((p->section() & Entry::SCOPE_MASK))
- {
- QCString scopeName = p->name();
- if (!scopeName.isEmpty())
- {
- scope.prepend(scopeName);
- break;
- }
- p=p->parent();
- }
-
- MemberDef::MemberType mtype;
- QCString type=root->type.stripWhiteSpace();
- ClassDef *cd=0;
- bool isRelated=FALSE;
- bool isMemberOf=FALSE;
- QCString classScope=stripAnonymousNamespaceScope(scope);
- classScope=stripTemplateSpecifiersFromScope(classScope,FALSE);
- QCString annScopePrefix=scope.left(scope.length()-classScope.length());
- if (root->name.findRev("::")!=-1)
- {
- if (root->type=="friend class" || root->type=="friend struct" ||
- root->type=="friend union")
- {
- cd=getClass(scope);
- if (cd)
- {
- addVariableToClass(rootNav, // entry
- cd, // class to add member to
- MemberDef::Friend, // type of member
- name, // name of the member
- FALSE, // from Anonymous scope
- 0, // anonymous member
- Public, // protection
- Member // related to a class
- );
- }
- }
- goto nextMember;
- /* skip this member, because it is a
- * static variable definition (always?), which will be
- * found in a class scope as well, but then we know the
- * correct protection level, so only then it will be
- * inserted in the correct list!
- */
- }
- if (type=="@")
- mtype=MemberDef::EnumValue;
- else if (type.left(8)=="typedef ")
- mtype=MemberDef::Typedef;
- else if (type.left(7)=="friend ")
- mtype=MemberDef::Friend;
- else if (root->mtype==Property)
- mtype=MemberDef::Property;
- else if (root->mtype==Event)
- mtype=MemberDef::Event;
- else
- mtype=MemberDef::Variable;
- if (!root->relates.isEmpty()) // related variable
- {
- isRelated=TRUE;
- isMemberOf=(root->relatesType == MemberOf);
- if (getClass(root->relates)==0 && !scope.isEmpty())
- scope=mergeScopes(scope,root->relates);
- else
- scope=root->relates;
- }
-
- cd=getClass(scope);
- if (cd==0 && classScope!=scope) cd=getClass(classScope);
- if (cd)
- {
- MemberDef *md=0;
- // if cd is an annonymous scope we insert the member
- // into a non-annonymous scope as well. This is needed to
- // be able to refer to it using \var or \fn
- //int indentDepth=0;
- int si=scope.find('@');
- //int anonyScopes = 0;
- bool added=FALSE;
-
- if (si!=-1) // anonymous scope
- {
- QCString pScope;
- ClassDef *pcd=0;
- pScope = scope.left(QMAX(si-2,0));
- if (!pScope.isEmpty())
- pScope.prepend(annScopePrefix);
- else if (annScopePrefix.length()>2)
- pScope=annScopePrefix.left(annScopePrefix.length()-2);
- if (name.at(0)!='@')
- {
- if (!pScope.isEmpty() && (pcd=getClass(pScope)))
- {
- md=addVariableToClass(rootNav, // entry
- pcd, // class to add member to
- mtype, // member type
- name, // member name
- TRUE, // from anonymous scope
- 0, // from anonymous member
- root->protection,
- isMemberOf ? Foreign : isRelated ? Related : Member
- );
- added=TRUE;
- }
- else // anonymous scope inside namespace or file => put variable in the global scope
- {
- if (mtype==MemberDef::Variable)
- {
- md=addVariableToFile(rootNav,mtype,pScope,name,TRUE,0);
- }
- added=TRUE;
- }
- }
- }
- //printf("name=`%s' scope=%s scope.right=%s\n",
- // name.data(),scope.data(),
- // scope.right(scope.length()-si).data());
- addVariableToClass(rootNav, // entry
- cd, // class to add member to
- mtype, // member type
- name, // name of the member
- FALSE, // from anonymous scope
- md, // from anonymous member
- root->protection,
- isMemberOf ? Foreign : isRelated ? Related : Member);
- }
- else if (!name.isEmpty()) // global variable
- {
- //printf("Inserting member in global scope %s!\n",scope.data());
- addVariableToFile(rootNav,mtype,scope,name,FALSE,/*0,*/0);
- }
- nextMember:
- rootNav->releaseEntry();
- }
- //----------------------------------------------------------------------
- // Searches the Entry tree for typedef documentation sections.
- // If found they are stored in their class or in the global list.
- static void buildTypedefList(EntryNav *rootNav)
- {
- //printf("buildVarList(%s)\n",rootNav->name().data());
- if (!rootNav->name().isEmpty() &&
- rootNav->section()==Entry::VARIABLE_SEC &&
- rootNav->type().find("typedef ")!=-1 // its a typedef
- )
- {
- addVariable(rootNav);
- }
- if (rootNav->children())
- {
- EntryNavListIterator eli(*rootNav->children());
- EntryNav *e;
- for (;(e=eli.current());++eli)
- {
- if (e->section()!=Entry::ENUM_SEC)
- {
- buildTypedefList(e);
- }
- }
- }
- }
- //----------------------------------------------------------------------
- // Searches the Entry tree for Variable documentation sections.
- // If found they are stored in their class or in the global list.
- static void buildVarList(EntryNav *rootNav)
- {
- //printf("buildVarList(%s)\n",rootNav->name().data());
- int isFuncPtr=-1;
- if (!rootNav->name().isEmpty() &&
- (rootNav->type().isEmpty() || g_compoundKeywordDict.find(rootNav->type())==0) &&
- (
- (rootNav->section()==Entry::VARIABLE_SEC // it's a variable
- ) ||
- (rootNav->section()==Entry::FUNCTION_SEC && // or maybe a function pointer variable
- (isFuncPtr=findFunctionPtr(rootNav->type()))!=-1
- ) ||
- (rootNav->section()==Entry::FUNCTION_SEC && // class variable initialized by constructor
- isVarWithConstructor(rootNav)
- )
- )
- ) // documented variable
- {
- addVariable(rootNav,isFuncPtr);
- }
- if (rootNav->children())
- {
- EntryNavListIterator eli(*rootNav->children());
- EntryNav *e;
- for (;(e=eli.current());++eli)
- {
- if (e->section()!=Entry::ENUM_SEC)
- {
- buildVarList(e);
- }
- }
- }
- }
- //----------------------------------------------------------------------
- // Searches the Entry tree for Function sections.
- // If found they are stored in their class or in the global list.
- static void addMethodToClass(EntryNav *rootNav,ClassDef *cd,
- const QCString &rname,bool isFriend)
- {
- Entry *root = rootNav->entry();
- FileDef *fd=rootNav->fileDef();
- int l,i=-1;
- static QRegExp re("([a-z_A-Z0-9: ]*[ &*]+[ ]*");
- if (!root->type.isEmpty() && (i=re.match(root->type,0,&l))!=-1) // function variable
- {
- root->args+=root->type.right(root->type.length()-i-l);
- root->type=root->type.left(i+l);
- }
- QCString name=removeRedundantWhiteSpace(rname);
- if (name.left(2)=="::") name=name.right(name.length()-2);
- MemberDef::MemberType mtype;
- if (isFriend) mtype=MemberDef::Friend;
- else if (root->mtype==Signal) mtype=MemberDef::Signal;
- else if (root->mtype==Slot) mtype=MemberDef::Slot;
- else if (root->mtype==DCOP) mtype=MemberDef::DCOP;
- else mtype=MemberDef::Function;
- // strip redundant template specifier for constructors
- if ((fd==0 || getLanguageFromFileName(fd->name())==SrcLangExt_Cpp) &&
- name.left(9)!="operator " && (i=name.find('<'))!=-1 && name.find('>')!=-1)
- {
- name=name.left(i);
- }
- //printf("root->name=`%s; root->args=`%s' root->argList=`%s'\n",
- // root->name.data(),root->args.data(),argListToString(root->argList).data()
- // );
- // adding class member
- MemberDef *md=new MemberDef(
- root->fileName,root->startLine,
- root->type,name,root->args,root->exception,
- root->protection,root->virt,
- root->stat && root->relatesType != MemberOf,
- root->relates.isEmpty() ? Member :
- root->relatesType == MemberOf ? Foreign : Related,
- mtype,root->tArgLists ? root->tArgLists->last() : 0,root->argList);
- md->setTagInfo(rootNav->tagInfo());
- md->setMemberClass(cd);
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setDocsForDefinition(!root->proto);
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setMemberSpecifiers(root->spec);
- md->setMemberGroupId(root->mGrpId);
- md->setTypeConstraints(root->typeConstr);
- md->setBodyDef(fd);
- md->setFileDef(fd);
- //md->setScopeTemplateArguments(root->tArgList);
- md->addSectionsToDefinition(root->anchors);
- QCString def;
- QCString qualScope = cd->qualifiedNameWithTemplateParameters();
- QCString scopeSeparator="::";
- if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
- {
- qualScope = substitute(qualScope,"::",".");
- scopeSeparator=".";
- }
- if (!root->relates.isEmpty() || isFriend || Config_getBool("HIDE_SCOPE_NAMES"))
- {
- if (!root->type.isEmpty())
- {
- if (root->argList)
- {
- def=root->type+" "+name;
- }
- else
- {
- def=root->type+" "+name+root->args;
- }
- }
- else
- {
- if (root->argList)
- {
- def=name;
- }
- else
- {
- def=name+root->args;
- }
- }
- }
- else
- {
- if (!root->type.isEmpty())
- {
- if (root->argList)
- {
- def=root->type+" "+qualScope+scopeSeparator+name;
- }
- else
- {
- def=root->type+" "+qualScope+scopeSeparator+name+root->args;
- }
- }
- else
- {
- if (root->argList)
- {
- def=qualScope+scopeSeparator+name;
- }
- else
- {
- def=qualScope+scopeSeparator+name+root->args;
- }
- }
- }
- if (def.left(7)=="friend ") def=def.right(def.length()-7);
- md->setDefinition(def);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- Debug::print(Debug::Functions,0,
- " Func Member:\n"
- " `%s' `%s'::`%s' `%s' proto=%d\n"
- " def=`%s'\n",
- root->type.data(),
- qualScope.data(),
- rname.data(),
- root->args.data(),
- root->proto,
- def.data()
- );
- // add member to the global list of all members
- //printf("Adding member=%s class=%s\n",md->name().data(),cd->name().data());
- MemberName *mn;
- if ((mn=Doxygen::memberNameSDict->find(name)))
- {
- mn->append(md);
- }
- else
- {
- mn = new MemberName(name);
- mn->append(md);
- Doxygen::memberNameSDict->append(name,mn);
- }
- // add member to the class cd
- cd->insertMember(md);
- // add file to list of used files
- cd->insertUsedFile(root->fileName);
- addMemberToGroups(root,md);
- rootNav->changeSection(Entry::EMPTY_SEC);
- md->setRefItems(root->sli);
- }
- static void buildFunctionList(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::FUNCTION_SEC)
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- Debug::print(Debug::Functions,0,
- "FUNCTION_SEC:\n"
- " `%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",
- root->type.data(),
- rootNav->parent()->name().data(),
- root->name.data(),
- root->args.data(),
- root->relates.data(),
- root->relatesType,
- root->fileName.data(),
- root->startLine,
- root->bodyLine,
- root->tArgLists ? (int)root->tArgLists->count() : -1,
- root->mGrpId,
- root->spec,
- root->proto,
- root->docFile.data()
- );
- bool isFriend=root->type.find("friend ")!=-1;
- QCString rname = removeRedundantWhiteSpace(root->name);
- //printf("rname=%s\n",rname.data());
- QCString scope=rootNav->parent()->name(); //stripAnonymousNamespaceScope(root->parent->name);
- if (!rname.isEmpty() && scope.find('@')==-1)
- {
- ClassDef *cd=0;
- // check if this function's parent is a class
- scope=stripTemplateSpecifiersFromScope(scope,FALSE);
- FileDef *rfd=rootNav->fileDef();
- int memIndex=rname.findRev("::");
- cd=getClass(scope);
- if (cd && scope+"::"==rname.left(scope.length()+2)) // found A::f inside A
- {
- // strip scope from name
- rname=rname.right(rname.length()-rootNav->parent()->name().length()-2);
- }
- NamespaceDef *nd = 0;
- bool isMember=FALSE;
- if (memIndex!=-1)
- {
- int ts=rname.find('<');
- int te=rname.find('>');
- if (memIndex>0 && (ts==-1 || te==-1))
- {
- // note: the following code was replaced by inMember=TRUE to deal with a
- // function rname='X::foo' of class X inside a namespace also called X...
- // bug id 548175
- //nd = Doxygen::namespaceSDict->find(rname.left(memIndex));
- //isMember = nd==0;
- //if (nd)
- //{
- // // strip namespace scope from name
- // scope=rname.left(memIndex);
- // rname=rname.right(rname.length()-memIndex-2);
- //}
- isMember = TRUE;
- }
- else
- {
- isMember=memIndex<ts || memIndex>te;
- }
- }
- static QRegExp re("([a-z_A-Z0-9: ]*[ &*]+[ ]*");
- if (!rootNav->parent()->name().isEmpty() &&
- (rootNav->parent()->section() & Entry::COMPOUND_MASK) &&
- cd &&
- // do some fuzzy things to exclude function pointers
- (root->type.isEmpty() ||
- (root->type.find(re,0)==-1 || root->args.find(")[")!=-1) || // type contains ..(..* and args not )[.. -> function pointer
- root->type.find(")(")!=-1 || root->type.find("operator")!=-1 // type contains ..)(.. and not "operator"
- )
- )
- {
- Debug::print(Debug::Functions,0," --> member %s of class %s!\n",
- rname.data(),cd->name().data());
- addMethodToClass(rootNav,cd,rname,isFriend);
- }
- else if (!((rootNav->parent()->section() & Entry::COMPOUND_MASK)
- || rootNav->parent()->section()==Entry::OBJCIMPL_SEC
- ) &&
- !isMember &&
- (root->relates.isEmpty() || root->relatesType == Duplicate) &&
- root->type.left(7)!="extern " && root->type.left(8)!="typedef "
- )
- // no member => unrelated function
- {
- /* check the uniqueness of the function name in the file.
- * A file could contain a function prototype and a function definition
- * or even multiple function prototypes.
- */
- bool found=FALSE;
- MemberName *mn;
- MemberDef *md=0;
- if ((mn=Doxygen::functionNameSDict->find(rname)))
- {
- Debug::print(Debug::Functions,0," --> function %s already found!\n",rname.data());
- MemberNameIterator mni(*mn);
- for (mni.toFirst();(!found && (md=mni.current()));++mni)
- {
- NamespaceDef *mnd = md->getNamespaceDef();
- NamespaceDef *rnd = 0;
- //printf("root namespace=%s\n",rootNav->parent()->name().data());
- QCString fullScope = scope;
- QCString parentScope = rootNav->parent()->name();
- if (!parentScope.isEmpty() && !leftScopeMatch(parentScope,scope))
- {
- if (!scope.isEmpty()) fullScope.prepend("::");
- fullScope.prepend(parentScope);
- }
- //printf("fullScope=%s\n",fullScope.data());
- rnd = getResolvedNamespace(fullScope);
- FileDef *mfd = md->getFileDef();
- QCString nsName,rnsName;
- if (mnd) nsName = mnd->name().copy();
- if (rnd) rnsName = rnd->name().copy();
- //printf("matching arguments for %s%s %s%s\n",
- // md->name().data(),md->argsString(),rname.data(),argListToString(root->argList).data());
- LockingPtr<ArgumentList> mdAl = md->argumentList();
- LockingPtr<ArgumentList> mdTempl = md->templateArguments();
- // in case of template functions, we need to check if the
- // functions have the same number of template parameters
- bool sameNumTemplateArgs = TRUE;
- if (mdTempl!=0 && root->tArgLists)
- {
- if (mdTempl->count()!=root->tArgLists->getLast()->count())
- {
- sameNumTemplateArgs = FALSE;
- }
- }
- if (
- matchArguments2(md->getOuterScope(),mfd,mdAl.pointer(),
- rnd ? rnd : Doxygen::globalScope,rfd,root->argList,
- FALSE) &&
- sameNumTemplateArgs
- )
- {
- GroupDef *gd=0;
- if (root->groups->first()!=0)
- {
- gd = Doxygen::groupSDict->find(root->groups->first()->groupname.data());
- }
- //printf("match!\n");
- //printf("mnd=%p rnd=%p nsName=%s rnsName=%s\n",mnd,rnd,nsName.data(),rnsName.data());
- // see if we need to create a new member
- found=(mnd && rnd && nsName==rnsName) || // members are in the same namespace
- ((mnd==0 && rnd==0 && mfd!=0 && // no external reference and
- mfd->absFilePath()==root->fileName // prototype in the same file
- )
- );
- // otherwise, allow a duplicate global member with the same argument list
- if (!found && gd && gd==md->getGroupDef())
- {
- // member is already in the group, so we don't want to add it again.
- found=TRUE;
- }
- //printf("combining function with prototype found=%d in namespace %s\n",
- // found,nsName.data());
- if (found)
- {
- // merge argument lists
- mergeArguments(mdAl.pointer(),root->argList,!root->doc.isEmpty());
- // merge documentation
- if (md->documentation().isEmpty() && !root->doc.isEmpty())
- {
- ArgumentList *argList = new ArgumentList;
- stringToArgumentList(root->args,argList);
- if (root->proto)
- {
- //printf("setDeclArgumentList to %p\n",argList);
- md->setDeclArgumentList(argList);
- }
- else
- {
- md->setArgumentList(argList);
- }
- }
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setDocsForDefinition(!root->proto);
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setBodyDef(rfd);
- if (md->briefDescription().isEmpty() && !root->brief.isEmpty())
- {
- md->setArgsString(root->args);
- }
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->addSectionsToDefinition(root->anchors);
- md->enableCallGraph(md->hasCallGraph() || root->callGraph);
- md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
- // merge ingroup specifiers
- if (md->getGroupDef()==0 && root->groups->first()!=0)
- {
- addMemberToGroups(root,md);
- }
- else if (md->getGroupDef()!=0 && root->groups->count()==0)
- {
- //printf("existing member is grouped, new member not\n");
- root->groups->append(new Grouping(md->getGroupDef()->name(), md->getGroupPri()));
- }
- else if (md->getGroupDef()!=0 && root->groups->first()!=0)
- {
- //printf("both members are grouped\n");
- }
- // if md is a declaration and root is the corresponding
- // definition, then turn md into a definition.
- if (md->isPrototype() && !root->proto)
- {
- md->setPrototype(FALSE);
- }
- }
- }
- }
- }
- if (!found) /* global function is unique with respect to the file */
- {
- Debug::print(Debug::Functions,0," --> new function %s found!\n",rname.data());
- //printf("New function type=`%s' name=`%s' args=`%s' bodyLine=%d\n",
- // root->type.data(),rname.data(),root->args.data(),root->bodyLine);
- // new global function
- ArgumentList *tArgList = root->tArgLists ? root->tArgLists->last() : 0;
- QCString name=removeRedundantWhiteSpace(rname);
- md=new MemberDef(
- root->fileName,root->startLine,
- root->type,name,root->args,root->exception,
- root->protection,root->virt,root->stat,Member,
- MemberDef::Function,tArgList,root->argList);
- md->setTagInfo(rootNav->tagInfo());
- //md->setDefFile(root->fileName);
- //md->setDefLine(root->startLine);
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setPrototype(root->proto);
- md->setDocsForDefinition(!root->proto);
- md->setTypeConstraints(root->typeConstr);
- //md->setBody(root->body);
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- FileDef *fd=rootNav->fileDef();
- md->setBodyDef(fd);
- md->addSectionsToDefinition(root->anchors);
- md->setMemberSpecifiers(root->spec);
- md->setMemberGroupId(root->mGrpId);
- // see if the function is inside a namespace that was not part of
- // the name already (in that case nd should be non-zero already)
- if (nd==0 && rootNav->parent()->section() == Entry::NAMESPACE_SEC )
- {
- //QCString nscope=removeAnonymousScopes(rootNav->parent()->name());
- QCString nscope=rootNav->parent()->name();
- if (!nscope.isEmpty())
- {
- nd = getResolvedNamespace(nscope);
- }
- }
- if (!scope.isEmpty())
- {
- if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
- {
- scope = substitute(scope,"::",".")+".";
- }
- else
- {
- scope+="::";
- }
- }
- QCString def;
- if (!root->type.isEmpty())
- {
- if (root->argList)
- {
- def=root->type+" "+scope+name;
- }
- else
- {
- def=root->type+" "+scope+name+root->args;
- }
- }
- else
- {
- if (root->argList)
- {
- def=scope+name.copy();
- }
- else
- {
- def=scope+name+root->args;
- }
- }
- Debug::print(Debug::Functions,0,
- " Global Function:\n"
- " `%s' `%s'::`%s' `%s' proto=%d\n"
- " def=`%s'\n",
- root->type.data(),
- rootNav->parent()->name().data(),
- rname.data(),
- root->args.data(),
- root->proto,
- def.data()
- );
- md->setDefinition(def);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- //if (root->mGrpId!=-1)
- //{
- // md->setMemberGroup(memberGroupDict[root->mGrpId]);
- //}
- md->setRefItems(root->sli);
- if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
- {
- // add member to namespace
- md->setNamespace(nd);
- nd->insertMember(md);
- }
- if (fd)
- {
- // add member to the file (we do this even if we have already
- // inserted it into the namespace)
- md->setFileDef(fd);
- fd->insertMember(md);
- }
- // add member to the list of file members
- //printf("Adding member=%s\n",md->name().data());
- MemberName *mn;
- if ((mn=Doxygen::functionNameSDict->find(name)))
- {
- mn->append(md);
- }
- else
- {
- mn = new MemberName(name);
- mn->append(md);
- Doxygen::functionNameSDict->append(name,mn);
- }
- addMemberToGroups(root,md);
- if (root->relatesType == Simple) // if this is a relatesalso command,
- // allow find Member to pick it up
- {
- rootNav->changeSection(Entry::EMPTY_SEC); // Otherwise we have finished
- // with this entry.
- }
- }
- else
- {
- FileDef *fd=rootNav->fileDef();
- if (fd)
- {
- // add member to the file (we do this even if we have already
- // inserted it into the namespace)
- fd->insertMember(md);
- }
- }
- //printf("unrelated function %d `%s' `%s' `%s'\n",
- // root->parent->section,root->type.data(),rname.data(),root->args.data());
- }
- else
- {
- Debug::print(Debug::Functions,0," --> %s not processed!\n",rname.data());
- }
- }
- else if (rname.isEmpty())
- {
- warn(root->fileName,root->startLine,
- "Warning: Illegal member name found."
- );
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(buildFunctionList,rootNav);
- }
- //----------------------------------------------------------------------
- static void findFriends()
- {
- //printf("findFriends()\n");
- MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
- MemberName *fn;
- for (;(fn=fnli.current());++fnli) // for each global function name
- {
- //printf("Function name=`%s'\n",fn->memberName());
- MemberName *mn;
- if ((mn=Doxygen::memberNameSDict->find(fn->memberName())))
- { // there are members with the same name
- //printf("Function name is also a member name\n");
- MemberNameIterator fni(*fn);
- MemberDef *fmd;
- for (;(fmd=fni.current());++fni) // for each function with that name
- {
- MemberNameIterator mni(*mn);
- MemberDef *mmd;
- for (;(mmd=mni.current());++mni) // for each member with that name
- {
- //printf("Checking for matching arguments
- // mmd->isRelated()=%d mmd->isFriend()=%d mmd->isFunction()=%d\n",
- // mmd->isRelated(),mmd->isFriend(),mmd->isFunction());
- LockingPtr<ArgumentList> mmdAl = mmd->argumentList();
- LockingPtr<ArgumentList> fmdAl = fmd->argumentList();
- if ((mmd->isFriend() || (mmd->isRelated() && mmd->isFunction())) &&
- matchArguments2(mmd->getOuterScope(), mmd->getFileDef(), mmdAl.pointer(),
- fmd->getOuterScope(), fmd->getFileDef(), fmdAl.pointer(),
- TRUE
- )
-
- ) // if the member is related and the arguments match then the
- // function is actually a friend.
- {
- mergeArguments(mmdAl.pointer(),fmdAl.pointer());
- if (!fmd->documentation().isEmpty())
- {
- mmd->setDocumentation(fmd->documentation(),fmd->docFile(),fmd->docLine());
- }
- else if (!mmd->documentation().isEmpty())
- {
- fmd->setDocumentation(mmd->documentation(),mmd->docFile(),mmd->docLine());
- }
- if (mmd->briefDescription().isEmpty() && !fmd->briefDescription().isEmpty())
- {
- mmd->setBriefDescription(fmd->briefDescription(),fmd->briefFile(),fmd->briefLine());
- }
- else if (!mmd->briefDescription().isEmpty() && !fmd->briefDescription().isEmpty())
- {
- fmd->setBriefDescription(mmd->briefDescription(),mmd->briefFile(),mmd->briefLine());
- }
- if (!fmd->inbodyDocumentation().isEmpty())
- {
- mmd->setInbodyDocumentation(fmd->inbodyDocumentation(),fmd->inbodyFile(),fmd->inbodyLine());
- }
- else if (!mmd->inbodyDocumentation().isEmpty())
- {
- fmd->setInbodyDocumentation(mmd->inbodyDocumentation(),mmd->inbodyFile(),mmd->inbodyLine());
- }
- //printf("body mmd %d fmd %d\n",mmd->getStartBodyLine(),fmd->getStartBodyLine());
- if (mmd->getStartBodyLine()==-1 && fmd->getStartBodyLine()!=-1)
- {
- mmd->setBodySegment(fmd->getStartBodyLine(),fmd->getEndBodyLine());
- mmd->setBodyDef(fmd->getBodyDef());
- //mmd->setBodyMember(fmd);
- }
- else if (mmd->getStartBodyLine()!=-1 && fmd->getStartBodyLine()==-1)
- {
- fmd->setBodySegment(mmd->getStartBodyLine(),mmd->getEndBodyLine());
- fmd->setBodyDef(mmd->getBodyDef());
- //fmd->setBodyMember(mmd);
- }
- mmd->setDocsForDefinition(fmd->isDocsForDefinition());
- mmd->enableCallGraph(mmd->hasCallGraph() || fmd->hasCallGraph());
- mmd->enableCallerGraph(mmd->hasCallerGraph() || fmd->hasCallerGraph());
- fmd->enableCallGraph(mmd->hasCallGraph() || fmd->hasCallGraph());
- fmd->enableCallerGraph(mmd->hasCallerGraph() || fmd->hasCallerGraph());
- }
- }
- }
- }
- }
- }
- //----------------------------------------------------------------------
- static void transferArgumentDocumentation(ArgumentList *decAl,ArgumentList *defAl)
- {
- if (decAl && defAl)
- {
- ArgumentListIterator decAli(*decAl);
- ArgumentListIterator defAli(*defAl);
- Argument *decA,*defA;
- for (decAli.toFirst(),defAli.toFirst();
- (decA=decAli.current()) && (defA=defAli.current());
- ++decAli,++defAli)
- {
- //printf("Argument decA->name=%s (doc=%s) defA->name=%s (doc=%s)\n",
- // decA->name.data(),decA->docs.data(),
- // defA->name.data(),defA->docs.data()
- // );
- if (decA->docs.isEmpty() && !defA->docs.isEmpty())
- {
- decA->docs = defA->docs.copy();
- }
- else if (defA->docs.isEmpty() && !decA->docs.isEmpty())
- {
- defA->docs = decA->docs.copy();
- }
- }
- }
- }
- static void transferFunctionDocumentation()
- {
- //printf("---- transferFunctionDocumentation()\n");
- // find matching function declaration and definitions.
- MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict);
- MemberName *mn;
- for (;(mn=mnli.current());++mnli)
- {
- //printf("memberName=%s count=%d\n",mn->memberName(),mn->count());
- MemberDef *mdef=0,*mdec=0;
- MemberNameIterator mni1(*mn);
- /* find a matching function declaration and definition for this function */
- for (;(mdec=mni1.current());++mni1)
- {
- //printf("mdec=%s isPrototype()=%d\n",mdec->name().data(),mdec->isPrototype());
- if (mdec->isPrototype() ||
- (mdec->isVariable() && mdec->isExternal())
- )
- {
- MemberNameIterator mni2(*mn);
- for (;(mdef=mni2.current());++mni2)
- {
- if (
- (mdef->isFunction() && !mdef->isStatic() && !mdef->isPrototype()) ||
- (mdef->isVariable() && !mdef->isExternal() && !mdef->isStatic())
- )
- {
- //printf("mdef=(%p,%s) mdec=(%p,%s)\n",
- // mdef, mdef ? mdef->name().data() : "",
- // mdec, mdec ? mdec->name().data() : "");
- LockingPtr<ArgumentList> mdefAl = mdef->argumentList();
- LockingPtr<ArgumentList> mdecAl = mdec->argumentList();
- if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl.pointer(),
- mdec->getOuterScope(),mdec->getFileDef(),mdecAl.pointer(),
- TRUE
- )
- ) /* match found */
- {
- //printf("Found member %s: definition in %s (doc=`%s') and declaration in %s (doc=`%s')\n",
- // mn->memberName(),
- // mdef->getFileDef()->name().data(),mdef->documentation().data(),
- // mdec->getFileDef()->name().data(),mdec->documentation().data()
- // );
- // first merge argument documentation
- transferArgumentDocumentation(mdecAl.pointer(),mdefAl.pointer());
- /* copy documentation between function definition and declaration */
- if (!mdec->briefDescription().isEmpty())
- {
- mdef->setBriefDescription(mdec->briefDescription(),mdec->briefFile(),mdec->briefLine());
- }
- else if (!mdef->briefDescription().isEmpty())
- {
- mdec->setBriefDescription(mdef->briefDescription(),mdef->briefFile(),mdef->briefLine());
- }
- if (!mdef->documentation().isEmpty())
- {
- //printf("transfering docs mdef->mdec (%s->%s)\n",mdef->argsString(),mdec->argsString());
- mdec->setDocumentation(mdef->documentation(),mdef->docFile(),mdef->docLine());
- mdec->setDocsForDefinition(mdef->isDocsForDefinition());
- if (mdefAl!=0)
- {
- ArgumentList *mdefAlComb = new ArgumentList;
- stringToArgumentList(mdef->argsString(),mdefAlComb);
- transferArgumentDocumentation(mdefAl.pointer(),mdefAlComb);
- mdec->setArgumentList(mdefAlComb);
- }
- }
- else if (!mdec->documentation().isEmpty())
- {
- //printf("transfering docs mdec->mdef (%s->%s)\n",mdec->argsString(),mdef->argsString());
- mdef->setDocumentation(mdec->documentation(),mdec->docFile(),mdec->docLine());
- mdef->setDocsForDefinition(mdec->isDocsForDefinition());
- if (mdecAl!=0)
- {
- ArgumentList *mdecAlComb = new ArgumentList;
- stringToArgumentList(mdec->argsString(),mdecAlComb);
- transferArgumentDocumentation(mdecAl.pointer(),mdecAlComb);
- mdef->setDeclArgumentList(mdecAlComb);
- }
- }
- if (!mdef->inbodyDocumentation().isEmpty())
- {
- mdec->setInbodyDocumentation(mdef->inbodyDocumentation(),mdef->inbodyFile(),mdef->inbodyLine());
- }
- else if (!mdec->inbodyDocumentation().isEmpty())
- {
- mdef->setInbodyDocumentation(mdec->inbodyDocumentation(),mdec->inbodyFile(),mdec->inbodyLine());
- }
- if (mdec->getStartBodyLine()!=-1 && mdef->getStartBodyLine()==-1)
- {
- //printf("body mdec->mdef %d-%d\n",mdec->getStartBodyLine(),mdef->getEndBodyLine());
- mdef->setBodySegment(mdec->getStartBodyLine(),mdec->getEndBodyLine());
- mdef->setBodyDef(mdec->getBodyDef());
- //mdef->setBodyMember(mdec);
- }
- else if (mdef->getStartBodyLine()!=-1 && mdec->getStartBodyLine()==-1)
- {
- //printf("body mdef->mdec %d-%d\n",mdef->getStartBodyLine(),mdec->getEndBodyLine());
- mdec->setBodySegment(mdef->getStartBodyLine(),mdef->getEndBodyLine());
- mdec->setBodyDef(mdef->getBodyDef());
- //mdec->setBodyMember(mdef);
- }
- mdec->mergeMemberSpecifiers(mdef->getMemberSpecifiers());
- mdef->mergeMemberSpecifiers(mdec->getMemberSpecifiers());
- // copy group info.
- if (mdec->getGroupDef()==0 && mdef->getGroupDef()!=0)
- {
- mdec->setGroupDef(mdef->getGroupDef(),
- mdef->getGroupPri(),
- mdef->docFile(),
- mdef->docLine(),
- mdef->hasDocumentation(),
- mdef
- );
- }
- else if (mdef->getGroupDef()==0 && mdec->getGroupDef()!=0)
- {
- mdef->setGroupDef(mdec->getGroupDef(),
- mdec->getGroupPri(),
- mdec->docFile(),
- mdec->docLine(),
- mdec->hasDocumentation(),
- mdec
- );
- }
- mdec->mergeRefItems(mdef);
- mdef->mergeRefItems(mdec);
- mdef->setMemberDeclaration(mdec);
- mdec->setMemberDefinition(mdef);
- mdef->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
- mdef->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
- mdec->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
- mdec->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
- }
- }
- }
- }
- }
- }
- }
- //----------------------------------------------------------------------
- static void transferFunctionReferences()
- {
- MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict);
- MemberName *mn;
- for (;(mn=mnli.current());++mnli)
- {
- MemberDef *md,*mdef=0,*mdec=0;
- MemberNameIterator mni(*mn);
- /* find a matching function declaration and definition for this function */
- for (;(md=mni.current());++mni)
- {
- if (md->isPrototype())
- mdec=md;
- else if (md->isVariable() && md->isExternal())
- mdec=md;
-
- if (md->isFunction() && !md->isStatic() && !md->isPrototype())
- mdef=md;
- else if (md->isVariable() && !md->isExternal() && !md->isStatic())
- mdef=md;
- }
- if (mdef && mdec)
- {
- LockingPtr<ArgumentList> mdefAl = mdef->argumentList();
- LockingPtr<ArgumentList> mdecAl = mdec->argumentList();
- if (
- matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl.pointer(),
- mdec->getOuterScope(),mdec->getFileDef(),mdecAl.pointer(),
- TRUE
- )
- ) /* match found */
- {
- LockingPtr<MemberSDict> defDict = mdef->getReferencesMembers();
- LockingPtr<MemberSDict> decDict = mdec->getReferencesMembers();
- if (defDict!=0)
- {
- MemberSDict::Iterator msdi(*defDict);
- MemberDef *rmd;
- for (msdi.toFirst();(rmd=msdi.current());++msdi)
- {
- if (decDict==0 || decDict->find(rmd->name())==0)
- {
- mdec->addSourceReferences(rmd);
- }
- }
- }
- if (decDict!=0)
- {
- MemberSDict::Iterator msdi(*decDict);
- MemberDef *rmd;
- for (msdi.toFirst();(rmd=msdi.current());++msdi)
- {
- if (defDict==0 || defDict->find(rmd->name())==0)
- {
- mdef->addSourceReferences(rmd);
- }
- }
- }
- defDict = mdef->getReferencedByMembers();
- decDict = mdec->getReferencedByMembers();
- if (defDict!=0)
- {
- MemberSDict::Iterator msdi(*defDict);
- MemberDef *rmd;
- for (msdi.toFirst();(rmd=msdi.current());++msdi)
- {
- if (decDict==0 || decDict->find(rmd->name())==0)
- {
- mdec->addSourceReferencedBy(rmd);
- }
- }
- }
- if (decDict!=0)
- {
- MemberSDict::Iterator msdi(*decDict);
- MemberDef *rmd;
- for (msdi.toFirst();(rmd=msdi.current());++msdi)
- {
- if (defDict==0 || defDict->find(rmd->name())==0)
- {
- mdef->addSourceReferencedBy(rmd);
- }
- }
- }
- }
- }
- }
- }
- //----------------------------------------------------------------------
- static void transferRelatedFunctionDocumentation()
- {
- // find match between function declaration and definition for
- // related functions
- MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict);
- MemberName *mn;
- for (mnli.toFirst();(mn=mnli.current());++mnli)
- {
- MemberDef *md;
- MemberNameIterator mni(*mn);
- /* find a matching function declaration and definition for this function */
- for (mni.toFirst();(md=mni.current());++mni) // for each global function
- {
- //printf(" Function `%s'\n",md->name().data());
- MemberName *rmn;
- if ((rmn=Doxygen::memberNameSDict->find(md->name()))) // check if there is a member with the same name
- {
- //printf(" Member name found\n");
- MemberDef *rmd;
- MemberNameIterator rmni(*rmn);
- for (rmni.toFirst();(rmd=rmni.current());++rmni) // for each member with the same name
- {
- LockingPtr<ArgumentList> mdAl = md->argumentList();
- LockingPtr<ArgumentList> rmdAl = rmd->argumentList();
- //printf(" Member found: related=`%d'\n",rmd->isRelated());
- if ((rmd->isRelated() || rmd->isForeign()) && // related function
- matchArguments2( md->getOuterScope(), md->getFileDef(), mdAl.pointer(),
- rmd->getOuterScope(),rmd->getFileDef(),rmdAl.pointer(),
- TRUE
- )
- )
- {
- //printf(" Found related member `%s'\n",md->name().data());
- if (rmd->relatedAlso())
- md->setRelatedAlso(rmd->relatedAlso());
- else if (rmd->isForeign())
- md->makeForeign();
- else
- md->makeRelated();
- }
- }
- }
- }
- }
- }
- //----------------------------------------------------------------------
- /*! make a dictionary of all template arguments of class cd
- * that are part of the base class name.
- * Example: A template class A with template arguments <R,S,T>
- * that inherits from B<T,T,S> will have T and S in the dictionary.
- */
- static QDict<int> *getTemplateArgumentsInName(ArgumentList *templateArguments,const QCString &name)
- {
- QDict<int> *templateNames = new QDict<int>(17);
- templateNames->setAutoDelete(TRUE);
- static QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*");
- if (templateArguments)
- {
- ArgumentListIterator ali(*templateArguments);
- Argument *arg;
- int count=0;
- for (ali.toFirst();(arg=ali.current());++ali,count++)
- {
- int i,p=0,l;
- while ((i=re.match(name,p,&l))!=-1)
- {
- QCString n = name.mid(i,l);
- if (n==arg->name)
- {
- if (templateNames->find(n)==0)
- {
- templateNames->insert(n,new int(count));
- }
- }
- p=i+l;
- }
- }
- }
- return templateNames;
- }
- /*! Searches a class from within \a context and \a cd and returns its
- * definition if found (otherwise 0 is returned).
- */
- static ClassDef *findClassWithinClassContext(Definition *context,ClassDef *cd,const QCString &name)
- {
- FileDef *fd=cd->getFileDef();
- ClassDef *result=0;
- if (context && cd!=context)
- {
- result = getResolvedClass(context,0,name,0,0,TRUE,TRUE);
- }
- if (result==0)
- {
- result = getResolvedClass(cd,fd,name,0,0,TRUE,TRUE);
- }
- //printf("** Trying to find %s within context %s class %s result=%s lookup=%p\n",
- // name.data(),
- // context ? context->name().data() : "<none>",
- // cd ? cd->name().data() : "<none>",
- // result ? result->name().data() : "<none>",
- // Doxygen::classSDict.find(name)
- // );
- return result;
- }
- enum FindBaseClassRelation_Mode
- {
- TemplateInstances,
- DocumentedOnly,
- Undocumented
- };
- static bool findClassRelation(
- EntryNav *rootNav,
- Definition *context,
- ClassDef *cd,
- BaseInfo *bi,
- QDict<int> *templateNames,
- /*bool insertUndocumented*/
- FindBaseClassRelation_Mode mode,
- bool isArtificial
- );
- static void findUsedClassesForClass(EntryNav *rootNav,
- Definition *context,
- ClassDef *masterCd,
- ClassDef *instanceCd,
- bool isArtificial,
- ArgumentList *actualArgs=0,
- QDict<int> *templateNames=0
- )
- {
- masterCd->visited=TRUE;
- ArgumentList *formalArgs = masterCd->templateArguments();
- if (masterCd->memberNameInfoSDict())
- {
- MemberNameInfoSDict::Iterator mnili(*masterCd->memberNameInfoSDict());
- MemberNameInfo *mni;
- for (;(mni=mnili.current());++mnili)
- {
- MemberNameInfoIterator mnii(*mni);
- MemberInfo *mi;
- for (mnii.toFirst();(mi=mnii.current());++mnii)
- {
- MemberDef *md=mi->memberDef;
- if (md->isVariable()) // for each member variable in this class
- {
- //printf(" Found variable %s in class %s\n",md->name().data(),masterCd->name().data());
- QCString type=removeRedundantWhiteSpace(md->typeString());
- QCString typedefValue = resolveTypeDef(masterCd,type);
- if (!typedefValue.isEmpty())
- {
- type = typedefValue;
- }
- int pos=0;
- QCString usedClassName;
- QCString templSpec;
- bool found=FALSE;
- // the type can contain template variables, replace them if present
- if (actualArgs)
- {
- type = substituteTemplateArgumentsInString(type,formalArgs,actualArgs);
- }
- //printf(" template substitution gives=%s\n",type.data());
- while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec)!=-1)
- {
- // find the type (if any) that matches usedClassName
- ClassDef *typeCd = getResolvedClass(masterCd,
- masterCd->getFileDef(),
- usedClassName,
- 0,0,
- FALSE,TRUE
- );
- //printf("====> usedClassName=%s -> typeCd=%s\n",
- // usedClassName.data(),typeCd?typeCd->name().data():"<none>");
- if (typeCd)
- {
- usedClassName = typeCd->name();
- }
- int sp=usedClassName.find('<');
- if (sp==-1) sp=0;
- int si=usedClassName.findRev("::",sp);
- if (si!=-1)
- {
- // replace any namespace aliases
- replaceNamespaceAliases(usedClassName,si);
- }
- // add any template arguments to the class
- QCString usedName = removeRedundantWhiteSpace(usedClassName+templSpec);
- //printf(" usedName=%s\n",usedName.data());
- bool delTempNames=FALSE;
- if (templateNames==0)
- {
- templateNames = getTemplateArgumentsInName(formalArgs,usedName);
- delTempNames=TRUE;
- }
- BaseInfo bi(usedName,Public,Normal);
- findClassRelation(rootNav,context,instanceCd,&bi,templateNames,TemplateInstances,isArtificial);
- if (masterCd->templateArguments())
- {
- ArgumentListIterator ali(*masterCd->templateArguments());
- Argument *arg;
- int count=0;
- for (ali.toFirst();(arg=ali.current());++ali,++count)
- {
- if (arg->name==usedName) // type is a template argument
- {
- found=TRUE;
- Debug::print(Debug::Classes,0," New used class `%s'\n", usedName.data());
- ClassDef *usedCd = Doxygen::hiddenClasses->find(usedName);
- if (usedCd==0)
- {
- usedCd = new ClassDef(
- masterCd->getDefFileName(),masterCd->getDefLine(),
- usedName,ClassDef::Class);
- //printf("making %s a template argument!!!\n",usedCd->name().data());
- usedCd->makeTemplateArgument();
- usedCd->setUsedOnly(TRUE);
- Doxygen::hiddenClasses->append(usedName,usedCd);
- }
- if (usedCd)
- {
- if (isArtificial) usedCd->setArtificial(TRUE);
- Debug::print(Debug::Classes,0," Adding used class `%s' (1)\n", usedCd->name().data());
- instanceCd->addUsedClass(usedCd,md->name());
- usedCd->addUsedByClass(instanceCd,md->name());
- }
- }
- }
- }
- if (!found)
- {
- ClassDef *usedCd=findClassWithinClassContext(context,masterCd,usedName);
- //printf("Looking for used class %s: result=%s master=%s\n",
- // usedName.data(),usedCd?usedCd->name().data():"<none>",masterCd?masterCd->name().data():"<none>");
- if (usedCd)
- {
- found=TRUE;
- Debug::print(Debug::Classes,0," Adding used class `%s' (2)\n", usedCd->name().data());
- instanceCd->addUsedClass(usedCd,md->name()); // class exists
- usedCd->addUsedByClass(instanceCd,md->name());
- }
- }
- if (delTempNames)
- {
- delete templateNames;
- templateNames=0;
- }
- }
- if (!found && !type.isEmpty()) // used class is not documented in any scope
- {
- ClassDef *usedCd = Doxygen::hiddenClasses->find(type);
- if (usedCd==0 && !Config_getBool("HIDE_UNDOC_RELATIONS"))
- {
- if (type.right(2)=="(*") // type is a function pointer
- {
- type+=md->argsString();
- }
- Debug::print(Debug::Classes,0," New undocumented used class `%s'\n", type.data());
- usedCd = new ClassDef(
- masterCd->getDefFileName(),masterCd->getDefLine(),
- type,ClassDef::Class);
- usedCd->setUsedOnly(TRUE);
- Doxygen::hiddenClasses->append(type,usedCd);
- }
- if (usedCd)
- {
- if (isArtificial) usedCd->setArtificial(TRUE);
- Debug::print(Debug::Classes,0," Adding used class `%s' (3)\n", usedCd->name().data());
- instanceCd->addUsedClass(usedCd,md->name());
- usedCd->addUsedByClass(instanceCd,md->name());
- }
- }
- }
- }
- }
- }
- else
- {
- //printf("no members for class %s (%p)\n",masterCd->name().data(),masterCd);
- }
- }
- static void findBaseClassesForClass(
- EntryNav *rootNav,
- Definition *context,
- ClassDef *masterCd,
- ClassDef *instanceCd,
- FindBaseClassRelation_Mode mode,
- bool isArtificial,
- ArgumentList *actualArgs=0,
- QDict<int> *templateNames=0
- )
- {
- Entry *root = rootNav->entry();
- //if (masterCd->visited) return;
- masterCd->visited=TRUE;
- // The base class could ofcouse also be a non-nested class
- ArgumentList *formalArgs = masterCd->templateArguments();
- QListIterator<BaseInfo> bii(*root->extends);
- BaseInfo *bi=0;
- for (bii.toFirst();(bi=bii.current());++bii)
- {
- //printf("masterCd=%s bi->name='%s' #actualArgs=%d\n",
- // masterCd->localName().data(),bi->name.data(),actualArgs?(int)actualArgs->count():-1);
- bool delTempNames=FALSE;
- if (templateNames==0)
- {
- templateNames = getTemplateArgumentsInName(formalArgs,bi->name);
- delTempNames=TRUE;
- }
- BaseInfo tbi(bi->name,bi->prot,bi->virt);
- if (actualArgs) // substitute the formal template arguments of the base class
- {
- tbi.name = substituteTemplateArgumentsInString(bi->name,formalArgs,actualArgs);
- }
- //printf("bi->name=%s tbi.name=%s\n",bi->name.data(),tbi.name.data());
- if (mode==DocumentedOnly)
- {
- // find a documented base class in the correct scope
- if (!findClassRelation(rootNav,context,instanceCd,&tbi,templateNames,DocumentedOnly,isArtificial))
- {
- if (!Config_getBool("HIDE_UNDOC_RELATIONS"))
- {
- // no documented base class -> try to find an undocumented one
- findClassRelation(rootNav,context,instanceCd,&tbi,templateNames,Undocumented,isArtificial);
- }
- }
- }
- else if (mode==TemplateInstances)
- {
- findClassRelation(rootNav,context,instanceCd,&tbi,templateNames,TemplateInstances,isArtificial);
- }
- if (delTempNames)
- {
- delete templateNames;
- templateNames=0;
- }
- }
- }
- //----------------------------------------------------------------------
- static bool findTemplateInstanceRelation(Entry *root,
- Definition *context,
- ClassDef *templateClass,const QCString &templSpec,
- QDict<int> *templateNames,
- bool isArtificial)
- {
- Debug::print(Debug::Classes,0," derived from template %s with parameters %s\n",
- templateClass->name().data(),templSpec.data());
- //printf("findTemplateInstanceRelation(base=%s templSpec=%s templateNames=",
- // templateClass->name().data(),templSpec.data());
- //if (templateNames)
- //{
- // QDictIterator<int> qdi(*templateNames);
- // int *tempArgIndex;
- // for (;(tempArgIndex=qdi.current());++qdi)
- // {
- // printf("(%s->%d) ",qdi.currentKey().data(),*tempArgIndex);
- // }
- //}
- //printf("\n");
-
- bool existingClass = (templSpec ==
- tempArgListToString(templateClass->templateArguments())
- );
- if (existingClass) return TRUE;
- bool freshInstance=FALSE;
- ClassDef *instanceClass = templateClass->insertTemplateInstance(
- root->fileName,root->startLine,templSpec,freshInstance);
- if (isArtificial) instanceClass->setArtificial(TRUE);
- instanceClass->setIsObjectiveC(root->objc);
- if (freshInstance)
- {
- Debug::print(Debug::Classes,0," found fresh instance '%s'!\n",instanceClass->name().data());
- Doxygen::classSDict->append(instanceClass->name(),instanceClass);
- instanceClass->setTemplateBaseClassNames(templateNames);
- // search for new template instances caused by base classes of
- // instanceClass
- EntryNav *templateRootNav = g_classEntries.find(templateClass->name());
- if (templateRootNav)
- {
- bool unloadNeeded=FALSE;
- Entry *templateRoot = templateRootNav->entry();
- if (templateRoot==0) // not yet loaded
- {
- templateRootNav->loadEntry(g_storage);
- templateRoot = templateRootNav->entry();
- ASSERT(templateRoot!=0); // now it should really be loaded
- unloadNeeded=TRUE;
- }
- Debug::print(Debug::Classes,0," template root found %s templSpec=%s!\n",
- templateRoot->name.data(),templSpec.data());
- ArgumentList *templArgs = new ArgumentList;
- stringToArgumentList(templSpec,templArgs);
- findBaseClassesForClass(templateRootNav,context,templateClass,instanceClass,
- TemplateInstances,isArtificial,templArgs,templateNames);
- findUsedClassesForClass(templateRootNav,context,templateClass,instanceClass,
- isArtificial,templArgs,templateNames);
- delete templArgs;
- if (unloadNeeded) // still cleanup to do
- {
- templateRootNav->releaseEntry();
- }
- }
- else
- {
- Debug::print(Debug::Classes,0," no template root entry found!\n");
- // TODO: what happened if we get here?
- }
- //Debug::print(Debug::Classes,0," Template instance %s : \n",instanceClass->name().data());
- //ArgumentList *tl = templateClass->templateArguments();
- }
- else
- {
- Debug::print(Debug::Classes,0," instance already exists!\n");
- }
- return TRUE;
- }
- static bool isRecursiveBaseClass(const QCString &scope,const QCString &name)
- {
- QCString n=name;
- int index=n.find('<');
- if (index!=-1)
- {
- n=n.left(index);
- }
- bool result = rightScopeMatch(scope,n);
- return result;
- }
- /*! Searches for the end of a template in prototype \a s starting from
- * character position \a startPos. If the end was found the position
- * of the closing \> is returned, otherwise -1 is returned.
- *
- * Handles exotic cases such as
- * \code
- * Class<(id<0)>
- * Class<bits<<2>
- * Class<"<">
- * Class<'<'>
- * Class<(")<")>
- * \endcode
- */
- static int findEndOfTemplate(const QCString &s,int startPos)
- {
- // locate end of template
- int e=startPos;
- int brCount=1;
- int roundCount=0;
- int len = s.length();
- bool insideString=FALSE;
- bool insideChar=FALSE;
- char pc = 0;
- while (e<len && brCount!=0)
- {
- char c=s.at(e);
- switch(c)
- {
- case '<':
- if (!insideString && !insideChar)
- {
- if (e<len-1 && s.at(e+1)=='<')
- e++;
- else if (roundCount==0)
- brCount++;
- }
- break;
- case '>':
- if (!insideString && !insideChar)
- {
- if (e<len-1 && s.at(e+1)=='>')
- e++;
- else if (roundCount==0)
- brCount--;
- }
- break;
- case '(':
- if (!insideString && !insideChar)
- roundCount++;
- break;
- case ')':
- if (!insideString && !insideChar)
- roundCount--;
- break;
- case '"':
- if (!insideChar)
- {
- if (insideString && pc!='\\')
- insideString=FALSE;
- else
- insideString=TRUE;
- }
- break;
- case '\'':
- if (!insideString)
- {
- if (insideChar && pc!='\\')
- insideChar=FALSE;
- else
- insideChar=TRUE;
- }
- break;
- }
- pc = c;
- e++;
- }
- return brCount==0 ? e : -1;
- }
- static bool findClassRelation(
- EntryNav *rootNav,
- Definition *context,
- ClassDef *cd,
- BaseInfo *bi,
- QDict<int> *templateNames,
- FindBaseClassRelation_Mode mode,
- bool isArtificial
- )
- {
- //printf("findClassRelation(class=%s base=%s templateNames=",
- // cd->name().data(),bi->name.data());
- //if (templateNames)
- //{
- // QDictIterator<int> qdi(*templateNames);
- // int *tempArgIndex;
- // for (;(tempArgIndex=qdi.current());++qdi)
- // {
- // printf("(%s->%d) ",qdi.currentKey(),*tempArgIndex);
- // }
- //}
- //printf("\n");
- Entry *root = rootNav->entry();
- QCString biName=bi->name;
- bool explicitGlobalScope=FALSE;
- //printf("findClassRelation: biName=`%s'\n",biName.data());
- if (biName.left(2)=="::") // explicit global scope
- {
- biName=biName.right(biName.length()-2);
- explicitGlobalScope=TRUE;
- }
- EntryNav *parentNode=rootNav->parent();
- bool lastParent=FALSE;
- do // for each parent scope, starting with the largest scope
- // (in case of nested classes)
- {
- QCString scopeName= parentNode ? parentNode->name().data() : "";
- int scopeOffset=explicitGlobalScope ? 0 : scopeName.length();
- do // try all parent scope prefixes, starting with the largest scope
- {
- //printf("scopePrefix=`%s' biName=`%s'\n",
- // scopeName.left(scopeOffset).data(),biName.data());
- QCString baseClassName=biName;
- if (scopeOffset>0)
- {
- baseClassName.prepend(scopeName.left(scopeOffset)+"::");
- }
- //QCString stripped;
- //baseClassName=stripTemplateSpecifiersFromScope
- // (removeRedundantWhiteSpace(baseClassName),TRUE,
- // &stripped);
- MemberDef *baseClassTypeDef=0;
- QCString templSpec;
- ClassDef *baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
- cd->getFileDef(),
- baseClassName,
- &baseClassTypeDef,
- &templSpec,
- mode==Undocumented,
- TRUE
- );
- //printf("baseClassName=%s baseClass=%p cd=%p explicitGlobalScope=%d\n",
- // baseClassName.data(),baseClass,cd,explicitGlobalScope);
- //printf(" scope=`%s' baseClassName=`%s' baseClass=%s templSpec=%s\n",
- // cd ? cd->name().data():"<none>",
- // baseClassName.data(),
- // baseClass?baseClass->name().data():"<none>",
- // templSpec.data()
- // );
- //if (baseClassName.left(root->name.length())!=root->name ||
- // baseClassName.at(root->name.length())!='<'
- // ) // Check for base class with the same name.
- // // If found then look in the outer scope for a match
- // // and prevent recursion.
- if (!isRecursiveBaseClass(rootNav->name(),baseClassName) || explicitGlobalScope)
- {
- Debug::print(
- Debug::Classes,0," class relation %s inherited/used by %s found (%s and %s) templSpec='%s'\n",
- baseClassName.data(),
- rootNav->name().data(),
- (bi->prot==Private)?"private":((bi->prot==Protected)?"protected":"public"),
- (bi->virt==Normal)?"normal":"virtual",
- templSpec.data()
- );
- int i=baseClassName.find('<');
- int si=baseClassName.findRev("::",i==-1 ? baseClassName.length() : i);
- if (si==-1) si=0;
- if (baseClass==0 && i!=-1)
- // base class has template specifiers
- {
- // TODO: here we should try to find the correct template specialization
- // but for now, we only look for the unspecializated base class.
- int e=findEndOfTemplate(baseClassName,i+1);
- //printf("baseClass==0 i=%d e=%d\n",i,e);
- if (e!=-1) // end of template was found at e
- {
- templSpec=removeRedundantWhiteSpace(baseClassName.mid(i,e-i));
- baseClassName=baseClassName.left(i)+baseClassName.right(baseClassName.length()-e);
- baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
- cd->getFileDef(),
- baseClassName,
- &baseClassTypeDef,
- 0, //&templSpec,
- mode==Undocumented,
- TRUE
- );
- //printf("baseClass=%p -> baseClass=%s templSpec=%s\n",
- // baseClass,baseClassName.data(),templSpec.data());
- }
- }
- else if (baseClass && !templSpec.isEmpty()) // we have a known class, but also
- // know it is a template, so see if
- // we can also link to the explicit
- // instance (for instance if a class
- // derived from a template argument)
- {
- //printf("baseClass=%p templSpec=%s\n",baseClass,templSpec.data());
- ClassDef *templClass=getClass(baseClass->name()+templSpec);
- if (templClass)
- {
- // use the template instance instead of the template base.
- baseClass = templClass;
- templSpec.resize(0);
- }
- }
- //printf("cd=%p baseClass=%p\n",cd,baseClass);
- bool found=baseClass!=0 && (baseClass!=cd || mode==TemplateInstances);
- //printf("1. found=%d\n",found);
- if (!found && si!=-1)
- {
- QCString tmpTemplSpec;
- // replace any namespace aliases
- replaceNamespaceAliases(baseClassName,si);
- baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
- cd->getFileDef(),
- baseClassName,
- &baseClassTypeDef,
- &tmpTemplSpec,
- mode==Undocumented,
- TRUE
- );
- found=baseClass!=0 && baseClass!=cd;
- if (found) templSpec = tmpTemplSpec;
- }
- //printf("2. found=%d\n",found);
-
- //printf("root->name=%s biName=%s baseClassName=%s\n",
- // root->name.data(),biName.data(),baseClassName.data());
- if (!found)
- {
- baseClass=findClassWithinClassContext(context,cd,baseClassName);
- //printf("findClassWithinClassContext(%s,%s)=%p\n",
- // cd->name().data(),baseClassName.data(),baseClass);
- found = baseClass!=0 && baseClass!=cd;
- }
- bool isATemplateArgument = templateNames!=0 && templateNames->find(biName)!=0;
- // make templSpec canonical
- // Warning: the following line doesn't work for Mixin classes (see bug 560623)
- // templSpec = getCanonicalTemplateSpec(cd, cd->getFileDef(), templSpec);
- //printf("3. found=%d\n",found);
- if (found)
- {
- Debug::print(Debug::Classes,0," Documented base class `%s' templSpec=%s\n",biName.data(),templSpec.isEmpty()?"":templSpec.data());
- // add base class to this class
- // if templSpec is not empty then we should "instantiate"
- // the template baseClass. A new ClassDef should be created
- // to represent the instance. To be able to add the (instantiated)
- // members and documentation of a template class
- // (inserted in that template class at a later stage),
- // the template should know about its instances.
- // the instantiation process, should be done in a recursive way,
- // since instantiating a template may introduce new inheritance
- // relations.
- if (!templSpec.isEmpty() && mode==TemplateInstances)
- {
- // if baseClass is actually a typedef then we should not
- // instantiate it, since typedefs are in a different namespace
- // see bug531637 for an example where this would otherwise hang
- // doxygen
- if (baseClassTypeDef==0)
- {
- //printf(" => findTemplateInstanceRelation: %p\n",baseClassTypeDef);
- findTemplateInstanceRelation(root,context,baseClass,templSpec,templateNames,isArtificial);
- }
- }
- else if (mode==DocumentedOnly || mode==Undocumented)
- {
- //printf(" => insert base class\n");
- QCString usedName;
- if (baseClassTypeDef)
- {
- usedName=biName;
- //printf("***** usedName=%s templSpec=%s\n",usedName.data(),templSpec.data());
- }
- if (Config_getBool("SIP_SUPPORT")) bi->prot=Public;
- cd->insertBaseClass(baseClass,usedName,bi->prot,bi->virt,templSpec);
- // add this class as super class to the base class
- baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec);
- }
- return TRUE;
- }
- else if (mode==Undocumented && (scopeOffset==0 || isATemplateArgument))
- {
- Debug::print(Debug::Classes,0,
- " New undocumented base class `%s' baseClassName=%s\n",
- biName.data(),baseClassName.data()
- );
- baseClass=0;
- if (isATemplateArgument)
- {
- baseClass=Doxygen::hiddenClasses->find(baseClassName);
- if (baseClass==0)
- {
- baseClass=new ClassDef(root->fileName,root->startLine,
- baseClassName,ClassDef::Class);
- Doxygen::hiddenClasses->append(baseClassName,baseClass);
- if (isArtificial) baseClass->setArtificial(TRUE);
- }
- }
- else
- {
- baseClass=Doxygen::classSDict->find(baseClassName);
- //printf("*** classDDict->find(%s)=%p biName=%s templSpec=%s\n",
- // baseClassName.data(),baseClass,biName.data(),templSpec.data());
- if (baseClass==0)
- {
- baseClass=new ClassDef(root->fileName,root->startLine,
- baseClassName,ClassDef::Class);
- Doxygen::classSDict->append(baseClassName,baseClass);
- if (isArtificial) baseClass->setArtificial(TRUE);
- }
- }
- // add base class to this class
- cd->insertBaseClass(baseClass,biName,bi->prot,bi->virt,templSpec);
- // add this class as super class to the base class
- baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec);
- // the undocumented base was found in this file
- baseClass->insertUsedFile(root->fileName);
- baseClass->setOuterScope(Doxygen::globalScope);
- return TRUE;
- }
- else
- {
- Debug::print(Debug::Classes,0," Base class `%s' not found\n",biName.data());
- }
- }
- else
- {
- if (mode!=TemplateInstances)
- {
- warn(root->fileName,root->startLine,
- "Detected potential recursive class relation "
- "between class %s and base class %s!\n",
- root->name.data(),baseClassName.data()
- );
- }
- // for mode==TemplateInstance this case is quite common and
- // indicates a relation between a template class and a template
- // instance with the same name.
- }
- if (scopeOffset==0)
- {
- scopeOffset=-1;
- }
- else if ((scopeOffset=scopeName.findRev("::",scopeOffset-1))==-1)
- {
- scopeOffset=0;
- }
- //printf("new scopeOffset=`%d'",scopeOffset);
- } while (scopeOffset>=0);
- if (parentNode==0)
- {
- lastParent=TRUE;
- }
- else
- {
- parentNode=parentNode->parent();
- }
- } while (lastParent);
- return FALSE;
- }
- //----------------------------------------------------------------------
- // Computes the base and super classes for each class in the tree
- static bool isClassSection(EntryNav *rootNav)
- {
- if ( !rootNav->name().isEmpty() )
- {
- if (rootNav->section() & Entry::COMPOUND_MASK)
- // is it a compound (class, struct, union, interface ...)
- {
- return TRUE;
- }
- else if (rootNav->section() & Entry::COMPOUNDDOC_MASK)
- // is it a documentation block with inheritance info.
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- bool extends = root->extends->count()>0;
- rootNav->releaseEntry();
- if (extends) return TRUE;
- }
- }
- return FALSE;
- }
- /*! Builds a dictionary of all entry nodes in the tree starting with \a root
- */
- static void findClassEntries(EntryNav *rootNav)
- {
- if (isClassSection(rootNav))
- {
- g_classEntries.insert(rootNav->name(),rootNav);
- }
- RECURSE_ENTRYTREE(findClassEntries,rootNav);
- }
- /*! Using the dictionary build by findClassEntries(), this
- * function will look for additional template specialization that
- * exists as inheritance relations only. These instances will be
- * added to the template they are derived from.
- */
- static void findInheritedTemplateInstances()
- {
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
- QDictIterator<EntryNav> edi(g_classEntries);
- EntryNav *rootNav;
- for (;(rootNav=edi.current());++edi)
- {
- ClassDef *cd;
- // strip any annonymous scopes first
- QCString bName=stripAnonymousNamespaceScope(rootNav->name());
- bName=stripTemplateSpecifiersFromScope(bName);
- Debug::print(Debug::Classes,0," Inheritance: Class %s : \n",bName.data());
- if ((cd=getClass(bName)))
- {
- rootNav->loadEntry(g_storage);
- //printf("Class %s %d\n",cd->name().data(),root->extends->count());
- findBaseClassesForClass(rootNav,cd,cd,cd,TemplateInstances,FALSE);
- rootNav->releaseEntry();
- }
- }
- }
- static void findUsedTemplateInstances()
- {
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
- QDictIterator<EntryNav> edi(g_classEntries);
- EntryNav *rootNav;
- for (;(rootNav=edi.current());++edi)
- {
- ClassDef *cd;
- // strip any annonymous scopes first
- QCString bName=stripAnonymousNamespaceScope(rootNav->name());
- bName=stripTemplateSpecifiersFromScope(bName);
- Debug::print(Debug::Classes,0," Usage: Class %s : \n",bName.data());
- if ((cd=getClass(bName)))
- {
- rootNav->loadEntry(g_storage);
- findUsedClassesForClass(rootNav,cd,cd,cd,TRUE);
- rootNav->releaseEntry();
- }
- }
- }
- static void computeClassRelations()
- {
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
- QDictIterator<EntryNav> edi(g_classEntries);
- EntryNav *rootNav;
- for (;(rootNav=edi.current());++edi)
- {
- ClassDef *cd;
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- // strip any annonymous scopes first
- QCString bName=stripAnonymousNamespaceScope(rootNav->name());
- bName=stripTemplateSpecifiersFromScope(bName);
- Debug::print(Debug::Classes,0," Relations: Class %s : \n",bName.data());
- if ((cd=getClass(bName)))
- {
- findBaseClassesForClass(rootNav,cd,cd,cd,DocumentedOnly,FALSE);
- }
- if ((cd==0 || (!cd->hasDocumentation() && !cd->isReference())) &&
- bName.right(2)!="::")
- {
- if (!root->name.isEmpty() && root->name.find('@')==-1 && // normal name
- (guessSection(root->fileName)==Entry::HEADER_SEC ||
- Config_getBool("EXTRACT_LOCAL_CLASSES")) && // not defined in source file
- (root->protection!=Private || Config_getBool("EXTRACT_PRIVATE")) && // hidden by protection
- !Config_getBool("HIDE_UNDOC_CLASSES") // undocumented class are visible
- )
- warn_undoc(
- root->fileName,root->startLine,
- "Warning: Compound %s is not documented.",
- root->name.data()
- );
- }
- rootNav->releaseEntry();
- }
- }
- static void computeTemplateClassRelations()
- {
- QDictIterator<EntryNav> edi(g_classEntries);
- EntryNav *rootNav;
- for (;(rootNav=edi.current());++edi)
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- QCString bName=stripAnonymousNamespaceScope(root->name);
- bName=stripTemplateSpecifiersFromScope(bName);
- ClassDef *cd=getClass(bName);
- // strip any annonymous scopes first
- QDict<ClassDef> *templInstances = 0;
- if (cd && (templInstances=cd->getTemplateInstances()))
- {
- Debug::print(Debug::Classes,0," Template class %s : \n",cd->name().data());
- QDictIterator<ClassDef> tdi(*templInstances);
- ClassDef *tcd;
- for (tdi.toFirst();(tcd=tdi.current());++tdi) // for each template instance
- {
- Debug::print(Debug::Classes,0," Template instance %s : \n",tcd->name().data());
- QCString templSpec = tdi.currentKey();
- ArgumentList *templArgs = new ArgumentList;
- stringToArgumentList(templSpec,templArgs);
- QList<BaseInfo> *baseList=root->extends;
- BaseInfo *bi=baseList->first();
- while (bi) // for each base class of the template
- {
- // check if the base class is a template argument
- BaseInfo tbi(bi->name,bi->prot,bi->virt);
- ArgumentList *tl = cd->templateArguments();
- if (tl)
- {
- QDict<int> *baseClassNames = tcd->getTemplateBaseClassNames();
- QDict<int> *templateNames = getTemplateArgumentsInName(tl,bi->name);
- // for each template name that we inherit from we need to
- // substitute the formal with the actual arguments
- QDict<int> *actualTemplateNames = new QDict<int>(17);
- actualTemplateNames->setAutoDelete(TRUE);
- QDictIterator<int> qdi(*templateNames);
- for (qdi.toFirst();qdi.current();++qdi)
- {
- int templIndex = *qdi.current();
- Argument *actArg = 0;
- if (templIndex<(int)templArgs->count())
- {
- actArg=templArgs->at(templIndex);
- }
- if (actArg!=0 &&
- baseClassNames!=0 &&
- baseClassNames->find(actArg->type)!=0 &&
- actualTemplateNames->find(actArg->type)==0
- )
- {
- actualTemplateNames->insert(actArg->type,new int(templIndex));
- }
- }
- delete templateNames;
-
- tbi.name = substituteTemplateArgumentsInString(bi->name,tl,templArgs);
- // find a documented base class in the correct scope
- if (!findClassRelation(rootNav,cd,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE))
- {
- // no documented base class -> try to find an undocumented one
- findClassRelation(rootNav,cd,tcd,&tbi,actualTemplateNames,Undocumented,FALSE);
- }
- delete actualTemplateNames;
- }
- bi=baseList->next();
- }
- delete templArgs;
- } // class has no base classes
- }
- rootNav->releaseEntry();
- }
- }
- //-----------------------------------------------------------------------
- // compute the references (anchors in HTML) for each function in the file
- static void computeMemberReferences()
- {
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd=0;
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- cd->computeAnchors();
- }
- FileName *fn=Doxygen::inputNameList->first();
- while (fn)
- {
- FileDef *fd=fn->first();
- while (fd)
- {
- fd->computeAnchors();
- fd=fn->next();
- }
- fn=Doxygen::inputNameList->next();
- }
- NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd=0;
- for (nli.toFirst();(nd=nli.current());++nli)
- {
- nd->computeAnchors();
- }
- GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
- for (gli.toFirst();(gd=gli.current());++gli)
- {
- gd->computeAnchors();
- }
- }
- //----------------------------------------------------------------------
- static void addListReferences()
- {
- MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
- MemberName *mn=0;
- for (mnli.toFirst();(mn=mnli.current());++mnli)
- {
- MemberNameIterator mni(*mn);
- MemberDef *md=0;
- for (mni.toFirst();(md=mni.current());++mni)
- {
- md->visited=FALSE;
- }
- }
- MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
- for (fnli.toFirst();(mn=fnli.current());++fnli)
- {
- MemberNameIterator mni(*mn);
- MemberDef *md=0;
- for (mni.toFirst();(md=mni.current());++mni)
- {
- md->visited=FALSE;
- }
- }
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd=0;
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- cd->addListReferences();
- }
- FileName *fn=Doxygen::inputNameList->first();
- while (fn)
- {
- FileDef *fd=fn->first();
- while (fd)
- {
- fd->addListReferences();
- fd=fn->next();
- }
- fn=Doxygen::inputNameList->next();
- }
- NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd=0;
- for (nli.toFirst();(nd=nli.current());++nli)
- {
- nd->addListReferences();
- }
- GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
- for (gli.toFirst();(gd=gli.current());++gli)
- {
- gd->addListReferences();
- }
- PageSDict::Iterator pdi(*Doxygen::pageSDict);
- PageDef *pd=0;
- for (pdi.toFirst();(pd=pdi.current());++pdi)
- {
- QCString name = pd->name();
- if (pd->getGroupDef())
- {
- name = pd->getGroupDef()->getOutputFileBase();
- }
- {
- LockingPtr< QList<ListItemInfo> > xrefItems = pd->xrefListItems();
- addRefItem(xrefItems.pointer(),
- name,
- theTranslator->trPage(TRUE,TRUE),
- name,pd->title(),0);
- }
- }
- DirSDict::Iterator ddi(*Doxygen::directories);
- DirDef *dd = 0;
- for (ddi.toFirst();(dd=ddi.current());++ddi)
- {
- QCString name = dd->getOutputFileBase();
- //if (dd->getGroupDef())
- //{
- // name = dd->getGroupDef()->getOutputFileBase();
- //}
- LockingPtr< QList<ListItemInfo> > xrefItems = dd->xrefListItems();
- addRefItem(xrefItems.pointer(),
- name,
- theTranslator->trDir(TRUE,TRUE),
- name,dd->displayName(),0);
- }
- }
- //----------------------------------------------------------------------
- static void generateXRefPages()
- {
- QDictIterator<RefList> di(*Doxygen::xrefLists);
- RefList *rl;
- for (di.toFirst();(rl=di.current());++di)
- {
- rl->generatePage();
- }
- }
- //----------------------------------------------------------------------
- // Copy the documentation in entry `root' to member definition `md' and
- // set the function declaration of the member to `funcDecl'. If the boolean
- // over_load is set the standard overload text is added.
- static void addMemberDocs(EntryNav *rootNav,
- MemberDef *md, const char *funcDecl,
- ArgumentList *al,
- bool over_load,
- NamespaceSDict *
- )
- {
- Entry *root = rootNav->entry();
- //printf("addMemberDocs: `%s'::`%s' `%s' funcDecl=`%s' mSpec=%d\n",
- // root->parent->name.data(),md->name().data(),md->argsString(),funcDecl,root->spec);
- QCString fDecl=funcDecl;
- // strip extern specifier
- fDecl.stripPrefix("extern ");
- md->setDefinition(fDecl);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- ClassDef *cd=md->getClassDef();
- NamespaceDef *nd=md->getNamespaceDef();
- QCString fullName;
- if (cd)
- fullName = cd->name();
- else if (nd)
- fullName = nd->name();
- if (!fullName.isEmpty()) fullName+="::";
- fullName+=md->name();
- FileDef *rfd=rootNav->fileDef();
- // TODO determine scope based on root not md
- Definition *rscope = md->getOuterScope();
- LockingPtr<ArgumentList> mdAl = md->argumentList();
- if (al)
- {
- //printf("merging arguments (1) docs=%d\n",root->doc.isEmpty());
- mergeArguments(mdAl.pointer(),al,!root->doc.isEmpty());
- }
- else
- {
- if (
- matchArguments2( md->getOuterScope(), md->getFileDef(), mdAl.pointer(),
- rscope,rfd,root->argList,
- TRUE
- )
- )
- {
- //printf("merging arguments (2)\n");
- mergeArguments(mdAl.pointer(),root->argList,!root->doc.isEmpty());
- }
- }
- if (over_load) // the \overload keyword was used
- {
- QCString doc=getOverloadDocs();
- if (!root->doc.isEmpty())
- {
- doc+="<p>";
- doc+=root->doc;
- }
- md->setDocumentation(doc,root->docFile,root->docLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setDocsForDefinition(!root->proto);
- }
- else
- {
- //printf("overwrite!\n");
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setDocsForDefinition(!root->proto);
- //printf("overwrite!\n");
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- if (
- (md->inbodyDocumentation().isEmpty() ||
- !rootNav->parent()->name().isEmpty()
- ) && !root->inbodyDocs.isEmpty()
- )
- {
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- }
- }
- //printf("initializer: '%s'(isEmpty=%d) '%s'(isEmpty=%d)\n",
- // md->initializer().data(),md->initializer().isEmpty(),
- // root->initializer.data(),root->initializer.isEmpty()
- // );
- if (md->initializer().isEmpty() && !root->initializer.isEmpty())
- {
- //printf("setInitializer\n");
- md->setInitializer(root->initializer);
- }
- md->setMaxInitLines(root->initLines);
- if (rfd)
- {
- if ((md->getStartBodyLine()==-1 && root->bodyLine!=-1)
- )
- {
- //printf("Setting new body segment [%d,%d]\n",root->bodyLine,root->endBodyLine);
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setBodyDef(rfd);
- }
- md->setRefItems(root->sli);
- }
- md->enableCallGraph(md->hasCallGraph() || root->callGraph);
- md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
- md->mergeMemberSpecifiers(root->spec);
- md->addSectionsToDefinition(root->anchors);
- addMemberToGroups(root,md);
- if (cd) cd->insertUsedFile(root->fileName);
- //printf("root->mGrpId=%d\n",root->mGrpId);
- if (root->mGrpId!=-1)
- {
- if (md->getMemberGroupId()!=-1)
- {
- if (md->getMemberGroupId()!=root->mGrpId)
- {
- warn(
- root->fileName,root->startLine,
- "Warning: member %s belongs to two different groups. The second "
- "one found here will be ignored.",
- md->name().data()
- );
- }
- }
- else // set group id
- {
- //printf("setMemberGroupId=%d md=%s\n",root->mGrpId,md->name().data());
- md->setMemberGroupId(root->mGrpId);
- }
- }
- }
- //----------------------------------------------------------------------
- // find a class definition given the scope name and (optionally) a
- // template list specifier
- static ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd,
- const char *scopeName)
- {
- ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE);
- return tcd;
- }
- //----------------------------------------------------------------------
- // Adds the documentation contained in `root' to a global function
- // with name `name' and argument list `args' (for overloading) and
- // function declaration `decl' to the corresponding member definition.
- static bool findGlobalMember(EntryNav *rootNav,
- const QCString &namespaceName,
- const char *name,
- const char *tempArg,
- const char *,
- const char *decl)
- {
- Entry *root = rootNav->entry();
- Debug::print(Debug::FindMembers,0,
- "2. findGlobalMember(namespace=%s,name=%s,tempArg=%s,decl=%s)\n",
- namespaceName.data(),name,tempArg,decl);
- QCString n=name;
- if (n.isEmpty()) return FALSE;
- if (n.find("::")!=-1) return FALSE; // skip undefined class members
- MemberName *mn=Doxygen::functionNameSDict->find(n+tempArg); // look in function dictionary
- if (mn==0)
- {
- mn=Doxygen::functionNameSDict->find(n); // try without template arguments
- }
- if (mn) // function name defined
- {
- Debug::print(Debug::FindMembers,0,"3. Found function scope\n");
- //int count=0;
- MemberNameIterator mni(*mn);
- MemberDef *md;
- bool found=FALSE;
- for (mni.toFirst();(md=mni.current()) && !found;++mni)
- {
- NamespaceDef *nd=md->getNamespaceDef();
- //printf("Namespace namespaceName=%s nd=%s\n",
- // namespaceName.data(),nd ? nd->name().data() : "<none>");
- FileDef *fd=rootNav->fileDef();
- //printf("File %s\n",fd ? fd->name().data() : "<none>");
- NamespaceSDict *nl = fd ? fd->getUsedNamespaces() : 0;
- //SDict<Definition> *cl = fd ? fd->getUsedClasses() : 0;
- //printf("NamespaceList %p\n",nl);
- // search in the list of namespaces that are imported via a
- // using declaration
- bool viaUsingDirective = nl && nd && nl->find(nd->qualifiedName())!=0;
- if ((namespaceName.isEmpty() && nd==0) || // not in a namespace
- (nd && nd->name()==namespaceName) || // or in the same namespace
- viaUsingDirective // member in `using' namespace
- )
- {
- Debug::print(Debug::FindMembers,0,"4. Try to add member `%s' to scope `%s'\n",
- md->name().data(),namespaceName.data());
- QCString nsName = nd ? nd->name().data() : "";
- NamespaceDef *rnd = 0;
- if (!namespaceName.isEmpty()) rnd = Doxygen::namespaceSDict->find(namespaceName);
- LockingPtr<ArgumentList> mdAl = md->argumentList();
- bool matching=
- (mdAl==0 && root->argList->count()==0) ||
- md->isVariable() || md->isTypedef() || /* in case of function pointers */
- matchArguments2(md->getOuterScope(),md->getFileDef(),mdAl.pointer(),
- rnd ? rnd : Doxygen::globalScope,fd,root->argList,
- FALSE);
- // for template members we need to check if the number of
- // template arguments is the same, otherwise we are dealing with
- // different functions.
- if (matching && root->tArgLists)
- {
- LockingPtr<ArgumentList> mdTempl = md->templateArguments();
- if (mdTempl!=0)
- {
- if (root->tArgLists->getLast()->count()!=mdTempl->count())
- {
- matching=FALSE;
- }
- }
- }
- //printf("%s<->%s\n",
- // argListToString(md->argumentList()).data(),
- // argListToString(root->argList).data());
- // for static members we also check if the comment block was found in
- // the same file. This is needed because static members with the same
- // name can be in different files. Thus it would be wrong to just
- // put the comment block at the first syntactically matching member.
- if (matching && md->isStatic() &&
- md->getDefFileName()!=root->fileName &&
- mn->count()>1)
- {
- matching = FALSE;
- }
- if (matching) // add docs to the member
- {
- Debug::print(Debug::FindMembers,0,"5. Match found\n");
- addMemberDocs(rootNav,md,decl,root->argList,FALSE);
- found=TRUE;
- }
- }
- }
- if (!found && root->relatesType != Duplicate) // no match
- {
- QCString fullFuncDecl=decl;
- if (root->argList) fullFuncDecl+=argListToString(root->argList,TRUE);
- warn(root->fileName,root->startLine,
- "Warning: no matching file member found for \n%s",fullFuncDecl.data());
- if (mn->count()>0)
- {
- warn_cont("Possible candidates:\n");
- for (mni.toFirst();(md=mni.current());++mni)
- {
- warn_cont(" %s\n",md->declaration());
- }
- }
- }
- }
- else // got docs for an undefined member!
- {
- if (root->type!="friend class" &&
- root->type!="friend struct" &&
- root->type!="friend union" &&
- (!Config_getBool("TYPEDEF_HIDES_STRUCT") ||
- root->type.find("typedef ")==-1)
- )
- {
- warn(root->fileName,root->startLine,
- "Warning: documented function `%s' was not declared or defined.",decl
- );
- }
- }
- return TRUE;
- }
- static bool isSpecialization(
- const QList<ArgumentList> &srcTempArgLists,
- const QList<ArgumentList> &dstTempArgLists
- )
- {
- QListIterator<ArgumentList> srclali(srcTempArgLists);
- QListIterator<ArgumentList> dstlali(dstTempArgLists);
- for (;srclali.current();++srclali,++dstlali)
- {
- ArgumentList *sal = srclali.current();
- ArgumentList *dal = dstlali.current();
- if (!(sal && dal && sal->count()==dal->count())) return TRUE;
- }
- return FALSE;
- }
- static QCString substituteTemplatesInString(
- const QList<ArgumentList> &srcTempArgLists,
- const QList<ArgumentList> &dstTempArgLists,
- ArgumentList *funcTempArgList, // can be used to match template specializations
- const QCString &src
- )
- {
- QCString dst;
- QRegExp re( "[A-Za-z_][A-Za-z_0-9]*");
- //printf("type=%s\n",sa->type.data());
- int i,p=0,l;
- while ((i=re.match(src,p,&l))!=-1) // for each word in srcType
- {
- bool found=FALSE;
- dst+=src.mid(p,i-p);
- QCString name=src.mid(i,l);
- QListIterator<ArgumentList> srclali(srcTempArgLists);
- QListIterator<ArgumentList> dstlali(dstTempArgLists);
- for (;srclali.current() && !found;++srclali,++dstlali)
- {
- ArgumentListIterator tsali(*srclali.current());
- ArgumentListIterator tdali(*dstlali.current());
- Argument *tsa =0,*tda=0, *fa=0;
- if (funcTempArgList)
- {
- fa=funcTempArgList->first();
- }
- for (tsali.toFirst();(tsa=tsali.current()) && !found;++tsali)
- {
- tda = tdali.current();
- //if (tda) printf("tsa=%s|%s tda=%s|%s\n",
- // tsa->type.data(),tsa->name.data(),
- // tda->type.data(),tda->name.data());
- if (name==tsa->name)
- {
- if (tda && tda->name.isEmpty())
- {
- int vc=0;
- if (tda->type.left(6)=="class ") vc=6;
- else if (tda->type.left(9)=="typename ") vc=9;
- if (vc>0) // convert type=="class T" to type=="class" name=="T"
- {
- tda->name = tda->type.mid(vc);
- tda->type = tda->type.left(vc-1);
- }
- }
- if (tda && !tda->name.isEmpty())
- {
- name=tda->name; // substitute
- found=TRUE;
- }
- else if (fa)
- {
- name=fa->type;
- found=TRUE;
- }
- }
- if (tda)
- ++tdali;
- else if (fa)
- fa=funcTempArgList->next();
- }
- //printf(" srcList='%s' dstList='%s faList='%s'\n",
- // argListToString(srclali.current()).data(),
- // argListToString(dstlali.current()).data(),
- // funcTempArgList ? argListToString(funcTempArgList).data() : "<none>");
- }
- dst+=name;
- p=i+l;
- }
- dst+=src.right(src.length()-p);
- //printf(" substituteTemplatesInString(%s)=%s\n",
- // src.data(),dst.data());
- return dst;
- }
- static void substituteTemplatesInArgList(
- const QList<ArgumentList> &srcTempArgLists,
- const QList<ArgumentList> &dstTempArgLists,
- ArgumentList *src,
- ArgumentList *dst,
- ArgumentList *funcTempArgs = 0
- )
- {
- ArgumentListIterator sali(*src);
- Argument *sa=0;
- Argument *da=dst->first();
- for (sali.toFirst();(sa=sali.current());++sali) // for each member argument
- {
- QCString dstType = substituteTemplatesInString(
- srcTempArgLists,dstTempArgLists,funcTempArgs,
- sa->type);
- QCString dstArray = substituteTemplatesInString(
- srcTempArgLists,dstTempArgLists,funcTempArgs,
- sa->array);
- if (da==0)
- {
- da=new Argument(*sa);
- dst->append(da);
- da->type=dstType;
- da->array=dstArray;
- da=0;
- }
- else
- {
- da->type=dstType;
- da->type=dstArray;
- da=dst->next();
- }
- }
- dst->constSpecifier = src->constSpecifier;
- dst->volatileSpecifier = src->volatileSpecifier;
- dst->pureSpecifier = src->pureSpecifier;
- //printf("substituteTemplatesInArgList: replacing %s with %s\n",
- // argListToString(src).data(),argListToString(dst).data()
- // );
- }
- /*! This function tries to find a member (in a documented class/file/namespace)
- * that corresponds to the function/variable declaration given in \a funcDecl.
- *
- * The boolean \a overloaded is used to specify whether or not a standard
- * overload documentation line should be generated.
- *
- * The boolean \a isFunc is a hint that indicates that this is a function
- * instead of a variable or typedef.
- */
- static void findMember(EntryNav *rootNav,
- QCString funcDecl,
- bool overloaded,
- bool isFunc
- )
- {
- Entry *root = rootNav->entry();
- Debug::print(Debug::FindMembers,0,
- "findMember(root=%p,funcDecl=`%s',related=`%s',overload=%d,"
- "isFunc=%d mGrpId=%d tArgList=%p (#=%d) "
- "spec=%d isObjC=%d\n",
- root,funcDecl.data(),root->relates.data(),overloaded,isFunc,root->mGrpId,
- root->tArgLists,root->tArgLists ? root->tArgLists->count() : 0,
- root->spec,root->objc
- );
- QCString scopeName;
- QCString className;
- QCString namespaceName;
- QCString funcType;
- QCString funcName;
- QCString funcArgs;
- QCString funcTempList;
- QCString exceptions;
- QCString funcSpec;
- bool isRelated=FALSE;
- bool isMemberOf=FALSE;
- bool isFriend=FALSE;
- bool done;
- do
- {
- done=TRUE;
- if (funcDecl.stripPrefix("friend ")) // treat friends as related members
- {
- isFriend=TRUE;
- done=FALSE;
- }
- if (funcDecl.stripPrefix("inline "))
- {
- root->spec|=Entry::Inline;
- done=FALSE;
- }
- if (funcDecl.stripPrefix("explicit "))
- {
- root->spec|=Entry::Explicit;
- done=FALSE;
- }
- if (funcDecl.stripPrefix("mutable "))
- {
- root->spec|=Entry::Mutable;
- done=FALSE;
- }
- if (funcDecl.stripPrefix("virtual "))
- {
- done=FALSE;
- }
- } while (!done);
- // delete any ; from the function declaration
- int sep;
- while ((sep=funcDecl.find(';'))!=-1)
- {
- funcDecl=(funcDecl.left(sep)+funcDecl.right(funcDecl.length()-sep-1)).stripWhiteSpace();
- }
-
- // make sure the first character is a space to simplify searching.
- if (!funcDecl.isEmpty() && funcDecl[0]!=' ') funcDecl.prepend(" ");
-
- // remove some superfluous spaces
- funcDecl= substitute(
- substitute(
- substitute(funcDecl,"~ ","~"),
- ":: ","::"
- ),
- " ::","::"
- ).stripWhiteSpace();
-
- //printf("funcDecl=`%s'\n",funcDecl.data());
- if (isFriend && funcDecl.left(6)=="class ")
- {
- //printf("friend class\n");
- funcDecl=funcDecl.right(funcDecl.length()-6);
- funcName = funcDecl.copy();
- }
- else if (isFriend && funcDecl.left(7)=="struct ")
- {
- funcDecl=funcDecl.right(funcDecl.length()-7);
- funcName = funcDecl.copy();
- }
- else
- {
- // extract information from the declarations
- parseFuncDecl(funcDecl,root->objc,scopeName,funcType,funcName,
- funcArgs,funcTempList,exceptions
- );
- }
- //printf("scopeName=`%s' funcType=`%s' funcName=`%s' funcArgs=`%s'\n",
- // scopeName.data(),funcType.data(),funcName.data(),funcArgs.data());
- // the class name can also be a namespace name, we decide this later.
- // if a related class name is specified and the class name could
- // not be derived from the function declaration, then use the
- // related field.
- //printf("scopeName=`%s' className=`%s' namespaceName=`%s'\n",
- // scopeName.data(),className.data(),namespaceName.data());
- if (!root->relates.isEmpty())
- { // related member, prefix user specified scope
- isRelated=TRUE;
- isMemberOf=(root->relatesType == MemberOf);
- if (getClass(root->relates)==0 && !scopeName.isEmpty())
- {
- scopeName= mergeScopes(scopeName,root->relates);
- }
- else
- {
- scopeName = root->relates;
- }
- }
- if (root->relates.isEmpty() && rootNav->parent() &&
- ((rootNav->parent()->section()&Entry::SCOPE_MASK) ||
- (rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
- ) &&
- !rootNav->parent()->name().isEmpty()) // see if we can combine scopeName
- // with the scope in which it was found
- {
- QCString joinedName = rootNav->parent()->name()+"::"+scopeName;
- if (!scopeName.isEmpty() &&
- (getClass(joinedName) || Doxygen::namespaceSDict->find(joinedName)))
- {
- scopeName = joinedName;
- }
- else
- {
- scopeName = mergeScopes(rootNav->parent()->name(),scopeName);
- }
- }
- else // see if we can prefix a namespace or class that is used from the file
- {
- FileDef *fd=rootNav->fileDef();
- if (fd)
- {
- NamespaceSDict *fnl = fd->getUsedNamespaces();
- if (fnl)
- {
- QCString joinedName;
- NamespaceDef *fnd;
- NamespaceSDict::Iterator nsdi(*fnl);
- for (nsdi.toFirst();(fnd=nsdi.current());++nsdi)
- {
- joinedName = fnd->name()+"::"+scopeName;
- if (Doxygen::namespaceSDict->find(joinedName))
- {
- scopeName=joinedName;
- break;
- }
- }
- }
- }
- }
- scopeName=stripTemplateSpecifiersFromScope(
- removeRedundantWhiteSpace(scopeName),FALSE,&funcSpec);
- // funcSpec contains the last template specifiers of the given scope.
- // If this method does not have any template arguments or they are
- // empty while funcSpec is not empty we assume this is a
- // specialization of a method. If not, we clear the funcSpec and treat
- // this as a normal method of a template class.
- if (!(root->tArgLists &&
- root->tArgLists->count()>0 &&
- root->tArgLists->first()->count()==0
- )
- )
- {
- funcSpec.resize(0);
- }
-
- // split scope into a namespace and a class part
- extractNamespaceName(scopeName,className,namespaceName,TRUE);
- //printf("scopeName=`%s' className=`%s' namespaceName=`%s'\n",
- // scopeName.data(),className.data(),namespaceName.data());
-
- //namespaceName=removeAnonymousScopes(namespaceName);
- if (namespaceName.find('@')!=-1) return; // skip stuff in anonymous namespace...
- //printf("namespaceName=`%s' className=`%s'\n",namespaceName.data(),className.data());
- // merge class and namespace scopes again
- scopeName.resize(0);
- if (!namespaceName.isEmpty())
- {
- if (className.isEmpty())
- {
- scopeName=namespaceName;
- }
- else if (!root->relates.isEmpty() || // relates command with explicit scope
- !getClass(className)) // class name only exists in a namespace
- {
- scopeName=namespaceName+"::"+className;
- }
- else
- {
- scopeName=className;
- }
- }
- else if (!className.isEmpty())
- {
- scopeName=className;
- }
- //printf("new scope=`%s'\n",scopeName.data());
- QCString tempScopeName=scopeName;
- ClassDef *cd=getClass(scopeName);
- if (cd)
- {
- if (root->tArgLists) root->tArgLists->first();
- if (funcSpec.isEmpty())
- {
- tempScopeName=cd->qualifiedNameWithTemplateParameters(root->tArgLists);
- }
- else
- {
- tempScopeName=scopeName+funcSpec;
- }
- }
- //printf("scopeName=%s cd=%p root->tArgLists=%p result=%s\n",
- // scopeName.data(),cd,root->tArgLists,tempScopeName.data());
-
- //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
- // rebuild the function declaration (needed to get the scope right).
- if (!scopeName.isEmpty() && !isRelated && !isFriend && !Config_getBool("HIDE_SCOPE_NAMES"))
- {
- if (!funcType.isEmpty())
- {
- if (isFunc) // a function -> we use argList for the arguments
- {
- funcDecl=funcType+" "+tempScopeName+"::"+funcName+funcTempList;
- }
- else
- {
- funcDecl=funcType+" "+tempScopeName+"::"+funcName+funcArgs;
- }
- }
- else
- {
- if (isFunc) // a function => we use argList for the arguments
- {
- funcDecl=tempScopeName+"::"+funcName+funcTempList;
- }
- else // variable => add `argument' list
- {
- funcDecl=tempScopeName+"::"+funcName+funcArgs;
- }
- }
- }
- else // build declaration without scope
- {
- if (!funcType.isEmpty()) // but with a type
- {
- if (isFunc) // function => omit argument list
- {
- funcDecl=funcType+" "+funcName+funcTempList;
- }
- else // variable => add `argument' list
- {
- funcDecl=funcType+" "+funcName+funcArgs;
- }
- }
- else // no type
- {
- if (isFunc)
- {
- funcDecl=funcName+funcTempList;
- }
- else
- {
- funcDecl=funcName+funcArgs;
- }
- }
- }
-
- if (funcType=="template class" && !funcTempList.isEmpty())
- return; // ignore explicit template instantiations
-
- Debug::print(Debug::FindMembers,0,
- "findMember() Parse results:\n"
- " namespaceName=`%s'\n"
- " className=`%s`\n"
- " funcType=`%s'\n"
- " funcSpec=`%s'\n"
- " funcName=`%s'\n"
- " funcArgs=`%s'\n"
- " funcTempList=`%s'\n"
- " funcDecl=`%s'\n"
- " related=`%s'\n"
- " exceptions=`%s'\n"
- " isRelated=%d\n"
- " isMemberOf=%d\n"
- " isFriend=%d\n"
- " isFunc=%d\n\n",
- namespaceName.data(),className.data(),
- funcType.data(),funcSpec.data(),funcName.data(),funcArgs.data(),funcTempList.data(),
- funcDecl.data(),root->relates.data(),exceptions.data(),isRelated,isMemberOf,isFriend,
- isFunc
- );
- MemberName *mn=0;
- if (!funcName.isEmpty()) // function name is valid
- {
- Debug::print(Debug::FindMembers,0,
- "1. funcName=`%s'\n",funcName.data());
- if (funcName.left(9)=="operator ") // strip class scope from cast operator
- {
- funcName = substitute(funcName,className+"::","");
- }
- if (!funcTempList.isEmpty()) // try with member specialization
- {
- mn=Doxygen::memberNameSDict->find(funcName+funcTempList);
- }
- if (mn==0) // try without specialization
- {
- mn=Doxygen::memberNameSDict->find(funcName);
- }
- if (!isRelated && mn) // function name already found
- {
- Debug::print(Debug::FindMembers,0,
- "2. member name exists (%d members with this name)\n",mn->count());
- if (!className.isEmpty()) // class name is valid
- {
- if (funcSpec.isEmpty()) // not a member specialization
- {
- int count=0;
- int noMatchCount=0;
- MemberNameIterator mni(*mn);
- MemberDef *md;
- bool memFound=FALSE;
- for (mni.toFirst();!memFound && (md=mni.current());++mni)
- {
- ClassDef *cd=md->getClassDef();
- Debug::print(Debug::FindMembers,0,
- "3. member definition found, "
- "scope needed=`%s' scope=`%s' args=`%s' fileName=%s\n",
- scopeName.data(),cd ? cd->name().data() : "<none>",
- md->argsString(),
- root->fileName.data());
- //printf("Member %s (member scopeName=%s) (this scopeName=%s) classTempList=%s\n",md->name().data(),cd->name().data(),scopeName.data(),classTempList.data());
- FileDef *fd=rootNav->fileDef();
- NamespaceDef *nd=0;
- if (!namespaceName.isEmpty()) nd=getResolvedNamespace(namespaceName);
- //printf("scopeName %s->%s\n",scopeName.data(),
- // stripTemplateSpecifiersFromScope(scopeName,FALSE).data());
- ClassDef *tcd=findClassDefinition(fd,nd,scopeName);
- if (tcd==0 && stripAnonymousNamespaceScope(cd->name())==scopeName)
- {
- // don't be fooled by anonymous scopes
- tcd=cd;
- }
- //printf("Looking for %s inside nd=%s result=%p (%s) cd=%p\n",
- // scopeName.data(),nd?nd->name().data():"<none>",tcd,tcd?tcd->name().data():"",cd);
- if (cd && tcd==cd) // member's classes match
- {
- Debug::print(Debug::FindMembers,0,
- "4. class definition %s found\n",cd->name().data());
- // get the template parameter lists found at the member declaration
- QList<ArgumentList> declTemplArgs;
- cd->getTemplateParameterLists(declTemplArgs);
- LockingPtr<ArgumentList> templAl = md->templateArguments();
- if (templAl!=0)
- {
- declTemplArgs.append(templAl.pointer());
- }
- // get the template parameter lists found at the member definition
- QList<ArgumentList> *defTemplArgs = root->tArgLists;
- //printf("defTemplArgs=%p\n",defTemplArgs);
- // do we replace the decl argument lists with the def argument lists?
- bool substDone=FALSE;
- ArgumentList *argList=0;
- /* substitute the occurrences of class template names in the
- * argument list before matching
- */
- LockingPtr<ArgumentList> mdAl = md->argumentList();
- if (declTemplArgs.count()>0 && defTemplArgs &&
- declTemplArgs.count()==defTemplArgs->count() &&
- mdAl.pointer()
- )
- {
- /* the function definition has template arguments
- * and the class definition also has template arguments, so
- * we must substitute the template names of the class by that
- * of the function definition before matching.
- */
- argList = new ArgumentList;
- substituteTemplatesInArgList(declTemplArgs,*defTemplArgs,
- mdAl.pointer(),argList);
- substDone=TRUE;
- }
- else /* no template arguments, compare argument lists directly */
- {
- argList = mdAl.pointer();
- }
- Debug::print(Debug::FindMembers,0,
- "5. matching `%s'<=>`%s' className=%s namespaceName=%s\n",
- argListToString(argList,TRUE).data(),argListToString(root->argList,TRUE).data(),
- className.data(),namespaceName.data()
- );
- bool matching=
- md->isVariable() || md->isTypedef() || // needed for function pointers
- (mdAl.pointer()==0 && root->argList->count()==0) ||
- matchArguments2(
- md->getClassDef(),md->getFileDef(),argList,
- cd,fd,root->argList,
- TRUE);
- Debug::print(Debug::FindMembers,0,
- "6. match results of matchArguments2 = %d\n",matching);
- if (substDone) // found a new argument list
- {
- if (matching) // replace member's argument list
- {
- md->setDefinitionTemplateParameterLists(root->tArgLists);
- md->setArgumentList(argList); // new owner of the list => no delete
- }
- else // no match
- {
- if (!funcTempList.isEmpty() &&
- isSpecialization(declTemplArgs,*defTemplArgs))
- {
- // check if we are dealing with a partial template
- // specialization. In this case we add it to the class
- // even though the member arguments do not match.
-
- // TODO: copy other aspects?
- root->protection=md->protection(); // copy protection level
- addMethodToClass(rootNav,cd,md->name(),isFriend);
- return;
- }
- delete argList;
- }
- }
- if (matching)
- {
- addMemberDocs(rootNav,md,funcDecl,0,overloaded,0/* TODO */);
- count++;
- memFound=TRUE;
- }
- }
- else if (cd && cd!=tcd) // we did find a class with the same name as cd
- // but in a different namespace
- {
- noMatchCount++;
- }
- }
- if (count==0 && rootNav->parent() &&
- rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
- {
- goto localObjCMethod;
- }
- if (count==0 && !(isFriend && funcType=="class"))
- {
- int candidates=0;
- if (mn->count()>0)
- {
- //printf("Assume template class\n");
- for (mni.toFirst();(md=mni.current());++mni)
- {
- ClassDef *cd=md->getClassDef();
- //printf("cd->name()==%s className=%s\n",cd->name().data(),className.data());
- if (cd!=0 && rightScopeMatch(cd->name(),className))
- {
- LockingPtr<ArgumentList> templAl = md->templateArguments();
- if (root->tArgLists && templAl!=0 &&
- root->tArgLists->getLast()->count()<=templAl->count())
- {
- addMethodToClass(rootNav,cd,md->name(),isFriend);
- return;
- }
- candidates++;
- }
- }
- }
- warn(root->fileName,root->startLine,
- "Warning: no %smatching class member found for",
- noMatchCount>1 ? "uniquely " : ""
- );
- if (root->tArgLists)
- {
- QListIterator<ArgumentList> alli(*root->tArgLists);
- ArgumentList *al;
- for (;(al=alli.current());++alli)
- {
- warn_cont(" template %s\n",tempArgListToString(al).data());
- }
- }
- QCString fullFuncDecl=funcDecl.copy();
- if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE);
- warn_cont(" %s\n",fullFuncDecl.data());
- if (candidates>0)
- {
- warn_cont("Possible candidates:\n");
- for (mni.toFirst();(md=mni.current());++mni)
- {
- ClassDef *cd=md->getClassDef();
- if (cd!=0 && rightScopeMatch(cd->name(),className))
- {
- LockingPtr<ArgumentList> templAl = md->templateArguments();
- if (templAl!=0)
- {
- warn_cont(" template %s\n",tempArgListToString(templAl.pointer()).data());
- }
- warn_cont(" ");
- if (md->typeString())
- {
- warn_cont("%s ",md->typeString());
- }
- QCString qScope = cd->qualifiedNameWithTemplateParameters();
- if (!qScope.isEmpty()) warn_cont("%s::%s",qScope.data(),md->name().data());
- if (md->argsString()) warn_cont("%s",md->argsString());
- if (noMatchCount>1) warn_cont(" at line %d of file %s",md->getDefLine(),md->getDefFileName().data());
- warn_cont("\n");
- }
- }
- }
- }
- }
- else if (cd) // member specialization
- {
- MemberDef::MemberType mtype=MemberDef::Function;
- ArgumentList *tArgList = new ArgumentList;
- // getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists);
- MemberDef *md=new MemberDef(
- root->fileName,root->startLine,
- funcType,funcName,funcArgs,exceptions,
- root->protection,root->virt,root->stat,Member,
- mtype,tArgList,root->argList);
- //printf("new specialized member %s args=`%s'\n",md->name().data(),funcArgs.data());
- md->setTagInfo(rootNav->tagInfo());
- md->setMemberClass(cd);
- md->setTemplateSpecialization(TRUE);
- md->setTypeConstraints(root->typeConstr);
- md->setDefinition(funcDecl);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setDocsForDefinition(!root->proto);
- md->setPrototype(root->proto);
- md->addSectionsToDefinition(root->anchors);
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- FileDef *fd=rootNav->fileDef();
- md->setBodyDef(fd);
- md->setMemberSpecifiers(root->spec);
- md->setMemberGroupId(root->mGrpId);
- mn->append(md);
- cd->insertMember(md);
- md->setRefItems(root->sli);
- delete tArgList;
- }
- else
- {
- //printf("*** Specialized member %s of unknown scope %s%s found!\n",
- // scopeName.data(),funcName.data(),funcArgs.data());
- }
- }
- else if (overloaded) // check if the function belongs to only one class
- {
- // for unique overloaded member we allow the class to be
- // omitted, this is to be Qt compatable. Using this should
- // however be avoided, because it is error prone
- MemberNameIterator mni(*mn);
- MemberDef *md=mni.toFirst();
- ASSERT(md);
- ClassDef *cd=md->getClassDef();
- ASSERT(cd);
- QCString className=cd->name().copy();
- ++mni;
- bool unique=TRUE;
- for (;(md=mni.current());++mni)
- {
- ClassDef *cd=md->getClassDef();
- if (className!=cd->name()) unique=FALSE;
- }
- if (unique)
- {
- MemberDef::MemberType mtype;
- if (root->mtype==Signal) mtype=MemberDef::Signal;
- else if (root->mtype==Slot) mtype=MemberDef::Slot;
- else if (root->mtype==DCOP) mtype=MemberDef::DCOP;
- else mtype=MemberDef::Function;
-
- // new overloaded member function
- ArgumentList *tArgList =
- getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists);
- //printf("new related member %s args=`%s'\n",md->name().data(),funcArgs.data());
- MemberDef *md=new MemberDef(
- root->fileName,root->startLine,
- funcType,funcName,funcArgs,exceptions,
- root->protection,root->virt,root->stat,Related,
- mtype,tArgList,root->argList);
- md->setTagInfo(rootNav->tagInfo());
- md->setTypeConstraints(root->typeConstr);
- md->setMemberClass(cd);
- md->setDefinition(funcDecl);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- QCString doc=getOverloadDocs();
- doc+="<p>";
- doc+=root->doc;
- md->setDocumentation(doc,root->docFile,root->docLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setDocsForDefinition(!root->proto);
- md->setPrototype(root->proto);
- md->addSectionsToDefinition(root->anchors);
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- FileDef *fd=rootNav->fileDef();
- md->setBodyDef(fd);
- md->setMemberSpecifiers(root->spec);
- md->setMemberGroupId(root->mGrpId);
- mn->append(md);
- cd->insertMember(md);
- cd->insertUsedFile(root->fileName);
- md->setRefItems(root->sli);
- }
- }
- else // unrelated function with the same name as a member
- {
- if (!findGlobalMember(rootNav,namespaceName,funcName,funcTempList,funcArgs,funcDecl))
- {
- QCString fullFuncDecl=funcDecl.copy();
- if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE);
- warn(root->fileName,root->startLine,
- "Warning: Cannot determine class for function\n%s",
- fullFuncDecl.data()
- );
- }
- }
- }
- else if (isRelated && !root->relates.isEmpty())
- {
- Debug::print(Debug::FindMembers,0,"2. related function\n"
- " scopeName=%s className=%s\n",scopeName.data(),className.data());
- if (className.isEmpty()) className=root->relates;
- ClassDef *cd;
- //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
- if ((cd=getClass(scopeName)))
- {
- bool newMember=TRUE; // assume we have a new member
- bool newMemberName=FALSE;
- bool isDefine=FALSE;
- {
- MemberName *mn = Doxygen::functionNameSDict->find(funcName);
- if (mn)
- {
- MemberDef *md = mn->first();
- while (md && !isDefine)
- {
- isDefine = isDefine || md->isDefine();
- md = mn->next();
- }
- }
- }
- FileDef *fd=rootNav->fileDef();
- if ((mn=Doxygen::memberNameSDict->find(funcName))==0)
- {
- mn=new MemberName(funcName);
- newMemberName=TRUE; // we create a new member name
- }
- else
- {
- MemberDef *rmd=mn->first();
- while (rmd && newMember) // see if we got another member with matching arguments
- {
- LockingPtr<ArgumentList> rmdAl = rmd->argumentList();
- newMember=newMember &&
- !matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl.pointer(),
- cd,fd,root->argList,
- TRUE);
- if (newMember) rmd=mn->next();
- }
- if (!newMember && rmd) // member already exists as rmd -> add docs
- {
- //printf("addMemberDocs for related member %s\n",root->name.data());
- //rmd->setMemberDefTemplateArguments(root->mtArgList);
- addMemberDocs(rootNav,rmd,funcDecl,0,overloaded);
- }
- }
- if (newMember) // need to create a new member
- {
- MemberDef::MemberType mtype;
- if (isDefine)
- mtype=MemberDef::Define;
- else if (root->mtype==Signal)
- mtype=MemberDef::Signal;
- else if (root->mtype==Slot)
- mtype=MemberDef::Slot;
- else if (root->mtype==DCOP)
- mtype=MemberDef::DCOP;
- else
- mtype=MemberDef::Function;
- //printf("New related name `%s' `%d'\n",funcName.data(),
- // root->argList ? (int)root->argList->count() : -1);
- // new related (member) function
- #if 0 // removed as it doesn't handle related template functions correctly
- ArgumentList *tArgList =
- getTemplateArgumentsFromName(scopeName+"::"+funcName,root->tArgLists);
- MemberDef *md=new MemberDef(
- root->fileName,root->startLine,
- funcType,funcName,funcArgs,exceptions,
- root->protection,root->virt,root->stat,TRUE,
- mtype,tArgList,funcArgs.isEmpty() ? 0 : root->argList);
- #endif
- // first note that we pass:
- // (root->tArgLists ? root->tArgLists->last() : 0)
- // for the template arguments fo the new "member."
- // this accurately reflects the template arguments of
- // the related function, which don't have to do with
- // those of the related class.
- MemberDef *md=new MemberDef(
- root->fileName,root->startLine,
- funcType,funcName,funcArgs,exceptions,
- root->protection,root->virt,
- root->stat && !isMemberOf,
- isMemberOf ? Foreign : isRelated ? Related : Member,
- mtype,
- (root->tArgLists ? root->tArgLists->last() : 0),
- funcArgs.isEmpty() ? 0 : root->argList);
- //
- // we still have the problem that
- // MemberDef::writeDocumentation() in memberdef.cpp
- // writes the template argument list for the class,
- // as if this member is a member of the class.
- // fortunately, MemberDef::writeDocumentation() has
- // a special mechanism that allows us to totally
- // override the set of template argument lists that
- // are printed. We use that and set it to the
- // template argument lists of the related function.
- //
- md->setDefinitionTemplateParameterLists(root->tArgLists);
- md->setTagInfo(rootNav->tagInfo());
- //printf("Related member name=`%s' decl=`%s' bodyLine=`%d'\n",
- // funcName.data(),funcDecl.data(),root->bodyLine);
- // try to find the matching line number of the body from the
- // global function list
- bool found=FALSE;
- if (root->bodyLine==-1)
- {
- MemberName *rmn=Doxygen::functionNameSDict->find(funcName);
- if (rmn)
- {
- MemberDef *rmd=rmn->first();
- while (rmd && !found) // see if we got another member with matching arguments
- {
- LockingPtr<ArgumentList> rmdAl = rmd->argumentList();
- // check for matching argument lists
- if (
- matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl.pointer(),
- cd,fd,root->argList,
- TRUE)
- )
- {
- found=TRUE;
- }
- if (!found) rmd=rmn->next();
- }
- if (rmd) // member found -> copy line number info
- {
- md->setBodySegment(rmd->getStartBodyLine(),rmd->getEndBodyLine());
- md->setBodyDef(rmd->getBodyDef());
- //md->setBodyMember(rmd);
- }
- }
- }
- if (!found) // line number could not be found or is available in this
- // entry
- {
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setBodyDef(fd);
- }
- //if (root->mGrpId!=-1)
- //{
- // md->setMemberGroup(memberGroupDict[root->mGrpId]);
- //}
- md->setMemberClass(cd);
- md->setMemberSpecifiers(root->spec);
- md->setDefinition(funcDecl);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setDocsForDefinition(!root->proto);
- md->setPrototype(root->proto);
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->addSectionsToDefinition(root->anchors);
- md->setMemberGroupId(root->mGrpId);
- //md->setMemberDefTemplateArguments(root->mtArgList);
- mn->append(md);
- cd->insertMember(md);
- cd->insertUsedFile(root->fileName);
- md->setRefItems(root->sli);
- if (root->relatesType == Duplicate) md->setRelatedAlso(cd);
- addMemberToGroups(root,md);
- //printf("Adding member=%s\n",md->name().data());
- if (newMemberName)
- {
- //Doxygen::memberNameList.append(mn);
- //Doxygen::memberNameDict.insert(funcName,mn);
- Doxygen::memberNameSDict->append(funcName,mn);
- }
- }
- if (root->relatesType == Duplicate)
- {
- if (!findGlobalMember(rootNav,namespaceName,funcName,funcTempList,funcArgs,funcDecl))
- {
- QCString fullFuncDecl=funcDecl.copy();
- if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE);
- warn(root->fileName,root->startLine,
- "Warning: Cannot determine file/namespace for relatedalso function\n%s",
- fullFuncDecl.data()
- );
- }
- }
- }
- else
- {
- warn_undoc(root->fileName,root->startLine,
- "Warning: class `%s' for related function `%s' is not "
- "documented.",
- className.data(),funcName.data()
- );
- }
- }
- else if (rootNav->parent() && rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
- {
- localObjCMethod:
- ClassDef *cd;
- //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
- if (Config_getBool("EXTRACT_LOCAL_METHODS") && (cd=getClass(scopeName)))
- {
- //printf("Local objective C method `%s' of class `%s' found\n",root->name.data(),cd->name().data());
- MemberDef *md=new MemberDef(
- root->fileName,root->startLine,
- funcType,funcName,funcArgs,exceptions,
- root->protection,root->virt,root->stat,Member,
- MemberDef::Function,0,root->argList);
- md->setTagInfo(rootNav->tagInfo());
- md->makeImplementationDetail();
- md->setMemberClass(cd);
- md->setDefinition(funcDecl);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setDocsForDefinition(!root->proto);
- md->setPrototype(root->proto);
- md->addSectionsToDefinition(root->anchors);
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- FileDef *fd=rootNav->fileDef();
- md->setBodyDef(fd);
- md->setMemberSpecifiers(root->spec);
- md->setMemberGroupId(root->mGrpId);
- cd->insertMember(md);
- cd->insertUsedFile(root->fileName);
- md->setRefItems(root->sli);
- if ((mn=Doxygen::memberNameSDict->find(root->name)))
- {
- mn->append(md);
- }
- else
- {
- mn = new MemberName(root->name);
- mn->append(md);
- Doxygen::memberNameSDict->append(root->name,mn);
- }
- }
- else
- {
- // local objective C method found for class without interface
- }
- }
- else // unrelated not overloaded member found
- {
- bool globMem = findGlobalMember(rootNav,namespaceName,funcName,funcTempList,funcArgs,funcDecl);
- if (className.isEmpty() && !globMem)
- {
- warn(root->fileName,root->startLine,
- "Warning: class for member `%s' cannot "
- "be found.", funcName.data()
- );
- }
- else if (!className.isEmpty() && !globMem)
- {
- warn(root->fileName,root->startLine,
- "Warning: member `%s' of class `%s' cannot be found",
- funcName.data(),className.data());
- }
- }
- }
- else
- {
- // this should not be called
- warn(root->fileName,root->startLine,
- "Warning: member with no name found.");
- }
- return;
- }
- //----------------------------------------------------------------------
- // find the members corresponding to the different documentation blocks
- // that are extracted from the sources.
- static void filterMemberDocumentation(EntryNav *rootNav)
- {
- Entry *root = rootNav->entry();
- int i=-1,l;
- Debug::print(Debug::FindMembers,0,
- "findMemberDocumentation(): root->type=`%s' root->inside=`%s' root->name=`%s' root->args=`%s' section=%x root->spec=%d root->mGrpId=%d\n",
- root->type.data(),root->inside.data(),root->name.data(),root->args.data(),root->section,root->spec,root->mGrpId
- );
- //printf("rootNav->parent()->name()=%s\n",rootNav->parent()->name().data());
- bool isFunc=TRUE;
- if (root->relatesType == Duplicate && !root->relates.isEmpty())
- {
- QCString tmp = root->relates;
- root->relates.resize(0);
- filterMemberDocumentation(rootNav);
- root->relates = tmp;
- }
- if ( // detect func variable/typedef to func ptr
- (i=findFunctionPtr(root->type,&l))!=-1
- )
- {
- //printf("Fixing function pointer!\n");
- // fix type and argument
- root->args.prepend(root->type.right(root->type.length()-i-l));
- root->type=root->type.left(i+l);
- //printf("Results type=%s,name=%s,args=%s\n",root->type.data(),root->name.data(),root->args.data());
- isFunc=FALSE;
- }
- else if ((root->type.left(8)=="typedef " && root->args.find('(')!=-1))
- // detect function types marked as functions
- {
- isFunc=FALSE;
- }
- //printf("Member %s isFunc=%d\n",root->name.data(),isFunc);
- if (root->section==Entry::MEMBERDOC_SEC)
- {
- //printf("Documentation for inline member `%s' found args=`%s'\n",
- // root->name.data(),root->args.data());
- //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
- if (root->type.isEmpty())
- {
- findMember(rootNav,root->name+root->args+root->exception,FALSE,isFunc);
- }
- else
- {
- findMember(rootNav,root->type+" "+root->name+root->args+root->exception,FALSE,isFunc);
- }
- }
- else if (root->section==Entry::OVERLOADDOC_SEC)
- {
- //printf("Overloaded member %s found\n",root->name.data());
- findMember(rootNav,root->name,TRUE,isFunc);
- }
- else if
- ((root->section==Entry::FUNCTION_SEC // function
- ||
- (root->section==Entry::VARIABLE_SEC && // variable
- !root->type.isEmpty() && // with a type
- g_compoundKeywordDict.find(root->type)==0 // that is not a keyword
- // (to skip forward declaration of class etc.)
- )
- )
- )
- {
- //printf("Documentation for member `%s' found args=`%s' excp=`%s'\n",
- // root->name.data(),root->args.data(),root->exception.data());
- //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
- //printf("Inside=%s\n Relates=%s\n",root->inside.data(),root->relates.data());
- if (root->type=="friend class" || root->type=="friend struct" ||
- root->type=="friend union")
- {
- findMember(rootNav,
- root->type+" "+
- root->name,
- FALSE,FALSE);
- }
- else if (!root->type.isEmpty())
- {
- findMember(rootNav,
- root->type+" "+
- root->inside+
- root->name+
- root->args+
- root->exception,
- FALSE,isFunc);
- }
- else
- {
- findMember(rootNav,
- root->inside+
- root->name+
- root->args+
- root->exception,
- FALSE,isFunc);
- }
- }
- else if (root->section==Entry::DEFINE_SEC && !root->relates.isEmpty())
- {
- findMember(rootNav,root->name+root->args,FALSE,!root->args.isEmpty());
- }
- else if (root->section==Entry::VARIABLEDOC_SEC)
- {
- //printf("Documentation for variable %s found\n",root->name.data());
- //if (!root->relates.isEmpty()) printf(" Relates %s\n",root->relates.data());
- findMember(rootNav,root->name,FALSE,FALSE);
- }
- else
- {
- // skip section
- //printf("skip section\n");
- }
- }
- static void findMemberDocumentation(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::MEMBERDOC_SEC ||
- rootNav->section()==Entry::OVERLOADDOC_SEC ||
- rootNav->section()==Entry::FUNCTION_SEC ||
- rootNav->section()==Entry::VARIABLE_SEC ||
- rootNav->section()==Entry::VARIABLEDOC_SEC ||
- rootNav->section()==Entry::DEFINE_SEC
- )
- {
- rootNav->loadEntry(g_storage);
- filterMemberDocumentation(rootNav);
- rootNav->releaseEntry();
- }
- if (rootNav->children())
- {
- EntryNavListIterator eli(*rootNav->children());
- EntryNav *e;
- for (;(e=eli.current());++eli)
- {
- if (e->section()!=Entry::ENUM_SEC) findMemberDocumentation(e);
- }
- }
- }
- //----------------------------------------------------------------------
- static void findObjCMethodDefinitions(EntryNav *rootNav)
- {
- if (rootNav->children())
- {
- EntryNavListIterator eli(*rootNav->children());
- EntryNav *objCImplNav;
- for (;(objCImplNav=eli.current());++eli)
- {
- if (objCImplNav->section()==Entry::OBJCIMPL_SEC && objCImplNav->children())
- {
- EntryNavListIterator seli(*objCImplNav->children());
- EntryNav *objCMethodNav;
- for (;(objCMethodNav=seli.current());++seli)
- {
- if (objCMethodNav->section()==Entry::FUNCTION_SEC)
- {
- objCMethodNav->loadEntry(g_storage);
- Entry *objCMethod = objCMethodNav->entry();
- //Printf(" Found ObjC method definition %s\n",objCMethod->name.data());
- findMember(objCMethodNav, objCMethod->type+" "+objCImplNav->name()+"::"+
- objCMethod->name+" "+objCMethod->args, FALSE,TRUE);
- objCMethod->section=Entry::EMPTY_SEC;
- objCMethodNav->releaseEntry();
- }
- }
- }
- }
- }
- }
- //----------------------------------------------------------------------
- // find and add the enumeration to their classes, namespaces or files
- static void findEnums(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::ENUM_SEC)
- // non anonymous enumeration
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- MemberDef *md=0;
- ClassDef *cd=0;
- FileDef *fd=0;
- NamespaceDef *nd=0;
- MemberNameSDict *mnsd=0;
- bool isGlobal;
- bool isRelated=FALSE;
- bool isMemberOf=FALSE;
- //printf("Found enum with name `%s' relates=%s\n",root->name.data(),root->relates.data());
- int i;
- QCString name;
- QCString scope;
- if ((i=root->name.findRev("::"))!=-1) // scope is specified
- {
- scope=root->name.left(i); // extract scope
- name=root->name.right(root->name.length()-i-2); // extract name
- if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
- }
- else // no scope, check the scope in which the docs where found
- {
- if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
- && !rootNav->parent()->name().isEmpty()
- ) // found enum docs inside a compound
- {
- scope=rootNav->parent()->name();
- if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
- }
- name=root->name;
- }
- if (!root->relates.isEmpty())
- { // related member, prefix user specified scope
- isRelated=TRUE;
- isMemberOf=(root->relatesType == MemberOf);
- if (getClass(root->relates)==0 && !scope.isEmpty())
- scope=mergeScopes(scope,root->relates);
- else
- scope=root->relates.copy();
- if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
- }
- if (cd && !name.isEmpty()) // found a enum inside a compound
- {
- //printf("Enum `%s'::`%s'\n",cd->name(),name.data());
- fd=0;
- mnsd=Doxygen::memberNameSDict;
- isGlobal=FALSE;
- }
- else if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') // found enum inside namespace
- {
- mnsd=Doxygen::functionNameSDict;
- isGlobal=TRUE;
- }
- else // found a global enum
- {
- fd=rootNav->fileDef();
- mnsd=Doxygen::functionNameSDict;
- isGlobal=TRUE;
- }
- if (!name.isEmpty())
- {
- // new enum type
- md = new MemberDef(
- root->fileName,root->startLine,
- 0,name,0,0,
- root->protection,Normal,FALSE,
- isMemberOf ? Foreign : isRelated ? Related : Member,
- MemberDef::Enumeration,
- 0,0);
- md->setTagInfo(rootNav->tagInfo());
- if (!isGlobal) md->setMemberClass(cd); else md->setFileDef(fd);
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setBodyDef(rootNav->fileDef());
- //printf("Enum %s definition at line %d of %s: protection=%d\n",
- // root->name.data(),root->bodyLine,root->fileName.data(),root->protection);
- md->addSectionsToDefinition(root->anchors);
- md->setMemberGroupId(root->mGrpId);
- md->enableCallGraph(root->callGraph);
- md->enableCallerGraph(root->callerGraph);
- //printf("%s::setRefItems(%d)\n",md->name().data(),root->sli?root->sli->count():-1);
- md->setRefItems(root->sli);
- //printf("found enum %s nd=%p\n",name.data(),nd);
- bool defSet=FALSE;
- if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
- {
- if (isRelated || Config_getBool("HIDE_SCOPE_NAMES"))
- {
- md->setDefinition(name);
- }
- else
- {
- md->setDefinition(nd->name()+"::"+name);
- }
- //printf("definition=%s\n",md->definition());
- defSet=TRUE;
- md->setNamespace(nd);
- nd->insertMember(md);
- }
- // even if we have already added the enum to a namespace, we still
- // also want to add it to other appropriate places such as file
- // or class.
- if (isGlobal)
- {
- if (!defSet) md->setDefinition(name);
- if (fd==0 && rootNav->parent())
- {
- fd=rootNav->parent()->fileDef();
- }
- if (fd)
- {
- md->setFileDef(fd);
- fd->insertMember(md);
- }
- }
- else if (cd)
- {
- if (isRelated || Config_getBool("HIDE_SCOPE_NAMES"))
- {
- md->setDefinition(name);
- }
- else
- {
- md->setDefinition(cd->name()+"::"+name);
- }
- cd->insertMember(md);
- cd->insertUsedFile(root->fileName);
- }
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setDocsForDefinition(!root->proto);
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- //printf("Adding member=%s\n",md->name().data());
- MemberName *mn;
- if ((mn=(*mnsd)[name]))
- {
- // this is used if the same enum is in multiple namespaces/classes
- mn->append(md);
- }
- else // new enum name
- {
- mn = new MemberName(name);
- mn->append(md);
- mnsd->append(name,mn);
- //printf("add %s to new memberName. Now %d members\n",
- // name.data(),mn->count());
- }
- addMemberToGroups(root,md);
- #if 0
- if (rootNav->children())
- {
- EntryNavListIterator eli(*rootNav->children());
- EntryNav *e;
- for (;(e=eli.current());++eli)
- {
- //printf("e->name=%s isRelated=%d\n",e->name.data(),isRelated);
- MemberName *fmn=0;
- MemberNameSDict *emnsd = isRelated ? Doxygen::functionNameSDict : mnsd;
- if (!e->name().isEmpty() && (fmn=(*emnsd)[e->name()]))
- // get list of members with the same name as the field
- {
- MemberNameIterator fmni(*fmn);
- MemberDef *fmd;
- for (fmni.toFirst(); (fmd=fmni.current()) ; ++fmni)
- {
- if (fmd->isEnumValue())
- {
- //printf("found enum value with same name\n");
- if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
- {
- NamespaceDef *fnd=fmd->getNamespaceDef();
- if (fnd==nd) // enum value is inside a namespace
- {
- md->insertEnumField(fmd);
- fmd->setEnumScope(md);
- }
- }
- else if (isGlobal)
- {
- FileDef *ffd=fmd->getFileDef();
- if (ffd==fd) // enum value has file scope
- {
- md->insertEnumField(fmd);
- fmd->setEnumScope(md);
- }
- }
- else if (isRelated && cd) // reparent enum value to
- // match the enum's scope
- {
- md->insertEnumField(fmd); // add field def to list
- fmd->setEnumScope(md); // cross ref with enum name
- fmd->setEnumClassScope(cd); // cross ref with enum name
- fmd->setOuterScope(cd);
- fmd->makeRelated();
- cd->insertMember(fmd);
- }
- else
- {
- ClassDef *fcd=fmd->getClassDef();
- if (fcd==cd) // enum value is inside a class
- {
- //printf("Inserting enum field %s in enum scope %s\n",
- // fmd->name().data(),md->name().data());
- md->insertEnumField(fmd); // add field def to list
- fmd->setEnumScope(md); // cross ref with enum name
- }
- }
- }
- }
- }
- }
- }
- #endif
- }
- rootNav->releaseEntry();
- }
- else
- {
- RECURSE_ENTRYTREE(findEnums,rootNav);
- }
- }
- //----------------------------------------------------------------------
- static void addEnumValuesToEnums(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::ENUM_SEC)
- // non anonymous enumeration
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- ClassDef *cd=0;
- FileDef *fd=0;
- NamespaceDef *nd=0;
- MemberNameSDict *mnsd=0;
- bool isGlobal;
- bool isRelated=FALSE;
- //printf("Found enum with name `%s' relates=%s\n",root->name.data(),root->relates.data());
- int i;
- QCString name;
- QCString scope;
- if ((i=root->name.findRev("::"))!=-1) // scope is specified
- {
- scope=root->name.left(i); // extract scope
- name=root->name.right(root->name.length()-i-2); // extract name
- if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
- }
- else // no scope, check the scope in which the docs where found
- {
- if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
- && !rootNav->parent()->name().isEmpty()
- ) // found enum docs inside a compound
- {
- scope=rootNav->parent()->name();
- if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
- }
- name=root->name;
- }
- if (!root->relates.isEmpty())
- { // related member, prefix user specified scope
- isRelated=TRUE;
- if (getClass(root->relates)==0 && !scope.isEmpty())
- scope=mergeScopes(scope,root->relates);
- else
- scope=root->relates.copy();
- if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
- }
- if (cd && !name.isEmpty()) // found a enum inside a compound
- {
- //printf("Enum in class `%s'::`%s'\n",cd->name().data(),name.data());
- fd=0;
- mnsd=Doxygen::memberNameSDict;
- isGlobal=FALSE;
- }
- else if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') // found enum inside namespace
- {
- //printf("Enum in namespace `%s'::`%s'\n",nd->name().data(),name.data());
- mnsd=Doxygen::functionNameSDict;
- isGlobal=TRUE;
- }
- else // found a global enum
- {
- fd=rootNav->fileDef();
- //printf("Enum in file `%s': `%s'\n",fd->name().data(),name.data());
- mnsd=Doxygen::functionNameSDict;
- isGlobal=TRUE;
- }
- if (!name.isEmpty())
- {
- MemberName *mn = mnsd->find(name); // for all members with this name
- if (mn)
- {
- MemberNameIterator mni(*mn);
- MemberDef *md;
- for (mni.toFirst(); (md=mni.current()) ; ++mni) // for each enum in this list
- {
- if (md->isEnumerate() && rootNav->children())
- {
- EntryNavListIterator eli(*rootNav->children()); // for each enum value
- EntryNav *e;
- for (;(e=eli.current());++eli)
- {
- SrcLangExt sle;
- if (rootNav->fileDef() //&&
- //( (sle=getLanguageFromFileName(rootNav->fileDef()->name()))==SrcLangExt_CSharp
- //|| sle==SrcLangExt_Java || sle==SrcLangExt_XML
- //)
- )
- {
- // Unlike C++, for C# enum value are only inside the enum
- // scope, so we must create them here and only add them to the
- // enum
- e->loadEntry(g_storage);
- Entry *root = e->entry();
- if (md->qualifiedName()==rootNav->name()) // enum value scope matches that of the enum
- {
- MemberDef *fmd=new MemberDef(
- root->fileName,root->startLine,
- root->type,root->name,root->args,0,
- Public, Normal,root->stat,Member,
- MemberDef::EnumValue,0,0);
- if (md->getClassDef()) fmd->setMemberClass(md->getClassDef());
- else if (md->getNamespaceDef()) fmd->setNamespace(md->getNamespaceDef());
- else if (md->getFileDef()) fmd->setFileDef(md->getFileDef());
- fmd->setOuterScope(md->getOuterScope());
- fmd->setTagInfo(e->tagInfo());
- fmd->setDocumentation(root->doc,root->docFile,root->docLine);
- fmd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- fmd->addSectionsToDefinition(root->anchors);
- fmd->setInitializer(root->initializer);
- fmd->setMaxInitLines(root->initLines);
- fmd->setMemberGroupId(root->mGrpId);
- fmd->setExplicitExternal(root->explicitExternal);
- fmd->setRefItems(root->sli);
- if (fmd)
- {
- md->insertEnumField(fmd);
- fmd->setEnumScope(md);
- }
- }
- e->releaseEntry();
- }
- else
- {
- //printf("e->name=%s isRelated=%d\n",e->name().data(),isRelated);
- MemberName *fmn=0;
- MemberNameSDict *emnsd = isRelated ? Doxygen::functionNameSDict : mnsd;
- if (!e->name().isEmpty() && (fmn=(*emnsd)[e->name()]))
- // get list of members with the same name as the field
- {
- MemberNameIterator fmni(*fmn);
- MemberDef *fmd;
- for (fmni.toFirst(); (fmd=fmni.current()) ; ++fmni)
- {
- if (fmd->isEnumValue() && fmd->getOuterScope()==md->getOuterScope()) // in same scope
- {
- //printf("found enum value with same name %s in scope %s\n",
- // fmd->name().data(),fmd->getOuterScope()->name().data());
- if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
- {
- NamespaceDef *fnd=fmd->getNamespaceDef();
- if (fnd==nd) // enum value is inside a namespace
- {
- md->insertEnumField(fmd);
- fmd->setEnumScope(md);
- }
- }
- else if (isGlobal)
- {
- FileDef *ffd=fmd->getFileDef();
- if (ffd==fd) // enum value has file scope
- {
- md->insertEnumField(fmd);
- fmd->setEnumScope(md);
- }
- }
- else if (isRelated && cd) // reparent enum value to
- // match the enum's scope
- {
- md->insertEnumField(fmd); // add field def to list
- fmd->setEnumScope(md); // cross ref with enum name
- fmd->setEnumClassScope(cd); // cross ref with enum name
- fmd->setOuterScope(cd);
- fmd->makeRelated();
- cd->insertMember(fmd);
- }
- else
- {
- ClassDef *fcd=fmd->getClassDef();
- if (fcd==cd) // enum value is inside a class
- {
- //printf("Inserting enum field %s in enum scope %s\n",
- // fmd->name().data(),md->name().data());
- md->insertEnumField(fmd); // add field def to list
- fmd->setEnumScope(md); // cross ref with enum name
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- rootNav->releaseEntry();
- }
- else
- {
- RECURSE_ENTRYTREE(addEnumValuesToEnums,rootNav);
- }
- }
- //----------------------------------------------------------------------
- // find the documentation blocks for the enumerations
- static void findEnumDocumentation(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::ENUMDOC_SEC
- && !rootNav->name().isEmpty()
- && rootNav->name().at(0)!='@' // skip anonymous enums
- )
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- //printf("Found docs for enum with name `%s' in context %s\n",
- // root->name.data(),root->parent->name.data());
- int i;
- QCString name;
- QCString scope;
- if ((i=root->name.findRev("::"))!=-1) // scope is specified as part of the name
- {
- name=root->name.right(root->name.length()-i-2); // extract name
- scope=root->name.left(i); // extract scope
- //printf("Scope=`%s' Name=`%s'\n",scope.data(),name.data());
- }
- else // just the name
- {
- name=root->name;
- }
- if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
- && !rootNav->parent()->name().isEmpty()
- ) // found enum docs inside a compound
- {
- if (!scope.isEmpty()) scope.prepend("::");
- scope.prepend(rootNav->parent()->name());
- }
- ClassDef *cd=getClass(scope);
- if (!name.isEmpty())
- {
- bool found=FALSE;
- if (cd)
- {
- //printf("Enum: scope=`%s' name=`%s'\n",cd->name(),name.data());
- QCString className=cd->name().copy();
- MemberName *mn=Doxygen::memberNameSDict->find(name);
- if (mn)
- {
- MemberNameIterator mni(*mn);
- MemberDef *md;
- for (mni.toFirst();(md=mni.current()) && !found;++mni)
- {
- ClassDef *cd=md->getClassDef();
- if (cd && cd->name()==className && md->isEnumerate())
- {
- // documentation outside a compound overrides the documentation inside it
- #if 0
- if (!md->documentation() || rootNav->parent()->name().isEmpty())
- #endif
- {
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setDocsForDefinition(!root->proto);
- }
- // brief descriptions inside a compound override the documentation
- // outside it
- #if 0
- if (!md->briefDescription() || !rootNav->parent()->name().isEmpty())
- #endif
- {
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- }
- if (!md->inbodyDocumentation() || !rootNav->parent()->name().isEmpty())
- {
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- }
- if (root->mGrpId!=-1 && md->getMemberGroupId()==-1)
- {
- md->setMemberGroupId(root->mGrpId);
- }
- md->addSectionsToDefinition(root->anchors);
- md->setRefItems(root->sli);
- GroupDef *gd=md->getGroupDef();
- if (gd==0 &&root->groups->first()!=0) // member not grouped but out-of-line documentation is
- {
- addMemberToGroups(root,md);
- }
- found=TRUE;
- }
- }
- }
- else
- {
- //printf("MemberName %s not found!\n",name.data());
- }
- }
- else // enum outside class
- {
- //printf("Enum outside class: %s grpId=%d\n",name.data(),root->mGrpId);
- MemberName *mn=Doxygen::functionNameSDict->find(name);
- if (mn)
- {
- MemberNameIterator mni(*mn);
- MemberDef *md;
- for (mni.toFirst();(md=mni.current()) && !found;++mni)
- {
- if (md->isEnumerate())
- {
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setDocsForDefinition(!root->proto);
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->addSectionsToDefinition(root->anchors);
- md->setMemberGroupId(root->mGrpId);
- GroupDef *gd=md->getGroupDef();
- if (gd==0 && root->groups->first()!=0) // member not grouped but out-of-line documentation is
- {
- addMemberToGroups(root,md);
- }
- found=TRUE;
- }
- }
- }
- }
- if (!found)
- {
- warn(root->fileName,root->startLine,
- "Warning: Documentation for undefined enum `%s' found.",
- name.data()
- );
- }
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(findEnumDocumentation,rootNav);
- }
- // seach for each enum (member or function) in mnl if it has documented
- // enum values.
- static void findDEV(const MemberNameSDict &mnsd)
- {
- MemberName *mn;
- MemberNameSDict::Iterator mnli(mnsd);
- // for each member name
- for (mnli.toFirst();(mn=mnli.current());++mnli)
- {
- MemberDef *md;
- MemberNameIterator mni(*mn);
- // for each member definition
- for (mni.toFirst();(md=mni.current());++mni)
- {
- if (md->isEnumerate()) // member is an enum
- {
- LockingPtr<MemberList> fmdl = md->enumFieldList();
- int documentedEnumValues=0;
- if (fmdl!=0) // enum has values
- {
- MemberListIterator fmni(*fmdl);
- MemberDef *fmd;
- // for each enum value
- for (fmni.toFirst();(fmd=fmni.current());++fmni)
- {
- if (fmd->isLinkableInProject()) documentedEnumValues++;
- }
- }
- // at least one enum value is documented
- if (documentedEnumValues>0) md->setDocumentedEnumValues(TRUE);
- }
- }
- }
- }
- // seach for each enum (member or function) if it has documented enum
- // values.
- static void findDocumentedEnumValues()
- {
- findDEV(*Doxygen::memberNameSDict);
- findDEV(*Doxygen::functionNameSDict);
- }
- //----------------------------------------------------------------------
- static void addMembersToIndex()
- {
- MemberName *mn;
- MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
- // for each member name
- for (mnli.toFirst();(mn=mnli.current());++mnli)
- {
- MemberDef *md;
- MemberNameIterator mni(*mn);
- // for each member definition
- for (mni.toFirst();(md=mni.current());++mni)
- {
- addClassMemberNameToIndex(md);
- }
- }
- MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
- // for each member name
- for (fnli.toFirst();(mn=fnli.current());++fnli)
- {
- MemberDef *md;
- MemberNameIterator mni(*mn);
- // for each member definition
- for (mni.toFirst();(md=mni.current());++mni)
- {
- if (md->getNamespaceDef())
- {
- addNamespaceMemberNameToIndex(md);
- }
- else
- {
- addFileMemberNameToIndex(md);
- }
- }
- }
- }
- //----------------------------------------------------------------------
- // computes the relation between all members. For each member `m'
- // the members that override the implementation of `m' are searched and
- // the member that `m' overrides is searched.
- static void computeMemberRelations()
- {
- MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
- MemberName *mn;
- for ( ; (mn=mnli.current()) ; ++mnli ) // for each member name
- {
- MemberNameIterator mdi(*mn);
- MemberDef *md;
- for ( ; (md=mdi.current()) ; ++mdi ) // for each member with a specific name
- {
- MemberDef *bmd = mn->first(); // for each other member with the same name
- while (bmd)
- {
- ClassDef *mcd = md->getClassDef();
- if (mcd && mcd->baseClasses())
- {
- ClassDef *bmcd = bmd->getClassDef();
- //printf("Check relation between `%s'::`%s' (%p) and `%s'::`%s' (%p)\n",
- // mcd->name().data(),md->name().data(),md,
- // bmcd->name().data(),bmd->name().data(),bmd
- // );
- if (md!=bmd && bmcd && mcd && bmcd!=mcd && mcd->isBaseClass(bmcd,TRUE))
- {
- LockingPtr<ArgumentList> bmdAl = bmd->argumentList();
- LockingPtr<ArgumentList> mdAl = md->argumentList();
- //printf(" Base argList=`%s'\n Super argList=`%s'\n",
- // argListToString(bmdAl.pointer()).data(),
- // argListToString(mdAl.pointer()).data()
- // );
- if (
- matchArguments2(bmd->getOuterScope(),bmd->getFileDef(),bmdAl.pointer(),
- md->getOuterScope(), md->getFileDef(), mdAl.pointer(),
- TRUE
- )
- )
- {
- //printf(" match found!\n");
- if (mcd && bmcd &&
- mcd->isLinkable() && bmcd->isLinkable()
- )
- {
- MemberDef *rmd;
- if ((rmd=md->reimplements())==0 ||
- minClassDistance(mcd,bmcd)<minClassDistance(mcd,rmd->getClassDef())
- )
- {
- //printf("setting (new) reimplements member\n");
- md->setReimplements(bmd);
- }
- //printf("%s: add reimplements member %s\n",mcd->name().data(),bmcd->name().data());
- //md->setImplements(bmd);
- //printf("%s: add reimplementedBy member %s\n",bmcd->name().data(),mcd->name().data());
- bmd->insertReimplementedBy(md);
- }
- }
- }
- }
- bmd = mn->next();
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- //static void computeClassImplUsageRelations()
- //{
- // ClassDef *cd;
- // ClassSDict::Iterator cli(*Doxygen::classSDict);
- // for (;(cd=cli.current());++cli)
- // {
- // cd->determineImplUsageRelation();
- // }
- //}
- //----------------------------------------------------------------------------
- static void createTemplateInstanceMembers()
- {
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
- // for each class
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- // that is a template
- QDict<ClassDef> *templInstances = cd->getTemplateInstances();
- if (templInstances)
- {
- QDictIterator<ClassDef> qdi(*templInstances);
- ClassDef *tcd=0;
- // for each instance of the template
- for (qdi.toFirst();(tcd=qdi.current());++qdi)
- {
- tcd->addMembersToTemplateInstance(cd,qdi.currentKey());
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- // builds the list of all members for each class
- static void buildCompleteMemberLists()
- {
- ClassDef *cd;
- // merge members of categories into the class they extend
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- int i=cd->name().find('(');
- if (i!=-1) // it is an Objective-C category
- {
- QCString baseName=cd->name().left(i);
- ClassDef *baseClass=Doxygen::classSDict->find(baseName);
- if (baseClass)
- {
- //printf("*** merging members of category %s into %s\n",
- // cd->name().data(),baseClass->name().data());
- baseClass->mergeCategory(cd);
- }
- }
- }
- // merge the member list of base classes into the inherited classes.
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- if (// !cd->isReference() && // not an external class
- cd->subClasses()==0 && // is a root of the hierarchy
- cd->baseClasses()) // and has at least one base class
- {
- //printf("*** merging members for %s\n",cd->name().data());
- cd->mergeMembers();
- }
- }
- // now sort the member list of all classes.
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- if (cd->memberNameInfoSDict()) cd->memberNameInfoSDict()->sort();
- }
- }
- //----------------------------------------------------------------------------
- static void generateFileSources()
- {
- if (documentedHtmlFiles==0) return;
- if (Doxygen::inputNameList->count()>0)
- {
- FileNameListIterator fnli(*Doxygen::inputNameList);
- FileName *fn;
- for (;(fn=fnli.current());++fnli)
- {
- FileNameIterator fni(*fn);
- FileDef *fd;
- for (;(fd=fni.current());++fni)
- {
- if (fd->generateSourceFile()) // sources need to be shown in the output
- {
- msg("Generating code for file %s...\n",fd->docName().data());
- fd->writeSource(*g_outputList);
- }
- else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
- // we needed to parse the sources even if we do not show them
- {
- msg("Parsing code for file %s...\n",fd->docName().data());
- fd->parseSource();
- }
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- static void generateFileDocs()
- {
- if (documentedHtmlFiles==0) return;
-
- if (Doxygen::inputNameList->count()>0)
- {
- FileNameListIterator fnli(*Doxygen::inputNameList);
- FileName *fn;
- for (fnli.toFirst();(fn=fnli.current());++fnli)
- {
- FileNameIterator fni(*fn);
- FileDef *fd;
- for (fni.toFirst();(fd=fni.current());++fni)
- {
- bool doc = fd->isLinkableInProject();
- if (doc)
- {
- msg("Generating docs for file %s...\n",fd->docName().data());
- fd->writeDocumentation(*g_outputList);
- }
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- static void addSourceReferences()
- {
- // add source references for class definitions
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd=0;
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- FileDef *fd=cd->getBodyDef();
- if (fd && cd->isLinkableInProject() && cd->getStartBodyLine()!=-1)
- {
- fd->addSourceRef(cd->getStartBodyLine(),cd,0);
- }
- }
- // add source references for namespace definitions
- NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd=0;
- for (nli.toFirst();(nd=nli.current());++nli)
- {
- FileDef *fd=nd->getBodyDef();
- if (fd && nd->isLinkableInProject() && nd->getStartBodyLine()!=-1)
- {
- fd->addSourceRef(nd->getStartBodyLine(),nd,0);
- }
- }
-
- // add source references for member names
- MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
- MemberName *mn=0;
- for (mnli.toFirst();(mn=mnli.current());++mnli)
- {
- MemberNameIterator mni(*mn);
- MemberDef *md=0;
- for (mni.toFirst();(md=mni.current());++mni)
- {
- //printf("class member %s\n",md->name().data());
- FileDef *fd=md->getBodyDef();
- if (fd &&
- md->getStartBodyLine()!=-1 &&
- md->isLinkableInProject() &&
- (fd->generateSourceFile() || Doxygen::parseSourcesNeeded)
- )
- {
- //printf("Found member `%s' in file `%s' at line `%d' def=%s\n",
- // md->name().data(),fd->name().data(),md->getStartBodyLine(),md->getOuterScope()->name().data());
- fd->addSourceRef(md->getStartBodyLine(),md->getOuterScope(),md);
- }
- }
- }
- MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
- for (fnli.toFirst();(mn=fnli.current());++fnli)
- {
- MemberNameIterator mni(*mn);
- MemberDef *md=0;
- for (mni.toFirst();(md=mni.current());++mni)
- {
- FileDef *fd=md->getBodyDef();
- //printf("member %s body=[%d,%d] fd=%p link=%d parseSources=%d\n",
- // md->name().data(),
- // md->getStartBodyLine(),md->getEndBodyLine(),fd,
- // md->isLinkableInProject(),
- // Doxygen::parseSourcesNeeded);
- if (fd &&
- md->getStartBodyLine()!=-1 &&
- md->isLinkableInProject() &&
- (fd->generateSourceFile() || Doxygen::parseSourcesNeeded)
- )
- {
- //printf("Found member `%s' in file `%s' at line `%d' def=%s\n",
- // md->name().data(),fd->name().data(),md->getStartBodyLine(),md->getOuterScope()->name().data());
- fd->addSourceRef(md->getStartBodyLine(),md->getOuterScope(),md);
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- // generate the documentation of all classes
-
- static void generateClassList(ClassSDict &classSDict)
- {
- ClassSDict::Iterator cli(classSDict);
- for ( ; cli.current() ; ++cli )
- {
- ClassDef *cd=cli.current();
-
- //printf("cd=%s getOuterScope=%p global=%p\n",cd->name().data(),cd->getOuterScope(),Doxygen::globalScope);
- if ((cd->getOuterScope()==0 || // <-- should not happen, but can if we read an old tag file
- cd->getOuterScope()==Doxygen::globalScope // only look at global classes
- ) && !cd->isHidden()
- )
- {
- // skip external references, anonymous compounds and
- // template instances
- if ( cd->isLinkableInProject() && cd->templateMaster()==0)
- {
- msg("Generating docs for compound %s...\n",cd->name().data());
- cd->writeDocumentation(*g_outputList);
- cd->writeMemberList(*g_outputList);
- }
- // even for undocumented classes, the inner classes can be documented.
- cd->writeDocumentationForInnerClasses(*g_outputList);
- }
- }
- }
- static void generateClassDocs()
- {
- // write the installdox script if necessary
- if (Config_getBool("GENERATE_HTML") &&
- (Config_getList("TAGFILES").count()>0 ||
- Config_getBool("SEARCHENGINE")
- )
- )
- {
- writeInstallScript();
- }
-
- msg("Generating annotated compound index...\n");
- writeAnnotatedIndex(*g_outputList);
- //if (Config_getBool("ALPHABETICAL_INDEX"))
- //{
- msg("Generating alphabetical compound index...\n");
- writeAlphabeticalIndex(*g_outputList);
- //}
- msg("Generating hierarchical class index...\n");
- writeHierarchicalIndex(*g_outputList);
- msg("Generating member index...\n");
- writeClassMemberIndex(*g_outputList);
- if (Doxygen::exampleSDict->count()>0)
- {
- msg("Generating example index...\n");
- }
- generateClassList(*Doxygen::classSDict);
- generateClassList(*Doxygen::hiddenClasses);
- }
- //----------------------------------------------------------------------------
- static void inheritDocumentation()
- {
- MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
- MemberName *mn;
- //int count=0;
- for (;(mn=mnli.current());++mnli)
- {
- MemberNameIterator mni(*mn);
- MemberDef *md;
- for (;(md=mni.current());++mni)
- {
- //printf("%04d Member `%s'\n",count++,md->name().data());
- if (md->documentation().isEmpty() && md->briefDescription().isEmpty())
- { // no documentation yet
- MemberDef *bmd = md->reimplements();
- while (bmd && bmd->documentation().isEmpty() &&
- bmd->briefDescription().isEmpty()
- )
- { // search up the inheritance tree for a documentation member
- //printf("bmd=%s class=%s\n",bmd->name().data(),bmd->getClassDef()->name().data());
- bmd = bmd->reimplements();
- }
- if (bmd) // copy the documentation from the reimplemented member
- {
- md->setInheritsDocsFrom(bmd);
- md->setDocumentation(bmd->documentation(),bmd->docFile(),bmd->docLine());
- md->setDocsForDefinition(bmd->isDocsForDefinition());
- md->setBriefDescription(bmd->briefDescription(),bmd->briefFile(),bmd->briefLine());
- md->copyArgumentNames(bmd);
- md->setInbodyDocumentation(bmd->inbodyDocumentation(),bmd->inbodyFile(),bmd->inbodyLine());
- }
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- static void combineUsingRelations()
- {
- // for each file
- FileNameListIterator fnli(*Doxygen::inputNameList);
- FileName *fn;
- for (fnli.toFirst();(fn=fnli.current());++fnli)
- {
- FileNameIterator fni(*fn);
- FileDef *fd;
- for (fni.toFirst();(fd=fni.current());++fni)
- {
- fd->visited=FALSE;
- }
- }
- for (fnli.toFirst();(fn=fnli.current());++fnli)
- {
- FileNameIterator fni(*fn);
- FileDef *fd;
- for (fni.toFirst();(fd=fni.current());++fni)
- {
- fd->combineUsingRelations();
- }
- }
- // for each namespace
- NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd;
- for (nli.toFirst() ; (nd=nli.current()) ; ++nli )
- {
- nd->visited=FALSE;
- }
- for (nli.toFirst() ; (nd=nli.current()) ; ++nli )
- {
- nd->combineUsingRelations();
- }
- }
- //----------------------------------------------------------------------------
-
- static void addMembersToMemberGroup()
- {
- // for each class
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
- for ( ; (cd=cli.current()) ; ++cli )
- {
- cd->addMembersToMemberGroup();
- }
- // for each file
- FileName *fn=Doxygen::inputNameList->first();
- while (fn)
- {
- FileDef *fd=fn->first();
- while (fd)
- {
- fd->addMembersToMemberGroup();
- fd=fn->next();
- }
- fn=Doxygen::inputNameList->next();
- }
- // for each namespace
- NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd;
- for ( ; (nd=nli.current()) ; ++nli )
- {
- nd->addMembersToMemberGroup();
- }
- // for each group
- GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
- for (gli.toFirst();(gd=gli.current());++gli)
- {
- gd->addMembersToMemberGroup();
- }
- }
- //----------------------------------------------------------------------------
- static void distributeMemberGroupDocumentation()
- {
- // for each class
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
- for ( ; (cd=cli.current()) ; ++cli )
- {
- cd->distributeMemberGroupDocumentation();
- }
- // for each file
- FileName *fn=Doxygen::inputNameList->first();
- while (fn)
- {
- FileDef *fd=fn->first();
- while (fd)
- {
- fd->distributeMemberGroupDocumentation();
- fd=fn->next();
- }
- fn=Doxygen::inputNameList->next();
- }
- // for each namespace
- NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd;
- for ( ; (nd=nli.current()) ; ++nli )
- {
- nd->distributeMemberGroupDocumentation();
- }
- // for each group
- GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
- for (gli.toFirst();(gd=gli.current());++gli)
- {
- gd->distributeMemberGroupDocumentation();
- }
- }
- //----------------------------------------------------------------------------
- static void findSectionsInDocumentation()
- {
- // for each class
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
- for ( ; (cd=cli.current()) ; ++cli )
- {
- cd->findSectionsInDocumentation();
- }
- // for each file
- FileName *fn=Doxygen::inputNameList->first();
- while (fn)
- {
- FileDef *fd=fn->first();
- while (fd)
- {
- fd->findSectionsInDocumentation();
- fd=fn->next();
- }
- fn=Doxygen::inputNameList->next();
- }
- // for each namespace
- NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd;
- for ( ; (nd=nli.current()) ; ++nli )
- {
- nd->findSectionsInDocumentation();
- }
- // for each group
- GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
- for (gli.toFirst();(gd=gli.current());++gli)
- {
- gd->findSectionsInDocumentation();
- }
- // for each page
- PageSDict::Iterator pdi(*Doxygen::pageSDict);
- PageDef *pd=0;
- for (pdi.toFirst();(pd=pdi.current());++pdi)
- {
- pd->findSectionsInDocumentation();
- }
- if (Doxygen::mainPage) Doxygen::mainPage->findSectionsInDocumentation();
- }
- static void flushCachedTemplateRelations()
- {
- // remove all references to classes from the cache
- // as there can be new template instances in the inheritance path
- // to this class. Optimization: only remove those classes that
- // have inheritance instances as direct or indirect sub classes.
- QCacheIterator<LookupInfo> ci(Doxygen::lookupCache);
- LookupInfo *li=0;
- for (ci.toFirst();(li=ci.current());++ci)
- {
- if (li->classDef)
- {
- Doxygen::lookupCache.remove(ci.currentKey());
- }
- }
- // remove all cached typedef resolutions whose target is a
- // template class as this may now be a template instance
- MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
- MemberName *fn;
- for (;(fn=fnli.current());++fnli) // for each global function name
- {
- MemberNameIterator fni(*fn);
- MemberDef *fmd;
- for (;(fmd=fni.current());++fni) // for each function with that name
- {
- if (fmd->isTypedefValCached())
- {
- ClassDef *cd = fmd->getCachedTypedefVal();
- if (cd->isTemplate()) fmd->invalidateTypedefValCache();
- }
- }
- }
- MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
- for (;(fn=mnli.current());++mnli) // for each class method name
- {
- MemberNameIterator mni(*fn);
- MemberDef *fmd;
- for (;(fmd=mni.current());++mni) // for each function with that name
- {
- if (fmd->isTypedefValCached())
- {
- ClassDef *cd = fmd->getCachedTypedefVal();
- if (cd->isTemplate()) fmd->invalidateTypedefValCache();
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- static void flushUnresolvedRelations()
- {
- // Remove all unresolved references to classes from the cache.
- // This is needed before resolving the inheritance relations, since
- // it would otherwise not find the inheritance relation
- // for C in the example below, as B::I was already found to be unresolvable
- // (which is correct if you igore the inheritance relation between A and B).
- //
- // class A { class I {} };
- // class B : public A {};
- // class C : public B::I {};
- //
- QCacheIterator<LookupInfo> ci(Doxygen::lookupCache);
- LookupInfo *li=0;
- for (ci.toFirst();(li=ci.current());++ci)
- {
- if (li->classDef==0 && li->typeDef==0)
- {
- Doxygen::lookupCache.remove(ci.currentKey());
- }
- }
- MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
- MemberName *fn;
- for (;(fn=fnli.current());++fnli) // for each global function name
- {
- MemberNameIterator fni(*fn);
- MemberDef *fmd;
- for (;(fmd=fni.current());++fni) // for each function with that name
- {
- fmd->invalidateCachedArgumentTypes();
- }
- }
- MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
- for (;(fn=mnli.current());++mnli) // for each class method name
- {
- MemberNameIterator mni(*fn);
- MemberDef *fmd;
- for (;(fmd=mni.current());++mni) // for each function with that name
- {
- fmd->invalidateCachedArgumentTypes();
- }
- }
- }
- //----------------------------------------------------------------------------
- static void findDefineDocumentation(EntryNav *rootNav)
- {
- if ((rootNav->section()==Entry::DEFINEDOC_SEC ||
- rootNav->section()==Entry::DEFINE_SEC) && !rootNav->name().isEmpty()
- )
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
-
- //printf("found define `%s' `%s' brief=`%s' doc=`%s'\n",
- // root->name.data(),root->args.data(),root->brief.data(),root->doc.data());
- if (rootNav->tagInfo() && !root->name.isEmpty()) // define read from a tag file
- {
- MemberDef *md=new MemberDef("<tagfile>",1,
- "#define",root->name,root->args,0,
- Public,Normal,FALSE,Member,MemberDef::Define,0,0);
- md->setTagInfo(rootNav->tagInfo());
- //printf("Searching for `%s' fd=%p\n",filePathName.data(),fd);
- md->setFileDef(rootNav->parent()->fileDef());
- //printf("Adding member=%s\n",md->name().data());
- MemberName *mn;
- if ((mn=Doxygen::functionNameSDict->find(root->name)))
- {
- mn->append(md);
- }
- else
- {
- mn = new MemberName(root->name);
- mn->append(md);
- Doxygen::functionNameSDict->append(root->name,mn);
- }
- }
- MemberName *mn=Doxygen::functionNameSDict->find(root->name);
- if (mn)
- {
- int count=0;
- MemberDef *md=mn->first();
- while (md)
- {
- if (md->memberType()==MemberDef::Define) count++;
- md=mn->next();
- }
- if (count==1)
- {
- md=mn->first();
- while (md)
- {
- if (md->memberType()==MemberDef::Define)
- {
- #if 0
- if (md->documentation().isEmpty())
- #endif
- {
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setDocsForDefinition(!root->proto);
- }
- #if 0
- if (md->briefDescription().isEmpty())
- #endif
- {
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- }
- if (md->inbodyDocumentation().isEmpty())
- {
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- }
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setBodyDef(rootNav->fileDef());
- md->addSectionsToDefinition(root->anchors);
- md->setMaxInitLines(root->initLines);
- md->setRefItems(root->sli);
- if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId);
- addMemberToGroups(root,md);
- }
- md=mn->next();
- }
- }
- else if (count>1 &&
- (!root->doc.isEmpty() ||
- !root->brief.isEmpty() ||
- root->bodyLine!=-1
- )
- )
- // multiple defines don't know where to add docs
- // but maybe they are in different files together with their documentation
- {
- md=mn->first();
- while (md)
- {
- if (md->memberType()==MemberDef::Define)
- {
- FileDef *fd=md->getFileDef();
- if (fd && fd->absFilePath()==root->fileName)
- // doc and define in the same file assume they belong together.
- {
- #if 0
- if (md->documentation().isEmpty())
- #endif
- {
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setDocsForDefinition(!root->proto);
- }
- #if 0
- if (md->briefDescription().isEmpty())
- #endif
- {
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- }
- if (md->inbodyDocumentation().isEmpty())
- {
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- }
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setBodyDef(rootNav->fileDef());
- md->addSectionsToDefinition(root->anchors);
- md->setRefItems(root->sli);
- if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId);
- addMemberToGroups(root,md);
- }
- }
- md=mn->next();
- }
- //warn("Warning: define %s found in the following files:\n",root->name.data());
- //warn("Cannot determine where to add the documentation found "
- // "at line %d of file %s. \n",
- // root->startLine,root->fileName.data());
- }
- }
- else if (!root->doc.isEmpty() || !root->brief.isEmpty()) // define not found
- {
- static bool preEnabled = Config_getBool("ENABLE_PREPROCESSING");
- if (preEnabled)
- {
- warn(root->fileName,root->startLine,
- "Warning: documentation for unknown define %s found.\n",
- root->name.data()
- );
- }
- else
- {
- warn(root->fileName,root->startLine,
- "Warning: found documented #define but ignoring it because "
- "ENABLE_PREPROCESSING is NO.\n",
- root->name.data()
- );
- }
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(findDefineDocumentation,rootNav);
- }
- //----------------------------------------------------------------------------
- static void findDirDocumentation(EntryNav *rootNav)
- {
- if (rootNav->section() == Entry::DIRDOC_SEC)
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- QCString normalizedName = root->name;
- normalizedName = substitute(normalizedName,"\\","/");
- //printf("root->docFile=%s normalizedName=%s\n",
- // root->docFile.data(),normalizedName.data());
- if (root->docFile==normalizedName) // current dir?
- {
- int lastSlashPos=normalizedName.findRev('/');
- if (lastSlashPos!=-1) // strip file name
- {
- normalizedName=normalizedName.left(lastSlashPos);
- }
- }
- if (normalizedName.at(normalizedName.length()-1)!='/')
- {
- normalizedName+='/';
- }
- DirDef *dir,*matchingDir=0;
- SDict<DirDef>::Iterator sdi(*Doxygen::directories);
- for (sdi.toFirst();(dir=sdi.current());++sdi)
- {
- //printf("Dir: %s<->%s\n",dir->name().data(),normalizedName.data());
- if (dir->name().right(normalizedName.length())==normalizedName)
- {
- if (matchingDir)
- {
- warn(root->fileName,root->startLine,
- "Warning: \\dir command matches multiple directories.\n"
- " Applying the command for directory %s\n"
- " Ignoring the command for directory %s\n",
- matchingDir->name().data(),dir->name().data()
- );
- }
- else
- {
- matchingDir=dir;
- }
- }
- }
- if (matchingDir)
- {
- //printf("Match for with dir %s\n",matchingDir->name().data());
- matchingDir->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- matchingDir->setDocumentation(root->doc,root->docFile,root->docLine);
- matchingDir->setRefItems(root->sli);
- addDirToGroups(root,matchingDir);
- }
- else
- {
- warn(root->fileName,root->startLine,"Warning: No matching "
- "directory found for command \\dir %s\n",normalizedName.data());
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(findDirDocumentation,rootNav);
- }
- //----------------------------------------------------------------------------
- // create a (sorted) list of separate documentation pages
- static void buildPageList(EntryNav *rootNav)
- {
- if (rootNav->section() == Entry::PAGEDOC_SEC)
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- if (!root->name.isEmpty())
- {
- addRelatedPage(rootNav);
- }
- rootNav->releaseEntry();
- }
- else if (rootNav->section() == Entry::MAINPAGEDOC_SEC)
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- QCString title=root->args.stripWhiteSpace();
- if (title.isEmpty()) title=theTranslator->trMainPage();
- QCString name = Config_getBool("GENERATE_TREEVIEW")?"main":"index";
- addRefItem(root->sli,
- name,
- "page",
- name,
- title,
- 0
- );
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(buildPageList,rootNav);
- }
- static void findMainPage(EntryNav *rootNav)
- {
- if (rootNav->section() == Entry::MAINPAGEDOC_SEC)
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- if (Doxygen::mainPage==0)
- {
- //printf("Found main page! \n======\n%s\n=======\n",root->doc.data());
- QCString title=root->args.stripWhiteSpace();
- QCString indexName=Config_getBool("GENERATE_TREEVIEW")?"main":"index";
- Doxygen::mainPage = new PageDef(root->fileName,root->startLine,
- indexName, root->brief+root->doc+root->inbodyDocs,title);
- //setFileNameForSections(root->anchors,"index",Doxygen::mainPage);
- Doxygen::mainPage->setFileName(indexName);
- addPageToContext(Doxygen::mainPage,rootNav);
-
- // a page name is a label as well!
- SectionInfo *si=new SectionInfo(
- indexName,
- Doxygen::mainPage->name(),
- Doxygen::mainPage->title(),
- SectionInfo::Page);
- Doxygen::sectionDict.insert(indexName,si);
- Doxygen::mainPage->addSectionsToDefinition(root->anchors);
- }
- else
- {
- warn(root->fileName,root->startLine,
- "Warning: found more than one \\mainpage comment block! Skipping this "
- "block."
- );
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(findMainPage,rootNav);
- }
- static void computePageRelations(EntryNav *rootNav)
- {
- if ((rootNav->section()==Entry::PAGEDOC_SEC ||
- rootNav->section()==Entry::MAINPAGEDOC_SEC
- )
- && !rootNav->name().isEmpty()
- )
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- PageDef *pd = root->section==Entry::PAGEDOC_SEC ?
- Doxygen::pageSDict->find(root->name) :
- Doxygen::mainPage;
- if (pd)
- {
- QListIterator<BaseInfo> bii(*root->extends);
- BaseInfo *bi;
- for (bii.toFirst();(bi=bii.current());++bii)
- {
- PageDef *subPd = Doxygen::pageSDict->find(bi->name);
- if (subPd)
- {
- pd->addInnerCompound(subPd);
- //printf("*** Added subpage relation: %s->%s\n",
- // pd->name().data(),subPd->name().data());
- }
- }
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(computePageRelations,rootNav);
- }
- static void checkPageRelations()
- {
- PageSDict::Iterator pdi(*Doxygen::pageSDict);
- PageDef *pd=0;
- for (pdi.toFirst();(pd=pdi.current());++pdi)
- {
- Definition *ppd = pd->getOuterScope();
- while (ppd)
- {
- if (ppd==pd)
- {
- err("Warning: page defined at line %d of file %s with label %s is a subpage "
- "of itself! Please remove this cyclic dependency.\n",
- pd->docLine(),pd->docFile().data(),pd->name().data());
- exit(1);
- }
- ppd=ppd->getOuterScope();
- }
- }
- }
- //----------------------------------------------------------------------------
- static void resolveUserReferences()
- {
- QDictIterator<SectionInfo> sdi(Doxygen::sectionDict);
- SectionInfo *si;
- for (;(si=sdi.current());++sdi)
- {
- //printf("si->label=`%s' si->definition=%s si->fileName=`%s'\n",
- // si->label.data(),si->definition?si->definition->name().data():"<none>",
- // si->fileName.data());
- PageDef *pd=0;
- // hack: the items of a todo/test/bug/deprecated list are all fragments from
- // different files, so the resulting section's all have the wrong file
- // name (not from the todo/test/bug/deprecated list, but from the file in
- // which they are defined). We correct this here by looking at the
- // generated section labels!
- QDictIterator<RefList> rli(*Doxygen::xrefLists);
- RefList *rl;
- for (rli.toFirst();(rl=rli.current());++rli)
- {
- QCString label="_"+rl->listName(); // "_todo", "_test", ...
- if (si->label.left(label.length())==label)
- {
- si->fileName=rl->listName();
- si->generated=TRUE;
- break;
- }
- }
- //printf("start: si->label=%s si->fileName=%s\n",si->label.data(),si->fileName.data());
- if (!si->generated)
- {
- // if this section is in a page and the page is in a group, then we
- // have to adjust the link file name to point to the group.
- if (!si->fileName.isEmpty() &&
- (pd=Doxygen::pageSDict->find(si->fileName)) &&
- pd->getGroupDef())
- {
- si->fileName=pd->getGroupDef()->getOutputFileBase().copy();
- }
- if (si->definition)
- {
- // TODO: there should be one function in Definition that returns
- // the file to link to, so we can avoid the following tests.
- GroupDef *gd=0;
- if (si->definition->definitionType()==Definition::TypeMember)
- {
- gd = ((MemberDef *)si->definition)->getGroupDef();
- }
- if (gd)
- {
- si->fileName=gd->getOutputFileBase().copy();
- }
- else
- {
- //si->fileName=si->definition->getOutputFileBase().copy();
- //printf("Setting si->fileName to %s\n",si->fileName.data());
- }
- }
- }
- //printf("end: si->label=%s si->fileName=%s\n",si->label.data(),si->fileName.data());
- }
- }
- //----------------------------------------------------------------------------
- // generate all separate documentation pages
- static void generatePageDocs()
- {
- //printf("documentedPages=%d real=%d\n",documentedPages,Doxygen::pageSDict->count());
- if (documentedPages==0) return;
- PageSDict::Iterator pdi(*Doxygen::pageSDict);
- PageDef *pd=0;
- for (pdi.toFirst();(pd=pdi.current());++pdi)
- {
- if (!pd->getGroupDef() && !pd->isReference())
- {
- msg("Generating docs for page %s...\n",pd->name().data());
- Doxygen::insideMainPage=TRUE;
- pd->writeDocumentation(*g_outputList);
- Doxygen::insideMainPage=FALSE;
- }
- }
- }
- //----------------------------------------------------------------------------
- // create a (sorted) list & dictionary of example pages
- static void buildExampleList(EntryNav *rootNav)
- {
- if (rootNav->section()==Entry::EXAMPLE_SEC && !rootNav->name().isEmpty())
- {
- rootNav->loadEntry(g_storage);
- Entry *root = rootNav->entry();
- if (Doxygen::exampleSDict->find(root->name))
- {
- warn(root->fileName,root->startLine,
- "Warning: Example %s was already documented. Ignoring "
- "documentation found here.",
- root->name.data()
- );
- }
- else
- {
- PageDef *pd=new PageDef(root->fileName,root->startLine,
- root->name,root->brief+root->doc+root->inbodyDocs,root->args);
- pd->setFileName(convertNameToFile(pd->name()+"-example",TRUE,FALSE));
- pd->addSectionsToDefinition(root->anchors);
- //pi->addSections(root->anchors);
- Doxygen::exampleSDict->inSort(root->name,pd);
- //we don't add example to groups
- //addExampleToGroups(root,pd);
- }
- rootNav->releaseEntry();
- }
- RECURSE_ENTRYTREE(buildExampleList,rootNav);
- }
- //----------------------------------------------------------------------------
- // prints the Entry tree (for debugging)
- void printNavTree(EntryNav *rootNav,int indent)
- {
- QCString indentStr;
- indentStr.fill(' ',indent);
- msg("%s%s (sec=0x%x)\n",
- indentStr.isEmpty()?"":indentStr.data(),
- rootNav->name().isEmpty()?"<empty>":rootNav->name().data(),
- rootNav->section());
- if (rootNav->children())
- {
- EntryNavListIterator eli(*rootNav->children());
- for (;eli.current();++eli) printNavTree(eli.current(),indent+2);
- }
- }
- //----------------------------------------------------------------------------
- // generate the example documentation
- static void generateExampleDocs()
- {
- g_outputList->disable(OutputGenerator::Man);
- PageSDict::Iterator pdi(*Doxygen::exampleSDict);
- PageDef *pd=0;
- for (pdi.toFirst();(pd=pdi.current());++pdi)
- {
- msg("Generating docs for example %s...\n",pd->name().data());
- resetCCodeParserState();
- QCString n=pd->getOutputFileBase();
- startFile(*g_outputList,n,n,pd->name());
- startTitle(*g_outputList,n);
- g_outputList->docify(pd->name());
- endTitle(*g_outputList,n,0);
- g_outputList->parseDoc(pd->docFile(), // file
- pd->docLine(), // startLine
- pd, // context
- 0, // memberDef
- pd->documentation()+"\n\n\\include "+pd->name(), // docs
- TRUE, // index words
- TRUE, // is example
- pd->name()
- );
- endFile(*g_outputList);
- }
- g_outputList->enable(OutputGenerator::Man);
- }
- //----------------------------------------------------------------------------
- // generate module pages
- static void generateGroupDocs()
- {
- GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
- for (gli.toFirst();(gd=gli.current());++gli)
- {
- if (!gd->isReference())
- {
- gd->writeDocumentation(*g_outputList);
- }
- }
- }
- //----------------------------------------------------------------------------
- //static void generatePackageDocs()
- //{
- // writePackageIndex(*g_outputList);
- //
- // if (Doxygen::packageDict.count()>0)
- // {
- // PackageSDict::Iterator pdi(Doxygen::packageDict);
- // PackageDef *pd;
- // for (pdi.toFirst();(pd=pdi.current());++pdi)
- // {
- // pd->writeDocumentation(*g_outputList);
- // }
- // }
- //}
- //----------------------------------------------------------------------------
- // generate module pages
- static void generateNamespaceDocs()
- {
- writeNamespaceIndex(*g_outputList);
-
- NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd;
- // for each namespace...
- for (;(nd=nli.current());++nli)
- {
- if (nd->isLinkableInProject())
- {
- msg("Generating docs for namespace %s\n",nd->name().data());
- nd->writeDocumentation(*g_outputList);
- }
- // for each class in the namespace...
- ClassSDict::Iterator cli(*nd->getClassSDict());
- for ( ; cli.current() ; ++cli )
- {
- ClassDef *cd=cli.current();
- if ( ( cd->isLinkableInProject() &&
- cd->templateMaster()==0
- ) // skip external references, anonymous compounds and
- // template instances and nested classes
- && !cd->isHidden()
- )
- {
- msg("Generating docs for compound %s...\n",cd->name().data());
- cd->writeDocumentation(*g_outputList);
- cd->writeMemberList(*g_outputList);
- }
- cd->writeDocumentationForInnerClasses(*g_outputList);
- }
- }
- }
- #if defined(_WIN32)
- static QCString fixSlashes(QCString &s)
- {
- QCString result;
- uint i;
- for (i=0;i<s.length();i++)
- {
- switch(s.at(i))
- {
- case '/':
- case '\\':
- result+="\\\\";
- break;
- default:
- result+=s.at(i);
- }
- }
- return result;
- }
- #endif
- //----------------------------------------------------------------------------
- // generate files for the search engine
- //static void generateSearchIndex()
- //{
- // if (Config_getBool("SEARCHENGINE") && Config_getBool("GENERATE_HTML"))
- // {
- // // create search index
- // QCString fileName;
- // writeSearchButton(Config_getString("HTML_OUTPUT"));
- //
- //#if !defined(_WIN32)
- // // create cgi script
- // fileName = Config_getString("HTML_OUTPUT")+"/"+Config_getString("CGI_NAME");
- // QFile f(fileName);
- // if (f.open(IO_WriteOnly))
- // {
- // QTextStream t(&f);
- // t << "#!/bin/sh" << endl
- // << "DOXYSEARCH=" << Config_getString("BIN_ABSPATH") << "/doxysearch" << endl
- // << "DOXYPATH=\"" << Config_getString("DOC_ABSPATH") << " ";
- //
- // QStrList &extDocPaths=Config_getList("EXT_DOC_PATHS");
- // char *s= extDocPaths.first();
- // while (s)
- // {
- // t << s << " ";
- // s=extDocPaths.next();
- // }
- //
- // t << "\"" << endl
- // << "if [ -f $DOXYSEARCH ]" << endl
- // << "then" << endl
- // << " $DOXYSEARCH $DOXYPATH" << endl
- // << "else" << endl
- // << " echo \"Content-Type: text/html\"" << endl
- // << " echo \"\"" << endl
- // << " echo \"<h2>Error: $DOXYSEARCH not found. Check cgi script!</h2>\"" << endl
- // << "fi" << endl;
- //
- // f.close();
- // struct stat stat_struct;
- // stat(fileName,&stat_struct);
- // chmod(fileName,stat_struct.st_mode|S_IXUSR|S_IXGRP|S_IXOTH);
- // }
- // else
- // {
- // err("Error: Cannot open file %s for writing\n",fileName.data());
- // }
- //#else /* Windows platform */
- // // create cgi program
- // fileName = Config_getString("CGI_NAME").copy();
- // if (fileName.right(4)==".cgi")
- // fileName=fileName.left(fileName.length()-4);
- // fileName+=".c";
- // fileName.prepend(Config_getString("HTML_OUTPUT")+"/");
- // QFile f(fileName);
- // if (f.open(IO_WriteOnly))
- // {
- // QTextStream t(&f);
- // t << "#include <stdio.h>" << endl;
- // t << "#include <stdlib.h>" << endl;
- // t << "#include <process.h>" << endl;
- // t << endl;
- // t << "const char *DOXYSEARCH = \"" <<
- // fixSlashes(Config_getString("BIN_ABSPATH")) << "\\\\doxysearch.exe\";" << endl;
- // t << "const char *DOXYPATH = \"" <<
- // fixSlashes(Config_getString("DOC_ABSPATH")) << "\";" << endl;
- // t << endl;
- // t << "int main(void)" << endl;
- // t << "{" << endl;
- // t << " char buf[1024];" << endl;
- // t << " sprintf(buf,\"%s %s\",DOXYSEARCH,DOXYPATH);" << endl;
- // t << " if (system(buf))" << endl;
- // t << " {" << endl;
- // t << " printf(\"Content-Type: text/html\\n\\n\");" << endl;
- // t << " printf(\"<h2>Error: failed to execute %s</h2>\\n\",DOXYSEARCH);" << endl;
- // t << " exit(1);" << endl;
- // t << " }" << endl;
- // t << " return 0;" << endl;
- // t << "}" << endl;
- // f.close();
- // }
- // else
- // {
- // err("Error: Cannot open file %s for writing\n",fileName.data());
- // }
- //#endif /* !defined(_WIN32) */
- //
- // // create config file
- // fileName = Config_getString("HTML_OUTPUT")+"/search.cfg";
- // f.setName(fileName);
- // if (f.open(IO_WriteOnly))
- // {
- // QTextStream t(&f);
- // t << Config_getString("DOC_URL") << "/" << endl
- // << Config_getString("CGI_URL") << "/" << Config_getString("CGI_NAME") << endl;
- // f.close();
- // }
- // else
- // {
- // err("Error: Cannot open file %s for writing\n",fileName.data());
- // }
- // //g_outputList->generateExternalIndex();
- // g_outputList->pushGeneratorState();
- // g_outputList->disableAllBut(OutputGenerator::Html);
- // startFile(*g_outputList,"header"+Doxygen::htmlFileExtension,0,"Search Engine",TRUE);
- // g_outputList->endPlainFile();
- // g_outputList->startPlainFile("footer"+Doxygen::htmlFileExtension);
- // endFile(*g_outputList,TRUE);
- // g_outputList->popGeneratorState();
- // }
- //}
- //----------------------------------------------------------------------------
- static bool openOutputFile(const char *outFile,QFile &f)
- {
- bool fileOpened=FALSE;
- bool writeToStdout=(outFile[0]=='-' && outFile[1]=='\0');
- if (writeToStdout) // write to stdout
- {
- fileOpened = f.open(IO_WriteOnly,stdout);
- }
- else // write to file
- {
- QFileInfo fi(outFile);
- if (fi.exists()) // create a backup
- {
- QDir dir=fi.dir();
- QFileInfo backup(fi.fileName()+".bak");
- if (backup.exists()) // remove existing backup
- dir.remove(backup.fileName());
- dir.rename(fi.fileName(),fi.fileName()+".bak");
- }
- f.setName(outFile);
- fileOpened = f.open(IO_WriteOnly|IO_Translate);
- }
- return fileOpened;
- }
- /*! Generate a template version of the configuration file.
- * If the \a shortList parameter is TRUE a configuration file without
- * comments will be generated.
- */
- static void generateConfigFile(const char *configFile,bool shortList,
- bool updateOnly=FALSE)
- {
- QFile f;
- bool fileOpened=openOutputFile(configFile,f);
- bool writeToStdout=(configFile[0]=='-' && configFile[1]=='\0');
- if (fileOpened)
- {
- QTextStream t(&f);
- t.setEncoding(QTextStream::UnicodeUTF8);
- Config::instance()->writeTemplate(t,shortList,updateOnly);
- if (!writeToStdout)
- {
- if (!updateOnly)
- {
- msg("\n\nConfiguration file `%s' created.\n\n",configFile);
- msg("Now edit the configuration file and enter\n\n");
- if (strcmp(configFile,"Doxyfile") || strcmp(configFile,"doxyfile"))
- msg(" doxygen %s\n\n",configFile);
- else
- msg(" doxygen\n\n");
- msg("to generate the documentation for your project\n\n");
- }
- else
- {
- msg("\n\nConfiguration file `%s' updated.\n\n",configFile);
- }
- }
- }
- else
- {
- err("Error: Cannot open file %s for writing\n",configFile);
- exit(1);
- }
- }
- //----------------------------------------------------------------------------
- // read and parse a tag file
- //static bool readLineFromFile(QFile &f,QCString &s)
- //{
- // char c=0;
- // s.resize(0);
- // while (!f.atEnd() && (c=f.getch())!='\n') s+=c;
- // return f.atEnd();
- //}
- //----------------------------------------------------------------------------
- static void readTagFile(Entry *root,const char *tl)
- {
- QCString tagLine = tl;
- QCString fileName;
- QCString destName;
- int eqPos = tagLine.find('=');
- if (eqPos!=-1) // tag command contains a destination
- {
- fileName = tagLine.left(eqPos).stripWhiteSpace();
- destName = tagLine.right(tagLine.length()-eqPos-1).stripWhiteSpace();
- QFileInfo fi(fileName);
- Doxygen::tagDestinationDict.insert(fi.fileName(),new QCString(destName));
- //printf("insert tagDestination %s->%s\n",fi.fileName().data(),destName.data());
- }
- else
- {
- fileName = tagLine;
- }
-
- QFileInfo fi(fileName);
- if (!fi.exists() || !fi.isFile())
- {
- err("Error: Tag file `%s' does not exist or is not a file. Skipping it...\n",
- fileName.data());
- return;
- }
- if (!destName.isEmpty())
- msg("Reading tag file `%s', location `%s'...\n",fileName.data(),destName.data());
- else
- msg("Reading tag file `%s'...\n",fileName.data());
- parseTagFile(root,fi.absFilePath(),fi.fileName());
- }
- //----------------------------------------------------------------------------
- static void copyStyleSheet()
- {
- QCString &htmlStyleSheet = Config_getString("HTML_STYLESHEET");
- if (!htmlStyleSheet.isEmpty())
- {
- QFile cssf(htmlStyleSheet);
- QFileInfo cssfi(htmlStyleSheet);
- if (cssf.open(IO_ReadOnly))
- {
- QCString destFileName = Config_getString("HTML_OUTPUT")+"/"+cssfi.fileName().data();
- QFile df(destFileName);
- if (df.open(IO_WriteOnly))
- {
- char *buffer = new char[cssf.size()];
- cssf.readBlock(buffer,cssf.size());
- df.writeBlock(buffer,cssf.size());
- df.flush();
- delete[] buffer;
- }
- else
- {
- err("Error: could not write to style sheet %s\n",destFileName.data());
- }
- }
- else
- {
- err("Error: could not open user specified style sheet %s\n",Config_getString("HTML_STYLESHEET").data());
- htmlStyleSheet.resize(0); // revert to the default
- }
- }
- }
- //! parse the list of input files
- static void parseFiles(Entry *root,EntryNav *rootNav)
- {
- #if 0
- void *cd = 0;
- QCString inpEncoding = Config_getString("INPUT_ENCODING");
- bool needsTranscoding = !inpEncoding.isEmpty();
- if (needsTranscoding)
- {
- if (!(cd = portable_iconv_open("UTF-8", inpEncoding)))
- {
- err("Error: unsupported character enconding: '%s'",inpEncoding.data());
- exit(1);
- }
- }
- #endif
- QCString *s=g_inputFiles.first();
- while (s)
- {
- QCString fileName=*s;
- QCString extension;
- int ei = fileName.findRev('.');
- if (ei!=-1) extension=fileName.right(fileName.length()-ei);
- ParserInterface *parser = Doxygen::parserManager->getParser(extension);
- QFileInfo fi(fileName);
- BufStr preBuf(fi.size()+4096);
- if (Config_getBool("ENABLE_PREPROCESSING") &&
- parser->needsPreprocessing(extension))
- {
- BufStr inBuf(fi.size()+4096);
- msg("Preprocessing %s...\n",s->data());
- readInputFile(fileName,inBuf);
- preprocessFile(fileName,inBuf,preBuf);
- }
- else // no preprocessing
- {
- msg("Reading %s...\n",s->data());
- readInputFile(fileName,preBuf);
- }
- BufStr convBuf(preBuf.curPos()+1024);
- // convert multi-line C++ comments to C style comments
- convertCppComments(&preBuf,&convBuf,fileName);
- convBuf.addChar('\0');
- // use language parse to parse the file
- parser->parseInput(fileName,convBuf.data(),root);
- // store the Entry tree in a file and create an index to
- // navigate/load entries
- bool ambig;
- FileDef *fd=findFileDef(Doxygen::inputNameDict,fileName,ambig);
- ASSERT(fd!=0);
- root->createNavigationIndex(rootNav,g_storage,fd);
- s=g_inputFiles.next();
- }
- }
- // resolves a path that may include symlinks, if a recursive symlink is
- // found an empty string is returned.
- static QCString resolveSymlink(QCString path)
- {
- int sepPos=0;
- QFileInfo fi;
- QDict<void> nonSymlinks;
- QDict<void> known;
- QCString result = path;
- QCString oldPrefix = "/";
- do
- {
- #ifdef WIN32
- // UNC path, skip server and share name
- if (sepPos==0 && (result.left(2)=="//" || result.left(2)=="\\\\"))
- sepPos = result.find('/',2);
- if (sepPos!=-1)
- sepPos = result.find('/',sepPos+1);
- #else
- sepPos = result.find('/',sepPos+1);
- #endif
- QCString prefix = sepPos==-1 ? result : result.left(sepPos);
- if (nonSymlinks.find(prefix)==0)
- {
- fi.setFile(prefix);
- if (fi.isSymLink())
- {
- QString target = fi.readLink();
- if (QFileInfo(target).isRelative())
- {
- target = QDir::cleanDirPath(oldPrefix+"/"+target.data());
- }
- if (sepPos!=-1)
- {
- if (fi.isDir() && target.length()>0 && target.at(target.length()-1)!='/')
- {
- target+='/';
- }
- target+=result.mid(sepPos);
- }
- result = QDir::cleanDirPath(target).data();
- sepPos = 0;
- if (known.find(result)) return QCString(); // recursive symlink!
- known.insert(result,(void*)0x8);
- }
- else
- {
- nonSymlinks.insert(prefix,(void*)0x8);
- }
- oldPrefix = prefix;
- }
- }
- while (sepPos!=-1);
- return QDir::cleanDirPath(result).data();
- }
- static QDict<void> g_pathsVisited(1009);
- //----------------------------------------------------------------------------
- // Read all files matching at least one pattern in `patList' in the
- // directory represented by `fi'.
- // The directory is read iff the recusiveFlag is set.
- // The contents of all files is append to the input string
- int readDir(QFileInfo *fi,
- FileNameList *fnList,
- FileNameDict *fnDict,
- StringDict *exclDict,
- QStrList *patList,
- QStrList *exclPatList,
- StringList *resultList,
- StringDict *resultDict,
- bool errorIfNotExist,
- bool recursive,
- QDict<void> *killDict
- )
- {
- QString dirName = fi->absFilePath();
- if (fi->isSymLink())
- {
- dirName = resolveSymlink(dirName.data());
- if (dirName.isEmpty()) return 0; // recusive symlink
- if (g_pathsVisited.find(dirName)) return 0; // already visited path
- g_pathsVisited.insert(dirName,(void*)0x8);
- }
- QDir dir(dirName);
- dir.setFilter( QDir::Files | QDir::Dirs | QDir::Hidden );
- int totalSize=0;
- msg("Searching for files in directory %s\n", fi->absFilePath().data());
- //printf("killDict=%p count=%d\n",killDict,killDict->count());
-
- const QFileInfoList *list = dir.entryInfoList();
- if (list)
- {
- QFileInfoListIterator it( *list );
- QFileInfo *cfi;
- while ((cfi=it.current()))
- {
- if (exclDict==0 || exclDict->find(cfi->absFilePath())==0)
- { // file should not be excluded
- //printf("killDict->find(%s)\n",cfi->absFilePath().data());
- if (!cfi->exists() || !cfi->isReadable())
- {
- if (errorIfNotExist)
- {
- err("Warning: source %s is not a readable file or directory... skipping.\n",cfi->absFilePath().data());
- }
- }
- else if (cfi->isFile() &&
- (!Config_getBool("EXCLUDE_SYMLINKS") || !cfi->isSymLink()) &&
- (patList==0 || patternMatch(*cfi,patList)) &&
- !patternMatch(*cfi,exclPatList) &&
- (killDict==0 || killDict->find(cfi->absFilePath())==0)
- )
- {
- totalSize+=cfi->size()+cfi->absFilePath().length()+4;
- QCString name=convertToQCString(cfi->fileName());
- //printf("New file %s\n",name.data());
- if (fnDict)
- {
- FileDef *fd=new FileDef(cfi->dirPath()+"/",name);
- FileName *fn=0;
- if (!name.isEmpty() && (fn=(*fnDict)[name]))
- {
- fn->append(fd);
- }
- else
- {
- fn = new FileName(cfi->absFilePath(),name);
- fn->append(fd);
- if (fnList) fnList->inSort(fn);
- fnDict->insert(name,fn);
- }
- }
- QCString *rs=0;
- if (resultList || resultDict)
- {
- rs=new QCString(cfi->absFilePath());
- }
- if (resultList) resultList->append(rs);
- if (resultDict) resultDict->insert(cfi->absFilePath(),rs);
- if (killDict) killDict->insert(cfi->absFilePath(),(void *)0x8);
- }
- else if (recursive &&
- (!Config_getBool("EXCLUDE_SYMLINKS") || !cfi->isSymLink()) &&
- cfi->isDir() && cfi->fileName()!="." &&
- !patternMatch(*cfi,exclPatList) &&
- cfi->fileName()!="..")
- {
- cfi->setFile(cfi->absFilePath());
- totalSize+=readDir(cfi,fnList,fnDict,exclDict,
- patList,exclPatList,resultList,resultDict,errorIfNotExist,
- recursive,killDict);
- }
- }
- ++it;
- }
- }
- return totalSize;
- }
- //----------------------------------------------------------------------------
- // read a file or all files in a directory and append their contents to the
- // input string. The names of the files are appended to the `fiList' list.
- int readFileOrDirectory(const char *s,
- FileNameList *fnList,
- FileNameDict *fnDict,
- StringDict *exclDict,
- QStrList *patList,
- QStrList *exclPatList,
- StringList *resultList,
- StringDict *resultDict,
- bool recursive,
- bool errorIfNotExist,
- QDict<void> *killDict
- )
- {
- //printf("killDict=%p count=%d\n",killDict,killDict->count());
- // strip trailing slashes
- if (s==0) return 0;
- QCString fs = s;
- char lc = fs.at(fs.length()-1);
- if (lc=='/' || lc=='\\') fs = fs.left(fs.length()-1);
- QFileInfo fi(fs);
- //printf("readFileOrDirectory(%s)\n",s);
- int totalSize=0;
- {
- if (exclDict==0 || exclDict->find(fi.absFilePath())==0)
- {
- if (!fi.exists() || !fi.isReadable())
- {
- if (errorIfNotExist)
- {
- err("Warning: source %s is not a readable file or directory... skipping.\n",s);
- }
- }
- else if (!Config_getBool("EXCLUDE_SYMLINKS") || !fi.isSymLink())
- {
- if (fi.isFile())
- {
- //printf("killDict->find(%s)\n",fi.absFilePath().data());
- if (killDict==0 || killDict->find(fi.absFilePath())==0)
- {
- totalSize+=fi.size()+fi.absFilePath().length()+4; //readFile(&fi,fiList,input);
- //fiList->inSort(new FileInfo(fi));
- QCString name=convertToQCString(fi.fileName());
- //printf("New file %s\n",name.data());
- if (fnDict)
- {
- FileDef *fd=new FileDef(fi.dirPath(TRUE)+"/",name);
- FileName *fn=0;
- if (!name.isEmpty() && (fn=(*fnDict)[name]))
- {
- fn->append(fd);
- }
- else
- {
- fn = new FileName(fi.absFilePath(),name);
- fn->append(fd);
- if (fnList) fnList->inSort(fn);
- fnDict->insert(name,fn);
- }
- }
- QCString *rs=0;
- if (resultList || resultDict)
- {
- rs=new QCString(fi.absFilePath());
- if (resultList) resultList->append(rs);
- if (resultDict) resultDict->insert(fi.absFilePath(),rs);
- }
- if (killDict) killDict->insert(fi.absFilePath(),(void *)0x8);
- }
- }
- else if (fi.isDir()) // readable dir
- {
- totalSize+=readDir(&fi,fnList,fnDict,exclDict,patList,
- exclPatList,resultList,resultDict,errorIfNotExist,
- recursive,killDict);
- }
- }
- }
- }
- return totalSize;
- }
- //----------------------------------------------------------------------------
- void readFormulaRepository()
- {
- QFile f(Config_getString("HTML_OUTPUT")+"/formula.repository");
- if (f.open(IO_ReadOnly)) // open repository
- {
- msg("Reading formula repository...\n");
- QTextStream t(&f);
- QCString line;
- while (!t.eof())
- {
- line=t.readLine();
- int se=line.find(':'); // find name and text separator.
- if (se==-1)
- {
- err("Warning: formula.repository is corrupted!\n");
- break;
- }
- else
- {
- QCString formName = line.left(se);
- QCString formText = line.right(line.length()-se-1);
- Formula *f=new Formula(formText);
- Doxygen::formulaList.append(f);
- Doxygen::formulaDict.insert(formText,f);
- Doxygen::formulaNameDict.insert(formName,f);
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- static void expandAliases()
- {
- QDictIterator<QCString> adi(Doxygen::aliasDict);
- QCString *s;
- for (adi.toFirst();(s=adi.current());++adi)
- {
- *s = expandAlias(adi.currentKey(),*s);
- }
- }
- //----------------------------------------------------------------------------
- static void escapeAliases()
- {
- QDictIterator<QCString> adi(Doxygen::aliasDict);
- QCString *s;
- for (adi.toFirst();(s=adi.current());++adi)
- {
- QCString value=*s,newValue;
- int in,p=0;
- // for each \n in the alias command value
- while ((in=value.find("\\n",p))!=-1)
- {
- newValue+=value.mid(p,in-p);
- // expand \n's except if \n is part of a built-in command.
- if (value.mid(in,5)!="\\note" &&
- value.mid(in,5)!="\\name" &&
- value.mid(in,10)!="\\namespace" &&
- value.mid(in,14)!="\\nosubgrouping"
- )
- {
- newValue+="\\_linebr ";
- }
- else
- {
- newValue+="\\n";
- }
- p=in+2;
- }
- newValue+=value.mid(p,value.length()-p);
- *s=newValue;
- //printf("Alias %s has value %s\n",adi.currentKey().data(),s->data());
- }
- }
- //----------------------------------------------------------------------------
- void readAliases()
- {
- // add aliases to a dictionary
- Doxygen::aliasDict.setAutoDelete(TRUE);
- QStrList &aliasList = Config_getList("ALIASES");
- const char *s=aliasList.first();
- while (s)
- {
- if (Doxygen::aliasDict[s]==0)
- {
- QCString alias=s;
- int i=alias.find('=');
- if (i>0)
- {
- QCString name=alias.left(i).stripWhiteSpace();
- QCString value=alias.right(alias.length()-i-1);
- //printf("Alias: found name=`%s' value=`%s'\n",name.data(),value.data());
- if (!name.isEmpty())
- {
- QCString *dn=Doxygen::aliasDict[name];
- if (dn==0) // insert new alias
- {
- Doxygen::aliasDict.insert(name,new QCString(value));
- }
- else // overwrite previous alias
- {
- *dn=value;
- }
- }
- }
- }
- s=aliasList.next();
- }
- expandAliases();
- escapeAliases();
- }
- //----------------------------------------------------------------------------
- static void dumpSymbol(QTextStream &t,Definition *d)
- {
- QCString anchor;
- if (d->definitionType()==Definition::TypeMember)
- {
- MemberDef *md = (MemberDef *)d;
- anchor=":"+md->anchor();
- }
- QCString scope;
- if (d->getOuterScope() && d->getOuterScope()!=Doxygen::globalScope)
- {
- scope = d->getOuterScope()->getOutputFileBase()+Doxygen::htmlFileExtension;
- }
- t << "REPLACE INTO symbols (symbol_id,scope_id,name,file,line) VALUES('"
- << d->getOutputFileBase()+Doxygen::htmlFileExtension+anchor << "','"
- << scope << "','"
- << d->name() << "','"
- << d->getDefFileName() << "','"
- << d->getDefLine()
- << "');" << endl;
- }
- static void dumpSymbolMap()
- {
- QFile f("symbols.sql");
- if (f.open(IO_WriteOnly))
- {
- QTextStream t(&f);
- QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap);
- DefinitionIntf *intf;
- for (;(intf=di.current());++di)
- {
- if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols
- {
- DefinitionListIterator dli(*(DefinitionList*)intf);
- Definition *d;
- // for each symbol
- for (dli.toFirst();(d=dli.current());++dli)
- {
- dumpSymbol(t,d);
- }
- }
- else // single symbol
- {
- Definition *d = (Definition *)intf;
- if (d!=Doxygen::globalScope) dumpSymbol(t,d);
- }
- }
- }
- }
- //----------------------------------------------------------------------------
- void dumpConfigAsXML()
- {
- QFile f("config.xml");
- if (f.open(IO_WriteOnly))
- {
- QTextStream t(&f);
- Config::instance()->writeXML(t);
- }
- }
- //----------------------------------------------------------------------------
- // print the usage of doxygen
- static void usage(const char *name)
- {
- msg("Doxygen version %s\nCopyright Dimitri van Heesch 1997-2010\n\n",versionString);
- msg("You can use doxygen in a number of ways:\n\n");
- msg("1) Use doxygen to generate a template configuration file:\n");
- msg(" %s [-s] -g [configName]\n\n",name);
- msg(" If - is used for configName doxygen will write to standard output.\n\n");
- msg("2) Use doxygen to update an old configuration file:\n");
- msg(" %s [-s] -u [configName]\n\n",name);
- msg("3) Use doxygen to generate documentation using an existing ");
- msg("configuration file:\n");
- msg(" %s [configName]\n\n",name);
- msg(" If - is used for configName doxygen will read from standard input.\n\n");
- msg("4) Use doxygen to generate a template file controlling the layout of the\n");
- msg(" generated documentation:\n");
- msg(" %s -l layoutFileName.xml\n\n",name);
- msg("5) Use doxygen to generate a template style sheet file for RTF, HTML or Latex.\n");
- msg(" RTF: %s -w rtf styleSheetFile\n",name);
- msg(" HTML: %s -w html headerFile footerFile styleSheetFile [configFile]\n",name);
- msg(" LaTeX: %s -w latex headerFile styleSheetFile [configFile]\n\n",name);
- msg("6) Use doxygen to generate an rtf extensions file\n");
- msg(" RTF: %s -e rtf extensionsFile\n\n",name);
- msg("If -s is specified the comments in the config file will be omitted.\n");
- msg("If configName is omitted `Doxyfile' will be used as a default.\n\n");
- exit(1);
- }
- //----------------------------------------------------------------------------
- // read the argument of option `c' from the comment argument list and
- // update the option index `optind'.
- static const char *getArg(int argc,char **argv,int &optind)
- {
- char *s=0;
- if (strlen(&argv[optind][2])>0)
- s=&argv[optind][2];
- else if (optind+1<argc && argv[optind+1][0]!='-')
- s=argv[++optind];
- return s;
- }
- //----------------------------------------------------------------------------
- extern void commentScanTest();
- void initDoxygen()
- {
- setlocale(LC_ALL,"");
- setlocale(LC_CTYPE,"C"); // to get isspace(0xA0)==0, needed for UTF-8
- setlocale(LC_NUMERIC,"C");
- //Doxygen::symbolMap->setAutoDelete(TRUE);
- Doxygen::runningTime.start();
- initPreprocessor();
- Doxygen::parserManager = new ParserManager;
- Doxygen::parserManager->registerParser("c", new CLanguageScanner, TRUE);
- Doxygen::parserManager->registerParser("python", new PythonLanguageScanner);
- Doxygen::parserManager->registerParser("fortran", new FortranLanguageScanner);
- Doxygen::parserManager->registerParser("vhdl", new VHDLLanguageScanner);
- Doxygen::parserManager->registerParser("dbusxml", new DBusXMLScanner);
- // register any additional parsers here...
- initDefaultExtensionMapping();
- initClassMemberIndices();
- initNamespaceMemberIndices();
- initFileMemberIndices();
- Doxygen::symbolMap = new QDict<DefinitionIntf>(1000);
- Doxygen::inputNameList = new FileNameList;
- Doxygen::inputNameList->setAutoDelete(TRUE);
- Doxygen::memberNameSDict = new MemberNameSDict(10000);
- Doxygen::memberNameSDict->setAutoDelete(TRUE);
- Doxygen::functionNameSDict = new MemberNameSDict(10000);
- Doxygen::functionNameSDict->setAutoDelete(TRUE);
- Doxygen::groupSDict = new GroupSDict(17);
- Doxygen::groupSDict->setAutoDelete(TRUE);
- Doxygen::globalScope = new NamespaceDef("<globalScope>",1,"<globalScope>");
- Doxygen::namespaceSDict = new NamespaceSDict(20);
- Doxygen::namespaceSDict->setAutoDelete(TRUE);
- Doxygen::classSDict = new ClassSDict(1009);
- Doxygen::classSDict->setAutoDelete(TRUE);
- Doxygen::hiddenClasses = new ClassSDict(257);
- Doxygen::hiddenClasses->setAutoDelete(TRUE);
- Doxygen::directories = new DirSDict(17);
- Doxygen::directories->setAutoDelete(TRUE);
- Doxygen::pageSDict = new PageSDict(1009); // all doc pages
- Doxygen::pageSDict->setAutoDelete(TRUE);
- Doxygen::exampleSDict = new PageSDict(1009); // all examples
- Doxygen::exampleSDict->setAutoDelete(TRUE);
- Doxygen::inputNameDict = new FileNameDict(10007);
- Doxygen::includeNameDict = new FileNameDict(10007);
- Doxygen::exampleNameDict = new FileNameDict(1009);
- Doxygen::exampleNameDict->setAutoDelete(TRUE);
- Doxygen::imageNameDict = new FileNameDict(257);
- Doxygen::dotFileNameDict = new FileNameDict(257);
- Doxygen::sectionDict.setAutoDelete(TRUE);
- Doxygen::memGrpInfoDict.setAutoDelete(TRUE);
- Doxygen::tagDestinationDict.setAutoDelete(TRUE);
- Doxygen::lookupCache.setAutoDelete(TRUE);
- Doxygen::dirRelations.setAutoDelete(TRUE);
- }
- void cleanUpDoxygen()
- {
- delete Doxygen::inputNameDict;
- delete Doxygen::includeNameDict;
- delete Doxygen::exampleNameDict;
- delete Doxygen::imageNameDict;
- delete Doxygen::dotFileNameDict;
- delete Doxygen::mainPage;
- delete Doxygen::pageSDict;
- delete Doxygen::exampleSDict;
- delete Doxygen::globalScope;
- delete Doxygen::xrefLists;
- delete Doxygen::parserManager;
- cleanUpPreprocessor();
- delete theTranslator;
- delete g_outputList;
- Mappers::freeMappers();
- codeFreeScanner();
- if (Doxygen::symbolMap)
- {
- // iterate through Doxygen::symbolMap and delete all
- // DefinitionList objects, since they have no owner
- QDictIterator<DefinitionIntf> dli(*Doxygen::symbolMap);
- DefinitionIntf *di;
- for (dli.toFirst();(di=dli.current());)
- {
- if (di->definitionType()==DefinitionIntf::TypeSymbolList)
- {
- DefinitionIntf *tmp = Doxygen::symbolMap->take(dli.currentKey());
- delete (DefinitionList *)tmp;
- }
- else
- {
- ++dli;
- }
- }
- }
- delete Doxygen::inputNameList;
- delete Doxygen::memberNameSDict;
- delete Doxygen::functionNameSDict;
- delete Doxygen::groupSDict;
- delete Doxygen::classSDict;
- delete Doxygen::hiddenClasses;
- delete Doxygen::namespaceSDict;
- delete Doxygen::directories;
- //delete Doxygen::symbolMap; <- we cannot do this unless all static lists
- // (such as Doxygen::namespaceSDict)
- // with objects based on Definition are made
- // dynamic first
- }
- void readConfiguration(int argc, char **argv)
- {
- /**************************************************************************
- * Handle arguments *
- **************************************************************************/
- int optind=1;
- const char *configName=0;
- const char *layoutName=0;
- const char *debugLabel;
- const char *formatName;
- bool genConfig=FALSE;
- bool shortList=FALSE;
- bool updateConfig=FALSE;
- bool genLayout=FALSE;
- while (optind<argc && argv[optind][0]=='-' &&
- (isalpha(argv[optind][1]) || argv[optind][1]=='?' ||
- argv[optind][1]=='-')
- )
- {
- switch(argv[optind][1])
- {
- case 'g':
- genConfig=TRUE;
- configName=getArg(argc,argv,optind);
- if (strcmp(argv[optind+1],"-")==0)
- { configName="-"; optind++; }
- if (!configName)
- { configName="Doxyfile"; }
- break;
- case 'l':
- genLayout=TRUE;
- layoutName=getArg(argc,argv,optind);
- if (!layoutName)
- { layoutName="DoxygenLayout.xml"; }
- break;
- case 'd':
- debugLabel=getArg(argc,argv,optind);
- Debug::setFlag(debugLabel);
- break;
- case 's':
- shortList=TRUE;
- break;
- case 'u':
- updateConfig=TRUE;
- break;
- case 'e':
- formatName=getArg(argc,argv,optind);
- if (!formatName)
- {
- err("Error:option -e is missing format specifier rtf.\n");
- cleanUpDoxygen();
- exit(1);
- }
- if (stricmp(formatName,"rtf")==0)
- {
- if (optind+1>=argc)
- {
- err("Error: option \"-e rtf\" is missing an extensions file name\n");
- cleanUpDoxygen();
- exit(1);
- }
- QFile f;
- if (openOutputFile(argv[optind+1],f))
- {
- RTFGenerator::writeExtensionsFile(f);
- }
- cleanUpDoxygen();
- exit(1);
- }
- err("Error: option \"-e\" has invalid format specifier.\n");
- cleanUpDoxygen();
- exit(1);
- break;
- case 'w':
- formatName=getArg(argc,argv,optind);
- if (!formatName)
- {
- err("Error: option -w is missing format specifier rtf, html or latex\n");
- cleanUpDoxygen();
- exit(1);
- }
- if (stricmp(formatName,"rtf")==0)
- {
- if (optind+1>=argc)
- {
- err("Error: option \"-w rtf\" is missing a style sheet file name\n");
- cleanUpDoxygen();
- exit(1);
- }
- QFile f;
- if (openOutputFile(argv[optind+1],f))
- {
- RTFGenerator::writeStyleSheetFile(f);
- }
- cleanUpDoxygen();
- exit(1);
- }
- else if (stricmp(formatName,"html")==0)
- {
- if (optind+4<argc)
- {
- if (!Config::instance()->parse(argv[optind+4]))
- {
- err("Error opening or reading configuration file %s!\n",argv[optind+4]);
- cleanUpDoxygen();
- exit(1);
- }
- Config::instance()->substituteEnvironmentVars();
- Config::instance()->convertStrToVal();
- Config::instance()->check();
- }
- else
- {
- Config::instance()->init();
- }
- if (optind+3>=argc)
- {
- err("Error: option \"-w html\" does not have enough arguments\n");
- cleanUpDoxygen();
- exit(1);
- }
- QCString outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
- if (!setTranslator(outputLanguage))
- {
- err("Warning: Output language %s not supported! Using English instead.\n", outputLanguage.data());
- }
- QFile f;
- if (openOutputFile(argv[optind+1],f))
- {
- HtmlGenerator::writeHeaderFile(f);
- }
- f.close();
- if (openOutputFile(argv[optind+2],f))
- {
- HtmlGenerator::writeFooterFile(f);
- }
- f.close();
- if (openOutputFile(argv[optind+3],f))
- {
- HtmlGenerator::writeStyleSheetFile(f);
- }
- cleanUpDoxygen();
- exit(0);
- }
- else if (stricmp(formatName,"latex")==0)
- {
- if (optind+3<argc) // use config file to get settings
- {
- if (!Config::instance()->parse(argv[optind+3]))
- {
- err("Error opening or reading configuration file %s!\n",argv[optind+3]);
- exit(1);
- }
- Config::instance()->substituteEnvironmentVars();
- Config::instance()->convertStrToVal();
- Config::instance()->check();
- }
- else // use default config
- {
- Config::instance()->init();
- }
- if (optind+2>=argc)
- {
- err("Error: option \"-w latex\" does not have enough arguments\n");
- cleanUpDoxygen();
- exit(1);
- }
- QCString outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
- if (!setTranslator(outputLanguage))
- {
- err("Warning: Output language %s not supported! Using English instead.\n", outputLanguage.data());
- }
- QFile f;
- if (openOutputFile(argv[optind+1],f))
- {
- LatexGenerator::writeHeaderFile(f);
- }
- f.close();
- if (openOutputFile(argv[optind+2],f))
- {
- LatexGenerator::writeStyleSheetFile(f);
- }
- cleanUpDoxygen();
- exit(0);
- }
- else
- {
- err("Error: Illegal format specifier %s: should be one of rtf, html, or latex\n",formatName);
- cleanUpDoxygen();
- exit(1);
- }
- break;
- case 'm':
- g_dumpSymbolMap = TRUE;
- break;
- case 'x':
- g_dumpConfigAsXML = TRUE;
- break;
- case '-':
- if (strcmp(&argv[optind][2],"help")==0)
- {
- usage(argv[0]);
- }
- else if (strcmp(&argv[optind][2],"version")==0)
- {
- msg("%s\n",versionString);
- cleanUpDoxygen();
- exit(0);
- }
- break;
- case 'b':
- setvbuf(stdout,NULL,_IONBF,0);
- Doxygen::outputToWizard=TRUE;
- break;
- case 'h':
- case '?':
- usage(argv[0]);
- break;
- default:
- err("Unknown option -%c\n",argv[optind][1]);
- usage(argv[0]);
- }
- optind++;
- }
-
- /**************************************************************************
- * Parse or generate the config file *
- **************************************************************************/
- Config::instance()->init();
- if (genConfig)
- {
- if (g_dumpConfigAsXML)
- {
- checkConfiguration();
- generateConfigFile(configName,shortList);
- dumpConfigAsXML();
- exit(0);
- }
- else
- {
- generateConfigFile(configName,shortList);
- }
- cleanUpDoxygen();
- exit(0);
- }
- if (genLayout)
- {
- writeDefaultLayoutFile(layoutName);
- cleanUpDoxygen();
- exit(0);
- }
- QFileInfo configFileInfo1("Doxyfile"),configFileInfo2("doxyfile");
- if (optind>=argc)
- {
- if (configFileInfo1.exists())
- {
- configName="Doxyfile";
- }
- else if (configFileInfo2.exists())
- {
- configName="doxyfile";
- }
- else
- {
- err("Doxyfile not found and no input file specified!\n");
- usage(argv[0]);
- }
- }
- else
- {
- QFileInfo fi(argv[optind]);
- if (fi.exists() || strcmp(argv[optind],"-")==0)
- {
- configName=argv[optind];
- }
- else
- {
- err("Error: configuration file %s not found!\n",argv[optind]);
- usage(argv[0]);
- }
- }
- if (!Config::instance()->parse(configName))
- {
- err("Error: could not open or read configuration file %s!\n",configName);
- cleanUpDoxygen();
- exit(1);
- }
- if (updateConfig)
- {
- generateConfigFile(configName,shortList,TRUE);
- cleanUpDoxygen();
- exit(0);
- }
- /* Perlmod wants to know the path to the config file.*/
- QFileInfo configFileInfo(configName);
- setPerlModDoxyfile(configFileInfo.absFilePath());
- }
- /** check and resolve config options */
- void checkConfiguration()
- {
-
- Config::instance()->substituteEnvironmentVars();
- Config::instance()->convertStrToVal();
- Config::instance()->check();
-
- initWarningFormat();
- }
- /** adjust globals that depend on configuration settings. */
- void adjustConfiguration()
- {
- QCString outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
- if (!setTranslator(outputLanguage))
- {
- err("Warning: Output language %s not supported! Using English instead.\n",
- outputLanguage.data());
- }
- QStrList &includePath = Config_getList("INCLUDE_PATH");
- char *s=includePath.first();
- while (s)
- {
- QFileInfo fi(s);
- addSearchDir(fi.absFilePath());
- s=includePath.next();
- }
- /* Set the global html file extension. */
- Doxygen::htmlFileExtension = Config_getString("HTML_FILE_EXTENSION");
- Doxygen::xrefLists->setAutoDelete(TRUE);
- Doxygen::parseSourcesNeeded = Config_getBool("CALL_GRAPH") ||
- Config_getBool("CALLER_GRAPH") ||
- Config_getBool("REFERENCES_RELATION") ||
- Config_getBool("REFERENCED_BY_RELATION");
-
- /**************************************************************************
- * Add custom extension mappings
- **************************************************************************/
- QStrList &extMaps = Config_getList("EXTENSION_MAPPING");
- char *mapping = extMaps.first();
- while (mapping)
- {
- QCString mapStr = mapping;
- int i;
- if ((i=mapStr.find('='))!=-1)
- {
- QCString ext=mapStr.left(i).stripWhiteSpace().lower();
- QCString language=mapStr.mid(i+1).stripWhiteSpace().lower();
- if (!updateLanguageMapping(ext,language))
- {
- err("Failed to map file extension '%s' to unsupported language '%s'.\n"
- "Check the EXTENSION_MAPPING setting in the config file.\n",
- ext.data(),language.data());
- }
- else
- {
- msg("Adding custom extension mapping: .%s will be treated as language %s\n",
- ext.data(),language.data());
- }
- }
- mapping = extMaps.next();
- }
- // add predefined macro name to a dictionary
- QStrList &expandAsDefinedList =Config_getList("EXPAND_AS_DEFINED");
- s=expandAsDefinedList.first();
- while (s)
- {
- if (Doxygen::expandAsDefinedDict[s]==0)
- {
- Doxygen::expandAsDefinedDict.insert(s,(void *)666);
- }
- s=expandAsDefinedList.next();
- }
- // read aliases and store them in a dictionary
- readAliases();
- // store number of spaces in a tab into Doxygen::spaces
- int &tabSize = Config_getInt("TAB_SIZE");
- Doxygen::spaces.resize(tabSize+1);
- int sp;for (sp=0;sp<tabSize;sp++) Doxygen::spaces.at(sp)=' ';
- Doxygen::spaces.at(tabSize)='\0';
- }
- #ifdef HAS_SIGNALS
- static void stopDoxygen(int)
- {
- QDir thisDir;
- msg("Cleaning up...\n");
- if (!Doxygen::entryDBFileName.isEmpty())
- {
- thisDir.remove(Doxygen::entryDBFileName);
- }
- if (!Doxygen::objDBFileName.isEmpty())
- {
- thisDir.remove(Doxygen::objDBFileName);
- }
- exit(1);
- }
- #endif
- static void exitDoxygen()
- {
- if (!g_successfulRun) // premature exit
- {
- QDir thisDir;
- msg("Exiting...\n");
- if (!Doxygen::entryDBFileName.isEmpty())
- {
- thisDir.remove(Doxygen::entryDBFileName);
- }
- if (!Doxygen::objDBFileName.isEmpty())
- {
- thisDir.remove(Doxygen::objDBFileName);
- }
- }
- }
- static QCString createOutputDirectory(const QCString &baseDirName,
- const char *formatDirOption,
- const char *defaultDirName)
- {
- // Note the & on the next line, we modify the formatDirOption!
- QCString &formatDirName = Config_getString(formatDirOption);
- if (formatDirName.isEmpty())
- {
- formatDirName = baseDirName + defaultDirName;
- }
- else if (formatDirName[0]!='/' && (formatDirName.length()==1 || formatDirName[1]!=':'))
- {
- formatDirName.prepend(baseDirName+'/');
- }
- QDir formatDir(formatDirName);
- if (!formatDir.exists() && !formatDir.mkdir(formatDirName))
- {
- err("Could not create output directory %s\n", formatDirName.data());
- cleanUpDoxygen();
- exit(1);
- }
- return formatDirName;
- }
- static QCString getQchFileName()
- {
- QCString const & qchFile = Config_getString("QCH_FILE");
- if (!qchFile.isEmpty())
- {
- return qchFile;
- }
- QCString const & projectName = Config_getString("PROJECT_NAME");
- QCString const & versionText = Config_getString("PROJECT_NUMBER");
- return QCString("../qch/")
- + (projectName.isEmpty() ? QCString("index") : projectName)
- + (versionText.isEmpty() ? QCString("") : QCString("-") + versionText)
- + QCString(".qch");
- }
- void searchInputFiles(StringList &inputFiles)
- {
- QStrList &exclPatterns = Config_getList("EXCLUDE_PATTERNS");
- bool alwaysRecursive = Config_getBool("RECURSIVE");
- StringDict excludeNameDict(1009);
- excludeNameDict.setAutoDelete(TRUE);
- // gather names of all files in the include path
- msg("Searching for include files...\n");
- QStrList &includePathList = Config_getList("INCLUDE_PATH");
- char *s=includePathList.first();
- while (s)
- {
- QStrList &pl = Config_getList("INCLUDE_FILE_PATTERNS");
- if (pl.count()==0)
- {
- pl = Config_getList("FILE_PATTERNS");
- }
- readFileOrDirectory(s,0,Doxygen::includeNameDict,0,&pl,
- &exclPatterns,0,0,
- alwaysRecursive);
- s=includePathList.next();
- }
-
- msg("Searching for example files...\n");
- QStrList &examplePathList = Config_getList("EXAMPLE_PATH");
- s=examplePathList.first();
- while (s)
- {
- readFileOrDirectory(s,0,Doxygen::exampleNameDict,0,
- &Config_getList("EXAMPLE_PATTERNS"),
- 0,0,0,
- (alwaysRecursive || Config_getBool("EXAMPLE_RECURSIVE")));
- s=examplePathList.next();
- }
- msg("Searching for images...\n");
- QStrList &imagePathList=Config_getList("IMAGE_PATH");
- s=imagePathList.first();
- while (s)
- {
- readFileOrDirectory(s,0,Doxygen::imageNameDict,0,0,
- 0,0,0,
- alwaysRecursive);
- s=imagePathList.next();
- }
- msg("Searching for dot files...\n");
- QStrList &dotFileList=Config_getList("DOTFILE_DIRS");
- s=dotFileList.first();
- while (s)
- {
- readFileOrDirectory(s,0,Doxygen::dotFileNameDict,0,0,
- 0,0,0,
- alwaysRecursive);
- s=dotFileList.next();
- }
- msg("Searching for files to exclude\n");
- QStrList &excludeList = Config_getList("EXCLUDE");
- s=excludeList.first();
- while (s)
- {
- readFileOrDirectory(s,0,0,0,&Config_getList("FILE_PATTERNS"),
- 0,0,&excludeNameDict,
- alwaysRecursive,
- FALSE);
- s=excludeList.next();
- }
- /**************************************************************************
- * Determine Input Files *
- **************************************************************************/
- msg("Searching for files to process...\n");
- QDict<void> *killDict = new QDict<void>(10007);
- int inputSize=0;
- QStrList &inputList=Config_getList("INPUT");
- inputFiles.setAutoDelete(TRUE);
- s=inputList.first();
- while (s)
- {
- QCString path=s;
- uint l = path.length();
- // strip trailing slashes
- if (path.at(l-1)=='\\' || path.at(l-1)=='/') path=path.left(l-1);
- inputSize+=readFileOrDirectory(
- path,
- Doxygen::inputNameList,
- Doxygen::inputNameDict,
- &excludeNameDict,
- &Config_getList("FILE_PATTERNS"),
- &exclPatterns,
- &inputFiles,0,
- alwaysRecursive,
- TRUE,
- killDict);
- s=inputList.next();
- }
- delete killDict;
- }
-
- void parseInput()
- {
- atexit(exitDoxygen);
- /**************************************************************************
- * Make sure the output directory exists
- **************************************************************************/
- QCString &outputDirectory = Config_getString("OUTPUT_DIRECTORY");
- if (outputDirectory.isEmpty())
- {
- outputDirectory=QDir::currentDirPath();
- }
- else
- {
- QDir dir(outputDirectory);
- if (!dir.exists())
- {
- dir.setPath(QDir::currentDirPath());
- if (!dir.mkdir(outputDirectory))
- {
- err("Error: tag OUTPUT_DIRECTORY: Output directory `%s' does not "
- "exist and cannot be created\n",outputDirectory.data());
- cleanUpDoxygen();
- exit(1);
- }
- else if (!Config_getBool("QUIET"))
- {
- err("Notice: Output directory `%s' does not exist. "
- "I have created it for you.\n", outputDirectory.data());
- }
- dir.cd(outputDirectory);
- }
- outputDirectory=dir.absPath();
- }
- /**************************************************************************
- * Initialize global lists and dictionaries
- **************************************************************************/
- int cacheSize = Config_getInt("SYMBOL_CACHE_SIZE");
- if (cacheSize<0) cacheSize=0;
- if (cacheSize>9) cacheSize=9;
- Doxygen::symbolCache = new ObjCache(16+cacheSize); // 16 -> room for 65536 elements,
- // ~2.0 MByte "overhead"
- Doxygen::symbolStorage = new Store;
- #ifdef HAS_SIGNALS
- signal(SIGINT, stopDoxygen);
- #endif
- uint pid = portable_pid();
- Doxygen::objDBFileName.sprintf("doxygen_objdb_%d.tmp",pid);
- Doxygen::objDBFileName.prepend(outputDirectory+"/");
- Doxygen::entryDBFileName.sprintf("doxygen_entrydb_%d.tmp",pid);
- Doxygen::entryDBFileName.prepend(outputDirectory+"/");
-
- if (Doxygen::symbolStorage->open(Doxygen::objDBFileName)==-1)
- {
- err("Failed to open temporary file %s\n",Doxygen::objDBFileName.data());
- exit(1);
- }
- /**************************************************************************
- * Initialize some global constants
- **************************************************************************/
-
- g_compoundKeywordDict.insert("template class",(void *)8);
- g_compoundKeywordDict.insert("template struct",(void *)8);
- g_compoundKeywordDict.insert("class",(void *)8);
- g_compoundKeywordDict.insert("struct",(void *)8);
- g_compoundKeywordDict.insert("union",(void *)8);
- g_compoundKeywordDict.insert("interface",(void *)8);
- g_compoundKeywordDict.insert("exception",(void *)8);
- /**************************************************************************
- * Check/create output directorties *
- **************************************************************************/
- QCString htmlOutput;
- bool &generateHtml = Config_getBool("GENERATE_HTML");
- if (generateHtml)
- htmlOutput = createOutputDirectory(outputDirectory,"HTML_OUTPUT","/html");
- QCString xmlOutput;
- bool &generateXml = Config_getBool("GENERATE_XML");
- if (generateXml)
- xmlOutput = createOutputDirectory(outputDirectory,"XML_OUTPUT","/xml");
-
- QCString latexOutput;
- bool &generateLatex = Config_getBool("GENERATE_LATEX");
- if (generateLatex)
- latexOutput = createOutputDirectory(outputDirectory,"LATEX_OUTPUT","/latex");
- QCString rtfOutput;
- bool &generateRtf = Config_getBool("GENERATE_RTF");
- if (generateRtf)
- rtfOutput = createOutputDirectory(outputDirectory,"RTF_OUTPUT","/rtf");
- QCString manOutput;
- bool &generateMan = Config_getBool("GENERATE_MAN");
- if (generateMan)
- manOutput = createOutputDirectory(outputDirectory,"MAN_OUTPUT","/man");
- if (Config_getBool("HAVE_DOT"))
- {
- QCString curFontPath = Config_getString("DOT_FONTPATH");
- if (curFontPath.isEmpty())
- {
- portable_getenv("DOTFONTPATH");
- QCString newFontPath = ".";
- if (!curFontPath.isEmpty())
- {
- newFontPath+=portable_pathListSeparator();
- newFontPath+=curFontPath;
- }
- portable_setenv("DOTFONTPATH",newFontPath);
- }
- else
- {
- portable_setenv("DOTFONTPATH",curFontPath);
- }
- }
- /**************************************************************************
- * Handle layout file *
- **************************************************************************/
- LayoutDocManager::instance().init();
- QCString layoutFileName = Config_getString("LAYOUT_FILE");
- bool defaultLayoutUsed = FALSE;
- if (layoutFileName.isEmpty())
- {
- layoutFileName = "DoxygenLayout.xml";
- defaultLayoutUsed = TRUE;
- }
- QFile layoutFile(layoutFileName);
- if (layoutFile.open(IO_ReadOnly))
- {
- msg("Parsing layout file %s...\n",layoutFileName.data());
- QTextStream t(&layoutFile);
- LayoutDocManager::instance().parse(t);
- }
- else if (!defaultLayoutUsed)
- {
- err("Warning: failed to open layout file '%s' for reading!\n",layoutFileName.data());
- }
- /**************************************************************************
- * Read and preprocess input *
- **************************************************************************/
-
- // prevent search in the output directories
- QStrList &exclPatterns = Config_getList("EXCLUDE_PATTERNS");
- if (generateHtml) exclPatterns.append(htmlOutput);
- if (generateXml) exclPatterns.append(xmlOutput);
- if (generateLatex) exclPatterns.append(latexOutput);
- if (generateRtf) exclPatterns.append(rtfOutput);
- if (generateMan) exclPatterns.append(manOutput);
- searchInputFiles(g_inputFiles);
- // Notice: the order of the function calls below is very important!
-
- if (Config_getBool("GENERATE_HTML"))
- {
- readFormulaRepository();
- }
-
- /**************************************************************************
- * Handle Tag Files *
- **************************************************************************/
- g_storage = new FileStorage;
- g_storage->setName(Doxygen::entryDBFileName);
- if (!g_storage->open(IO_WriteOnly))
- {
- err("Failed to create temporary storage file %s\n",
- Doxygen::entryDBFileName.data());
- exit(1);
- }
- Entry *root=new Entry;
- EntryNav *rootNav = new EntryNav(0,root);
- rootNav->setEntry(root);
- msg("Reading and parsing tag files\n");
-
- QStrList &tagFileList = Config_getList("TAGFILES");
- char *s=tagFileList.first();
- while (s)
- {
- readTagFile(root,s);
- root->createNavigationIndex(rootNav,g_storage,0);
- s=tagFileList.next();
- }
-
- /**************************************************************************
- * Parse source files *
- **************************************************************************/
- parseFiles(root,rootNav);
- g_storage->close();
- if (!g_storage->open(IO_ReadOnly))
- {
- err("Failed to open temporary storage file %s for reading",
- Doxygen::entryDBFileName.data());
- exit(1);
- }
- //printNavTree(rootNav,0);
- // we are done with input scanning now, so free up the buffers used by flex
- // (can be around 4MB)
- preFreeScanner();
- scanFreeScanner();
- pyscanFreeScanner();
- //delete rootNav;
- //g_storage.close();
- //exit(1);
- /**************************************************************************
- * Gather information *
- **************************************************************************/
-
- msg("Building group list...\n");
- buildGroupList(rootNav);
- organizeSubGroups(rootNav);
- msg("Building directory list...\n");
- buildDirectories();
- findDirDocumentation(rootNav);
- if (Config_getBool("BUILTIN_STL_SUPPORT"))
- {
- addSTLClasses(rootNav);
- }
- msg("Building namespace list...\n");
- buildNamespaceList(rootNav);
- findUsingDirectives(rootNav);
- msg("Building file list...\n");
- buildFileList(rootNav);
- //generateFileTree();
-
- msg("Building class list...\n");
- buildClassList(rootNav);
- msg("Associating documentation with classes...\n");
- buildClassDocList(rootNav);
- // build list of using declarations here (global list)
- buildListOfUsingDecls(rootNav);
-
- msg("Computing nesting relations for classes...\n");
- resolveClassNestingRelations();
- // calling buildClassList may result in cached relations that
- // become invalid after resolveClassNestingRelations(), that's why
- // we need to clear the cache here
- Doxygen::lookupCache.clear();
- // we don't need the list of using declaration anymore
- g_usingDeclarations.clear();
- msg("Building example list...\n");
- buildExampleList(rootNav);
-
- msg("Searching for enumerations...\n");
- findEnums(rootNav);
-
- // Since buildVarList calls isVarWithConstructor
- // and this calls getResolvedClass we need to process
- // typedefs first so the relations between classes via typedefs
- // are properly resolved. See bug 536385 for an example.
- msg("Searching for documented typedefs...\n");
- buildTypedefList(rootNav);
- msg("Searching for members imported via using declarations...\n");
- findUsingDeclImports(rootNav);
- // this should be after buildTypedefList in order to properly import
- // used typedefs
- findUsingDeclarations(rootNav);
- msg("Searching for included using directives...\n");
- findIncludedUsingDirectives();
- msg("Searching for documented variables...\n");
- buildVarList(rootNav);
- msg("Building member list...\n"); // using class info only !
- buildFunctionList(rootNav);
- msg("Searching for friends...\n");
- findFriends();
-
- msg("Searching for documented defines...\n");
- findDefineDocumentation(rootNav);
-
- findClassEntries(rootNav);
- msg("Computing class inheritance relations...\n");
- findInheritedTemplateInstances();
- msg("Computing class usage relations...\n");
- findUsedTemplateInstances();
- msg("Flushing cached template relations that have become invalid...\n");
- flushCachedTemplateRelations();
-
- msg("Creating members for template instances...\n");
- createTemplateInstanceMembers();
- msg("Computing class relations...\n");
- computeTemplateClassRelations();
- flushUnresolvedRelations();
- computeClassRelations();
- if (Config_getBool("OPTIMIZE_OUTPUT_VHDL"))
- VhdlDocGen::computeVhdlComponentRelations();
- g_classEntries.clear();
- msg("Add enum values to enums...\n");
- addEnumValuesToEnums(rootNav);
- findEnumDocumentation(rootNav);
- msg("Searching for member function documentation...\n");
- findObjCMethodDefinitions(rootNav);
- findMemberDocumentation(rootNav); // may introduce new members !
- transferRelatedFunctionDocumentation();
- transferFunctionDocumentation();
-
- msg("Building page list...\n");
- buildPageList(rootNav);
- msg("Search for main page...\n");
- findMainPage(rootNav);
- msg("Computing page relations...\n");
- computePageRelations(rootNav);
- checkPageRelations();
- msg("Determining the scope of groups...\n");
- findGroupScope(rootNav);
- msg("Sorting lists...\n");
- Doxygen::memberNameSDict->sort();
- Doxygen::functionNameSDict->sort();
- Doxygen::hiddenClasses->sort();
- Doxygen::classSDict->sort();
-
- msg("Freeing entry tree\n");
- delete rootNav;
- g_storage->close();
- delete g_storage;
- g_storage=0;
- QDir thisDir;
- thisDir.remove(Doxygen::entryDBFileName);
-
- msg("Determining which enums are documented\n");
- findDocumentedEnumValues();
- msg("Computing member relations...\n");
- computeMemberRelations();
- msg("Building full member lists recursively...\n");
- buildCompleteMemberLists();
-
- msg("Adding members to member groups.\n");
- addMembersToMemberGroup();
- if (Config_getBool("DISTRIBUTE_GROUP_DOC"))
- {
- msg("Distributing member group documentation.\n");
- distributeMemberGroupDocumentation();
- }
-
- msg("Computing member references...\n");
- computeMemberReferences();
- if (Config_getBool("INHERIT_DOCS"))
- {
- msg("Inheriting documentation...\n");
- inheritDocumentation();
- }
- // compute the shortest possible names of all files
- // without loosing the uniqueness of the file names.
- msg("Generating disk names...\n");
- Doxygen::inputNameList->generateDiskNames();
-
- msg("Adding source references...\n");
- addSourceReferences();
- msg("Adding xrefitems...\n");
- addListReferences();
- generateXRefPages();
- if (Config_getBool("SHOW_DIRECTORIES") && Config_getBool("DIRECTORY_GRAPH"))
- {
- msg("Computing dependencies between directories...\n");
- computeDirDependencies();
- }
- msg("Counting data structures...\n");
- countDataStructures();
-
- msg("Resolving user defined references...\n");
- resolveUserReferences();
- msg("Finding anchors and sections in the documentation...\n");
- findSectionsInDocumentation();
- transferFunctionReferences();
- msg("Combining using relations...\n");
- combineUsingRelations();
- msg("Adding members to index pages...\n");
- addMembersToIndex();
- }
- void generateOutput()
- {
- /**************************************************************************
- * Initialize output generators *
- **************************************************************************/
- //// dump all symbols
- //SDict<DefinitionList>::Iterator sdi(Doxygen::symbolMap);
- //DefinitionList *dl;
- //for (sdi.toFirst();(dl=sdi.current());++sdi)
- //{
- // DefinitionListIterator dli(*dl);
- // Definition *d;
- // printf("Symbol: ");
- // for (dli.toFirst();(d=dli.current());++dli)
- // {
- // printf("%s ",d->qualifiedName().data());
- // }
- // printf("\n");
- //}
- if (g_dumpSymbolMap)
- {
- dumpSymbolMap();
- exit(0);
- }
- initDocParser();
- g_outputList = new OutputList(TRUE);
- if (Config_getBool("GENERATE_HTML"))
- {
- g_outputList->add(new HtmlGenerator);
- HtmlGenerator::init();
- #if 0
- if (Config_getBool("GENERATE_INDEXLOG")) Doxygen::indexList.addIndex(new IndexLog);
- #endif
- bool generateHtmlHelp = Config_getBool("GENERATE_HTMLHELP");
- bool generateEclipseHelp = Config_getBool("GENERATE_ECLIPSEHELP");
- bool generateQhp = Config_getBool("GENERATE_QHP");
- bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");
- bool generateDocSet = Config_getBool("GENERATE_DOCSET");
- if (generateEclipseHelp) Doxygen::indexList.addIndex(new EclipseHelp);
- if (generateHtmlHelp) Doxygen::indexList.addIndex(new HtmlHelp);
- if (generateQhp) Doxygen::indexList.addIndex(new Qhp);
- if (generateTreeView) Doxygen::indexList.addIndex(new FTVHelp);
- if (generateDocSet) Doxygen::indexList.addIndex(new DocSets);
- Doxygen::indexList.initialize();
- Doxygen::indexList.addImageFile("tab_r.gif");
- Doxygen::indexList.addImageFile("tab_l.gif");
- Doxygen::indexList.addImageFile("tab_b.gif");
- Doxygen::indexList.addStyleSheetFile("tabs.css");
- Doxygen::indexList.addImageFile("doxygen.png");
- if (Config_getBool("HTML_DYNAMIC_SECTIONS")) HtmlGenerator::generateSectionImages();
- copyStyleSheet();
- }
- if (Config_getBool("GENERATE_LATEX"))
- {
- g_outputList->add(new LatexGenerator);
- LatexGenerator::init();
- }
- if (Config_getBool("GENERATE_MAN"))
- {
- g_outputList->add(new ManGenerator);
- ManGenerator::init();
- }
- if (Config_getBool("GENERATE_RTF"))
- {
- g_outputList->add(new RTFGenerator);
- RTFGenerator::init();
- }
- if (Config_getBool("USE_HTAGS"))
- {
- Htags::useHtags = TRUE;
- QCString htmldir = Config_getString("HTML_OUTPUT");
- if (!Htags::execute(htmldir))
- err("Error: USE_HTAGS is YES but htags(1) failed. \n");
- if (!Htags::loadFilemap(htmldir))
- err("Error: htags(1) ended normally but failed to load the filemap. \n");
- }
-
- /**************************************************************************
- * Generate documentation *
- **************************************************************************/
- QFile *tag=0;
- QCString &generateTagFile = Config_getString("GENERATE_TAGFILE");
- if (!generateTagFile.isEmpty())
- {
- tag=new QFile(generateTagFile);
- if (!tag->open(IO_WriteOnly))
- {
- err("Error: cannot open tag file %s for writing\n",
- generateTagFile.data()
- );
- cleanUpDoxygen();
- exit(1);
- }
- Doxygen::tagFile.setDevice(tag);
- Doxygen::tagFile.setEncoding(QTextStream::UnicodeUTF8);
- Doxygen::tagFile << "<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?>" << endl;
- Doxygen::tagFile << "<tagfile>" << endl;
- }
- if (Config_getBool("GENERATE_HTML")) writeDoxFont(Config_getString("HTML_OUTPUT"));
- if (Config_getBool("GENERATE_LATEX")) writeDoxFont(Config_getString("LATEX_OUTPUT"));
- if (Config_getBool("GENERATE_RTF")) writeDoxFont(Config_getString("RTF_OUTPUT"));
- msg("Generating style sheet...\n");
- //printf("writing style info\n");
- QCString genString =
- theTranslator->trGeneratedAt(dateToString(TRUE),Config_getString("PROJECT_NAME"));
- g_outputList->writeStyleInfo(0); // write first part
- g_outputList->disableAllBut(OutputGenerator::Latex);
- g_outputList->parseText(genString);
- g_outputList->writeStyleInfo(1); // write second part
- //parseText(*g_outputList,theTranslator->trWrittenBy());
- g_outputList->writeStyleInfo(2); // write third part
- g_outputList->parseText(genString);
- g_outputList->writeStyleInfo(3); // write fourth part
- //parseText(*g_outputList,theTranslator->trWrittenBy());
- g_outputList->writeStyleInfo(4); // write last part
- g_outputList->enableAll();
-
- static bool searchEngine = Config_getBool("SEARCHENGINE");
- static bool serverBasedSearch = Config_getBool("SERVER_BASED_SEARCH");
- // generate search indices (need to do this before writing other HTML
- // pages as these contain a drop down menu with options depending on
- // what categories we find in this function.
- if (Config_getBool("GENERATE_HTML") && searchEngine)
- {
- QCString searchDirName = Config_getString("HTML_OUTPUT")+"/search";
- QDir searchDir(searchDirName);
- if (!searchDir.exists() && !searchDir.mkdir(searchDirName))
- {
- err("Error: Could not create search results directory '%s' $PWD='%s'\n",
- searchDirName.data(),QDir::currentDirPath().data());
- exit(1);
- }
- HtmlGenerator::writeSearchData(searchDirName);
- writeSearchStyleSheet();
- if (!serverBasedSearch) // client side search index
- {
- writeJavascriptSearchIndex();
- }
- }
- //statistics();
-
- // count the number of documented elements in the lists we have built.
- // If the result is 0 we do not generate the lists and omit the
- // corresponding links in the index.
- msg("Generating index page...\n");
- writeIndex(*g_outputList);
- msg("Generating page index...\n");
- writePageIndex(*g_outputList);
-
- msg("Generating example documentation...\n");
- generateExampleDocs();
- msg("Generating file sources...\n");
- if (!Htags::useHtags)
- {
- generateFileSources();
- }
- msg("Generating file documentation...\n");
- generateFileDocs();
-
- msg("Generating page documentation...\n");
- generatePageDocs();
-
- msg("Generating group documentation...\n");
- generateGroupDocs();
- msg("Generating group index...\n");
- writeGroupIndex(*g_outputList);
-
- msg("Generating class documentation...\n");
- generateClassDocs();
-
- if (Config_getBool("HAVE_DOT") && Config_getBool("GRAPHICAL_HIERARCHY"))
- {
- msg("Generating graphical class hierarchy...\n");
- writeGraphicalClassHierarchy(*g_outputList);
- }
- msg("Generating namespace index...\n");
- generateNamespaceDocs();
-
- msg("Generating namespace member index...\n");
- writeNamespaceMemberIndex(*g_outputList);
- if (Config_getBool("GENERATE_LEGEND"))
- {
- msg("Generating graph info page...\n");
- writeGraphInfo(*g_outputList);
- }
- if (Config_getBool("SHOW_DIRECTORIES"))
- {
- msg("Generating directory documentation...\n");
- generateDirDocs(*g_outputList);
- }
- msg("Generating file index...\n");
- writeFileIndex(*g_outputList);
-
- if (Config_getBool("SHOW_DIRECTORIES"))
- {
- msg("Generating directory index...\n");
- writeDirIndex(*g_outputList);
- }
- msg("Generating example index...\n");
- writeExampleIndex(*g_outputList);
-
- msg("Generating file member index...\n");
- writeFileMemberIndex(*g_outputList);
-
- //writeDirDependencyGraph(Config_getString("HTML_OUTPUT"));
-
- if (Config_getBool("GENERATE_RTF"))
- {
- msg("Combining RTF output...\n");
- if (!RTFGenerator::preProcessFileInplace(Config_getString("RTF_OUTPUT"),"refman.rtf"))
- {
- err("An error occurred during post-processing the RTF files!\n");
- }
- }
-
- if (Doxygen::formulaList.count()>0 && Config_getBool("GENERATE_HTML"))
- {
- msg("Generating bitmaps for formulas in HTML...\n");
- Doxygen::formulaList.generateBitmaps(Config_getString("HTML_OUTPUT"));
- }
-
- //if (Config_getBool("GENERATE_HTML") && Config_getBool("GENERATE_HTMLHELP"))
- //{
- // HtmlHelp::getInstance()->finalize();
- //}
- //if (Config_getBool("GENERATE_HTML") && Config_getBool("GENERATE_TREEVIEW"))
- //{
- // FTVHelp::getInstance()->finalize();
- //}
- Doxygen::indexList.finalize();
- if (!Config_getString("GENERATE_TAGFILE").isEmpty())
- {
- Doxygen::tagFile << "</tagfile>" << endl;
- delete tag;
- }
- if (Config_getBool("DOT_CLEANUP"))
- {
- if (Config_getBool("GENERATE_HTML"))
- removeDoxFont(Config_getString("HTML_OUTPUT"));
- if (Config_getBool("GENERATE_RTF"))
- removeDoxFont(Config_getString("RTF_OUTPUT"));
- if (Config_getBool("GENERATE_LATEX"))
- removeDoxFont(Config_getString("LATEX_OUTPUT"));
- }
- if (Config_getBool("GENERATE_XML"))
- {
- msg("Generating XML output...\n");
- generateXML();
- }
- if (Config_getBool("GENERATE_AUTOGEN_DEF"))
- {
- msg("Generating AutoGen DEF output...\n");
- generateDEF();
- }
- if (Config_getBool("GENERATE_PERLMOD"))
- {
- msg("Generating Perl module output...\n");
- generatePerlMod();
- }
- if (Config_getBool("GENERATE_HTML") &&
- Config_getBool("GENERATE_HTMLHELP") &&
- !Config_getString("HHC_LOCATION").isEmpty())
- {
- msg("Running html help compiler...\n");
- QString oldDir = QDir::currentDirPath();
- QDir::setCurrent(Config_getString("HTML_OUTPUT"));
- if (portable_system(Config_getString("HHC_LOCATION"), "index.hhp", FALSE))
- {
- err("Error: failed to run html help compiler on index.hhp\n");
- }
- QDir::setCurrent(oldDir);
- }
- if ( Config_getBool("GENERATE_HTML") &&
- Config_getBool("GENERATE_QHP") &&
- !Config_getString("QHG_LOCATION").isEmpty())
- {
- msg("Running qhelpgenerator...\n");
- QCString const qhpFileName = Qhp::getQhpFileName();
- QCString const qchFileName = getQchFileName();
- QCString const args = QCString().sprintf("%s -o \"%s\"", qhpFileName.data(), qchFileName.data());
- QString const oldDir = QDir::currentDirPath();
- QDir::setCurrent(Config_getString("HTML_OUTPUT"));
- if (portable_system(Config_getString("QHG_LOCATION"), args.data(), FALSE))
- {
- err("Error: failed to run qhelpgenerator on index.qhp\n");
- }
- QDir::setCurrent(oldDir);
- }
- if (Config_getBool("GENERATE_HTML") && searchEngine && serverBasedSearch)
- {
- msg("Generating search index\n");
- HtmlGenerator::writeSearchPage();
- Doxygen::searchIndex->write(Config_getString("HTML_OUTPUT")+"/search/search.idx");
- }
- if (Debug::isFlagSet(Debug::Time))
- {
- msg("Total elapsed time: %.3f seconds\n(of which %.3f seconds waiting for external tools to finish)\n",
- ((double)Doxygen::runningTime.elapsed())/1000.0,
- portable_getSysElapsedTime()
- );
- }
- /**************************************************************************
- * Start cleaning up *
- **************************************************************************/
- //Doxygen::symbolCache->printStats();
- //Doxygen::symbolStorage->printStats();
- cleanUpDoxygen();
- finializeDocParser();
- Doxygen::symbolStorage->close();
- QDir thisDir;
- thisDir.remove(Doxygen::objDBFileName);
- Config::deleteInstance();
- QTextCodec::deleteAllCodecs();
- delete Doxygen::symbolCache;
- delete Doxygen::symbolMap;
- delete Doxygen::symbolStorage;
- g_successfulRun=TRUE;
- }
|