ebrowse.c 92 KB

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