ebrowse.c 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991
  1. /* ebrowse.c --- parsing files for the ebrowse C++ browser
  2. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
  3. 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
  4. Free Software Foundation, Inc.
  5. This file is part of GNU Emacs.
  6. GNU Emacs is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. GNU Emacs is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
  16. #ifdef HAVE_CONFIG_H
  17. #include <config.h>
  18. #endif
  19. #include <stdio.h>
  20. #ifdef HAVE_STDLIB_H
  21. #include <stdlib.h>
  22. #endif
  23. #ifdef HAVE_STRING_H
  24. #include <string.h>
  25. #endif
  26. #include <ctype.h>
  27. #include <assert.h>
  28. #include "getopt.h"
  29. /* The SunOS compiler doesn't have SEEK_END. */
  30. #ifndef SEEK_END
  31. #define SEEK_END 2
  32. #endif
  33. /* Conditionalize function prototypes. */
  34. #ifdef PROTOTYPES /* From config.h. */
  35. #define P_(x) x
  36. #else
  37. #define P_(x) ()
  38. #endif
  39. /* Value is non-zero if strings X and Y compare equal. */
  40. #define streq(X, Y) (*(X) == *(Y) && strcmp ((X) + 1, (Y) + 1) == 0)
  41. /* The ubiquitous `max' and `min' macros. */
  42. #ifndef max
  43. #define max(X, Y) ((X) > (Y) ? (X) : (Y))
  44. #define min(X, Y) ((X) < (Y) ? (X) : (Y))
  45. #endif
  46. /* Files are read in chunks of this number of bytes. */
  47. #define READ_CHUNK_SIZE (100 * 1024)
  48. /* The character used as a separator in path lists (like $PATH). */
  49. #if defined(__MSDOS__)
  50. #define PATH_LIST_SEPARATOR ';'
  51. #define FILENAME_EQ(X,Y) (strcasecmp(X,Y) == 0)
  52. #else
  53. #if defined(WINDOWSNT)
  54. #define PATH_LIST_SEPARATOR ';'
  55. #define FILENAME_EQ(X,Y) (stricmp(X,Y) == 0)
  56. #else
  57. #define PATH_LIST_SEPARATOR ':'
  58. #define FILENAME_EQ(X,Y) (streq(X,Y))
  59. #endif
  60. #endif
  61. /* The default output file name. */
  62. #define DEFAULT_OUTFILE "BROWSE"
  63. /* A version string written to the output file. Change this whenever
  64. the structure of the output file changes. */
  65. #define EBROWSE_FILE_VERSION "ebrowse 5.0"
  66. /* The output file consists of a tree of Lisp objects, with major
  67. nodes built out of Lisp structures. These are the heads of the
  68. Lisp structs with symbols identifying their type. */
  69. #define TREE_HEADER_STRUCT "[ebrowse-hs "
  70. #define TREE_STRUCT "[ebrowse-ts "
  71. #define MEMBER_STRUCT "[ebrowse-ms "
  72. #define BROWSE_STRUCT "[ebrowse-bs "
  73. #define CLASS_STRUCT "[ebrowse-cs "
  74. /* The name of the symbol table entry for global functions, variables,
  75. defines etc. This name also appears in the browser display. */
  76. #define GLOBALS_NAME "*Globals*"
  77. /* Token definitions. */
  78. enum token
  79. {
  80. YYEOF = 0, /* end of file */
  81. CSTRING = 256, /* string constant */
  82. CCHAR, /* character constant */
  83. CINT, /* integral constant */
  84. CFLOAT, /* real constant */
  85. ELLIPSIS, /* ... */
  86. LSHIFTASGN, /* <<= */
  87. RSHIFTASGN, /* >>= */
  88. ARROWSTAR, /* ->* */
  89. IDENT, /* identifier */
  90. DIVASGN, /* /= */
  91. INC, /* ++ */
  92. ADDASGN, /* += */
  93. DEC, /* -- */
  94. ARROW, /* -> */
  95. SUBASGN, /* -= */
  96. MULASGN, /* *= */
  97. MODASGN, /* %= */
  98. LOR, /* || */
  99. ORASGN, /* |= */
  100. LAND, /* && */
  101. ANDASGN, /* &= */
  102. XORASGN, /* ^= */
  103. POINTSTAR, /* .* */
  104. DCOLON, /* :: */
  105. EQ, /* == */
  106. NE, /* != */
  107. LE, /* <= */
  108. LSHIFT, /* << */
  109. GE, /* >= */
  110. RSHIFT, /* >> */
  111. /* Keywords. The undef's are there because these
  112. three symbols are very likely to be defined somewhere. */
  113. #undef BOOL
  114. #undef TRUE
  115. #undef FALSE
  116. ASM, /* asm */
  117. AUTO, /* auto */
  118. BREAK, /* break */
  119. CASE, /* case */
  120. CATCH, /* catch */
  121. CHAR, /* char */
  122. CLASS, /* class */
  123. CONST, /* const */
  124. CONTINUE, /* continue */
  125. DEFAULT, /* default */
  126. DELETE, /* delete */
  127. DO, /* do */
  128. DOUBLE, /* double */
  129. ELSE, /* else */
  130. ENUM, /* enum */
  131. EXTERN, /* extern */
  132. FLOAT, /* float */
  133. FOR, /* for */
  134. FRIEND, /* friend */
  135. GOTO, /* goto */
  136. IF, /* if */
  137. T_INLINE, /* inline */
  138. INT, /* int */
  139. LONG, /* long */
  140. NEW, /* new */
  141. OPERATOR, /* operator */
  142. PRIVATE, /* private */
  143. PROTECTED, /* protected */
  144. PUBLIC, /* public */
  145. REGISTER, /* register */
  146. RETURN, /* return */
  147. SHORT, /* short */
  148. SIGNED, /* signed */
  149. SIZEOF, /* sizeof */
  150. STATIC, /* static */
  151. STRUCT, /* struct */
  152. SWITCH, /* switch */
  153. TEMPLATE, /* template */
  154. THIS, /* this */
  155. THROW, /* throw */
  156. TRY, /* try */
  157. TYPEDEF, /* typedef */
  158. UNION, /* union */
  159. UNSIGNED, /* unsigned */
  160. VIRTUAL, /* virtual */
  161. VOID, /* void */
  162. VOLATILE, /* volatile */
  163. WHILE, /* while */
  164. MUTABLE, /* mutable */
  165. BOOL, /* bool */
  166. TRUE, /* true */
  167. FALSE, /* false */
  168. SIGNATURE, /* signature (GNU extension) */
  169. NAMESPACE, /* namespace */
  170. EXPLICIT, /* explicit */
  171. TYPENAME, /* typename */
  172. CONST_CAST, /* const_cast */
  173. DYNAMIC_CAST, /* dynamic_cast */
  174. REINTERPRET_CAST, /* reinterpret_cast */
  175. STATIC_CAST, /* static_cast */
  176. TYPEID, /* typeid */
  177. USING, /* using */
  178. WCHAR /* wchar_t */
  179. };
  180. /* Storage classes, in a wider sense. */
  181. enum sc
  182. {
  183. SC_UNKNOWN,
  184. SC_MEMBER, /* Is an instance member. */
  185. SC_STATIC, /* Is static member. */
  186. SC_FRIEND, /* Is friend function. */
  187. SC_TYPE /* Is a type definition. */
  188. };
  189. /* Member visibility. */
  190. enum visibility
  191. {
  192. V_PUBLIC,
  193. V_PROTECTED,
  194. V_PRIVATE
  195. };
  196. /* Member flags. */
  197. #define F_VIRTUAL 1 /* Is virtual function. */
  198. #define F_INLINE 2 /* Is inline function. */
  199. #define F_CONST 4 /* Is const. */
  200. #define F_PURE 8 /* Is pure virtual function. */
  201. #define F_MUTABLE 16 /* Is mutable. */
  202. #define F_TEMPLATE 32 /* Is a template. */
  203. #define F_EXPLICIT 64 /* Is explicit constructor. */
  204. #define F_THROW 128 /* Has a throw specification. */
  205. #define F_EXTERNC 256 /* Is declared extern "C". */
  206. #define F_DEFINE 512 /* Is a #define. */
  207. /* Two macros to set and test a bit in an int. */
  208. #define SET_FLAG(F, FLAG) ((F) |= (FLAG))
  209. #define HAS_FLAG(F, FLAG) (((F) & (FLAG)) != 0)
  210. /* Structure describing a class member. */
  211. struct member
  212. {
  213. struct member *next; /* Next in list of members. */
  214. struct member *anext; /* Collision chain in member_table. */
  215. struct member **list; /* Pointer to list in class. */
  216. unsigned param_hash; /* Hash value for parameter types. */
  217. int vis; /* Visibility (public, ...). */
  218. int flags; /* See F_* above. */
  219. char *regexp; /* Matching regular expression. */
  220. char *filename; /* Don't free this shared string. */
  221. int pos; /* Buffer position of occurrence. */
  222. char *def_regexp; /* Regular expression matching definition. */
  223. char *def_filename; /* File name of definition. */
  224. int def_pos; /* Buffer position of definition. */
  225. char name[1]; /* Member name. */
  226. };
  227. /* Structures of this type are used to connect class structures with
  228. their super and subclasses. */
  229. struct link
  230. {
  231. struct sym *sym; /* The super or subclass. */
  232. struct link *next; /* Next in list or NULL. */
  233. };
  234. /* Structure used to record namespace aliases. */
  235. struct alias
  236. {
  237. struct alias *next; /* Next in list. */
  238. struct sym *namesp; /* Namespace in which defined. */
  239. struct link *aliasee; /* List of aliased namespaces (A::B::C...). */
  240. char name[1]; /* Alias name. */
  241. };
  242. /* The structure used to describe a class in the symbol table,
  243. or a namespace in all_namespaces. */
  244. struct sym
  245. {
  246. int flags; /* Is class a template class?. */
  247. unsigned char visited; /* Used to find circles. */
  248. struct sym *next; /* Hash collision list. */
  249. struct link *subs; /* List of subclasses. */
  250. struct link *supers; /* List of superclasses. */
  251. struct member *vars; /* List of instance variables. */
  252. struct member *fns; /* List of instance functions. */
  253. struct member *static_vars; /* List of static variables. */
  254. struct member *static_fns; /* List of static functions. */
  255. struct member *friends; /* List of friend functions. */
  256. struct member *types; /* List of local types. */
  257. char *regexp; /* Matching regular expression. */
  258. int pos; /* Buffer position. */
  259. char *filename; /* File in which it can be found. */
  260. char *sfilename; /* File in which members can be found. */
  261. struct sym *namesp; /* Namespace in which defined. . */
  262. char name[1]; /* Name of the class. */
  263. };
  264. /* Experimental: Print info for `--position-info'. We print
  265. '(CLASS-NAME SCOPE MEMBER-NAME). */
  266. #define P_DEFN 1
  267. #define P_DECL 2
  268. int info_where;
  269. struct sym *info_cls = NULL;
  270. struct member *info_member = NULL;
  271. /* Experimental. For option `--position-info', the buffer position we
  272. are interested in. When this position is reached, print out
  273. information about what we know about that point. */
  274. int info_position = -1;
  275. /* Command line options structure for getopt_long. */
  276. struct option options[] =
  277. {
  278. {"append", no_argument, NULL, 'a'},
  279. {"files", required_argument, NULL, 'f'},
  280. {"help", no_argument, NULL, -2},
  281. {"min-regexp-length", required_argument, NULL, 'm'},
  282. {"max-regexp-length", required_argument, NULL, 'M'},
  283. {"no-nested-classes", no_argument, NULL, 'n'},
  284. {"no-regexps", no_argument, NULL, 'x'},
  285. {"no-structs-or-unions", no_argument, NULL, 's'},
  286. {"output-file", required_argument, NULL, 'o'},
  287. {"position-info", required_argument, NULL, 'p'},
  288. {"search-path", required_argument, NULL, 'I'},
  289. {"verbose", no_argument, NULL, 'v'},
  290. {"version", no_argument, NULL, -3},
  291. {"very-verbose", no_argument, NULL, 'V'},
  292. {NULL, 0, NULL, 0}
  293. };
  294. /* Semantic values of tokens. Set by yylex.. */
  295. unsigned yyival; /* Set for token CINT. */
  296. char *yytext; /* Set for token IDENT. */
  297. char *yytext_end;
  298. /* Output file. */
  299. FILE *yyout;
  300. /* Current line number. */
  301. int yyline;
  302. /* The name of the current input file. */
  303. char *filename;
  304. /* Three character class vectors, and macros to test membership
  305. of characters. */
  306. char is_ident[255];
  307. char is_digit[255];
  308. char is_white[255];
  309. #define IDENTP(C) is_ident[(unsigned char) (C)]
  310. #define DIGITP(C) is_digit[(unsigned char) (C)]
  311. #define WHITEP(C) is_white[(unsigned char) (C)]
  312. /* Command line flags. */
  313. int f_append;
  314. int f_verbose;
  315. int f_very_verbose;
  316. int f_structs = 1;
  317. int f_regexps = 1;
  318. int f_nested_classes = 1;
  319. /* Maximum and minimum lengths of regular expressions matching a
  320. member, class etc., for writing them to the output file. These are
  321. overridable from the command line. */
  322. int min_regexp = 5;
  323. int max_regexp = 50;
  324. /* Input buffer. */
  325. char *inbuffer;
  326. char *in;
  327. int inbuffer_size;
  328. /* Return the current buffer position in the input file. */
  329. #define BUFFER_POS() (in - inbuffer)
  330. /* If current lookahead is CSTRING, the following points to the
  331. first character in the string constant. Used for recognizing
  332. extern "C". */
  333. char *string_start;
  334. /* The size of the hash tables for classes.and members. Should be
  335. prime. */
  336. #define TABLE_SIZE 1001
  337. /* The hash table for class symbols. */
  338. struct sym *class_table[TABLE_SIZE];
  339. /* Hash table containing all member structures. This is generally
  340. faster for member lookup than traversing the member lists of a
  341. `struct sym'. */
  342. struct member *member_table[TABLE_SIZE];
  343. /* Hash table for namespace aliases */
  344. struct alias *namespace_alias_table[TABLE_SIZE];
  345. /* The special class symbol used to hold global functions,
  346. variables etc. */
  347. struct sym *global_symbols;
  348. /* The current namespace. */
  349. struct sym *current_namespace;
  350. /* The list of all known namespaces. */
  351. struct sym *all_namespaces;
  352. /* Stack of namespaces we're currently nested in, during the parse. */
  353. struct sym **namespace_stack;
  354. int namespace_stack_size;
  355. int namespace_sp;
  356. /* The current lookahead token. */
  357. int tk = -1;
  358. /* Structure describing a keyword. */
  359. struct kw
  360. {
  361. char *name; /* Spelling. */
  362. int tk; /* Token value. */
  363. struct kw *next; /* Next in collision chain. */
  364. };
  365. /* Keywords are lookup up in a hash table of their own. */
  366. #define KEYWORD_TABLE_SIZE 1001
  367. struct kw *keyword_table[KEYWORD_TABLE_SIZE];
  368. /* Search path. */
  369. struct search_path
  370. {
  371. char *path;
  372. struct search_path *next;
  373. };
  374. struct search_path *search_path;
  375. struct search_path *search_path_tail;
  376. /* Function prototypes. */
  377. int yylex P_ ((void));
  378. void yyparse P_ ((void));
  379. void re_init_parser P_ ((void));
  380. char *token_string P_ ((int));
  381. char *matching_regexp P_ ((void));
  382. void init_sym P_ ((void));
  383. struct sym *add_sym P_ ((char *, struct sym *));
  384. void add_link P_ ((struct sym *, struct sym *));
  385. void add_member_defn P_ ((struct sym *, char *, char *,
  386. int, unsigned, int, int, int));
  387. void add_member_decl P_ ((struct sym *, char *, char *, int,
  388. unsigned, int, int, int, int));
  389. void dump_roots P_ ((FILE *));
  390. void *xmalloc P_ ((int));
  391. void xfree P_ ((void *));
  392. void add_global_defn P_ ((char *, char *, int, unsigned, int, int, int));
  393. void add_global_decl P_ ((char *, char *, int, unsigned, int, int, int));
  394. void add_define P_ ((char *, char *, int));
  395. void mark_inherited_virtual P_ ((void));
  396. void leave_namespace P_ ((void));
  397. void enter_namespace P_ ((char *));
  398. void register_namespace_alias P_ ((char *, struct link *));
  399. void insert_keyword P_ ((char *, int));
  400. void re_init_scanner P_ ((void));
  401. void init_scanner P_ ((void));
  402. void usage P_ ((int));
  403. void version P_ ((void));
  404. void process_file P_ ((char *));
  405. void add_search_path P_ ((char *));
  406. FILE *open_file P_ ((char *));
  407. int process_pp_line P_ ((void));
  408. int dump_members P_ ((FILE *, struct member *));
  409. void dump_sym P_ ((FILE *, struct sym *));
  410. int dump_tree P_ ((FILE *, struct sym *));
  411. struct member *find_member P_ ((struct sym *, char *, int, int, unsigned));
  412. struct member *add_member P_ ((struct sym *, char *, int, int, unsigned));
  413. void mark_virtual P_ ((struct sym *));
  414. void mark_virtual P_ ((struct sym *));
  415. struct sym *make_namespace P_ ((char *, struct sym *));
  416. char *sym_scope P_ ((struct sym *));
  417. char *sym_scope_1 P_ ((struct sym *));
  418. int skip_to P_ ((int));
  419. void skip_matching P_ ((void));
  420. void member P_ ((struct sym *, int));
  421. void class_body P_ ((struct sym *, int));
  422. void class_definition P_ ((struct sym *, int, int, int));
  423. void declaration P_ ((int));
  424. unsigned parm_list P_ ((int *));
  425. char *operator_name P_ ((int *));
  426. struct sym *parse_classname P_ ((void));
  427. struct sym *parse_qualified_ident_or_type P_ ((char **));
  428. void parse_qualified_param_ident_or_type P_ ((char **));
  429. int globals P_ ((int));
  430. void yyerror P_ ((char *, char *));
  431. void usage P_ ((int)) NO_RETURN;
  432. void version P_ (()) NO_RETURN;
  433. /***********************************************************************
  434. Utilities
  435. ***********************************************************************/
  436. /* Print an error in a printf-like style with the current input file
  437. name and line number. */
  438. void
  439. yyerror (format, s)
  440. char *format, *s;
  441. {
  442. fprintf (stderr, "%s:%d: ", filename, yyline);
  443. fprintf (stderr, format, s);
  444. putc ('\n', stderr);
  445. }
  446. /* Like malloc but print an error and exit if not enough memory is
  447. available. */
  448. void *
  449. xmalloc (nbytes)
  450. int nbytes;
  451. {
  452. void *p = malloc (nbytes);
  453. if (p == NULL)
  454. {
  455. yyerror ("out of memory", NULL);
  456. exit (EXIT_FAILURE);
  457. }
  458. return p;
  459. }
  460. /* Like realloc but print an error and exit if out of memory. */
  461. void *
  462. xrealloc (p, sz)
  463. void *p;
  464. int sz;
  465. {
  466. p = realloc (p, sz);
  467. if (p == NULL)
  468. {
  469. yyerror ("out of memory", NULL);
  470. exit (EXIT_FAILURE);
  471. }
  472. return p;
  473. }
  474. /* Like strdup, but print an error and exit if not enough memory is
  475. available.. If S is null, return null. */
  476. char *
  477. xstrdup (s)
  478. char *s;
  479. {
  480. if (s)
  481. s = strcpy (xmalloc (strlen (s) + 1), s);
  482. return s;
  483. }
  484. /***********************************************************************
  485. Symbols
  486. ***********************************************************************/
  487. /* Initialize the symbol table. This currently only sets up the
  488. special symbol for globals (`*Globals*'). */
  489. void
  490. init_sym ()
  491. {
  492. global_symbols = add_sym (GLOBALS_NAME, NULL);
  493. }
  494. /* Add a symbol for class NAME to the symbol table. NESTED_IN_CLASS
  495. is the class in which class NAME was found. If it is null,
  496. this means the scope of NAME is the current namespace.
  497. If a symbol for NAME already exists, return that. Otherwise
  498. create a new symbol and set it to default values. */
  499. struct sym *
  500. add_sym (name, nested_in_class)
  501. char *name;
  502. struct sym *nested_in_class;
  503. {
  504. struct sym *sym;
  505. unsigned h;
  506. char *s;
  507. struct sym *scope = nested_in_class ? nested_in_class : current_namespace;
  508. for (s = name, h = 0; *s; ++s)
  509. h = (h << 1) ^ *s;
  510. h %= TABLE_SIZE;
  511. for (sym = class_table[h]; sym; sym = sym->next)
  512. if (streq (name, sym->name)
  513. && ((!sym->namesp && !scope)
  514. || (sym->namesp && scope
  515. && streq (sym->namesp->name, scope->name))))
  516. break;
  517. if (sym == NULL)
  518. {
  519. if (f_very_verbose)
  520. {
  521. putchar ('\t');
  522. puts (name);
  523. }
  524. sym = (struct sym *) xmalloc (sizeof *sym + strlen (name));
  525. bzero (sym, sizeof *sym);
  526. strcpy (sym->name, name);
  527. sym->namesp = scope;
  528. sym->next = class_table[h];
  529. class_table[h] = sym;
  530. }
  531. return sym;
  532. }
  533. /* Add links between superclass SUPER and subclass SUB. */
  534. void
  535. add_link (super, sub)
  536. struct sym *super, *sub;
  537. {
  538. struct link *lnk, *lnk2, *p, *prev;
  539. /* See if a link already exists. */
  540. for (p = super->subs, prev = NULL;
  541. p && strcmp (sub->name, p->sym->name) > 0;
  542. prev = p, p = p->next)
  543. ;
  544. /* Avoid duplicates. */
  545. if (p == NULL || p->sym != sub)
  546. {
  547. lnk = (struct link *) xmalloc (sizeof *lnk);
  548. lnk2 = (struct link *) xmalloc (sizeof *lnk2);
  549. lnk->sym = sub;
  550. lnk->next = p;
  551. if (prev)
  552. prev->next = lnk;
  553. else
  554. super->subs = lnk;
  555. lnk2->sym = super;
  556. lnk2->next = sub->supers;
  557. sub->supers = lnk2;
  558. }
  559. }
  560. /* Find in class CLS member NAME.
  561. VAR non-zero means look for a member variable; otherwise a function
  562. is searched. SC specifies what kind of member is searched---a
  563. static, or per-instance member etc. HASH is a hash code for the
  564. parameter types of functions. Value is a pointer to the member
  565. found or null if not found. */
  566. struct member *
  567. find_member (cls, name, var, sc, hash)
  568. struct sym *cls;
  569. char *name;
  570. int var, sc;
  571. unsigned hash;
  572. {
  573. struct member **list;
  574. struct member *p;
  575. unsigned name_hash = 0;
  576. char *s;
  577. int i;
  578. switch (sc)
  579. {
  580. case SC_FRIEND:
  581. list = &cls->friends;
  582. break;
  583. case SC_TYPE:
  584. list = &cls->types;
  585. break;
  586. case SC_STATIC:
  587. list = var ? &cls->static_vars : &cls->static_fns;
  588. break;
  589. default:
  590. list = var ? &cls->vars : &cls->fns;
  591. break;
  592. }
  593. for (s = name; *s; ++s)
  594. name_hash = (name_hash << 1) ^ *s;
  595. i = name_hash % TABLE_SIZE;
  596. for (p = member_table[i]; p; p = p->anext)
  597. if (p->list == list && p->param_hash == hash && streq (name, p->name))
  598. break;
  599. return p;
  600. }
  601. /* Add to class CLS information for the declaration of member NAME.
  602. REGEXP is a regexp matching the declaration, if non-null. POS is
  603. the position in the source where the declaration is found. HASH is
  604. a hash code for the parameter list of the member, if it's a
  605. function. VAR non-zero means member is a variable or type. SC
  606. specifies the type of member (instance member, static, ...). VIS
  607. is the member's visibility (public, protected, private). FLAGS is
  608. a bit set giving additional information about the member (see the
  609. F_* defines). */
  610. void
  611. add_member_decl (cls, name, regexp, pos, hash, var, sc, vis, flags)
  612. struct sym *cls;
  613. char *name;
  614. char *regexp;
  615. int pos;
  616. unsigned hash;
  617. int var;
  618. int sc;
  619. int vis;
  620. int flags;
  621. {
  622. struct member *m;
  623. m = find_member (cls, name, var, sc, hash);
  624. if (m == NULL)
  625. m = add_member (cls, name, var, sc, hash);
  626. /* Have we seen a new filename? If so record that. */
  627. if (!cls->filename || !FILENAME_EQ (cls->filename, filename))
  628. m->filename = filename;
  629. m->regexp = regexp;
  630. m->pos = pos;
  631. m->flags = flags;
  632. switch (vis)
  633. {
  634. case PRIVATE:
  635. m->vis = V_PRIVATE;
  636. break;
  637. case PROTECTED:
  638. m->vis = V_PROTECTED;
  639. break;
  640. case PUBLIC:
  641. m->vis = V_PUBLIC;
  642. break;
  643. }
  644. info_where = P_DECL;
  645. info_cls = cls;
  646. info_member = m;
  647. }
  648. /* Add to class CLS information for the definition of member NAME.
  649. REGEXP is a regexp matching the declaration, if non-null. POS is
  650. the position in the source where the declaration is found. HASH is
  651. a hash code for the parameter list of the member, if it's a
  652. function. VAR non-zero means member is a variable or type. SC
  653. specifies the type of member (instance member, static, ...). VIS
  654. is the member's visibility (public, protected, private). FLAGS is
  655. a bit set giving additional information about the member (see the
  656. F_* defines). */
  657. void
  658. add_member_defn (cls, name, regexp, pos, hash, var, sc, flags)
  659. struct sym *cls;
  660. char *name;
  661. char *regexp;
  662. int pos;
  663. unsigned hash;
  664. int var;
  665. int sc;
  666. int flags;
  667. {
  668. struct member *m;
  669. if (sc == SC_UNKNOWN)
  670. {
  671. m = find_member (cls, name, var, SC_MEMBER, hash);
  672. if (m == NULL)
  673. {
  674. m = find_member (cls, name, var, SC_STATIC, hash);
  675. if (m == NULL)
  676. m = add_member (cls, name, var, sc, hash);
  677. }
  678. }
  679. else
  680. {
  681. m = find_member (cls, name, var, sc, hash);
  682. if (m == NULL)
  683. m = add_member (cls, name, var, sc, hash);
  684. }
  685. if (!cls->sfilename)
  686. cls->sfilename = filename;
  687. if (!FILENAME_EQ (cls->sfilename, filename))
  688. m->def_filename = filename;
  689. m->def_regexp = regexp;
  690. m->def_pos = pos;
  691. m->flags |= flags;
  692. info_where = P_DEFN;
  693. info_cls = cls;
  694. info_member = m;
  695. }
  696. /* Add a symbol for a define named NAME to the symbol table.
  697. REGEXP is a regular expression matching the define in the source,
  698. if it is non-null. POS is the position in the file. */
  699. void
  700. add_define (name, regexp, pos)
  701. char *name, *regexp;
  702. int pos;
  703. {
  704. add_global_defn (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
  705. add_global_decl (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
  706. }
  707. /* Add information for the global definition of NAME.
  708. REGEXP is a regexp matching the declaration, if non-null. POS is
  709. the position in the source where the declaration is found. HASH is
  710. a hash code for the parameter list of the member, if it's a
  711. function. VAR non-zero means member is a variable or type. SC
  712. specifies the type of member (instance member, static, ...). VIS
  713. is the member's visibility (public, protected, private). FLAGS is
  714. a bit set giving additional information about the member (see the
  715. F_* defines). */
  716. void
  717. add_global_defn (name, regexp, pos, hash, var, sc, flags)
  718. char *name, *regexp;
  719. int pos;
  720. unsigned hash;
  721. int var;
  722. int sc;
  723. int flags;
  724. {
  725. int i;
  726. struct sym *sym;
  727. /* Try to find out for which classes a function is a friend, and add
  728. what we know about it to them. */
  729. if (!var)
  730. for (i = 0; i < TABLE_SIZE; ++i)
  731. for (sym = class_table[i]; sym; sym = sym->next)
  732. if (sym != global_symbols && sym->friends)
  733. if (find_member (sym, name, 0, SC_FRIEND, hash))
  734. add_member_defn (sym, name, regexp, pos, hash, 0,
  735. SC_FRIEND, flags);
  736. /* Add to global symbols. */
  737. add_member_defn (global_symbols, name, regexp, pos, hash, var, sc, flags);
  738. }
  739. /* Add information for the global declaration of NAME.
  740. REGEXP is a regexp matching the declaration, if non-null. POS is
  741. the position in the source where the declaration is found. HASH is
  742. a hash code for the parameter list of the member, if it's a
  743. function. VAR non-zero means member is a variable or type. SC
  744. specifies the type of member (instance member, static, ...). VIS
  745. is the member's visibility (public, protected, private). FLAGS is
  746. a bit set giving additional information about the member (see the
  747. F_* defines). */
  748. void
  749. add_global_decl (name, regexp, pos, hash, var, sc, flags)
  750. char *name, *regexp;
  751. int pos;
  752. unsigned hash;
  753. int var;
  754. int sc;
  755. int flags;
  756. {
  757. /* Add declaration only if not already declared. Header files must
  758. be processed before source files for this to have the right effect.
  759. I do not want to handle implicit declarations at the moment. */
  760. struct member *m;
  761. struct member *found;
  762. m = found = find_member (global_symbols, name, var, sc, hash);
  763. if (m == NULL)
  764. m = add_member (global_symbols, name, var, sc, hash);
  765. /* Definition already seen => probably last declaration implicit.
  766. Override. This means that declarations must always be added to
  767. the symbol table before definitions. */
  768. if (!found)
  769. {
  770. if (!global_symbols->filename
  771. || !FILENAME_EQ (global_symbols->filename, filename))
  772. m->filename = filename;
  773. m->regexp = regexp;
  774. m->pos = pos;
  775. m->vis = V_PUBLIC;
  776. m->flags = flags;
  777. info_where = P_DECL;
  778. info_cls = global_symbols;
  779. info_member = m;
  780. }
  781. }
  782. /* Add a symbol for member NAME to class CLS.
  783. VAR non-zero means it's a variable. SC specifies the kind of
  784. member. HASH is a hash code for the parameter types of a function.
  785. Value is a pointer to the member's structure. */
  786. struct member *
  787. add_member (cls, name, var, sc, hash)
  788. struct sym *cls;
  789. char *name;
  790. int var;
  791. int sc;
  792. unsigned hash;
  793. {
  794. struct member *m = (struct member *) xmalloc (sizeof *m + strlen (name));
  795. struct member **list;
  796. struct member *p;
  797. struct member *prev;
  798. unsigned name_hash = 0;
  799. int i;
  800. char *s;
  801. strcpy (m->name, name);
  802. m->param_hash = hash;
  803. m->vis = 0;
  804. m->flags = 0;
  805. m->regexp = NULL;
  806. m->filename = NULL;
  807. m->pos = 0;
  808. m->def_regexp = NULL;
  809. m->def_filename = NULL;
  810. m->def_pos = 0;
  811. assert (cls != NULL);
  812. switch (sc)
  813. {
  814. case SC_FRIEND:
  815. list = &cls->friends;
  816. break;
  817. case SC_TYPE:
  818. list = &cls->types;
  819. break;
  820. case SC_STATIC:
  821. list = var ? &cls->static_vars : &cls->static_fns;
  822. break;
  823. default:
  824. list = var ? &cls->vars : &cls->fns;
  825. break;
  826. }
  827. for (s = name; *s; ++s)
  828. name_hash = (name_hash << 1) ^ *s;
  829. i = name_hash % TABLE_SIZE;
  830. m->anext = member_table[i];
  831. member_table[i] = m;
  832. m->list = list;
  833. /* Keep the member list sorted. It's cheaper to do it here than to
  834. sort them in Lisp. */
  835. for (prev = NULL, p = *list;
  836. p && strcmp (name, p->name) > 0;
  837. prev = p, p = p->next)
  838. ;
  839. m->next = p;
  840. if (prev)
  841. prev->next = m;
  842. else
  843. *list = m;
  844. return m;
  845. }
  846. /* Given the root R of a class tree, step through all subclasses
  847. recursively, marking functions as virtual that are declared virtual
  848. in base classes. */
  849. void
  850. mark_virtual (r)
  851. struct sym *r;
  852. {
  853. struct link *p;
  854. struct member *m, *m2;
  855. for (p = r->subs; p; p = p->next)
  856. {
  857. for (m = r->fns; m; m = m->next)
  858. if (HAS_FLAG (m->flags, F_VIRTUAL))
  859. {
  860. for (m2 = p->sym->fns; m2; m2 = m2->next)
  861. if (m->param_hash == m2->param_hash && streq (m->name, m2->name))
  862. SET_FLAG (m2->flags, F_VIRTUAL);
  863. }
  864. mark_virtual (p->sym);
  865. }
  866. }
  867. /* For all roots of the class tree, mark functions as virtual that
  868. are virtual because of a virtual declaration in a base class. */
  869. void
  870. mark_inherited_virtual ()
  871. {
  872. struct sym *r;
  873. int i;
  874. for (i = 0; i < TABLE_SIZE; ++i)
  875. for (r = class_table[i]; r; r = r->next)
  876. if (r->supers == NULL)
  877. mark_virtual (r);
  878. }
  879. /* Create and return a symbol for a namespace with name NAME. */
  880. struct sym *
  881. make_namespace (name, context)
  882. char *name;
  883. struct sym *context;
  884. {
  885. struct sym *s = (struct sym *) xmalloc (sizeof *s + strlen (name));
  886. bzero (s, sizeof *s);
  887. strcpy (s->name, name);
  888. s->next = all_namespaces;
  889. s->namesp = context;
  890. all_namespaces = s;
  891. return s;
  892. }
  893. /* Find the symbol for namespace NAME. If not found, retrun NULL */
  894. struct sym *
  895. check_namespace (name, context)
  896. char *name;
  897. struct sym *context;
  898. {
  899. struct sym *p = NULL;
  900. for (p = all_namespaces; p; p = p->next)
  901. {
  902. if (streq (p->name, name) && (p->namesp == context))
  903. break;
  904. }
  905. return p;
  906. }
  907. /* Find the symbol for namespace NAME. If not found, add a new symbol
  908. for NAME to all_namespaces. */
  909. struct sym *
  910. find_namespace (name, context)
  911. char *name;
  912. struct sym *context;
  913. {
  914. struct sym *p = check_namespace (name, context);
  915. if (p == NULL)
  916. p = make_namespace (name, context);
  917. return p;
  918. }
  919. /* Find namespace alias with name NAME. If not found return NULL. */
  920. struct link *
  921. check_namespace_alias (name)
  922. char *name;
  923. {
  924. struct link *p = NULL;
  925. struct alias *al;
  926. unsigned h;
  927. char *s;
  928. for (s = name, h = 0; *s; ++s)
  929. h = (h << 1) ^ *s;
  930. h %= TABLE_SIZE;
  931. for (al = namespace_alias_table[h]; al; al = al->next)
  932. if (streq (name, al->name) && (al->namesp == current_namespace))
  933. {
  934. p = al->aliasee;
  935. break;
  936. }
  937. return p;
  938. }
  939. /* Register the name NEW_NAME as an alias for namespace list OLD_NAME. */
  940. void
  941. register_namespace_alias (new_name, old_name)
  942. char *new_name;
  943. struct link *old_name;
  944. {
  945. unsigned h;
  946. char *s;
  947. struct alias *al;
  948. for (s = new_name, h = 0; *s; ++s)
  949. h = (h << 1) ^ *s;
  950. h %= TABLE_SIZE;
  951. /* Is it already in the table of aliases? */
  952. for (al = namespace_alias_table[h]; al; al = al->next)
  953. if (streq (new_name, al->name) && (al->namesp == current_namespace))
  954. return;
  955. al = (struct alias *) xmalloc (sizeof *al + strlen (new_name));
  956. strcpy (al->name, new_name);
  957. al->next = namespace_alias_table[h];
  958. al->namesp = current_namespace;
  959. al->aliasee = old_name;
  960. namespace_alias_table[h] = al;
  961. }
  962. /* Enter namespace with name NAME. */
  963. void
  964. enter_namespace (name)
  965. char *name;
  966. {
  967. struct sym *p = find_namespace (name, current_namespace);
  968. if (namespace_sp == namespace_stack_size)
  969. {
  970. int size = max (10, 2 * namespace_stack_size);
  971. namespace_stack
  972. = (struct sym **) xrealloc ((void *)namespace_stack,
  973. size * sizeof *namespace_stack);
  974. namespace_stack_size = size;
  975. }
  976. namespace_stack[namespace_sp++] = current_namespace;
  977. current_namespace = p;
  978. }
  979. /* Leave the current namespace. */
  980. void
  981. leave_namespace ()
  982. {
  983. assert (namespace_sp > 0);
  984. current_namespace = namespace_stack[--namespace_sp];
  985. }
  986. /***********************************************************************
  987. Writing the Output File
  988. ***********************************************************************/
  989. /* Write string S to the output file FP in a Lisp-readable form.
  990. If S is null, write out `()'. */
  991. #define PUTSTR(s, fp) \
  992. do { \
  993. if (!s) \
  994. { \
  995. putc ('(', fp); \
  996. putc (')', fp); \
  997. putc (' ', fp); \
  998. } \
  999. else \
  1000. { \
  1001. putc ('"', fp); \
  1002. fputs (s, fp); \
  1003. putc ('"', fp); \
  1004. putc (' ', fp); \
  1005. } \
  1006. } while (0)
  1007. /* A dynamically allocated buffer for constructing a scope name. */
  1008. char *scope_buffer;
  1009. int scope_buffer_size;
  1010. int scope_buffer_len;
  1011. /* Make sure scope_buffer has enough room to add LEN chars to it. */
  1012. void
  1013. ensure_scope_buffer_room (len)
  1014. int len;
  1015. {
  1016. if (scope_buffer_len + len >= scope_buffer_size)
  1017. {
  1018. int new_size = max (2 * scope_buffer_size, scope_buffer_len + len);
  1019. scope_buffer = (char *) xrealloc (scope_buffer, new_size);
  1020. scope_buffer_size = new_size;
  1021. }
  1022. }
  1023. /* Recursively add the scope names of symbol P and the scopes of its
  1024. namespaces to scope_buffer. Value is a pointer to the complete
  1025. scope name constructed. */
  1026. char *
  1027. sym_scope_1 (p)
  1028. struct sym *p;
  1029. {
  1030. int len;
  1031. if (p->namesp)
  1032. sym_scope_1 (p->namesp);
  1033. if (*scope_buffer)
  1034. {
  1035. ensure_scope_buffer_room (3);
  1036. strcat (scope_buffer, "::");
  1037. scope_buffer_len += 2;
  1038. }
  1039. len = strlen (p->name);
  1040. ensure_scope_buffer_room (len + 1);
  1041. strcat (scope_buffer, p->name);
  1042. scope_buffer_len += len;
  1043. if (HAS_FLAG (p->flags, F_TEMPLATE))
  1044. {
  1045. ensure_scope_buffer_room (3);
  1046. strcat (scope_buffer, "<>");
  1047. scope_buffer_len += 2;
  1048. }
  1049. return scope_buffer;
  1050. }
  1051. /* Return the scope of symbol P in printed representation, i.e.
  1052. as it would appear in a C*+ source file. */
  1053. char *
  1054. sym_scope (p)
  1055. struct sym *p;
  1056. {
  1057. if (!scope_buffer)
  1058. {
  1059. scope_buffer_size = 1024;
  1060. scope_buffer = (char *) xmalloc (scope_buffer_size);
  1061. }
  1062. *scope_buffer = '\0';
  1063. scope_buffer_len = 0;
  1064. if (p->namesp)
  1065. sym_scope_1 (p->namesp);
  1066. return scope_buffer;
  1067. }
  1068. /* Dump the list of members M to file FP. Value is the length of the
  1069. list. */
  1070. int
  1071. dump_members (fp, m)
  1072. FILE *fp;
  1073. struct member *m;
  1074. {
  1075. int n;
  1076. putc ('(', fp);
  1077. for (n = 0; m; m = m->next, ++n)
  1078. {
  1079. fputs (MEMBER_STRUCT, fp);
  1080. PUTSTR (m->name, fp);
  1081. PUTSTR (NULL, fp); /* FIXME? scope for globals */
  1082. fprintf (fp, "%u ", (unsigned) m->flags);
  1083. PUTSTR (m->filename, fp);
  1084. PUTSTR (m->regexp, fp);
  1085. fprintf (fp, "%u ", (unsigned) m->pos);
  1086. fprintf (fp, "%u ", (unsigned) m->vis);
  1087. putc (' ', fp);
  1088. PUTSTR (m->def_filename, fp);
  1089. PUTSTR (m->def_regexp, fp);
  1090. fprintf (fp, "%u", (unsigned) m->def_pos);
  1091. putc (']', fp);
  1092. putc ('\n', fp);
  1093. }
  1094. putc (')', fp);
  1095. putc ('\n', fp);
  1096. return n;
  1097. }
  1098. /* Dump class ROOT to stream FP. */
  1099. void
  1100. dump_sym (fp, root)
  1101. FILE *fp;
  1102. struct sym *root;
  1103. {
  1104. fputs (CLASS_STRUCT, fp);
  1105. PUTSTR (root->name, fp);
  1106. /* Print scope, if any. */
  1107. if (root->namesp)
  1108. PUTSTR (sym_scope (root), fp);
  1109. else
  1110. PUTSTR (NULL, fp);
  1111. /* Print flags. */
  1112. fprintf (fp, "%u", root->flags);
  1113. PUTSTR (root->filename, fp);
  1114. PUTSTR (root->regexp, fp);
  1115. fprintf (fp, "%u", (unsigned) root->pos);
  1116. PUTSTR (root->sfilename, fp);
  1117. putc (']', fp);
  1118. putc ('\n', fp);
  1119. }
  1120. /* Dump class ROOT and its subclasses to file FP. Value is the
  1121. number of classes written. */
  1122. int
  1123. dump_tree (fp, root)
  1124. FILE *fp;
  1125. struct sym *root;
  1126. {
  1127. struct link *lk;
  1128. unsigned n = 0;
  1129. dump_sym (fp, root);
  1130. if (f_verbose)
  1131. {
  1132. putchar ('+');
  1133. fflush (stdout);
  1134. }
  1135. putc ('(', fp);
  1136. for (lk = root->subs; lk; lk = lk->next)
  1137. {
  1138. fputs (TREE_STRUCT, fp);
  1139. n += dump_tree (fp, lk->sym);
  1140. putc (']', fp);
  1141. }
  1142. putc (')', fp);
  1143. dump_members (fp, root->vars);
  1144. n += dump_members (fp, root->fns);
  1145. dump_members (fp, root->static_vars);
  1146. n += dump_members (fp, root->static_fns);
  1147. n += dump_members (fp, root->friends);
  1148. dump_members (fp, root->types);
  1149. /* Superclasses. */
  1150. putc ('(', fp);
  1151. putc (')', fp);
  1152. /* Mark slot. */
  1153. putc ('(', fp);
  1154. putc (')', fp);
  1155. putc ('\n', fp);
  1156. return n;
  1157. }
  1158. /* Dump the entire class tree to file FP. */
  1159. void
  1160. dump_roots (fp)
  1161. FILE *fp;
  1162. {
  1163. int i, n = 0;
  1164. struct sym *r;
  1165. /* Output file header containing version string, command line
  1166. options etc. */
  1167. if (!f_append)
  1168. {
  1169. fputs (TREE_HEADER_STRUCT, fp);
  1170. PUTSTR (EBROWSE_FILE_VERSION, fp);
  1171. putc ('\"', fp);
  1172. if (!f_structs)
  1173. fputs (" -s", fp);
  1174. if (f_regexps)
  1175. fputs (" -x", fp);
  1176. putc ('\"', fp);
  1177. fputs (" ()", fp);
  1178. fputs (" ()", fp);
  1179. putc (']', fp);
  1180. }
  1181. /* Mark functions as virtual that are so because of functions
  1182. declared virtual in base classes. */
  1183. mark_inherited_virtual ();
  1184. /* Dump the roots of the graph. */
  1185. for (i = 0; i < TABLE_SIZE; ++i)
  1186. for (r = class_table[i]; r; r = r->next)
  1187. if (!r->supers)
  1188. {
  1189. fputs (TREE_STRUCT, fp);
  1190. n += dump_tree (fp, r);
  1191. putc (']', fp);
  1192. }
  1193. if (f_verbose)
  1194. putchar ('\n');
  1195. }
  1196. /***********************************************************************
  1197. Scanner
  1198. ***********************************************************************/
  1199. #ifdef DEBUG
  1200. #define INCREMENT_LINENO \
  1201. do { \
  1202. if (f_very_verbose) \
  1203. { \
  1204. ++yyline; \
  1205. printf ("%d:\n", yyline); \
  1206. } \
  1207. else \
  1208. ++yyline; \
  1209. } while (0)
  1210. #else
  1211. #define INCREMENT_LINENO ++yyline
  1212. #endif
  1213. /* Define two macros for accessing the input buffer (current input
  1214. file). GET(C) sets C to the next input character and advances the
  1215. input pointer. UNGET retracts the input pointer. */
  1216. #define GET(C) ((C) = *in++)
  1217. #define UNGET() (--in)
  1218. /* Process a preprocessor line. Value is the next character from the
  1219. input buffer not consumed. */
  1220. int
  1221. process_pp_line ()
  1222. {
  1223. int in_comment = 0, in_string = 0;
  1224. int c;
  1225. char *p = yytext;
  1226. /* Skip over white space. The `#' has been consumed already. */
  1227. while (WHITEP (GET (c)))
  1228. ;
  1229. /* Read the preprocessor command (if any). */
  1230. while (IDENTP (c))
  1231. {
  1232. *p++ = c;
  1233. GET (c);
  1234. }
  1235. /* Is it a `define'? */
  1236. *p = '\0';
  1237. if (*yytext && streq (yytext, "define"))
  1238. {
  1239. p = yytext;
  1240. while (WHITEP (c))
  1241. GET (c);
  1242. while (IDENTP (c))
  1243. {
  1244. *p++ = c;
  1245. GET (c);
  1246. }
  1247. *p = '\0';
  1248. if (*yytext)
  1249. {
  1250. char *regexp = matching_regexp ();
  1251. int pos = BUFFER_POS ();
  1252. add_define (yytext, regexp, pos);
  1253. }
  1254. }
  1255. while (c && (c != '\n' || in_comment || in_string))
  1256. {
  1257. if (c == '\\')
  1258. GET (c);
  1259. else if (c == '/' && !in_comment)
  1260. {
  1261. if (GET (c) == '*')
  1262. in_comment = 1;
  1263. }
  1264. else if (c == '*' && in_comment)
  1265. {
  1266. if (GET (c) == '/')
  1267. in_comment = 0;
  1268. }
  1269. else if (c == '"')
  1270. in_string = !in_string;
  1271. if (c == '\n')
  1272. INCREMENT_LINENO;
  1273. GET (c);
  1274. }
  1275. return c;
  1276. }
  1277. /* Value is the next token from the input buffer. */
  1278. int
  1279. yylex ()
  1280. {
  1281. int c;
  1282. char end_char;
  1283. char *p;
  1284. for (;;)
  1285. {
  1286. while (WHITEP (GET (c)))
  1287. ;
  1288. switch (c)
  1289. {
  1290. case '\n':
  1291. INCREMENT_LINENO;
  1292. break;
  1293. case '\r':
  1294. break;
  1295. case 0:
  1296. /* End of file. */
  1297. return YYEOF;
  1298. case '\\':
  1299. GET (c);
  1300. break;
  1301. case '"':
  1302. case '\'':
  1303. /* String and character constants. */
  1304. end_char = c;
  1305. string_start = in;
  1306. while (GET (c) && c != end_char)
  1307. {
  1308. switch (c)
  1309. {
  1310. case '\\':
  1311. /* Escape sequences. */
  1312. if (!GET (c))
  1313. {
  1314. if (end_char == '\'')
  1315. yyerror ("EOF in character constant", NULL);
  1316. else
  1317. yyerror ("EOF in string constant", NULL);
  1318. goto end_string;
  1319. }
  1320. else switch (c)
  1321. {
  1322. case '\n':
  1323. INCREMENT_LINENO;
  1324. case 'a':
  1325. case 'b':
  1326. case 'f':
  1327. case 'n':
  1328. case 'r':
  1329. case 't':
  1330. case 'v':
  1331. break;
  1332. case 'x':
  1333. {
  1334. /* Hexadecimal escape sequence. */
  1335. int i;
  1336. for (i = 0; i < 2; ++i)
  1337. {
  1338. GET (c);
  1339. if (c >= '0' && c <= '7')
  1340. ;
  1341. else if (c >= 'a' && c <= 'f')
  1342. ;
  1343. else if (c >= 'A' && c <= 'F')
  1344. ;
  1345. else
  1346. {
  1347. UNGET ();
  1348. break;
  1349. }
  1350. }
  1351. }
  1352. break;
  1353. case '0':
  1354. {
  1355. /* Octal escape sequence. */
  1356. int i;
  1357. for (i = 0; i < 3; ++i)
  1358. {
  1359. GET (c);
  1360. if (c >= '0' && c <= '7')
  1361. ;
  1362. else
  1363. {
  1364. UNGET ();
  1365. break;
  1366. }
  1367. }
  1368. }
  1369. break;
  1370. default:
  1371. break;
  1372. }
  1373. break;
  1374. case '\n':
  1375. if (end_char == '\'')
  1376. yyerror ("newline in character constant", NULL);
  1377. else
  1378. yyerror ("newline in string constant", NULL);
  1379. INCREMENT_LINENO;
  1380. break;
  1381. default:
  1382. break;
  1383. }
  1384. }
  1385. end_string:
  1386. return end_char == '\'' ? CCHAR : CSTRING;
  1387. case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
  1388. case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
  1389. case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
  1390. case 'v': case 'w': case 'x': case 'y': case 'z':
  1391. case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
  1392. case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
  1393. case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
  1394. case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_':
  1395. {
  1396. /* Identifier and keywords. */
  1397. unsigned hash;
  1398. struct kw *k;
  1399. p = yytext;
  1400. *p++ = hash = c;
  1401. while (IDENTP (GET (*p)))
  1402. {
  1403. hash = (hash << 1) ^ *p++;
  1404. if (p == yytext_end - 1)
  1405. {
  1406. int size = yytext_end - yytext;
  1407. yytext = (char *) xrealloc (yytext, 2 * size);
  1408. yytext_end = yytext + 2 * size;
  1409. p = yytext + size - 1;
  1410. }
  1411. }
  1412. UNGET ();
  1413. *p = 0;
  1414. for (k = keyword_table[hash % KEYWORD_TABLE_SIZE]; k; k = k->next)
  1415. if (streq (k->name, yytext))
  1416. return k->tk;
  1417. return IDENT;
  1418. }
  1419. case '/':
  1420. /* C and C++ comments, '/' and '/='. */
  1421. switch (GET (c))
  1422. {
  1423. case '*':
  1424. while (GET (c))
  1425. {
  1426. switch (c)
  1427. {
  1428. case '*':
  1429. if (GET (c) == '/')
  1430. goto comment_end;
  1431. UNGET ();
  1432. break;
  1433. case '\\':
  1434. GET (c);
  1435. break;
  1436. case '\n':
  1437. INCREMENT_LINENO;
  1438. break;
  1439. }
  1440. }
  1441. comment_end:;
  1442. break;
  1443. case '=':
  1444. return DIVASGN;
  1445. case '/':
  1446. while (GET (c) && c != '\n')
  1447. ;
  1448. INCREMENT_LINENO;
  1449. break;
  1450. default:
  1451. UNGET ();
  1452. return '/';
  1453. }
  1454. break;
  1455. case '+':
  1456. if (GET (c) == '+')
  1457. return INC;
  1458. else if (c == '=')
  1459. return ADDASGN;
  1460. UNGET ();
  1461. return '+';
  1462. case '-':
  1463. switch (GET (c))
  1464. {
  1465. case '-':
  1466. return DEC;
  1467. case '>':
  1468. if (GET (c) == '*')
  1469. return ARROWSTAR;
  1470. UNGET ();
  1471. return ARROW;
  1472. case '=':
  1473. return SUBASGN;
  1474. }
  1475. UNGET ();
  1476. return '-';
  1477. case '*':
  1478. if (GET (c) == '=')
  1479. return MULASGN;
  1480. UNGET ();
  1481. return '*';
  1482. case '%':
  1483. if (GET (c) == '=')
  1484. return MODASGN;
  1485. UNGET ();
  1486. return '%';
  1487. case '|':
  1488. if (GET (c) == '|')
  1489. return LOR;
  1490. else if (c == '=')
  1491. return ORASGN;
  1492. UNGET ();
  1493. return '|';
  1494. case '&':
  1495. if (GET (c) == '&')
  1496. return LAND;
  1497. else if (c == '=')
  1498. return ANDASGN;
  1499. UNGET ();
  1500. return '&';
  1501. case '^':
  1502. if (GET (c) == '=')
  1503. return XORASGN;
  1504. UNGET ();
  1505. return '^';
  1506. case '.':
  1507. if (GET (c) == '*')
  1508. return POINTSTAR;
  1509. else if (c == '.')
  1510. {
  1511. if (GET (c) != '.')
  1512. yyerror ("invalid token '..' ('...' assumed)", NULL);
  1513. UNGET ();
  1514. return ELLIPSIS;
  1515. }
  1516. else if (!DIGITP (c))
  1517. {
  1518. UNGET ();
  1519. return '.';
  1520. }
  1521. goto mantissa;
  1522. case ':':
  1523. if (GET (c) == ':')
  1524. return DCOLON;
  1525. UNGET ();
  1526. return ':';
  1527. case '=':
  1528. if (GET (c) == '=')
  1529. return EQ;
  1530. UNGET ();
  1531. return '=';
  1532. case '!':
  1533. if (GET (c) == '=')
  1534. return NE;
  1535. UNGET ();
  1536. return '!';
  1537. case '<':
  1538. switch (GET (c))
  1539. {
  1540. case '=':
  1541. return LE;
  1542. case '<':
  1543. if (GET (c) == '=')
  1544. return LSHIFTASGN;
  1545. UNGET ();
  1546. return LSHIFT;
  1547. }
  1548. UNGET ();
  1549. return '<';
  1550. case '>':
  1551. switch (GET (c))
  1552. {
  1553. case '=':
  1554. return GE;
  1555. case '>':
  1556. if (GET (c) == '=')
  1557. return RSHIFTASGN;
  1558. UNGET ();
  1559. return RSHIFT;
  1560. }
  1561. UNGET ();
  1562. return '>';
  1563. case '#':
  1564. c = process_pp_line ();
  1565. if (c == 0)
  1566. return YYEOF;
  1567. break;
  1568. case '(': case ')': case '[': case ']': case '{': case '}':
  1569. case ';': case ',': case '?': case '~':
  1570. return c;
  1571. case '0':
  1572. yyival = 0;
  1573. if (GET (c) == 'x' || c == 'X')
  1574. {
  1575. while (GET (c))
  1576. {
  1577. if (DIGITP (c))
  1578. yyival = yyival * 16 + c - '0';
  1579. else if (c >= 'a' && c <= 'f')
  1580. yyival = yyival * 16 + c - 'a' + 10;
  1581. else if (c >= 'A' && c <= 'F')
  1582. yyival = yyival * 16 + c - 'A' + 10;
  1583. else
  1584. break;
  1585. }
  1586. goto int_suffixes;
  1587. }
  1588. else if (c == '.')
  1589. goto mantissa;
  1590. while (c >= '0' && c <= '7')
  1591. {
  1592. yyival = (yyival << 3) + c - '0';
  1593. GET (c);
  1594. }
  1595. int_suffixes:
  1596. /* Integer suffixes. */
  1597. while (isalpha (c))
  1598. GET (c);
  1599. UNGET ();
  1600. return CINT;
  1601. case '1': case '2': case '3': case '4': case '5': case '6':
  1602. case '7': case '8': case '9':
  1603. /* Integer or floating constant, part before '.'. */
  1604. yyival = c - '0';
  1605. while (GET (c) && DIGITP (c))
  1606. yyival = 10 * yyival + c - '0';
  1607. if (c != '.')
  1608. goto int_suffixes;
  1609. mantissa:
  1610. /* Digits following '.'. */
  1611. while (DIGITP (c))
  1612. GET (c);
  1613. /* Optional exponent. */
  1614. if (c == 'E' || c == 'e')
  1615. {
  1616. if (GET (c) == '-' || c == '+')
  1617. GET (c);
  1618. while (DIGITP (c))
  1619. GET (c);
  1620. }
  1621. /* Optional type suffixes. */
  1622. while (isalpha (c))
  1623. GET (c);
  1624. UNGET ();
  1625. return CFLOAT;
  1626. default:
  1627. break;
  1628. }
  1629. }
  1630. }
  1631. /* Actually local to matching_regexp. These variables must be in
  1632. global scope for the case that `static' get's defined away. */
  1633. static char *matching_regexp_buffer, *matching_regexp_end_buf;
  1634. /* Value is the string from the start of the line to the current
  1635. position in the input buffer, or maybe a bit more if that string is
  1636. shorter than min_regexp. */
  1637. char *
  1638. matching_regexp ()
  1639. {
  1640. char *p;
  1641. char *s;
  1642. char *t;
  1643. if (!f_regexps)
  1644. return NULL;
  1645. if (matching_regexp_buffer == NULL)
  1646. {
  1647. matching_regexp_buffer = (char *) xmalloc (max_regexp);
  1648. matching_regexp_end_buf = &matching_regexp_buffer[max_regexp] - 1;
  1649. }
  1650. /* Scan back to previous newline of buffer start. */
  1651. for (p = in - 1; p > inbuffer && *p != '\n'; --p)
  1652. ;
  1653. if (*p == '\n')
  1654. {
  1655. while (in - p < min_regexp && p > inbuffer)
  1656. {
  1657. /* Line probably not significant enough */
  1658. for (--p; p > inbuffer && *p != '\n'; --p)
  1659. ;
  1660. }
  1661. if (*p == '\n')
  1662. ++p;
  1663. }
  1664. /* Copy from end to make sure significant portions are included.
  1665. This implies that in the browser a regular expressing of the form
  1666. `^.*{regexp}' has to be used. */
  1667. for (s = matching_regexp_end_buf - 1, t = in;
  1668. s > matching_regexp_buffer && t > p;)
  1669. {
  1670. *--s = *--t;
  1671. if (*s == '"' || *s == '\\')
  1672. *--s = '\\';
  1673. }
  1674. *(matching_regexp_end_buf - 1) = '\0';
  1675. return xstrdup (s);
  1676. }
  1677. /* Return a printable representation of token T. */
  1678. char *
  1679. token_string (t)
  1680. int t;
  1681. {
  1682. static char b[3];
  1683. switch (t)
  1684. {
  1685. case CSTRING: return "string constant";
  1686. case CCHAR: return "char constant";
  1687. case CINT: return "int constant";
  1688. case CFLOAT: return "floating constant";
  1689. case ELLIPSIS: return "...";
  1690. case LSHIFTASGN: return "<<=";
  1691. case RSHIFTASGN: return ">>=";
  1692. case ARROWSTAR: return "->*";
  1693. case IDENT: return "identifier";
  1694. case DIVASGN: return "/=";
  1695. case INC: return "++";
  1696. case ADDASGN: return "+=";
  1697. case DEC: return "--";
  1698. case ARROW: return "->";
  1699. case SUBASGN: return "-=";
  1700. case MULASGN: return "*=";
  1701. case MODASGN: return "%=";
  1702. case LOR: return "||";
  1703. case ORASGN: return "|=";
  1704. case LAND: return "&&";
  1705. case ANDASGN: return "&=";
  1706. case XORASGN: return "^=";
  1707. case POINTSTAR: return ".*";
  1708. case DCOLON: return "::";
  1709. case EQ: return "==";
  1710. case NE: return "!=";
  1711. case LE: return "<=";
  1712. case LSHIFT: return "<<";
  1713. case GE: return ">=";
  1714. case RSHIFT: return ">>";
  1715. case ASM: return "asm";
  1716. case AUTO: return "auto";
  1717. case BREAK: return "break";
  1718. case CASE: return "case";
  1719. case CATCH: return "catch";
  1720. case CHAR: return "char";
  1721. case CLASS: return "class";
  1722. case CONST: return "const";
  1723. case CONTINUE: return "continue";
  1724. case DEFAULT: return "default";
  1725. case DELETE: return "delete";
  1726. case DO: return "do";
  1727. case DOUBLE: return "double";
  1728. case ELSE: return "else";
  1729. case ENUM: return "enum";
  1730. case EXTERN: return "extern";
  1731. case FLOAT: return "float";
  1732. case FOR: return "for";
  1733. case FRIEND: return "friend";
  1734. case GOTO: return "goto";
  1735. case IF: return "if";
  1736. case T_INLINE: return "inline";
  1737. case INT: return "int";
  1738. case LONG: return "long";
  1739. case NEW: return "new";
  1740. case OPERATOR: return "operator";
  1741. case PRIVATE: return "private";
  1742. case PROTECTED: return "protected";
  1743. case PUBLIC: return "public";
  1744. case REGISTER: return "register";
  1745. case RETURN: return "return";
  1746. case SHORT: return "short";
  1747. case SIGNED: return "signed";
  1748. case SIZEOF: return "sizeof";
  1749. case STATIC: return "static";
  1750. case STRUCT: return "struct";
  1751. case SWITCH: return "switch";
  1752. case TEMPLATE: return "template";
  1753. case THIS: return "this";
  1754. case THROW: return "throw";
  1755. case TRY: return "try";
  1756. case TYPEDEF: return "typedef";
  1757. case UNION: return "union";
  1758. case UNSIGNED: return "unsigned";
  1759. case VIRTUAL: return "virtual";
  1760. case VOID: return "void";
  1761. case VOLATILE: return "volatile";
  1762. case WHILE: return "while";
  1763. case MUTABLE: return "mutable";
  1764. case BOOL: return "bool";
  1765. case TRUE: return "true";
  1766. case FALSE: return "false";
  1767. case SIGNATURE: return "signature";
  1768. case NAMESPACE: return "namespace";
  1769. case EXPLICIT: return "explicit";
  1770. case TYPENAME: return "typename";
  1771. case CONST_CAST: return "const_cast";
  1772. case DYNAMIC_CAST: return "dynamic_cast";
  1773. case REINTERPRET_CAST: return "reinterpret_cast";
  1774. case STATIC_CAST: return "static_cast";
  1775. case TYPEID: return "typeid";
  1776. case USING: return "using";
  1777. case WCHAR: return "wchar_t";
  1778. case YYEOF: return "EOF";
  1779. default:
  1780. if (t < 255)
  1781. {
  1782. b[0] = t;
  1783. b[1] = '\0';
  1784. return b;
  1785. }
  1786. else
  1787. return "???";
  1788. }
  1789. }
  1790. /* Reinitialize the scanner for a new input file. */
  1791. void
  1792. re_init_scanner ()
  1793. {
  1794. in = inbuffer;
  1795. yyline = 1;
  1796. if (yytext == NULL)
  1797. {
  1798. int size = 256;
  1799. yytext = (char *) xmalloc (size * sizeof *yytext);
  1800. yytext_end = yytext + size;
  1801. }
  1802. }
  1803. /* Insert a keyword NAME with token value TK into the keyword hash
  1804. table. */
  1805. void
  1806. insert_keyword (name, tk)
  1807. char *name;
  1808. int tk;
  1809. {
  1810. char *s;
  1811. unsigned h = 0;
  1812. struct kw *k = (struct kw *) xmalloc (sizeof *k);
  1813. for (s = name; *s; ++s)
  1814. h = (h << 1) ^ *s;
  1815. h %= KEYWORD_TABLE_SIZE;
  1816. k->name = name;
  1817. k->tk = tk;
  1818. k->next = keyword_table[h];
  1819. keyword_table[h] = k;
  1820. }
  1821. /* Initialize the scanner for the first file. This sets up the
  1822. character class vectors and fills the keyword hash table. */
  1823. void
  1824. init_scanner ()
  1825. {
  1826. int i;
  1827. /* Allocate the input buffer */
  1828. inbuffer_size = READ_CHUNK_SIZE + 1;
  1829. inbuffer = in = (char *) xmalloc (inbuffer_size);
  1830. yyline = 1;
  1831. /* Set up character class vectors. */
  1832. for (i = 0; i < sizeof is_ident; ++i)
  1833. {
  1834. if (i == '_' || isalnum (i))
  1835. is_ident[i] = 1;
  1836. if (i >= '0' && i <= '9')
  1837. is_digit[i] = 1;
  1838. if (i == ' ' || i == '\t' || i == '\f' || i == '\v')
  1839. is_white[i] = 1;
  1840. }
  1841. /* Fill keyword hash table. */
  1842. insert_keyword ("and", LAND);
  1843. insert_keyword ("and_eq", ANDASGN);
  1844. insert_keyword ("asm", ASM);
  1845. insert_keyword ("auto", AUTO);
  1846. insert_keyword ("bitand", '&');
  1847. insert_keyword ("bitor", '|');
  1848. insert_keyword ("bool", BOOL);
  1849. insert_keyword ("break", BREAK);
  1850. insert_keyword ("case", CASE);
  1851. insert_keyword ("catch", CATCH);
  1852. insert_keyword ("char", CHAR);
  1853. insert_keyword ("class", CLASS);
  1854. insert_keyword ("compl", '~');
  1855. insert_keyword ("const", CONST);
  1856. insert_keyword ("const_cast", CONST_CAST);
  1857. insert_keyword ("continue", CONTINUE);
  1858. insert_keyword ("default", DEFAULT);
  1859. insert_keyword ("delete", DELETE);
  1860. insert_keyword ("do", DO);
  1861. insert_keyword ("double", DOUBLE);
  1862. insert_keyword ("dynamic_cast", DYNAMIC_CAST);
  1863. insert_keyword ("else", ELSE);
  1864. insert_keyword ("enum", ENUM);
  1865. insert_keyword ("explicit", EXPLICIT);
  1866. insert_keyword ("extern", EXTERN);
  1867. insert_keyword ("false", FALSE);
  1868. insert_keyword ("float", FLOAT);
  1869. insert_keyword ("for", FOR);
  1870. insert_keyword ("friend", FRIEND);
  1871. insert_keyword ("goto", GOTO);
  1872. insert_keyword ("if", IF);
  1873. insert_keyword ("inline", T_INLINE);
  1874. insert_keyword ("int", INT);
  1875. insert_keyword ("long", LONG);
  1876. insert_keyword ("mutable", MUTABLE);
  1877. insert_keyword ("namespace", NAMESPACE);
  1878. insert_keyword ("new", NEW);
  1879. insert_keyword ("not", '!');
  1880. insert_keyword ("not_eq", NE);
  1881. insert_keyword ("operator", OPERATOR);
  1882. insert_keyword ("or", LOR);
  1883. insert_keyword ("or_eq", ORASGN);
  1884. insert_keyword ("private", PRIVATE);
  1885. insert_keyword ("protected", PROTECTED);
  1886. insert_keyword ("public", PUBLIC);
  1887. insert_keyword ("register", REGISTER);
  1888. insert_keyword ("reinterpret_cast", REINTERPRET_CAST);
  1889. insert_keyword ("return", RETURN);
  1890. insert_keyword ("short", SHORT);
  1891. insert_keyword ("signed", SIGNED);
  1892. insert_keyword ("sizeof", SIZEOF);
  1893. insert_keyword ("static", STATIC);
  1894. insert_keyword ("static_cast", STATIC_CAST);
  1895. insert_keyword ("struct", STRUCT);
  1896. insert_keyword ("switch", SWITCH);
  1897. insert_keyword ("template", TEMPLATE);
  1898. insert_keyword ("this", THIS);
  1899. insert_keyword ("throw", THROW);
  1900. insert_keyword ("true", TRUE);
  1901. insert_keyword ("try", TRY);
  1902. insert_keyword ("typedef", TYPEDEF);
  1903. insert_keyword ("typeid", TYPEID);
  1904. insert_keyword ("typename", TYPENAME);
  1905. insert_keyword ("union", UNION);
  1906. insert_keyword ("unsigned", UNSIGNED);
  1907. insert_keyword ("using", USING);
  1908. insert_keyword ("virtual", VIRTUAL);
  1909. insert_keyword ("void", VOID);
  1910. insert_keyword ("volatile", VOLATILE);
  1911. insert_keyword ("wchar_t", WCHAR);
  1912. insert_keyword ("while", WHILE);
  1913. insert_keyword ("xor", '^');
  1914. insert_keyword ("xor_eq", XORASGN);
  1915. }
  1916. /***********************************************************************
  1917. Parser
  1918. ***********************************************************************/
  1919. /* Match the current lookahead token and set it to the next token. */
  1920. #define MATCH() (tk = yylex ())
  1921. /* Return the lookahead token. If current lookahead token is cleared,
  1922. read a new token. */
  1923. #define LA1 (tk == -1 ? (tk = yylex ()) : tk)
  1924. /* Is the current lookahead equal to the token T? */
  1925. #define LOOKING_AT(T) (tk == (T))
  1926. /* Is the current lookahead one of T1 or T2? */
  1927. #define LOOKING_AT2(T1, T2) (tk == (T1) || tk == (T2))
  1928. /* Is the current lookahead one of T1, T2 or T3? */
  1929. #define LOOKING_AT3(T1, T2, T3) (tk == (T1) || tk == (T2) || tk == (T3))
  1930. /* Is the current lookahead one of T1...T4? */
  1931. #define LOOKING_AT4(T1, T2, T3, T4) \
  1932. (tk == (T1) || tk == (T2) || tk == (T3) || tk == (T4))
  1933. /* Match token T if current lookahead is T. */
  1934. #define MATCH_IF(T) if (LOOKING_AT (T)) MATCH (); else ((void) 0)
  1935. /* Skip to matching token if current token is T. */
  1936. #define SKIP_MATCHING_IF(T) \
  1937. if (LOOKING_AT (T)) skip_matching (); else ((void) 0)
  1938. /* Skip forward until a given token TOKEN or YYEOF is seen and return
  1939. the current lookahead token after skipping. */
  1940. int
  1941. skip_to (token)
  1942. int token;
  1943. {
  1944. while (!LOOKING_AT2 (YYEOF, token))
  1945. MATCH ();
  1946. return tk;
  1947. }
  1948. /* Skip over pairs of tokens (parentheses, square brackets,
  1949. angle brackets, curly brackets) matching the current lookahead. */
  1950. void
  1951. skip_matching ()
  1952. {
  1953. int open, close, n;
  1954. switch (open = LA1)
  1955. {
  1956. case '{':
  1957. close = '}';
  1958. break;
  1959. case '(':
  1960. close = ')';
  1961. break;
  1962. case '<':
  1963. close = '>';
  1964. break;
  1965. case '[':
  1966. close = ']';
  1967. break;
  1968. default:
  1969. abort ();
  1970. }
  1971. for (n = 0;;)
  1972. {
  1973. if (LOOKING_AT (open))
  1974. ++n;
  1975. else if (LOOKING_AT (close))
  1976. --n;
  1977. else if (LOOKING_AT (YYEOF))
  1978. break;
  1979. MATCH ();
  1980. if (n == 0)
  1981. break;
  1982. }
  1983. }
  1984. void
  1985. skip_initializer ()
  1986. {
  1987. for (;;)
  1988. {
  1989. switch (LA1)
  1990. {
  1991. case ';':
  1992. case ',':
  1993. case YYEOF:
  1994. return;
  1995. case '{':
  1996. case '[':
  1997. case '(':
  1998. skip_matching ();
  1999. break;
  2000. default:
  2001. MATCH ();
  2002. break;
  2003. }
  2004. }
  2005. }
  2006. /* Build qualified namespace alias (A::B::c) and return it. */
  2007. struct link *
  2008. match_qualified_namespace_alias ()
  2009. {
  2010. struct link *head = NULL;
  2011. struct link *cur = NULL;
  2012. struct link *tmp = NULL;
  2013. for (;;)
  2014. {
  2015. MATCH ();
  2016. switch (LA1)
  2017. {
  2018. case IDENT:
  2019. tmp = (struct link *) xmalloc (sizeof *cur);
  2020. tmp->sym = find_namespace (yytext, cur);
  2021. tmp->next = NULL;
  2022. if (head)
  2023. {
  2024. cur = cur->next = tmp;
  2025. }
  2026. else
  2027. {
  2028. head = cur = tmp;
  2029. }
  2030. break;
  2031. case DCOLON:
  2032. /* Just skip */
  2033. break;
  2034. default:
  2035. return head;
  2036. break;
  2037. }
  2038. }
  2039. }
  2040. /* Re-initialize the parser by resetting the lookahead token. */
  2041. void
  2042. re_init_parser ()
  2043. {
  2044. tk = -1;
  2045. }
  2046. /* Parse a parameter list, including the const-specifier,
  2047. pure-specifier, and throw-list that may follow a parameter list.
  2048. Return in FLAGS what was seen following the parameter list.
  2049. Returns a hash code for the parameter types. This value is used to
  2050. distinguish between overloaded functions. */
  2051. unsigned
  2052. parm_list (flags)
  2053. int *flags;
  2054. {
  2055. unsigned hash = 0;
  2056. int type_seen = 0;
  2057. while (!LOOKING_AT2 (YYEOF, ')'))
  2058. {
  2059. switch (LA1)
  2060. {
  2061. /* Skip over grouping parens or parameter lists in parameter
  2062. declarations. */
  2063. case '(':
  2064. skip_matching ();
  2065. break;
  2066. /* Next parameter. */
  2067. case ',':
  2068. MATCH ();
  2069. type_seen = 0;
  2070. break;
  2071. /* Ignore the scope part of types, if any. This is because
  2072. some types need scopes when defined outside of a class body,
  2073. and don't need them inside the class body. This means that
  2074. we have to look for the last IDENT in a sequence of
  2075. IDENT::IDENT::... */
  2076. case IDENT:
  2077. if (!type_seen)
  2078. {
  2079. char *last_id;
  2080. unsigned ident_type_hash = 0;
  2081. parse_qualified_param_ident_or_type (&last_id);
  2082. if (last_id)
  2083. {
  2084. /* LAST_ID null means something like `X::*'. */
  2085. for (; *last_id; ++last_id)
  2086. ident_type_hash = (ident_type_hash << 1) ^ *last_id;
  2087. hash = (hash << 1) ^ ident_type_hash;
  2088. type_seen = 1;
  2089. }
  2090. }
  2091. else
  2092. MATCH ();
  2093. break;
  2094. case VOID:
  2095. /* This distinction is made to make `func (void)' equivalent
  2096. to `func ()'. */
  2097. type_seen = 1;
  2098. MATCH ();
  2099. if (!LOOKING_AT (')'))
  2100. hash = (hash << 1) ^ VOID;
  2101. break;
  2102. case BOOL: case CHAR: case CLASS: case CONST:
  2103. case DOUBLE: case ENUM: case FLOAT: case INT:
  2104. case LONG: case SHORT: case SIGNED: case STRUCT:
  2105. case UNION: case UNSIGNED: case VOLATILE: case WCHAR:
  2106. case ELLIPSIS:
  2107. type_seen = 1;
  2108. hash = (hash << 1) ^ LA1;
  2109. MATCH ();
  2110. break;
  2111. case '*': case '&': case '[': case ']':
  2112. hash = (hash << 1) ^ LA1;
  2113. MATCH ();
  2114. break;
  2115. default:
  2116. MATCH ();
  2117. break;
  2118. }
  2119. }
  2120. if (LOOKING_AT (')'))
  2121. {
  2122. MATCH ();
  2123. if (LOOKING_AT (CONST))
  2124. {
  2125. /* We can overload the same function on `const' */
  2126. hash = (hash << 1) ^ CONST;
  2127. SET_FLAG (*flags, F_CONST);
  2128. MATCH ();
  2129. }
  2130. if (LOOKING_AT (THROW))
  2131. {
  2132. MATCH ();
  2133. SKIP_MATCHING_IF ('(');
  2134. SET_FLAG (*flags, F_THROW);
  2135. }
  2136. if (LOOKING_AT ('='))
  2137. {
  2138. MATCH ();
  2139. if (LOOKING_AT (CINT) && yyival == 0)
  2140. {
  2141. MATCH ();
  2142. SET_FLAG (*flags, F_PURE);
  2143. }
  2144. }
  2145. }
  2146. return hash;
  2147. }
  2148. /* Print position info to stdout. */
  2149. void
  2150. print_info ()
  2151. {
  2152. if (info_position >= 0 && BUFFER_POS () <= info_position)
  2153. if (info_cls)
  2154. printf ("(\"%s\" \"%s\" \"%s\" %d)\n",
  2155. info_cls->name, sym_scope (info_cls),
  2156. info_member->name, info_where);
  2157. }
  2158. /* Parse a member declaration within the class body of CLS. VIS is
  2159. the access specifier for the member (private, protected,
  2160. public). */
  2161. void
  2162. member (cls, vis)
  2163. struct sym *cls;
  2164. int vis;
  2165. {
  2166. char *id = NULL;
  2167. int sc = SC_MEMBER;
  2168. char *regexp = NULL;
  2169. int pos;
  2170. int is_constructor;
  2171. int anonymous = 0;
  2172. int flags = 0;
  2173. int class_tag;
  2174. int type_seen = 0;
  2175. int paren_seen = 0;
  2176. unsigned hash = 0;
  2177. int tilde = 0;
  2178. while (!LOOKING_AT4 (';', '{', '}', YYEOF))
  2179. {
  2180. switch (LA1)
  2181. {
  2182. default:
  2183. MATCH ();
  2184. break;
  2185. /* A function or class may follow. */
  2186. case TEMPLATE:
  2187. MATCH();
  2188. SET_FLAG (flags, F_TEMPLATE);
  2189. /* Skip over template argument list */
  2190. SKIP_MATCHING_IF ('<');
  2191. break;
  2192. case EXPLICIT:
  2193. SET_FLAG (flags, F_EXPLICIT);
  2194. goto typeseen;
  2195. case MUTABLE:
  2196. SET_FLAG (flags, F_MUTABLE);
  2197. goto typeseen;
  2198. case T_INLINE:
  2199. SET_FLAG (flags, F_INLINE);
  2200. goto typeseen;
  2201. case VIRTUAL:
  2202. SET_FLAG (flags, F_VIRTUAL);
  2203. goto typeseen;
  2204. case '[':
  2205. skip_matching ();
  2206. break;
  2207. case ENUM:
  2208. sc = SC_TYPE;
  2209. goto typeseen;
  2210. case TYPEDEF:
  2211. sc = SC_TYPE;
  2212. goto typeseen;
  2213. case FRIEND:
  2214. sc = SC_FRIEND;
  2215. goto typeseen;
  2216. case STATIC:
  2217. sc = SC_STATIC;
  2218. goto typeseen;
  2219. case '~':
  2220. tilde = 1;
  2221. MATCH ();
  2222. break;
  2223. case IDENT:
  2224. /* Remember IDENTS seen so far. Among these will be the member
  2225. name. */
  2226. id = (char *) xrealloc (id, strlen (yytext) + 2);
  2227. if (tilde)
  2228. {
  2229. *id = '~';
  2230. strcpy (id + 1, yytext);
  2231. }
  2232. else
  2233. strcpy (id, yytext);
  2234. MATCH ();
  2235. break;
  2236. case OPERATOR:
  2237. {
  2238. char *s = operator_name (&sc);
  2239. id = (char *) xrealloc (id, strlen (s) + 1);
  2240. strcpy (id, s);
  2241. }
  2242. break;
  2243. case '(':
  2244. /* Most probably the beginning of a parameter list. */
  2245. MATCH ();
  2246. paren_seen = 1;
  2247. if (id && cls)
  2248. {
  2249. if (!(is_constructor = streq (id, cls->name)))
  2250. regexp = matching_regexp ();
  2251. }
  2252. else
  2253. is_constructor = 0;
  2254. pos = BUFFER_POS ();
  2255. hash = parm_list (&flags);
  2256. if (is_constructor)
  2257. regexp = matching_regexp ();
  2258. if (id && cls != NULL)
  2259. add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, flags);
  2260. while (!LOOKING_AT3 (';', '{', YYEOF))
  2261. MATCH ();
  2262. if (LOOKING_AT ('{') && id && cls)
  2263. add_member_defn (cls, id, regexp, pos, hash, 0, sc, flags);
  2264. free (id);
  2265. id = NULL;
  2266. sc = SC_MEMBER;
  2267. break;
  2268. case STRUCT: case UNION: case CLASS:
  2269. /* Nested class */
  2270. class_tag = LA1;
  2271. type_seen = 1;
  2272. MATCH ();
  2273. anonymous = 1;
  2274. /* More than one ident here to allow for MS-DOS specialties
  2275. like `_export class' etc. The last IDENT seen counts
  2276. as the class name. */
  2277. while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
  2278. {
  2279. if (LOOKING_AT (IDENT))
  2280. anonymous = 0;
  2281. MATCH ();
  2282. }
  2283. if (LOOKING_AT2 (':', '{'))
  2284. class_definition (anonymous ? NULL : cls, class_tag, flags, 1);
  2285. else
  2286. skip_to (';');
  2287. break;
  2288. case INT: case CHAR: case LONG: case UNSIGNED:
  2289. case SIGNED: case CONST: case DOUBLE: case VOID:
  2290. case SHORT: case VOLATILE: case BOOL: case WCHAR:
  2291. case TYPENAME:
  2292. typeseen:
  2293. type_seen = 1;
  2294. MATCH ();
  2295. break;
  2296. }
  2297. }
  2298. if (LOOKING_AT (';'))
  2299. {
  2300. /* The end of a member variable, a friend declaration or an access
  2301. declaration. We don't want to add friend classes as members. */
  2302. if (id && sc != SC_FRIEND && cls)
  2303. {
  2304. regexp = matching_regexp ();
  2305. pos = BUFFER_POS ();
  2306. if (cls != NULL)
  2307. {
  2308. if (type_seen || !paren_seen)
  2309. add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
  2310. else
  2311. add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, 0);
  2312. }
  2313. }
  2314. MATCH ();
  2315. print_info ();
  2316. }
  2317. else if (LOOKING_AT ('{'))
  2318. {
  2319. /* A named enum. */
  2320. if (sc == SC_TYPE && id && cls)
  2321. {
  2322. regexp = matching_regexp ();
  2323. pos = BUFFER_POS ();
  2324. if (cls != NULL)
  2325. {
  2326. add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
  2327. add_member_defn (cls, id, regexp, pos, 0, 1, sc, 0);
  2328. }
  2329. }
  2330. skip_matching ();
  2331. print_info ();
  2332. }
  2333. free (id);
  2334. }
  2335. /* Parse the body of class CLS. TAG is the tag of the class (struct,
  2336. union, class). */
  2337. void
  2338. class_body (cls, tag)
  2339. struct sym *cls;
  2340. int tag;
  2341. {
  2342. int vis = tag == CLASS ? PRIVATE : PUBLIC;
  2343. int temp;
  2344. while (!LOOKING_AT2 (YYEOF, '}'))
  2345. {
  2346. switch (LA1)
  2347. {
  2348. case PRIVATE: case PROTECTED: case PUBLIC:
  2349. temp = LA1;
  2350. MATCH ();
  2351. if (LOOKING_AT (':'))
  2352. {
  2353. vis = temp;
  2354. MATCH ();
  2355. }
  2356. else
  2357. {
  2358. /* Probably conditional compilation for inheritance list.
  2359. We don't known whether there comes more of this.
  2360. This is only a crude fix that works most of the time. */
  2361. do
  2362. {
  2363. MATCH ();
  2364. }
  2365. while (LOOKING_AT2 (IDENT, ',')
  2366. || LOOKING_AT3 (PUBLIC, PROTECTED, PRIVATE));
  2367. }
  2368. break;
  2369. case TYPENAME:
  2370. case USING:
  2371. skip_to (';');
  2372. break;
  2373. /* Try to synchronize */
  2374. case CHAR: case CLASS: case CONST:
  2375. case DOUBLE: case ENUM: case FLOAT: case INT:
  2376. case LONG: case SHORT: case SIGNED: case STRUCT:
  2377. case UNION: case UNSIGNED: case VOID: case VOLATILE:
  2378. case TYPEDEF: case STATIC: case T_INLINE: case FRIEND:
  2379. case VIRTUAL: case TEMPLATE: case IDENT: case '~':
  2380. case BOOL: case WCHAR: case EXPLICIT: case MUTABLE:
  2381. member (cls, vis);
  2382. break;
  2383. default:
  2384. MATCH ();
  2385. break;
  2386. }
  2387. }
  2388. }
  2389. /* Parse a qualified identifier. Current lookahead is IDENT. A
  2390. qualified ident has the form `X<..>::Y<...>::T<...>. Returns a
  2391. symbol for that class. */
  2392. struct sym *
  2393. parse_classname ()
  2394. {
  2395. struct sym *last_class = NULL;
  2396. while (LOOKING_AT (IDENT))
  2397. {
  2398. last_class = add_sym (yytext, last_class);
  2399. MATCH ();
  2400. if (LOOKING_AT ('<'))
  2401. {
  2402. skip_matching ();
  2403. SET_FLAG (last_class->flags, F_TEMPLATE);
  2404. }
  2405. if (!LOOKING_AT (DCOLON))
  2406. break;
  2407. MATCH ();
  2408. }
  2409. return last_class;
  2410. }
  2411. /* Parse an operator name. Add the `static' flag to *SC if an
  2412. implicitly static operator has been parsed. Value is a pointer to
  2413. a static buffer holding the constructed operator name string. */
  2414. char *
  2415. operator_name (sc)
  2416. int *sc;
  2417. {
  2418. static int id_size = 0;
  2419. static char *id = NULL;
  2420. char *s;
  2421. int len;
  2422. MATCH ();
  2423. if (LOOKING_AT2 (NEW, DELETE))
  2424. {
  2425. /* `new' and `delete' are implicitly static. */
  2426. if (*sc != SC_FRIEND)
  2427. *sc = SC_STATIC;
  2428. s = token_string (LA1);
  2429. MATCH ();
  2430. len = strlen (s) + 10;
  2431. if (len > id_size)
  2432. {
  2433. int new_size = max (len, 2 * id_size);
  2434. id = (char *) xrealloc (id, new_size);
  2435. id_size = new_size;
  2436. }
  2437. strcpy (id, s);
  2438. /* Vector new or delete? */
  2439. if (LOOKING_AT ('['))
  2440. {
  2441. strcat (id, "[");
  2442. MATCH ();
  2443. if (LOOKING_AT (']'))
  2444. {
  2445. strcat (id, "]");
  2446. MATCH ();
  2447. }
  2448. }
  2449. }
  2450. else
  2451. {
  2452. int tokens_matched = 0;
  2453. len = 20;
  2454. if (len > id_size)
  2455. {
  2456. int new_size = max (len, 2 * id_size);
  2457. id = (char *) xrealloc (id, new_size);
  2458. id_size = new_size;
  2459. }
  2460. strcpy (id, "operator");
  2461. /* Beware access declarations of the form "X::f;" Beware of
  2462. `operator () ()'. Yet another difficulty is found in
  2463. GCC 2.95's STL: `operator == __STL_NULL_TMPL_ARGS (...'. */
  2464. while (!(LOOKING_AT ('(') && tokens_matched)
  2465. && !LOOKING_AT2 (';', YYEOF))
  2466. {
  2467. s = token_string (LA1);
  2468. len += strlen (s) + 2;
  2469. if (len > id_size)
  2470. {
  2471. int new_size = max (len, 2 * id_size);
  2472. id = (char *) xrealloc (id, new_size);
  2473. id_size = new_size;
  2474. }
  2475. if (*s != ')' && *s != ']')
  2476. strcat (id, " ");
  2477. strcat (id, s);
  2478. MATCH ();
  2479. /* If this is a simple operator like `+', stop now. */
  2480. if (!isalpha ((unsigned char) *s) && *s != '(' && *s != '[')
  2481. break;
  2482. ++tokens_matched;
  2483. }
  2484. }
  2485. return id;
  2486. }
  2487. /* This one consumes the last IDENT of a qualified member name like
  2488. `X::Y::z'. This IDENT is returned in LAST_ID. Value is the
  2489. symbol structure for the ident. */
  2490. struct sym *
  2491. parse_qualified_ident_or_type (last_id)
  2492. char **last_id;
  2493. {
  2494. struct sym *cls = NULL;
  2495. char *id = NULL;
  2496. size_t id_size = 0;
  2497. int enter = 0;
  2498. while (LOOKING_AT (IDENT))
  2499. {
  2500. int len = strlen (yytext) + 1;
  2501. if (len > id_size)
  2502. {
  2503. id = (char *) xrealloc (id, len);
  2504. id_size = len;
  2505. }
  2506. strcpy (id, yytext);
  2507. *last_id = id;
  2508. MATCH ();
  2509. SKIP_MATCHING_IF ('<');
  2510. if (LOOKING_AT (DCOLON))
  2511. {
  2512. struct sym *pcn = NULL;
  2513. struct link *pna = check_namespace_alias (id);
  2514. if (pna)
  2515. {
  2516. do
  2517. {
  2518. enter_namespace (pna->sym->name);
  2519. enter++;
  2520. pna = pna->next;
  2521. }
  2522. while (pna);
  2523. }
  2524. else if ((pcn = check_namespace (id, current_namespace)))
  2525. {
  2526. enter_namespace (pcn->name);
  2527. enter++;
  2528. }
  2529. else
  2530. cls = add_sym (id, cls);
  2531. *last_id = NULL;
  2532. free (id);
  2533. id = NULL;
  2534. id_size = 0;
  2535. MATCH ();
  2536. }
  2537. else
  2538. break;
  2539. }
  2540. while (enter--)
  2541. leave_namespace();
  2542. return cls;
  2543. }
  2544. /* This one consumes the last IDENT of a qualified member name like
  2545. `X::Y::z'. This IDENT is returned in LAST_ID. Value is the
  2546. symbol structure for the ident. */
  2547. void
  2548. parse_qualified_param_ident_or_type (last_id)
  2549. char **last_id;
  2550. {
  2551. struct sym *cls = NULL;
  2552. static char *id = NULL;
  2553. static int id_size = 0;
  2554. while (LOOKING_AT (IDENT))
  2555. {
  2556. int len = strlen (yytext) + 1;
  2557. if (len > id_size)
  2558. {
  2559. id = (char *) xrealloc (id, len);
  2560. id_size = len;
  2561. }
  2562. strcpy (id, yytext);
  2563. *last_id = id;
  2564. MATCH ();
  2565. SKIP_MATCHING_IF ('<');
  2566. if (LOOKING_AT (DCOLON))
  2567. {
  2568. cls = add_sym (id, cls);
  2569. *last_id = NULL;
  2570. MATCH ();
  2571. }
  2572. else
  2573. break;
  2574. }
  2575. }
  2576. /* Parse a class definition.
  2577. CONTAINING is the class containing the class being parsed or null.
  2578. This may also be null if NESTED != 0 if the containing class is
  2579. anonymous. TAG is the tag of the class (struct, union, class).
  2580. NESTED is non-zero if we are parsing a nested class.
  2581. Current lookahead is the class name. */
  2582. void
  2583. class_definition (containing, tag, flags, nested)
  2584. struct sym *containing;
  2585. int tag;
  2586. int flags;
  2587. int nested;
  2588. {
  2589. struct sym *current;
  2590. struct sym *base_class;
  2591. /* Set CURRENT to null if no entry has to be made for the class
  2592. parsed. This is the case for certain command line flag
  2593. settings. */
  2594. if ((tag != CLASS && !f_structs) || (nested && !f_nested_classes))
  2595. current = NULL;
  2596. else
  2597. {
  2598. current = add_sym (yytext, containing);
  2599. current->pos = BUFFER_POS ();
  2600. current->regexp = matching_regexp ();
  2601. current->filename = filename;
  2602. current->flags = flags;
  2603. }
  2604. /* If at ':', base class list follows. */
  2605. if (LOOKING_AT (':'))
  2606. {
  2607. int done = 0;
  2608. MATCH ();
  2609. while (!done)
  2610. {
  2611. switch (LA1)
  2612. {
  2613. case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE:
  2614. MATCH ();
  2615. break;
  2616. case IDENT:
  2617. base_class = parse_classname ();
  2618. if (base_class && current && base_class != current)
  2619. add_link (base_class, current);
  2620. break;
  2621. /* The `,' between base classes or the end of the base
  2622. class list. Add the previously found base class.
  2623. It's done this way to skip over sequences of
  2624. `A::B::C' until we reach the end.
  2625. FIXME: it is now possible to handle `class X : public B::X'
  2626. because we have enough information. */
  2627. case ',':
  2628. MATCH ();
  2629. break;
  2630. default:
  2631. /* A syntax error, possibly due to preprocessor constructs
  2632. like
  2633. #ifdef SOMETHING
  2634. class A : public B
  2635. #else
  2636. class A : private B.
  2637. MATCH until we see something like `;' or `{'. */
  2638. while (!LOOKING_AT3 (';', YYEOF, '{'))
  2639. MATCH ();
  2640. done = 1;
  2641. case '{':
  2642. done = 1;
  2643. break;
  2644. }
  2645. }
  2646. }
  2647. /* Parse the class body if there is one. */
  2648. if (LOOKING_AT ('{'))
  2649. {
  2650. if (tag != CLASS && !f_structs)
  2651. skip_matching ();
  2652. else
  2653. {
  2654. MATCH ();
  2655. class_body (current, tag);
  2656. if (LOOKING_AT ('}'))
  2657. {
  2658. MATCH ();
  2659. if (LOOKING_AT (';') && !nested)
  2660. MATCH ();
  2661. }
  2662. }
  2663. }
  2664. }
  2665. /* Add to class *CLS information for the declaration of variable or
  2666. type *ID. If *CLS is null, this means a global declaration. SC is
  2667. the storage class of *ID. FLAGS is a bit set giving additional
  2668. information about the member (see the F_* defines). */
  2669. void
  2670. add_declarator (cls, id, flags, sc)
  2671. struct sym **cls;
  2672. char **id;
  2673. int flags, sc;
  2674. {
  2675. if (LOOKING_AT2 (';', ','))
  2676. {
  2677. /* The end of a member variable or of an access declaration
  2678. `X::f'. To distinguish between them we have to know whether
  2679. type information has been seen. */
  2680. if (*id)
  2681. {
  2682. char *regexp = matching_regexp ();
  2683. int pos = BUFFER_POS ();
  2684. if (*cls)
  2685. add_member_defn (*cls, *id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
  2686. else
  2687. add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
  2688. }
  2689. MATCH ();
  2690. print_info ();
  2691. }
  2692. else if (LOOKING_AT ('{'))
  2693. {
  2694. if (sc == SC_TYPE && *id)
  2695. {
  2696. /* A named enumeration. */
  2697. char *regexp = matching_regexp ();
  2698. int pos = BUFFER_POS ();
  2699. add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
  2700. }
  2701. skip_matching ();
  2702. print_info ();
  2703. }
  2704. free (*id);
  2705. *id = NULL;
  2706. *cls = NULL;
  2707. }
  2708. /* Parse a declaration. */
  2709. void
  2710. declaration (flags)
  2711. int flags;
  2712. {
  2713. char *id = NULL;
  2714. struct sym *cls = NULL;
  2715. char *regexp = NULL;
  2716. int pos = 0;
  2717. unsigned hash = 0;
  2718. int is_constructor;
  2719. int sc = 0;
  2720. while (!LOOKING_AT3 (';', '{', YYEOF))
  2721. {
  2722. switch (LA1)
  2723. {
  2724. default:
  2725. MATCH ();
  2726. break;
  2727. case '[':
  2728. skip_matching ();
  2729. break;
  2730. case ENUM:
  2731. case TYPEDEF:
  2732. sc = SC_TYPE;
  2733. MATCH ();
  2734. break;
  2735. case STATIC:
  2736. sc = SC_STATIC;
  2737. MATCH ();
  2738. break;
  2739. case INT: case CHAR: case LONG: case UNSIGNED:
  2740. case SIGNED: case CONST: case DOUBLE: case VOID:
  2741. case SHORT: case VOLATILE: case BOOL: case WCHAR:
  2742. MATCH ();
  2743. break;
  2744. case CLASS: case STRUCT: case UNION:
  2745. /* This is for the case `STARTWRAP class X : ...' or
  2746. `declare (X, Y)\n class A : ...'. */
  2747. if (id)
  2748. {
  2749. free (id);
  2750. return;
  2751. }
  2752. case '=':
  2753. /* Assumed to be the start of an initialization in this
  2754. context. */
  2755. skip_initializer ();
  2756. break;
  2757. case ',':
  2758. add_declarator (&cls, &id, flags, sc);
  2759. break;
  2760. case OPERATOR:
  2761. {
  2762. char *s = operator_name (&sc);
  2763. id = (char *) xrealloc (id, strlen (s) + 1);
  2764. strcpy (id, s);
  2765. }
  2766. break;
  2767. case T_INLINE:
  2768. SET_FLAG (flags, F_INLINE);
  2769. MATCH ();
  2770. break;
  2771. case '~':
  2772. MATCH ();
  2773. if (LOOKING_AT (IDENT))
  2774. {
  2775. id = (char *) xrealloc (id, strlen (yytext) + 2);
  2776. *id = '~';
  2777. strcpy (id + 1, yytext);
  2778. MATCH ();
  2779. }
  2780. break;
  2781. case IDENT:
  2782. cls = parse_qualified_ident_or_type (&id);
  2783. break;
  2784. case '(':
  2785. /* Most probably the beginning of a parameter list. */
  2786. if (cls)
  2787. {
  2788. MATCH ();
  2789. if (id && cls)
  2790. {
  2791. if (!(is_constructor = streq (id, cls->name)))
  2792. regexp = matching_regexp ();
  2793. }
  2794. else
  2795. is_constructor = 0;
  2796. pos = BUFFER_POS ();
  2797. hash = parm_list (&flags);
  2798. if (is_constructor)
  2799. regexp = matching_regexp ();
  2800. if (id && cls)
  2801. add_member_defn (cls, id, regexp, pos, hash, 0,
  2802. SC_UNKNOWN, flags);
  2803. }
  2804. else
  2805. {
  2806. /* This may be a C functions, but also a macro
  2807. call of the form `declare (A, B)' --- such macros
  2808. can be found in some class libraries. */
  2809. MATCH ();
  2810. if (id)
  2811. {
  2812. regexp = matching_regexp ();
  2813. pos = BUFFER_POS ();
  2814. hash = parm_list (&flags);
  2815. add_global_decl (id, regexp, pos, hash, 0, sc, flags);
  2816. }
  2817. /* This is for the case that the function really is
  2818. a macro with no `;' following it. If a CLASS directly
  2819. follows, we would miss it otherwise. */
  2820. if (LOOKING_AT3 (CLASS, STRUCT, UNION))
  2821. return;
  2822. }
  2823. while (!LOOKING_AT3 (';', '{', YYEOF))
  2824. MATCH ();
  2825. if (!cls && id && LOOKING_AT ('{'))
  2826. add_global_defn (id, regexp, pos, hash, 0, sc, flags);
  2827. free (id);
  2828. id = NULL;
  2829. break;
  2830. }
  2831. }
  2832. add_declarator (&cls, &id, flags, sc);
  2833. }
  2834. /* Parse a list of top-level declarations/definitions. START_FLAGS
  2835. says in which context we are parsing. If it is F_EXTERNC, we are
  2836. parsing in an `extern "C"' block. Value is 1 if EOF is reached, 0
  2837. otherwise. */
  2838. int
  2839. globals (start_flags)
  2840. int start_flags;
  2841. {
  2842. int anonymous;
  2843. int class_tk;
  2844. int flags = start_flags;
  2845. for (;;)
  2846. {
  2847. char *prev_in = in;
  2848. switch (LA1)
  2849. {
  2850. case NAMESPACE:
  2851. {
  2852. MATCH ();
  2853. if (LOOKING_AT (IDENT))
  2854. {
  2855. char *namespace_name = xstrdup (yytext);
  2856. MATCH ();
  2857. if (LOOKING_AT ('='))
  2858. {
  2859. struct link *qna = match_qualified_namespace_alias ();
  2860. if (qna)
  2861. register_namespace_alias (namespace_name, qna);
  2862. if (skip_to (';') == ';')
  2863. MATCH ();
  2864. }
  2865. else if (LOOKING_AT ('{'))
  2866. {
  2867. MATCH ();
  2868. enter_namespace (namespace_name);
  2869. globals (0);
  2870. leave_namespace ();
  2871. MATCH_IF ('}');
  2872. }
  2873. free (namespace_name);
  2874. }
  2875. }
  2876. break;
  2877. case EXTERN:
  2878. MATCH ();
  2879. if (LOOKING_AT (CSTRING) && *string_start == 'C'
  2880. && *(string_start + 1) == '"')
  2881. {
  2882. /* This is `extern "C"'. */
  2883. MATCH ();
  2884. if (LOOKING_AT ('{'))
  2885. {
  2886. MATCH ();
  2887. globals (F_EXTERNC);
  2888. MATCH_IF ('}');
  2889. }
  2890. else
  2891. SET_FLAG (flags, F_EXTERNC);
  2892. }
  2893. break;
  2894. case TEMPLATE:
  2895. MATCH ();
  2896. SKIP_MATCHING_IF ('<');
  2897. SET_FLAG (flags, F_TEMPLATE);
  2898. break;
  2899. case CLASS: case STRUCT: case UNION:
  2900. class_tk = LA1;
  2901. MATCH ();
  2902. anonymous = 1;
  2903. /* More than one ident here to allow for MS-DOS and OS/2
  2904. specialties like `far', `_Export' etc. Some C++ libs
  2905. have constructs like `_OS_DLLIMPORT(_OS_CLIENT)' in front
  2906. of the class name. */
  2907. while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
  2908. {
  2909. if (LOOKING_AT (IDENT))
  2910. anonymous = 0;
  2911. MATCH ();
  2912. }
  2913. /* Don't add anonymous unions. */
  2914. if (LOOKING_AT2 (':', '{') && !anonymous)
  2915. class_definition (NULL, class_tk, flags, 0);
  2916. else
  2917. {
  2918. if (skip_to (';') == ';')
  2919. MATCH ();
  2920. }
  2921. flags = start_flags;
  2922. break;
  2923. case YYEOF:
  2924. return 1;
  2925. case '}':
  2926. return 0;
  2927. default:
  2928. declaration (flags);
  2929. flags = start_flags;
  2930. break;
  2931. }
  2932. if (prev_in == in)
  2933. yyerror ("parse error", NULL);
  2934. }
  2935. }
  2936. /* Parse the current input file. */
  2937. void
  2938. yyparse ()
  2939. {
  2940. while (globals (0) == 0)
  2941. MATCH_IF ('}');
  2942. }
  2943. /***********************************************************************
  2944. Main Program
  2945. ***********************************************************************/
  2946. /* Add the list of paths PATH_LIST to the current search path for
  2947. input files. */
  2948. void
  2949. add_search_path (path_list)
  2950. char *path_list;
  2951. {
  2952. while (*path_list)
  2953. {
  2954. char *start = path_list;
  2955. struct search_path *p;
  2956. while (*path_list && *path_list != PATH_LIST_SEPARATOR)
  2957. ++path_list;
  2958. p = (struct search_path *) xmalloc (sizeof *p);
  2959. p->path = (char *) xmalloc (path_list - start + 1);
  2960. memcpy (p->path, start, path_list - start);
  2961. p->path[path_list - start] = '\0';
  2962. p->next = NULL;
  2963. if (search_path_tail)
  2964. {
  2965. search_path_tail->next = p;
  2966. search_path_tail = p;
  2967. }
  2968. else
  2969. search_path = search_path_tail = p;
  2970. while (*path_list == PATH_LIST_SEPARATOR)
  2971. ++path_list;
  2972. }
  2973. }
  2974. /* Open FILE and return a file handle for it, or -1 if FILE cannot be
  2975. opened. Try to find FILE in search_path first, then try the
  2976. unchanged file name. */
  2977. FILE *
  2978. open_file (file)
  2979. char *file;
  2980. {
  2981. FILE *fp = NULL;
  2982. static char *buffer;
  2983. static int buffer_size;
  2984. struct search_path *path;
  2985. int flen = strlen (file) + 1; /* +1 for the slash */
  2986. filename = xstrdup (file);
  2987. for (path = search_path; path && fp == NULL; path = path->next)
  2988. {
  2989. int len = strlen (path->path) + flen;
  2990. if (len + 1 >= buffer_size)
  2991. {
  2992. buffer_size = max (len + 1, 2 * buffer_size);
  2993. buffer = (char *) xrealloc (buffer, buffer_size);
  2994. }
  2995. strcpy (buffer, path->path);
  2996. strcat (buffer, "/");
  2997. strcat (buffer, file);
  2998. fp = fopen (buffer, "r");
  2999. }
  3000. /* Try the original file name. */
  3001. if (fp == NULL)
  3002. fp = fopen (file, "r");
  3003. if (fp == NULL)
  3004. yyerror ("cannot open", NULL);
  3005. return fp;
  3006. }
  3007. /* Display usage information and exit program. */
  3008. #define USAGE "\
  3009. Usage: ebrowse [options] {files}\n\
  3010. \n\
  3011. -a, --append append output to existing file\n\
  3012. -f, --files=FILES read input file names from FILE\n\
  3013. -I, --search-path=LIST set search path for input files\n\
  3014. -m, --min-regexp-length=N set minimum regexp length to N\n\
  3015. -M, --max-regexp-length=N set maximum regexp length to N\n\
  3016. -n, --no-nested-classes exclude nested classes\n\
  3017. -o, --output-file=FILE set output file name to FILE\n\
  3018. -p, --position-info print info about position in file\n\
  3019. -s, --no-structs-or-unions don't record structs or unions\n\
  3020. -v, --verbose be verbose\n\
  3021. -V, --very-verbose be very verbose\n\
  3022. -x, --no-regexps don't record regular expressions\n\
  3023. --help display this help\n\
  3024. --version display version info\n\
  3025. "
  3026. void
  3027. usage (error)
  3028. int error;
  3029. {
  3030. puts (USAGE);
  3031. exit (error ? EXIT_FAILURE : EXIT_SUCCESS);
  3032. }
  3033. /* Display version and copyright info. The VERSION macro is set
  3034. from the Makefile and contains the Emacs version. */
  3035. #ifndef VERSION
  3036. # define VERSION "21"
  3037. #endif
  3038. void
  3039. version ()
  3040. {
  3041. /* Makes it easier to update automatically. */
  3042. char emacs_copyright[] = "Copyright (C) 2010 Free Software Foundation, Inc.";
  3043. printf ("ebrowse %s\n", VERSION);
  3044. puts (emacs_copyright);
  3045. puts ("This program is distributed under the same terms as Emacs.");
  3046. exit (EXIT_SUCCESS);
  3047. }
  3048. /* Parse one input file FILE, adding classes and members to the symbol
  3049. table. */
  3050. void
  3051. process_file (file)
  3052. char *file;
  3053. {
  3054. FILE *fp;
  3055. fp = open_file (file);
  3056. if (fp)
  3057. {
  3058. int nread, nbytes;
  3059. /* Give a progress indication if needed. */
  3060. if (f_very_verbose)
  3061. {
  3062. puts (filename);
  3063. fflush (stdout);
  3064. }
  3065. else if (f_verbose)
  3066. {
  3067. putchar ('.');
  3068. fflush (stdout);
  3069. }
  3070. /* Read file to inbuffer. */
  3071. for (nread = 0;;)
  3072. {
  3073. if (nread + READ_CHUNK_SIZE >= inbuffer_size)
  3074. {
  3075. inbuffer_size = nread + READ_CHUNK_SIZE + 1;
  3076. inbuffer = (char *) xrealloc (inbuffer, inbuffer_size);
  3077. }
  3078. nbytes = fread (inbuffer + nread, 1, READ_CHUNK_SIZE, fp);
  3079. if (nbytes <= 0)
  3080. break;
  3081. nread += nbytes;
  3082. }
  3083. if (nread < 0)
  3084. nread = 0;
  3085. inbuffer[nread] = '\0';
  3086. /* Reinitialize scanner and parser for the new input file. */
  3087. re_init_scanner ();
  3088. re_init_parser ();
  3089. /* Parse it and close the file. */
  3090. yyparse ();
  3091. fclose (fp);
  3092. }
  3093. }
  3094. /* Read a line from stream FP and return a pointer to a static buffer
  3095. containing its contents without the terminating newline. Value
  3096. is null when EOF is reached. */
  3097. char *
  3098. read_line (fp)
  3099. FILE *fp;
  3100. {
  3101. static char *buffer;
  3102. static int buffer_size;
  3103. int i = 0, c;
  3104. while ((c = getc (fp)) != EOF && c != '\n')
  3105. {
  3106. if (i >= buffer_size)
  3107. {
  3108. buffer_size = max (100, buffer_size * 2);
  3109. buffer = (char *) xrealloc (buffer, buffer_size);
  3110. }
  3111. buffer[i++] = c;
  3112. }
  3113. if (c == EOF && i == 0)
  3114. return NULL;
  3115. if (i == buffer_size)
  3116. {
  3117. buffer_size = max (100, buffer_size * 2);
  3118. buffer = (char *) xrealloc (buffer, buffer_size);
  3119. }
  3120. buffer[i] = '\0';
  3121. if (i > 0 && buffer[i - 1] == '\r')
  3122. buffer[i - 1] = '\0';
  3123. return buffer;
  3124. }
  3125. /* Main entry point. */
  3126. int
  3127. main (argc, argv)
  3128. int argc;
  3129. char **argv;
  3130. {
  3131. int i;
  3132. int any_inputfiles = 0;
  3133. static char *out_filename = DEFAULT_OUTFILE;
  3134. static char **input_filenames = NULL;
  3135. static int input_filenames_size = 0;
  3136. static int n_input_files;
  3137. filename = "command line";
  3138. yyout = stdout;
  3139. while ((i = getopt_long (argc, argv, "af:I:m:M:no:p:svVx",
  3140. options, NULL)) != EOF)
  3141. {
  3142. switch (i)
  3143. {
  3144. /* Experimental. */
  3145. case 'p':
  3146. info_position = atoi (optarg);
  3147. break;
  3148. case 'n':
  3149. f_nested_classes = 0;
  3150. break;
  3151. case 'x':
  3152. f_regexps = 0;
  3153. break;
  3154. /* Add the name of a file containing more input files. */
  3155. case 'f':
  3156. if (n_input_files == input_filenames_size)
  3157. {
  3158. input_filenames_size = max (10, 2 * input_filenames_size);
  3159. input_filenames = (char **) xrealloc ((void *)input_filenames,
  3160. input_filenames_size);
  3161. }
  3162. input_filenames[n_input_files++] = xstrdup (optarg);
  3163. break;
  3164. /* Append new output to output file instead of truncating it. */
  3165. case 'a':
  3166. f_append = 1;
  3167. break;
  3168. /* Include structs in the output */
  3169. case 's':
  3170. f_structs = 0;
  3171. break;
  3172. /* Be verbose (give a progress indication). */
  3173. case 'v':
  3174. f_verbose = 1;
  3175. break;
  3176. /* Be very verbose (print file names as they are processed). */
  3177. case 'V':
  3178. f_verbose = 1;
  3179. f_very_verbose = 1;
  3180. break;
  3181. /* Change the name of the output file. */
  3182. case 'o':
  3183. out_filename = optarg;
  3184. break;
  3185. /* Set minimum length for regular expression strings
  3186. when recorded in the output file. */
  3187. case 'm':
  3188. min_regexp = atoi (optarg);
  3189. break;
  3190. /* Set maximum length for regular expression strings
  3191. when recorded in the output file. */
  3192. case 'M':
  3193. max_regexp = atoi (optarg);
  3194. break;
  3195. /* Add to search path. */
  3196. case 'I':
  3197. add_search_path (optarg);
  3198. break;
  3199. /* Display help */
  3200. case -2:
  3201. usage (0);
  3202. break;
  3203. case -3:
  3204. version ();
  3205. break;
  3206. }
  3207. }
  3208. /* Call init_scanner after command line flags have been processed to be
  3209. able to add keywords depending on command line (not yet
  3210. implemented). */
  3211. init_scanner ();
  3212. init_sym ();
  3213. /* Open output file */
  3214. if (*out_filename)
  3215. {
  3216. if (f_append)
  3217. {
  3218. /* Check that the file to append to exists, and is not
  3219. empty. More specifically, it should be a valid file
  3220. produced by a previous run of ebrowse, but that's too
  3221. difficult to check. */
  3222. FILE *fp;
  3223. int rc;
  3224. fp = fopen (out_filename, "r");
  3225. if (fp == NULL)
  3226. {
  3227. yyerror ("file `%s' must exist for --append", out_filename);
  3228. exit (EXIT_FAILURE);
  3229. }
  3230. rc = fseek (fp, 0, SEEK_END);
  3231. if (rc == -1)
  3232. {
  3233. yyerror ("error seeking in file `%s'", out_filename);
  3234. exit (EXIT_FAILURE);
  3235. }
  3236. rc = ftell (fp);
  3237. if (rc == -1)
  3238. {
  3239. yyerror ("error getting size of file `%s'", out_filename);
  3240. exit (EXIT_FAILURE);
  3241. }
  3242. else if (rc == 0)
  3243. {
  3244. yyerror ("file `%s' is empty", out_filename);
  3245. /* It may be ok to use an empty file for appending.
  3246. exit (EXIT_FAILURE); */
  3247. }
  3248. fclose (fp);
  3249. }
  3250. yyout = fopen (out_filename, f_append ? "a" : "w");
  3251. if (yyout == NULL)
  3252. {
  3253. yyerror ("cannot open output file `%s'", out_filename);
  3254. exit (EXIT_FAILURE);
  3255. }
  3256. }
  3257. /* Process input files specified on the command line. */
  3258. while (optind < argc)
  3259. {
  3260. process_file (argv[optind++]);
  3261. any_inputfiles = 1;
  3262. }
  3263. /* Process files given on stdin if no files specified. */
  3264. if (!any_inputfiles && n_input_files == 0)
  3265. {
  3266. char *file;
  3267. while ((file = read_line (stdin)) != NULL)
  3268. process_file (file);
  3269. }
  3270. else
  3271. {
  3272. /* Process files from `--files=FILE'. Every line in FILE names
  3273. one input file to process. */
  3274. for (i = 0; i < n_input_files; ++i)
  3275. {
  3276. FILE *fp = fopen (input_filenames[i], "r");
  3277. if (fp == NULL)
  3278. yyerror ("cannot open input file `%s'", input_filenames[i]);
  3279. else
  3280. {
  3281. char *file;
  3282. while ((file = read_line (fp)) != NULL)
  3283. process_file (file);
  3284. fclose (fp);
  3285. }
  3286. }
  3287. }
  3288. /* Write output file. */
  3289. dump_roots (yyout);
  3290. /* Close output file. */
  3291. if (yyout != stdout)
  3292. fclose (yyout);
  3293. return EXIT_SUCCESS;
  3294. }
  3295. /* arch-tag: fc03b4bc-91a9-4c3d-b3b9-12a77fa86dd8
  3296. (do not change this comment) */
  3297. /* ebrowse.c ends here */