| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797 |
- /*#define DEBUG 1*/
- /*
- * "$Id: mxmldoc.c 451 2014-01-04 21:50:06Z msweet $"
- *
- * Documentation generator using Mini-XML, a small XML-like file parsing
- * library.
- *
- * Copyright 2003-2014 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- */
- /*
- * Include necessary headers...
- */
- #include "config.h"
- #include "mxml.h"
- #include <time.h>
- #include <sys/stat.h>
- #ifndef WIN32
- # include <dirent.h>
- # include <unistd.h>
- #endif /* !WIN32 */
- #ifdef __APPLE__
- # include <spawn.h>
- # include <sys/wait.h>
- extern char **environ;
- #endif /* __APPLE__ */
- /*
- * This program scans source and header files and produces public API
- * documentation for code that conforms to the CUPS Configuration
- * Management Plan (CMP) coding standards. Please see the following web
- * page for details:
- *
- * http://www.cups.org/cmp.html
- *
- * Using Mini-XML, this program creates and maintains an XML representation
- * of the public API code documentation which can then be converted to HTML
- * as desired. The following is a poor-man's schema:
- *
- * <?xml version="1.0"?>
- * <mxmldoc xmlns="http://www.easysw.com"
- * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- * xsi:schemaLocation="http://www.minixml.org/mxmldoc.xsd">
- *
- * <namespace name=""> [optional...]
- * <constant name="">
- * <description>descriptive text</description>
- * </constant>
- *
- * <enumeration name="">
- * <description>descriptive text</description>
- * <constant name="">...</constant>
- * </enumeration>
- *
- * <typedef name="">
- * <description>descriptive text</description>
- * <type>type string</type>
- * </typedef>
- *
- * <function name="" scope="">
- * <description>descriptive text</description>
- * <argument name="" direction="I|O|IO" default="">
- * <description>descriptive text</description>
- * <type>type string</type>
- * </argument>
- * <returnvalue>
- * <description>descriptive text</description>
- * <type>type string</type>
- * </returnvalue>
- * <seealso>function names separated by spaces</seealso>
- * </function>
- *
- * <variable name="" scope="">
- * <description>descriptive text</description>
- * <type>type string</type>
- * </variable>
- *
- * <struct name="">
- * <description>descriptive text</description>
- * <variable name="">...</variable>
- * <function name="">...</function>
- * </struct>
- *
- * <union name="">
- * <description>descriptive text</description>
- * <variable name="">...</variable>
- * </union>
- *
- * <class name="" parent="">
- * <description>descriptive text</description>
- * <class name="">...</class>
- * <enumeration name="">...</enumeration>
- * <function name="">...</function>
- * <struct name="">...</struct>
- * <variable name="">...</variable>
- * </class>
- * </namespace>
- * </mxmldoc>
- */
- /*
- * Basic states for file parser...
- */
- #define STATE_NONE 0 /* No state - whitespace, etc. */
- #define STATE_PREPROCESSOR 1 /* Preprocessor directive */
- #define STATE_C_COMMENT 2 /* Inside a C comment */
- #define STATE_CXX_COMMENT 3 /* Inside a C++ comment */
- #define STATE_STRING 4 /* Inside a string constant */
- #define STATE_CHARACTER 5 /* Inside a character constant */
- #define STATE_IDENTIFIER 6 /* Inside a keyword/identifier */
- /*
- * Output modes...
- */
- #define OUTPUT_NONE 0 /* No output */
- #define OUTPUT_HTML 1 /* Output HTML */
- #define OUTPUT_XML 2 /* Output XML */
- #define OUTPUT_MAN 3 /* Output nroff/man */
- #define OUTPUT_TOKENS 4 /* Output docset Tokens.xml file */
- /*
- * Local functions...
- */
- static mxml_node_t *add_variable(mxml_node_t *parent, const char *name,
- mxml_node_t *type);
- static mxml_node_t *find_public(mxml_node_t *node, mxml_node_t *top,
- const char *name);
- static char *get_comment_info(mxml_node_t *description);
- static char *get_text(mxml_node_t *node, char *buffer, int buflen);
- static mxml_type_t load_cb(mxml_node_t *node);
- static mxml_node_t *new_documentation(mxml_node_t **mxmldoc);
- static int remove_directory(const char *path);
- static void safe_strcpy(char *dst, const char *src);
- static int scan_file(const char *filename, FILE *fp,
- mxml_node_t *doc);
- static void sort_node(mxml_node_t *tree, mxml_node_t *func);
- static void update_comment(mxml_node_t *parent,
- mxml_node_t *comment);
- static void usage(const char *option);
- static void write_description(FILE *out, mxml_node_t *description,
- const char *element, int summary);
- static void write_element(FILE *out, mxml_node_t *doc,
- mxml_node_t *element, int mode);
- static void write_file(FILE *out, const char *file);
- static void write_function(FILE *out, mxml_node_t *doc,
- mxml_node_t *function, int level);
- static void write_html(const char *section, const char *title,
- const char *footerfile,
- const char *headerfile,
- const char *introfile, const char *cssfile,
- const char *framefile,
- const char *docset, const char *docversion,
- const char *feedname, const char *feedurl,
- mxml_node_t *doc);
- static void write_html_head(FILE *out, const char *section,
- const char *title, const char *cssfile);
- static void write_man(const char *man_name, const char *section,
- const char *title, const char *headerfile,
- const char *footerfile, const char *introfile,
- mxml_node_t *doc);
- static void write_scu(FILE *out, mxml_node_t *doc,
- mxml_node_t *scut);
- static void write_string(FILE *out, const char *s, int mode);
- static void write_toc(FILE *out, mxml_node_t *doc,
- const char *introfile, const char *target,
- int xml);
- static void write_tokens(FILE *out, mxml_node_t *doc,
- const char *path);
- static const char *ws_cb(mxml_node_t *node, int where);
- /*
- * 'main()' - Main entry for test program.
- */
- int /* O - Exit status */
- main(int argc, /* I - Number of command-line args */
- char *argv[]) /* I - Command-line args */
- {
- int i; /* Looping var */
- int len; /* Length of argument */
- FILE *fp; /* File to read */
- mxml_node_t *doc; /* XML documentation tree */
- mxml_node_t *mxmldoc; /* mxmldoc node */
- const char *cssfile, /* CSS stylesheet file */
- *docset, /* Documentation set directory */
- *docversion, /* Documentation set version */
- *feedname, /* Feed name for documentation set */
- *feedurl, /* Feed URL for documentation set */
- *footerfile, /* Footer file */
- *framefile, /* Framed HTML basename */
- *headerfile, /* Header file */
- *introfile, /* Introduction file */
- *name, /* Name of manpage */
- *path, /* Path to help file for tokens */
- *section, /* Section/keywords of documentation */
- *title, /* Title of documentation */
- *xmlfile; /* XML file */
- int mode, /* Output mode */
- update; /* Updated XML file */
- /*
- * Check arguments...
- */
- cssfile = NULL;
- doc = NULL;
- docset = NULL;
- docversion = NULL;
- feedname = NULL;
- feedurl = NULL;
- footerfile = NULL;
- framefile = NULL;
- headerfile = NULL;
- introfile = NULL;
- mode = OUTPUT_HTML;
- mxmldoc = NULL;
- name = NULL;
- path = NULL;
- section = NULL;
- title = NULL;
- update = 0;
- xmlfile = NULL;
- for (i = 1; i < argc; i ++)
- if (!strcmp(argv[i], "--help"))
- {
- /*
- * Show help...
- */
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--version"))
- {
- /*
- * Show version...
- */
- puts(MXML_VERSION + 10);
- return (0);
- }
- else if (!strcmp(argv[i], "--css") && !cssfile)
- {
- /*
- * Set CSS stylesheet file...
- */
- i ++;
- if (i < argc)
- cssfile = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--docset") && !docset)
- {
- /*
- * Set documentation set directory...
- */
- i ++;
- if (i < argc)
- docset = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--docversion") && !docversion)
- {
- /*
- * Set documentation set directory...
- */
- i ++;
- if (i < argc)
- docversion = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--footer") && !footerfile)
- {
- /*
- * Set footer file...
- */
- i ++;
- if (i < argc)
- footerfile = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--feedname") && !feedname)
- {
- /*
- * Set documentation set feed name...
- */
- i ++;
- if (i < argc)
- feedname = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--feedurl") && !feedurl)
- {
- /*
- * Set documentation set feed name...
- */
- i ++;
- if (i < argc)
- feedurl = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--framed") && !framefile)
- {
- /*
- * Set base filename for framed HTML output...
- */
- i ++;
- if (i < argc)
- framefile = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--header") && !headerfile)
- {
- /*
- * Set header file...
- */
- i ++;
- if (i < argc)
- headerfile = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--intro") && !introfile)
- {
- /*
- * Set intro file...
- */
- i ++;
- if (i < argc)
- introfile = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--man") && !name)
- {
- /*
- * Output manpage...
- */
- i ++;
- if (i < argc)
- {
- mode = OUTPUT_MAN;
- name = argv[i];
- }
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--no-output"))
- mode = OUTPUT_NONE;
- else if (!strcmp(argv[i], "--section") && !section)
- {
- /*
- * Set section/keywords...
- */
- i ++;
- if (i < argc)
- section = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--title") && !title)
- {
- /*
- * Set title...
- */
- i ++;
- if (i < argc)
- title = argv[i];
- else
- usage(NULL);
- }
- else if (!strcmp(argv[i], "--tokens"))
- {
- /*
- * Output Tokens.xml file...
- */
- mode = OUTPUT_TOKENS;
- i ++;
- if (i < argc)
- path = argv[i];
- else
- usage(NULL);
- }
- else if (argv[i][0] == '-')
- {
- /*
- * Unknown/bad option...
- */
- usage(argv[i]);
- }
- else
- {
- /*
- * Process XML or source file...
- */
- len = (int)strlen(argv[i]);
- if (len > 4 && !strcmp(argv[i] + len - 4, ".xml"))
- {
- /*
- * Set XML file...
- */
- if (xmlfile)
- usage(NULL);
- xmlfile = argv[i];
- if (!doc)
- {
- if ((fp = fopen(argv[i], "r")) != NULL)
- {
- /*
- * Read the existing XML file...
- */
- doc = mxmlLoadFile(NULL, fp, load_cb);
- fclose(fp);
- if (!doc)
- {
- mxmldoc = NULL;
- fprintf(stderr,
- "mxmldoc: Unable to read the XML documentation file "
- "\"%s\"!\n", argv[i]);
- }
- else if ((mxmldoc = mxmlFindElement(doc, doc, "mxmldoc", NULL,
- NULL, MXML_DESCEND)) == NULL)
- {
- fprintf(stderr,
- "mxmldoc: XML documentation file \"%s\" is missing "
- "<mxmldoc> node!!\n", argv[i]);
- mxmlDelete(doc);
- doc = NULL;
- }
- }
- else
- {
- doc = NULL;
- mxmldoc = NULL;
- }
- if (!doc)
- doc = new_documentation(&mxmldoc);
- }
- }
- else
- {
- /*
- * Load source file...
- */
- update = 1;
- if (!doc)
- doc = new_documentation(&mxmldoc);
- if ((fp = fopen(argv[i], "r")) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to open source file \"%s\": %s\n",
- argv[i], strerror(errno));
- mxmlDelete(doc);
- return (1);
- }
- else if (scan_file(argv[i], fp, mxmldoc))
- {
- fclose(fp);
- mxmlDelete(doc);
- return (1);
- }
- else
- fclose(fp);
- }
- }
- if (update && xmlfile)
- {
- /*
- * Save the updated XML documentation file...
- */
- if ((fp = fopen(xmlfile, "w")) != NULL)
- {
- /*
- * Write over the existing XML file...
- */
- mxmlSetWrapMargin(0);
- if (mxmlSaveFile(doc, fp, ws_cb))
- {
- fprintf(stderr,
- "mxmldoc: Unable to write the XML documentation file \"%s\": "
- "%s!\n", xmlfile, strerror(errno));
- fclose(fp);
- mxmlDelete(doc);
- return (1);
- }
- fclose(fp);
- }
- else
- {
- fprintf(stderr,
- "mxmldoc: Unable to create the XML documentation file \"%s\": "
- "%s!\n", xmlfile, strerror(errno));
- mxmlDelete(doc);
- return (1);
- }
- }
- switch (mode)
- {
- case OUTPUT_HTML :
- /*
- * Write HTML documentation...
- */
- write_html(section, title ? title : "Documentation", footerfile,
- headerfile, introfile, cssfile, framefile, docset,
- docversion, feedname, feedurl, mxmldoc);
- break;
- case OUTPUT_MAN :
- /*
- * Write manpage documentation...
- */
- write_man(name, section, title, footerfile, headerfile, introfile,
- mxmldoc);
- break;
- case OUTPUT_TOKENS :
- fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<Tokens version=\"1.0\">\n", stdout);
- write_tokens(stdout, mxmldoc, path);
- fputs("</Tokens>\n", stdout);
- break;
- }
- /*
- * Delete the tree and return...
- */
- mxmlDelete(doc);
- return (0);
- }
- /*
- * 'add_variable()' - Add a variable or argument.
- */
- static mxml_node_t * /* O - New variable/argument */
- add_variable(mxml_node_t *parent, /* I - Parent node */
- const char *name, /* I - "argument" or "variable" */
- mxml_node_t *type) /* I - Type nodes */
- {
- mxml_node_t *variable, /* New variable */
- *node, /* Current node */
- *next; /* Next node */
- char buffer[16384], /* String buffer */
- *bufptr; /* Pointer into buffer */
- #ifdef DEBUG
- fprintf(stderr, "add_variable(parent=%p, name=\"%s\", type=%p)\n",
- parent, name, type);
- #endif /* DEBUG */
- /*
- * Range check input...
- */
- if (!type || !type->child)
- return (NULL);
- /*
- * Create the variable/argument node...
- */
- variable = mxmlNewElement(parent, name);
- /*
- * Check for a default value...
- */
- for (node = type->child; node; node = node->next)
- if (!strcmp(node->value.text.string, "="))
- break;
- if (node)
- {
- /*
- * Default value found, copy it and add as a "default" attribute...
- */
- for (bufptr = buffer; node; bufptr += strlen(bufptr))
- {
- if (node->value.text.whitespace && bufptr > buffer)
- *bufptr++ = ' ';
- strcpy(bufptr, node->value.text.string);
- next = node->next;
- mxmlDelete(node);
- node = next;
- }
- mxmlElementSetAttr(variable, "default", buffer);
- }
- /*
- * Extract the argument/variable name...
- */
- if (type->last_child->value.text.string[0] == ')')
- {
- /*
- * Handle "type (*name)(args)"...
- */
- for (node = type->child; node; node = node->next)
- if (node->value.text.string[0] == '(')
- break;
- for (bufptr = buffer; node; bufptr += strlen(bufptr))
- {
- if (node->value.text.whitespace && bufptr > buffer)
- *bufptr++ = ' ';
- strcpy(bufptr, node->value.text.string);
- next = node->next;
- mxmlDelete(node);
- node = next;
- }
- }
- else
- {
- /*
- * Handle "type name"...
- */
- strcpy(buffer, type->last_child->value.text.string);
- mxmlDelete(type->last_child);
- }
- /*
- * Set the name...
- */
- mxmlElementSetAttr(variable, "name", buffer);
- /*
- * Add the remaining type information to the variable node...
- */
- mxmlAdd(variable, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
- /*
- * Add new new variable node...
- */
- return (variable);
- }
- /*
- * 'find_public()' - Find a public function, type, etc.
- */
- static mxml_node_t * /* I - Found node or NULL */
- find_public(mxml_node_t *node, /* I - Current node */
- mxml_node_t *top, /* I - Top node */
- const char *name) /* I - Name of element */
- {
- mxml_node_t *description, /* Description node */
- *comment; /* Comment node */
- for (node = mxmlFindElement(node, top, name, NULL, NULL,
- node == top ? MXML_DESCEND_FIRST :
- MXML_NO_DESCEND);
- node;
- node = mxmlFindElement(node, top, name, NULL, NULL, MXML_NO_DESCEND))
- {
- /*
- * Get the description for this node...
- */
- description = mxmlFindElement(node, node, "description", NULL, NULL,
- MXML_DESCEND_FIRST);
- /*
- * A missing or empty description signals a private node...
- */
- if (!description)
- continue;
- /*
- * Look for @private@ in the comment text...
- */
- for (comment = description->child; comment; comment = comment->next)
- if ((comment->type == MXML_TEXT &&
- strstr(comment->value.text.string, "@private@")) ||
- (comment->type == MXML_OPAQUE &&
- strstr(comment->value.opaque, "@private@")))
- break;
- if (!comment)
- {
- /*
- * No @private@, so return this node...
- */
- return (node);
- }
- }
- /*
- * If we get here, there are no (more) public nodes...
- */
- return (NULL);
- }
- /*
- * 'get_comment_info()' - Get info from comment.
- */
- static char * /* O - Info from comment */
- get_comment_info(
- mxml_node_t *description) /* I - Description node */
- {
- char text[10240], /* Description text */
- since[255], /* @since value */
- *ptr; /* Pointer into text */
- static char info[1024]; /* Info string */
- if (!description)
- return ("");
- get_text(description, text, sizeof(text));
- for (ptr = strchr(text, '@'); ptr; ptr = strchr(ptr + 1, '@'))
- {
- if (!strncmp(ptr, "@deprecated@", 12))
- return ("<span class=\"info\"> DEPRECATED </span>");
- else if (!strncmp(ptr, "@since ", 7))
- {
- strncpy(since, ptr + 7, sizeof(since) - 1);
- since[sizeof(since) - 1] = '\0';
- if ((ptr = strchr(since, '@')) != NULL)
- *ptr = '\0';
- snprintf(info, sizeof(info), "<span class=\"info\"> %s </span>", since);
- return (info);
- }
- }
- return ("");
- }
- /*
- * 'get_text()' - Get the text for a node.
- */
- static char * /* O - Text in node */
- get_text(mxml_node_t *node, /* I - Node to get */
- char *buffer, /* I - Buffer */
- int buflen) /* I - Size of buffer */
- {
- char *ptr, /* Pointer into buffer */
- *end; /* End of buffer */
- int len; /* Length of node */
- mxml_node_t *current; /* Current node */
- ptr = buffer;
- end = buffer + buflen - 1;
- for (current = node->child; current && ptr < end; current = current->next)
- {
- if (current->type == MXML_TEXT)
- {
- if (current->value.text.whitespace)
- *ptr++ = ' ';
- len = (int)strlen(current->value.text.string);
- if (len > (int)(end - ptr))
- len = (int)(end - ptr);
- memcpy(ptr, current->value.text.string, len);
- ptr += len;
- }
- else if (current->type == MXML_OPAQUE)
- {
- len = (int)strlen(current->value.opaque);
- if (len > (int)(end - ptr))
- len = (int)(end - ptr);
- memcpy(ptr, current->value.opaque, len);
- ptr += len;
- }
- }
- *ptr = '\0';
- return (buffer);
- }
- /*
- * 'load_cb()' - Set the type of child nodes.
- */
- static mxml_type_t /* O - Node type */
- load_cb(mxml_node_t *node) /* I - Node */
- {
- if (!strcmp(node->value.element.name, "description"))
- return (MXML_OPAQUE);
- else
- return (MXML_TEXT);
- }
- /*
- * 'new_documentation()' - Create a new documentation tree.
- */
- static mxml_node_t * /* O - New documentation */
- new_documentation(mxml_node_t **mxmldoc)/* O - mxmldoc node */
- {
- mxml_node_t *doc; /* New documentation */
- /*
- * Create an empty XML documentation file...
- */
- doc = mxmlNewXML(NULL);
- *mxmldoc = mxmlNewElement(doc, "mxmldoc");
- mxmlElementSetAttr(*mxmldoc, "xmlns", "http://www.easysw.com");
- mxmlElementSetAttr(*mxmldoc, "xmlns:xsi",
- "http://www.w3.org/2001/XMLSchema-instance");
- mxmlElementSetAttr(*mxmldoc, "xsi:schemaLocation",
- "http://www.minixml.org/mxmldoc.xsd");
- return (doc);
- }
- /*
- * 'remove_directory()' - Remove a directory.
- */
- static int /* O - 1 on success, 0 on failure */
- remove_directory(const char *path) /* I - Directory to remove */
- {
- #ifdef WIN32
- /* TODO: Add Windows directory removal code */
- #else
- DIR *dir; /* Directory */
- struct dirent *dent; /* Current directory entry */
- char filename[1024]; /* Current filename */
- struct stat fileinfo; /* File information */
- if ((dir = opendir(path)) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to open directory \"%s\": %s\n", path,
- strerror(errno));
- return (0);
- }
- while ((dent = readdir(dir)) != NULL)
- {
- /*
- * Skip "." and ".."...
- */
- if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
- continue;
- /*
- * See if we have a file or directory...
- */
- snprintf(filename, sizeof(filename), "%s/%s", path, dent->d_name);
- if (stat(filename, &fileinfo))
- {
- fprintf(stderr, "mxmldoc: Unable to stat \"%s\": %s\n", filename,
- strerror(errno));
- closedir(dir);
- return (0);
- }
- if (S_ISDIR(fileinfo.st_mode))
- {
- if (!remove_directory(filename))
- {
- closedir(dir);
- return (0);
- }
- }
- else if (unlink(filename))
- {
- fprintf(stderr, "mxmldoc: Unable to remove \"%s\": %s\n", filename,
- strerror(errno));
- closedir(dir);
- return (0);
- }
- }
- closedir(dir);
- if (rmdir(path))
- {
- fprintf(stderr, "mxmldoc: Unable to remove directory \"%s\": %s\n", path,
- strerror(errno));
- return (0);
- }
- #endif /* WIN32 */
- return (1);
- }
- /*
- * 'safe_strcpy()' - Copy a string allowing for overlapping strings.
- */
- static void
- safe_strcpy(char *dst, /* I - Destination string */
- const char *src) /* I - Source string */
- {
- while (*src)
- *dst++ = *src++;
- *dst = '\0';
- }
- /*
- * 'scan_file()' - Scan a source file.
- */
- static int /* O - 0 on success, -1 on error */
- scan_file(const char *filename, /* I - Filename */
- FILE *fp, /* I - File to scan */
- mxml_node_t *tree) /* I - Function tree */
- {
- int state, /* Current parser state */
- braces, /* Number of braces active */
- parens; /* Number of active parenthesis */
- int ch; /* Current character */
- char buffer[65536], /* String buffer */
- *bufptr; /* Pointer into buffer */
- const char *scope; /* Current variable/function scope */
- mxml_node_t *comment, /* <comment> node */
- *constant, /* <constant> node */
- *enumeration, /* <enumeration> node */
- *function, /* <function> node */
- *fstructclass, /* function struct/class node */
- *structclass, /* <struct> or <class> node */
- *typedefnode, /* <typedef> node */
- *variable, /* <variable> or <argument> node */
- *returnvalue, /* <returnvalue> node */
- *type, /* <type> node */
- *description, /* <description> node */
- *node, /* Current node */
- *next; /* Next node */
- #if DEBUG > 1
- mxml_node_t *temp; /* Temporary node */
- int oldstate, /* Previous state */
- oldch; /* Old character */
- static const char *states[] = /* State strings */
- {
- "STATE_NONE",
- "STATE_PREPROCESSOR",
- "STATE_C_COMMENT",
- "STATE_CXX_COMMENT",
- "STATE_STRING",
- "STATE_CHARACTER",
- "STATE_IDENTIFIER"
- };
- #endif /* DEBUG > 1 */
- #ifdef DEBUG
- fprintf(stderr, "scan_file(filename=\"%s\", fp=%p, tree=%p)\n", filename,
- fp, tree);
- #endif /* DEBUG */
- /*
- * Initialize the finite state machine...
- */
- state = STATE_NONE;
- braces = 0;
- parens = 0;
- bufptr = buffer;
- comment = mxmlNewElement(MXML_NO_PARENT, "temp");
- constant = NULL;
- enumeration = NULL;
- function = NULL;
- variable = NULL;
- returnvalue = NULL;
- type = NULL;
- description = NULL;
- typedefnode = NULL;
- structclass = NULL;
- fstructclass = NULL;
- if (!strcmp(tree->value.element.name, "class"))
- scope = "private";
- else
- scope = NULL;
- /*
- * Read until end-of-file...
- */
- while ((ch = getc(fp)) != EOF)
- {
- #if DEBUG > 1
- oldstate = state;
- oldch = ch;
- #endif /* DEBUG > 1 */
- switch (state)
- {
- case STATE_NONE : /* No state - whitespace, etc. */
- switch (ch)
- {
- case '/' : /* Possible C/C++ comment */
- ch = getc(fp);
- bufptr = buffer;
- if (ch == '*')
- state = STATE_C_COMMENT;
- else if (ch == '/')
- state = STATE_CXX_COMMENT;
- else
- {
- ungetc(ch, fp);
- if (type)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< / >>>\n", stderr);
- #endif /* DEBUG */
- ch = type->last_child->value.text.string[0];
- mxmlNewText(type, isalnum(ch) || ch == '_', "/");
- }
- }
- break;
- case '#' : /* Preprocessor */
- #ifdef DEBUG
- fputs(" #preprocessor...\n", stderr);
- #endif /* DEBUG */
- state = STATE_PREPROCESSOR;
- break;
- case '\'' : /* Character constant */
- state = STATE_CHARACTER;
- bufptr = buffer;
- *bufptr++ = ch;
- break;
- case '\"' : /* String constant */
- state = STATE_STRING;
- bufptr = buffer;
- *bufptr++ = ch;
- break;
- case '{' :
- #ifdef DEBUG
- fprintf(stderr, " open brace, function=%p, type=%p...\n",
- function, type);
- if (type)
- fprintf(stderr, " type->child=\"%s\"...\n",
- type->child->value.text.string);
- #endif /* DEBUG */
- if (function)
- {
- if (fstructclass)
- {
- sort_node(fstructclass, function);
- fstructclass = NULL;
- }
- else
- sort_node(tree, function);
- function = NULL;
- }
- else if (type && type->child &&
- ((!strcmp(type->child->value.text.string, "typedef") &&
- type->child->next &&
- (!strcmp(type->child->next->value.text.string, "struct") ||
- !strcmp(type->child->next->value.text.string, "union") ||
- !strcmp(type->child->next->value.text.string, "class"))) ||
- !strcmp(type->child->value.text.string, "union") ||
- !strcmp(type->child->value.text.string, "struct") ||
- !strcmp(type->child->value.text.string, "class")))
- {
- /*
- * Start of a class or structure...
- */
- if (!strcmp(type->child->value.text.string, "typedef"))
- {
- #ifdef DEBUG
- fputs(" starting typedef...\n", stderr);
- #endif /* DEBUG */
- typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
- mxmlDelete(type->child);
- }
- else
- typedefnode = NULL;
- structclass = mxmlNewElement(MXML_NO_PARENT,
- type->child->value.text.string);
- #ifdef DEBUG
- fprintf(stderr, "%c%s: <<<< %s >>>\n",
- toupper(type->child->value.text.string[0]),
- type->child->value.text.string + 1,
- type->child->next ?
- type->child->next->value.text.string : "(noname)");
- fputs(" type =", stderr);
- for (node = type->child; node; node = node->next)
- fprintf(stderr, " \"%s\"", node->value.text.string);
- putc('\n', stderr);
- fprintf(stderr, " scope = %s\n", scope ? scope : "(null)");
- #endif /* DEBUG */
- if (type->child->next)
- {
- mxmlElementSetAttr(structclass, "name",
- type->child->next->value.text.string);
- sort_node(tree, structclass);
- }
- if (typedefnode && type->child)
- type->child->value.text.whitespace = 0;
- else if (structclass && type->child &&
- type->child->next && type->child->next->next)
- {
- for (bufptr = buffer, node = type->child->next->next;
- node;
- bufptr += strlen(bufptr))
- {
- if (node->value.text.whitespace && bufptr > buffer)
- *bufptr++ = ' ';
- strcpy(bufptr, node->value.text.string);
- next = node->next;
- mxmlDelete(node);
- node = next;
- }
- mxmlElementSetAttr(structclass, "parent", buffer);
- mxmlDelete(type);
- type = NULL;
- }
- else
- {
- mxmlDelete(type);
- type = NULL;
- }
- if (typedefnode && comment->last_child)
- {
- /*
- * Copy comment for typedef as well as class/struct/union...
- */
- mxmlNewText(comment, 0,
- comment->last_child->value.text.string);
- description = mxmlNewElement(typedefnode, "description");
- #ifdef DEBUG
- fprintf(stderr,
- " duplicating comment %p/%p for typedef...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- update_comment(typedefnode, comment->last_child);
- mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
- comment->last_child);
- }
- description = mxmlNewElement(structclass, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to %s...\n",
- comment->last_child, comment->child,
- structclass->value.element.name);
- #endif /* DEBUG */
- update_comment(structclass, comment->last_child);
- mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
- comment->last_child);
- if (scan_file(filename, fp, structclass))
- {
- mxmlDelete(comment);
- return (-1);
- }
- #ifdef DEBUG
- fputs(" ended typedef...\n", stderr);
- #endif /* DEBUG */
- structclass = NULL;
- break;
- }
- else if (type && type->child && type->child->next &&
- (!strcmp(type->child->value.text.string, "enum") ||
- (!strcmp(type->child->value.text.string, "typedef") &&
- !strcmp(type->child->next->value.text.string, "enum"))))
- {
- /*
- * Enumeration type...
- */
- if (!strcmp(type->child->value.text.string, "typedef"))
- {
- #ifdef DEBUG
- fputs(" starting typedef...\n", stderr);
- #endif /* DEBUG */
- typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
- mxmlDelete(type->child);
- }
- else
- typedefnode = NULL;
- enumeration = mxmlNewElement(MXML_NO_PARENT, "enumeration");
- #ifdef DEBUG
- fprintf(stderr, "Enumeration: <<<< %s >>>\n",
- type->child->next ?
- type->child->next->value.text.string : "(noname)");
- #endif /* DEBUG */
- if (type->child->next)
- {
- mxmlElementSetAttr(enumeration, "name",
- type->child->next->value.text.string);
- sort_node(tree, enumeration);
- }
- if (typedefnode && type->child)
- type->child->value.text.whitespace = 0;
- else
- {
- mxmlDelete(type);
- type = NULL;
- }
- if (typedefnode && comment->last_child)
- {
- /*
- * Copy comment for typedef as well as class/struct/union...
- */
- mxmlNewText(comment, 0,
- comment->last_child->value.text.string);
- description = mxmlNewElement(typedefnode, "description");
- #ifdef DEBUG
- fprintf(stderr,
- " duplicating comment %p/%p for typedef...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- update_comment(typedefnode, comment->last_child);
- mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
- comment->last_child);
- }
- description = mxmlNewElement(enumeration, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to enumeration...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- update_comment(enumeration, comment->last_child);
- mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
- comment->last_child);
- }
- else if (type && type->child &&
- !strcmp(type->child->value.text.string, "extern"))
- {
- if (scan_file(filename, fp, tree))
- {
- mxmlDelete(comment);
- return (-1);
- }
- }
- else if (type)
- {
- mxmlDelete(type);
- type = NULL;
- }
- braces ++;
- function = NULL;
- variable = NULL;
- break;
- case '}' :
- #ifdef DEBUG
- fputs(" close brace...\n", stderr);
- #endif /* DEBUG */
- if (structclass)
- scope = NULL;
- if (!typedefnode)
- enumeration = NULL;
- constant = NULL;
- structclass = NULL;
- if (braces > 0)
- braces --;
- else
- {
- mxmlDelete(comment);
- return (0);
- }
- break;
- case '(' :
- if (type)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< ( >>>\n", stderr);
- #endif /* DEBUG */
- mxmlNewText(type, 0, "(");
- }
- parens ++;
- break;
- case ')' :
- if (type && parens)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< ) >>>\n", stderr);
- #endif /* DEBUG */
- mxmlNewText(type, 0, ")");
- }
- if (function && type && !parens)
- {
- /*
- * Check for "void" argument...
- */
- if (type->child && type->child->next)
- variable = add_variable(function, "argument", type);
- else
- mxmlDelete(type);
- type = NULL;
- }
- if (parens > 0)
- parens --;
- break;
- case ';' :
- #ifdef DEBUG
- fputs("Identifier: <<<< ; >>>\n", stderr);
- fprintf(stderr, " enumeration=%p, function=%p, type=%p, type->child=%p, typedefnode=%p\n",
- enumeration, function, type, type ? type->child : NULL, typedefnode);
- #endif /* DEBUG */
- if (function)
- {
- if (!strcmp(tree->value.element.name, "class"))
- {
- #ifdef DEBUG
- fputs(" ADDING FUNCTION TO CLASS\n", stderr);
- #endif /* DEBUG */
- sort_node(tree, function);
- }
- else
- mxmlDelete(function);
- function = NULL;
- variable = NULL;
- }
- if (type)
- {
- /*
- * See if we have a typedef...
- */
- if (type->child &&
- !strcmp(type->child->value.text.string, "typedef"))
- {
- /*
- * Yes, add it!
- */
- typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
- for (node = type->child->next; node; node = node->next)
- if (!strcmp(node->value.text.string, "("))
- break;
- if (node)
- {
- for (node = node->next; node; node = node->next)
- if (strcmp(node->value.text.string, "*"))
- break;
- }
- if (!node)
- node = type->last_child;
- #ifdef DEBUG
- fprintf(stderr, " ADDING TYPEDEF FOR %p(%s)...\n",
- node, node->value.text.string);
- #endif /* DEBUG */
- mxmlElementSetAttr(typedefnode, "name",
- node->value.text.string);
- sort_node(tree, typedefnode);
- if (type->child != node)
- mxmlDelete(type->child);
- mxmlDelete(node);
- if (type->child)
- type->child->value.text.whitespace = 0;
- mxmlAdd(typedefnode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
- type);
- type = NULL;
- break;
- }
- else if (typedefnode && enumeration)
- {
- /*
- * Add enum typedef...
- */
- node = type->child;
- #ifdef DEBUG
- fprintf(stderr, " ADDING TYPEDEF FOR %p(%s)...\n",
- node, node->value.text.string);
- #endif /* DEBUG */
- mxmlElementSetAttr(typedefnode, "name",
- node->value.text.string);
- sort_node(tree, typedefnode);
- mxmlDelete(type);
- type = mxmlNewElement(typedefnode, "type");
- mxmlNewText(type, 0, "enum");
- mxmlNewText(type, 1,
- mxmlElementGetAttr(enumeration, "name"));
- enumeration = NULL;
- type = NULL;
- break;
- }
- mxmlDelete(type);
- type = NULL;
- }
- break;
- case ':' :
- if (type)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< : >>>\n", stderr);
- #endif /* DEBUG */
- mxmlNewText(type, 1, ":");
- }
- break;
- case '*' :
- if (type)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< * >>>\n", stderr);
- #endif /* DEBUG */
- ch = type->last_child->value.text.string[0];
- mxmlNewText(type, isalnum(ch) || ch == '_', "*");
- }
- break;
- case ',' :
- if (type && !enumeration)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< , >>>\n", stderr);
- #endif /* DEBUG */
- mxmlNewText(type, 0, ",");
- }
- break;
- case '&' :
- if (type)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< & >>>\n", stderr);
- #endif /* DEBUG */
- mxmlNewText(type, 1, "&");
- }
- break;
- case '+' :
- if (type)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< + >>>\n", stderr);
- #endif /* DEBUG */
- ch = type->last_child->value.text.string[0];
- mxmlNewText(type, isalnum(ch) || ch == '_', "+");
- }
- break;
- case '-' :
- if (type)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< - >>>\n", stderr);
- #endif /* DEBUG */
- ch = type->last_child->value.text.string[0];
- mxmlNewText(type, isalnum(ch) || ch == '_', "-");
- }
- break;
- case '=' :
- if (type)
- {
- #ifdef DEBUG
- fputs("Identifier: <<<< = >>>\n", stderr);
- #endif /* DEBUG */
- ch = type->last_child->value.text.string[0];
- mxmlNewText(type, isalnum(ch) || ch == '_', "=");
- }
- break;
- default : /* Other */
- if (isalnum(ch) || ch == '_' || ch == '.' || ch == ':' || ch == '~')
- {
- state = STATE_IDENTIFIER;
- bufptr = buffer;
- *bufptr++ = ch;
- }
- break;
- }
- break;
- case STATE_PREPROCESSOR : /* Preprocessor directive */
- if (ch == '\n')
- state = STATE_NONE;
- else if (ch == '\\')
- getc(fp);
- break;
- case STATE_C_COMMENT : /* Inside a C comment */
- switch (ch)
- {
- case '\n' :
- while ((ch = getc(fp)) != EOF)
- if (ch == '*')
- {
- ch = getc(fp);
- if (ch == '/')
- {
- *bufptr = '\0';
- if (comment->child != comment->last_child)
- {
- #ifdef DEBUG
- fprintf(stderr, " removing comment %p(%20.20s), last comment %p(%20.20s)...\n",
- comment->child,
- comment->child ? comment->child->value.text.string : "",
- comment->last_child,
- comment->last_child ? comment->last_child->value.text.string : "");
- #endif /* DEBUG */
- mxmlDelete(comment->child);
- #ifdef DEBUG
- fprintf(stderr, " new comment %p, last comment %p...\n",
- comment->child, comment->last_child);
- #endif /* DEBUG */
- }
- #ifdef DEBUG
- fprintf(stderr,
- " processing comment, variable=%p, "
- "constant=%p, typedefnode=%p, tree=\"%s\"\n",
- variable, constant, typedefnode,
- tree->value.element.name);
- #endif /* DEBUG */
- if (variable)
- {
- if (strstr(buffer, "@private@"))
- {
- /*
- * Delete private variables...
- */
- mxmlDelete(variable);
- }
- else
- {
- description = mxmlNewElement(variable, "description");
- #ifdef DEBUG
- fprintf(stderr,
- " adding comment %p/%p to variable...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(variable,
- mxmlNewText(description, 0, buffer));
- }
- variable = NULL;
- }
- else if (constant)
- {
- if (strstr(buffer, "@private@"))
- {
- /*
- * Delete private constants...
- */
- mxmlDelete(constant);
- }
- else
- {
- description = mxmlNewElement(constant, "description");
- #ifdef DEBUG
- fprintf(stderr,
- " adding comment %p/%p to constant...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(constant,
- mxmlNewText(description, 0, buffer));
- }
- constant = NULL;
- }
- else if (typedefnode)
- {
- if (strstr(buffer, "@private@"))
- {
- /*
- * Delete private typedefs...
- */
- mxmlDelete(typedefnode);
- if (structclass)
- {
- mxmlDelete(structclass);
- structclass = NULL;
- }
- if (enumeration)
- {
- mxmlDelete(enumeration);
- enumeration = NULL;
- }
- }
- else
- {
- description = mxmlNewElement(typedefnode, "description");
- #ifdef DEBUG
- fprintf(stderr,
- " adding comment %p/%p to typedef %s...\n",
- comment->last_child, comment->child,
- mxmlElementGetAttr(typedefnode, "name"));
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(typedefnode,
- mxmlNewText(description, 0, buffer));
- if (structclass)
- {
- description = mxmlNewElement(structclass, "description");
- update_comment(structclass,
- mxmlNewText(description, 0, buffer));
- }
- else if (enumeration)
- {
- description = mxmlNewElement(enumeration, "description");
- update_comment(enumeration,
- mxmlNewText(description, 0, buffer));
- }
- }
- typedefnode = NULL;
- }
- else if (strcmp(tree->value.element.name, "mxmldoc") &&
- !mxmlFindElement(tree, tree, "description",
- NULL, NULL, MXML_DESCEND_FIRST))
- {
- description = mxmlNewElement(tree, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to parent...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(tree,
- mxmlNewText(description, 0, buffer));
- }
- else
- {
- #ifdef DEBUG
- fprintf(stderr, " before adding comment, child=%p, last_child=%p\n",
- comment->child, comment->last_child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- #ifdef DEBUG
- fprintf(stderr, " after adding comment, child=%p, last_child=%p\n",
- comment->child, comment->last_child);
- #endif /* DEBUG */
- }
- #ifdef DEBUG
- fprintf(stderr, "C comment: <<<< %s >>>\n", buffer);
- #endif /* DEBUG */
- state = STATE_NONE;
- break;
- }
- else
- ungetc(ch, fp);
- }
- else if (ch == '\n' && bufptr > buffer &&
- bufptr < (buffer + sizeof(buffer) - 1))
- *bufptr++ = ch;
- else if (!isspace(ch))
- break;
- if (ch != EOF)
- ungetc(ch, fp);
- if (bufptr > buffer && bufptr < (buffer + sizeof(buffer) - 1))
- *bufptr++ = '\n';
- break;
- case '/' :
- if (ch == '/' && bufptr > buffer && bufptr[-1] == '*')
- {
- while (bufptr > buffer &&
- (bufptr[-1] == '*' || isspace(bufptr[-1] & 255)))
- bufptr --;
- *bufptr = '\0';
- if (comment->child != comment->last_child)
- {
- #ifdef DEBUG
- fprintf(stderr, " removing comment %p(%20.20s), last comment %p(%20.20s)...\n",
- comment->child,
- comment->child ? comment->child->value.text.string : "",
- comment->last_child,
- comment->last_child ? comment->last_child->value.text.string : "");
- #endif /* DEBUG */
- mxmlDelete(comment->child);
- #ifdef DEBUG
- fprintf(stderr, " new comment %p, last comment %p...\n",
- comment->child, comment->last_child);
- #endif /* DEBUG */
- }
- #ifdef DEBUG
- fprintf(stderr,
- " processing comment, variable=%p, "
- "constant=%p, typedefnode=%p, tree=\"%s\"\n",
- variable, constant, typedefnode,
- tree->value.element.name);
- #endif /* DEBUG */
- if (variable)
- {
- if (strstr(buffer, "@private@"))
- {
- /*
- * Delete private variables...
- */
- mxmlDelete(variable);
- }
- else
- {
- description = mxmlNewElement(variable, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to variable...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(variable,
- mxmlNewText(description, 0, buffer));
- }
- variable = NULL;
- }
- else if (constant)
- {
- if (strstr(buffer, "@private@"))
- {
- /*
- * Delete private constants...
- */
- mxmlDelete(constant);
- }
- else
- {
- description = mxmlNewElement(constant, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to constant...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(constant,
- mxmlNewText(description, 0, buffer));
- }
- constant = NULL;
- }
- else if (typedefnode)
- {
- if (strstr(buffer, "@private@"))
- {
- /*
- * Delete private typedefs...
- */
- mxmlDelete(typedefnode);
- if (structclass)
- {
- mxmlDelete(structclass);
- structclass = NULL;
- }
- if (enumeration)
- {
- mxmlDelete(enumeration);
- enumeration = NULL;
- }
- }
- else
- {
- description = mxmlNewElement(typedefnode, "description");
- #ifdef DEBUG
- fprintf(stderr,
- " adding comment %p/%p to typedef %s...\n",
- comment->last_child, comment->child,
- mxmlElementGetAttr(typedefnode, "name"));
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(typedefnode,
- mxmlNewText(description, 0, buffer));
- if (structclass)
- {
- description = mxmlNewElement(structclass, "description");
- update_comment(structclass,
- mxmlNewText(description, 0, buffer));
- }
- else if (enumeration)
- {
- description = mxmlNewElement(enumeration, "description");
- update_comment(enumeration,
- mxmlNewText(description, 0, buffer));
- }
- }
- typedefnode = NULL;
- }
- else if (strcmp(tree->value.element.name, "mxmldoc") &&
- !mxmlFindElement(tree, tree, "description",
- NULL, NULL, MXML_DESCEND_FIRST))
- {
- description = mxmlNewElement(tree, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to parent...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(tree,
- mxmlNewText(description, 0, buffer));
- }
- else
- mxmlNewText(comment, 0, buffer);
- #ifdef DEBUG
- fprintf(stderr, "C comment: <<<< %s >>>\n", buffer);
- #endif /* DEBUG */
- state = STATE_NONE;
- break;
- }
- default :
- if (ch == ' ' && bufptr == buffer)
- break;
- if (bufptr < (buffer + sizeof(buffer) - 1))
- *bufptr++ = ch;
- break;
- }
- break;
- case STATE_CXX_COMMENT : /* Inside a C++ comment */
- if (ch == '\n')
- {
- state = STATE_NONE;
- *bufptr = '\0';
- if (comment->child != comment->last_child)
- {
- #ifdef DEBUG
- fprintf(stderr, " removing comment %p(%20.20s), last comment %p(%20.20s)...\n",
- comment->child,
- comment->child ? comment->child->value.text.string : "",
- comment->last_child,
- comment->last_child ? comment->last_child->value.text.string : "");
- #endif /* DEBUG */
- mxmlDelete(comment->child);
- #ifdef DEBUG
- fprintf(stderr, " new comment %p, last comment %p...\n",
- comment->child, comment->last_child);
- #endif /* DEBUG */
- }
- if (variable)
- {
- if (strstr(buffer, "@private@"))
- {
- /*
- * Delete private variables...
- */
- mxmlDelete(variable);
- }
- else
- {
- description = mxmlNewElement(variable, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to variable...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(variable,
- mxmlNewText(description, 0, buffer));
- }
- variable = NULL;
- }
- else if (constant)
- {
- if (strstr(buffer, "@private@"))
- {
- /*
- * Delete private constants...
- */
- mxmlDelete(constant);
- }
- else
- {
- description = mxmlNewElement(constant, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to constant...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(constant,
- mxmlNewText(description, 0, buffer));
- }
- constant = NULL;
- }
- else if (typedefnode)
- {
- if (strstr(buffer, "@private@"))
- {
- /*
- * Delete private typedefs...
- */
- mxmlDelete(typedefnode);
- typedefnode = NULL;
- if (structclass)
- {
- mxmlDelete(structclass);
- structclass = NULL;
- }
- if (enumeration)
- {
- mxmlDelete(enumeration);
- enumeration = NULL;
- }
- }
- else
- {
- description = mxmlNewElement(typedefnode, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to typedef %s...\n",
- comment->last_child, comment->child,
- mxmlElementGetAttr(typedefnode, "name"));
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(typedefnode,
- mxmlNewText(description, 0, buffer));
- if (structclass)
- {
- description = mxmlNewElement(structclass, "description");
- update_comment(structclass,
- mxmlNewText(description, 0, buffer));
- }
- else if (enumeration)
- {
- description = mxmlNewElement(enumeration, "description");
- update_comment(enumeration,
- mxmlNewText(description, 0, buffer));
- }
- }
- }
- else if (strcmp(tree->value.element.name, "mxmldoc") &&
- !mxmlFindElement(tree, tree, "description",
- NULL, NULL, MXML_DESCEND_FIRST))
- {
- description = mxmlNewElement(tree, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to parent...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- mxmlNewText(comment, 0, buffer);
- update_comment(tree,
- mxmlNewText(description, 0, buffer));
- }
- else
- mxmlNewText(comment, 0, buffer);
- #ifdef DEBUG
- fprintf(stderr, "C++ comment: <<<< %s >>>\n", buffer);
- #endif /* DEBUG */
- }
- else if (ch == ' ' && bufptr == buffer)
- break;
- else if (bufptr < (buffer + sizeof(buffer) - 1))
- *bufptr++ = ch;
- break;
- case STATE_STRING : /* Inside a string constant */
- *bufptr++ = ch;
- if (ch == '\\')
- *bufptr++ = getc(fp);
- else if (ch == '\"')
- {
- *bufptr = '\0';
- if (type)
- mxmlNewText(type, type->child != NULL, buffer);
- state = STATE_NONE;
- }
- break;
- case STATE_CHARACTER : /* Inside a character constant */
- *bufptr++ = ch;
- if (ch == '\\')
- *bufptr++ = getc(fp);
- else if (ch == '\'')
- {
- *bufptr = '\0';
- if (type)
- mxmlNewText(type, type->child != NULL, buffer);
- state = STATE_NONE;
- }
- break;
- case STATE_IDENTIFIER : /* Inside a keyword or identifier */
- if (isalnum(ch) || ch == '_' || ch == '[' || ch == ']' ||
- (ch == ',' && (parens > 1 || (type && !enumeration && !function))) ||
- ch == ':' || ch == '.' || ch == '~')
- {
- if (bufptr < (buffer + sizeof(buffer) - 1))
- *bufptr++ = ch;
- }
- else
- {
- ungetc(ch, fp);
- *bufptr = '\0';
- state = STATE_NONE;
- #ifdef DEBUG
- fprintf(stderr, " braces=%d, type=%p, type->child=%p, buffer=\"%s\"\n",
- braces, type, type ? type->child : NULL, buffer);
- #endif /* DEBUG */
- if (!braces)
- {
- if (!type || !type->child)
- {
- if (!strcmp(tree->value.element.name, "class"))
- {
- if (!strcmp(buffer, "public") ||
- !strcmp(buffer, "public:"))
- {
- scope = "public";
- #ifdef DEBUG
- fputs(" scope = public\n", stderr);
- #endif /* DEBUG */
- break;
- }
- else if (!strcmp(buffer, "private") ||
- !strcmp(buffer, "private:"))
- {
- scope = "private";
- #ifdef DEBUG
- fputs(" scope = private\n", stderr);
- #endif /* DEBUG */
- break;
- }
- else if (!strcmp(buffer, "protected") ||
- !strcmp(buffer, "protected:"))
- {
- scope = "protected";
- #ifdef DEBUG
- fputs(" scope = protected\n", stderr);
- #endif /* DEBUG */
- break;
- }
- }
- }
- if (!type)
- type = mxmlNewElement(MXML_NO_PARENT, "type");
- #ifdef DEBUG
- fprintf(stderr, " function=%p (%s), type->child=%p, ch='%c', parens=%d\n",
- function,
- function ? mxmlElementGetAttr(function, "name") : "null",
- type->child, ch, parens);
- #endif /* DEBUG */
- if (!function && ch == '(')
- {
- if (type->child &&
- !strcmp(type->child->value.text.string, "extern"))
- {
- /*
- * Remove external declarations...
- */
- mxmlDelete(type);
- type = NULL;
- break;
- }
- if (type->child &&
- !strcmp(type->child->value.text.string, "static") &&
- !strcmp(tree->value.element.name, "mxmldoc"))
- {
- /*
- * Remove static functions...
- */
- mxmlDelete(type);
- type = NULL;
- break;
- }
- function = mxmlNewElement(MXML_NO_PARENT, "function");
- if ((bufptr = strchr(buffer, ':')) != NULL && bufptr[1] == ':')
- {
- *bufptr = '\0';
- bufptr += 2;
- if ((fstructclass =
- mxmlFindElement(tree, tree, "class", "name", buffer,
- MXML_DESCEND_FIRST)) == NULL)
- fstructclass =
- mxmlFindElement(tree, tree, "struct", "name", buffer,
- MXML_DESCEND_FIRST);
- }
- else
- bufptr = buffer;
- mxmlElementSetAttr(function, "name", bufptr);
- if (scope)
- mxmlElementSetAttr(function, "scope", scope);
- #ifdef DEBUG
- fprintf(stderr, "function: %s\n", buffer);
- fprintf(stderr, " scope = %s\n", scope ? scope : "(null)");
- fprintf(stderr, " comment = %p\n", comment);
- fprintf(stderr, " child = (%p) %s\n",
- comment->child,
- comment->child ?
- comment->child->value.text.string : "(null)");
- fprintf(stderr, " last_child = (%p) %s\n",
- comment->last_child,
- comment->last_child ?
- comment->last_child->value.text.string : "(null)");
- #endif /* DEBUG */
- if (type->last_child &&
- strcmp(type->last_child->value.text.string, "void"))
- {
- returnvalue = mxmlNewElement(function, "returnvalue");
- mxmlAdd(returnvalue, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
- description = mxmlNewElement(returnvalue, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to returnvalue...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- update_comment(returnvalue, comment->last_child);
- mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
- comment->last_child);
- }
- else
- mxmlDelete(type);
- description = mxmlNewElement(function, "description");
- #ifdef DEBUG
- fprintf(stderr, " adding comment %p/%p to function...\n",
- comment->last_child, comment->child);
- #endif /* DEBUG */
- update_comment(function, comment->last_child);
- mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
- comment->last_child);
- type = NULL;
- }
- else if (function && ((ch == ')' && parens == 1) || ch == ','))
- {
- /*
- * Argument definition...
- */
- if (strcmp(buffer, "void"))
- {
- mxmlNewText(type, type->child != NULL &&
- type->last_child->value.text.string[0] != '(' &&
- type->last_child->value.text.string[0] != '*',
- buffer);
- #ifdef DEBUG
- fprintf(stderr, "Argument: <<<< %s >>>\n", buffer);
- #endif /* DEBUG */
- variable = add_variable(function, "argument", type);
- }
- else
- mxmlDelete(type);
- type = NULL;
- }
- else if (type->child && !function && (ch == ';' || ch == ','))
- {
- #ifdef DEBUG
- fprintf(stderr, " got semicolon, typedefnode=%p, structclass=%p\n",
- typedefnode, structclass);
- #endif /* DEBUG */
- if (typedefnode || structclass)
- {
- #ifdef DEBUG
- fprintf(stderr, "Typedef/struct/class: <<<< %s >>>>\n", buffer);
- #endif /* DEBUG */
- if (typedefnode)
- {
- mxmlElementSetAttr(typedefnode, "name", buffer);
- sort_node(tree, typedefnode);
- }
- if (structclass && !mxmlElementGetAttr(structclass, "name"))
- {
- #ifdef DEBUG
- fprintf(stderr, "setting struct/class name to %s!\n",
- type->last_child->value.text.string);
- #endif /* DEBUG */
- mxmlElementSetAttr(structclass, "name", buffer);
- sort_node(tree, structclass);
- structclass = NULL;
- }
- if (typedefnode)
- mxmlAdd(typedefnode, MXML_ADD_BEFORE, MXML_ADD_TO_PARENT,
- type);
- else
- mxmlDelete(type);
- type = NULL;
- typedefnode = NULL;
- }
- else if (type->child &&
- !strcmp(type->child->value.text.string, "typedef"))
- {
- /*
- * Simple typedef...
- */
- #ifdef DEBUG
- fprintf(stderr, "Typedef: <<<< %s >>>\n", buffer);
- #endif /* DEBUG */
- typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
- mxmlElementSetAttr(typedefnode, "name", buffer);
- mxmlDelete(type->child);
- sort_node(tree, typedefnode);
- if (type->child)
- type->child->value.text.whitespace = 0;
- mxmlAdd(typedefnode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
- type = NULL;
- }
- else if (!parens)
- {
- /*
- * Variable definition...
- */
- if (type->child &&
- !strcmp(type->child->value.text.string, "static") &&
- !strcmp(tree->value.element.name, "mxmldoc"))
- {
- /*
- * Remove static functions...
- */
- mxmlDelete(type);
- type = NULL;
- break;
- }
- mxmlNewText(type, type->child != NULL &&
- type->last_child->value.text.string[0] != '(' &&
- type->last_child->value.text.string[0] != '*',
- buffer);
- #ifdef DEBUG
- fprintf(stderr, "Variable: <<<< %s >>>>\n", buffer);
- fprintf(stderr, " scope = %s\n", scope ? scope : "(null)");
- #endif /* DEBUG */
- variable = add_variable(MXML_NO_PARENT, "variable", type);
- type = NULL;
- sort_node(tree, variable);
- if (scope)
- mxmlElementSetAttr(variable, "scope", scope);
- }
- }
- else
- {
- #ifdef DEBUG
- fprintf(stderr, "Identifier: <<<< %s >>>>\n", buffer);
- #endif /* DEBUG */
- mxmlNewText(type, type->child != NULL &&
- type->last_child->value.text.string[0] != '(' &&
- type->last_child->value.text.string[0] != '*',
- buffer);
- }
- }
- else if (enumeration && !isdigit(buffer[0] & 255))
- {
- #ifdef DEBUG
- fprintf(stderr, "Constant: <<<< %s >>>\n", buffer);
- #endif /* DEBUG */
- constant = mxmlNewElement(MXML_NO_PARENT, "constant");
- mxmlElementSetAttr(constant, "name", buffer);
- sort_node(enumeration, constant);
- }
- else if (type)
- {
- mxmlDelete(type);
- type = NULL;
- }
- }
- break;
- }
- #if DEBUG > 1
- if (state != oldstate)
- {
- fprintf(stderr, " changed states from %s to %s on receipt of character '%c'...\n",
- states[oldstate], states[state], oldch);
- fprintf(stderr, " variable = %p\n", variable);
- if (type)
- {
- fputs(" type =", stderr);
- for (temp = type->child; temp; temp = temp->next)
- fprintf(stderr, " \"%s\"", temp->value.text.string);
- fputs("\n", stderr);
- }
- }
- #endif /* DEBUG > 1 */
- }
- mxmlDelete(comment);
- /*
- * All done, return with no errors...
- */
- return (0);
- }
- /*
- * 'sort_node()' - Insert a node sorted into a tree.
- */
- static void
- sort_node(mxml_node_t *tree, /* I - Tree to sort into */
- mxml_node_t *node) /* I - Node to add */
- {
- mxml_node_t *temp; /* Current node */
- const char *tempname, /* Name of current node */
- *nodename, /* Name of node */
- *scope; /* Scope */
- #if DEBUG > 1
- fprintf(stderr, " sort_node(tree=%p, node=%p)\n", tree, node);
- #endif /* DEBUG > 1 */
- /*
- * Range check input...
- */
- if (!tree || !node || node->parent == tree)
- return;
- /*
- * Get the node name...
- */
- if ((nodename = mxmlElementGetAttr(node, "name")) == NULL)
- return;
- if (nodename[0] == '_')
- return; /* Hide private names */
- #if DEBUG > 1
- fprintf(stderr, " nodename=%p (\"%s\")\n", nodename, nodename);
- #endif /* DEBUG > 1 */
- /*
- * Delete any existing definition at this level, if one exists...
- */
- if ((temp = mxmlFindElement(tree, tree, node->value.element.name,
- "name", nodename, MXML_DESCEND_FIRST)) != NULL)
- {
- /*
- * Copy the scope if needed...
- */
- if ((scope = mxmlElementGetAttr(temp, "scope")) != NULL &&
- mxmlElementGetAttr(node, "scope") == NULL)
- {
- #ifdef DEBUG
- fprintf(stderr, " copying scope %s for %s\n", scope, nodename);
- #endif /* DEBUG */
- mxmlElementSetAttr(node, "scope", scope);
- }
- mxmlDelete(temp);
- }
- /*
- * Add the node into the tree at the proper place...
- */
- for (temp = tree->child; temp; temp = temp->next)
- {
- #if DEBUG > 1
- fprintf(stderr, " temp=%p\n", temp);
- #endif /* DEBUG > 1 */
- if ((tempname = mxmlElementGetAttr(temp, "name")) == NULL)
- continue;
- #if DEBUG > 1
- fprintf(stderr, " tempname=%p (\"%s\")\n", tempname, tempname);
- #endif /* DEBUG > 1 */
- if (strcmp(nodename, tempname) < 0)
- break;
- }
- if (temp)
- mxmlAdd(tree, MXML_ADD_BEFORE, temp, node);
- else
- mxmlAdd(tree, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
- }
- /*
- * 'update_comment()' - Update a comment node.
- */
- static void
- update_comment(mxml_node_t *parent, /* I - Parent node */
- mxml_node_t *comment) /* I - Comment node */
- {
- char *ptr; /* Pointer into comment */
- #ifdef DEBUG
- fprintf(stderr, "update_comment(parent=%p, comment=%p)\n",
- parent, comment);
- #endif /* DEBUG */
- /*
- * Range check the input...
- */
- if (!parent || !comment)
- return;
- /*
- * Convert "\/" to "/"...
- */
- for (ptr = strstr(comment->value.text.string, "\\/");
- ptr;
- ptr = strstr(ptr, "\\/"))
- safe_strcpy(ptr, ptr + 1);
- /*
- * Update the comment...
- */
- ptr = comment->value.text.string;
- if (*ptr == '\'')
- {
- /*
- * Convert "'name()' - description" to "description".
- */
- for (ptr ++; *ptr && *ptr != '\''; ptr ++);
- if (*ptr == '\'')
- {
- ptr ++;
- while (isspace(*ptr & 255))
- ptr ++;
- if (*ptr == '-')
- ptr ++;
- while (isspace(*ptr & 255))
- ptr ++;
- safe_strcpy(comment->value.text.string, ptr);
- }
- }
- else if (!strncmp(ptr, "I ", 2) || !strncmp(ptr, "O ", 2) ||
- !strncmp(ptr, "IO ", 3))
- {
- /*
- * 'Convert "I - description", "IO - description", or "O - description"
- * to description + direction attribute.
- */
- ptr = strchr(ptr, ' ');
- *ptr++ = '\0';
- if (!strcmp(parent->value.element.name, "argument"))
- mxmlElementSetAttr(parent, "direction", comment->value.text.string);
- while (isspace(*ptr & 255))
- ptr ++;
- if (*ptr == '-')
- ptr ++;
- while (isspace(*ptr & 255))
- ptr ++;
- safe_strcpy(comment->value.text.string, ptr);
- }
- /*
- * Eliminate leading and trailing *'s...
- */
- for (ptr = comment->value.text.string; *ptr == '*'; ptr ++);
- for (; isspace(*ptr & 255); ptr ++);
- if (ptr > comment->value.text.string)
- safe_strcpy(comment->value.text.string, ptr);
- for (ptr = comment->value.text.string + strlen(comment->value.text.string) - 1;
- ptr > comment->value.text.string && *ptr == '*';
- ptr --)
- *ptr = '\0';
- for (; ptr > comment->value.text.string && isspace(*ptr & 255); ptr --)
- *ptr = '\0';
- #ifdef DEBUG
- fprintf(stderr, " updated comment = %s\n", comment->value.text.string);
- #endif /* DEBUG */
- }
- /*
- * 'usage()' - Show program usage...
- */
- static void
- usage(const char *option) /* I - Unknown option */
- {
- if (option)
- printf("mxmldoc: Bad option \"%s\"!\n\n", option);
- puts("Usage: mxmldoc [options] [filename.xml] [source files] >filename.html");
- puts("Options:");
- puts(" --css filename.css Set CSS stylesheet file");
- puts(" --docset bundleid.docset Generate documentation set");
- puts(" --docversion version Set documentation version");
- puts(" --feedname name Set documentation set feed name");
- puts(" --feedurl url Set documentation set feed URL");
- puts(" --footer footerfile Set footer file");
- puts(" --framed basename Generate framed HTML to basename*.html");
- puts(" --header headerfile Set header file");
- puts(" --intro introfile Set introduction file");
- puts(" --man name Generate man page");
- puts(" --no-output Do no generate documentation file");
- puts(" --section section Set section name");
- puts(" --title title Set documentation title");
- puts(" --tokens path Generate Xcode docset Tokens.xml file");
- puts(" --version Show mxmldoc/Mini-XML version");
- exit(1);
- }
- /*
- * 'write_description()' - Write the description text.
- */
- static void
- write_description(
- FILE *out, /* I - Output file */
- mxml_node_t *description, /* I - Description node */
- const char *element, /* I - HTML element, if any */
- int summary) /* I - Show summary */
- {
- char text[10240], /* Text for description */
- *start, /* Start of code/link */
- *ptr; /* Pointer into text */
- int col; /* Current column */
- if (!description)
- return;
- get_text(description, text, sizeof(text));
- ptr = strstr(text, "\n\n");
- if (summary)
- {
- if (ptr)
- *ptr = '\0';
- ptr = text;
- }
- else if (!ptr || !ptr[2])
- return;
- else
- ptr += 2;
- if (element && *element)
- fprintf(out, "<%s class=\"%s\">", element,
- summary ? "description" : "discussion");
- else if (!summary)
- fputs(".PP\n", out);
- for (col = 0; *ptr; ptr ++)
- {
- if (*ptr == '@' &&
- (!strncmp(ptr + 1, "deprecated@", 11) ||
- !strncmp(ptr + 1, "since ", 6)))
- {
- ptr ++;
- while (*ptr && *ptr != '@')
- ptr ++;
- if (!*ptr)
- return;
- }
- else if (!strncmp(ptr, "@code ", 6))
- {
- for (ptr += 6; isspace(*ptr & 255); ptr ++);
- for (start = ptr, ptr ++; *ptr && *ptr != '@'; ptr ++);
- if (*ptr)
- *ptr = '\0';
- else
- ptr --;
- if (element && *element)
- {
- fputs("<code>", out);
- for (; *start; start ++)
- {
- if (*start == '<')
- fputs("<", out);
- else if (*start == '>')
- fputs(">", out);
- else if (*start == '&')
- fputs("&", out);
- else
- putc(*start, out);
- }
- fputs("</code>", out);
- }
- else if (element)
- fputs(start, out);
- else
- fprintf(out, "\\fB%s\\fR", start);
- }
- else if (!strncmp(ptr, "@link ", 6))
- {
- for (ptr += 6; isspace(*ptr & 255); ptr ++);
- for (start = ptr, ptr ++; *ptr && *ptr != '@'; ptr ++);
- if (*ptr)
- *ptr = '\0';
- else
- ptr --;
- if (element && *element)
- fprintf(out, "<a href=\"#%s\"><code>%s</code></a>", start, start);
- else if (element)
- fputs(start, out);
- else
- fprintf(out, "\\fI%s\\fR", start);
- }
- else if (element)
- {
- if (*ptr == '&')
- fputs("&", out);
- else if (*ptr == '<')
- fputs("<", out);
- else if (*ptr == '>')
- fputs(">", out);
- else if (*ptr == '\"')
- fputs(""", out);
- else if (*ptr & 128)
- {
- /*
- * Convert UTF-8 to Unicode constant...
- */
- int ch; /* Unicode character */
- ch = *ptr & 255;
- if ((ch & 0xe0) == 0xc0)
- {
- ch = ((ch & 0x1f) << 6) | (ptr[1] & 0x3f);
- ptr ++;
- }
- else if ((ch & 0xf0) == 0xe0)
- {
- ch = ((((ch * 0x0f) << 6) | (ptr[1] & 0x3f)) << 6) | (ptr[2] & 0x3f);
- ptr += 2;
- }
- if (ch == 0xa0)
- {
- /*
- * Handle non-breaking space as-is...
- */
- fputs(" ", out);
- }
- else
- fprintf(out, "&#x%x;", ch);
- }
- else if (*ptr == '\n' && ptr[1] == '\n' && ptr[2] && ptr[2] != '@')
- {
- fputs("<br>\n<br>\n", out);
- ptr ++;
- }
- else
- putc(*ptr, out);
- }
- else if (*ptr == '\n' && ptr[1] == '\n' && ptr[2] && ptr[2] != '@')
- {
- fputs("\n.PP\n", out);
- ptr ++;
- }
- else
- {
- if (*ptr == '\\' || (*ptr == '.' && col == 0))
- putc('\\', out);
- putc(*ptr, out);
- if (*ptr == '\n')
- col = 0;
- else
- col ++;
- }
- }
- if (element && *element)
- fprintf(out, "</%s>\n", element);
- else if (!element)
- putc('\n', out);
- }
- /*
- * 'write_element()' - Write an element's text nodes.
- */
- static void
- write_element(FILE *out, /* I - Output file */
- mxml_node_t *doc, /* I - Document tree */
- mxml_node_t *element, /* I - Element to write */
- int mode) /* I - Output mode */
- {
- mxml_node_t *node; /* Current node */
- if (!element)
- return;
- for (node = element->child;
- node;
- node = mxmlWalkNext(node, element, MXML_NO_DESCEND))
- if (node->type == MXML_TEXT)
- {
- if (node->value.text.whitespace)
- putc(' ', out);
- if (mode == OUTPUT_HTML &&
- (mxmlFindElement(doc, doc, "class", "name", node->value.text.string,
- MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "enumeration", "name",
- node->value.text.string, MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "struct", "name", node->value.text.string,
- MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "typedef", "name", node->value.text.string,
- MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "union", "name", node->value.text.string,
- MXML_DESCEND)))
- {
- fputs("<a href=\"#", out);
- write_string(out, node->value.text.string, mode);
- fputs("\">", out);
- write_string(out, node->value.text.string, mode);
- fputs("</a>", out);
- }
- else
- write_string(out, node->value.text.string, mode);
- }
- if (!strcmp(element->value.element.name, "type") &&
- element->last_child->value.text.string[0] != '*')
- putc(' ', out);
- }
- /*
- * 'write_file()' - Copy a file to the output.
- */
- static void
- write_file(FILE *out, /* I - Output file */
- const char *file) /* I - File to copy */
- {
- FILE *fp; /* Copy file */
- char line[8192]; /* Line from file */
- if ((fp = fopen(file, "r")) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to open \"%s\": %s\n", file,
- strerror(errno));
- return;
- }
- while (fgets(line, sizeof(line), fp))
- fputs(line, out);
- fclose(fp);
- }
- /*
- * 'write_function()' - Write documentation for a function.
- */
- static void
- write_function(FILE *out, /* I - Output file */
- mxml_node_t *doc, /* I - Document */
- mxml_node_t *function, /* I - Function */
- int level) /* I - Base heading level */
- {
- mxml_node_t *arg, /* Current argument */
- *adesc, /* Description of argument */
- *description, /* Description of function */
- *type, /* Type for argument */
- *node; /* Node in description */
- const char *name, /* Name of function/type */
- *defval; /* Default value */
- char prefix; /* Prefix character */
- char *sep; /* Newline separator */
- name = mxmlElementGetAttr(function, "name");
- description = mxmlFindElement(function, function, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<h%d class=\"%s\">%s<a name=\"%s\">%s</a></h%d>\n",
- level, level == 3 ? "function" : "method",
- get_comment_info(description), name, name, level);
- if (description)
- write_description(out, description, "p", 1);
- fputs("<p class=\"code\">\n", out);
- arg = mxmlFindElement(function, function, "returnvalue", NULL,
- NULL, MXML_DESCEND_FIRST);
- if (arg)
- write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_HTML);
- else
- fputs("void ", out);
- fprintf(out, "%s ", name);
- for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
- MXML_DESCEND_FIRST), prefix = '(';
- arg;
- arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
- MXML_NO_DESCEND), prefix = ',')
- {
- type = mxmlFindElement(arg, arg, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- fprintf(out, "%c<br>\n ", prefix);
- if (type->child)
- write_element(out, doc, type, OUTPUT_HTML);
- fputs(mxmlElementGetAttr(arg, "name"), out);
- if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
- fprintf(out, " %s", defval);
- }
- if (prefix == '(')
- fputs("(void);</p>\n", out);
- else
- {
- fprintf(out,
- "<br>\n);</p>\n"
- "<h%d class=\"parameters\">Parameters</h%d>\n"
- "<dl>\n", level + 1, level + 1);
- for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
- MXML_DESCEND_FIRST);
- arg;
- arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
- MXML_NO_DESCEND))
- {
- fprintf(out, "<dt>%s</dt>\n", mxmlElementGetAttr(arg, "name"));
- adesc = mxmlFindElement(arg, arg, "description", NULL, NULL,
- MXML_DESCEND_FIRST);
- write_description(out, adesc, "dd", 1);
- write_description(out, adesc, "dd", 0);
- }
- fputs("</dl>\n", out);
- }
- arg = mxmlFindElement(function, function, "returnvalue", NULL,
- NULL, MXML_DESCEND_FIRST);
- if (arg)
- {
- fprintf(out, "<h%d class=\"returnvalue\">Return Value</h%d>\n", level + 1,
- level + 1);
- adesc = mxmlFindElement(arg, arg, "description", NULL, NULL,
- MXML_DESCEND_FIRST);
- write_description(out, adesc, "p", 1);
- write_description(out, adesc, "p", 0);
- }
- if (description)
- {
- for (node = description->child; node; node = node->next)
- if (node->value.text.string &&
- (sep = strstr(node->value.text.string, "\n\n")) != NULL)
- {
- sep += 2;
- if (*sep && strncmp(sep, "@since ", 7) &&
- strncmp(sep, "@deprecated@", 12))
- break;
- }
- if (node)
- {
- fprintf(out, "<h%d class=\"discussion\">Discussion</h%d>\n", level + 1,
- level + 1);
- write_description(out, description, "p", 0);
- }
- }
- }
- /*
- * 'write_html()' - Write HTML documentation.
- */
- static void
- write_html(const char *section, /* I - Section */
- const char *title, /* I - Title */
- const char *footerfile, /* I - Footer file */
- const char *headerfile, /* I - Header file */
- const char *introfile, /* I - Intro file */
- const char *cssfile, /* I - Stylesheet file */
- const char *framefile, /* I - Framed HTML basename */
- const char *docset, /* I - Documentation set directory */
- const char *docversion, /* I - Documentation set version */
- const char *feedname, /* I - Feed name for doc set */
- const char *feedurl, /* I - Feed URL for doc set */
- mxml_node_t *doc) /* I - XML documentation */
- {
- FILE *out; /* Output file */
- mxml_node_t *function, /* Current function */
- *scut, /* Struct/class/union/typedef */
- *arg, /* Current argument */
- *description, /* Description of function/var */
- *type; /* Type for argument */
- const char *name, /* Name of function/type */
- *defval, /* Default value */
- *basename; /* Base filename for framed output */
- char filename[1024]; /* Current output filename */
- if (framefile)
- {
- /*
- * Get the basename of the frame file...
- */
- if ((basename = strrchr(framefile, '/')) != NULL)
- basename ++;
- else
- basename = framefile;
- if (strstr(basename, ".html"))
- fputs("mxmldoc: Frame base name should not contain .html extension!\n",
- stderr);
- /*
- * Create the container HTML file for the frames...
- */
- snprintf(filename, sizeof(filename), "%s.html", framefile);
- if ((out = fopen(filename, "w")) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" "
- "\"http://www.w3.org/TR/html4/frameset.dtd\">\n"
- "<html>\n"
- "<head>\n"
- "\t<title>", out);
- write_string(out, title, OUTPUT_HTML);
- fputs("</title>\n", out);
- if (section)
- fprintf(out, "\t<meta name=\"keywords\" content=\"%s\">\n", section);
- fputs("\t<meta http-equiv=\"Content-Type\" "
- "content=\"text/html;charset=utf-8\">\n"
- "\t<meta name=\"creator\" content=\"" MXML_VERSION "\">\n"
- "</head>\n", out);
- fputs("<frameset cols=\"250,*\">\n", out);
- fprintf(out, "<frame src=\"%s-toc.html\">\n", basename);
- fprintf(out, "<frame name=\"body\" src=\"%s-body.html\">\n", basename);
- fputs("</frameset>\n"
- "<noframes>\n"
- "<h1>", out);
- write_string(out, title, OUTPUT_HTML);
- fprintf(out,
- "</h1>\n"
- "<ul>\n"
- "\t<li><a href=\"%s-toc.html\">Table of Contents</a></li>\n"
- "\t<li><a href=\"%s-body.html\">Body</a></li>\n"
- "</ul>\n", basename, basename);
- fputs("</noframes>\n"
- "</html>\n", out);
- fclose(out);
- /*
- * Write the table-of-contents file...
- */
- snprintf(filename, sizeof(filename), "%s-toc.html", framefile);
- if ((out = fopen(filename, "w")) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- write_html_head(out, section, title, cssfile);
- snprintf(filename, sizeof(filename), "%s-body.html", basename);
- fputs("<div class=\"contents\">\n", out);
- fprintf(out, "<h1 class=\"title\"><a href=\"%s\" target=\"body\">",
- filename);
- write_string(out, title, OUTPUT_HTML);
- fputs("</a></h1>\n", out);
- write_toc(out, doc, introfile, filename, 0);
- fputs("</div>\n"
- "</body>\n"
- "</html>\n", out);
- fclose(out);
- /*
- * Finally, open the body file...
- */
- snprintf(filename, sizeof(filename), "%s-body.html", framefile);
- if ((out = fopen(filename, "w")) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- }
- else if (docset)
- {
- /*
- * Create an Xcode documentation set - start by removing any existing
- * output directory...
- */
- #ifdef __APPLE__
- const char *id; /* Identifier */
- if (!access(docset, 0) && !remove_directory(docset))
- return;
- /*
- * Then make the Apple standard bundle directory structure...
- */
- if (mkdir(docset, 0755))
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", docset,
- strerror(errno));
- return;
- }
- snprintf(filename, sizeof(filename), "%s/Contents", docset);
- if (mkdir(filename, 0755))
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- snprintf(filename, sizeof(filename), "%s/Contents/Resources", docset);
- if (mkdir(filename, 0755))
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- snprintf(filename, sizeof(filename), "%s/Contents/Resources/Documentation",
- docset);
- if (mkdir(filename, 0755))
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- /*
- * The Info.plist file, which describes the documentation set...
- */
- if ((id = strrchr(docset, '/')) != NULL)
- id ++;
- else
- id = docset;
- snprintf(filename, sizeof(filename), "%s/Contents/Info.plist", docset);
- if ((out = fopen(filename, "w")) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
- "<plist version=\"1.0\">\n"
- "<dict>\n"
- "\t<key>CFBundleIdentifier</key>\n"
- "\t<string>", out);
- write_string(out, id, OUTPUT_HTML);
- fputs("</string>\n"
- "\t<key>CFBundleName</key>\n"
- "\t<string>", out);
- write_string(out, title, OUTPUT_HTML);
- fputs("</string>\n"
- "\t<key>CFBundleVersion</key>\n"
- "\t<string>", out);
- write_string(out, docversion ? docversion : "0.0", OUTPUT_HTML);
- fputs("</string>\n"
- "\t<key>CFBundleShortVersionString</key>\n"
- "\t<string>", out);
- write_string(out, docversion ? docversion : "0.0", OUTPUT_HTML);
- fputs("</string>\n", out);
- if (feedname)
- {
- fputs("\t<key>DocSetFeedName</key>\n"
- "\t<string>", out);
- write_string(out, feedname ? feedname : title, OUTPUT_HTML);
- fputs("</string>\n", out);
- }
- if (feedurl)
- {
- fputs("\t<key>DocSetFeedURL</key>\n"
- "\t<string>", out);
- write_string(out, feedurl, OUTPUT_HTML);
- fputs("</string>\n", out);
- }
- fputs("</dict>\n"
- "</plist>\n", out);
- fclose(out);
- /*
- * Next the Nodes.xml file...
- */
- snprintf(filename, sizeof(filename), "%s/Contents/Resources/Nodes.xml",
- docset);
- if ((out = fopen(filename, "w")) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<DocSetNodes version=\"1.0\">\n"
- "<TOC>\n"
- "<Node id=\"0\">\n"
- "<Name>", out);
- write_string(out, title, OUTPUT_HTML);
- fputs("</Name>\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Subnodes>\n", out);
- write_toc(out, doc, introfile, NULL, 1);
- fputs("</Subnodes>\n"
- "</Node>\n"
- "</TOC>\n"
- "</DocSetNodes>\n", out);
- fclose(out);
- /*
- * Then the Tokens.xml file...
- */
- snprintf(filename, sizeof(filename), "%s/Contents/Resources/Tokens.xml",
- docset);
- if ((out = fopen(filename, "w")) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<Tokens version=\"1.0\">\n", out);
- write_tokens(out, doc, "index.html");
- fputs("</Tokens>\n", out);
- fclose(out);
- /*
- * Finally the HTML file...
- */
- snprintf(filename, sizeof(filename),
- "%s/Contents/Resources/Documentation/index.html",
- docset);
- if ((out = fopen(filename, "w")) == NULL)
- {
- fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
- strerror(errno));
- return;
- }
- #else
- fputs("mxmldoc: Xcode documentation sets can only be created on "
- "Mac OS X.\n", stderr);
- return;
- #endif /* __APPLE__ */
- }
- else
- out = stdout;
- /*
- * Standard header...
- */
- write_html_head(out, section, title, cssfile);
- fputs("<div class='body'>\n", out);
- /*
- * Header...
- */
- if (headerfile)
- {
- /*
- * Use custom header...
- */
- write_file(out, headerfile);
- }
- else
- {
- /*
- * Use standard header...
- */
- fputs("<h1 class=\"title\">", out);
- write_string(out, title, OUTPUT_HTML);
- fputs("</h1>\n", out);
- }
- /*
- * Table of contents...
- */
- if (!framefile)
- write_toc(out, doc, introfile, NULL, 0);
- /*
- * Intro...
- */
- if (introfile)
- write_file(out, introfile);
- /*
- * List of classes...
- */
- if ((scut = find_public(doc, doc, "class")) != NULL)
- {
- fputs("<h2 class=\"title\"><a name=\"CLASSES\">Classes</a></h2>\n", out);
- while (scut)
- {
- write_scu(out, doc, scut);
- scut = find_public(scut, doc, "class");
- }
- }
- /*
- * List of functions...
- */
- if ((function = find_public(doc, doc, "function")) != NULL)
- {
- fputs("<h2 class=\"title\"><a name=\"FUNCTIONS\">Functions</a></h2>\n", out);
- while (function)
- {
- write_function(out, doc, function, 3);
- function = find_public(function, doc, "function");
- }
- }
- /*
- * List of types...
- */
- if ((scut = find_public(doc, doc, "typedef")) != NULL)
- {
- fputs("<h2 class=\"title\"><a name=\"TYPES\">Data Types</a></h2>\n", out);
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<h3 class=\"typedef\">%s<a name=\"%s\">%s</a></h3>\n",
- get_comment_info(description), name, name);
- if (description)
- write_description(out, description, "p", 1);
- fputs("<p class=\"code\">\n"
- "typedef ", out);
- type = mxmlFindElement(scut, scut, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- for (type = type->child; type; type = type->next)
- if (!strcmp(type->value.text.string, "("))
- break;
- else
- {
- if (type->value.text.whitespace)
- putc(' ', out);
- if (mxmlFindElement(doc, doc, "class", "name",
- type->value.text.string, MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "enumeration", "name",
- type->value.text.string, MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "struct", "name",
- type->value.text.string, MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "typedef", "name",
- type->value.text.string, MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "union", "name",
- type->value.text.string, MXML_DESCEND))
- {
- fputs("<a href=\"#", out);
- write_string(out, type->value.text.string, OUTPUT_HTML);
- fputs("\">", out);
- write_string(out, type->value.text.string, OUTPUT_HTML);
- fputs("</a>", out);
- }
- else
- write_string(out, type->value.text.string, OUTPUT_HTML);
- }
- if (type)
- {
- /*
- * Output function type...
- */
- if (type->prev && type->prev->value.text.string[0] != '*')
- putc(' ', out);
- fprintf(out, "(*%s", name);
- for (type = type->next->next; type; type = type->next)
- {
- if (type->value.text.whitespace)
- putc(' ', out);
- if (mxmlFindElement(doc, doc, "class", "name",
- type->value.text.string, MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "enumeration", "name",
- type->value.text.string, MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "struct", "name",
- type->value.text.string, MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "typedef", "name",
- type->value.text.string, MXML_DESCEND) ||
- mxmlFindElement(doc, doc, "union", "name",
- type->value.text.string, MXML_DESCEND))
- {
- fputs("<a href=\"#", out);
- write_string(out, type->value.text.string, OUTPUT_HTML);
- fputs("\">", out);
- write_string(out, type->value.text.string, OUTPUT_HTML);
- fputs("</a>", out);
- }
- else
- write_string(out, type->value.text.string, OUTPUT_HTML);
- }
- fputs(";\n", out);
- }
- else
- {
- type = mxmlFindElement(scut, scut, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- if (type->last_child->value.text.string[0] != '*')
- putc(' ', out);
- fprintf(out, "%s;\n", name);
- }
- fputs("</p>\n", out);
- scut = find_public(scut, doc, "typedef");
- }
- }
- /*
- * List of structures...
- */
- if ((scut = find_public(doc, doc, "struct")) != NULL)
- {
- fputs("<h2 class=\"title\"><a name=\"STRUCTURES\">Structures</a></h2>\n",
- out);
- while (scut)
- {
- write_scu(out, doc, scut);
- scut = find_public(scut, doc, "struct");
- }
- }
- /*
- * List of unions...
- */
- if ((scut = find_public(doc, doc, "union")) != NULL)
- {
- fputs("<h2 class=\"title\"><a name=\"UNIONS\">Unions</a></h2>\n", out);
- while (scut)
- {
- write_scu(out, doc, scut);
- scut = find_public(scut, doc, "union");
- }
- }
- /*
- * Variables...
- */
- if ((arg = find_public(doc, doc, "variable")) != NULL)
- {
- fputs("<h2 class=\"title\"><a name=\"VARIABLES\">Variables</a></h2>\n",
- out);
- while (arg)
- {
- name = mxmlElementGetAttr(arg, "name");
- description = mxmlFindElement(arg, arg, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<h3 class=\"variable\">%s<a name=\"%s\">%s</a></h3>\n",
- get_comment_info(description), name, name);
- if (description)
- write_description(out, description, "p", 1);
- fputs("<p class=\"code\">", out);
- write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_HTML);
- fputs(mxmlElementGetAttr(arg, "name"), out);
- if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
- fprintf(out, " %s", defval);
- fputs(";</p>\n", out);
- arg = find_public(arg, doc, "variable");
- }
- }
- /*
- * List of enumerations...
- */
- if ((scut = find_public(doc, doc, "enumeration")) != NULL)
- {
- fputs("<h2 class=\"title\"><a name=\"ENUMERATIONS\">Constants</a></h2>\n",
- out);
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<h3 class=\"enumeration\">%s<a name=\"%s\">%s</a></h3>\n",
- get_comment_info(description), name, name);
- if (description)
- write_description(out, description, "p", 1);
- fputs("<h4 class=\"constants\">Constants</h4>\n"
- "<dl>\n", out);
- for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
- MXML_DESCEND_FIRST);
- arg;
- arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
- MXML_NO_DESCEND))
- {
- description = mxmlFindElement(arg, arg, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<dt>%s %s</dt>\n",
- mxmlElementGetAttr(arg, "name"), get_comment_info(description));
- write_description(out, description, "dd", 1);
- write_description(out, description, "dd", 0);
- }
- fputs("</dl>\n", out);
- scut = find_public(scut, doc, "enumeration");
- }
- }
- /*
- * Footer...
- */
- if (footerfile)
- {
- /*
- * Use custom footer...
- */
- write_file(out, footerfile);
- }
- fputs("</div>\n"
- "</body>\n"
- "</html>\n", out);
- /*
- * Close output file as needed...
- */
- if (out != stdout)
- fclose(out);
- #ifdef __APPLE__
- /*
- * When generating document sets, run the docsetutil program to index it...
- */
- if (docset)
- {
- int argc = 0; /* Argument count */
- const char *args[5]; /* Argument array */
- pid_t pid; /* Process ID */
- int status; /* Exit status */
- args[argc++] = "/usr/bin/xcrun";
- args[argc++] = "docsetutil";
- args[argc++] = "index";
- args[argc++] = docset;
- args[argc ] = NULL;
- if (posix_spawn(&pid, args[0], NULL, NULL, (char **)args, environ))
- {
- fprintf(stderr, "mxmldoc: Unable to index documentation set \"%s\": %s\n",
- docset, strerror(errno));
- }
- else
- {
- while (wait(&status) != pid);
- if (status)
- {
- if (WIFEXITED(status))
- fprintf(stderr, "mxmldoc: docsetutil exited with status %d\n",
- WEXITSTATUS(status));
- else
- fprintf(stderr, "mxmldoc: docsetutil crashed with signal %d\n",
- WTERMSIG(status));
- }
- else
- {
- /*
- * Remove unneeded temporary XML files...
- */
- snprintf(filename, sizeof(filename), "%s/Contents/Resources/Nodes.xml",
- docset);
- unlink(filename);
- snprintf(filename, sizeof(filename), "%s/Contents/Resources/Tokens.xml",
- docset);
- unlink(filename);
- }
- }
- }
- #endif /* __APPLE__ */
- }
- /*
- * 'write_html_head()' - Write the standard HTML header.
- */
- static void
- write_html_head(FILE *out, /* I - Output file */
- const char *section, /* I - Section */
- const char *title, /* I - Title */
- const char *cssfile) /* I - Stylesheet */
- {
- fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
- "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
- "<html>\n", out);
- if (section)
- fprintf(out, "<!-- SECTION: %s -->\n", section);
- fputs("<head>\n"
- "\t<title>", out);
- write_string(out, title, OUTPUT_HTML);
- fputs("\t</title>\n", out);
- if (section)
- fprintf(out, "\t<meta name=\"keywords\" content=\"%s\">\n", section);
- fputs("\t<meta http-equiv=\"Content-Type\" "
- "content=\"text/html;charset=utf-8\">\n"
- "\t<meta name=\"creator\" content=\"" MXML_VERSION "\">\n"
- "<style type=\"text/css\"><!--\n", out);
- if (cssfile)
- {
- /*
- * Use custom stylesheet file...
- */
- write_file(out, cssfile);
- }
- else
- {
- /*
- * Use standard stylesheet...
- */
- fputs("body, p, h1, h2, h3, h4 {\n"
- " font-family: \"lucida grande\", geneva, helvetica, arial, "
- "sans-serif;\n"
- "}\n"
- "div.body h1 {\n"
- " font-size: 250%;\n"
- " font-weight: bold;\n"
- " margin: 0;\n"
- "}\n"
- "div.body h2 {\n"
- " font-size: 250%;\n"
- " margin-top: 1.5em;\n"
- "}\n"
- "div.body h3 {\n"
- " font-size: 150%;\n"
- " margin-bottom: 0.5em;\n"
- " margin-top: 1.5em;\n"
- "}\n"
- "div.body h4 {\n"
- " font-size: 110%;\n"
- " margin-bottom: 0.5em;\n"
- " margin-top: 1.5em;\n"
- "}\n"
- "div.body h5 {\n"
- " font-size: 100%;\n"
- " margin-bottom: 0.5em;\n"
- " margin-top: 1.5em;\n"
- "}\n"
- "div.contents {\n"
- " background: #e8e8e8;\n"
- " border: solid thin black;\n"
- " padding: 10px;\n"
- "}\n"
- "div.contents h1 {\n"
- " font-size: 110%;\n"
- "}\n"
- "div.contents h2 {\n"
- " font-size: 100%;\n"
- "}\n"
- "div.contents ul.contents {\n"
- " font-size: 80%;\n"
- "}\n"
- ".class {\n"
- " border-bottom: solid 2px gray;\n"
- "}\n"
- ".constants {\n"
- "}\n"
- ".description {\n"
- " margin-top: 0.5em;\n"
- "}\n"
- ".discussion {\n"
- "}\n"
- ".enumeration {\n"
- " border-bottom: solid 2px gray;\n"
- "}\n"
- ".function {\n"
- " border-bottom: solid 2px gray;\n"
- " margin-bottom: 0;\n"
- "}\n"
- ".members {\n"
- "}\n"
- ".method {\n"
- "}\n"
- ".parameters {\n"
- "}\n"
- ".returnvalue {\n"
- "}\n"
- ".struct {\n"
- " border-bottom: solid 2px gray;\n"
- "}\n"
- ".typedef {\n"
- " border-bottom: solid 2px gray;\n"
- "}\n"
- ".union {\n"
- " border-bottom: solid 2px gray;\n"
- "}\n"
- ".variable {\n"
- "}\n"
- "code, p.code, pre, ul.code li {\n"
- " font-family: monaco, courier, monospace;\n"
- " font-size: 90%;\n"
- "}\n"
- "a:link, a:visited {\n"
- " text-decoration: none;\n"
- "}\n"
- "span.info {\n"
- " background: black;\n"
- " border: solid thin black;\n"
- " color: white;\n"
- " font-size: 80%;\n"
- " font-style: italic;\n"
- " font-weight: bold;\n"
- " white-space: nowrap;\n"
- "}\n"
- "h3 span.info, h4 span.info {\n"
- " float: right;\n"
- " font-size: 100%;\n"
- "}\n"
- "ul.code, ul.contents, ul.subcontents {\n"
- " list-style-type: none;\n"
- " margin: 0;\n"
- " padding-left: 0;\n"
- "}\n"
- "ul.code li {\n"
- " margin: 0;\n"
- "}\n"
- "ul.contents > li {\n"
- " margin-top: 1em;\n"
- "}\n"
- "ul.contents li ul.code, ul.contents li ul.subcontents {\n"
- " padding-left: 2em;\n"
- "}\n"
- "div.body dl {\n"
- " margin-top: 0;\n"
- "}\n"
- "div.body dt {\n"
- " font-style: italic;\n"
- " margin-top: 0;\n"
- "}\n"
- "div.body dd {\n"
- " margin-bottom: 0.5em;\n"
- "}\n"
- "h1.title {\n"
- "}\n"
- "h2.title {\n"
- " border-bottom: solid 2px black;\n"
- "}\n"
- "h3.title {\n"
- " border-bottom: solid 2px black;\n"
- "}\n", out);
- }
- fputs("--></style>\n"
- "</head>\n"
- "<body>\n", out);
- }
- /*
- * 'write_man()' - Write manpage documentation.
- */
- static void
- write_man(const char *man_name, /* I - Name of manpage */
- const char *section, /* I - Section */
- const char *title, /* I - Title */
- const char *footerfile, /* I - Footer file */
- const char *headerfile, /* I - Header file */
- const char *introfile, /* I - Intro file */
- mxml_node_t *doc) /* I - XML documentation */
- {
- int i; /* Looping var */
- mxml_node_t *function, /* Current function */
- *scut, /* Struct/class/union/typedef */
- *arg, /* Current argument */
- *description, /* Description of function/var */
- *type; /* Type for argument */
- const char *name, /* Name of function/type */
- *cname, /* Class name */
- *defval, /* Default value */
- *parent; /* Parent class */
- int inscope; /* Variable/method scope */
- char prefix; /* Prefix character */
- time_t curtime; /* Current time */
- struct tm *curdate; /* Current date */
- char buffer[1024]; /* String buffer */
- static const char * const scopes[] = /* Scope strings */
- {
- "private",
- "protected",
- "public"
- };
- /*
- * Standard man page...
- */
- curtime = time(NULL);
- curdate = localtime(&curtime);
- strftime(buffer, sizeof(buffer), "%x", curdate);
- printf(".TH %s %s \"%s\" \"%s\" \"%s\"\n", man_name, section ? section : "3",
- title ? title : "", buffer, title ? title : "");
- /*
- * Header...
- */
- if (headerfile)
- {
- /*
- * Use custom header...
- */
- write_file(stdout, headerfile);
- }
- else
- {
- /*
- * Use standard header...
- */
- puts(".SH NAME");
- printf("%s \\- %s\n", man_name, title ? title : man_name);
- }
- /*
- * Intro...
- */
- if (introfile)
- write_file(stdout, introfile);
- /*
- * List of classes...
- */
- if (find_public(doc, doc, "class"))
- {
- puts(".SH CLASSES");
- for (scut = find_public(doc, doc, "class");
- scut;
- scut = find_public(scut, doc, "class"))
- {
- cname = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- printf(".SS %s\n", cname);
- write_description(stdout, description, NULL, 1);
- printf(".PP\n"
- ".nf\n"
- "class %s", cname);
- if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL)
- printf(" %s", parent);
- puts("\n{");
- for (i = 0; i < 3; i ++)
- {
- inscope = 0;
- for (arg = mxmlFindElement(scut, scut, "variable", "scope", scopes[i],
- MXML_DESCEND_FIRST);
- arg;
- arg = mxmlFindElement(arg, scut, "variable", "scope", scopes[i],
- MXML_NO_DESCEND))
- {
- if (!inscope)
- {
- inscope = 1;
- printf(" %s:\n", scopes[i]);
- }
- printf(" ");
- write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_MAN);
- printf("%s;\n", mxmlElementGetAttr(arg, "name"));
- }
- for (function = mxmlFindElement(scut, scut, "function", "scope",
- scopes[i], MXML_DESCEND_FIRST);
- function;
- function = mxmlFindElement(function, scut, "function", "scope",
- scopes[i], MXML_NO_DESCEND))
- {
- if (!inscope)
- {
- inscope = 1;
- printf(" %s:\n", scopes[i]);
- }
- name = mxmlElementGetAttr(function, "name");
- printf(" ");
- arg = mxmlFindElement(function, function, "returnvalue", NULL,
- NULL, MXML_DESCEND_FIRST);
- if (arg)
- write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_MAN);
- else if (strcmp(cname, name) && strcmp(cname, name + 1))
- fputs("void ", stdout);
- printf("%s", name);
- for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
- MXML_DESCEND_FIRST), prefix = '(';
- arg;
- arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
- MXML_NO_DESCEND), prefix = ',')
- {
- type = mxmlFindElement(arg, arg, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- putchar(prefix);
- if (prefix == ',')
- putchar(' ');
- if (type->child)
- write_element(stdout, doc, type, OUTPUT_MAN);
- fputs(mxmlElementGetAttr(arg, "name"), stdout);
- if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
- printf(" %s", defval);
- }
- if (prefix == '(')
- puts("(void);");
- else
- puts(");");
- }
- }
- puts("};\n"
- ".fi");
- write_description(stdout, description, NULL, 0);
- }
- }
- /*
- * List of enumerations...
- */
- if (find_public(doc, doc, "enumeration"))
- {
- puts(".SH ENUMERATIONS");
- for (scut = find_public(doc, doc, "enumeration");
- scut;
- scut = find_public(scut, doc, "enumeration"))
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- printf(".SS %s\n", name);
- write_description(stdout, description, NULL, 1);
- write_description(stdout, description, NULL, 0);
- for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
- MXML_DESCEND_FIRST);
- arg;
- arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
- MXML_NO_DESCEND))
- {
- description = mxmlFindElement(arg, arg, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- printf(".TP 5\n%s\n.br\n", mxmlElementGetAttr(arg, "name"));
- write_description(stdout, description, NULL, 1);
- }
- }
- }
- /*
- * List of functions...
- */
- if (find_public(doc, doc, "function"))
- {
- puts(".SH FUNCTIONS");
- for (function = find_public(doc, doc, "function");
- function;
- function = find_public(function, doc, "function"))
- {
- name = mxmlElementGetAttr(function, "name");
- description = mxmlFindElement(function, function, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- printf(".SS %s\n", name);
- write_description(stdout, description, NULL, 1);
- puts(".PP\n"
- ".nf");
- arg = mxmlFindElement(function, function, "returnvalue", NULL,
- NULL, MXML_DESCEND_FIRST);
- if (arg)
- write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_MAN);
- else
- fputs("void", stdout);
- printf(" %s ", name);
- for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
- MXML_DESCEND_FIRST), prefix = '(';
- arg;
- arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
- MXML_NO_DESCEND), prefix = ',')
- {
- type = mxmlFindElement(arg, arg, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- printf("%c\n ", prefix);
- if (type->child)
- write_element(stdout, doc, type, OUTPUT_MAN);
- fputs(mxmlElementGetAttr(arg, "name"), stdout);
- if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
- printf(" %s", defval);
- }
- if (prefix == '(')
- puts("(void);");
- else
- puts("\n);");
- puts(".fi");
- write_description(stdout, description, NULL, 0);
- }
- }
- /*
- * List of structures...
- */
- if (find_public(doc, doc, "struct"))
- {
- puts(".SH STRUCTURES");
- for (scut = find_public(doc, doc, "struct");
- scut;
- scut = find_public(scut, doc, "struct"))
- {
- cname = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- printf(".SS %s\n", cname);
- write_description(stdout, description, NULL, 1);
- printf(".PP\n"
- ".nf\n"
- "struct %s\n{\n", cname);
- for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
- MXML_DESCEND_FIRST);
- arg;
- arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
- MXML_NO_DESCEND))
- {
- printf(" ");
- write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_MAN);
- printf("%s;\n", mxmlElementGetAttr(arg, "name"));
- }
- for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
- MXML_DESCEND_FIRST);
- function;
- function = mxmlFindElement(function, scut, "function", NULL, NULL,
- MXML_NO_DESCEND))
- {
- name = mxmlElementGetAttr(function, "name");
- printf(" ");
- arg = mxmlFindElement(function, function, "returnvalue", NULL,
- NULL, MXML_DESCEND_FIRST);
- if (arg)
- write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_MAN);
- else if (strcmp(cname, name) && strcmp(cname, name + 1))
- fputs("void ", stdout);
- fputs(name, stdout);
- for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
- MXML_DESCEND_FIRST), prefix = '(';
- arg;
- arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
- MXML_NO_DESCEND), prefix = ',')
- {
- type = mxmlFindElement(arg, arg, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- putchar(prefix);
- if (prefix == ',')
- putchar(' ');
- if (type->child)
- write_element(stdout, doc, type, OUTPUT_MAN);
- fputs(mxmlElementGetAttr(arg, "name"), stdout);
- if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
- printf(" %s", defval);
- }
- if (prefix == '(')
- puts("(void);");
- else
- puts(");");
- }
- puts("};\n"
- ".fi");
- write_description(stdout, description, NULL, 0);
- }
- }
- /*
- * List of types...
- */
- if (find_public(doc, doc, "typedef"))
- {
- puts(".SH TYPES");
- for (scut = find_public(doc, doc, "typedef");
- scut;
- scut = find_public(scut, doc, "typedef"))
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- printf(".SS %s\n", name);
- write_description(stdout, description, NULL, 1);
- fputs(".PP\n"
- ".nf\n"
- "typedef ", stdout);
- type = mxmlFindElement(scut, scut, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- for (type = type->child; type; type = type->next)
- if (!strcmp(type->value.text.string, "("))
- break;
- else
- {
- if (type->value.text.whitespace)
- putchar(' ');
- write_string(stdout, type->value.text.string, OUTPUT_MAN);
- }
- if (type)
- {
- /*
- * Output function type...
- */
- printf(" (*%s", name);
- for (type = type->next->next; type; type = type->next)
- {
- if (type->value.text.whitespace)
- putchar(' ');
- write_string(stdout, type->value.text.string, OUTPUT_MAN);
- }
- puts(";");
- }
- else
- printf(" %s;\n", name);
- puts(".fi");
- write_description(stdout, description, NULL, 0);
- }
- }
- /*
- * List of unions...
- */
- if (find_public(doc, doc, "union"))
- {
- puts(".SH UNIONS");
- for (scut = find_public(doc, doc, "union");
- scut;
- scut = find_public(scut, doc, "union"))
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- printf(".SS %s\n", name);
- write_description(stdout, description, NULL, 1);
- printf(".PP\n"
- ".nf\n"
- "union %s\n{\n", name);
- for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
- MXML_DESCEND_FIRST);
- arg;
- arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
- MXML_NO_DESCEND))
- {
- printf(" ");
- write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_MAN);
- printf("%s;\n", mxmlElementGetAttr(arg, "name"));
- }
- puts("};\n"
- ".fi");
- write_description(stdout, description, NULL, 0);
- }
- }
- /*
- * Variables...
- */
- if (find_public(doc, doc, "variable"))
- {
- puts(".SH VARIABLES");
- for (arg = find_public(doc, doc, "variable");
- arg;
- arg = find_public(arg, doc, "variable"))
- {
- name = mxmlElementGetAttr(arg, "name");
- description = mxmlFindElement(arg, arg, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- printf(".SS %s\n", name);
- write_description(stdout, description, NULL, 1);
- puts(".PP\n"
- ".nf");
- write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_MAN);
- fputs(mxmlElementGetAttr(arg, "name"), stdout);
- if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
- printf(" %s", defval);
- puts(";\n"
- ".fi");
- write_description(stdout, description, NULL, 0);
- }
- }
- if (footerfile)
- {
- /*
- * Use custom footer...
- */
- write_file(stdout, footerfile);
- }
- }
- /*
- * 'write_scu()' - Write a structure, class, or union.
- */
- static void
- write_scu(FILE *out, /* I - Output file */
- mxml_node_t *doc, /* I - Document */
- mxml_node_t *scut) /* I - Structure, class, or union */
- {
- int i; /* Looping var */
- mxml_node_t *function, /* Current function */
- *arg, /* Current argument */
- *description, /* Description of function/var */
- *type; /* Type for argument */
- const char *name, /* Name of function/type */
- *cname, /* Class name */
- *defval, /* Default value */
- *parent, /* Parent class */
- *scope; /* Scope for variable/function */
- int inscope, /* Variable/method scope */
- maxscope; /* Maximum scope */
- char prefix; /* Prefix character */
- static const char * const scopes[] = /* Scope strings */
- {
- "private",
- "protected",
- "public"
- };
- cname = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<h3 class=\"%s\">%s<a name=\"%s\">%s</a></h3>\n",
- scut->value.element.name, get_comment_info(description), cname,
- cname);
- if (description)
- write_description(out, description, "p", 1);
- fprintf(out, "<p class=\"code\">%s %s", scut->value.element.name, cname);
- if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL)
- fprintf(out, " %s", parent);
- fputs(" {<br>\n", out);
- maxscope = !strcmp(scut->value.element.name, "class") ? 3 : 1;
- for (i = 0; i < maxscope; i ++)
- {
- inscope = maxscope == 1;
- for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
- MXML_DESCEND_FIRST);
- arg;
- arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
- MXML_NO_DESCEND))
- {
- if (maxscope > 1 &&
- ((scope = mxmlElementGetAttr(arg, "scope")) == NULL ||
- strcmp(scope, scopes[i])))
- continue;
- if (!inscope)
- {
- inscope = 1;
- fprintf(out, " %s:<br>\n", scopes[i]);
- }
- fputs(" ", out);
- write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_HTML);
- fprintf(out, "%s;<br>\n", mxmlElementGetAttr(arg, "name"));
- }
- for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
- MXML_DESCEND_FIRST);
- function;
- function = mxmlFindElement(function, scut, "function", NULL, NULL,
- MXML_NO_DESCEND))
- {
- if (maxscope > 1 &&
- ((scope = mxmlElementGetAttr(arg, "scope")) == NULL ||
- strcmp(scope, scopes[i])))
- continue;
- if (!inscope)
- {
- inscope = 1;
- fprintf(out, " %s:<br>\n", scopes[i]);
- }
- name = mxmlElementGetAttr(function, "name");
- fputs(" ", out);
- arg = mxmlFindElement(function, function, "returnvalue", NULL,
- NULL, MXML_DESCEND_FIRST);
- if (arg)
- write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_HTML);
- else if (strcmp(cname, name) && strcmp(cname, name + 1))
- fputs("void ", out);
- fprintf(out, "<a href=\"#%s.%s\">%s</a>", cname, name, name);
- for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
- MXML_DESCEND_FIRST), prefix = '(';
- arg;
- arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
- MXML_NO_DESCEND), prefix = ',')
- {
- type = mxmlFindElement(arg, arg, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- putc(prefix, out);
- if (prefix == ',')
- putc(' ', out);
- if (type->child)
- write_element(out, doc, type, OUTPUT_HTML);
- fputs(mxmlElementGetAttr(arg, "name"), out);
- if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
- fprintf(out, " %s", defval);
- }
- if (prefix == '(')
- fputs("(void);<br>\n", out);
- else
- fputs(");<br>\n", out);
- }
- }
- fputs("};</p>\n"
- "<h4 class=\"members\">Members</h4>\n"
- "<dl>\n", out);
- for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
- MXML_DESCEND_FIRST);
- arg;
- arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
- MXML_NO_DESCEND))
- {
- description = mxmlFindElement(arg, arg, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<dt>%s %s</dt>\n",
- mxmlElementGetAttr(arg, "name"), get_comment_info(description));
- write_description(out, description, "dd", 1);
- write_description(out, description, "dd", 0);
- }
- fputs("</dl>\n", out);
- for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
- MXML_DESCEND_FIRST);
- function;
- function = mxmlFindElement(function, scut, "function", NULL, NULL,
- MXML_NO_DESCEND))
- {
- write_function(out, doc, function, 4);
- }
- }
- /*
- * 'write_string()' - Write a string, quoting HTML special chars as needed.
- */
- static void
- write_string(FILE *out, /* I - Output file */
- const char *s, /* I - String to write */
- int mode) /* I - Output mode */
- {
- switch (mode)
- {
- case OUTPUT_HTML :
- case OUTPUT_XML :
- while (*s)
- {
- if (*s == '&')
- fputs("&", out);
- else if (*s == '<')
- fputs("<", out);
- else if (*s == '>')
- fputs(">", out);
- else if (*s == '\"')
- fputs(""", out);
- else if (*s & 128)
- {
- /*
- * Convert UTF-8 to Unicode constant...
- */
- int ch; /* Unicode character */
- ch = *s & 255;
- if ((ch & 0xe0) == 0xc0)
- {
- ch = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
- s ++;
- }
- else if ((ch & 0xf0) == 0xe0)
- {
- ch = ((((ch * 0x0f) << 6) | (s[1] & 0x3f)) << 6) | (s[2] & 0x3f);
- s += 2;
- }
- if (ch == 0xa0)
- {
- /*
- * Handle non-breaking space as-is...
- */
- fputs(" ", out);
- }
- else
- fprintf(out, "&#x%x;", ch);
- }
- else
- putc(*s, out);
- s ++;
- }
- break;
- case OUTPUT_MAN :
- while (*s)
- {
- if (*s == '\\' || *s == '-')
- putc('\\', out);
- putc(*s++, out);
- }
- break;
- }
- }
- /*
- * 'write_toc()' - Write a table-of-contents.
- */
- static void
- write_toc(FILE *out, /* I - Output file */
- mxml_node_t *doc, /* I - Document */
- const char *introfile, /* I - Introduction file */
- const char *target, /* I - Target name */
- int xml) /* I - Write XML nodes? */
- {
- FILE *fp; /* Intro file */
- mxml_node_t *function, /* Current function */
- *scut, /* Struct/class/union/typedef */
- *arg, /* Current argument */
- *description; /* Description of function/var */
- const char *name, /* Name of function/type */
- *targetattr; /* Target attribute, if any */
- int xmlid = 1; /* Current XML node ID */
- /*
- * If target is set, it is the frame file that contains the body.
- * Otherwise, we are creating a single-file...
- */
- if (target)
- targetattr = " target=\"body\"";
- else
- targetattr = "";
- /*
- * The table-of-contents is a nested unordered list. Start by
- * reading any intro file to see if there are any headings there.
- */
- if (!xml)
- fputs("<h2 class=\"title\">Contents</h2>\n"
- "<ul class=\"contents\">\n", out);
- if (introfile && (fp = fopen(introfile, "r")) != NULL)
- {
- char line[8192], /* Line from file */
- *ptr, /* Pointer in line */
- *end, /* End of line */
- *anchor, /* Anchor name */
- quote, /* Quote character for value */
- level = '2', /* Current heading level */
- newlevel; /* New heading level */
- int inelement; /* In an element? */
- while (fgets(line, sizeof(line), fp))
- {
- /*
- * See if this line has a heading...
- */
- if ((ptr = strstr(line, "<h")) == NULL &&
- (ptr = strstr(line, "<H")) == NULL)
- continue;
- if (ptr[2] != '2' && ptr[2] != '3')
- continue;
- newlevel = ptr[2];
- /*
- * Make sure we have the whole heading...
- */
- while (!strstr(line, "</h") && !strstr(line, "</H"))
- {
- end = line + strlen(line);
- if (end == (line + sizeof(line) - 1) ||
- !fgets(end, (int)(sizeof(line) - (end - line)), fp))
- break;
- }
- /*
- * Convert newlines and tabs to spaces...
- */
- for (ptr = line; *ptr; ptr ++)
- if (isspace(*ptr & 255))
- *ptr = ' ';
- /*
- * Find the anchor and text...
- */
- for (ptr = strchr(line, '<'); ptr; ptr = strchr(ptr + 1, '<'))
- if (!strncmp(ptr, "<A NAME=", 8) || !strncmp(ptr, "<a name=", 8))
- break;
- if (!ptr)
- continue;
- ptr += 8;
- inelement = 1;
- if (*ptr == '\'' || *ptr == '\"')
- {
- /*
- * Quoted anchor...
- */
- quote = *ptr++;
- anchor = ptr;
- while (*ptr && *ptr != quote)
- ptr ++;
- if (!*ptr)
- continue;
- *ptr++ = '\0';
- }
- else
- {
- /*
- * Non-quoted anchor...
- */
- anchor = ptr;
- while (*ptr && *ptr != '>' && !isspace(*ptr & 255))
- ptr ++;
- if (!*ptr)
- continue;
- if (*ptr == '>')
- inelement = 0;
- *ptr++ = '\0';
- }
- /*
- * Write text until we see "</A>"...
- */
- if (xml)
- {
- if (newlevel < level)
- fputs("</Node>\n"
- "</Subnodes></Node>\n", out);
- else if (newlevel > level && newlevel == '3')
- fputs("<Subnodes>\n", out);
- else if (xmlid > 1)
- fputs("</Node>\n", out);
- level = newlevel;
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<Name>", xmlid ++, anchor);
- quote = 0;
- while (*ptr)
- {
- if (inelement)
- {
- if (*ptr == quote)
- quote = 0;
- else if (*ptr == '>')
- inelement = 0;
- else if (*ptr == '\'' || *ptr == '\"')
- quote = *ptr;
- }
- else if (*ptr == '<')
- {
- if (!strncmp(ptr, "</A>", 4) || !strncmp(ptr, "</a>", 4))
- break;
- inelement = 1;
- }
- else
- putc(*ptr, out);
- ptr ++;
- }
- fputs("</Name>\n", out);
- }
- else
- {
- if (newlevel < level)
- fputs("</li>\n"
- "</ul></li>\n", out);
- else if (newlevel > level)
- fputs("<ul class=\"subcontents\">\n", out);
- else if (xmlid > 1)
- fputs("</li>\n", out);
- level = newlevel;
- xmlid ++;
- fprintf(out, "%s<li><a href=\"%s#%s\"%s>", level > '2' ? "\t" : "",
- target ? target : "", anchor, targetattr);
- quote = 0;
- while (*ptr)
- {
- if (inelement)
- {
- if (*ptr == quote)
- quote = 0;
- else if (*ptr == '>')
- inelement = 0;
- else if (*ptr == '\'' || *ptr == '\"')
- quote = *ptr;
- }
- else if (*ptr == '<')
- {
- if (!strncmp(ptr, "</A>", 4) || !strncmp(ptr, "</a>", 4))
- break;
- inelement = 1;
- }
- else
- putc(*ptr, out);
- ptr ++;
- }
- fputs("</a>", out);
- }
- }
- if (level > '1')
- {
- if (xml)
- {
- fputs("</Node>\n", out);
- if (level == '3')
- fputs("</Subnodes></Node>\n", out);
- }
- else
- {
- fputs("</li>\n", out);
- if (level == '3')
- fputs("</ul></li>\n", out);
- }
- }
- fclose(fp);
- }
- /*
- * Next the classes...
- */
- if ((scut = find_public(doc, doc, "class")) != NULL)
- {
- if (xml)
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>CLASSES</Anchor>\n"
- "<Name>Classes</Name>\n"
- "<Subnodes>\n", xmlid ++);
- else
- fprintf(out, "<li><a href=\"%s#CLASSES\"%s>Classes</a>"
- "<ul class=\"code\">\n",
- target ? target : "", targetattr);
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- if (xml)
- {
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<Name>%s</Name>\n"
- "</Node>\n", xmlid ++, name, name);
- }
- else
- {
- fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
- target ? target : "", name, targetattr);
- write_description(out, description, "", 1);
- fprintf(out, "\">%s</a></li>\n", name);
- }
- scut = find_public(scut, doc, "class");
- }
- if (xml)
- fputs("</Subnodes></Node>\n", out);
- else
- fputs("</ul></li>\n", out);
- }
- /*
- * Functions...
- */
- if ((function = find_public(doc, doc, "function")) != NULL)
- {
- if (xml)
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>FUNCTIONS</Anchor>\n"
- "<Name>Functions</Name>\n"
- "<Subnodes>\n", xmlid ++);
- else
- fprintf(out, "<li><a href=\"%s#FUNCTIONS\"%s>Functions</a>"
- "<ul class=\"code\">\n", target ? target : "", targetattr);
- while (function)
- {
- name = mxmlElementGetAttr(function, "name");
- description = mxmlFindElement(function, function, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- if (xml)
- {
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<Name>%s</Name>\n"
- "</Node>\n", xmlid ++, name, name);
- }
- else
- {
- fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
- target ? target : "", name, targetattr);
- write_description(out, description, "", 1);
- fprintf(out, "\">%s</a></li>\n", name);
- }
- function = find_public(function, doc, "function");
- }
- if (xml)
- fputs("</Subnodes></Node>\n", out);
- else
- fputs("</ul></li>\n", out);
- }
- /*
- * Data types...
- */
- if ((scut = find_public(doc, doc, "typedef")) != NULL)
- {
- if (xml)
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>TYPES</Anchor>\n"
- "<Name>Data Types</Name>\n"
- "<Subnodes>\n", xmlid ++);
- else
- fprintf(out, "<li><a href=\"%s#TYPES\"%s>Data Types</a>"
- "<ul class=\"code\">\n", target ? target : "", targetattr);
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- if (xml)
- {
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<Name>%s</Name>\n"
- "</Node>\n", xmlid ++, name, name);
- }
- else
- {
- fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
- target ? target : "", name, targetattr);
- write_description(out, description, "", 1);
- fprintf(out, "\">%s</a></li>\n", name);
- }
- scut = find_public(scut, doc, "typedef");
- }
- if (xml)
- fputs("</Subnodes></Node>\n", out);
- else
- fputs("</ul></li>\n", out);
- }
- /*
- * Structures...
- */
- if ((scut = find_public(doc, doc, "struct")) != NULL)
- {
- if (xml)
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>STRUCTURES</Anchor>\n"
- "<Name>Structures</Name>\n"
- "<Subnodes>\n", xmlid ++);
- else
- fprintf(out, "<li><a href=\"%s#STRUCTURES\"%s>Structures</a>"
- "<ul class=\"code\">\n", target ? target : "", targetattr);
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- if (xml)
- {
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<Name>%s</Name>\n"
- "</Node>\n", xmlid ++, name, name);
- }
- else
- {
- fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
- target ? target : "", name, targetattr);
- write_description(out, description, "", 1);
- fprintf(out, "\">%s</a></li>\n", name);
- }
- scut = find_public(scut, doc, "struct");
- }
- if (xml)
- fputs("</Subnodes></Node>\n", out);
- else
- fputs("</ul></li>\n", out);
- }
- /*
- * Unions...
- */
- if ((scut = find_public(doc, doc, "union")) != NULL)
- {
- if (xml)
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>UNIONS</Anchor>\n"
- "<Name>Unions</Name>\n"
- "<Subnodes>\n", xmlid ++);
- else
- fprintf(out,
- "<li><a href=\"%s#UNIONS\"%s>Unions</a><ul class=\"code\">\n",
- target ? target : "", targetattr);
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- if (xml)
- {
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<Name>%s</Name>\n"
- "</Node>\n", xmlid ++, name, name);
- }
- else
- {
- fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
- target ? target : "", name, targetattr);
- write_description(out, description, "", 1);
- fprintf(out, "\">%s</a></li>\n", name);
- }
- scut = find_public(scut, doc, "union");
- }
- if (xml)
- fputs("</Subnodes></Node>\n", out);
- else
- fputs("</ul></li>\n", out);
- }
- /*
- * Globals variables...
- */
- if ((arg = find_public(doc, doc, "variable")) != NULL)
- {
- if (xml)
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>VARIABLES</Anchor>\n"
- "<Name>Variables</Name>\n"
- "<Subnodes>\n", xmlid ++);
- else
- fprintf(out, "<li><a href=\"%s#VARIABLES\"%s>Variables</a>"
- "<ul class=\"code\">\n", target ? target : "", targetattr);
- while (arg)
- {
- name = mxmlElementGetAttr(arg, "name");
- description = mxmlFindElement(arg, arg, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- if (xml)
- {
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<Name>%s</Name>\n"
- "</Node>\n", xmlid ++, name, name);
- }
- else
- {
- fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
- target ? target : "", name, targetattr);
- write_description(out, description, "", 1);
- fprintf(out, "\">%s</a></li>\n", name);
- }
- arg = find_public(arg, doc, "variable");
- }
- if (xml)
- fputs("</Subnodes></Node>\n", out);
- else
- fputs("</ul></li>\n", out);
- }
- /*
- * Enumerations/constants...
- */
- if ((scut = find_public(doc, doc, "enumeration")) != NULL)
- {
- if (xml)
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>ENUMERATIONS</Anchor>\n"
- "<Name>Constants</Name>\n"
- "<Subnodes>\n", xmlid ++);
- else
- fprintf(out, "<li><a href=\"%s#ENUMERATIONS\"%s>Constants</a>"
- "<ul class=\"code\">\n", target ? target : "", targetattr);
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- if (xml)
- {
- fprintf(out, "<Node id=\"%d\">\n"
- "<Path>Documentation/index.html</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<Name>%s</Name>\n"
- "</Node>\n", xmlid ++, name, name);
- }
- else
- {
- fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
- target ? target : "", name, targetattr);
- write_description(out, description, "", 1);
- fprintf(out, "\">%s</a></li>\n", name);
- }
- scut = find_public(scut, doc, "enumeration");
- }
- if (xml)
- fputs("</Subnodes></Node>\n", out);
- else
- fputs("</ul></li>\n", out);
- }
- /*
- * Close out the HTML table-of-contents list as needed...
- */
- if (!xml)
- fputs("</ul>\n", out);
- }
- /*
- * 'write_tokens()' - Write <Token> nodes for all APIs.
- */
- static void
- write_tokens(FILE *out, /* I - Output file */
- mxml_node_t *doc, /* I - Document */
- const char *path) /* I - Path to help file */
- {
- mxml_node_t *function, /* Current function */
- *scut, /* Struct/class/union/typedef */
- *arg, /* Current argument */
- *description, /* Description of function/var */
- *type, /* Type node */
- *node; /* Current child node */
- const char *name, /* Name of function/type */
- *cename, /* Current class/enum name */
- *defval; /* Default value for argument */
- char prefix; /* Prefix for declarations */
- /*
- * Classes...
- */
- if ((scut = find_public(doc, doc, "class")) != NULL)
- {
- while (scut)
- {
- cename = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<Token>\n"
- "<Path>Documentation/%s</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<TokenIdentifier>//apple_ref/cpp/cl/%s</TokenIdentifier>\n"
- "<Abstract>", path, cename, cename);
- write_description(out, description, "", 1);
- fputs("</Abstract>\n"
- "</Token>\n", out);
- if ((function = find_public(scut, scut, "function")) != NULL)
- {
- while (function)
- {
- name = mxmlElementGetAttr(function, "name");
- description = mxmlFindElement(function, function, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<Token>\n"
- "<Path>Documentation/%s</Path>\n"
- "<Anchor>%s.%s</Anchor>\n"
- "<TokenIdentifier>//apple_ref/cpp/clm/%s/%s", path,
- cename, name, cename, name);
- arg = mxmlFindElement(function, function, "returnvalue", NULL,
- NULL, MXML_DESCEND_FIRST);
- if (arg && (type = mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST)) != NULL)
- {
- for (node = type->child; node; node = node->next)
- fputs(node->value.text.string, out);
- }
- else if (strcmp(cename, name) && strcmp(cename, name + 1))
- fputs("void", out);
- fputs("/", out);
- for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
- MXML_DESCEND_FIRST), prefix = '(';
- arg;
- arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
- MXML_NO_DESCEND), prefix = ',')
- {
- type = mxmlFindElement(arg, arg, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- putc(prefix, out);
- for (node = type->child; node; node = node->next)
- fputs(node->value.text.string, out);
- fputs(mxmlElementGetAttr(arg, "name"), out);
- }
- if (prefix == '(')
- fputs("(void", out);
- fputs(")</TokenIdentifier>\n"
- "<Abstract>", out);
- write_description(out, description, "", 1);
- fputs("</Abstract>\n"
- "<Declaration>", out);
- arg = mxmlFindElement(function, function, "returnvalue", NULL,
- NULL, MXML_DESCEND_FIRST);
- if (arg)
- write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_XML);
- else if (strcmp(cename, name) && strcmp(cename, name + 1))
- fputs("void ", out);
- fputs(name, out);
- for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
- MXML_DESCEND_FIRST), prefix = '(';
- arg;
- arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
- MXML_NO_DESCEND), prefix = ',')
- {
- type = mxmlFindElement(arg, arg, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- putc(prefix, out);
- if (prefix == ',')
- putc(' ', out);
- if (type->child)
- write_element(out, doc, type, OUTPUT_XML);
- fputs(mxmlElementGetAttr(arg, "name"), out);
- if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
- fprintf(out, " %s", defval);
- }
- if (prefix == '(')
- fputs("(void);", out);
- else
- fputs(");", out);
- fputs("</Declaration>\n"
- "</Token>\n", out);
- function = find_public(function, doc, "function");
- }
- }
- scut = find_public(scut, doc, "class");
- }
- }
- /*
- * Functions...
- */
- if ((function = find_public(doc, doc, "function")) != NULL)
- {
- while (function)
- {
- name = mxmlElementGetAttr(function, "name");
- description = mxmlFindElement(function, function, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<Token>\n"
- "<Path>Documentation/%s</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<TokenIdentifier>//apple_ref/c/func/%s</TokenIdentifier>\n"
- "<Abstract>", path, name, name);
- write_description(out, description, "", 1);
- fputs("</Abstract>\n"
- "<Declaration>", out);
- arg = mxmlFindElement(function, function, "returnvalue", NULL,
- NULL, MXML_DESCEND_FIRST);
- if (arg)
- write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
- NULL, MXML_DESCEND_FIRST),
- OUTPUT_XML);
- else // if (strcmp(cname, name) && strcmp(cname, name + 1))
- fputs("void ", out);
- fputs(name, out);
- for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
- MXML_DESCEND_FIRST), prefix = '(';
- arg;
- arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
- MXML_NO_DESCEND), prefix = ',')
- {
- type = mxmlFindElement(arg, arg, "type", NULL, NULL,
- MXML_DESCEND_FIRST);
- putc(prefix, out);
- if (prefix == ',')
- putc(' ', out);
- if (type->child)
- write_element(out, doc, type, OUTPUT_XML);
- fputs(mxmlElementGetAttr(arg, "name"), out);
- if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
- fprintf(out, " %s", defval);
- }
- if (prefix == '(')
- fputs("(void);", out);
- else
- fputs(");", out);
- fputs("</Declaration>\n"
- "</Token>\n", out);
- function = find_public(function, doc, "function");
- }
- }
- /*
- * Data types...
- */
- if ((scut = find_public(doc, doc, "typedef")) != NULL)
- {
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<Token>\n"
- "<Path>Documentation/%s</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<TokenIdentifier>//apple_ref/c/tdef/%s</TokenIdentifier>\n"
- "<Abstract>", path, name, name);
- write_description(out, description, "", 1);
- fputs("</Abstract>\n"
- "</Token>\n", out);
- scut = find_public(scut, doc, "typedef");
- }
- }
- /*
- * Structures...
- */
- if ((scut = find_public(doc, doc, "struct")) != NULL)
- {
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<Token>\n"
- "<Path>Documentation/%s</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<TokenIdentifier>//apple_ref/c/tag/%s</TokenIdentifier>\n"
- "<Abstract>", path, name, name);
- write_description(out, description, "", 1);
- fputs("</Abstract>\n"
- "</Token>\n", out);
- scut = find_public(scut, doc, "struct");
- }
- }
- /*
- * Unions...
- */
- if ((scut = find_public(doc, doc, "union")) != NULL)
- {
- while (scut)
- {
- name = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<Token>\n"
- "<Path>Documentation/%s</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<TokenIdentifier>//apple_ref/c/tag/%s</TokenIdentifier>\n"
- "<Abstract>", path, name, name);
- write_description(out, description, "", 1);
- fputs("</Abstract>\n"
- "</Token>\n", out);
- scut = find_public(scut, doc, "union");
- }
- }
- /*
- * Globals variables...
- */
- if ((arg = find_public(doc, doc, "variable")) != NULL)
- {
- while (arg)
- {
- name = mxmlElementGetAttr(arg, "name");
- description = mxmlFindElement(arg, arg, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<Token>\n"
- "<Path>Documentation/%s</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<TokenIdentifier>//apple_ref/c/data/%s</TokenIdentifier>\n"
- "<Abstract>", path, name, name);
- write_description(out, description, "", 1);
- fputs("</Abstract>\n"
- "</Token>\n", out);
- arg = find_public(arg, doc, "variable");
- }
- }
- /*
- * Enumerations/constants...
- */
- if ((scut = find_public(doc, doc, "enumeration")) != NULL)
- {
- while (scut)
- {
- cename = mxmlElementGetAttr(scut, "name");
- description = mxmlFindElement(scut, scut, "description",
- NULL, NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<Token>\n"
- "<Path>Documentation/%s</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<TokenIdentifier>//apple_ref/c/tag/%s</TokenIdentifier>\n"
- "<Abstract>", path, cename, cename);
- write_description(out, description, "", 1);
- fputs("</Abstract>\n"
- "</Token>\n", out);
- for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
- MXML_DESCEND_FIRST);
- arg;
- arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
- MXML_NO_DESCEND))
- {
- name = mxmlElementGetAttr(arg, "name");
- description = mxmlFindElement(arg, arg, "description", NULL,
- NULL, MXML_DESCEND_FIRST);
- fprintf(out, "<Token>\n"
- "<Path>Documentation/%s</Path>\n"
- "<Anchor>%s</Anchor>\n"
- "<TokenIdentifier>//apple_ref/c/econst/%s</TokenIdentifier>\n"
- "<Abstract>", path, cename, name);
- write_description(out, description, "", 1);
- fputs("</Abstract>\n"
- "</Token>\n", out);
- }
- scut = find_public(scut, doc, "enumeration");
- }
- }
- }
- /*
- * 'ws_cb()' - Whitespace callback for saving.
- */
- static const char * /* O - Whitespace string or NULL for none */
- ws_cb(mxml_node_t *node, /* I - Element node */
- int where) /* I - Where value */
- {
- const char *name; /* Name of element */
- int depth; /* Depth of node */
- static const char *spaces = " ";
- /* Whitespace (40 spaces) for indent */
- name = node->value.element.name;
- switch (where)
- {
- case MXML_WS_BEFORE_CLOSE :
- if (strcmp(name, "argument") &&
- strcmp(name, "class") &&
- strcmp(name, "constant") &&
- strcmp(name, "enumeration") &&
- strcmp(name, "function") &&
- strcmp(name, "mxmldoc") &&
- strcmp(name, "namespace") &&
- strcmp(name, "returnvalue") &&
- strcmp(name, "struct") &&
- strcmp(name, "typedef") &&
- strcmp(name, "union") &&
- strcmp(name, "variable"))
- return (NULL);
- for (depth = -4; node; node = node->parent, depth += 2);
- if (depth > 40)
- return (spaces);
- else if (depth < 2)
- return (NULL);
- else
- return (spaces + 40 - depth);
- case MXML_WS_AFTER_CLOSE :
- return ("\n");
- case MXML_WS_BEFORE_OPEN :
- for (depth = -4; node; node = node->parent, depth += 2);
- if (depth > 40)
- return (spaces);
- else if (depth < 2)
- return (NULL);
- else
- return (spaces + 40 - depth);
- default :
- case MXML_WS_AFTER_OPEN :
- if (strcmp(name, "argument") &&
- strcmp(name, "class") &&
- strcmp(name, "constant") &&
- strcmp(name, "enumeration") &&
- strcmp(name, "function") &&
- strcmp(name, "mxmldoc") &&
- strcmp(name, "namespace") &&
- strcmp(name, "returnvalue") &&
- strcmp(name, "struct") &&
- strcmp(name, "typedef") &&
- strcmp(name, "union") &&
- strcmp(name, "variable") &&
- strncmp(name, "?xml", 4))
- return (NULL);
- else
- return ("\n");
- }
- }
- /*
- * End of "$Id: mxmldoc.c 451 2014-01-04 21:50:06Z msweet $".
- */
|