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