Imported Upstream version 1.8.15
[platform/upstream/doxygen.git] / src / code.l
1 /******************************************************************************
2  *
3  * 
4  *
5  * Copyright (C) 1997-2015 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby 
9  * granted. No representations are made about the suitability of this software 
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17 %option never-interactive
18 %option prefix="codeYY"
19
20 %{
21
22 /*
23  *      includes
24  */
25 #include <stdio.h>
26 #include <assert.h>
27 #include <ctype.h>
28 #include <qregexp.h>
29 #include <qdir.h>
30
31 #include "entry.h"
32 #include "doxygen.h"
33 #include "message.h"
34 #include "outputlist.h"
35 #include "util.h"
36 #include "membername.h"
37 #include "searchindex.h"
38 #include "arguments.h"
39 #include "config.h"
40 #include "groupdef.h"
41 #include "classlist.h"
42 #include "filedef.h"
43 #include "filename.h"
44 #include "namespacedef.h"
45 #include "tooltip.h"
46
47 // Toggle for some debugging info
48 //#define DBG_CTX(x) fprintf x
49 #define DBG_CTX(x) do { } while(0)
50
51 #define YY_NO_UNISTD_H 1
52
53 #define CLASSBLOCK (int *)4
54 #define SCOPEBLOCK (int *)8
55 #define INNERBLOCK (int *)12
56
57 /* -----------------------------------------------------------------
58  *      statics
59  */
60   
61 static CodeOutputInterface * g_code;
62
63 static ClassSDict    *g_codeClassSDict = 0;
64 static QCString      g_curClassName;
65 static QStrList      g_curClassBases;
66
67 static QCString      g_parmType;
68 static QCString      g_parmName;
69
70 static const char *  g_inputString;     //!< the code fragment as text
71 static int           g_inputPosition;   //!< read offset during parsing 
72 static int           g_inputLines;      //!< number of line in the code fragment
73 static int           g_yyLineNr;        //!< current line number
74 static int           g_yyColNr;         //!< current column number
75 static bool          g_needsTermination;
76
77 static bool          g_exampleBlock;
78 static QCString      g_exampleName;
79 static QCString      g_exampleFile;
80
81 static bool          g_insideTemplate = FALSE;
82 static QCString      g_type;
83 static QCString      g_name;
84 static QCString      g_args;
85 static QCString      g_classScope;
86 static QCString      g_realScope;
87 static QStack<int>   g_scopeStack;      //!< 1 if bracket starts a scope, 
88                                         //   2 for internal blocks 
89 static int           g_anchorCount;
90 static FileDef *     g_sourceFileDef;
91 static bool          g_lineNumbers;
92 static Definition *  g_currentDefinition;
93 static MemberDef *   g_currentMemberDef;
94 static bool          g_includeCodeFragment;
95 static const char *  g_currentFontClass;
96 static bool          g_searchingForBody;
97 static bool          g_insideBody;
98 static int           g_bodyCurlyCount;
99 static QCString      g_saveName;
100 static QCString      g_saveType;
101 static QCString      g_delimiter;
102
103 static int           g_bracketCount = 0;
104 static int           g_curlyCount   = 0;
105 static int           g_sharpCount   = 0;
106 static bool          g_inFunctionTryBlock = FALSE;
107 static bool          g_inForEachExpression = FALSE;
108
109 static int           g_lastTemplCastContext;
110 static int           g_lastSpecialCContext;
111 static int           g_lastStringContext;
112 static int           g_lastSkipCppContext;
113 static int           g_lastVerbStringContext;
114 static int           g_lastObjCCallContext;
115 static int           g_memCallContext;
116 static int           g_lastCContext;
117 static int           g_skipInlineInitContext;
118
119 static bool          g_insideCpp;
120 static bool          g_insideObjC;
121 static bool          g_insideJava;
122 static bool          g_insideCS;
123 static bool          g_insidePHP;
124 static bool          g_insideProtocolList;
125 static bool          g_insideSlice;
126
127 static bool          g_lexInit = FALSE;
128
129 static QStack<int>   g_classScopeLengthStack;
130
131 static int           g_prefixed_with_this_keyword = FALSE;
132 static Definition   *g_searchCtx;
133 static bool          g_collectXRefs;
134
135 // context for an Objective-C method call
136 struct ObjCCallCtx
137 {
138   int id;
139   QCString methodName;
140   QCString objectTypeOrName;
141   QGString comment;
142   ClassDef *objectType;
143   MemberDef *objectVar;
144   MemberDef *method;
145   QCString format;
146   int lexState;
147   int braceCount;
148 };
149
150 // globals for objective-C method calls 
151 static ObjCCallCtx *g_currentCtx=0;
152 static int g_currentCtxId=0;
153 static int g_currentNameId=0;
154 static int g_currentObjId=0;
155 static int g_currentWordId=0;
156 static int g_currentCommentId=0;
157 static QStack<ObjCCallCtx> g_contextStack;
158 static QIntDict<ObjCCallCtx> g_contextDict;
159 static QIntDict<QCString> g_nameDict;
160 static QIntDict<QCString> g_objectDict;
161 static QIntDict<QCString> g_wordDict;
162 static QIntDict<QCString> g_commentDict;
163 static int g_braceCount=0;
164   
165 static void saveObjCContext();
166 static void restoreObjCContext();
167
168 static QCString g_forceTagReference;
169
170
171 //-------------------------------------------------------------------
172
173 /*! Represents a stack of variable to class mappings as found in the
174  *  code. Each scope is enclosed in pushScope() and popScope() calls.
175  *  Variables are added by calling addVariables() and one can search
176  *  for variable using findVariable().
177  */
178 class VariableContext
179 {
180   public:
181     static const ClassDef *dummyContext;
182     
183     class Scope : public SDict<ClassDef>
184     {
185       public:
186         Scope() : SDict<ClassDef>(17) {}
187     };
188     
189     VariableContext() 
190     {
191       m_scopes.setAutoDelete(TRUE);
192     }
193     virtual ~VariableContext()
194     {
195     }
196     
197     void pushScope()
198     {
199       m_scopes.append(new Scope);
200       DBG_CTX((stderr,"** Push var context %d\n",m_scopes.count()));
201     }
202
203     void popScope()
204     {
205       if (m_scopes.count()>0)
206       {
207         DBG_CTX((stderr,"** Pop var context %d\n",m_scopes.count()));
208         m_scopes.remove(m_scopes.count()-1);
209       }
210       else
211       {
212         DBG_CTX((stderr,"** ILLEGAL: Pop var context\n"));
213       }
214     }
215
216     void clear()
217     {
218       m_scopes.clear();
219       m_globalScope.clear();
220     }
221
222     void clearExceptGlobal()
223     {
224       DBG_CTX((stderr,"** Clear var context\n"));
225       m_scopes.clear();
226     }
227
228     void addVariable(const QCString &type,const QCString &name);
229     ClassDef *findVariable(const QCString &name);
230
231     int count() const { return m_scopes.count(); }
232     
233   private:
234     Scope        m_globalScope;
235     QList<Scope> m_scopes;
236 };
237
238 void VariableContext::addVariable(const QCString &type,const QCString &name)
239 {
240   //printf("VariableContext::addVariable(%s,%s)\n",type.data(),name.data());
241   QCString ltype = type.simplifyWhiteSpace();
242   QCString lname = name.simplifyWhiteSpace();
243   if (ltype.left(7)=="struct ") 
244   {
245     ltype = ltype.right(ltype.length()-7);
246   }
247   else if (ltype.left(6)=="union ")
248   {
249     ltype = ltype.right(ltype.length()-6);
250   }
251   if (ltype.isEmpty() || lname.isEmpty()) return;
252   DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' g_currentDefinition=%s\n",
253         ltype.data(),lname.data(),g_currentDefinition?g_currentDefinition->name().data():"<none>"));
254   Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast();
255   ClassDef *varType;
256   int i=0;
257   if (
258       (varType=g_codeClassSDict->find(ltype)) ||  // look for class definitions inside the code block
259       (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,ltype)) // look for global class definitions
260      ) 
261   {
262     DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data()));
263     scope->append(lname,varType); // add it to a list
264   }
265   else if ((i=ltype.find('<'))!=-1)
266   {
267     // probably a template class
268     QCString typeName(ltype.left(i));
269     ClassDef* newDef = 0;
270     QCString templateArgs(ltype.right(ltype.length() - i));
271     if (  
272          ( // look for class definitions inside the code block
273            (varType=g_codeClassSDict->find(typeName)) ||
274            // otherwise look for global class definitions
275            (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,typeName,0,0,TRUE,TRUE))
276          ) && // and it must be a template
277          varType->templateArguments())
278     {
279       newDef = varType->getVariableInstance( templateArgs );
280     }
281     if (newDef)
282     {
283       DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data()));
284       scope->append(lname, newDef);
285     }
286     else
287     {
288       // Doesn't seem to be a template. Try just the base name.
289       addVariable(typeName,name);
290     }
291   }
292   else 
293   {
294     if (m_scopes.count()>0) // for local variables add a dummy entry so the name 
295                             // is hidden to avoid false links to global variables with the same name
296                             // TODO: make this work for namespaces as well!
297     {
298       DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data()));
299       scope->append(lname,dummyContext);
300     }
301     else
302     {
303       DBG_CTX((stderr,"** addVariable: not adding variable!\n"));
304     }
305   }
306 }
307
308 ClassDef *VariableContext::findVariable(const QCString &name)
309 {
310   if (name.isEmpty()) return 0;
311   ClassDef *result = 0;
312   QListIterator<Scope> sli(m_scopes);
313   Scope *scope;
314   QCString key = name;
315   // search from inner to outer scope
316   for (sli.toLast();(scope=sli.current());--sli)
317   {
318     result = scope->find(key);
319     if (result)
320     {
321       DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result));
322       return result;
323     }
324   }
325   // nothing found -> also try the global scope
326   result=m_globalScope.find(name);
327   DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result));
328   return result;
329 }
330
331 static VariableContext g_theVarContext;
332 const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8;
333
334 //-------------------------------------------------------------------
335
336 class CallContext
337 {
338   public:
339     struct Ctx
340     {
341       Ctx() : name(g_name), type(g_type), d(0) {}
342       QCString name;
343       QCString type;
344       Definition *d;
345     };
346
347     CallContext() 
348     {
349       m_defList.append(new Ctx);
350       m_defList.setAutoDelete(TRUE);
351     }
352     virtual ~CallContext() {}
353     void setScope(Definition *d)
354     {
355       Ctx *ctx = m_defList.getLast();
356       if (ctx)
357       {
358         DBG_CTX((stderr,"** Set call context %s (%p)\n",d==0 ? "<null>" : d->name().data(),d));
359         ctx->d=d;
360       }
361     }
362     void pushScope()
363     {
364       m_defList.append(new Ctx);
365       DBG_CTX((stderr,"** Push call context %d\n",m_defList.count()));
366     }
367     void popScope()
368     {
369       if (m_defList.count()>1)
370       {
371         DBG_CTX((stderr,"** Pop call context %d\n",m_defList.count()));
372         Ctx *ctx = m_defList.getLast();
373         if (ctx)
374         {
375           g_name = ctx->name;
376           g_type = ctx->type;
377         }
378         m_defList.removeLast();
379       }
380       else
381       {
382         DBG_CTX((stderr,"** ILLEGAL: Pop call context\n"));
383       }
384     }
385     void clear()
386     {
387       DBG_CTX((stderr,"** Clear call context\n"));
388       m_defList.clear();
389       m_defList.append(new Ctx);
390     }
391     Definition *getScope() const
392     {
393       Ctx *ctx = m_defList.getLast();
394       if (ctx) return ctx->d; else return 0;
395     }
396
397   private:
398     QList<Ctx> m_defList;
399 };
400
401 static CallContext g_theCallContext;
402
403 //-------------------------------------------------------------------
404
405 /*! add class/namespace name s to the scope */
406 static void pushScope(const char *s)
407 {
408   g_classScopeLengthStack.push(new int(g_classScope.length()));
409   if (g_classScope.isEmpty() || leftScopeMatch(s,g_classScope))
410   {
411     g_classScope = s;
412   }
413   else
414   {
415     g_classScope += "::";
416     g_classScope += s;
417   }
418   //printf("pushScope(%s) result: `%s'\n",s,g_classScope.data());
419 }
420
421 /*! remove the top class/namespace name from the scope */
422 static void popScope()
423 {
424   if (!g_classScopeLengthStack.isEmpty())
425   {
426     int *pLength = g_classScopeLengthStack.pop();
427     g_classScope.truncate(*pLength);
428     delete pLength;
429   }
430   else
431   {
432     //err("Too many end of scopes found!\n");
433   }
434   //printf("popScope() result: `%s'\n",g_classScope.data());
435 }
436
437 static void setCurrentDoc(const QCString &anchor)
438 {
439   if (Doxygen::searchIndex)
440   {
441     if (g_searchCtx)
442     {
443       g_code->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
444     }
445     else
446     {
447       g_code->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
448     }
449   }
450 }
451
452 static void addToSearchIndex(const char *text)
453 {
454   if (Doxygen::searchIndex)
455   {
456     g_code->addWord(text,FALSE);
457   }
458 }
459
460 static void setClassScope(const QCString &name)
461 {
462   //printf("setClassScope(%s)\n",name.data());
463   QCString n=name;
464   n=n.simplifyWhiteSpace();
465   int ts=n.find('<'); // start of template
466   int te=n.findRev('>'); // end of template
467   //printf("ts=%d te=%d\n",ts,te);
468   if (ts!=-1 && te!=-1 && te>ts)
469   {
470     // remove template from scope
471     n=n.left(ts)+n.right(n.length()-te-1);
472   }
473   while (!g_classScopeLengthStack.isEmpty())
474   {
475     popScope();
476   }
477   g_classScope.resize(0);
478   int i;
479   while ((i=n.find("::"))!=-1)
480   {
481     pushScope(n.left(i));
482     n = n.mid(i+2);
483   }
484   pushScope(n);
485   //printf("--->New class scope `%s'\n",g_classScope.data());
486 }
487
488 /*! start a new line of code, inserting a line number if g_sourceFileDef
489  * is TRUE. If a definition starts at the current line, then the line
490  * number is linked to the documentation of that definition.
491  */
492 static void startCodeLine()
493 {
494   //if (g_currentFontClass) { g_code->endFontClass(); }
495   if (g_sourceFileDef && g_lineNumbers)
496   {
497     //QCString lineNumber,lineAnchor;
498     //lineNumber.sprintf("%05d",g_yyLineNr);
499     //lineAnchor.sprintf("l%05d",g_yyLineNr);
500    
501     Definition *d   = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
502     //printf("%s:startCodeLine(%d)=%p\n",g_sourceFileDef->name().data(),g_yyLineNr,d);
503     if (!g_includeCodeFragment && d)
504     {
505       g_currentDefinition = d;
506       g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
507       g_insideBody = FALSE;
508       g_searchingForBody = TRUE;
509       g_realScope = d->name();
510       //g_classScope = "";
511       g_type.resize(0);
512       g_name.resize(0);
513       g_args.resize(0);
514       g_parmType.resize(0);
515       g_parmName.resize(0);
516       //printf("Real scope: `%s'\n",g_realScope.data());
517       g_bodyCurlyCount = 0;
518       QCString lineAnchor;
519       lineAnchor.sprintf("l%05d",g_yyLineNr);
520       if (g_currentMemberDef)
521       {
522         g_code->writeLineNumber(g_currentMemberDef->getReference(),
523                                 g_currentMemberDef->getOutputFileBase(),
524                                 g_currentMemberDef->anchor(),g_yyLineNr);
525         setCurrentDoc(lineAnchor);
526       }
527       else if (d->isLinkableInProject())
528       {
529         g_code->writeLineNumber(d->getReference(),
530                                 d->getOutputFileBase(),
531                                 0,g_yyLineNr);
532         setCurrentDoc(lineAnchor);
533       }
534     }
535     else
536     {
537       g_code->writeLineNumber(0,0,0,g_yyLineNr);
538     }
539   }
540   DBG_CTX((stderr,"startCodeLine(%d)\n",g_yyLineNr));
541   g_code->startCodeLine(g_sourceFileDef && g_lineNumbers); 
542   if (g_currentFontClass)
543   {
544     g_code->startFontClass(g_currentFontClass);
545   }
546 }
547
548
549 static void endFontClass();
550 static void startFontClass(const char *s);
551
552 static void endCodeLine()
553 {
554   DBG_CTX((stderr,"endCodeLine(%d)\n",g_yyLineNr));
555   endFontClass();
556   g_code->endCodeLine();
557 }
558
559 static void nextCodeLine()
560 {
561   const char * fc = g_currentFontClass;
562   endCodeLine();
563   if (g_yyLineNr<g_inputLines) 
564   {
565     g_currentFontClass = fc;
566     startCodeLine();
567   }
568 }
569
570 /*! write a code fragment `text' that may span multiple lines, inserting
571  * line numbers for each line.
572  */
573 static void codifyLines(const char *text)
574 {
575   //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
576   const char *p=text,*sp=p;
577   char c;
578   bool done=FALSE;
579   while (!done)
580   {
581     sp=p;
582     while ((c=*p++) && c!='\n') { g_yyColNr++; }
583     if (c=='\n')
584     {
585       g_yyLineNr++;
586       g_yyColNr=1;
587       //*(p-1)='\0';
588       int l = (int)(p-sp-1);
589       char *tmp = (char*)malloc(l+1);
590       memcpy(tmp,sp,l);
591       tmp[l]='\0';
592       g_code->codify(tmp);
593       free(tmp);
594       nextCodeLine();
595     }
596     else
597     {
598       g_code->codify(sp);
599       done=TRUE;
600     }
601   }
602 }
603
604 /*! writes a link to a fragment \a text that may span multiple lines, inserting
605  * line numbers for each line. If \a text contains newlines, the link will be 
606  * split into multiple links with the same destination, one for each line.
607  */
608 static void writeMultiLineCodeLink(CodeOutputInterface &ol,
609                                    Definition *d,
610                                    const char *text)
611 {
612   static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
613   TooltipManager::instance()->addTooltip(d);
614   QCString ref  = d->getReference();
615   QCString file = d->getOutputFileBase();
616   QCString anchor = d->anchor();
617   QCString tooltip; 
618   if (!sourceTooltips) // fall back to simple "title" tooltips
619   {
620     tooltip = d->briefDescriptionAsTooltip();
621   }
622   bool done=FALSE;
623   char *p=(char *)text;
624   while (!done)
625   {
626     char *sp=p;
627     char c;
628     while ((c=*p++) && c!='\n') { }
629     if (c=='\n')
630     {
631       g_yyLineNr++;
632       *(p-1)='\0';
633       //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
634       ol.writeCodeLink(ref,file,anchor,sp,tooltip);
635       nextCodeLine();
636     }
637     else
638     {
639       //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
640       ol.writeCodeLink(ref,file,anchor,sp,tooltip);
641       done=TRUE;
642     }
643   }
644 }
645
646 static void addType()
647 {
648   if (g_name=="const") { g_name.resize(0); return; }
649   if (!g_type.isEmpty()) g_type += ' ' ;
650   g_type += g_name ;
651   g_name.resize(0) ;
652   if (!g_type.isEmpty()) g_type += ' ' ;
653   g_type += g_args ;
654   g_args.resize(0) ;
655 }
656
657 static void addParmType()
658 {
659   if (g_parmName=="const") { g_parmName.resize(0); return; }
660   if (!g_parmType.isEmpty()) g_parmType += ' ' ;
661   g_parmType += g_parmName ;
662   g_parmName.resize(0) ;
663 }
664
665 static void addUsingDirective(const char *name)
666 {
667   if (g_sourceFileDef && name)
668   {
669     NamespaceDef *nd = Doxygen::namespaceSDict->find(name);
670     if (nd)
671     {
672       g_sourceFileDef->addUsingDirective(nd);
673     }
674   }
675 }
676
677 static void setParameterList(MemberDef *md)
678 {
679   g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : "";
680   ArgumentList *al = md->argumentList();
681   if (al==0) return;
682   ArgumentListIterator it(*al);
683   Argument *a;
684   for (;(a=it.current());++it)
685   {
686     g_parmName = a->name.copy();
687     g_parmType = a->type.copy();
688     int i = g_parmType.find('*');
689     if (i!=-1) g_parmType = g_parmType.left(i);
690     i = g_parmType.find('&');
691     if (i!=-1) g_parmType = g_parmType.left(i);
692     g_parmType.stripPrefix("const ");
693     g_parmType=g_parmType.stripWhiteSpace();
694     g_theVarContext.addVariable(g_parmType,g_parmName);
695   }
696 }
697
698 static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
699 {
700   int pos=0;
701   QCString type = s;
702   QCString className;
703   QCString templSpec;
704   while (extractClassNameFromType(type,pos,className,templSpec)!=-1)
705   {
706     QCString clName=className+templSpec;
707     ClassDef *cd=0;
708     if (!g_classScope.isEmpty())
709     {
710       cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName);
711     }
712     if (cd==0)
713     {
714       cd=getResolvedClass(d,g_sourceFileDef,clName);
715     }
716     //printf("stripClass trying `%s' = %p\n",clName.data(),cd);
717     if (cd)
718     {
719       return cd;
720     }
721   }
722
723   return 0;
724 }
725
726 static MemberDef *setCallContextForVar(const QCString &name)
727 {
728   if (name.isEmpty()) return 0;
729   DBG_CTX((stderr,"setCallContextForVar(%s) g_classScope=%s\n",name.data(),g_classScope.data()));
730
731   int scopeEnd = name.findRev("::");
732   if (scopeEnd!=-1) // name with explicit scope
733   {
734     QCString scope   = name.left(scopeEnd);
735     QCString locName = name.right(name.length()-scopeEnd-2);
736     //printf("explicit scope: name=%s scope=%s\n",locName.data(),scope.data());
737     ClassDef *mcd = getClass(scope); 
738     if (mcd && !locName.isEmpty())
739     {
740       MemberDef *md=mcd->getMemberByName(locName);
741       if (md)
742       {
743         //printf("name=%s scope=%s\n",locName.data(),scope.data());
744         g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
745         return md;
746       }
747     }
748     else // check namespace as well
749     {
750       NamespaceDef *mnd = getResolvedNamespace(scope);
751       if (mnd && !locName.isEmpty())
752       {
753         MemberDef *md=mnd->getMemberByName(locName);
754         if (md)
755         {
756           //printf("name=%s scope=%s\n",locName.data(),scope.data());
757           g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
758           return md;
759         }
760       }
761     }
762   }
763   
764   MemberName *mn;
765   ClassDef *mcd = g_theVarContext.findVariable(name);
766   if (mcd) // local variable
767   {
768     DBG_CTX((stderr,"local variable?\n"));
769     if (mcd!=VariableContext::dummyContext)
770     {
771       DBG_CTX((stderr,"local var `%s' mcd=%s\n",name.data(),mcd->name().data()));
772       g_theCallContext.setScope(mcd);
773     }
774   }
775   else
776   {
777     DBG_CTX((stderr,"class member? scope=%s\n",g_classScope.data()));
778     // look for a class member 
779     mcd = getClass(g_classScope);
780     if (mcd)
781     {
782       DBG_CTX((stderr,"Inside class %s\n",mcd->name().data()));
783       MemberDef *md=mcd->getMemberByName(name);
784       if (md) 
785       {
786         DBG_CTX((stderr,"Found member %s\n",md->name().data()));
787         if (g_scopeStack.top()!=CLASSBLOCK)
788         {
789           DBG_CTX((stderr,"class member `%s' mcd=%s\n",name.data(),mcd->name().data()));
790           g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
791         }
792         return md;
793       }
794     }
795   }
796
797   // look for a global member
798   if ((mn=Doxygen::functionNameSDict->find(name)))
799   {
800     //printf("global var `%s'\n",name.data());
801     if (mn->count()==1) // global defined only once
802     {
803       MemberDef *md=mn->getFirst();
804       if (!md->isStatic() || md->getBodyDef()==g_sourceFileDef)
805       {
806         g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
807         return md;
808       }
809       return 0;
810     }
811     else if (mn->count()>1) // global defined more than once
812     {
813       MemberNameIterator it(*mn);
814       MemberDef *md;
815       for (;(md=it.current());++it)
816       {
817         //printf("mn=%p md=%p md->getBodyDef()=%p g_sourceFileDef=%p\n",
818         //    mn,md,
819         //    md->getBodyDef(),g_sourceFileDef);
820
821         // in case there are multiple members we could link to, we 
822         // only link to members if defined in the same file or 
823         // defined as external.
824         if ((!md->isStatic() || md->getBodyDef()==g_sourceFileDef) &&
825             (g_forceTagReference.isEmpty() || g_forceTagReference==md->getReference())
826            )
827         {
828           g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
829           //printf("returning member %s in source file %s\n",md->name().data(),g_sourceFileDef->name().data());
830           return md;
831         }
832       }
833       return 0;
834     }
835   }
836   return 0;
837 }
838
839 static void updateCallContextForSmartPointer()
840 {
841   Definition *d = g_theCallContext.getScope();
842   //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : "<none>");
843   MemberDef *md;
844   if (d && d->definitionType()==Definition::TypeClass && (md=((ClassDef*)d)->isSmartPointer()))
845   {
846     ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope());
847     if (ncd)
848     {
849       g_theCallContext.setScope(ncd);
850       //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data());
851     }
852   }
853 }
854
855 static bool getLinkInScope(const QCString &c,  // scope
856                            const QCString &m,  // member
857                            const char *memberText, // exact text
858                            CodeOutputInterface &ol,
859                            const char *text,
860                            bool varOnly=FALSE
861                           )
862 {
863   MemberDef    *md;
864   ClassDef     *cd;
865   FileDef      *fd;
866   NamespaceDef *nd;
867   GroupDef     *gd;
868   DBG_CTX((stderr,"getLinkInScope: trying `%s'::`%s' varOnly=%d\n",c.data(),m.data(),varOnly));
869   if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef,FALSE,g_forceTagReference) && 
870       (!varOnly || md->isVariable()))
871   {
872     if (md->isLinkable())
873     {
874       //printf("found it %s!\n",md->qualifiedName().data());
875       if (g_exampleBlock)
876       {
877         QCString anchor;
878         anchor.sprintf("a%d",g_anchorCount);
879         //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
880         //                                  g_exampleFile.data());
881         if (md->addExample(anchor,g_exampleName,g_exampleFile))
882         {
883           ol.writeCodeAnchor(anchor);
884           g_anchorCount++;
885         }
886       }
887
888       Definition *d = md->getOuterScope()==Doxygen::globalScope ?
889         md->getFileDef() : md->getOuterScope();
890       if (md->getGroupDef()) d = md->getGroupDef();
891       if (d && d->isLinkable())
892       {
893         g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
894         //printf("g_currentDefinition=%p g_currentMemberDef=%p g_insideBody=%d\n",
895         //        g_currentDefinition,g_currentMemberDef,g_insideBody);
896
897         if (g_currentDefinition && g_currentMemberDef &&
898             md!=g_currentMemberDef && g_insideBody && g_collectXRefs)
899         {
900           addDocCrossReference(g_currentMemberDef,md);
901         }
902         //printf("d->getReference()=`%s' d->getOutputBase()=`%s' name=`%s' member name=`%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data());
903
904         writeMultiLineCodeLink(ol,md, text ? text : memberText);
905         addToSearchIndex(text ? text : memberText);
906         return TRUE;
907       }
908     }
909     else // found member, but it is not linkable, so make sure content inside is not assigned
910          // to the previous member, see bug762760
911     {
912       DBG_CTX((stderr,"unlinkable member %s\n",md->name().data()));
913       g_currentMemberDef = 0;
914     }
915   }
916   return FALSE;
917 }
918
919 static bool getLink(const char *className,
920                     const char *memberName,
921                     CodeOutputInterface &ol,
922                     const char *text=0,
923                     bool varOnly=FALSE)
924 {
925   //printf("getLink(%s,%s) g_curClassName=%s\n",className,memberName,g_curClassName.data());
926   QCString m=removeRedundantWhiteSpace(memberName);
927   QCString c=className;
928   if (!getLinkInScope(c,m,memberName,ol,text,varOnly))
929   {
930     if (!g_curClassName.isEmpty())
931     {
932       if (!c.isEmpty()) c.prepend("::");
933       c.prepend(g_curClassName);
934       return getLinkInScope(c,m,memberName,ol,text,varOnly);
935     }
936     return FALSE;
937   }
938   return TRUE;
939 }
940
941 static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName,
942                                       bool typeOnly=FALSE,bool varOnly=FALSE)
943 {
944   int i=0;
945   if (*clName=='~') // correct for matching negated values i.s.o. destructors.
946   {
947     g_code->codify("~");
948     clName++;
949   }
950   QCString className=clName;
951   if (className.isEmpty()) return;
952   if (g_insideProtocolList) // for Obj-C
953   {
954     className+="-p";
955   }
956   if (g_insidePHP)
957   {
958     className = substitute(className,"\\","::"); // for PHP namespaces
959   }
960   else if (g_insideCS || g_insideJava)
961   {
962     className = substitute(className,".","::"); // for PHP namespaces
963   }
964   ClassDef *cd=0,*lcd=0;
965   MemberDef *md=0;
966   bool isLocal=FALSE;
967
968   //printf("generateClassOrGlobalLink(className=%s)\n",className.data());
969   if (!g_prefixed_with_this_keyword || (lcd=g_theVarContext.findVariable(className))==0) // not a local variable
970   {
971     Definition *d = g_currentDefinition;
972     //printf("d=%s g_sourceFileDef=%s\n",d?d->name().data():"<none>",g_sourceFileDef?g_sourceFileDef->name().data():"<none>");
973     cd = getResolvedClass(d,g_sourceFileDef,className,&md);
974     DBG_CTX((stderr,"non-local variable name=%s context=%d cd=%s md=%s!\n",
975     className.data(),g_theVarContext.count(),cd?cd->name().data():"<none>",
976         md?md->name().data():"<none>"));
977     if (cd==0 && md==0 && (i=className.find('<'))!=-1)
978     {
979       QCString bareName = className.left(i); //stripTemplateSpecifiersFromScope(className);
980       DBG_CTX((stderr,"bareName=%s\n",bareName.data()));
981       if (bareName!=className)
982       {
983         cd=getResolvedClass(d,g_sourceFileDef,bareName,&md); // try unspecialized version
984       }
985     }
986     NamespaceDef *nd = getResolvedNamespace(className);
987     if (nd && nd->isLinkableInProject())
988     {
989       g_theCallContext.setScope(nd);
990       addToSearchIndex(className);
991       writeMultiLineCodeLink(*g_code,nd,clName);
992       return;
993     }
994     //printf("md=%s\n",md?md->name().data():"<none>");
995     DBG_CTX((stderr,"is found as a type cd=%s nd=%s\n",
996           cd?cd->name().data():"<null>",
997           nd?nd->name().data():"<null>"));
998     if (cd==0 && md==0) // also see if it is variable or enum or enum value
999     {
1000       if (getLink(g_classScope,clName,ol,clName,varOnly))
1001       {
1002         return;
1003       }
1004     }
1005   }
1006   else
1007   {
1008     //printf("local variable!\n");
1009     if (lcd!=VariableContext::dummyContext) 
1010     {
1011       //printf("non-dummy context lcd=%s!\n",lcd->name().data());
1012       g_theCallContext.setScope(lcd);
1013
1014       // to following is needed for links to a global variable, but is
1015       // no good for a link to a local variable that is also a global symbol.
1016        
1017       //if (getLink(g_classScope,clName,ol,clName))
1018       //{
1019         //return;
1020       //}
1021     }
1022     isLocal=TRUE;
1023     DBG_CTX((stderr,"is a local variable cd=%p!\n",cd));
1024   }
1025   g_prefixed_with_this_keyword = FALSE; // discard the "this" prefix for the next calls
1026
1027   if (cd && cd->isLinkable()) // is it a linkable class
1028   {
1029     DBG_CTX((stderr,"is linkable class %s\n",clName));
1030     if (g_exampleBlock)
1031     {
1032       QCString anchor;
1033       anchor.sprintf("_a%d",g_anchorCount);
1034       //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
1035       //                                   g_exampleFile.data());
1036       if (cd->addExample(anchor,g_exampleName,g_exampleFile))
1037       {
1038         ol.writeCodeAnchor(anchor);
1039         g_anchorCount++;
1040       }
1041     }
1042     writeMultiLineCodeLink(ol,cd,clName);
1043     addToSearchIndex(className);
1044     g_theCallContext.setScope(cd);
1045     if (md)
1046     {
1047       Definition *d = md->getOuterScope()==Doxygen::globalScope ?
1048                       md->getFileDef() : md->getOuterScope();
1049       if (md->getGroupDef()) d = md->getGroupDef();
1050       if (d && d->isLinkable() && md->isLinkable() && 
1051           g_currentMemberDef && g_collectXRefs)
1052       {
1053         addDocCrossReference(g_currentMemberDef,md);
1054       }
1055     }
1056   }
1057   else // not a class, maybe a global member
1058   {
1059     DBG_CTX((stderr,"class %s not linkable! cd=%p md=%p typeOnly=%d\n",clName,cd,md,typeOnly));
1060     if (!isLocal && (md!=0 || (cd==0 && !typeOnly))) // not a class, see if it is a global enum/variable/typedef.
1061     {
1062       if (md==0) // not found as a typedef
1063       {
1064         md = setCallContextForVar(clName);
1065         //printf("setCallContextForVar(%s) md=%p g_currentDefinition=%p\n",clName,md,g_currentDefinition);
1066         if (md && g_currentDefinition)
1067         {
1068           DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n",
1069               md->name().data(),g_currentDefinition->name().data(),
1070               isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md),
1071               md->getOuterScope()->name().data()));
1072         }
1073              
1074         if (md && g_currentDefinition && 
1075             isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md)==-1)
1076         {
1077           md=0; // variable not accessible
1078         }
1079       }
1080       if (md && (!varOnly || md->isVariable()))
1081       {
1082         DBG_CTX((stderr,"is a global md=%p g_currentDefinition=%s linkable=%d\n",md,g_currentDefinition?g_currentDefinition->name().data():"<none>",md->isLinkable()));
1083         if (md->isLinkable())
1084         {
1085           QCString text;
1086           if (!g_forceTagReference.isEmpty()) // explicit reference to symbol in tag file
1087           {
1088             text=g_forceTagReference;
1089             if (text.right(4)==".tag") // strip .tag if present
1090             {
1091               text=text.left(text.length()-4);
1092             }
1093             text+=getLanguageSpecificSeparator(md->getLanguage());
1094             text+=clName;
1095             md->setName(text);
1096             md->setLocalName(text);
1097           }
1098           else // normal reference
1099           {
1100             text=clName;
1101           }
1102           writeMultiLineCodeLink(ol,md,text);
1103           addToSearchIndex(clName);
1104           if (g_currentMemberDef && g_collectXRefs)
1105           {
1106             addDocCrossReference(g_currentMemberDef,md);
1107           }
1108           return;
1109         }
1110       }
1111     }
1112     
1113     // nothing found, just write out the word
1114     DBG_CTX((stderr,"not found!\n"));
1115     codifyLines(clName);
1116     addToSearchIndex(clName);
1117   }
1118 }
1119
1120 static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const char *memName)
1121 {
1122   // extract class definition of the return type in order to resolve
1123   // a->b()->c() like call chains
1124
1125   //printf("type=`%s' args=`%s' class=%s\n",
1126   //  xmd->typeString(),xmd->argsString(),
1127   //  xmd->getClassDef()->name().data());
1128
1129   if (g_exampleBlock)
1130   {
1131     QCString anchor;
1132     anchor.sprintf("a%d",g_anchorCount);
1133     //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
1134     //                                  g_exampleFile.data());
1135     if (xmd->addExample(anchor,g_exampleName,g_exampleFile))
1136     {
1137       ol.writeCodeAnchor(anchor);
1138       g_anchorCount++;
1139     }
1140   }
1141
1142   ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope());
1143   DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass));
1144   g_theCallContext.setScope(typeClass);
1145
1146   Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
1147                    xmd->getFileDef() : xmd->getOuterScope();
1148   if (xmd->getGroupDef()) xd = xmd->getGroupDef();
1149   if (xd && xd->isLinkable())
1150   {
1151
1152     //printf("g_currentDefiniton=%p g_currentMemberDef=%p xmd=%p g_insideBody=%d\n",g_currentDefinition,g_currentMemberDef,xmd,g_insideBody);
1153
1154     if (xmd->templateMaster()) xmd = xmd->templateMaster();
1155
1156     if (xmd->isLinkable())
1157     {
1158       // add usage reference
1159       if (g_currentDefinition && g_currentMemberDef &&
1160           /*xmd!=g_currentMemberDef &&*/ g_insideBody && g_collectXRefs)
1161       {
1162         addDocCrossReference(g_currentMemberDef,xmd);
1163       }
1164
1165       // write the actual link
1166       writeMultiLineCodeLink(ol,xmd,memName);
1167       addToSearchIndex(memName);
1168       return TRUE;
1169     }
1170   }
1171
1172   return FALSE;
1173 }
1174
1175 static bool generateClassMemberLink(CodeOutputInterface &ol,Definition *def,const char *memName)
1176 {
1177   if (def && def->definitionType()==Definition::TypeClass)
1178   {
1179     ClassDef *cd = (ClassDef*)def;
1180     MemberDef *xmd = cd->getMemberByName(memName);
1181     //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd);
1182     if (xmd)
1183     {
1184       return generateClassMemberLink(ol,xmd,memName);
1185     }
1186     else
1187     {
1188       Definition *innerDef = cd->findInnerCompound(memName);
1189       if (innerDef)
1190       {
1191         g_theCallContext.setScope(innerDef);
1192         addToSearchIndex(memName);
1193         writeMultiLineCodeLink(*g_code,innerDef,memName);
1194         return TRUE;
1195       }
1196     }
1197   }
1198   else if (def && def->definitionType()==Definition::TypeNamespace)
1199   {
1200     NamespaceDef *nd = (NamespaceDef*)def;
1201     //printf("Looking for %s inside namespace %s\n",memName,nd->name().data());
1202     Definition *innerDef = nd->findInnerCompound(memName);
1203     if (innerDef)
1204     {
1205       g_theCallContext.setScope(innerDef);
1206       addToSearchIndex(memName);
1207       writeMultiLineCodeLink(*g_code,innerDef,memName);
1208       return TRUE;
1209     }
1210   }
1211   return FALSE;
1212 }
1213
1214 static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName,
1215             char *memName)
1216 {
1217   //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n",
1218   //    varName.data(),memName,g_classScope.data());
1219
1220   if (varName.isEmpty()) return;
1221
1222   // look for the variable in the current context
1223   ClassDef *vcd = g_theVarContext.findVariable(varName);
1224   if (vcd) 
1225   {
1226     if (vcd!=VariableContext::dummyContext)
1227     {
1228       //printf("Class found!\n");
1229       if (getLink(vcd->name(),memName,ol)) 
1230       {
1231         //printf("Found result!\n");
1232         return;
1233       }
1234       if (vcd->baseClasses())
1235       {
1236         BaseClassListIterator bcli(*vcd->baseClasses());
1237         for ( ; bcli.current() ; ++bcli)
1238         {
1239           if (getLink(bcli.current()->classDef->name(),memName,ol)) 
1240           {
1241             //printf("Found result!\n");
1242             return;
1243           }
1244         }
1245       }
1246     }
1247   }
1248   else // variable not in current context, maybe it is in a parent context
1249   {
1250     vcd = getResolvedClass(g_currentDefinition,g_sourceFileDef,g_classScope);
1251     if (vcd && vcd->isLinkable())
1252     {
1253       //printf("Found class %s for variable `%s'\n",g_classScope.data(),varName.data());
1254       MemberName *vmn=Doxygen::memberNameSDict->find(varName);
1255       if (vmn==0)
1256       {
1257         int vi;
1258         QCString vn=varName;
1259         if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1)  // explicit scope A::b(), probably static member
1260         {
1261           ClassDef *jcd = getClass(vn.left(vi));
1262           vn=vn.right(vn.length()-vi-2);
1263           vmn=Doxygen::memberNameSDict->find(vn);
1264           //printf("Trying name `%s' scope=%s\n",vn.data(),scope.data());
1265           if (vmn)
1266           {
1267             MemberNameIterator vmni(*vmn);
1268             MemberDef *vmd;
1269             for (;(vmd=vmni.current());++vmni)
1270             {
1271               if (/*(vmd->isVariable() || vmd->isFunction()) && */
1272                   vmd->getClassDef()==jcd)
1273               {
1274                 //printf("Found variable type=%s\n",vmd->typeString());
1275                 ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1276                 if (mcd && mcd->isLinkable())
1277                 {
1278                   if (generateClassMemberLink(ol,mcd,memName)) return;
1279                 }
1280               }
1281             }
1282           }
1283         }
1284       }
1285       if (vmn)
1286       {
1287         //printf("There is a variable with name `%s'\n",varName);
1288         MemberNameIterator vmni(*vmn);
1289         MemberDef *vmd;
1290         for (;(vmd=vmni.current());++vmni)
1291         {
1292           if (/*(vmd->isVariable() || vmd->isFunction()) && */
1293               vmd->getClassDef()==vcd)
1294           {
1295             //printf("Found variable type=%s\n",vmd->typeString());
1296             ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1297             if (mcd && mcd->isLinkable())
1298             {
1299               if (generateClassMemberLink(ol,mcd,memName)) return;
1300             }
1301           }
1302         }
1303       }
1304     }
1305   }
1306   // nothing found -> write result as is
1307   codifyLines(memName);
1308   addToSearchIndex(memName);
1309   return;
1310 }
1311
1312 static void generatePHPVariableLink(CodeOutputInterface &ol,const char *varName)
1313 {
1314   QCString name = varName+7; // strip $this->
1315   name.prepend("$");
1316   //printf("generatePHPVariableLink(%s) name=%s scope=%s\n",varName,name.data(),g_classScope.data());
1317   if (!getLink(g_classScope,name,ol,varName))
1318   {
1319     codifyLines(varName);
1320   }
1321 }
1322
1323 static void generateFunctionLink(CodeOutputInterface &ol,const char *funcName)
1324 {
1325   //CodeClassDef *ccd=0;
1326   ClassDef *ccd=0;
1327   QCString locScope=g_classScope;
1328   QString qq=removeRedundantWhiteSpace(funcName);
1329   if (g_insidePHP && qq.startsWith("self::")) qq=qq.mid(4);
1330   QCString locFunc(qq.data());
1331   QCString funcScope;
1332   QCString funcWithScope=locFunc;
1333   QCString funcWithFullScope=locFunc;
1334   QCString fullScope=locScope;
1335   DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data()));
1336   int len=2;
1337   int i=locFunc.findRev("::");
1338   if (g_currentMemberDef && g_currentMemberDef->getClassDef() &&
1339       funcName==g_currentMemberDef->localName() && 
1340       g_currentMemberDef->getDefLine()==g_yyLineNr &&
1341       generateClassMemberLink(ol,g_currentMemberDef,funcName)
1342      )
1343   {
1344     // special case where funcName is the name of a method that is also
1345     // defined on this line. In this case we can directly link to 
1346     // g_currentMemberDef, which is not only faster, but
1347     // in case of overloaded methods, this will make sure that we link to
1348     // the correct method, and thereby get the correct reimplemented relations.
1349     // See also bug 549022.
1350     goto exit;
1351   }
1352   if (i==-1) i=locFunc.findRev("."),len=1;
1353   if (i==-1) i=locFunc.findRev("\\"),len=1; // for PHP
1354   if (i>0)
1355   {
1356     funcScope=locFunc.left(i);
1357     locFunc=locFunc.right(locFunc.length()-i-len).stripWhiteSpace();
1358     int ts=locScope.find('<'); // start of template
1359     int te=locScope.findRev('>'); // end of template
1360     //printf("ts=%d te=%d\n",ts,te);
1361     if (ts!=-1 && te!=-1 && te>ts)
1362     {
1363       // remove template from scope
1364       locScope=locScope.left(ts)+locScope.right(locScope.length()-te-1);
1365     }
1366     ts=funcScope.find('<'); // start of template
1367     te=funcScope.findRev('>'); // end of template
1368     //printf("ts=%d te=%d\n",ts,te);
1369     if (ts!=-1 && te!=-1 && te>ts)
1370     {
1371       // remove template from scope
1372       funcScope=funcScope.left(ts)+funcScope.right(funcScope.length()-te-1);
1373     }
1374     if (!funcScope.isEmpty())
1375     {
1376       funcWithScope = funcScope+"::"+locFunc;
1377       if (!locScope.isEmpty())
1378       {
1379         fullScope=locScope+"::"+funcScope;
1380       }
1381     }
1382     if (!locScope.isEmpty())
1383     {
1384       funcWithFullScope = locScope+"::"+funcWithScope;
1385     }
1386   }
1387   if (!fullScope.isEmpty() && (ccd=g_codeClassSDict->find(fullScope)))
1388   {
1389     //printf("using classScope %s\n",g_classScope.data());
1390     if (ccd->baseClasses())
1391     {
1392       BaseClassListIterator bcli(*ccd->baseClasses());
1393       for ( ; bcli.current() ; ++bcli)
1394       {
1395         if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName)) 
1396         {
1397           goto exit;
1398         }
1399       }
1400     }
1401   }
1402   if (!locScope.isEmpty() && fullScope!=locScope && (ccd=g_codeClassSDict->find(locScope)))
1403   {
1404     //printf("using classScope %s\n",g_classScope.data());
1405     if (ccd->baseClasses())
1406     {
1407       BaseClassListIterator bcli(*ccd->baseClasses());
1408       for ( ; bcli.current() ; ++bcli)
1409       {
1410         if (getLink(bcli.current()->classDef->name(),funcWithScope,ol,funcName)) 
1411         {
1412           goto exit;
1413         }
1414       }
1415     }
1416   }
1417   if (!getLink(locScope,funcWithScope,ol,funcName))
1418   {
1419     generateClassOrGlobalLink(ol,funcName);
1420   }
1421 exit:  
1422   g_forceTagReference.resize(0);
1423   return;
1424 }
1425
1426 /*! counts the number of lines in the input */
1427 static int countLines()
1428 {
1429   const char *p=g_inputString;
1430   char c;
1431   int count=1;
1432   while ((c=*p)) 
1433   { 
1434     p++ ; 
1435     if (c=='\n') count++;  
1436   }
1437   if (p>g_inputString && *(p-1)!='\n') 
1438   { // last line does not end with a \n, so we add an extra
1439     // line and explicitly terminate the line after parsing.
1440     count++, 
1441     g_needsTermination=TRUE; 
1442   } 
1443   return count;
1444 }
1445
1446 static void endFontClass()
1447 {
1448   if (g_currentFontClass)
1449   {
1450     g_code->endFontClass();
1451     g_currentFontClass=0;
1452   }
1453 }
1454
1455 static void startFontClass(const char *s)
1456 {
1457   endFontClass();
1458   g_code->startFontClass(s);
1459   g_currentFontClass=s;
1460 }
1461
1462 //----------------------------------------------------------------------------
1463
1464 // recursively writes a linkified Objective-C method call
1465 static void writeObjCMethodCall(ObjCCallCtx *ctx)
1466 {
1467   if (ctx==0) return;
1468   char c;
1469   const char *p = ctx->format.data();
1470   if (!ctx->methodName.isEmpty())
1471   {
1472     //printf("writeObjCMethodCall(%s) obj=%s method=%s\n",
1473     //    ctx->format.data(),ctx->objectTypeOrName.data(),ctx->methodName.data());
1474     if (!ctx->objectTypeOrName.isEmpty() && ctx->objectTypeOrName.at(0)!='$')
1475     {
1476       //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(),
1477       //        ctx->methodName.data());
1478       ClassDef *cd = g_theVarContext.findVariable(ctx->objectTypeOrName);
1479       if (cd==0) // not a local variable
1480       {
1481         if (ctx->objectTypeOrName=="self")
1482         {
1483           if (g_currentDefinition && 
1484               g_currentDefinition->definitionType()==Definition::TypeClass)
1485           {
1486             ctx->objectType = (ClassDef *)g_currentDefinition;
1487           }
1488         }
1489         else
1490         {
1491           ctx->objectType = getResolvedClass(
1492               g_currentDefinition,
1493               g_sourceFileDef,
1494               ctx->objectTypeOrName,
1495               &ctx->method);
1496         }
1497         //printf("  object is class? %p\n",ctx->objectType);
1498         if (ctx->objectType) // found class
1499         {
1500           ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1501           //printf("    yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>");
1502         }
1503         else if (ctx->method==0) // search for class variable with the same name
1504         {
1505           //printf("    no\n");
1506           //printf("g_currentDefinition=%p\n",g_currentDefinition);
1507           if (g_currentDefinition && 
1508               g_currentDefinition->definitionType()==Definition::TypeClass)
1509           {
1510             ctx->objectVar = ((ClassDef *)g_currentDefinition)->getMemberByName(ctx->objectTypeOrName);
1511             //printf("      ctx->objectVar=%p\n",ctx->objectVar);
1512             if (ctx->objectVar)
1513             {
1514               ctx->objectType = stripClassName(ctx->objectVar->typeString());
1515               //printf("        ctx->objectType=%p\n",ctx->objectType);
1516               if (ctx->objectType)
1517               {
1518                 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1519                 //printf("          ctx->method=%p\n",ctx->method);
1520               }
1521             }
1522           }
1523         }
1524       }
1525       else // local variable
1526       {
1527         //printf("  object is local variable\n");
1528         if (cd!=VariableContext::dummyContext)
1529         {
1530           ctx->method = cd->getMemberByName(ctx->methodName);
1531           //printf("   class=%p method=%p\n",cd,ctx->method);
1532         }
1533       }
1534     }
1535   }
1536
1537   //printf("[");
1538   while ((c=*p++)) // for each character in ctx->format
1539   {
1540     if (c=='$')
1541     {
1542       char nc=*p++;
1543       if (nc=='$') // escaped $
1544       {
1545         g_code->codify("$");
1546       }
1547       else // name fragment or reference to a nested call 
1548       {
1549         if (nc=='n') // name fragment
1550         {
1551           nc=*p++;
1552           QCString refIdStr;
1553           while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1554           p--;
1555           int refId=refIdStr.toInt();
1556           QCString *pName = g_nameDict.find(refId);
1557           if (pName)
1558           {
1559             if (ctx->method && ctx->method->isLinkable())
1560             {
1561               writeMultiLineCodeLink(*g_code,ctx->method,pName->data());
1562               if (g_currentMemberDef && g_collectXRefs)
1563               {
1564                 addDocCrossReference(g_currentMemberDef,ctx->method);
1565               }
1566             }
1567             else
1568             {
1569               codifyLines(pName->data());
1570             }
1571           }
1572           else
1573           {
1574             //printf("Invalid name: id=%d\n",refId);
1575           }
1576         }
1577         else if (nc=='o') // reference to potential object name
1578         {
1579           nc=*p++;
1580           QCString refIdStr;
1581           while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1582           p--;
1583           int refId=refIdStr.toInt();
1584           QCString *pObject = g_objectDict.find(refId);
1585           if (pObject)
1586           {
1587             if (*pObject=="self")
1588             {
1589               if (g_currentDefinition && 
1590                   g_currentDefinition->definitionType()==Definition::TypeClass)
1591               {
1592                 ctx->objectType = (ClassDef *)g_currentDefinition;
1593                 if (ctx->objectType->categoryOf()) 
1594                 {
1595                   ctx->objectType = ctx->objectType->categoryOf();
1596                 }
1597                 if (ctx->objectType)
1598                 {
1599                   ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1600                 }
1601               }
1602               startFontClass("keyword");
1603               codifyLines(pObject->data());
1604               endFontClass();
1605             }
1606             else if (*pObject=="super")
1607             {
1608               if (g_currentDefinition &&
1609                   g_currentDefinition->definitionType()==Definition::TypeClass)
1610               {
1611                 ClassDef *cd = (ClassDef *)g_currentDefinition;
1612                 if (cd->categoryOf()) 
1613                 {
1614                   cd = cd->categoryOf();
1615                 }
1616                 BaseClassList *bcd = cd->baseClasses();
1617                 if (bcd) // get direct base class (there should be only one)
1618                 {
1619                   BaseClassListIterator bli(*bcd);
1620                   BaseClassDef *bclass;
1621                   for (bli.toFirst();(bclass=bli.current());++bli)
1622                   {
1623                     if (bclass->classDef->compoundType()!=ClassDef::Protocol)
1624                     {
1625                       ctx->objectType = bclass->classDef;
1626                       if (ctx->objectType)
1627                       {
1628                         ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1629                       }
1630                     }
1631                   }
1632                 }
1633               }
1634               startFontClass("keyword");
1635               codifyLines(pObject->data());
1636               endFontClass();
1637             }
1638             else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable
1639             {
1640               writeMultiLineCodeLink(*g_code,ctx->objectVar,pObject->data());
1641               if (g_currentMemberDef && g_collectXRefs)
1642               {
1643                 addDocCrossReference(g_currentMemberDef,ctx->objectVar);
1644               }
1645             }
1646             else if (ctx->objectType && 
1647                      ctx->objectType!=VariableContext::dummyContext && 
1648                      ctx->objectType->isLinkable()
1649                     ) // object is class name
1650             {
1651               ClassDef *cd = ctx->objectType;
1652               writeMultiLineCodeLink(*g_code,cd,pObject->data());
1653             }
1654             else // object still needs to be resolved
1655             {
1656               ClassDef *cd = getResolvedClass(g_currentDefinition, 
1657                   g_sourceFileDef, *pObject);
1658               if (cd && cd->isLinkable())
1659               {
1660                 if (ctx->objectType==0) ctx->objectType=cd;
1661                 writeMultiLineCodeLink(*g_code,cd,pObject->data());
1662               }
1663               else
1664               {
1665                 codifyLines(pObject->data());
1666               }
1667             }
1668           }
1669           else
1670           {
1671             //printf("Invalid object: id=%d\n",refId);
1672           }
1673         }
1674         else if (nc=='c') // reference to nested call
1675         {
1676           nc=*p++;
1677           QCString refIdStr;
1678           while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1679           p--;
1680           int refId=refIdStr.toInt();
1681           ObjCCallCtx *ictx = g_contextDict.find(refId);
1682           if (ictx) // recurse into nested call
1683           {
1684             writeObjCMethodCall(ictx);
1685             if (ictx->method) // link to nested call successfully
1686             {
1687               // get the ClassDef representing the method's return type
1688               if (QCString(ictx->method->typeString())=="id")
1689               {
1690                 // see if the method name is unique, if so we link to it
1691                 MemberName *mn=Doxygen::memberNameSDict->find(ctx->methodName);
1692                 //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n",
1693                 //    mn==0?-1:(int)mn->count(),
1694                 //    ictx->method->name().data(),
1695                 //    ctx->methodName.data());
1696                 if (mn && mn->count()==1) // member name unique
1697                 {
1698                   ctx->method = mn->getFirst();
1699                 }
1700               } 
1701               else
1702               {
1703                 ctx->objectType = stripClassName(ictx->method->typeString());
1704                 if (ctx->objectType)
1705                 {
1706                   ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1707                 }
1708               }
1709               //printf("  ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType);
1710             }
1711           }
1712           else
1713           {
1714             //printf("Invalid context: id=%d\n",refId);
1715           }
1716         }
1717         else if (nc=='w') // some word
1718         {
1719           nc=*p++;
1720           QCString refIdStr;
1721           while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1722           p--;
1723           int refId=refIdStr.toInt();
1724           QCString *pWord = g_wordDict.find(refId);
1725           if (pWord)
1726           {
1727             codifyLines(pWord->data());
1728           }
1729         }
1730         else if (nc=='d') // comment block
1731         {
1732           nc=*p++;
1733           QCString refIdStr;
1734           while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1735           p--;
1736           int refId=refIdStr.toInt();
1737           QCString *pComment = g_commentDict.find(refId);
1738           if (pComment)
1739           {
1740             startFontClass("comment");
1741             codifyLines(pComment->data());
1742             endFontClass();
1743           }
1744         }
1745         else // illegal marker
1746         {
1747           ASSERT(!"invalid escape sequence");
1748         }
1749       }
1750     }
1751     else // normal non-marker character
1752     {
1753       char s[2];
1754       s[0]=c;s[1]=0;
1755       codifyLines(s);
1756     }
1757   }
1758   //printf("%s %s]\n",ctx->objectTypeOrName.data(),ctx->methodName.data());
1759   //printf("}=(type='%s',name='%s')",
1760   //    ctx->objectTypeOrName.data(),
1761   //    ctx->methodName.data());
1762 }
1763
1764 // Replaces an Objective-C method name fragment s by a marker of the form
1765 // $n12, the number (12) can later be used as a key for obtaining the name 
1766 // fragment, from g_nameDict
1767 static QCString escapeName(const char *s)
1768 {
1769   QCString result;
1770   result.sprintf("$n%d",g_currentNameId);
1771   g_nameDict.insert(g_currentNameId,new QCString(s));
1772   g_currentNameId++;
1773   return result;
1774 }
1775
1776 static QCString escapeObject(const char *s)
1777 {
1778   QCString result;
1779   result.sprintf("$o%d",g_currentObjId);
1780   g_objectDict.insert(g_currentObjId,new QCString(s));
1781   g_currentObjId++;
1782   return result;
1783 }
1784
1785 static QCString escapeWord(const char *s)
1786 {
1787   QCString result;
1788   result.sprintf("$w%d",g_currentWordId);
1789   g_wordDict.insert(g_currentWordId,new QCString(s));
1790   g_currentWordId++;
1791   return result;
1792 }
1793
1794 static QCString escapeComment(const char *s)
1795 {
1796   QCString result;
1797   result.sprintf("$d%d",g_currentCommentId);
1798   g_commentDict.insert(g_currentCommentId,new QCString(s));
1799   g_currentCommentId++;
1800   return result;
1801 }
1802
1803 static bool skipLanguageSpecificKeyword(const QCString &kw)
1804 {
1805   return g_insideCpp && (kw == "remove" || kw == "set" || kw == "get");
1806 }
1807
1808 /* -----------------------------------------------------------------
1809  */
1810 #undef  YY_INPUT
1811 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
1812
1813 static int yyread(char *buf,int max_size)
1814 {
1815     int c=0;
1816     while( c < max_size && g_inputString[g_inputPosition] )
1817     {
1818         *buf = g_inputString[g_inputPosition++] ;
1819         c++; buf++;
1820     }
1821     return c;
1822 }
1823
1824 %}
1825
1826 B       [ \t]
1827 BN      [ \t\n\r]
1828 ID      "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
1829 SEP     ("::"|"\\")
1830 SCOPENAME ({SEP}{BN}*)?({ID}{BN}*{SEP}{BN}*)*("~"{BN}*)?{ID}
1831 TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">"
1832 SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?{SEP}{BN}*)*)((~{BN}*)?{ID})
1833 SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*{SEP}{BN}*)+
1834 KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property")
1835 KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"set"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"null"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|"alignas"|"alignof"|{KEYWORD_OBJC})
1836 FLOWKW  ("break"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"return"|"switch"|"throw"|"throws"|"@catch"|"@finally")
1837 FLOWCONDITION  ("case"|"for"|"foreach"|"for each"|"goto"|"if"|"try"|"while"|"@try")
1838 TYPEKW  ("bool"|"byte"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
1839 TYPEKWSL ("LocalObject"|"Object"|"Value")
1840 CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast")
1841 CHARLIT   (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'"))
1842 ARITHOP "+"|"-"|"/"|"*"|"%"|"--"|"++"
1843 ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|="
1844 LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"
1845 BITOP   "&"|"|"|"^"|"<<"|">>"|"~"
1846 OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
1847 RAWBEGIN  (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"("
1848 RAWEND    ")"[^ \t\(\)\\]{0,16}\"
1849
1850 %option noyywrap
1851
1852 %x      SkipString
1853 %x      SkipStringS
1854 %x      SkipVerbString
1855 %x      SkipCPP
1856 %x      SkipComment
1857 %x      SkipCxxComment
1858 %x      RemoveSpecialCComment
1859 %x      StripSpecialCComment
1860 %x      Body
1861 %x      FuncCall
1862 %x      MemberCall
1863 %x      MemberCall2
1864 %x      SkipInits
1865 %x      ClassName
1866 %x      AlignAs
1867 %x      AlignAsEnd
1868 %x      PackageName
1869 %x      ClassVar
1870 %x      CppCliTypeModifierFollowup
1871 %x      Bases
1872 %x      SkipSharp
1873 %x      ReadInclude
1874 %x      TemplDecl
1875 %x      TemplCast
1876 %x      CallEnd
1877 %x      ObjCMethod
1878 %x      ObjCParams
1879 %x      ObjCParamType
1880 %x      ObjCCall
1881 %x      ObjCMName
1882 %x      ObjCSkipStr
1883 %x      ObjCCallComment
1884 %x      OldStyleArgs
1885 %x      UsingName
1886 %x      RawString
1887 %x      InlineInit
1888
1889 %%
1890
1891 <*>\x0d
1892 <Body>^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") {
1893                                           startFontClass("preprocessor");
1894                                           g_code->codify(yytext);
1895                                           BEGIN( ReadInclude ); 
1896                                         }
1897 <Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ { 
1898                                           g_insideObjC=TRUE;
1899                                           startFontClass("keyword");
1900                                           codifyLines(yytext);
1901                                           endFontClass();
1902                                           if (!g_insideTemplate) 
1903                                             BEGIN( ClassName ); 
1904                                         }
1905 <Body>(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") {
1906                                           if (g_insideTemplate) REJECT;
1907                                           startFontClass("keyword");
1908                                           codifyLines(yytext);
1909                                           endFontClass();
1910                                           BEGIN( ClassName ); 
1911                                         }
1912 <Body>"property"|"event"/{BN}*                  { 
1913                                           if (g_insideTemplate) REJECT;
1914                                           startFontClass("keyword");
1915                                           codifyLines(yytext);
1916                                           endFontClass();
1917                                         }
1918 <Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ { 
1919                                           startFontClass("keyword");
1920                                           codifyLines(yytext);
1921                                           endFontClass();
1922                                           if (!g_insideTemplate) 
1923                                             BEGIN( ClassName ); 
1924                                         }
1925 <Body>("package")[ \t\n]+               { 
1926                                           startFontClass("keyword");
1927                                           codifyLines(yytext);
1928                                           endFontClass();
1929                                           BEGIN( PackageName ); 
1930                                         }
1931 <ClassVar>\n                            {
1932                                           if (!g_insideObjC) REJECT;
1933                                           codifyLines(yytext);
1934                                           BEGIN(Body);
1935                                         }
1936 <Body,ClassVar,Bases>"-"|"+"            {
1937                                           if (!g_insideObjC || g_insideBody)
1938                                           { 
1939                                             g_code->codify(yytext);
1940                                           }
1941                                           else // Start of Objective-C method
1942                                           {
1943                                             //printf("Method!\n");
1944                                             g_code->codify(yytext);
1945                                             BEGIN(ObjCMethod);
1946                                           }
1947                                         }
1948 <ObjCMethod>":"                         {
1949                                           g_code->codify(yytext);
1950                                           BEGIN(ObjCParams);
1951                                         }
1952 <ObjCParams>"("                         {
1953                                           g_code->codify(yytext);
1954                                           BEGIN(ObjCParamType);
1955                                         }
1956 <ObjCParams,ObjCMethod>";"|"{"          {
1957                                           g_code->codify(yytext);
1958                                           if (*yytext=='{')
1959                                           {
1960                                             if (g_searchingForBody)
1961                                             {
1962                                               g_searchingForBody=FALSE;
1963                                               g_insideBody=TRUE;
1964                                             }
1965                                             if (g_insideBody) g_bodyCurlyCount++;
1966                                             if (!g_curClassName.isEmpty()) // valid class name
1967                                             {
1968                                               pushScope(g_curClassName);
1969                                               DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
1970                                               g_scopeStack.push(SCOPEBLOCK);
1971                                             }
1972                                           }
1973                                           g_type.resize(0);
1974                                           g_name.resize(0);
1975                                           BEGIN(Body);
1976                                         }
1977 <ObjCParams>{ID}{B}*":"                 {
1978                                           g_code->codify(yytext);
1979                                         }
1980 <ObjCParamType>{TYPEKW}                 {
1981                                           startFontClass("keywordtype");
1982                                           g_code->codify(yytext);
1983                                           endFontClass();
1984                                           g_parmType=yytext;
1985                                         }
1986 <ObjCParamType>{ID}                     {
1987                                           generateClassOrGlobalLink(*g_code,yytext);
1988                                           g_parmType=yytext;
1989                                         }
1990 <ObjCParamType>")"                      {
1991                                           g_code->codify(yytext);
1992                                           BEGIN(ObjCParams);
1993                                         }
1994 <ObjCParams>{ID}                        {
1995                                           g_code->codify(yytext);
1996                                           g_parmName=yytext;
1997                                           g_theVarContext.addVariable(g_parmType,g_parmName);
1998                                           g_parmType.resize(0);g_parmName.resize(0);
1999                                         }
2000 <ObjCMethod,ObjCParams,ObjCParamType>{ID} {
2001                                           generateClassOrGlobalLink(*g_code,yytext);
2002                                         }
2003 <ObjCMethod,ObjCParams,ObjCParamType>.  {
2004                                           g_code->codify(yytext);
2005                                         }
2006 <ObjCMethod,ObjCParams,ObjCParamType>\n {
2007                                           codifyLines(yytext);
2008                                         }
2009 <ReadInclude>[^\n\"\>]+/(">"|"\"")      {
2010                                           //FileInfo *f;
2011                                           bool ambig;
2012                                           bool found=FALSE;
2013                                           //QCString absPath = yytext;
2014                                           //if (g_sourceFileDef && QDir::isRelativePath(absPath))
2015                                           //{
2016                                           //  absPath = QDir::cleanDirPath(g_sourceFileDef->getPath()+"/"+absPath);
2017                                           //}
2018
2019                                           FileDef *fd=findFileDef(Doxygen::inputNameDict,yytext,ambig);
2020                                           //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd);
2021                                           if (fd && fd->isLinkable())
2022                                           {
2023                                             if (ambig) // multiple input files match the name
2024                                             {
2025                                               //printf("===== yes %s is ambiguous\n",yytext);
2026                                               QCString name = QDir::cleanDirPath(yytext).utf8();
2027                                               if (!name.isEmpty() && g_sourceFileDef)
2028                                               {
2029                                                 FileName *fn = Doxygen::inputNameDict->find(name);
2030                                                 if (fn)
2031                                                 {
2032                                                   FileNameIterator fni(*fn);
2033                                                   // for each include name
2034                                                   for (fni.toFirst();!found && (fd=fni.current());++fni)
2035                                                   {
2036                                                     // see if this source file actually includes the file
2037                                                     found = g_sourceFileDef->isIncluded(fd->absFilePath());
2038                                                     //printf("      include file %s found=%d\n",fd->absFilePath().data(),found);
2039                                                   }
2040                                                 }
2041                                               }
2042                                             }
2043                                             else // not ambiguous
2044                                             {
2045                                               found = TRUE;
2046                                             }
2047                                           }
2048                                           //printf("      include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found);
2049                                           if (found)
2050                                           {
2051                                             writeMultiLineCodeLink(*g_code,fd,yytext);
2052                                           }
2053                                           else
2054                                           {
2055                                             g_code->codify(yytext);
2056                                           }
2057                                           char c=yyinput();
2058                                           QCString text;
2059                                           text+=c;
2060                                           g_code->codify(text);
2061                                           endFontClass();
2062                                           BEGIN( Body );
2063                                         }
2064 <Body,Bases>^[ \t]*"#"                  { 
2065                                           startFontClass("preprocessor");
2066                                           g_lastSkipCppContext = YY_START;
2067                                           g_code->codify(yytext);
2068                                           BEGIN( SkipCPP ) ; 
2069                                         }
2070 <SkipCPP>.                              { 
2071                                           g_code->codify(yytext);
2072                                         }
2073 <SkipCPP>[^\n\/\\]+                     {
2074                                           g_code->codify(yytext);
2075                                         }
2076 <SkipCPP>\\[\r]?\n                      { 
2077                                           codifyLines(yytext);
2078                                         }
2079 <SkipCPP>"//"                           { 
2080                                           g_code->codify(yytext);
2081                                         }
2082 <Body,FuncCall>"{"                      { 
2083                                           g_theVarContext.pushScope();
2084
2085                                           DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2086                                           g_scopeStack.push(INNERBLOCK);
2087
2088                                           if (g_searchingForBody)
2089                                           {
2090                                             g_searchingForBody=FALSE;
2091                                             g_insideBody=TRUE;
2092                                           }
2093                                           g_code->codify(yytext);
2094                                           if (g_insideBody) 
2095                                           {
2096                                             g_bodyCurlyCount++;
2097                                           }
2098                                           g_type.resize(0); 
2099                                           g_name.resize(0);
2100                                           BEGIN( Body );
2101                                         }
2102 <Body,FuncCall,MemberCall,MemberCall2>"}"  { 
2103                                           g_theVarContext.popScope();
2104                                           g_type.resize(0); 
2105                                           g_name.resize(0);
2106
2107                                           int *scope = g_scopeStack.pop();
2108                                           DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2109                                           if (scope==SCOPEBLOCK || scope==CLASSBLOCK) 
2110                                           {
2111                                             popScope();
2112                                           }
2113
2114                                           g_code->codify(yytext);
2115
2116                                           DBG_CTX((stderr,"g_bodyCurlyCount=%d\n",g_bodyCurlyCount));
2117                                           if (--g_bodyCurlyCount<=0)
2118                                           {
2119                                             g_insideBody=FALSE;
2120                                             g_currentMemberDef=0;
2121                                             if (g_currentDefinition) 
2122                                               g_currentDefinition=g_currentDefinition->getOuterScope();
2123                                           }
2124                                           BEGIN(Body);
2125                                         }
2126 <Body,ClassVar>"@end"                   { 
2127                                           //printf("End of objc scope fd=%s\n",g_sourceFileDef->name().data());
2128                                           if (g_sourceFileDef)
2129                                           {
2130                                             FileDef *fd=g_sourceFileDef;
2131                                             g_insideObjC = fd->name().lower().right(2)==".m" || 
2132                                                            fd->name().lower().right(3)==".mm"; 
2133                                             //printf("insideObjC=%d\n",g_insideObjC);
2134                                           }
2135                                           else
2136                                           {
2137                                             g_insideObjC = FALSE;
2138                                           }
2139                                           if (g_insideBody)
2140                                           {
2141                                             g_theVarContext.popScope();
2142
2143                                             int *scope = g_scopeStack.pop();
2144                                             DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2145                                             if (scope==SCOPEBLOCK || scope==CLASSBLOCK) 
2146                                             {
2147                                               popScope();
2148                                             }
2149                                             g_insideBody=FALSE;
2150                                           }
2151
2152                                           startFontClass("keyword");
2153                                           g_code->codify(yytext);
2154                                           endFontClass();
2155
2156                                           g_currentMemberDef=0;
2157                                           if (g_currentDefinition) 
2158                                             g_currentDefinition=g_currentDefinition->getOuterScope();
2159                                           BEGIN(Body);
2160                                         }
2161 <ClassName,ClassVar>";"                 { 
2162                                           g_code->codify(yytext);
2163                                           g_searchingForBody=FALSE; 
2164                                           BEGIN( Body ); 
2165                                         }
2166 <ClassName,ClassVar>[*&^%]+             {
2167                                           g_type=g_curClassName.copy();
2168                                           g_name.resize(0);
2169                                           g_code->codify(yytext);
2170                                           BEGIN( Body ); // variable of type struct *
2171                                         }
2172 <ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")"   {
2173                                           startFontClass("keyword");
2174                                           g_code->codify(yytext);
2175                                           endFontClass();
2176                                         }
2177 <ClassName>{ID}("."{ID})*               |
2178 <ClassName>{ID}("::"{ID})*              {
2179                                           if(g_insideCS)
2180                                             g_curClassName=substitute(yytext,".","::");
2181                                           else
2182                                             g_curClassName=yytext;
2183                                           addType();
2184                                           if (g_curClassName=="alignas")
2185                                           {
2186                                             startFontClass("keyword");
2187                                             g_code->codify(yytext);
2188                                             endFontClass();
2189                                             BEGIN( AlignAs );
2190                                           }
2191                                           else
2192                                           {
2193                                             generateClassOrGlobalLink(*g_code,yytext);
2194                                             BEGIN( ClassVar );
2195                                           }
2196                                         }
2197 <AlignAs>"("                            { 
2198                                           g_bracketCount=1;
2199                                           g_code->codify(yytext);
2200                                           BEGIN( AlignAsEnd );
2201                                         }
2202 <AlignAs>\n                             { g_yyLineNr++; 
2203                                           codifyLines(yytext);
2204                                         }
2205 <AlignAs>.                              { g_code->codify(yytext); }
2206 <AlignAsEnd>"("                         { g_code->codify(yytext);
2207                                           g_bracketCount++; 
2208                                         }
2209 <AlignAsEnd>")"                         { 
2210                                           g_code->codify(yytext);
2211                                           if (--g_bracketCount<=0)
2212                                           {
2213                                             BEGIN(ClassName);
2214                                           }
2215                                         }
2216 <AlignAsEnd>\n                          { g_yyLineNr++; 
2217                                           codifyLines(yytext); 
2218                                         }
2219 <AlignAsEnd>.                           { g_code->codify(yytext); }
2220 <ClassName>{ID}("\\"{ID})*              { // PHP namespace
2221                                           g_curClassName=substitute(yytext,"\\","::");
2222                                           g_scopeStack.push(CLASSBLOCK);
2223                                           pushScope(g_curClassName);
2224                                           addType();
2225                                           generateClassOrGlobalLink(*g_code,yytext);
2226                                           BEGIN( ClassVar );
2227                                         }
2228 <ClassName>{ID}{B}*"("{ID}")"           { // Obj-C category
2229                                           g_curClassName=removeRedundantWhiteSpace(yytext);
2230                                           g_scopeStack.push(CLASSBLOCK);
2231                                           pushScope(g_curClassName);
2232                                           addType();
2233                                           generateClassOrGlobalLink(*g_code,yytext);
2234                                           BEGIN( ClassVar );
2235                                         }
2236 <PackageName>{ID}("."{ID})*             {
2237                                           g_curClassName=substitute(yytext,".","::");
2238                                           //printf("found package: %s\n",g_curClassName.data());
2239                                           addType();
2240                                           codifyLines(yytext);
2241                                         }
2242 <ClassVar>"="                           {
2243                                           unput(*yytext);
2244                                           BEGIN( Body );
2245                                         }
2246 <ClassVar>("extends"|"implements")      { // Java, Slice
2247                                           startFontClass("keyword");
2248                                           codifyLines(yytext);
2249                                           endFontClass();
2250                                           g_curClassBases.clear();
2251                                           BEGIN( Bases ); 
2252                                         }
2253 <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") {
2254                                           DBG_CTX((stderr,"***** C++/CLI modifier %s on g_curClassName=%s\n",yytext,g_curClassName.data()));
2255                                           startFontClass("keyword");
2256                                           codifyLines(yytext);
2257                                           endFontClass();
2258                                           BEGIN( CppCliTypeModifierFollowup ); 
2259                                         }
2260 <ClassVar>{ID}                          {
2261                                           g_type = g_curClassName.copy();
2262                                           g_name = yytext;
2263                                           if (g_insideBody)
2264                                           {
2265                                             g_theVarContext.addVariable(g_type,g_name);
2266                                           }
2267                                           generateClassOrGlobalLink(*g_code,yytext);
2268                                         }
2269 <ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}*      {
2270                                           codifyLines(yytext);
2271                                           g_curClassBases.clear();
2272                                           BEGIN( Bases ); 
2273                                         }
2274 <PackageName>[ \t]*";"                  |
2275 <Bases>^{B}*/"@"{ID}                    | // Objective-C interface
2276 <Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* {
2277                                           g_theVarContext.pushScope();
2278                                           g_code->codify(yytext);
2279                                           if (YY_START==ClassVar && g_curClassName.isEmpty())
2280                                           {
2281                                             g_curClassName = g_name.copy();
2282                                           }
2283                                           if (g_searchingForBody)
2284                                           {
2285                                             g_searchingForBody=FALSE;
2286                                             g_insideBody=TRUE;
2287                                           }
2288                                           if (g_insideBody) g_bodyCurlyCount++;
2289                                           if (!g_curClassName.isEmpty()) // valid class name
2290                                           {
2291                                             DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2292                                             g_scopeStack.push(CLASSBLOCK);
2293                                             pushScope(g_curClassName);
2294                                             DBG_CTX((stderr,"***** g_curClassName=%s\n",g_curClassName.data()));
2295                                             if (getResolvedClass(g_currentDefinition,g_sourceFileDef,g_curClassName)==0)
2296                                             {
2297                                               DBG_CTX((stderr,"Adding new class %s\n",g_curClassName.data()));
2298                                               ClassDef *ncd=new ClassDef("<code>",1,1,
2299                                                   g_curClassName,ClassDef::Class,0,0,FALSE);
2300                                               g_codeClassSDict->append(g_curClassName,ncd);
2301                                               // insert base classes.
2302                                               char *s=g_curClassBases.first();
2303                                               while (s)
2304                                               {
2305                                                 ClassDef *bcd;
2306                                                 bcd=g_codeClassSDict->find(s);
2307                                                 if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s);
2308                                                 if (bcd && bcd!=ncd)
2309                                                 {
2310                                                   ncd->insertBaseClass(bcd,s,Public,Normal);
2311                                                 }
2312                                                 s=g_curClassBases.next();
2313                                               }
2314                                             }
2315                                             //printf("g_codeClassList.count()=%d\n",g_codeClassList.count());
2316                                           }
2317                                           else // not a class name -> assume inner block
2318                                           {
2319                                             DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2320                                             g_scopeStack.push(INNERBLOCK);
2321                                           }
2322                                           g_curClassName.resize(0);
2323                                           g_curClassBases.clear();
2324                                           BEGIN( Body );
2325                                         }
2326 <Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" { 
2327                                           startFontClass("keyword");
2328                                           g_code->codify(yytext);
2329                                           endFontClass();
2330                                         }
2331 <Bases>{SEP}?({ID}{SEP})*{ID}           { 
2332                                           DBG_CTX((stderr,"%s:addBase(%s)\n",g_curClassName.data(),yytext));
2333                                           g_curClassBases.inSort(yytext); 
2334                                           generateClassOrGlobalLink(*g_code,yytext);
2335                                         }
2336 <Bases>"<"                              { 
2337                                           g_code->codify(yytext);
2338                                           if (!g_insideObjC)
2339                                           {
2340                                             g_sharpCount=1;
2341                                             BEGIN ( SkipSharp );
2342                                           }
2343                                           else
2344                                           {
2345                                             g_insideProtocolList=TRUE;
2346                                           }
2347                                         }
2348 <Bases>">"                              {
2349                                           g_code->codify(yytext);
2350                                           g_insideProtocolList=FALSE;
2351                                         }
2352 <SkipSharp>"<"                          {
2353                                           g_code->codify(yytext);
2354                                           ++g_sharpCount; 
2355                                         }
2356 <SkipSharp>">"                          { 
2357                                           g_code->codify(yytext);
2358                                           if (--g_sharpCount<=0)
2359                                           BEGIN ( Bases );
2360                                         }
2361 <Bases>"("                              {
2362                                           g_code->codify(yytext);
2363                                           g_sharpCount=1;
2364                                           BEGIN ( SkipSharp );
2365                                         }
2366 <SkipSharp>"("                          {
2367                                           g_code->codify(yytext);
2368                                           ++g_sharpCount;
2369                                         }
2370 <SkipSharp>")"                          {
2371                                           g_code->codify(yytext);
2372                                           if (--g_sharpCount<=0)
2373                                             BEGIN ( Bases );
2374                                         }
2375       
2376       
2377 <Bases>","                              { 
2378                                           g_code->codify(yytext);
2379                                         }
2380                                         
2381
2382 <Body>{SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" {
2383                                           addType();
2384                                           generateFunctionLink(*g_code,yytext);
2385                                           g_bracketCount=0;
2386                                           g_args.resize(0);
2387                                           g_name+=yytext; 
2388                                           BEGIN( FuncCall );
2389                                         }
2390 <Body>{SCOPEPREFIX}?"operator"/"("      {
2391                                           addType();
2392                                           generateFunctionLink(*g_code,yytext);
2393                                           g_bracketCount=0;
2394                                           g_args.resize(0);
2395                                           g_name+=yytext; 
2396                                           BEGIN( FuncCall );
2397                                         }
2398 <Body>{SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\(\n]+/"(" {
2399                                           addType();
2400                                           generateFunctionLink(*g_code,yytext);
2401                                           g_bracketCount=0;
2402                                           g_args.resize(0);
2403                                           g_name+=yytext; 
2404                                           BEGIN( FuncCall );
2405                                         }
2406 <Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9])           {
2407                                           startFontClass("keyword");
2408                                           codifyLines(yytext);
2409                                           endFontClass();
2410                                           g_insideTemplate=TRUE;
2411                                           g_sharpCount=0;
2412                                         }
2413 <Body>"using"{BN}+"namespace"{BN}+      {
2414                                           startFontClass("keyword");
2415                                           codifyLines(yytext);
2416                                           endFontClass();
2417                                           BEGIN(UsingName);
2418                                         }
2419 <UsingName>{ID}("::"{ID})*              { addUsingDirective(yytext);
2420                                           generateClassOrGlobalLink(*g_code,yytext);
2421                                           DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2422                                           g_scopeStack.push(CLASSBLOCK);
2423                                           pushScope(yytext);
2424                                           BEGIN(Body);
2425                                         }
2426 <UsingName>\n                           { codifyLines(yytext); BEGIN(Body); }
2427 <UsingName>.                            { codifyLines(yytext); BEGIN(Body); }
2428 <Body,FuncCall>"$"?"this"("->"|".")     { g_code->codify(yytext); // this-> for C++, this. for C#
2429                                           g_prefixed_with_this_keyword = TRUE;
2430                                         }
2431 <Body>{KEYWORD}/([^a-z_A-Z0-9])         {
2432                                           if (g_insideJava && qstrcmp("internal",yytext) ==0) REJECT;
2433                                           if (skipLanguageSpecificKeyword(yytext)) REJECT;
2434                                           startFontClass("keyword");
2435                                           codifyLines(yytext);
2436                                           if (QCString(yytext)=="typedef")
2437                                           {
2438                                             addType();
2439                                             g_name+=yytext; 
2440                                           }
2441                                           endFontClass();
2442                                         }
2443 <Body>{KEYWORD}/{B}*                    {
2444                                           if (skipLanguageSpecificKeyword(yytext)) REJECT;
2445                                           startFontClass("keyword");
2446                                           codifyLines(yytext);
2447                                           endFontClass();
2448                                         }
2449 <Body>{KEYWORD}/{BN}*"("                {
2450                                           if (skipLanguageSpecificKeyword(yytext)) REJECT;
2451                                           startFontClass("keyword");
2452                                           codifyLines(yytext);
2453                                           endFontClass();
2454                                           g_name.resize(0);g_type.resize(0);
2455                                         }
2456 <FuncCall>"in"/{BN}*                    {
2457                                           if (!g_inForEachExpression) REJECT;
2458                                           startFontClass("keywordflow");
2459                                           codifyLines(yytext);
2460                                           endFontClass();
2461                                           // insert the variable in the parent scope, see bug 546158
2462                                           g_theVarContext.popScope();
2463                                           g_theVarContext.addVariable(g_parmType,g_parmName);
2464                                           g_theVarContext.pushScope();
2465                                           g_name.resize(0);g_type.resize(0);
2466                                         }
2467 <Body>{FLOWKW}/{BN}*"("                         {
2468                                           startFontClass("keywordflow");
2469                                           codifyLines(yytext);
2470                                           endFontClass();
2471                                           g_name.resize(0);g_type.resize(0);
2472                                           g_inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0);
2473                                           BEGIN(FuncCall);
2474                                         }
2475 <Body>{FLOWCONDITION}/{BN}*"("          {
2476                                           if (g_currentMemberDef && g_currentMemberDef->isFunction())
2477                                           {
2478                                             g_currentMemberDef->addFlowKeyWord();
2479                                           }
2480                                           startFontClass("keywordflow");
2481                                           codifyLines(yytext);
2482                                           endFontClass();
2483                                           g_name.resize(0);g_type.resize(0);
2484                                           g_inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0);
2485                                           BEGIN(FuncCall);
2486                                         }
2487 <Body>{FLOWKW}/([^a-z_A-Z0-9])          {
2488                                           startFontClass("keywordflow");
2489                                           codifyLines(yytext);
2490                                           endFontClass();
2491                                           if (g_inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0))
2492                                           {
2493                                             g_inFunctionTryBlock=FALSE;
2494                                           }
2495                                         }
2496 <Body>{FLOWCONDITION}/([^a-z_A-Z0-9])   {
2497                                           if (g_currentMemberDef && g_currentMemberDef->isFunction())
2498                                           {
2499                                             g_currentMemberDef->addFlowKeyWord();
2500                                           }
2501                                           startFontClass("keywordflow");
2502                                           codifyLines(yytext);
2503                                           endFontClass();
2504                                           if (g_inFunctionTryBlock && (strcmp(yytext,"catch")==0 || strcmp(yytext,"finally")==0))
2505                                           {
2506                                             g_inFunctionTryBlock=FALSE;
2507                                           }
2508                                         }
2509 <Body>{FLOWKW}/{B}*                     {
2510                                           startFontClass("keywordflow");
2511                                           codifyLines(yytext);
2512                                           endFontClass();
2513                                         }
2514 <Body>{FLOWCONDITION}/{B}*              {
2515                                           if (g_currentMemberDef && g_currentMemberDef->isFunction())
2516                                           {
2517                                             g_currentMemberDef->addFlowKeyWord();
2518                                           }
2519                                           startFontClass("keywordflow");
2520                                           codifyLines(yytext);
2521                                           endFontClass();
2522                                         }
2523 <Body>"*"{B}*")"                        { // end of cast?
2524                                           g_code->codify(yytext);
2525                                           g_theCallContext.popScope();
2526                                           g_bracketCount--;
2527                                           g_parmType = g_name;
2528                                           BEGIN(FuncCall);
2529                                         }
2530 <Body>[\\|\)\+\-\/\%\~\!]               {
2531                                           g_code->codify(yytext);
2532                                           g_name.resize(0);g_type.resize(0);
2533                                           if (*yytext==')')
2534                                           {
2535                                             g_theCallContext.popScope();
2536                                             g_bracketCount--;
2537                                             BEGIN(FuncCall);
2538                                           }
2539                                         }
2540 <Body,TemplDecl,ObjCMethod>{TYPEKW}/{B}* {
2541                                           startFontClass("keywordtype");
2542                                           g_code->codify(yytext);
2543                                           endFontClass();
2544                                           addType();
2545                                           g_name+=yytext; 
2546                                         }
2547 <Body,TemplDecl,ObjCMethod>{TYPEKWSL}/{B}* {
2548                                           if (!g_insideSlice)
2549                                           {
2550                                             REJECT;
2551                                           }
2552                                           else
2553                                           {
2554                                             startFontClass("keywordtype");
2555                                             g_code->codify(yytext);
2556                                             endFontClass();
2557                                             addType();
2558                                             g_name+=yytext; 
2559                                           }
2560                                         }
2561 <Body>"generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* {
2562                                           startFontClass("keyword");
2563                                           g_code->codify(yytext);
2564                                           endFontClass();
2565                                           g_sharpCount=0;
2566                                           BEGIN(TemplDecl);
2567                                         }
2568 <Body>"template"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { // template<...>
2569                                           startFontClass("keyword");
2570                                           g_code->codify(yytext);
2571                                           endFontClass();
2572                                           g_sharpCount=0;
2573                                           BEGIN(TemplDecl);
2574                                         }
2575 <TemplDecl>"class"|"typename"           {
2576                                           startFontClass("keyword");
2577                                           codifyLines(yytext);
2578                                           endFontClass();
2579                                         }
2580 <TemplDecl>"<"                          {
2581                                           g_code->codify(yytext);
2582                                           g_sharpCount++;
2583                                         }
2584 <TemplDecl>">"                          {
2585                                           g_code->codify(yytext);
2586                                           g_sharpCount--;
2587                                           if (g_sharpCount<=0)
2588                                           {
2589                                             BEGIN(Body);
2590                                           }
2591                                         }
2592 <TemplCast>">"                          {
2593                                           startFontClass("keyword");
2594                                           codifyLines(yytext);
2595                                           endFontClass();
2596                                           BEGIN( g_lastTemplCastContext );
2597                                         }
2598 <TemplCast>{ID}("::"{ID})*              {
2599                                           generateClassOrGlobalLink(*g_code,yytext);
2600                                         }
2601 <TemplCast>("const"|"volatile"){B}*     {
2602                                           startFontClass("keyword");
2603                                           codifyLines(yytext);
2604                                           endFontClass();
2605                                         }
2606 <TemplCast>[*^]*                        {
2607                                           codifyLines(yytext);
2608                                         }
2609 <Body,FuncCall>{CASTKW}"<"                { // static_cast<T>(
2610                                           startFontClass("keyword");
2611                                           codifyLines(yytext);
2612                                           endFontClass();
2613                                           g_lastTemplCastContext = YY_START;
2614                                           BEGIN(TemplCast);
2615                                         }
2616 <Body>"$this->"{SCOPENAME}/{BN}*[;,)\]] { // PHP member variable
2617                                           addType();
2618                                           generatePHPVariableLink(*g_code,yytext);
2619                                           g_name+=yytext+7; 
2620                                         }
2621 <Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>\(]*">"("::"{ID})*/{B}* { // A<T> *pt;
2622                                           int i=QCString(yytext).find('<');
2623                                           QCString kw = QCString(yytext).left(i).stripWhiteSpace();
2624                                           if (kw.right(5)=="_cast" && YY_START==Body)
2625                                           {
2626                                             REJECT;
2627                                           }
2628                                           addType();
2629                                           generateClassOrGlobalLink(*g_code,yytext);
2630                                           g_name+=yytext; 
2631                                         }
2632 <Body>{SCOPENAME}/{BN}*[:;,)\]]         { // "int var;" or "var, var2" or "debug(f) macro" , or int var : 5;
2633                                           addType();
2634                                           // changed this to generateFunctionLink, see bug 624514
2635                                           //generateClassOrGlobalLink(*g_code,yytext,FALSE,TRUE);
2636                                           generateFunctionLink(*g_code,yytext);
2637                                           g_name+=yytext; 
2638                                         }
2639 <Body>{SCOPENAME}/{B}*                  { // p->func()
2640                                           addType();
2641                                           generateClassOrGlobalLink(*g_code,yytext);
2642                                           g_name+=yytext; 
2643                                         }
2644 <Body>"("{B}*("*"{B}*)+{SCOPENAME}*{B}*")"/{B}* {  // (*p)->func() but not "if (p) ..."
2645                                           g_code->codify(yytext);
2646                                           int s=0;while (s<(int)yyleng && !isId(yytext[s])) s++;
2647                                           int e=(int)yyleng-1;while (e>=0 && !isId(yytext[e])) e--;
2648                                           QCString varname = ((QCString)yytext).mid(s,e-s+1); 
2649                                           addType();
2650                                           g_name=varname; 
2651                                         }
2652 <Body>{SCOPETNAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"/{BN}*"(" |
2653 <Body>{SCOPETNAME}/{BN}*"("             { // a() or c::a() or t<A,B>::a() or A\B\foo()
2654                                           addType();
2655                                           generateFunctionLink(*g_code,yytext);
2656                                           g_bracketCount=0;
2657                                           g_args.resize(0);
2658                                           g_name+=yytext; 
2659                                           BEGIN( FuncCall );
2660                                         }
2661 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN}   {
2662                                           QCString text=yytext;
2663                                           int i=text.find('R');
2664                                           g_code->codify(text.left(i+1));
2665                                           startFontClass("stringliteral");
2666                                           g_code->codify(yytext+i+1);
2667                                           g_lastStringContext=YY_START;
2668                                           g_inForEachExpression = FALSE;
2669                                           g_delimiter = yytext+i+2;
2670                                           g_delimiter=g_delimiter.left(g_delimiter.length()-1);
2671                                           BEGIN( RawString );
2672                                         }
2673 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\"   {
2674                                           startFontClass("stringliteral");
2675                                           g_code->codify(yytext);
2676                                           g_lastStringContext=YY_START;
2677                                           g_inForEachExpression = FALSE;
2678                                           BEGIN( SkipString );
2679                                         }
2680 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\'   {
2681                                           startFontClass("stringliteral");
2682                                           g_code->codify(yytext);
2683                                           g_lastStringContext=YY_START;
2684                                           g_inForEachExpression = FALSE;
2685                                           BEGIN( SkipStringS );
2686                                         }
2687 <SkipString>[^\"\\\r\n]*                { 
2688                                           g_code->codify(yytext);
2689                                         }
2690 <SkipStringS>[^\'\\\r\n]*               {
2691                                           g_code->codify(yytext);
2692                                         }
2693 <SkipString,SkipStringS>"//"|"/*"       {
2694                                           g_code->codify(yytext);
2695                                         }
2696 <SkipString>@?\"                        {
2697                                           g_code->codify(yytext);
2698                                           endFontClass();
2699                                           BEGIN( g_lastStringContext );
2700                                         }
2701 <SkipStringS>\'                         {
2702                                           g_code->codify(yytext);
2703                                           endFontClass();
2704                                           BEGIN( g_lastStringContext );
2705                                         }
2706 <SkipString,SkipStringS>\\.             {
2707                                           g_code->codify(yytext);
2708                                         }
2709 <RawString>{RAWEND}                     { 
2710                                           g_code->codify(yytext);
2711                                           QCString delimiter = yytext+1;
2712                                           delimiter=delimiter.left(delimiter.length()-1);
2713                                           if (delimiter==g_delimiter)
2714                                           {
2715                                             BEGIN( g_lastStringContext );
2716                                           }
2717                                         }
2718 <RawString>[^)\n]+                      { g_code->codify(yytext); }
2719 <RawString>.                            { g_code->codify(yytext); }
2720 <RawString>\n                           { codifyLines(yytext); }
2721 <SkipVerbString>[^"\n]+                 {
2722                                           g_code->codify(yytext);
2723                                         }
2724 <SkipVerbString>\"\"                    { // escaped quote
2725                                           g_code->codify(yytext);
2726                                         }
2727 <SkipVerbString>\"                      { // end of string
2728                                           g_code->codify(yytext);
2729                                           endFontClass();
2730                                           BEGIN( g_lastVerbStringContext );
2731                                         }
2732 <SkipVerbString>.                       {
2733                                           g_code->codify(yytext);
2734                                         }
2735 <SkipVerbString>\n                      {
2736                                           codifyLines(yytext);
2737                                         }
2738 <Body>":"                               {
2739                                           g_code->codify(yytext);
2740                                           g_name.resize(0);g_type.resize(0);
2741                                         }
2742 <Body>"<"                               {
2743                                           if (g_insideTemplate)
2744                                           {
2745                                             g_sharpCount++;
2746                                           }
2747                                           g_code->codify(yytext);
2748                                         }
2749 <Body>">"                               {
2750                                           if (g_insideTemplate)
2751                                           {
2752                                             if (--g_sharpCount<=0)
2753                                             {
2754                                               g_insideTemplate=FALSE;
2755                                             }
2756                                           }
2757                                           g_code->codify(yytext);
2758                                         }
2759 <Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'"   {
2760                                           startFontClass("charliteral"); 
2761                                           g_code->codify(yytext);
2762                                           endFontClass();
2763                                         }
2764 <Body>"."|"->"                          { 
2765                                           if (yytext[0]=='-') // -> could be overloaded
2766                                           {
2767                                             updateCallContextForSmartPointer();
2768                                           }
2769                                           g_code->codify(yytext);
2770                                           g_memCallContext = YY_START;
2771                                           BEGIN( MemberCall ); 
2772                                         }
2773 <MemberCall>{SCOPETNAME}/{BN}*"("       {
2774                                           if (g_theCallContext.getScope())
2775                                           {
2776                                             if (!generateClassMemberLink(*g_code,g_theCallContext.getScope(),yytext))
2777                                             {
2778                                               g_code->codify(yytext);
2779                                               addToSearchIndex(yytext);
2780                                             }
2781                                             g_name.resize(0);
2782                                           }
2783                                           else
2784                                           {
2785                                             g_code->codify(yytext);
2786                                             addToSearchIndex(yytext);
2787                                             g_name.resize(0);
2788                                           }
2789                                           g_type.resize(0);
2790                                           g_bracketCount=0;
2791                                           if (g_memCallContext==Body)
2792                                           {
2793                                             BEGIN(FuncCall);
2794                                           }
2795                                           else
2796                                           {
2797                                             BEGIN(g_memCallContext);
2798                                           }
2799                                         }
2800 <MemberCall>{SCOPENAME}/{B}*            {
2801                                           if (g_theCallContext.getScope())
2802                                           {
2803                                             DBG_CTX((stderr,"g_theCallContext.getClass()=%p\n",g_theCallContext.getScope()));
2804                                             if (!generateClassMemberLink(*g_code,g_theCallContext.getScope(),yytext))
2805                                             {
2806                                               g_code->codify(yytext);
2807                                               addToSearchIndex(yytext);
2808                                             }
2809                                             g_name.resize(0);
2810                                           }
2811                                           else
2812                                           {
2813                                             DBG_CTX((stderr,"no class context!\n"));
2814                                             g_code->codify(yytext);
2815                                             addToSearchIndex(yytext);
2816                                             g_name.resize(0);
2817                                           }
2818                                           g_type.resize(0);
2819                                           BEGIN(g_memCallContext);
2820                                         }
2821 <Body>[,=;\[]                           {
2822                                           if (g_insideObjC && *yytext=='[')
2823                                           {
2824                                             //printf("Found start of ObjC call!\n");
2825                                             // start of a method call
2826                                             g_contextDict.setAutoDelete(TRUE);
2827                                             g_nameDict.setAutoDelete(TRUE);
2828                                             g_objectDict.setAutoDelete(TRUE);
2829                                             g_wordDict.setAutoDelete(TRUE);
2830                                             g_commentDict.setAutoDelete(TRUE);
2831                                             g_contextDict.clear();
2832                                             g_nameDict.clear();
2833                                             g_objectDict.clear();
2834                                             g_wordDict.clear();
2835                                             g_commentDict.clear();
2836                                             g_currentCtxId  = 0;
2837                                             g_currentNameId  = 0;
2838                                             g_currentObjId  = 0;
2839                                             g_currentCtx = 0;
2840                                             g_braceCount = 0;
2841                                             unput('[');
2842                                             BEGIN(ObjCCall);
2843                                           }
2844                                           else
2845                                           {
2846                                             g_code->codify(yytext);
2847                                             g_saveName = g_name.copy();
2848                                             g_saveType = g_type.copy();
2849                                             if (*yytext!='[' && !g_type.isEmpty()) 
2850                                             {
2851                                               //printf("g_scopeStack.bottom()=%p\n",g_scopeStack.bottom());
2852                                               //if (g_scopeStack.top()!=CLASSBLOCK) // commented out for bug731363
2853                                               {
2854                                                 //printf("AddVariable: '%s' '%s' context=%d\n",
2855                                                 //    g_type.data(),g_name.data(),g_theVarContext.count());
2856                                                 g_theVarContext.addVariable(g_type,g_name);
2857                                               }
2858                                               g_name.resize(0);
2859                                             }
2860                                             if (*yytext==';' || *yytext=='=') 
2861                                             {
2862                                               g_type.resize(0);
2863                                               g_name.resize(0);
2864                                             }
2865                                             else if (*yytext=='[')
2866                                             {
2867                                               g_theCallContext.pushScope();
2868                                             }
2869                                             g_args.resize(0);
2870                                             g_parmType.resize(0);
2871                                             g_parmName.resize(0);
2872                                           }
2873                                         }
2874   /*
2875 <ObjCMemberCall>{ID}                    {
2876                                           if (qstrcmp(yytext,"self")==0 || qstrcmp(yytext,"super")==0)
2877                                           {
2878                                             // TODO: get proper base class for "super"
2879                                             g_theCallContext.setClass(getClass(g_curClassName));
2880                                             startFontClass("keyword");
2881                                             g_code->codify(yytext); 
2882                                             endFontClass();
2883                                           }
2884                                           else
2885                                           {
2886                                             generateClassOrGlobalLink(*g_code,yytext);
2887                                           }
2888                                           g_name.resize(0);
2889                                           BEGIN(ObjCMemberCall2);
2890                                         }
2891 <ObjCMemberCall>"["                     {
2892                                             g_code->codify(yytext);
2893                                             g_theCallContext.pushScope();
2894                                         }
2895 <ObjCMemberCall2>{ID}":"?               {
2896                                           g_name+=yytext;
2897                                           if (g_theCallContext.getClass())
2898                                           {
2899                                             //printf("Calling method %s\n",g_name.data());
2900                                             if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),g_name))
2901                                             {
2902                                               g_code->codify(yytext);
2903                                               addToSearchIndex(g_name);
2904                                             }
2905                                           }
2906                                           else
2907                                           {
2908                                             g_code->codify(yytext);
2909                                             addToSearchIndex(g_name);
2910                                           }
2911                                           g_name.resize(0);
2912                                           BEGIN(ObjCMemberCall3);
2913                                         }
2914 <ObjCMemberCall2,ObjCMemberCall3>"]"    {
2915                                           g_theCallContext.popScope();
2916                                           g_code->codify(yytext);
2917                                           BEGIN(Body);
2918                                         }
2919   */
2920 <ObjCCall,ObjCMName>"["|"{"       {
2921                                     saveObjCContext();
2922                                     g_currentCtx->format+=*yytext;
2923                                     BEGIN(ObjCCall);
2924                                     //printf("open\n");
2925                                   }
2926 <ObjCCall,ObjCMName>"]"|"}"       {
2927                                     g_currentCtx->format+=*yytext;
2928                                     restoreObjCContext();
2929                                     BEGIN(ObjCMName);
2930                                     if (g_currentCtx==0)
2931                                     {
2932                                       // end of call
2933                                       writeObjCMethodCall(g_contextDict.find(0));
2934                                       BEGIN(Body);
2935                                     }
2936                                     //printf("close\n");
2937                                   }
2938 <ObjCCall,ObjCMName>"//".*        {
2939                                     g_currentCtx->format+=escapeComment(yytext);
2940                                   }
2941 <ObjCCall,ObjCMName>"/*"          {
2942                                     g_lastObjCCallContext = YY_START;
2943                                     g_currentCtx->comment=yytext;
2944                                     BEGIN(ObjCCallComment);
2945                                   }
2946 <ObjCCallComment>"*/"             {
2947                                     g_currentCtx->comment+=yytext;
2948                                     g_currentCtx->format+=escapeComment(g_currentCtx->comment);
2949                                     BEGIN(g_lastObjCCallContext);
2950                                   }
2951 <ObjCCallComment>[^*\n]+          { g_currentCtx->comment+=yytext; }
2952 <ObjCCallComment>"//"|"/*"        { g_currentCtx->comment+=yytext; }
2953 <ObjCCallComment>\n               { g_currentCtx->comment+=*yytext; }
2954 <ObjCCallComment>.                { g_currentCtx->comment+=*yytext; }
2955 <ObjCCall>{ID}                    {
2956                                     g_currentCtx->format+=escapeObject(yytext);
2957                                     if (g_braceCount==0)
2958                                     {
2959                                       g_currentCtx->objectTypeOrName=yytext;
2960                                       //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
2961                                       BEGIN(ObjCMName);
2962                                     }
2963                                   }
2964 <ObjCMName>{ID}/{BN}*"]"          { 
2965                                     if (g_braceCount==0 && 
2966                                         g_currentCtx->methodName.isEmpty())
2967                                     {
2968                                       g_currentCtx->methodName=yytext; 
2969                                       g_currentCtx->format+=escapeName(yytext);
2970                                     }
2971                                     else
2972                                     {
2973                                       g_currentCtx->format+=escapeWord(yytext);
2974                                     }
2975                                   }
2976 <ObjCMName>{ID}/{BN}*":"           { 
2977                                      if (g_braceCount==0)
2978                                      {
2979                                        g_currentCtx->methodName+=yytext;
2980                                        g_currentCtx->methodName+=":";
2981                                      }
2982                                      g_currentCtx->format+=escapeName(yytext);
2983                                    }
2984 <ObjCSkipStr>[^\n\"$\\]*           { g_currentCtx->format+=yytext; }
2985 <ObjCSkipStr>\\.                   { g_currentCtx->format+=yytext; }
2986 <ObjCSkipStr>"\""                  { g_currentCtx->format+=yytext; 
2987                                       BEGIN(g_lastStringContext); 
2988                                    }
2989 <ObjCCall,ObjCMName>{CHARLIT}      { g_currentCtx->format+=yytext; }
2990 <ObjCCall,ObjCMName>"@"?"\""       { g_currentCtx->format+=yytext; 
2991                                       g_lastStringContext=YY_START;
2992                                       BEGIN(ObjCSkipStr); 
2993                                    }
2994 <ObjCCall,ObjCMName,ObjCSkipStr>"$" { g_currentCtx->format+="$$"; }
2995 <ObjCCall,ObjCMName>"("            { g_currentCtx->format+=*yytext; g_braceCount++; }
2996 <ObjCCall,ObjCMName>")"            { g_currentCtx->format+=*yytext; g_braceCount--; }
2997 <ObjCSkipStr>"@"/"\""              { // needed to prevent matching the global rule (for C#)
2998                                      g_currentCtx->format+=yytext;
2999                                    }
3000 <ObjCCall,ObjCMName,ObjCSkipStr>{ID} { g_currentCtx->format+=escapeWord(yytext); }
3001 <ObjCCall,ObjCMName,ObjCSkipStr>.  { g_currentCtx->format+=*yytext; }
3002 <ObjCCall,ObjCMName,ObjCSkipStr>\n { g_currentCtx->format+=*yytext; }
3003
3004 <Body>"]"                               {
3005                                           g_theCallContext.popScope();
3006                                           g_code->codify(yytext);
3007                                           // TODO: nested arrays like: a[b[0]->func()]->func()
3008                                           g_name = g_saveName.copy();
3009                                           g_type = g_saveType.copy();
3010                                         }
3011 <Body>[0-9]+                            {
3012                                           g_code->codify(yytext);
3013                                         }
3014 <Body>[0-9]+[xX][0-9A-Fa-f]+            {
3015                                           g_code->codify(yytext);
3016                                         }
3017 <MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) {
3018                                           //addParmType();
3019                                           //g_parmName=yytext; 
3020                                           if (skipLanguageSpecificKeyword(yytext)) REJECT;
3021                                           startFontClass("keyword");
3022                                           g_code->codify(yytext);
3023                                           endFontClass();
3024                                         }
3025 <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKW}/([^a-z_A-Z0-9]) {
3026                                           addParmType();
3027                                           g_parmName=yytext; 
3028                                           startFontClass("keywordtype");
3029                                           g_code->codify(yytext);
3030                                           endFontClass();
3031                                         }
3032 <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKWSL}/([^a-z_A-Z0-9]) {
3033                                           if (!g_insideSlice)
3034                                           {
3035                                             REJECT;
3036                                           }
3037                                           else
3038                                           {
3039                                             addParmType();
3040                                             g_parmName=yytext; 
3041                                             startFontClass("keywordtype");
3042                                             g_code->codify(yytext);
3043                                             endFontClass();
3044                                           }
3045                                         }
3046 <MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) {
3047                                           addParmType();
3048                                           g_parmName=yytext; 
3049                                           startFontClass("keywordflow");
3050                                           g_code->codify(yytext);
3051                                           endFontClass();
3052                                         }
3053 <MemberCall2,FuncCall>{FLOWCONDITION}/([^a-z_A-Z0-9]) {
3054                                           if (g_currentMemberDef && g_currentMemberDef->isFunction())
3055                                           {
3056                                             g_currentMemberDef->addFlowKeyWord();
3057                                           }
3058                                           addParmType();
3059                                           g_parmName=yytext;
3060                                           startFontClass("keywordflow");
3061                                           g_code->codify(yytext);
3062                                           endFontClass();
3063                                         }
3064 <MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* {
3065                                           addParmType();
3066                                           g_parmName=yytext; 
3067                                           generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3068                                         }
3069 <FuncCall>";"                           { // probably a cast, not a function call
3070                                           g_code->codify(yytext);
3071                                           g_inForEachExpression = FALSE;
3072                                           BEGIN( Body );
3073                                         }
3074 <MemberCall2,FuncCall>,                 {
3075                                           g_code->codify(yytext);
3076                                           g_theVarContext.addVariable(g_parmType,g_parmName);
3077                                           g_parmType.resize(0);g_parmName.resize(0);
3078                                         }
3079 <MemberCall2,FuncCall>"{"               {
3080                                           if (g_bracketCount>0)
3081                                           {
3082                                             g_code->codify(yytext);
3083                                             g_skipInlineInitContext=YY_START;
3084                                             g_curlyCount=0;
3085                                             BEGIN(InlineInit);
3086                                           }
3087                                           else
3088                                           {
3089                                             REJECT;
3090                                           }
3091                                         }
3092 <InlineInit>"{"                         { g_curlyCount++;
3093                                           g_code->codify(yytext);
3094                                         }
3095 <InlineInit>"}"                         {
3096                                           g_code->codify(yytext);
3097                                           if (--g_curlyCount<=0)
3098                                           {
3099                                             BEGIN(g_skipInlineInitContext);
3100                                           }
3101                                         }
3102 <InlineInit>\n                          {
3103                                           codifyLines(yytext);
3104                                         }
3105 <InlineInit>.                           {
3106                                           g_code->codify(yytext);
3107                                         }
3108 <MemberCall2,FuncCall>"("               {
3109                                           g_parmType.resize(0);g_parmName.resize(0);
3110                                           g_code->codify(yytext);
3111                                           g_bracketCount++; 
3112                                           g_theCallContext.pushScope();
3113                                           if (YY_START==FuncCall && !g_insideBody)
3114                                           {
3115                                             g_theVarContext.pushScope();
3116                                           }
3117                                         }
3118 <MemberCall2,FuncCall>{OPERATOR}        { // operator
3119                                           if (qstrcmp(yytext,"*") && 
3120                                               qstrcmp(yytext,"&") &&
3121                                               qstrcmp(yytext,"^") &&
3122                                               qstrcmp(yytext,"%")) // typically a pointer or reference
3123                                           {
3124                                             // not a * or &, or C++/CLI's ^ or %
3125                                             g_parmType.resize(0);g_parmName.resize(0);
3126                                           }
3127                                           g_code->codify(yytext);
3128                                         }
3129 <MemberCall,MemberCall2,FuncCall>("*"{B}*)?")"  { 
3130                                           if (yytext[0]==')') // no a pointer cast
3131                                           {
3132                                             //printf("addVariable(%s,%s)\n",g_parmType.data(),g_parmName.data());
3133                                             if (g_parmType.isEmpty())
3134                                             {
3135                                               g_parmType=g_parmName;
3136                                               g_parmName.resize(0);
3137                                             }
3138                                             g_theVarContext.addVariable(g_parmType,g_parmName);
3139                                           }
3140                                           else
3141                                           {
3142                                             g_parmType = g_parmName;
3143                                             g_parmName.resize(0);
3144                                             g_theVarContext.addVariable(g_parmType,g_parmName);
3145                                           }
3146                                           g_theCallContext.popScope();
3147                                           g_inForEachExpression = FALSE;
3148                                           //g_theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b().
3149                                           g_code->codify(yytext);
3150                                           if (--g_bracketCount<=0) 
3151                                           {
3152                                             if (g_name.isEmpty())
3153                                             {
3154                                               BEGIN( Body );
3155                                             }
3156                                             else
3157                                             {
3158                                               BEGIN( CallEnd ); 
3159                                             }
3160                                           }
3161                                         }
3162 <CallEnd>[ \t\n]*                       { codifyLines(yytext); }
3163   /*
3164 <MemberCall2,FuncCall>")"[ \t\n]*[;:]   {
3165   */
3166 <CallEnd>[;:]                           {
3167                                           codifyLines(yytext);
3168                                           g_bracketCount=0;
3169                                           if (*yytext==';') g_searchingForBody=FALSE; 
3170                                           if (!g_type.isEmpty())
3171                                           {
3172                                             DBG_CTX((stderr,"add variable g_type=%s g_name=%s)\n",g_type.data(),g_name.data()));
3173                                             g_theVarContext.addVariable(g_type,g_name);
3174                                           }
3175                                           g_parmType.resize(0);g_parmName.resize(0);
3176                                           g_theCallContext.setScope(0);
3177                                           if (*yytext==';' || g_insideBody)
3178                                           {
3179                                             if (!g_insideBody)
3180                                             {
3181                                               g_theVarContext.popScope();
3182                                             }
3183                                             g_name.resize(0);g_type.resize(0);
3184                                             BEGIN( Body );
3185                                           }
3186                                           else
3187                                           {
3188                                             g_bracketCount=0;
3189                                             BEGIN( SkipInits );
3190                                           }
3191                                         }
3192 <CallEnd>("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") {
3193                                           startFontClass("keyword");
3194                                           codifyLines(yytext);
3195                                           endFontClass();
3196                                         }
3197 <CallEnd,OldStyleArgs>("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" {
3198                                           if (g_insideBody)
3199                                           {
3200                                             g_theVarContext.pushScope();
3201                                           }
3202                                           g_theVarContext.addVariable(g_parmType,g_parmName);
3203                                           //g_theCallContext.popScope();
3204                                           g_parmType.resize(0);g_parmName.resize(0);
3205                                           int index = g_name.findRev("::");
3206                                           DBG_CTX((stderr,"g_name=%s\n",g_name.data()));
3207                                           if (index!=-1) 
3208                                           {
3209                                             QCString scope = g_name.left(index);
3210                                             if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::");
3211                                             ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope);
3212                                             if (cd)
3213                                             {
3214                                               setClassScope(cd->name());
3215                                               g_scopeStack.push(SCOPEBLOCK);
3216                                               DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3217                                             }
3218                                             else 
3219                                             {
3220                                               //setClassScope(g_realScope);
3221                                               g_scopeStack.push(INNERBLOCK);
3222                                               DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3223                                             }
3224                                           }
3225                                           else
3226                                           {
3227                                             DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3228                                             g_scopeStack.push(INNERBLOCK);
3229                                           }
3230                                           yytext[yyleng-1]='\0';
3231                                           QCString cv(yytext);
3232                                           if (!cv.stripWhiteSpace().isEmpty())
3233                                           {
3234                                             startFontClass("keyword");
3235                                             codifyLines(yytext);
3236                                             endFontClass();
3237                                           }
3238                                           else // just whitespace
3239                                           {
3240                                             codifyLines(yytext);
3241                                           }
3242                                           g_code->codify("{");
3243                                           if (g_searchingForBody)
3244                                           {
3245                                             g_searchingForBody=FALSE;
3246                                             g_insideBody=TRUE;
3247                                           }
3248                                           if (g_insideBody) g_bodyCurlyCount++;
3249                                           g_type.resize(0); g_name.resize(0);
3250                                           BEGIN( Body );
3251                                         }
3252 <CallEnd>"try"                          { // function-try-block
3253                                           startFontClass("keyword");
3254                                           g_code->codify(yytext);
3255                                           endFontClass();
3256                                           g_inFunctionTryBlock=TRUE;
3257                                         }
3258 <CallEnd>{ID}                           {
3259                                           if (g_insideBody || !g_parmType.isEmpty()) 
3260                                           {
3261                                             REJECT;
3262                                           }
3263                                           // could be K&R style definition
3264                                           addParmType();
3265                                           g_parmName=yytext; 
3266                                           generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3267                                           BEGIN(OldStyleArgs);
3268                                         }
3269 <OldStyleArgs>{ID}                      {
3270                                           addParmType();
3271                                           g_parmName=yytext; 
3272                                           generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3273                                         }
3274 <OldStyleArgs>[,;]                      {
3275                                           g_code->codify(yytext);
3276                                           g_theVarContext.addVariable(g_parmType,g_parmName);
3277                                           if (*yytext==';') g_parmType.resize(0);
3278                                           g_parmName.resize(0);
3279                                         }
3280 <CallEnd,OldStyleArgs>"#"               {
3281                                           startFontClass("preprocessor");
3282                                           g_lastSkipCppContext = Body;
3283                                           g_code->codify(yytext);
3284                                           BEGIN( SkipCPP );
3285                                         }
3286 <CallEnd>.                              {
3287                                           unput(*yytext);
3288                                           if (!g_insideBody) 
3289                                           {
3290                                             g_theVarContext.popScope();
3291                                           }
3292                                           g_name.resize(0);g_args.resize(0);
3293                                           g_parmType.resize(0);g_parmName.resize(0);
3294                                           BEGIN( Body ); 
3295                                         }
3296 <SkipInits>";"                          {
3297                                           g_code->codify(yytext);
3298                                           g_type.resize(0); g_name.resize(0);
3299                                           BEGIN( Body );
3300                                         }
3301 <SkipInits>"{"                          { 
3302                                           g_code->codify(yytext);
3303                                           if (g_searchingForBody)
3304                                           {
3305                                             g_searchingForBody=FALSE;
3306                                             g_insideBody=TRUE;
3307                                           }
3308                                           if (g_insideBody) g_bodyCurlyCount++;
3309                                           if (g_name.find("::")!=-1) 
3310                                           {
3311                                             DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3312                                             g_scopeStack.push(SCOPEBLOCK);
3313                                             setClassScope(g_realScope);
3314                                           }
3315                                           else
3316                                           {
3317                                             DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3318                                             g_scopeStack.push(INNERBLOCK);
3319                                           }
3320                                           g_type.resize(0); g_name.resize(0);
3321                                           BEGIN( Body ); 
3322                                         }
3323 <SkipInits>{ID}                         {
3324                                           generateClassOrGlobalLink(*g_code,yytext);
3325                                         }
3326 <FuncCall>{ID}/"("                      {
3327                                           generateFunctionLink(*g_code,yytext);
3328                                         }
3329 <FuncCall>{ID}/("."|"->")               { 
3330                                           g_name=yytext; 
3331                                           generateClassOrGlobalLink(*g_code,yytext);
3332                                           BEGIN( MemberCall2 ); 
3333                                         }
3334 <FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}*{B}*")"{B}*)/("."|"->") { 
3335                                           g_code->codify(yytext);
3336                                           int s=0;while (!isId(yytext[s])) s++;
3337                                           int e=(int)yyleng-1;while (!isId(yytext[e])) e--;
3338                                           g_name=((QCString)yytext).mid(s,e-s+1); 
3339                                           BEGIN( MemberCall2 ); 
3340                                         }
3341 <MemberCall2>{ID}/([ \t\n]*"(")         { 
3342                                           if (!g_args.isEmpty())
3343                                             generateMemberLink(*g_code,g_args,yytext);
3344                                           else
3345                                             generateClassOrGlobalLink(*g_code,yytext);
3346                                           g_args.resize(0);
3347                                           BEGIN( FuncCall );
3348                                         }
3349 <MemberCall2>{ID}/([ \t\n]*("."|"->"))  {
3350                                           //g_code->codify(yytext);
3351                                           g_name=yytext; 
3352                                           generateClassOrGlobalLink(*g_code,yytext);
3353                                           BEGIN( MemberCall2 ); 
3354                                         }
3355 <MemberCall2>"->"|"."                   {
3356                                           if (yytext[0]=='-') // -> could be overloaded
3357                                           {
3358                                             updateCallContextForSmartPointer();
3359                                           }
3360                                           g_code->codify(yytext);
3361                                           g_memCallContext = YY_START;
3362                                           BEGIN( MemberCall ); 
3363                                         }
3364 <SkipComment>"/*"("!"?)"*/"             { 
3365                                           g_code->codify(yytext);
3366                                           endFontClass();
3367                                           BEGIN( g_lastCContext ) ; 
3368                                         }
3369 <SkipComment>"//"|"/*"                  {
3370                                           g_code->codify(yytext);
3371                                         }
3372 <SkipComment>[^*/\n]+                   {
3373                                           g_code->codify(yytext);
3374                                         }
3375 <SkipComment>[ \t]*"*/"                 { 
3376                                           g_code->codify(yytext);
3377                                           endFontClass();
3378                                           if (g_lastCContext==SkipCPP)
3379                                           {
3380                                             startFontClass("preprocessor");
3381                                           }
3382                                           BEGIN( g_lastCContext ) ; 
3383                                         }
3384 <SkipCxxComment>[^\r\n]*"\\"[\r]?\n     { // line continuation
3385                                           codifyLines(yytext);
3386                                         }
3387 <SkipCxxComment>[^\r\n]+                { 
3388                                           g_code->codify(yytext);
3389                                         }
3390 <SkipCxxComment>\r                      
3391 <SkipCxxComment>\n                      {
3392                                           unput('\n');
3393                                           endFontClass();
3394                                           BEGIN( g_lastCContext ) ;
3395                                         }
3396 <SkipCxxComment>.                       {
3397                                           g_code->codify(yytext);
3398                                         }
3399 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] {
3400                                           g_yyLineNr+=QCString(yytext).contains('\n');
3401                                         }
3402 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? {
3403                                           g_yyLineNr+=QCString(yytext).contains('\n');
3404                                           nextCodeLine();
3405                                           if (g_lastSpecialCContext==SkipCxxComment)
3406                                           { // force end of C++ comment here
3407                                             endFontClass();
3408                                             BEGIN( g_lastCContext ) ;
3409                                           }
3410                                           else
3411                                           {
3412                                             BEGIN(g_lastSpecialCContext);
3413                                           }
3414                                         }
3415 <RemoveSpecialCComment>"*/"             {
3416                                           BEGIN(g_lastSpecialCContext);
3417                                         }
3418 <RemoveSpecialCComment>[^*\n]+
3419 <RemoveSpecialCComment>"//"|"/*"
3420 <RemoveSpecialCComment>\n  { g_yyLineNr++; }
3421 <RemoveSpecialCComment>.
3422 <MemberCall>[^a-z_A-Z0-9(\n]            { 
3423                                           g_code->codify(yytext);
3424                                           g_type.resize(0);
3425                                           g_name.resize(0);
3426                                           BEGIN(g_memCallContext); 
3427                                         }
3428 <*>\n({B}*"//"[!/][^\n]*\n)+            { // remove special one-line comment
3429                                           if (YY_START==SkipCPP) REJECT;
3430                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3431                                           {
3432                                             g_yyLineNr+=((QCString)yytext).contains('\n');
3433                                             nextCodeLine();
3434                                           }
3435                                           else
3436                                           {
3437                                             startFontClass("comment");
3438                                             codifyLines(yytext);
3439                                             endFontClass();
3440                                           }
3441                                           if (YY_START==SkipCxxComment)
3442                                           {
3443                                             endFontClass();
3444                                             BEGIN( g_lastCContext ) ;
3445                                           }
3446                                         }
3447 <SkipCPP>\n/.*\n                        { 
3448                                           endFontClass();
3449                                           codifyLines(yytext);
3450                                           BEGIN( g_lastSkipCppContext ) ;
3451                                         }
3452 <*>\n{B}*"//@"[{}].*\n                  { // remove one-line group marker
3453                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3454                                           {
3455                                             g_yyLineNr+=2;
3456                                             nextCodeLine();
3457                                           }
3458                                           else
3459                                           {
3460                                             startFontClass("comment");
3461                                             codifyLines(yytext);
3462                                             endFontClass();
3463                                           }
3464                                           if (YY_START==SkipCxxComment)
3465                                           {
3466                                             endFontClass();
3467                                             BEGIN( g_lastCContext ) ;
3468                                           }
3469                                         }
3470 <*>\n{B}*"/*@"[{}]                      { // remove one-line group marker
3471                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3472                                           {
3473                                             g_lastSpecialCContext = YY_START;
3474                                             g_yyLineNr++;
3475                                             BEGIN(RemoveSpecialCComment);
3476                                           }
3477                                           else
3478                                           {
3479                                             // check is to prevent getting stuck in skipping C++ comments
3480                                             if (YY_START != SkipCxxComment)
3481                                             {
3482                                               g_lastCContext = YY_START ;
3483                                             }
3484                                             startFontClass("comment");
3485                                             codifyLines(yytext);
3486                                             BEGIN(SkipComment);
3487                                           }
3488                                         }
3489 <*>^{B}*"//@"[{}].*\n                   { // remove one-line group marker
3490                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3491                                           {
3492                                             g_yyLineNr++;
3493                                             nextCodeLine();
3494                                           }
3495                                           else
3496                                           {
3497                                             startFontClass("comment");
3498                                             codifyLines(yytext);
3499                                             endFontClass();
3500                                           }
3501                                         }
3502 <*>^{B}*"/*@"[{}]                       { // remove multi-line group marker
3503                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3504                                           {
3505                                             g_lastSpecialCContext = YY_START;
3506                                             BEGIN(RemoveSpecialCComment);
3507                                           }
3508                                           else
3509                                           {
3510                                             // check is to prevent getting stuck in skipping C++ comments
3511                                             if (YY_START != SkipCxxComment)
3512                                             {
3513                                               g_lastCContext = YY_START ;
3514                                             }
3515                                             startFontClass("comment");
3516                                             g_code->codify(yytext);
3517                                             BEGIN(SkipComment);
3518                                           }
3519                                         }
3520 <*>^{B}*"//"[!/][^\n]*\n                { // remove special one-line comment
3521                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3522                                           {
3523                                             g_yyLineNr++;
3524                                             //nextCodeLine();
3525                                           }
3526                                           else
3527                                           {
3528                                             startFontClass("comment");
3529                                             codifyLines(yytext);
3530                                             endFontClass();
3531                                           }
3532                                         }
3533 <*>"//"[!/][^\n]*\n                     { // strip special one-line comment
3534                                           if (YY_START==SkipComment || YY_START==SkipString) REJECT;
3535                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3536                                           {
3537                                             char c[2]; c[0]='\n'; c[1]=0;
3538                                             codifyLines(c);
3539                                           }
3540                                           else
3541                                           {
3542                                             startFontClass("comment");
3543                                             codifyLines(yytext);
3544                                             endFontClass();
3545                                           }
3546                                         }
3547 <*>"/*[tag:"[^\]\n]*"]*/"{B}*           { // special pattern /*[tag:filename]*/ to force linking to a tag file
3548                                           g_forceTagReference=yytext;
3549                                           int s=g_forceTagReference.find(':');
3550                                           int e=g_forceTagReference.findRev(']');
3551                                           g_forceTagReference = g_forceTagReference.mid(s+1,e-s-1);
3552                                         }
3553 <*>\n{B}*"/*"[!*]/[^/*]                 {
3554                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3555                                           {
3556                                             g_lastSpecialCContext = YY_START;
3557                                             g_yyLineNr++;
3558                                             BEGIN(RemoveSpecialCComment);
3559                                           }
3560                                           else
3561                                           {
3562                                             // check is to prevent getting stuck in skipping C++ comments
3563                                             if (YY_START != SkipCxxComment)
3564                                             {
3565                                               g_lastCContext = YY_START ;
3566                                             }
3567                                             startFontClass("comment");
3568                                             codifyLines(yytext);
3569                                             BEGIN(SkipComment);
3570                                           }
3571                                         }
3572 <*>^{B}*"/*"[!*]/[^/*]                  { // special C comment block at a new line
3573                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3574                                           {
3575                                             g_lastSpecialCContext = YY_START;
3576                                             BEGIN(RemoveSpecialCComment);
3577                                           }
3578                                           else
3579                                           {
3580                                             // check is to prevent getting stuck in skipping C++ comments
3581                                             if (YY_START != SkipCxxComment)
3582                                             {
3583                                               g_lastCContext = YY_START ;
3584                                             }
3585                                             startFontClass("comment");
3586                                             g_code->codify(yytext);
3587                                             BEGIN(SkipComment);
3588                                           }
3589                                         }
3590 <*>"/*"[!*]/[^/*]                       { // special C comment block half way a line
3591                                           if (YY_START==SkipString) REJECT;
3592                                           if (Config_getBool(STRIP_CODE_COMMENTS))
3593                                           {
3594                                             g_lastSpecialCContext = YY_START;
3595                                             BEGIN(RemoveSpecialCComment);
3596                                           }
3597                                           else
3598                                           {
3599                                             // check is to prevent getting stuck in skipping C++ comments
3600                                             if (YY_START != SkipCxxComment)
3601                                             {
3602                                               g_lastCContext = YY_START ;
3603                                             }
3604                                             startFontClass("comment");
3605                                             g_code->codify(yytext);
3606                                             BEGIN(SkipComment);
3607                                           }
3608                                         }
3609 <*>"/*"("!"?)"*/"                       { 
3610                                           if (YY_START==SkipString) REJECT;
3611                                           if (!Config_getBool(STRIP_CODE_COMMENTS))
3612                                           {
3613                                             startFontClass("comment");
3614                                             g_code->codify(yytext);
3615                                             endFontClass();
3616                                           }
3617                                         }
3618 <SkipComment>[^\*\n]+                   {
3619                                           g_code->codify(yytext);
3620                                         }
3621 <*>"/*"                                 { 
3622                                           startFontClass("comment");
3623                                           g_code->codify(yytext);
3624                                           // check is to prevent getting stuck in skipping C++ comments
3625                                           if (YY_START != SkipCxxComment)
3626                                           {
3627                                             g_lastCContext = YY_START ;
3628                                           }
3629                                           BEGIN( SkipComment ) ;
3630                                         }
3631 <*>@\"                                  { // C# verbatim string
3632                                           startFontClass("stringliteral");
3633                                           g_code->codify(yytext);
3634                                           g_lastVerbStringContext=YY_START;
3635                                           BEGIN(SkipVerbString);
3636                                         }
3637 <*>"//"                                 { 
3638                                           startFontClass("comment");
3639                                           g_code->codify(yytext);
3640                                           g_lastCContext = YY_START ;
3641                                           BEGIN( SkipCxxComment ) ;
3642                                         }
3643 <*>"("|"["                                      {
3644                                           g_code->codify(yytext);
3645                                           g_theCallContext.pushScope();
3646                                         }
3647 <*>")"|"]"                                      {
3648                                           g_code->codify(yytext);
3649                                           g_theCallContext.popScope();
3650                                         }
3651 <*>\n                                   {
3652                                           g_yyColNr++;
3653                                           codifyLines(yytext); 
3654                                         }
3655 <*>.                                    {
3656                                           g_yyColNr++;
3657                                           g_code->codify(yytext);
3658                                         }
3659   /*
3660 <*>([ \t\n]*"\n"){2,}                   { // combine multiple blank lines
3661                                           //QCString sepLine=yytext;
3662                                           //g_code->codify("\n\n");
3663                                           //g_yyLineNr+=sepLine.contains('\n'); 
3664                                           //char sepLine[3]="\n\n";
3665                                           codifyLines(yytext);
3666                                         }
3667   */
3668
3669 %%
3670
3671 /*@ ----------------------------------------------------------------------------
3672  */
3673
3674 static void saveObjCContext()
3675 {
3676   if (g_currentCtx)
3677   {
3678     g_currentCtx->format+=QCString().sprintf("$c%d",g_currentCtxId);
3679     if (g_braceCount==0 && YY_START==ObjCCall)
3680     {
3681       g_currentCtx->objectTypeOrName=g_currentCtx->format.mid(1);
3682       //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
3683     }
3684     g_contextStack.push(g_currentCtx);
3685   }
3686   else
3687   {
3688     //printf("Trying to save NULL context!\n");
3689   }
3690   ObjCCallCtx *newCtx = new ObjCCallCtx;
3691   newCtx->id = g_currentCtxId;
3692   newCtx->lexState = YY_START;
3693   newCtx->braceCount = g_braceCount;
3694   newCtx->objectType = 0;
3695   newCtx->objectVar = 0;
3696   newCtx->method = 0;
3697   //printf("save state=%d\n",YY_START);
3698   g_contextDict.insert(g_currentCtxId,newCtx);
3699   g_currentCtx = newCtx;
3700   g_braceCount = 0;
3701   g_currentCtxId++;
3702 }
3703
3704 static void restoreObjCContext()
3705 {
3706   //printf("restore state=%d->%d\n",YY_START,g_currentCtx->lexState);
3707   BEGIN(g_currentCtx->lexState);
3708   g_braceCount = g_currentCtx->braceCount;
3709   if (!g_contextStack.isEmpty())
3710   {
3711     g_currentCtx = g_contextStack.pop();
3712   }
3713   else
3714   {
3715     g_currentCtx = 0;
3716     //printf("Trying to pop context while g_contextStack is empty!\n");
3717   }
3718 }
3719
3720 void resetCCodeParserState()
3721 {
3722   //printf("***initParseCodeContext()\n");
3723   g_forceTagReference.resize(0);
3724   g_theVarContext.clear();
3725   g_classScopeLengthStack.setAutoDelete(TRUE);
3726   g_classScopeLengthStack.clear();
3727   delete g_codeClassSDict;
3728   g_codeClassSDict = new ClassSDict(17);
3729   g_codeClassSDict->setAutoDelete(TRUE);
3730   g_codeClassSDict->clear();
3731   g_curClassBases.clear();
3732   g_anchorCount = 0;
3733 }
3734
3735 void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s, 
3736                 SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd,
3737                 int startLine,int endLine,bool inlineFragment,
3738                 MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
3739                 bool collectXRefs)
3740 {
3741   //printf("***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n",
3742   //      exBlock,exName,fd,className,searchCtx?searchCtx->name().data():"<none>");
3743
3744   if (s.isEmpty()) return;
3745
3746   printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
3747
3748   TooltipManager::instance()->clearTooltips();
3749   if (g_codeClassSDict==0)
3750   {
3751     resetCCodeParserState();
3752   }
3753   g_code = &od;
3754   g_inputString   = s;
3755   g_inputPosition = 0;
3756   g_currentFontClass = 0;
3757   g_needsTermination = FALSE;
3758   g_searchCtx = searchCtx;
3759   g_collectXRefs = collectXRefs;
3760   g_inFunctionTryBlock = FALSE;
3761
3762   if (startLine!=-1)
3763     g_yyLineNr    = startLine;
3764   else
3765     g_yyLineNr    = 1;
3766
3767   if (endLine!=-1)
3768     g_inputLines  = endLine+1;
3769   else
3770     g_inputLines  = g_yyLineNr + countLines() - 1;
3771
3772   g_curlyCount    = 0;
3773   g_bodyCurlyCount    = 0;
3774   g_bracketCount  = 0;
3775   g_sharpCount    = 0;
3776   g_insideTemplate = FALSE;
3777   g_theCallContext.clear();
3778   g_scopeStack.clear();
3779   g_classScope    = className;
3780   //printf("parseCCode %s\n",className);
3781   g_exampleBlock  = exBlock; 
3782   g_exampleName   = exName;
3783   g_sourceFileDef = fd;
3784   g_lineNumbers   = fd!=0 && showLineNumbers;
3785   bool cleanupSourceDef = FALSE;
3786   if (fd==0)
3787   {
3788     // create a dummy filedef for the example
3789     g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
3790     cleanupSourceDef = TRUE;
3791   }
3792   g_insideObjC  = lang==SrcLangExt_ObjC;
3793   g_insideJava  = lang==SrcLangExt_Java;
3794   g_insideCS    = lang==SrcLangExt_CSharp;
3795   g_insidePHP   = lang==SrcLangExt_PHP;
3796   g_insideCpp   = lang==SrcLangExt_Cpp;
3797   g_insideSlice = lang==SrcLangExt_Slice;
3798   if (g_sourceFileDef) 
3799   {
3800     setCurrentDoc("l00001");
3801   }
3802   g_currentDefinition = 0;
3803   g_currentMemberDef = 0;
3804   g_searchingForBody = exBlock;
3805   g_insideBody = FALSE;
3806   g_bracketCount = 0;
3807   if (!g_exampleName.isEmpty())
3808   {
3809     g_exampleFile = convertNameToFile(g_exampleName+"-example",FALSE,TRUE);
3810     //printf("g_exampleFile=%s\n",g_exampleFile.data());
3811   }
3812   g_includeCodeFragment = inlineFragment;
3813   //printf("** exBlock=%d exName=%s include=%d\n",exBlock,exName,inlineFragment);
3814   startCodeLine();
3815   g_type.resize(0);
3816   g_name.resize(0);
3817   g_args.resize(0);
3818   g_parmName.resize(0);
3819   g_parmType.resize(0);
3820   if (memberDef) setParameterList(memberDef);
3821   codeYYrestart( codeYYin );
3822   BEGIN( Body );
3823   codeYYlex();
3824   g_lexInit=TRUE;
3825   if (g_needsTermination)
3826   {
3827     endFontClass();
3828     DBG_CTX((stderr,"endCodeLine(%d)\n",g_yyLineNr));
3829     g_code->endCodeLine();
3830   }
3831   if (fd)
3832   {
3833     TooltipManager::instance()->writeTooltips(*g_code);
3834   }
3835   if (cleanupSourceDef)
3836   {
3837     // delete the temporary file definition used for this example
3838     delete g_sourceFileDef;
3839     g_sourceFileDef=0;
3840   }
3841
3842   printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
3843   return;
3844 }
3845
3846 void codeFreeScanner()
3847 {
3848 #if defined(YY_FLEX_SUBMINOR_VERSION) 
3849   if (g_lexInit)
3850   {
3851     codeYYlex_destroy();
3852   }
3853 #endif
3854 }
3855
3856
3857
3858 #if !defined(YY_FLEX_SUBMINOR_VERSION) 
3859 extern "C" { // some bogus code to keep the compiler happy
3860   void codeYYdummy() { yy_flex_realloc(0,0); } 
3861 }
3862 #elif YY_FLEX_MAJOR_VERSION<=2 && YY_FLEX_MINOR_VERSION<=5 && YY_FLEX_SUBMINOR_VERSION<33
3863 #error "You seem to be using a version of flex newer than 2.5.4. These are currently incompatible with 2.5.4, and do NOT work with doxygen! Please use version 2.5.4 or expect things to be parsed wrongly! A bug report has been submitted (#732132)."
3864 #endif
3865