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