0d23553e1b09390e0600735a1da80ba33ec450e0
[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), cd(0) {}
333       QCString name;
334       QCString type;
335       ClassDef *cd;
336     };
337
338     CallContext() 
339     {
340       m_classList.append(new Ctx);
341       m_classList.setAutoDelete(TRUE);
342     }
343     virtual ~CallContext() {}
344     void setClass(ClassDef *cd)
345     {
346       Ctx *ctx = m_classList.getLast();
347       if (ctx)
348       {
349         DBG_CTX((stderr,"** Set call context %s (%p)\n",cd==0 ? "<null>" : cd->name().data(),cd));
350         ctx->cd=cd;
351       }
352     }
353     void pushScope()
354     {
355       m_classList.append(new Ctx);
356       DBG_CTX((stderr,"** Push call context %d\n",m_classList.count()));
357     }
358     void popScope()
359     {
360       if (m_classList.count()>1)
361       {
362         DBG_CTX((stderr,"** Pop call context %d\n",m_classList.count()));
363         Ctx *ctx = m_classList.getLast();
364         if (ctx)
365         {
366           g_name = ctx->name;
367           g_type = ctx->type;
368         }
369         m_classList.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_classList.clear();
380       m_classList.append(new Ctx);
381     }
382     ClassDef *getClass() const
383     {
384       Ctx *ctx = m_classList.getLast();
385       if (ctx) return ctx->cd; else return 0;
386     }
387
388   private:
389     QList<Ctx> m_classList;    
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.setClass(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.setClass(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.setClass(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.setClass(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.setClass(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.setClass(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   ClassDef *cd = g_theCallContext.getClass();
833   //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? cd->name().data() : "<none>");
834   MemberDef *md;
835   if (cd && (md=cd->isSmartPointer()))
836   {
837     ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope());
838     if (ncd)
839     {
840       g_theCallContext.setClass(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.setClass(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     //printf("md=%s\n",md?md->name().data():"<none>");
969     DBG_CTX((stderr,"is found as a type %s\n",cd?cd->name().data():"<null>"));
970     if (cd==0 && md==0) // also see if it is variable or enum or enum value
971     {
972       if (getLink(g_classScope,clName,ol,clName,varOnly))
973       {
974         return;
975       }
976     }
977   }
978   else
979   {
980     //printf("local variable!\n");
981     if (lcd!=VariableContext::dummyContext) 
982     {
983       //printf("non-dummy context lcd=%s!\n",lcd->name().data());
984       g_theCallContext.setClass(lcd);
985
986       // to following is needed for links to a global variable, but is
987       // no good for a link to a local variable that is also a global symbol.
988        
989       //if (getLink(g_classScope,clName,ol,clName))
990       //{
991         //return;
992       //}
993     }
994     isLocal=TRUE;
995     DBG_CTX((stderr,"is a local variable cd=%p!\n",cd));
996   }
997   if (cd && cd->isLinkable()) // is it a linkable class
998   {
999     DBG_CTX((stderr,"is linkable class %s\n",clName));
1000     if (g_exampleBlock)
1001     {
1002       QCString anchor;
1003       anchor.sprintf("_a%d",g_anchorCount);
1004       //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
1005       //                                   g_exampleFile.data());
1006       if (cd->addExample(anchor,g_exampleName,g_exampleFile))
1007       {
1008         ol.writeCodeAnchor(anchor);
1009         g_anchorCount++;
1010       }
1011     }
1012     writeMultiLineCodeLink(ol,cd,clName);
1013     addToSearchIndex(className);
1014     g_theCallContext.setClass(cd);
1015     if (md)
1016     {
1017       Definition *d = md->getOuterScope()==Doxygen::globalScope ?
1018                       md->getFileDef() : md->getOuterScope();
1019       if (md->getGroupDef()) d = md->getGroupDef();
1020       if (d && d->isLinkable() && md->isLinkable() && 
1021           g_currentMemberDef && g_collectXRefs)
1022       {
1023         addDocCrossReference(g_currentMemberDef,md);
1024       }
1025     }
1026   }
1027   else // not a class, maybe a global member
1028   {
1029     DBG_CTX((stderr,"class %s not linkable! cd=%p md=%p typeOnly=%d\n",clName,cd,md,typeOnly));
1030     if (!isLocal && (md!=0 || (cd==0 && !typeOnly))) // not a class, see if it is a global enum/variable/typedef.
1031     {
1032       if (md==0) // not found as a typedef
1033       {
1034         md = setCallContextForVar(clName);
1035         //printf("setCallContextForVar(%s) md=%p g_currentDefinition=%p\n",clName,md,g_currentDefinition);
1036         if (md && g_currentDefinition)
1037         {
1038           DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n",
1039               md->name().data(),g_currentDefinition->name().data(),
1040               isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md),
1041               md->getOuterScope()->name().data()));
1042         }
1043              
1044         if (md && g_currentDefinition && 
1045             isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md)==-1)
1046         {
1047           md=0; // variable not accessible
1048         }
1049       }
1050       if (md && (!varOnly || md->isVariable()))
1051       {
1052         DBG_CTX((stderr,"is a global md=%p g_currentDefinition=%s linkable=%d\n",md,g_currentDefinition?g_currentDefinition->name().data():"<none>",md->isLinkable()));
1053         if (md->isLinkable())
1054         {
1055           QCString text;
1056           if (!g_forceTagReference.isEmpty()) // explicit reference to symbol in tag file
1057           {
1058             text=g_forceTagReference;
1059             if (text.right(4)==".tag") // strip .tag if present
1060             {
1061               text=text.left(text.length()-4);
1062             }
1063             text+=getLanguageSpecificSeparator(md->getLanguage());
1064             text+=clName;
1065             md->setName(text);
1066             md->setLocalName(text);
1067           }
1068           else // normal reference
1069           {
1070             text=clName;
1071           }
1072           writeMultiLineCodeLink(ol,md,text);
1073           addToSearchIndex(clName);
1074           if (g_currentMemberDef && g_collectXRefs)
1075           {
1076             addDocCrossReference(g_currentMemberDef,md);
1077           }
1078           return;
1079         }
1080       }
1081     }
1082     
1083     // nothing found, just write out the word
1084     DBG_CTX((stderr,"not found!\n"));
1085     codifyLines(clName);
1086     addToSearchIndex(clName);
1087   }
1088 }
1089
1090 static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const char *memName)
1091 {
1092   // extract class definition of the return type in order to resolve
1093   // a->b()->c() like call chains
1094
1095   //printf("type=`%s' args=`%s' class=%s\n",
1096   //  xmd->typeString(),xmd->argsString(),
1097   //  xmd->getClassDef()->name().data());
1098
1099   if (g_exampleBlock)
1100   {
1101     QCString anchor;
1102     anchor.sprintf("a%d",g_anchorCount);
1103     //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
1104     //                                  g_exampleFile.data());
1105     if (xmd->addExample(anchor,g_exampleName,g_exampleFile))
1106     {
1107       ol.writeCodeAnchor(anchor);
1108       g_anchorCount++;
1109     }
1110   }
1111
1112   ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope());
1113   DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass));
1114   g_theCallContext.setClass(typeClass);
1115
1116   Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
1117                    xmd->getFileDef() : xmd->getOuterScope();
1118   if (xmd->getGroupDef()) xd = xmd->getGroupDef();
1119   if (xd && xd->isLinkable())
1120   {
1121
1122     //printf("g_currentDefiniton=%p g_currentMemberDef=%p xmd=%p g_insideBody=%d\n",g_currentDefinition,g_currentMemberDef,xmd,g_insideBody);
1123
1124     if (xmd->templateMaster()) xmd = xmd->templateMaster();
1125
1126     if (xmd->isLinkable())
1127     {
1128       // add usage reference
1129       if (g_currentDefinition && g_currentMemberDef &&
1130           /*xmd!=g_currentMemberDef &&*/ g_insideBody && g_collectXRefs)
1131       {
1132         addDocCrossReference(g_currentMemberDef,xmd);
1133       }
1134
1135       // write the actual link
1136       writeMultiLineCodeLink(ol,xmd,memName);
1137       addToSearchIndex(memName);
1138       return TRUE;
1139     }
1140   }
1141
1142   return FALSE;
1143 }
1144
1145 static bool generateClassMemberLink(CodeOutputInterface &ol,ClassDef *mcd,const char *memName)
1146 {
1147   if (mcd)
1148   {
1149     MemberDef *xmd = mcd->getMemberByName(memName);
1150     //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",mcd->name().data(),memName,xmd);
1151     if (xmd)
1152     {
1153       return generateClassMemberLink(ol,xmd,memName);
1154     }
1155   }
1156   
1157   return FALSE;
1158 }
1159
1160 static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName,
1161             char *memName)
1162 {
1163   //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n",
1164   //    varName.data(),memName,g_classScope.data());
1165
1166   if (varName.isEmpty()) return;
1167
1168   // look for the variable in the current context
1169   ClassDef *vcd = g_theVarContext.findVariable(varName);
1170   if (vcd) 
1171   {
1172     if (vcd!=VariableContext::dummyContext)
1173     {
1174       //printf("Class found!\n");
1175       if (getLink(vcd->name(),memName,ol)) 
1176       {
1177         //printf("Found result!\n");
1178         return;
1179       }
1180       if (vcd->baseClasses())
1181       {
1182         BaseClassListIterator bcli(*vcd->baseClasses());
1183         for ( ; bcli.current() ; ++bcli)
1184         {
1185           if (getLink(bcli.current()->classDef->name(),memName,ol)) 
1186           {
1187             //printf("Found result!\n");
1188             return;
1189           }
1190         }
1191       }
1192     }
1193   }
1194   else // variable not in current context, maybe it is in a parent context
1195   {
1196     vcd = getResolvedClass(g_currentDefinition,g_sourceFileDef,g_classScope);
1197     if (vcd && vcd->isLinkable())
1198     {
1199       //printf("Found class %s for variable `%s'\n",g_classScope.data(),varName.data());
1200       MemberName *vmn=Doxygen::memberNameSDict->find(varName);
1201       if (vmn==0)
1202       {
1203         int vi;
1204         QCString vn=varName;
1205         QCString scope;
1206         if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1)  // explicit scope A::b(), probably static member
1207         {
1208           ClassDef *jcd = getClass(vn.left(vi));
1209           vn=vn.right(vn.length()-vi-2);
1210           vmn=Doxygen::memberNameSDict->find(vn);
1211           //printf("Trying name `%s' scope=%s\n",vn.data(),scope.data());
1212           if (vmn)
1213           {
1214             MemberNameIterator vmni(*vmn);
1215             MemberDef *vmd;
1216             for (;(vmd=vmni.current());++vmni)
1217             {
1218               if (/*(vmd->isVariable() || vmd->isFunction()) && */
1219                   vmd->getClassDef()==jcd)
1220               {
1221                 //printf("Found variable type=%s\n",vmd->typeString());
1222                 ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1223                 if (mcd && mcd->isLinkable())
1224                 {
1225                   if (generateClassMemberLink(ol,mcd,memName)) return;
1226                 }
1227               }
1228             }
1229           }
1230         }
1231       }
1232       if (vmn)
1233       {
1234         //printf("There is a variable with name `%s'\n",varName);
1235         MemberNameIterator vmni(*vmn);
1236         MemberDef *vmd;
1237         for (;(vmd=vmni.current());++vmni)
1238         {
1239           if (/*(vmd->isVariable() || vmd->isFunction()) && */
1240               vmd->getClassDef()==vcd)
1241           {
1242             //printf("Found variable type=%s\n",vmd->typeString());
1243             ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1244             if (mcd && mcd->isLinkable())
1245             {
1246               if (generateClassMemberLink(ol,mcd,memName)) return;
1247             }
1248           }
1249         }
1250       }
1251     }
1252   }
1253   // nothing found -> write result as is
1254   codifyLines(memName);
1255   addToSearchIndex(memName);
1256   return;
1257 }
1258
1259 static void generatePHPVariableLink(CodeOutputInterface &ol,const char *varName)
1260 {
1261   QCString name = varName+7; // strip $this->
1262   name.prepend("$");
1263   //printf("generatePHPVariableLink(%s) name=%s scope=%s\n",varName,name.data(),g_classScope.data());
1264   if (!getLink(g_classScope,name,ol,varName))
1265   {
1266     codifyLines(varName);
1267   }
1268 }
1269
1270 static void generateFunctionLink(CodeOutputInterface &ol,const char *funcName)
1271 {
1272   //CodeClassDef *ccd=0;
1273   ClassDef *ccd=0;
1274   QCString locScope=g_classScope;
1275   QCString locFunc=removeRedundantWhiteSpace(funcName);
1276   QCString funcScope;
1277   QCString funcWithScope=locFunc;
1278   QCString funcWithFullScope=locFunc;
1279   QCString fullScope=locScope;
1280   DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data()));
1281   int len=2;
1282   int i=locFunc.findRev("::");
1283   if (g_currentMemberDef && g_currentMemberDef->getClassDef() &&
1284       funcName==g_currentMemberDef->localName() && 
1285       g_currentMemberDef->getDefLine()==g_yyLineNr &&
1286       generateClassMemberLink(ol,g_currentMemberDef,funcName)
1287      )
1288   {
1289     // special case where funcName is the name of a method that is also
1290     // defined on this line. In this case we can directly link to 
1291     // g_currentMemberDef, which is not only faster, but
1292     // in case of overloaded methods, this will make sure that we link to
1293     // the correct method, and thereby get the correct reimplemented relations.
1294     // See also bug 549022.
1295     goto exit;
1296   }
1297   if (i==-1) i=locFunc.findRev("."),len=1;
1298   if (i==-1) i=locFunc.findRev("\\"),len=1; // for PHP
1299   if (i>0)
1300   {
1301     funcScope=locFunc.left(i);
1302     locFunc=locFunc.right(locFunc.length()-i-len).stripWhiteSpace();
1303     int ts=locScope.find('<'); // start of template
1304     int te=locScope.findRev('>'); // end of template
1305     //printf("ts=%d te=%d\n",ts,te);
1306     if (ts!=-1 && te!=-1 && te>ts)
1307     {
1308       // remove template from scope
1309       locScope=locScope.left(ts)+locScope.right(locScope.length()-te-1);
1310     }
1311     ts=funcScope.find('<'); // start of template
1312     te=funcScope.findRev('>'); // end of template
1313     //printf("ts=%d te=%d\n",ts,te);
1314     if (ts!=-1 && te!=-1 && te>ts)
1315     {
1316       // remove template from scope
1317       funcScope=funcScope.left(ts)+funcScope.right(funcScope.length()-te-1);
1318     }
1319     if (!funcScope.isEmpty())
1320     {
1321       funcWithScope = funcScope+"::"+locFunc;
1322       if (!locScope.isEmpty())
1323       {
1324         fullScope=locScope+"::"+funcScope;
1325       }
1326     }
1327     if (!locScope.isEmpty())
1328     {
1329       funcWithFullScope = locScope+"::"+funcWithScope;
1330     }
1331   }
1332   if (!fullScope.isEmpty() && (ccd=g_codeClassSDict->find(fullScope)))
1333   {
1334     //printf("using classScope %s\n",g_classScope.data());
1335     if (ccd->baseClasses())
1336     {
1337       BaseClassListIterator bcli(*ccd->baseClasses());
1338       for ( ; bcli.current() ; ++bcli)
1339       {
1340         if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName)) 
1341         {
1342           goto exit;
1343         }
1344       }
1345     }
1346   }
1347   if (!locScope.isEmpty() && fullScope!=locScope && (ccd=g_codeClassSDict->find(locScope)))
1348   {
1349     //printf("using classScope %s\n",g_classScope.data());
1350     if (ccd->baseClasses())
1351     {
1352       BaseClassListIterator bcli(*ccd->baseClasses());
1353       for ( ; bcli.current() ; ++bcli)
1354       {
1355         if (getLink(bcli.current()->classDef->name(),funcWithScope,ol,funcName)) 
1356         {
1357           goto exit;
1358         }
1359       }
1360     }
1361   }
1362   if (!getLink(locScope,funcWithScope,ol,funcName))
1363   {
1364     generateClassOrGlobalLink(ol,funcName);
1365   }
1366 exit:  
1367   g_forceTagReference.resize(0);
1368   return;
1369 }
1370
1371 /*! counts the number of lines in the input */
1372 static int countLines()
1373 {
1374   const char *p=g_inputString;
1375   char c;
1376   int count=1;
1377   while ((c=*p)) 
1378   { 
1379     p++ ; 
1380     if (c=='\n') count++;  
1381   }
1382   if (p>g_inputString && *(p-1)!='\n') 
1383   { // last line does not end with a \n, so we add an extra
1384     // line and explicitly terminate the line after parsing.
1385     count++, 
1386     g_needsTermination=TRUE; 
1387   } 
1388   return count;
1389 }
1390
1391 static void endFontClass()
1392 {
1393   if (g_currentFontClass)
1394   {
1395     g_code->endFontClass();
1396     g_currentFontClass=0;
1397   }
1398 }
1399
1400 static void startFontClass(const char *s)
1401 {
1402   endFontClass();
1403   g_code->startFontClass(s);
1404   g_currentFontClass=s;
1405 }
1406
1407 //----------------------------------------------------------------------------
1408
1409 // recursively writes a linkified Objective-C method call
1410 static void writeObjCMethodCall(ObjCCallCtx *ctx)
1411 {
1412   if (ctx==0) return;
1413   char c;
1414   const char *p = ctx->format.data();
1415   if (!ctx->methodName.isEmpty())
1416   {
1417     //printf("writeObjCMethodCall(%s) obj=%s method=%s\n",
1418     //    ctx->format.data(),ctx->objectTypeOrName.data(),ctx->methodName.data());
1419     if (!ctx->objectTypeOrName.isEmpty() && ctx->objectTypeOrName.at(0)!='$')
1420     {
1421       //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(),
1422       //        ctx->methodName.data());
1423       ClassDef *cd = g_theVarContext.findVariable(ctx->objectTypeOrName);
1424       if (cd==0) // not a local variable
1425       {
1426         if (ctx->objectTypeOrName=="self")
1427         {
1428           if (g_currentDefinition && 
1429               g_currentDefinition->definitionType()==Definition::TypeClass)
1430           {
1431             ctx->objectType = (ClassDef *)g_currentDefinition;
1432           }
1433         }
1434         else
1435         {
1436           ctx->objectType = getResolvedClass(
1437               g_currentDefinition,
1438               g_sourceFileDef,
1439               ctx->objectTypeOrName,
1440               &ctx->method);
1441         }
1442         //printf("  object is class? %p\n",ctx->objectType);
1443         if (ctx->objectType) // found class
1444         {
1445           ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1446           //printf("    yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>");
1447         }
1448         else if (ctx->method==0) // search for class variable with the same name
1449         {
1450           //printf("    no\n");
1451           //printf("g_currentDefinition=%p\n",g_currentDefinition);
1452           if (g_currentDefinition && 
1453               g_currentDefinition->definitionType()==Definition::TypeClass)
1454           {
1455             ctx->objectVar = ((ClassDef *)g_currentDefinition)->getMemberByName(ctx->objectTypeOrName);
1456             //printf("      ctx->objectVar=%p\n",ctx->objectVar);
1457             if (ctx->objectVar)
1458             {
1459               ctx->objectType = stripClassName(ctx->objectVar->typeString());
1460               //printf("        ctx->objectType=%p\n",ctx->objectType);
1461               if (ctx->objectType)
1462               {
1463                 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1464                 //printf("          ctx->method=%p\n",ctx->method);
1465               }
1466             }
1467           }
1468         }
1469       }
1470       else // local variable
1471       {
1472         //printf("  object is local variable\n");
1473         if (cd!=VariableContext::dummyContext)
1474         {
1475           ctx->method = cd->getMemberByName(ctx->methodName);
1476           //printf("   class=%p method=%p\n",cd,ctx->method);
1477         }
1478       }
1479     }
1480   }
1481
1482   //printf("[");
1483   while ((c=*p++)) // for each character in ctx->format
1484   {
1485     if (c=='$')
1486     {
1487       char nc=*p++;
1488       if (nc=='$') // escaped $
1489       {
1490         g_code->codify("$");
1491       }
1492       else // name fragment or reference to a nested call 
1493       {
1494         if (nc=='n') // name fragment
1495         {
1496           nc=*p++;
1497           QCString refIdStr;
1498           while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1499           p--;
1500           int refId=refIdStr.toInt();
1501           QCString *pName = g_nameDict.find(refId);
1502           if (pName)
1503           {
1504             if (ctx->method && ctx->method->isLinkable())
1505             {
1506               writeMultiLineCodeLink(*g_code,ctx->method,pName->data());
1507               if (g_currentMemberDef && g_collectXRefs)
1508               {
1509                 addDocCrossReference(g_currentMemberDef,ctx->method);
1510               }
1511             }
1512             else
1513             {
1514               codifyLines(pName->data());
1515             }
1516           }
1517           else
1518           {
1519             //printf("Invalid name: id=%d\n",refId);
1520           }
1521         }
1522         else if (nc=='o') // reference to potential object name
1523         {
1524           nc=*p++;
1525           QCString refIdStr;
1526           while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1527           p--;
1528           int refId=refIdStr.toInt();
1529           QCString *pObject = g_objectDict.find(refId);
1530           if (pObject)
1531           {
1532             if (*pObject=="self")
1533             {
1534               if (g_currentDefinition && 
1535                   g_currentDefinition->definitionType()==Definition::TypeClass)
1536               {
1537                 ctx->objectType = (ClassDef *)g_currentDefinition;
1538                 if (ctx->objectType->categoryOf()) 
1539                 {
1540                   ctx->objectType = ctx->objectType->categoryOf();
1541                 }
1542                 if (ctx->objectType)
1543                 {
1544                   ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1545                 }
1546               }
1547               startFontClass("keyword");
1548               codifyLines(pObject->data());
1549               endFontClass();
1550             }
1551             else if (*pObject=="super")
1552             {
1553               if (g_currentDefinition &&
1554                   g_currentDefinition->definitionType()==Definition::TypeClass)
1555               {
1556                 ClassDef *cd = (ClassDef *)g_currentDefinition;
1557                 if (cd->categoryOf()) 
1558                 {
1559                   cd = cd->categoryOf();
1560                 }
1561                 BaseClassList *bcd = cd->baseClasses();
1562                 if (bcd) // get direct base class (there should be only one)
1563                 {
1564                   BaseClassListIterator bli(*bcd);
1565                   BaseClassDef *bclass;
1566                   for (bli.toFirst();(bclass=bli.current());++bli)
1567                   {
1568                     if (bclass->classDef->compoundType()!=ClassDef::Protocol)
1569                     {
1570                       ctx->objectType = bclass->classDef;
1571                       if (ctx->objectType)
1572                       {
1573                         ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1574                       }
1575                     }
1576                   }
1577                 }
1578               }
1579               startFontClass("keyword");
1580               codifyLines(pObject->data());
1581               endFontClass();
1582             }
1583             else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable
1584             {
1585               writeMultiLineCodeLink(*g_code,ctx->objectVar,pObject->data());
1586               if (g_currentMemberDef && g_collectXRefs)
1587               {
1588                 addDocCrossReference(g_currentMemberDef,ctx->objectVar);
1589               }
1590             }
1591             else if (ctx->objectType && 
1592                      ctx->objectType!=VariableContext::dummyContext && 
1593                      ctx->objectType->isLinkable()
1594                     ) // object is class name
1595             {
1596               ClassDef *cd = ctx->objectType;
1597               writeMultiLineCodeLink(*g_code,cd,pObject->data());
1598             }
1599             else // object still needs to be resolved
1600             {
1601               ClassDef *cd = getResolvedClass(g_currentDefinition, 
1602                   g_sourceFileDef, *pObject);
1603               if (cd && cd->isLinkable())
1604               {
1605                 if (ctx->objectType==0) ctx->objectType=cd;
1606                 writeMultiLineCodeLink(*g_code,cd,pObject->data());
1607               }
1608               else
1609               {
1610                 codifyLines(pObject->data());
1611               }
1612             }
1613           }
1614           else
1615           {
1616             //printf("Invalid object: id=%d\n",refId);
1617           }
1618         }
1619         else if (nc=='c') // reference to nested call
1620         {
1621           nc=*p++;
1622           QCString refIdStr;
1623           while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1624           p--;
1625           int refId=refIdStr.toInt();
1626           ObjCCallCtx *ictx = g_contextDict.find(refId);
1627           if (ictx) // recurse into nested call
1628           {
1629             writeObjCMethodCall(ictx);
1630             if (ictx->method) // link to nested call successfully
1631             {
1632               // get the ClassDef representing the method's return type
1633               if (QCString(ictx->method->typeString())=="id")
1634               {
1635                 // see if the method name is unique, if so we link to it
1636                 MemberName *mn=Doxygen::memberNameSDict->find(ctx->methodName);
1637                 //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n",
1638                 //    mn==0?-1:(int)mn->count(),
1639                 //    ictx->method->name().data(),
1640                 //    ctx->methodName.data());
1641                 if (mn && mn->count()==1) // member name unique
1642                 {
1643                   ctx->method = mn->getFirst();
1644                 }
1645               } 
1646               else
1647               {
1648                 ctx->objectType = stripClassName(ictx->method->typeString());
1649                 if (ctx->objectType)
1650                 {
1651                   ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1652                 }
1653               }
1654               //printf("  ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType);
1655             }
1656           }
1657           else
1658           {
1659             //printf("Invalid context: id=%d\n",refId);
1660           }
1661         }
1662         else if (nc=='w') // some word
1663         {
1664           nc=*p++;
1665           QCString refIdStr;
1666           while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1667           p--;
1668           int refId=refIdStr.toInt();
1669           QCString *pWord = g_wordDict.find(refId);
1670           if (pWord)
1671           {
1672             codifyLines(pWord->data());
1673           }
1674         }
1675         else // illegal marker
1676         {
1677           ASSERT(!"invalid escape sequence");
1678         }
1679       }
1680     }
1681     else // normal non-marker character
1682     {
1683       char s[2];
1684       s[0]=c;s[1]=0;
1685       codifyLines(s);
1686     }
1687   }  
1688   //printf("%s %s]\n",ctx->objectTypeOrName.data(),ctx->methodName.data());
1689   //printf("}=(type='%s',name='%s')",
1690   //    ctx->objectTypeOrName.data(),
1691   //    ctx->methodName.data());
1692 }
1693
1694 // Replaces an Objective-C method name fragment s by a marker of the form
1695 // $n12, the number (12) can later be used as a key for obtaining the name 
1696 // fragment, from g_nameDict
1697 static QCString escapeName(const char *s)
1698 {
1699   QCString result;
1700   result.sprintf("$n%d",g_currentNameId);
1701   g_nameDict.insert(g_currentNameId,new QCString(s));
1702   g_currentNameId++;
1703   return result;
1704 }
1705
1706 static QCString escapeObject(const char *s)
1707 {
1708   QCString result;
1709   result.sprintf("$o%d",g_currentObjId);
1710   g_objectDict.insert(g_currentObjId,new QCString(s));
1711   g_currentObjId++;
1712   return result;
1713 }
1714
1715 static QCString escapeWord(const char *s)
1716 {
1717   QCString result;
1718   result.sprintf("$w%d",g_currentWordId);
1719   g_wordDict.insert(g_currentWordId,new QCString(s));
1720   g_currentWordId++;
1721   return result;
1722 }
1723
1724 /* -----------------------------------------------------------------
1725  */
1726 #undef  YY_INPUT
1727 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
1728
1729 static int yyread(char *buf,int max_size)
1730 {
1731     int c=0;
1732     while( c < max_size && g_inputString[g_inputPosition] )
1733     {
1734         *buf = g_inputString[g_inputPosition++] ;
1735         c++; buf++;
1736     }
1737     return c;
1738 }
1739
1740 %}
1741
1742 B       [ \t]
1743 BN      [ \t\n\r]
1744 ID      "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
1745 SEP     ("::"|"\\")
1746 SEPCS   (".")
1747 SCOPENAME ({SEP}{BN}*)?({ID}{BN}*{SEP}{BN}*)*("~"{BN}*)?{ID}
1748 SCOPENAMECS ({SEPCS}{BN}*)?({ID}{BN}*{SEPCS}{BN}*)*("~"{BN}*)?{ID}
1749 TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">"
1750 SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?{SEP}{BN}*)*)((~{BN}*)?{ID})
1751 SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*{SEP}{BN}*)+
1752 KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property")
1753 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})
1754 FLOWKW  ("break"|"case"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"for"|"foreach"|"for each"|"goto"|"if"|"return"|"switch"|"throw"|"throws"|"try"|"while"|"@try"|"@catch"|"@finally")
1755 TYPEKW  ("bool"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
1756 CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast")
1757 CHARLIT   (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'"))
1758 ARITHOP "+"|"-"|"/"|"*"|"%"|"--"|"++"
1759 ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|="
1760 LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"
1761 BITOP   "&"|"|"|"^"|"<<"|">>"|"~"
1762 OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
1763 RAWBEGIN  (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"("
1764 RAWEND    ")"[^ \t\(\)\\]{0,16}\"
1765
1766 %option noyywrap
1767
1768 %x      SkipString
1769 %x      SkipStringS
1770 %x      SkipVerbString
1771 %x      SkipCPP
1772 %x      SkipComment
1773 %x      SkipCxxComment
1774 %x      RemoveSpecialCComment
1775 %x      StripSpecialCComment
1776 %x      Body
1777 %x      FuncCall
1778 %x      MemberCall
1779 %x      MemberCall2
1780 %x      SkipInits
1781 %x      ClassName
1782 %x      AlignAs
1783 %x      AlignAsEnd
1784 %x      PackageName
1785 %x      ClassVar
1786 %x      CppCliTypeModifierFollowup
1787 %x      Bases
1788 %x      SkipSharp
1789 %x      ReadInclude
1790 %x      TemplDecl
1791 %x      TemplCast
1792 %x      CallEnd
1793 %x      ObjCMethod
1794 %x      ObjCParams
1795 %x      ObjCParamType
1796 %x      ObjCCall
1797 %x      ObjCMName
1798 %x      ObjCSkipStr
1799 %x      OldStyleArgs
1800 %x      UsingName
1801 %x      RawString
1802 %x      InlineInit
1803
1804 %%
1805
1806 <*>\x0d
1807 <Body>^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") {
1808                                           startFontClass("preprocessor");
1809                                           g_code->codify(yytext);
1810                                           BEGIN( ReadInclude ); 
1811                                         }
1812 <Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ { 
1813                                           g_insideObjC=TRUE;
1814                                           startFontClass("keyword");
1815                                           codifyLines(yytext);
1816                                           endFontClass();
1817                                           if (!g_insideTemplate) 
1818                                             BEGIN( ClassName ); 
1819                                         }
1820 <Body>(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") {
1821                                           if (g_insideTemplate) REJECT;
1822                                           startFontClass("keyword");
1823                                           codifyLines(yytext);
1824                                           endFontClass();
1825                                           BEGIN( ClassName ); 
1826                                         }
1827 <Body>"property"|"event"/{BN}*                  { 
1828                                           if (g_insideTemplate) REJECT;
1829                                           startFontClass("keyword");
1830                                           codifyLines(yytext);
1831                                           endFontClass();
1832                                         }
1833 <Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ { 
1834                                           startFontClass("keyword");
1835                                           codifyLines(yytext);
1836                                           endFontClass();
1837                                           if (!g_insideTemplate) 
1838                                             BEGIN( ClassName ); 
1839                                         }
1840 <Body>("package")[ \t\n]+               { 
1841                                           startFontClass("keyword");
1842                                           codifyLines(yytext);
1843                                           endFontClass();
1844                                           BEGIN( PackageName ); 
1845                                         }
1846 <ClassVar>\n                            {
1847                                           if (!g_insideObjC) REJECT;
1848                                           codifyLines(yytext);
1849                                           BEGIN(Body);
1850                                         }
1851 <Body,ClassVar,Bases>"-"|"+"            {
1852                                           if (!g_insideObjC || g_insideBody)
1853                                           { 
1854                                             g_code->codify(yytext);
1855                                           }
1856                                           else // Start of Objective-C method
1857                                           {
1858                                             //printf("Method!\n");
1859                                             g_code->codify(yytext);
1860                                             BEGIN(ObjCMethod);
1861                                           }
1862                                         }
1863 <ObjCMethod>":"                         {
1864                                           g_code->codify(yytext);
1865                                           BEGIN(ObjCParams);
1866                                         }
1867 <ObjCParams>"("                         {
1868                                           g_code->codify(yytext);
1869                                           BEGIN(ObjCParamType);
1870                                         }
1871 <ObjCParams,ObjCMethod>";"|"{"          {
1872                                           g_code->codify(yytext);
1873                                           if (*yytext=='{')
1874                                           {
1875                                             g_curlyCount++;
1876                                             if (g_searchingForBody)
1877                                             {
1878                                               g_searchingForBody=FALSE;
1879                                               g_insideBody=TRUE;
1880                                             }
1881                                             if (g_insideBody) g_bodyCurlyCount++;
1882                                             if (!g_curClassName.isEmpty()) // valid class name
1883                                             {
1884                                               pushScope(g_curClassName);
1885                                               DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
1886                                               g_scopeStack.push(SCOPEBLOCK);
1887                                             }
1888                                           }
1889                                           g_type.resize(0);
1890                                           g_name.resize(0);
1891                                           BEGIN(Body);
1892                                         }
1893 <ObjCParams>{ID}{B}*":"                 {
1894                                           g_code->codify(yytext);
1895                                         }
1896 <ObjCParamType>{TYPEKW}                 {
1897                                           startFontClass("keywordtype");
1898                                           g_code->codify(yytext);
1899                                           endFontClass();
1900                                           g_parmType=yytext;
1901                                         }
1902 <ObjCParamType>{ID}                     {
1903                                           generateClassOrGlobalLink(*g_code,yytext);
1904                                           g_parmType=yytext;
1905                                         }
1906 <ObjCParamType>")"                      {
1907                                           g_code->codify(yytext);
1908                                           BEGIN(ObjCParams);
1909                                         }
1910 <ObjCParams>{ID}                        {
1911                                           g_code->codify(yytext);
1912                                           g_parmName=yytext;
1913                                           g_theVarContext.addVariable(g_parmType,g_parmName);
1914                                           g_parmType.resize(0);g_parmName.resize(0);
1915                                         }
1916 <ObjCMethod,ObjCParams,ObjCParamType>{ID} {
1917                                           generateClassOrGlobalLink(*g_code,yytext);
1918                                         }
1919 <ObjCMethod,ObjCParams,ObjCParamType>.  {
1920                                           g_code->codify(yytext);
1921                                         }
1922 <ObjCMethod,ObjCParams,ObjCParamType>\n {
1923                                           codifyLines(yytext);
1924                                         }
1925 <ReadInclude>[^\n\"\>]+/(">"|"\"")      {
1926                                           //FileInfo *f;
1927                                           bool ambig;
1928                                           bool found=FALSE;
1929                                           //QCString absPath = yytext;
1930                                           //if (g_sourceFileDef && QDir::isRelativePath(absPath))
1931                                           //{
1932                                           //  absPath = QDir::cleanDirPath(g_sourceFileDef->getPath()+"/"+absPath);
1933                                           //}
1934
1935                                           FileDef *fd=findFileDef(Doxygen::inputNameDict,yytext,ambig);
1936                                           //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd);
1937                                           if (fd && fd->isLinkable())
1938                                           {
1939                                             if (ambig) // multiple input files match the name
1940                                             {
1941                                               //printf("===== yes %s is ambiguous\n",yytext);
1942                                               QCString name = QDir::cleanDirPath(yytext).utf8();
1943                                               if (!name.isEmpty() && g_sourceFileDef)
1944                                               {
1945                                                 FileName *fn = Doxygen::inputNameDict->find(name);
1946                                                 if (fn)
1947                                                 {
1948                                                   FileNameIterator fni(*fn);
1949                                                   // for each include name
1950                                                   for (fni.toFirst();!found && (fd=fni.current());++fni)
1951                                                   {
1952                                                     // see if this source file actually includes the file
1953                                                     found = g_sourceFileDef->isIncluded(fd->absFilePath());
1954                                                     //printf("      include file %s found=%d\n",fd->absFilePath().data(),found);
1955                                                   }
1956                                                 }
1957                                               }
1958                                             }
1959                                             else // not ambiguous
1960                                             {
1961                                               found = TRUE;
1962                                             }
1963                                           }
1964                                           //printf("      include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found);
1965                                           if (found)
1966                                           {
1967                                             writeMultiLineCodeLink(*g_code,fd,yytext);
1968                                           }
1969                                           else
1970                                           {
1971                                             g_code->codify(yytext);
1972                                           }
1973                                           char c=yyinput();
1974                                           QCString text;
1975                                           text+=c;
1976                                           g_code->codify(text);
1977                                           endFontClass();
1978                                           BEGIN( Body );
1979                                         }
1980 <Body,Bases>^[ \t]*"#"                  { 
1981                                           startFontClass("preprocessor");
1982                                           g_lastSkipCppContext = YY_START;
1983                                           g_code->codify(yytext);
1984                                           BEGIN( SkipCPP ) ; 
1985                                         }
1986 <SkipCPP>.                              { 
1987                                           g_code->codify(yytext);
1988                                         }
1989 <SkipCPP>[^\n\/\\]+                     {
1990                                           g_code->codify(yytext);
1991                                         }
1992 <SkipCPP>\\[\r]?\n                      { 
1993                                           codifyLines(yytext);
1994                                         }
1995 <SkipCPP>"//"                           { 
1996                                           g_code->codify(yytext);
1997                                         }
1998 <Body,FuncCall>"{"                      { 
1999                                           g_theVarContext.pushScope();
2000
2001                                           DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2002                                           g_scopeStack.push(INNERBLOCK);
2003
2004                                           if (g_searchingForBody)
2005                                           {
2006                                             g_searchingForBody=FALSE;
2007                                             g_insideBody=TRUE;
2008                                           }
2009                                           g_code->codify(yytext);
2010                                           g_curlyCount++;
2011                                           if (g_insideBody) 
2012                                           {
2013                                             g_bodyCurlyCount++;
2014                                           }
2015                                           g_type.resize(0); 
2016                                           g_name.resize(0);
2017                                           BEGIN( Body );
2018                                         }
2019 <Body,MemberCall,MemberCall2>"}"        { 
2020                                           g_theVarContext.popScope();
2021                                           g_type.resize(0); 
2022                                           g_name.resize(0);
2023
2024                                           int *scope = g_scopeStack.pop();
2025                                           DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2026                                           if (scope==SCOPEBLOCK || scope==CLASSBLOCK) 
2027                                           {
2028                                             popScope();
2029                                           }
2030
2031                                           g_code->codify(yytext);
2032
2033                                           DBG_CTX((stderr,"g_bodyCurlyCount=%d\n",g_bodyCurlyCount));
2034                                           if (--g_bodyCurlyCount<=0)
2035                                           {
2036                                             g_insideBody=FALSE;
2037                                             g_currentMemberDef=0;
2038                                             if (g_currentDefinition) 
2039                                               g_currentDefinition=g_currentDefinition->getOuterScope();
2040                                           }
2041                                           BEGIN(Body);
2042                                         }
2043 <Body,ClassVar>"@end"                   { 
2044                                           //printf("End of objc scope fd=%s\n",g_sourceFileDef->name().data());
2045                                           if (g_sourceFileDef)
2046                                           {
2047                                             FileDef *fd=g_sourceFileDef;
2048                                             g_insideObjC = fd->name().lower().right(2)==".m" || 
2049                                                            fd->name().lower().right(3)==".mm"; 
2050                                             //printf("insideObjC=%d\n",g_insideObjC);
2051                                           }
2052                                           else
2053                                           {
2054                                             g_insideObjC = FALSE;
2055                                           }
2056                                           if (g_insideBody)
2057                                           {
2058                                             g_theVarContext.popScope();
2059
2060                                             int *scope = g_scopeStack.pop();
2061                                             DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2062                                             if (scope==SCOPEBLOCK || scope==CLASSBLOCK) 
2063                                             {
2064                                               popScope();
2065                                             }
2066                                             g_insideBody=FALSE;
2067                                           }
2068
2069                                           startFontClass("keyword");
2070                                           g_code->codify(yytext);
2071                                           endFontClass();
2072
2073                                           g_currentMemberDef=0;
2074                                           if (g_currentDefinition) 
2075                                             g_currentDefinition=g_currentDefinition->getOuterScope();
2076                                           BEGIN(Body);
2077                                         }
2078 <ClassName,ClassVar>";"                 { 
2079                                           g_code->codify(yytext);
2080                                           g_searchingForBody=FALSE; 
2081                                           BEGIN( Body ); 
2082                                         }
2083 <ClassName,ClassVar>[*&^%]+             {
2084                                           g_type=g_curClassName.copy();
2085                                           g_name.resize(0);
2086                                           g_code->codify(yytext);
2087                                           BEGIN( Body ); // variable of type struct *
2088                                         }
2089 <ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")"   {
2090                                           startFontClass("keyword");
2091                                           g_code->codify(yytext);
2092                                           endFontClass();
2093                                         }
2094 <ClassName>{ID}("::"{ID})*              {
2095                                           g_curClassName=yytext;
2096                                           addType();
2097                                           if (g_curClassName=="alignas")
2098                                           {
2099                                             startFontClass("keyword");
2100                                             g_code->codify(yytext);
2101                                             endFontClass();
2102                                             BEGIN( AlignAs );
2103                                           }
2104                                           else
2105                                           {
2106                                             generateClassOrGlobalLink(*g_code,yytext);
2107                                             BEGIN( ClassVar );
2108                                           }
2109                                         }
2110 <AlignAs>"("                            { 
2111                                           g_bracketCount=1;
2112                                           g_code->codify(yytext);
2113                                           BEGIN( AlignAsEnd );
2114                                         }
2115 <AlignAs>\n                             { g_yyLineNr++; 
2116                                           codifyLines(yytext);
2117                                         }
2118 <AlignAs>.                              { g_code->codify(yytext); }
2119 <AlignAsEnd>"("                         { g_code->codify(yytext);
2120                                           g_bracketCount++; 
2121                                         }
2122 <AlignAsEnd>")"                         { 
2123                                           g_code->codify(yytext);
2124                                           if (--g_bracketCount<=0)
2125                                           {
2126                                             BEGIN(ClassName);
2127                                           }
2128                                         }
2129 <AlignAsEnd>\n                          { g_yyLineNr++; 
2130                                           codifyLines(yytext); 
2131                                         }
2132 <AlignAsEnd>.                           { g_code->codify(yytext); }
2133 <ClassName>{ID}("\\"{ID})*              { // PHP namespace
2134                                           g_curClassName=substitute(yytext,"\\","::");
2135                                           g_scopeStack.push(CLASSBLOCK);
2136                                           pushScope(g_curClassName);
2137                                           addType();
2138                                           generateClassOrGlobalLink(*g_code,yytext);
2139                                           BEGIN( ClassVar );
2140                                         }
2141 <ClassName>{ID}{B}*"("{ID}")"           { // Obj-C category
2142                                           g_curClassName=removeRedundantWhiteSpace(yytext);
2143                                           g_scopeStack.push(CLASSBLOCK);
2144                                           pushScope(g_curClassName);
2145                                           addType();
2146                                           generateClassOrGlobalLink(*g_code,yytext);
2147                                           BEGIN( ClassVar );
2148                                         }
2149 <PackageName>{ID}("."{ID})*             {
2150                                           g_curClassName=substitute(yytext,".","::");
2151                                           //printf("found package: %s\n",g_curClassName.data());
2152                                           addType();
2153                                           codifyLines(yytext);
2154                                         }
2155 <ClassVar>"="                           {
2156                                           unput(*yytext);
2157                                           BEGIN( Body );
2158                                         }
2159 <ClassVar>("extends"|"implements")      { // Java
2160                                           startFontClass("keyword");
2161                                           codifyLines(yytext);
2162                                           endFontClass();
2163                                           g_curClassBases.clear();
2164                                           BEGIN( Bases ); 
2165                                         }
2166 <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") {
2167                                           DBG_CTX((stderr,"***** C++/CLI modifier %s on g_curClassName=%s\n",yytext,g_curClassName.data()));
2168                                           startFontClass("keyword");
2169                                           codifyLines(yytext);
2170                                           endFontClass();
2171                                           BEGIN( CppCliTypeModifierFollowup ); 
2172                                         }
2173 <ClassVar>{ID}                          {
2174                                           g_type = g_curClassName.copy();
2175                                           g_name = yytext;
2176                                           if (g_insideBody)
2177                                           {
2178                                             g_theVarContext.addVariable(g_type,g_name);
2179                                           }
2180                                           generateClassOrGlobalLink(*g_code,yytext);
2181                                         }
2182 <ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}*      {
2183                                           codifyLines(yytext);
2184                                           g_curClassBases.clear();
2185                                           BEGIN( Bases ); 
2186                                         }
2187 <PackageName>[ \t]*";"                  |
2188 <Bases>^{B}*/"@"{ID}                    | // Objective-C interface
2189 <Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* {
2190                                           g_theVarContext.pushScope();
2191                                           g_code->codify(yytext);
2192                                           g_curlyCount++;
2193                                           if (YY_START==ClassVar && g_curClassName.isEmpty())
2194                                           {
2195                                             g_curClassName = g_name.copy();
2196                                           }
2197                                           if (g_searchingForBody)
2198                                           {
2199                                             g_searchingForBody=FALSE;
2200                                             g_insideBody=TRUE;
2201                                           }
2202                                           if (g_insideBody) g_bodyCurlyCount++;
2203                                           if (!g_curClassName.isEmpty()) // valid class name
2204                                           {
2205                                             DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2206                                             g_scopeStack.push(CLASSBLOCK);
2207                                             pushScope(g_curClassName);
2208                                             DBG_CTX((stderr,"***** g_curClassName=%s\n",g_curClassName.data()));
2209                                             if (getResolvedClass(g_currentDefinition,g_sourceFileDef,g_curClassName)==0)
2210                                             {
2211                                               DBG_CTX((stderr,"Adding new class %s\n",g_curClassName.data()));
2212                                               ClassDef *ncd=new ClassDef("<code>",1,1,
2213                                                   g_curClassName,ClassDef::Class,0,0,FALSE);
2214                                               g_codeClassSDict->append(g_curClassName,ncd);
2215                                               // insert base classes.
2216                                               char *s=g_curClassBases.first();
2217                                               while (s)
2218                                               {
2219                                                 ClassDef *bcd;
2220                                                 bcd=g_codeClassSDict->find(s);
2221                                                 if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s);
2222                                                 if (bcd && bcd!=ncd)
2223                                                 {
2224                                                   ncd->insertBaseClass(bcd,s,Public,Normal);
2225                                                 }
2226                                                 s=g_curClassBases.next();
2227                                               }
2228                                             }
2229                                             //printf("g_codeClassList.count()=%d\n",g_codeClassList.count());
2230                                           }
2231                                           else // not a class name -> assume inner block
2232                                           {
2233                                             DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2234                                             g_scopeStack.push(INNERBLOCK);
2235                                           }
2236                                           g_curClassName.resize(0);
2237                                           g_curClassBases.clear();
2238                                           BEGIN( Body );
2239                                         }
2240 <Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" { 
2241                                           startFontClass("keyword");
2242                                           g_code->codify(yytext);
2243                                           endFontClass();
2244                                         }
2245 <Bases>{SEP}?({ID}{SEP})*{ID}           { 
2246                                           DBG_CTX((stderr,"%s:addBase(%s)\n",g_curClassName.data(),yytext));
2247                                           g_curClassBases.inSort(yytext); 
2248                                           generateClassOrGlobalLink(*g_code,yytext);
2249                                         }
2250 <Bases>"<"                              { 
2251                                           g_code->codify(yytext);
2252                                           if (!g_insideObjC)
2253                                           {
2254                                             g_sharpCount=1;
2255                                             BEGIN ( SkipSharp );
2256                                           }
2257                                           else
2258                                           {
2259                                             g_insideProtocolList=TRUE;
2260                                           }
2261                                         }
2262 <Bases>">"                              {
2263                                           g_code->codify(yytext);
2264                                           g_insideProtocolList=FALSE;
2265                                         }
2266 <SkipSharp>"<"                          {
2267                                           g_code->codify(yytext);
2268                                           ++g_sharpCount; 
2269                                         }
2270 <SkipSharp>">"                          { 
2271                                           g_code->codify(yytext);
2272                                           if (--g_sharpCount<=0)
2273                                           BEGIN ( Bases );
2274                                         }
2275 <Bases>"("                              {
2276                                           g_code->codify(yytext);
2277                                           g_sharpCount=1;
2278                                           BEGIN ( SkipSharp );
2279                                         }
2280 <SkipSharp>"("                          {
2281                                           g_code->codify(yytext);
2282                                           ++g_sharpCount;
2283                                         }
2284 <SkipSharp>")"                          {
2285                                           g_code->codify(yytext);
2286                                           if (--g_sharpCount<=0)
2287                                             BEGIN ( Bases );
2288                                         }
2289       
2290       
2291 <Bases>","                              { 
2292                                           g_code->codify(yytext);
2293                                         }
2294                                         
2295
2296 <Body>{SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" {
2297                                           addType();
2298                                           generateFunctionLink(*g_code,yytext);
2299                                           g_bracketCount=0;
2300                                           g_args.resize(0);
2301                                           g_name+=yytext; 
2302                                           BEGIN( FuncCall );
2303                                         }
2304 <Body>{SCOPEPREFIX}?"operator"/"("      {
2305                                           addType();
2306                                           generateFunctionLink(*g_code,yytext);
2307                                           g_bracketCount=0;
2308                                           g_args.resize(0);
2309                                           g_name+=yytext; 
2310                                           BEGIN( FuncCall );
2311                                         }
2312 <Body>{SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\(\n]+/"(" {
2313                                           addType();
2314                                           generateFunctionLink(*g_code,yytext);
2315                                           g_bracketCount=0;
2316                                           g_args.resize(0);
2317                                           g_name+=yytext; 
2318                                           BEGIN( FuncCall );
2319                                         }
2320 <Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9])           {
2321                                           startFontClass("keyword");
2322                                           codifyLines(yytext);
2323                                           endFontClass();
2324                                           g_insideTemplate=TRUE;
2325                                           g_sharpCount=0;
2326                                         }
2327 <Body>"using"{BN}+"namespace"{BN}+      {
2328                                           startFontClass("keyword");
2329                                           codifyLines(yytext);
2330                                           endFontClass();
2331                                           BEGIN(UsingName);
2332                                         }
2333 <UsingName>{ID}("::"{ID})*              { addUsingDirective(yytext);
2334                                           generateClassOrGlobalLink(*g_code,yytext);
2335                                           DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2336                                           g_scopeStack.push(CLASSBLOCK);
2337                                           pushScope(yytext);
2338                                           BEGIN(Body);
2339                                         }
2340 <UsingName>\n                           { codifyLines(yytext); BEGIN(Body); }
2341 <UsingName>.                            { codifyLines(yytext); BEGIN(Body); }
2342 <Body,FuncCall>"$"?"this"("->"|".")     { g_code->codify(yytext); // this-> for C++, this. for C#
2343                                         }
2344 <Body>{KEYWORD}/([^a-z_A-Z0-9])         {
2345                                           startFontClass("keyword");
2346                                           codifyLines(yytext);
2347                                           if (QCString(yytext)=="typedef")
2348                                           {
2349                                             addType();
2350                                             g_name+=yytext; 
2351                                           }
2352                                           endFontClass();
2353                                         }
2354 <Body>{KEYWORD}/{B}*                    {
2355                                           startFontClass("keyword");
2356                                           codifyLines(yytext);
2357                                           endFontClass();
2358                                         }
2359 <Body>{KEYWORD}/{BN}*"("                {
2360                                           startFontClass("keyword");
2361                                           codifyLines(yytext);
2362                                           endFontClass();
2363                                           g_name.resize(0);g_type.resize(0);
2364                                         }
2365 <FuncCall>"in"/{BN}*                    {
2366                                           if (!g_inForEachExpression) REJECT;
2367                                           startFontClass("keywordflow");
2368                                           codifyLines(yytext);
2369                                           endFontClass();
2370                                           // insert the variable in the parent scope, see bug 546158
2371                                           g_theVarContext.popScope();
2372                                           g_theVarContext.addVariable(g_parmType,g_parmName);
2373                                           g_theVarContext.pushScope();
2374                                           g_name.resize(0);g_type.resize(0);
2375                                         }
2376 <Body>{FLOWKW}/{BN}*"("                         {
2377                                           startFontClass("keywordflow");
2378                                           codifyLines(yytext);
2379                                           endFontClass();
2380                                           g_name.resize(0);g_type.resize(0);
2381                                           g_inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0);
2382                                           BEGIN(FuncCall);
2383                                         }
2384 <Body>{FLOWKW}/([^a-z_A-Z0-9])          {
2385                                           startFontClass("keywordflow");
2386                                           codifyLines(yytext);
2387                                           endFontClass();
2388                                           if (g_inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0))
2389                                           {
2390                                             g_inFunctionTryBlock=FALSE;
2391                                           }
2392                                         }
2393 <Body>{FLOWKW}/{B}*                     {
2394                                           startFontClass("keywordflow");
2395                                           codifyLines(yytext);
2396                                           endFontClass();
2397                                         }
2398 <Body>"*"{B}*")"                        { // end of cast?
2399                                           g_code->codify(yytext);
2400                                           g_theCallContext.popScope();
2401                                           g_bracketCount--;
2402                                           g_parmType = g_name;
2403                                           BEGIN(FuncCall);
2404                                         }
2405 <Body>[\\|\)\+\-\/\%\~\!]               {
2406                                           g_code->codify(yytext);
2407                                           g_name.resize(0);g_type.resize(0);
2408                                           if (*yytext==')')
2409                                           {
2410                                             g_theCallContext.popScope();
2411                                             g_bracketCount--;
2412                                             BEGIN(FuncCall);
2413                                           }
2414                                         }
2415 <Body,TemplDecl,ObjCMethod>{TYPEKW}/{B}* {
2416                                           startFontClass("keywordtype");
2417                                           g_code->codify(yytext);
2418                                           endFontClass();
2419                                           addType();
2420                                           g_name+=yytext; 
2421                                         }
2422 <Body>"generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* {
2423                                           startFontClass("keyword");
2424                                           g_code->codify(yytext);
2425                                           endFontClass();
2426                                           g_sharpCount=0;
2427                                           BEGIN(TemplDecl);
2428                                         }
2429 <Body>"template"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { // template<...>
2430                                           startFontClass("keyword");
2431                                           g_code->codify(yytext);
2432                                           endFontClass();
2433                                           g_sharpCount=0;
2434                                           BEGIN(TemplDecl);
2435                                         }
2436 <TemplDecl>"class"|"typename"           {
2437                                           startFontClass("keyword");
2438                                           codifyLines(yytext);
2439                                           endFontClass();
2440                                         }
2441 <TemplDecl>"<"                          {
2442                                           g_code->codify(yytext);
2443                                           g_sharpCount++;
2444                                         }
2445 <TemplDecl>">"                          {
2446                                           g_code->codify(yytext);
2447                                           g_sharpCount--;
2448                                           if (g_sharpCount<=0)
2449                                           {
2450                                             BEGIN(Body);
2451                                           }
2452                                         }
2453 <TemplCast>">"                          {
2454                                           startFontClass("keyword");
2455                                           codifyLines(yytext);
2456                                           endFontClass();
2457                                           BEGIN( g_lastTemplCastContext );
2458                                         }
2459 <TemplCast>{ID}("::"{ID})*              {
2460                                           generateClassOrGlobalLink(*g_code,yytext);
2461                                         }
2462 <TemplCast>("const"|"volatile"){B}*     {
2463                                           startFontClass("keyword");
2464                                           codifyLines(yytext);
2465                                           endFontClass();
2466                                         }
2467 <TemplCast>[*^]*                        {
2468                                           codifyLines(yytext);
2469                                         }
2470 <Body,FuncCall>{CASTKW}"<"                { // static_cast<T>(
2471                                           startFontClass("keyword");
2472                                           codifyLines(yytext);
2473                                           endFontClass();
2474                                           g_lastTemplCastContext = YY_START;
2475                                           BEGIN(TemplCast);
2476                                         }
2477 <Body>"$this->"{SCOPENAME}/{BN}*[;,)\]] { // PHP member variable
2478                                           addType();
2479                                           generatePHPVariableLink(*g_code,yytext);
2480                                           g_name+=yytext+7; 
2481                                         }
2482 <Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"("::"{ID})*/{B}* { // A<T> *pt;
2483                                           int i=QCString(yytext).find('<');
2484                                           QCString kw = QCString(yytext).left(i).stripWhiteSpace();
2485                                           if (kw.right(5)=="_cast" && YY_START==Body)
2486                                           {
2487                                             REJECT;
2488                                           }
2489                                           addType();
2490                                           generateClassOrGlobalLink(*g_code,yytext);
2491                                           g_name+=yytext; 
2492                                         }
2493 <Body>{SCOPENAMECS}/{BN}*[;,)\]]        { // "int var;" or "var, var2" or "debug(f) macro" 
2494                                           if (!g_insideCS && !g_insideJava)
2495                                           {
2496                                             REJECT;
2497                                           }
2498                                           else
2499                                           {
2500                                             addType();
2501                                             // changed this to generateFunctionLink, see bug 624514
2502                                             //generateClassOrGlobalLink(*g_code,yytext,FALSE,TRUE);
2503                                             generateFunctionLink(*g_code,yytext);
2504                                             g_name+=yytext; 
2505                                           }
2506                                         }
2507 <Body>{SCOPENAME}/{BN}*[;,)\]]          { // "int var;" or "var, var2" or "debug(f) macro" 
2508                                           addType();
2509                                           // changed this to generateFunctionLink, see bug 624514
2510                                           //generateClassOrGlobalLink(*g_code,yytext,FALSE,TRUE);
2511                                           generateFunctionLink(*g_code,yytext);
2512                                           g_name+=yytext; 
2513                                         }
2514 <Body>{SCOPENAMECS}/{B}*                { // p->func()
2515                                           if (!g_insideCS && !g_insideJava)
2516                                           {
2517                                             REJECT;
2518                                           }
2519                                           else
2520                                           {
2521                                             addType();
2522                                             generateClassOrGlobalLink(*g_code,yytext);
2523                                             g_name+=yytext; 
2524                                           }
2525                                         }
2526 <Body>{SCOPENAME}/{B}*                  { // p->func()
2527                                           addType();
2528                                           generateClassOrGlobalLink(*g_code,yytext);
2529                                           g_name+=yytext; 
2530                                         }
2531 <Body>"("{B}*("*"{B}*)+{SCOPENAME}*{B}*")"/{B}* {  // (*p)->func() but not "if (p) ..."
2532                                           g_code->codify(yytext);
2533                                           int s=0;while (s<(int)yyleng && !isId(yytext[s])) s++;
2534                                           int e=(int)yyleng-1;while (e>=0 && !isId(yytext[e])) e--;
2535                                           QCString varname = ((QCString)yytext).mid(s,e-s+1); 
2536                                           addType();
2537                                           g_name=varname; 
2538                                         }
2539 <Body>{SCOPETNAME}/{BN}*"("             { // a() or c::a() or t<A,B>::a() or A\B\foo()
2540                                           addType();
2541                                           generateFunctionLink(*g_code,yytext);
2542                                           g_bracketCount=0;
2543                                           g_args.resize(0);
2544                                           g_name+=yytext; 
2545                                           BEGIN( FuncCall );
2546                                         }
2547 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN}   {
2548                                           QCString text=yytext;
2549                                           int i=text.find('R');
2550                                           g_code->codify(text.left(i+1));
2551                                           startFontClass("stringliteral");
2552                                           g_code->codify(yytext+i+1);
2553                                           g_lastStringContext=YY_START;
2554                                           g_inForEachExpression = FALSE;
2555                                           g_delimiter = yytext+i+2;
2556                                           g_delimiter=g_delimiter.left(g_delimiter.length()-1);
2557                                           BEGIN( RawString );
2558                                         }
2559 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\"   {
2560                                           startFontClass("stringliteral");
2561                                           g_code->codify(yytext);
2562                                           g_lastStringContext=YY_START;
2563                                           g_inForEachExpression = FALSE;
2564                                           BEGIN( SkipString );
2565                                         }
2566 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\'   {
2567                                           startFontClass("stringliteral");
2568                                           g_code->codify(yytext);
2569                                           g_lastStringContext=YY_START;
2570                                           g_inForEachExpression = FALSE;
2571                                           BEGIN( SkipStringS );
2572                                         }
2573 <SkipString>[^\"\\\r\n]*                { 
2574                                           g_code->codify(yytext);
2575                                         }
2576 <SkipStringS>[^\'\\\r\n]*               {
2577                                           g_code->codify(yytext);
2578                                         }
2579 <SkipString,SkipStringS>"//"|"/*"       {
2580                                           g_code->codify(yytext);
2581                                         }
2582 <SkipString>@?\"                        {
2583                                           g_code->codify(yytext);
2584                                           endFontClass();
2585                                           BEGIN( g_lastStringContext );
2586                                         }
2587 <SkipStringS>\'                         {
2588                                           g_code->codify(yytext);
2589                                           endFontClass();
2590                                           BEGIN( g_lastStringContext );
2591                                         }
2592 <SkipString,SkipStringS>\\.             {
2593                                           g_code->codify(yytext);
2594                                         }
2595 <RawString>{RAWEND}                     { 
2596                                           g_code->codify(yytext);
2597                                           QCString delimiter = yytext+1;
2598                                           delimiter=delimiter.left(delimiter.length()-1);
2599                                           if (delimiter==g_delimiter)
2600                                           {
2601                                             BEGIN( g_lastStringContext );
2602                                           }
2603                                         }
2604 <RawString>[^)\n]+                      { g_code->codify(yytext); }
2605 <RawString>.                            { g_code->codify(yytext); }
2606 <RawString>\n                           { codifyLines(yytext); }
2607 <SkipVerbString>[^"\n]+                 {
2608                                           g_code->codify(yytext);
2609                                         }
2610 <SkipVerbString>\"\"                    { // escaped quote
2611                                           g_code->codify(yytext);
2612                                         }
2613 <SkipVerbString>\"                      { // end of string
2614                                           g_code->codify(yytext);
2615                                           endFontClass();
2616                                           BEGIN( g_lastVerbStringContext );
2617                                         }
2618 <SkipVerbString>.                       {
2619                                           g_code->codify(yytext);
2620                                         }
2621 <SkipVerbString>\n                      {
2622                                           codifyLines(yytext);
2623                                         }
2624 <Body>":"                               {
2625                                           g_code->codify(yytext);
2626                                           g_name.resize(0);g_type.resize(0);
2627                                         }
2628 <Body>"<"                               {
2629                                           if (g_insideTemplate)
2630                                           {
2631                                             g_sharpCount++;
2632                                           }
2633                                           g_code->codify(yytext);
2634                                         }
2635 <Body>">"                               {
2636                                           if (g_insideTemplate)
2637                                           {
2638                                             if (--g_sharpCount<=0)
2639                                             {
2640                                               g_insideTemplate=FALSE;
2641                                             }
2642                                           }
2643                                           g_code->codify(yytext);
2644                                         }
2645 <Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'"   {
2646                                           startFontClass("charliteral"); 
2647                                           g_code->codify(yytext);
2648                                           endFontClass();
2649                                         }
2650 <Body>"."|"->"                          { 
2651                                           if (yytext[0]=='-') // -> could be overloaded
2652                                           {
2653                                             updateCallContextForSmartPointer();
2654                                           }
2655                                           g_code->codify(yytext);
2656                                           g_memCallContext = YY_START;
2657                                           BEGIN( MemberCall ); 
2658                                         }
2659 <MemberCall>{SCOPETNAME}/{BN}*"("       {
2660                                           if (g_theCallContext.getClass())
2661                                           {
2662                                             if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),yytext))
2663                                             {
2664                                               g_code->codify(yytext);
2665                                               addToSearchIndex(yytext);
2666                                             }
2667                                             g_name.resize(0);
2668                                           }
2669                                           else
2670                                           {
2671                                             g_code->codify(yytext);
2672                                             addToSearchIndex(yytext);
2673                                             g_name.resize(0);
2674                                           }
2675                                           g_type.resize(0);
2676                                           g_bracketCount=0;
2677                                           if (g_memCallContext==Body)
2678                                           {
2679                                             BEGIN(FuncCall);
2680                                           }
2681                                           else
2682                                           {
2683                                             BEGIN(g_memCallContext);
2684                                           }
2685                                         }
2686 <MemberCall>{SCOPENAME}/{B}*            {
2687                                           if (g_theCallContext.getClass())
2688                                           {
2689                                             DBG_CTX((stderr,"g_theCallContext.getClass()=%p\n",g_theCallContext.getClass()));
2690                                             if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),yytext))
2691                                             {
2692                                               g_code->codify(yytext);
2693                                               addToSearchIndex(yytext);
2694                                             }
2695                                             g_name.resize(0);
2696                                           }
2697                                           else
2698                                           {
2699                                             DBG_CTX((stderr,"no class context!\n"));
2700                                             g_code->codify(yytext);
2701                                             addToSearchIndex(yytext);
2702                                             g_name.resize(0);
2703                                           }
2704                                           g_type.resize(0);
2705                                           BEGIN(g_memCallContext);
2706                                         }
2707 <Body>[,=;\[]                           {
2708                                           if (g_insideObjC && *yytext=='[')
2709                                           {
2710                                             //printf("Found start of ObjC call!\n");
2711                                             // start of a method call
2712                                             g_contextDict.setAutoDelete(TRUE);
2713                                             g_nameDict.setAutoDelete(TRUE);
2714                                             g_objectDict.setAutoDelete(TRUE);
2715                                             g_wordDict.setAutoDelete(TRUE);
2716                                             g_contextDict.clear();
2717                                             g_nameDict.clear();
2718                                             g_objectDict.clear();
2719                                             g_wordDict.clear();
2720                                             g_currentCtxId  = 0;
2721                                             g_currentNameId  = 0;
2722                                             g_currentObjId  = 0;
2723                                             g_currentCtx = 0;
2724                                             g_braceCount = 0;
2725                                             unput('[');
2726                                             BEGIN(ObjCCall);
2727                                           }
2728                                           else
2729                                           {
2730                                             g_code->codify(yytext);
2731                                             g_saveName = g_name.copy();
2732                                             g_saveType = g_type.copy();
2733                                             if (*yytext!='[' && !g_type.isEmpty()) 
2734                                             {
2735                                               //printf("g_scopeStack.bottom()=%p\n",g_scopeStack.bottom());
2736                                               if (g_scopeStack.top()!=CLASSBLOCK)
2737                                               {
2738                                                 //printf("AddVariable: '%s' '%s' context=%d\n",
2739                                                 //    g_type.data(),g_name.data(),g_theVarContext.count());
2740                                                 g_theVarContext.addVariable(g_type,g_name);
2741                                               }
2742                                               g_name.resize(0);
2743                                             }
2744                                             if (*yytext==';' || *yytext=='=') 
2745                                             {
2746                                               g_type.resize(0);
2747                                               g_name.resize(0);
2748                                             }
2749                                             else if (*yytext=='[')
2750                                             {
2751                                               g_theCallContext.pushScope();
2752                                             }
2753                                             g_args.resize(0);
2754                                             g_parmType.resize(0);
2755                                             g_parmName.resize(0);
2756                                           }
2757                                         }
2758   /*
2759 <ObjCMemberCall>{ID}                    {
2760                                           if (qstrcmp(yytext,"self")==0 || qstrcmp(yytext,"super")==0)
2761                                           {
2762                                             // TODO: get proper base class for "super"
2763                                             g_theCallContext.setClass(getClass(g_curClassName));
2764                                             startFontClass("keyword");
2765                                             g_code->codify(yytext); 
2766                                             endFontClass();
2767                                           }
2768                                           else
2769                                           {
2770                                             generateClassOrGlobalLink(*g_code,yytext);
2771                                           }
2772                                           g_name.resize(0);
2773                                           BEGIN(ObjCMemberCall2);
2774                                         }
2775 <ObjCMemberCall>"["                     {
2776                                             g_code->codify(yytext);
2777                                             g_theCallContext.pushScope();
2778                                         }
2779 <ObjCMemberCall2>{ID}":"?               {
2780                                           g_name+=yytext;
2781                                           if (g_theCallContext.getClass())
2782                                           {
2783                                             //printf("Calling method %s\n",g_name.data());
2784                                             if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),g_name))
2785                                             {
2786                                               g_code->codify(yytext);
2787                                               addToSearchIndex(g_name);
2788                                             }
2789                                           }
2790                                           else
2791                                           {
2792                                             g_code->codify(yytext);
2793                                             addToSearchIndex(g_name);
2794                                           }
2795                                           g_name.resize(0);
2796                                           BEGIN(ObjCMemberCall3);
2797                                         }
2798 <ObjCMemberCall2,ObjCMemberCall3>"]"    {
2799                                           g_theCallContext.popScope();
2800                                           g_code->codify(yytext);
2801                                           BEGIN(Body);
2802                                         }
2803   */
2804 <ObjCCall,ObjCMName>"["         { 
2805                                    saveObjCContext();
2806                                    g_currentCtx->format+=*yytext;
2807                                    BEGIN(ObjCCall);
2808                                    //printf("open\n");
2809                                  }
2810 <ObjCCall,ObjCMName>"]"         { 
2811                                     g_currentCtx->format+=*yytext;
2812                                     restoreObjCContext();
2813                                     BEGIN(ObjCMName);
2814                                     if (g_currentCtx==0)
2815                                     {
2816                                       // end of call
2817                                       writeObjCMethodCall(g_contextDict.find(0));
2818                                       BEGIN(Body);
2819                                     }
2820                                     //printf("close\n");
2821                                   }
2822 <ObjCCall>{ID}                    {
2823                                     g_currentCtx->format+=escapeObject(yytext);
2824                                     if (g_braceCount==0)
2825                                     {
2826                                       g_currentCtx->objectTypeOrName=yytext;
2827                                       //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
2828                                       BEGIN(ObjCMName);
2829                                     }
2830                                   }
2831 <ObjCMName>{ID}/{BN}*"]"          { 
2832                                     if (g_braceCount==0 && 
2833                                         g_currentCtx->methodName.isEmpty())
2834                                     {
2835                                       g_currentCtx->methodName=yytext; 
2836                                       g_currentCtx->format+=escapeName(yytext);
2837                                     }
2838                                     else
2839                                     {
2840                                       g_currentCtx->format+=escapeWord(yytext);
2841                                     }
2842                                   }
2843 <ObjCMName>{ID}/{BN}*":"           { 
2844                                      if (g_braceCount==0)
2845                                      {
2846                                        g_currentCtx->methodName+=yytext;
2847                                        g_currentCtx->methodName+=":";
2848                                      }
2849                                      g_currentCtx->format+=escapeName(yytext);
2850                                    }
2851 <ObjCSkipStr>[^\n\"$\\]*           { g_currentCtx->format+=yytext; }
2852 <ObjCSkipStr>\\.                   { g_currentCtx->format+=yytext; }
2853 <ObjCSkipStr>"\""                  { g_currentCtx->format+=yytext; 
2854                                       BEGIN(g_lastStringContext); 
2855                                    }
2856 <ObjCCall,ObjCMName>{CHARLIT}      { g_currentCtx->format+=yytext; }
2857 <ObjCCall,ObjCMName>"@"?"\""       { g_currentCtx->format+=yytext; 
2858                                       g_lastStringContext=YY_START;
2859                                       BEGIN(ObjCSkipStr); 
2860                                    }
2861 <ObjCCall,ObjCMName,ObjCSkipStr>"$" { g_currentCtx->format+="$$"; }
2862 <ObjCCall,ObjCMName>"("            { g_currentCtx->format+=*yytext; g_braceCount++; }
2863 <ObjCCall,ObjCMName>")"            { g_currentCtx->format+=*yytext; g_braceCount--; }
2864 <ObjCSkipStr>"@"/"\""              { // needed to prevent matching the global rule (for C#)
2865                                      g_currentCtx->format+=yytext;
2866                                    }
2867 <ObjCCall,ObjCMName,ObjCSkipStr>{ID} { g_currentCtx->format+=escapeWord(yytext); }
2868 <ObjCCall,ObjCMName,ObjCSkipStr>.  { g_currentCtx->format+=*yytext; }
2869 <ObjCCall,ObjCMName,ObjCSkipStr>\n { g_currentCtx->format+=*yytext; }
2870
2871 <Body>"]"                               {
2872                                           g_theCallContext.popScope();
2873                                           g_code->codify(yytext);
2874                                           // TODO: nested arrays like: a[b[0]->func()]->func()
2875                                           g_name = g_saveName.copy();
2876                                           g_type = g_saveType.copy();
2877                                         }
2878 <Body>[0-9]+                            {
2879                                           g_code->codify(yytext);
2880                                         }
2881 <Body>[0-9]+[xX][0-9A-Fa-f]+            {
2882                                           g_code->codify(yytext);
2883                                         }
2884 <MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) {
2885                                           //addParmType();
2886                                           //g_parmName=yytext; 
2887                                           startFontClass("keyword");
2888                                           g_code->codify(yytext);
2889                                           endFontClass();
2890                                         }
2891 <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKW}/([^a-z_A-Z0-9]) {
2892                                           addParmType();
2893                                           g_parmName=yytext; 
2894                                           startFontClass("keywordtype");
2895                                           g_code->codify(yytext);
2896                                           endFontClass();
2897                                         }
2898 <MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) {
2899                                           addParmType();
2900                                           g_parmName=yytext; 
2901                                           startFontClass("keywordflow");
2902                                           g_code->codify(yytext);
2903                                           endFontClass();
2904                                         }
2905 <MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* {
2906                                           addParmType();
2907                                           g_parmName=yytext; 
2908                                           generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
2909                                         }
2910 <FuncCall>";"                           { // probably a cast, not a function call
2911                                           g_code->codify(yytext);
2912                                           g_inForEachExpression = FALSE;
2913                                           BEGIN( Body );
2914                                         }
2915 <MemberCall2,FuncCall>,                 {
2916                                           g_code->codify(yytext);
2917                                           g_theVarContext.addVariable(g_parmType,g_parmName);
2918                                           g_parmType.resize(0);g_parmName.resize(0);
2919                                         }
2920 <MemberCall2,FuncCall>"{"               {
2921                                           if (g_bracketCount>0)
2922                                           {
2923                                             g_code->codify(yytext);
2924                                             g_skipInlineInitContext=YY_START;
2925                                             g_curlyCount=0;
2926                                             BEGIN(InlineInit);
2927                                           }
2928                                           else
2929                                           {
2930                                             REJECT;
2931                                           }
2932                                         }
2933 <InlineInit>"{"                         { g_curlyCount++;
2934                                           g_code->codify(yytext);
2935                                         }
2936 <InlineInit>"}"                         {
2937                                           g_code->codify(yytext);
2938                                           if (--g_curlyCount<=0)
2939                                           {
2940                                             BEGIN(g_skipInlineInitContext);
2941                                           }
2942                                         }
2943 <InlineInit>\n                          {
2944                                           codifyLines(yytext);
2945                                         }
2946 <InlineInit>.                           {
2947                                           g_code->codify(yytext);
2948                                         }
2949 <MemberCall2,FuncCall>"("               {
2950                                           g_parmType.resize(0);g_parmName.resize(0);
2951                                           g_code->codify(yytext);
2952                                           g_bracketCount++; 
2953                                           g_theCallContext.pushScope();
2954                                           if (YY_START==FuncCall && !g_insideBody)
2955                                           {
2956                                             g_theVarContext.pushScope();
2957                                           }
2958                                         }
2959 <MemberCall2,FuncCall>{OPERATOR}        { // operator
2960                                           if (qstrcmp(yytext,"*") && 
2961                                               qstrcmp(yytext,"&") &&
2962                                               qstrcmp(yytext,"^") &&
2963                                               qstrcmp(yytext,"%")) // typically a pointer or reference
2964                                           {
2965                                             // not a * or &, or C++/CLI's ^ or %
2966                                             g_parmType.resize(0);g_parmName.resize(0);
2967                                           }
2968                                           g_code->codify(yytext);
2969                                         }
2970 <MemberCall,MemberCall2,FuncCall>("*"{B}*)?")"  { 
2971                                           if (yytext[0]==')') // no a pointer cast
2972                                           {
2973                                             //printf("addVariable(%s,%s)\n",g_parmType.data(),g_parmName.data());
2974                                             g_theVarContext.addVariable(g_parmType,g_parmName);
2975                                           }
2976                                           else
2977                                           {
2978                                             g_parmType.resize(0);
2979                                             g_parmName.resize(0);
2980                                           }
2981                                           g_theCallContext.popScope();
2982                                           g_inForEachExpression = FALSE;
2983                                           //g_theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b().
2984                                           g_code->codify(yytext);
2985                                           if (--g_bracketCount<=0) 
2986                                           {
2987                                             if (g_name.isEmpty())
2988                                             {
2989                                               BEGIN( Body );
2990                                             }
2991                                             else
2992                                             {
2993                                               BEGIN( CallEnd ); 
2994                                             }
2995                                           }
2996                                         }
2997 <CallEnd>[ \t\n]*                       { codifyLines(yytext); }
2998   /*
2999 <MemberCall2,FuncCall>")"[ \t\n]*[;:]   {
3000   */
3001 <CallEnd>[;:]                           {
3002                                           codifyLines(yytext);
3003                                           g_bracketCount=0;
3004                                           if (*yytext==';') g_searchingForBody=FALSE; 
3005                                           if (!g_type.isEmpty())
3006                                           {
3007                                             DBG_CTX((stderr,"add variable g_type=%s g_name=%s)\n",g_type.data(),g_name.data()));
3008                                             g_theVarContext.addVariable(g_type,g_name);
3009                                           }
3010                                           g_parmType.resize(0);g_parmName.resize(0);
3011                                           g_theCallContext.setClass(0);
3012                                           if (*yytext==';' || g_insideBody)
3013                                           {
3014                                             if (!g_insideBody)
3015                                             {
3016                                               g_theVarContext.popScope();
3017                                             }
3018                                             g_name.resize(0);g_type.resize(0);
3019                                             BEGIN( Body );
3020                                           }
3021                                           else
3022                                           {
3023                                             g_bracketCount=0;
3024                                             BEGIN( SkipInits );
3025                                           }
3026                                         }
3027 <CallEnd>("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") {
3028                                           startFontClass("keyword");
3029                                           codifyLines(yytext);
3030                                           endFontClass();
3031                                         }
3032 <CallEnd,OldStyleArgs>("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" {
3033                                           if (g_insideBody)
3034                                           {
3035                                             g_theVarContext.pushScope();
3036                                           }
3037                                           g_theVarContext.addVariable(g_parmType,g_parmName);
3038                                           //g_theCallContext.popScope();
3039                                           g_parmType.resize(0);g_parmName.resize(0);
3040                                           int index = g_name.findRev("::");
3041                                           DBG_CTX((stderr,"g_name=%s\n",g_name.data()));
3042                                           if (index!=-1) 
3043                                           {
3044                                             QCString scope = g_name.left(index);
3045                                             if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::");
3046                                             ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope);
3047                                             if (cd)
3048                                             {
3049                                               setClassScope(cd->name());
3050                                               g_scopeStack.push(SCOPEBLOCK);
3051                                               DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3052                                             }
3053                                             else 
3054                                             {
3055                                               //setClassScope(g_realScope);
3056                                               g_scopeStack.push(INNERBLOCK);
3057                                               DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3058                                             }
3059                                           }
3060                                           else
3061                                           {
3062                                             DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3063                                             g_scopeStack.push(INNERBLOCK);
3064                                           }
3065                                           yytext[yyleng-1]='\0';
3066                                           QCString cv(yytext);
3067                                           if (!cv.stripWhiteSpace().isEmpty())
3068                                           {
3069                                             startFontClass("keyword");
3070                                             codifyLines(yytext);
3071                                             endFontClass();
3072                                           }
3073                                           else // just whitespace
3074                                           {
3075                                             codifyLines(yytext);
3076                                           }
3077                                           g_code->codify("{");
3078                                           if (g_searchingForBody)
3079                                           {
3080                                             g_searchingForBody=FALSE;
3081                                             g_insideBody=TRUE;
3082                                           }
3083                                           if (g_insideBody) g_bodyCurlyCount++;
3084                                           g_curlyCount++;
3085                                           g_type.resize(0); g_name.resize(0);
3086                                           BEGIN( Body );
3087                                         }
3088 <CallEnd>"try"                          { // function-try-block
3089                                           startFontClass("keyword");
3090                                           g_code->codify(yytext);
3091                                           endFontClass();
3092                                           g_inFunctionTryBlock=TRUE;
3093                                         }
3094 <CallEnd>{ID}                           {
3095                                           if (g_insideBody || !g_parmType.isEmpty()) 
3096                                           {
3097                                             REJECT;
3098                                           }
3099                                           // could be K&R style definition
3100                                           addParmType();
3101                                           g_parmName=yytext; 
3102                                           generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3103                                           BEGIN(OldStyleArgs);
3104                                         }
3105 <OldStyleArgs>{ID}                      {
3106                                           addParmType();
3107                                           g_parmName=yytext; 
3108                                           generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3109                                         }
3110 <OldStyleArgs>[,;]                      {
3111                                           g_code->codify(yytext);
3112                                           g_theVarContext.addVariable(g_parmType,g_parmName);
3113                                           if (*yytext==';') g_parmType.resize(0);
3114                                           g_parmName.resize(0);
3115                                         }
3116 <CallEnd,OldStyleArgs>"#"               {
3117                                           startFontClass("preprocessor");
3118                                           g_lastSkipCppContext = Body;
3119                                           g_code->codify(yytext);
3120                                           BEGIN( SkipCPP );
3121                                         }
3122 <CallEnd>.                              {
3123                                           unput(*yytext);
3124                                           if (!g_insideBody) 
3125                                           {
3126                                             g_theVarContext.popScope();
3127                                           }
3128                                           g_name.resize(0);g_args.resize(0);
3129                                           g_parmType.resize(0);g_parmName.resize(0);
3130                                           BEGIN( Body ); 
3131                                         }
3132 <SkipInits>";"                          {
3133                                           g_code->codify(yytext);
3134                                           g_type.resize(0); g_name.resize(0);
3135                                           BEGIN( Body );
3136                                         }
3137 <SkipInits>"{"                          { 
3138                                           g_code->codify(yytext);
3139                                           g_curlyCount++; 
3140                                           if (g_searchingForBody)
3141                                           {
3142                                             g_searchingForBody=FALSE;
3143                                             g_insideBody=TRUE;
3144                                           }
3145                                           if (g_insideBody) g_bodyCurlyCount++;
3146                                           if (g_name.find("::")!=-1) 
3147                                           {
3148                                             DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3149                                             g_scopeStack.push(SCOPEBLOCK);
3150                                             setClassScope(g_realScope);
3151                                           }
3152                                           else
3153                                           {
3154                                             DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3155                                             g_scopeStack.push(INNERBLOCK);
3156                                           }
3157                                           g_type.resize(0); g_name.resize(0);
3158                                           BEGIN( Body ); 
3159                                         }
3160 <SkipInits>{ID}                         {
3161                                           generateClassOrGlobalLink(*g_code,yytext);
3162                                         }
3163 <FuncCall>{ID}/"("                      {
3164                                           generateFunctionLink(*g_code,yytext);
3165                                         }
3166 <FuncCall>{ID}/("."|"->")               { 
3167                                           g_name=yytext; 
3168                                           generateClassOrGlobalLink(*g_code,yytext);
3169                                           BEGIN( MemberCall2 ); 
3170                                         }
3171 <FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}*{B}*")"{B}*)/("."|"->") { 
3172                                           g_code->codify(yytext);
3173                                           int s=0;while (!isId(yytext[s])) s++;
3174                                           int e=(int)yyleng-1;while (!isId(yytext[e])) e--;
3175                                           g_name=((QCString)yytext).mid(s,e-s+1); 
3176                                           BEGIN( MemberCall2 ); 
3177                                         }
3178 <MemberCall2>{ID}/([ \t\n]*"(")         { 
3179                                           if (!g_args.isEmpty())
3180                                             generateMemberLink(*g_code,g_args,yytext);
3181                                           else
3182                                             generateClassOrGlobalLink(*g_code,yytext);
3183                                           g_args.resize(0);
3184                                           BEGIN( FuncCall );
3185                                         }
3186 <MemberCall2>{ID}/([ \t\n]*("."|"->"))  {
3187                                           //g_code->codify(yytext);
3188                                           g_name=yytext; 
3189                                           generateClassOrGlobalLink(*g_code,yytext);
3190                                           BEGIN( MemberCall2 ); 
3191                                         }
3192 <MemberCall2>"->"|"."                   {
3193                                           if (yytext[0]=='-') // -> could be overloaded
3194                                           {
3195                                             updateCallContextForSmartPointer();
3196                                           }
3197                                           g_code->codify(yytext);
3198                                           g_memCallContext = YY_START;
3199                                           BEGIN( MemberCall ); 
3200                                         }
3201 <SkipComment>"/*"("!"?)"*/"             { 
3202                                           g_code->codify(yytext);
3203                                           endFontClass();
3204                                           BEGIN( g_lastCContext ) ; 
3205                                         }
3206 <SkipComment>"//"|"/*"                  {
3207                                           g_code->codify(yytext);
3208                                         }
3209 <SkipComment>[^*/\n]+                   {
3210                                           g_code->codify(yytext);
3211                                         }
3212 <SkipComment>[ \t]*"*/"                 { 
3213                                           g_code->codify(yytext);
3214                                           endFontClass();
3215                                           if (g_lastCContext==SkipCPP)
3216                                           {
3217                                             startFontClass("preprocessor");
3218                                           }
3219                                           BEGIN( g_lastCContext ) ; 
3220                                         }
3221 <SkipCxxComment>[^\r\n]*"\\"[\r]?\n     { // line continuation
3222                                           codifyLines(yytext);
3223                                         }
3224 <SkipCxxComment>[^\r\n]+                { 
3225                                           g_code->codify(yytext);
3226                                         }
3227 <SkipCxxComment>\r                      
3228 <SkipCxxComment>\n                      {
3229                                           unput('\n');
3230                                           endFontClass();
3231                                           BEGIN( g_lastCContext ) ;
3232                                         }
3233 <SkipCxxComment>.                       {
3234                                           g_code->codify(yytext);
3235                                         }
3236 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] {
3237                                           g_yyLineNr+=QCString(yytext).contains('\n');
3238                                         }
3239 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? {
3240                                           g_yyLineNr+=QCString(yytext).contains('\n');
3241                                           nextCodeLine();
3242                                           if (g_lastSpecialCContext==SkipCxxComment)
3243                                           { // force end of C++ comment here
3244                                             endFontClass();
3245                                             BEGIN( g_lastCContext ) ;
3246                                           }
3247                                           else
3248                                           {
3249                                             BEGIN(g_lastSpecialCContext);
3250                                           }
3251                                         }
3252 <RemoveSpecialCComment>"*/"             {
3253                                           BEGIN(g_lastSpecialCContext);
3254                                         }
3255 <RemoveSpecialCComment>[^*\n]+
3256 <RemoveSpecialCComment>"//"|"/*"
3257 <RemoveSpecialCComment>\n  { g_yyLineNr++; }
3258 <RemoveSpecialCComment>.
3259 <MemberCall>[^a-z_A-Z0-9(\n]            { 
3260                                           g_code->codify(yytext);
3261                                           g_type.resize(0);
3262                                           g_name.resize(0);
3263                                           BEGIN(g_memCallContext); 
3264                                         }
3265 <*>\n({B}*"//"[!/][^\n]*\n)+            { // remove special one-line comment
3266                                           if (YY_START==SkipCPP) REJECT;
3267                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3268                                           {
3269                                             g_yyLineNr+=((QCString)yytext).contains('\n');
3270                                             nextCodeLine();
3271                                           }
3272                                           else
3273                                           {
3274                                             startFontClass("comment");
3275                                             codifyLines(yytext);
3276                                             endFontClass();
3277                                           }
3278                                           if (YY_START==SkipCxxComment)
3279                                           {
3280                                             endFontClass();
3281                                             BEGIN( g_lastCContext ) ;
3282                                           }
3283                                         }
3284 <SkipCPP>\n/.*\n                        { 
3285                                           endFontClass();
3286                                           codifyLines(yytext);
3287                                           BEGIN( g_lastSkipCppContext ) ;
3288                                         }
3289 <*>\n{B}*"//@"[{}].*\n                  { // remove one-line group marker
3290                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3291                                           {
3292                                             g_yyLineNr+=2;
3293                                             nextCodeLine();
3294                                           }
3295                                           else
3296                                           {
3297                                             startFontClass("comment");
3298                                             codifyLines(yytext);
3299                                             endFontClass();
3300                                           }
3301                                           if (YY_START==SkipCxxComment)
3302                                           {
3303                                             endFontClass();
3304                                             BEGIN( g_lastCContext ) ;
3305                                           }
3306                                         }
3307 <*>\n{B}*"/*@"[{}]                      { // remove one-line group marker
3308                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3309                                           {
3310                                             g_lastSpecialCContext = YY_START;
3311                                             g_yyLineNr++;
3312                                             BEGIN(RemoveSpecialCComment);
3313                                           }
3314                                           else
3315                                           {
3316                                             // check is to prevent getting stuck in skipping C++ comments
3317                                             if (YY_START != SkipCxxComment)
3318                                             {
3319                                               g_lastCContext = YY_START ;
3320                                             }
3321                                             startFontClass("comment");
3322                                             codifyLines(yytext);
3323                                             BEGIN(SkipComment);
3324                                           }
3325                                         }
3326 <*>^{B}*"//@"[{}].*\n                   { // remove one-line group marker
3327                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3328                                           {
3329                                             g_yyLineNr++;
3330                                             nextCodeLine();
3331                                           }
3332                                           else
3333                                           {
3334                                             startFontClass("comment");
3335                                             codifyLines(yytext);
3336                                             endFontClass();
3337                                           }
3338                                         }
3339 <*>^{B}*"/*@"[{}]                       { // remove multi-line group marker
3340                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3341                                           {
3342                                             g_lastSpecialCContext = YY_START;
3343                                             BEGIN(RemoveSpecialCComment);
3344                                           }
3345                                           else
3346                                           {
3347                                             // check is to prevent getting stuck in skipping C++ comments
3348                                             if (YY_START != SkipCxxComment)
3349                                             {
3350                                               g_lastCContext = YY_START ;
3351                                             }
3352                                             startFontClass("comment");
3353                                             g_code->codify(yytext);
3354                                             BEGIN(SkipComment);
3355                                           }
3356                                         }
3357 <*>^{B}*"//"[!/][^\n]*\n                { // remove special one-line comment
3358                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3359                                           {
3360                                             g_yyLineNr++;
3361                                             //nextCodeLine();
3362                                           }
3363                                           else
3364                                           {
3365                                             startFontClass("comment");
3366                                             codifyLines(yytext);
3367                                             endFontClass();
3368                                           }
3369                                         }
3370 <*>"//"[!/][^\n]*\n                     { // strip special one-line comment
3371                                           if (YY_START==SkipComment || YY_START==SkipString) REJECT;
3372                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3373                                           {
3374                                             char c[2]; c[0]='\n'; c[1]=0;
3375                                             codifyLines(c);
3376                                           }
3377                                           else
3378                                           {
3379                                             startFontClass("comment");
3380                                             codifyLines(yytext);
3381                                             endFontClass();
3382                                           }
3383                                         }
3384 <*>"/*[tag:"[^\]\n]*"]*/"{B}*           { // special pattern /*[tag:filename]*/ to force linking to a tag file
3385                                           g_forceTagReference=yytext;
3386                                           int s=g_forceTagReference.find(':');
3387                                           int e=g_forceTagReference.findRev(']');
3388                                           g_forceTagReference = g_forceTagReference.mid(s+1,e-s-1);
3389                                         }
3390 <*>\n{B}*"/*"[!*]/[^/*]                 {
3391                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3392                                           {
3393                                             g_lastSpecialCContext = YY_START;
3394                                             g_yyLineNr++;
3395                                             BEGIN(RemoveSpecialCComment);
3396                                           }
3397                                           else
3398                                           {
3399                                             // check is to prevent getting stuck in skipping C++ comments
3400                                             if (YY_START != SkipCxxComment)
3401                                             {
3402                                               g_lastCContext = YY_START ;
3403                                             }
3404                                             startFontClass("comment");
3405                                             codifyLines(yytext);
3406                                             BEGIN(SkipComment);
3407                                           }
3408                                         }
3409 <*>^{B}*"/*"[!*]/[^/*]                  { // special C comment block at a new line
3410                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3411                                           {
3412                                             g_lastSpecialCContext = YY_START;
3413                                             BEGIN(RemoveSpecialCComment);
3414                                           }
3415                                           else
3416                                           {
3417                                             // check is to prevent getting stuck in skipping C++ comments
3418                                             if (YY_START != SkipCxxComment)
3419                                             {
3420                                               g_lastCContext = YY_START ;
3421                                             }
3422                                             startFontClass("comment");
3423                                             g_code->codify(yytext);
3424                                             BEGIN(SkipComment);
3425                                           }
3426                                         }
3427 <*>"/*"[!*]/[^/*]                       { // special C comment block half way a line
3428                                           if (YY_START==SkipString) REJECT;
3429                                           if (Config_getBool("STRIP_CODE_COMMENTS"))
3430                                           {
3431                                             g_lastSpecialCContext = YY_START;
3432                                             BEGIN(RemoveSpecialCComment);
3433                                           }
3434                                           else
3435                                           {
3436                                             // check is to prevent getting stuck in skipping C++ comments
3437                                             if (YY_START != SkipCxxComment)
3438                                             {
3439                                               g_lastCContext = YY_START ;
3440                                             }
3441                                             startFontClass("comment");
3442                                             g_code->codify(yytext);
3443                                             BEGIN(SkipComment);
3444                                           }
3445                                         }
3446 <*>"/*"("!"?)"*/"                       { 
3447                                           if (YY_START==SkipString) REJECT;
3448                                           if (!Config_getBool("STRIP_CODE_COMMENTS"))
3449                                           {
3450                                             startFontClass("comment");
3451                                             g_code->codify(yytext);
3452                                             endFontClass();
3453                                           }
3454                                         }
3455 <*>"/*"                                 { 
3456                                           startFontClass("comment");
3457                                           g_code->codify(yytext);
3458                                           // check is to prevent getting stuck in skipping C++ comments
3459                                           if (YY_START != SkipCxxComment)
3460                                           {
3461                                             g_lastCContext = YY_START ;
3462                                           }
3463                                           BEGIN( SkipComment ) ;
3464                                         }
3465 <*>@\"                                  { // C# verbatim string
3466                                           startFontClass("stringliteral");
3467                                           g_code->codify(yytext);
3468                                           g_lastVerbStringContext=YY_START;
3469                                           BEGIN(SkipVerbString);
3470                                         }
3471 <*>"//"                                 { 
3472                                           startFontClass("comment");
3473                                           g_code->codify(yytext);
3474                                           g_lastCContext = YY_START ;
3475                                           BEGIN( SkipCxxComment ) ;
3476                                         }
3477 <*>"("|"["                                      {
3478                                           g_code->codify(yytext);
3479                                           g_theCallContext.pushScope();
3480                                         }
3481 <*>")"|"]"                                      {
3482                                           g_code->codify(yytext);
3483                                           g_theCallContext.popScope();
3484                                         }
3485 <*>\n                                   {
3486                                           g_yyColNr++;
3487                                           codifyLines(yytext); 
3488                                         }
3489 <*>.                                    {
3490                                           g_yyColNr++;
3491                                           g_code->codify(yytext);
3492                                         }
3493   /*
3494 <*>([ \t\n]*"\n"){2,}                   { // combine multiple blank lines
3495                                           //QCString sepLine=yytext;
3496                                           //g_code->codify("\n\n");
3497                                           //g_yyLineNr+=sepLine.contains('\n'); 
3498                                           //char sepLine[3]="\n\n";
3499                                           codifyLines(yytext);
3500                                         }
3501   */
3502
3503 %%
3504
3505 /*@ ----------------------------------------------------------------------------
3506  */
3507
3508 static void saveObjCContext()
3509 {
3510   if (g_currentCtx)
3511   {
3512     g_currentCtx->format+=QCString().sprintf("$c%d",g_currentCtxId);
3513     if (g_braceCount==0 && YY_START==ObjCCall)
3514     {
3515       g_currentCtx->objectTypeOrName=g_currentCtx->format.mid(1);
3516       //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
3517     }
3518     g_contextStack.push(g_currentCtx);
3519   }
3520   else
3521   {
3522     //printf("Trying to save NULL context!\n");
3523   }
3524   ObjCCallCtx *newCtx = new ObjCCallCtx;
3525   newCtx->id = g_currentCtxId;
3526   newCtx->lexState = YY_START;
3527   newCtx->braceCount = g_braceCount;
3528   newCtx->objectType = 0;
3529   newCtx->objectVar = 0;
3530   newCtx->method = 0;
3531   //printf("save state=%d\n",YY_START);
3532   g_contextDict.insert(g_currentCtxId,newCtx);
3533   g_currentCtx = newCtx;
3534   g_braceCount = 0;
3535   g_currentCtxId++;
3536 }
3537
3538 static void restoreObjCContext()
3539 {
3540   //printf("restore state=%d->%d\n",YY_START,g_currentCtx->lexState);
3541   BEGIN(g_currentCtx->lexState);
3542   g_braceCount = g_currentCtx->braceCount;
3543   if (!g_contextStack.isEmpty())
3544   {
3545     g_currentCtx = g_contextStack.pop();
3546   }
3547   else
3548   {
3549     g_currentCtx = 0;
3550     //printf("Trying to pop context while g_contextStack is empty!\n");
3551   }
3552 }
3553
3554 void resetCCodeParserState()
3555 {
3556   //printf("***initParseCodeContext()\n");
3557   g_forceTagReference.resize(0);
3558   g_theVarContext.clear();
3559   g_classScopeLengthStack.setAutoDelete(TRUE);
3560   g_classScopeLengthStack.clear();
3561   delete g_codeClassSDict;
3562   g_codeClassSDict = new ClassSDict(17);
3563   g_codeClassSDict->setAutoDelete(TRUE);
3564   g_codeClassSDict->clear();
3565   g_curClassBases.clear();
3566   g_anchorCount = 0;
3567 }
3568
3569 void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s, 
3570                 SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd,
3571                 int startLine,int endLine,bool inlineFragment,
3572                 MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
3573                 bool collectXRefs)
3574 {
3575   //printf("***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n",
3576   //      exBlock,exName,fd,className,searchCtx?searchCtx->name().data():"<none>");
3577
3578   if (s.isEmpty()) return;
3579
3580   printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
3581
3582   TooltipManager::instance()->clearTooltips();
3583   if (g_codeClassSDict==0)
3584   {
3585     resetCCodeParserState();
3586   }
3587   g_code = &od;
3588   g_inputString   = s;
3589   g_inputPosition = 0;
3590   g_currentFontClass = 0;
3591   g_needsTermination = FALSE;
3592   g_searchCtx = searchCtx;
3593   g_collectXRefs = collectXRefs;
3594   g_inFunctionTryBlock = FALSE;
3595   if (endLine!=-1)
3596     g_inputLines  = endLine+1;
3597   else
3598     g_inputLines  = countLines();
3599
3600   if (startLine!=-1)
3601     g_yyLineNr    = startLine;
3602   else
3603     g_yyLineNr    = 1;
3604
3605   g_curlyCount    = 0;
3606   g_bodyCurlyCount    = 0;
3607   g_bracketCount  = 0;
3608   g_sharpCount    = 0;
3609   g_insideTemplate = FALSE;
3610   g_theCallContext.clear();
3611   g_scopeStack.clear();
3612   g_classScope    = className;
3613   //printf("parseCCode %s\n",className);
3614   g_exampleBlock  = exBlock; 
3615   g_exampleName   = exName;
3616   g_sourceFileDef = fd;
3617   g_lineNumbers   = fd!=0 && showLineNumbers;
3618   bool cleanupSourceDef = FALSE;
3619   if (fd==0)
3620   {
3621     // create a dummy filedef for the example
3622     g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
3623     cleanupSourceDef = TRUE;
3624   }
3625   g_insideObjC = lang==SrcLangExt_ObjC;
3626   g_insideJava = lang==SrcLangExt_Java;
3627   g_insideCS   = lang==SrcLangExt_CSharp;
3628   g_insidePHP  = lang==SrcLangExt_PHP;
3629   if (g_sourceFileDef) 
3630   {
3631     setCurrentDoc("l00001");
3632   }
3633   g_currentDefinition = 0;
3634   g_currentMemberDef = 0;
3635   g_searchingForBody = exBlock;
3636   g_insideBody = FALSE;
3637   g_bracketCount = 0;
3638   if (!g_exampleName.isEmpty())
3639   {
3640     g_exampleFile = convertNameToFile(g_exampleName+"-example",FALSE,TRUE);
3641     //printf("g_exampleFile=%s\n",g_exampleFile.data());
3642   }
3643   g_includeCodeFragment = inlineFragment;
3644   //printf("** exBlock=%d exName=%s include=%d\n",exBlock,exName,inlineFragment);
3645   startCodeLine();
3646   g_type.resize(0);
3647   g_name.resize(0);
3648   g_args.resize(0);
3649   g_parmName.resize(0);
3650   g_parmType.resize(0);
3651   if (memberDef) setParameterList(memberDef);
3652   codeYYrestart( codeYYin );
3653   BEGIN( Body );
3654   codeYYlex();
3655   g_lexInit=TRUE;
3656   if (g_needsTermination)
3657   {
3658     endFontClass();
3659     DBG_CTX((stderr,"endCodeLine(%d)\n",g_yyLineNr));
3660     g_code->endCodeLine();
3661   }
3662   if (fd)
3663   {
3664     TooltipManager::instance()->writeTooltips(*g_code);
3665   }
3666   if (cleanupSourceDef)
3667   {
3668     // delete the temporary file definition used for this example
3669     delete g_sourceFileDef;
3670     g_sourceFileDef=0;
3671   }
3672
3673   printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
3674   return;
3675 }
3676
3677 void codeFreeScanner()
3678 {
3679 #if defined(YY_FLEX_SUBMINOR_VERSION) 
3680   if (g_lexInit)
3681   {
3682     codeYYlex_destroy();
3683   }
3684 #endif
3685 }
3686
3687
3688
3689 #if !defined(YY_FLEX_SUBMINOR_VERSION) 
3690 extern "C" { // some bogus code to keep the compiler happy
3691   void codeYYdummy() { yy_flex_realloc(0,0); } 
3692 }
3693 #elif YY_FLEX_SUBMINOR_VERSION<33
3694 #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!"
3695 #endif
3696