1 /******************************************************************************
5 * Copyright (C) 1997-2014 by Dimitri van Heesch.
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.
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
32 #include "outputlist.h"
34 #include "membername.h"
35 #include "searchindex.h"
36 #include "arguments.h"
39 #include "classlist.h"
42 #include "namespacedef.h"
45 // Toggle for some debugging info
46 //#define DBG_CTX(x) fprintf x
47 #define DBG_CTX(x) do { } while(0)
49 #define YY_NEVER_INTERACTIVE 1
51 #define CLASSBLOCK (int *)4
52 #define SCOPEBLOCK (int *)8
53 #define INNERBLOCK (int *)12
55 /* -----------------------------------------------------------------
59 static CodeOutputInterface * g_code;
61 static ClassSDict *g_codeClassSDict = 0;
62 static QCString g_curClassName;
63 static QStrList g_curClassBases;
65 static QCString g_parmType;
66 static QCString g_parmName;
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;
75 static bool g_exampleBlock;
76 static QCString g_exampleName;
77 static QCString g_exampleFile;
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;
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;
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;
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;
122 static bool g_lexInit = FALSE;
124 static QStack<int> g_classScopeLengthStack;
126 static Definition *g_searchCtx;
127 static bool g_collectXRefs;
129 // context for an Objective-C method call
134 QCString objectTypeOrName;
135 ClassDef *objectType;
136 MemberDef *objectVar;
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;
156 static void saveObjCContext();
157 static void restoreObjCContext();
159 static QCString g_forceTagReference;
162 //-------------------------------------------------------------------
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().
169 class VariableContext
172 static const ClassDef *dummyContext;
174 class Scope : public SDict<ClassDef>
177 Scope() : SDict<ClassDef>(17) {}
182 m_scopes.setAutoDelete(TRUE);
184 virtual ~VariableContext()
190 m_scopes.append(new Scope);
191 DBG_CTX((stderr,"** Push var context %d\n",m_scopes.count()));
196 if (m_scopes.count()>0)
198 DBG_CTX((stderr,"** Pop var context %d\n",m_scopes.count()));
199 m_scopes.remove(m_scopes.count()-1);
203 DBG_CTX((stderr,"** ILLEGAL: Pop var context\n"));
210 m_globalScope.clear();
213 void clearExceptGlobal()
215 DBG_CTX((stderr,"** Clear var context\n"));
219 void addVariable(const QCString &type,const QCString &name);
220 ClassDef *findVariable(const QCString &name);
222 int count() const { return m_scopes.count(); }
226 QList<Scope> m_scopes;
229 void VariableContext::addVariable(const QCString &type,const QCString &name)
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 ")
236 ltype = ltype.right(ltype.length()-7);
238 else if (ltype.left(6)=="union ")
240 ltype = ltype.right(ltype.length()-6);
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();
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
253 DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data()));
254 scope->append(lname,varType); // add it to a list
256 else if ((i=ltype.find('<'))!=-1)
258 // probably a template class
259 QCString typeName(ltype.left(i));
260 ClassDef* newDef = 0;
261 QCString templateArgs(ltype.right(ltype.length() - i));
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())
270 newDef = varType->getVariableInstance( templateArgs );
274 DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data()));
275 scope->append(lname, newDef);
279 // Doesn't seem to be a template. Try just the base name.
280 addVariable(typeName,name);
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!
289 DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data()));
290 scope->append(lname,dummyContext);
294 DBG_CTX((stderr,"** addVariable: not adding variable!\n"));
299 ClassDef *VariableContext::findVariable(const QCString &name)
301 if (name.isEmpty()) return 0;
302 ClassDef *result = 0;
303 QListIterator<Scope> sli(m_scopes);
306 // search from inner to outer scope
307 for (sli.toLast();(scope=sli.current());--sli)
309 result = scope->find(key);
312 DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result));
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));
322 static VariableContext g_theVarContext;
323 const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8;
325 //-------------------------------------------------------------------
332 Ctx() : name(g_name), type(g_type), d(0) {}
340 m_defList.append(new Ctx);
341 m_defList.setAutoDelete(TRUE);
343 virtual ~CallContext() {}
344 void setScope(Definition *d)
346 Ctx *ctx = m_defList.getLast();
349 DBG_CTX((stderr,"** Set call context %s (%p)\n",d==0 ? "<null>" : d->name().data(),d));
355 m_defList.append(new Ctx);
356 DBG_CTX((stderr,"** Push call context %d\n",m_defList.count()));
360 if (m_defList.count()>1)
362 DBG_CTX((stderr,"** Pop call context %d\n",m_defList.count()));
363 Ctx *ctx = m_defList.getLast();
369 m_defList.removeLast();
373 DBG_CTX((stderr,"** ILLEGAL: Pop call context\n"));
378 DBG_CTX((stderr,"** Clear call context\n"));
380 m_defList.append(new Ctx);
382 Definition *getScope() const
384 Ctx *ctx = m_defList.getLast();
385 if (ctx) return ctx->d; else return 0;
389 QList<Ctx> m_defList;
392 static CallContext g_theCallContext;
394 //-------------------------------------------------------------------
396 /*! add class/namespace name s to the scope */
397 static void pushScope(const char *s)
399 g_classScopeLengthStack.push(new int(g_classScope.length()));
400 if (g_classScope.isEmpty() || leftScopeMatch(s,g_classScope))
406 g_classScope += "::";
409 //printf("pushScope(%s) result: `%s'\n",s,g_classScope.data());
412 /*! remove the top class/namespace name from the scope */
413 static void popScope()
415 if (!g_classScopeLengthStack.isEmpty())
417 int *pLength = g_classScopeLengthStack.pop();
418 g_classScope.truncate(*pLength);
423 //err("Too many end of scopes found!\n");
425 //printf("popScope() result: `%s'\n",g_classScope.data());
428 static void setCurrentDoc(const QCString &anchor)
430 if (Doxygen::searchIndex)
434 g_code->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
438 g_code->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
443 static void addToSearchIndex(const char *text)
445 if (Doxygen::searchIndex)
447 g_code->addWord(text,FALSE);
451 static void setClassScope(const QCString &name)
453 //printf("setClassScope(%s)\n",name.data());
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)
461 // remove template from scope
462 n=n.left(ts)+n.right(n.length()-te-1);
464 while (!g_classScopeLengthStack.isEmpty())
468 g_classScope.resize(0);
470 while ((i=n.find("::"))!=-1)
472 pushScope(n.left(i));
476 //printf("--->New class scope `%s'\n",g_classScope.data());
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.
483 static void startCodeLine()
485 //if (g_currentFontClass) { g_code->endFontClass(); }
486 if (g_sourceFileDef && g_lineNumbers)
488 //QCString lineNumber,lineAnchor;
489 //lineNumber.sprintf("%05d",g_yyLineNr);
490 //lineAnchor.sprintf("l%05d",g_yyLineNr);
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)
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();
505 g_parmType.resize(0);
506 g_parmName.resize(0);
507 //printf("Real scope: `%s'\n",g_realScope.data());
508 g_bodyCurlyCount = 0;
510 lineAnchor.sprintf("l%05d",g_yyLineNr);
511 if (g_currentMemberDef)
513 g_code->writeLineNumber(g_currentMemberDef->getReference(),
514 g_currentMemberDef->getOutputFileBase(),
515 g_currentMemberDef->anchor(),g_yyLineNr);
516 setCurrentDoc(lineAnchor);
518 else if (d->isLinkableInProject())
520 g_code->writeLineNumber(d->getReference(),
521 d->getOutputFileBase(),
523 setCurrentDoc(lineAnchor);
528 g_code->writeLineNumber(0,0,0,g_yyLineNr);
531 DBG_CTX((stderr,"startCodeLine(%d)\n",g_yyLineNr));
532 g_code->startCodeLine(g_sourceFileDef && g_lineNumbers);
533 if (g_currentFontClass)
535 g_code->startFontClass(g_currentFontClass);
540 static void endFontClass();
541 static void startFontClass(const char *s);
543 static void endCodeLine()
545 DBG_CTX((stderr,"endCodeLine(%d)\n",g_yyLineNr));
547 g_code->endCodeLine();
550 static void nextCodeLine()
552 const char * fc = g_currentFontClass;
554 if (g_yyLineNr<g_inputLines)
556 g_currentFontClass = fc;
561 /*! write a code fragment `text' that may span multiple lines, inserting
562 * line numbers for each line.
564 static void codifyLines(const char *text)
566 //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
567 const char *p=text,*sp=p;
573 while ((c=*p++) && c!='\n') { g_yyColNr++; }
579 int l = (int)(p-sp-1);
580 char *tmp = (char*)malloc(l+1);
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.
599 static void writeMultiLineCodeLink(CodeOutputInterface &ol,
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();
609 if (!sourceTooltips) // fall back to simple "title" tooltips
611 tooltip = d->briefDescriptionAsTooltip();
614 char *p=(char *)text;
619 while ((c=*p++) && c!='\n') { }
624 //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
625 ol.writeCodeLink(ref,file,anchor,sp,tooltip);
630 //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
631 ol.writeCodeLink(ref,file,anchor,sp,tooltip);
637 static void addType()
639 if (g_name=="const") { g_name.resize(0); return; }
640 if (!g_type.isEmpty()) g_type += ' ' ;
643 if (!g_type.isEmpty()) g_type += ' ' ;
648 static void addParmType()
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) ;
656 static void addUsingDirective(const char *name)
658 if (g_sourceFileDef && name)
660 NamespaceDef *nd = Doxygen::namespaceSDict->find(name);
663 g_sourceFileDef->addUsingDirective(nd);
668 static void setParameterList(MemberDef *md)
670 g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : "";
671 ArgumentList *al = md->argumentList();
673 ArgumentListIterator it(*al);
675 for (;(a=it.current());++it)
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);
689 static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
695 while (extractClassNameFromType(type,pos,className,templSpec)!=-1)
697 QCString clName=className+templSpec;
699 if (!g_classScope.isEmpty())
701 cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName);
705 cd=getResolvedClass(d,g_sourceFileDef,clName);
707 //printf("stripClass trying `%s' = %p\n",clName.data(),cd);
717 static MemberDef *setCallContextForVar(const QCString &name)
719 if (name.isEmpty()) return 0;
720 DBG_CTX((stderr,"setCallContextForVar(%s) g_classScope=%s\n",name.data(),g_classScope.data()));
722 int scopeEnd = name.findRev("::");
723 if (scopeEnd!=-1) // name with explicit scope
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())
731 MemberDef *md=mcd->getMemberByName(locName);
734 //printf("name=%s scope=%s\n",locName.data(),scope.data());
735 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
739 else // check namespace as well
741 NamespaceDef *mnd = getResolvedNamespace(scope);
742 if (mnd && !locName.isEmpty())
744 MemberDef *md=mnd->getMemberByName(locName);
747 //printf("name=%s scope=%s\n",locName.data(),scope.data());
748 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
756 ClassDef *mcd = g_theVarContext.findVariable(name);
757 if (mcd) // local variable
759 DBG_CTX((stderr,"local variable?\n"));
760 if (mcd!=VariableContext::dummyContext)
762 DBG_CTX((stderr,"local var `%s' mcd=%s\n",name.data(),mcd->name().data()));
763 g_theCallContext.setScope(mcd);
768 DBG_CTX((stderr,"class member? scope=%s\n",g_classScope.data()));
769 // look for a class member
770 mcd = getClass(g_classScope);
773 DBG_CTX((stderr,"Inside class %s\n",mcd->name().data()));
774 MemberDef *md=mcd->getMemberByName(name);
777 DBG_CTX((stderr,"Found member %s\n",md->name().data()));
778 if (g_scopeStack.top()!=CLASSBLOCK)
780 DBG_CTX((stderr,"class member `%s' mcd=%s\n",name.data(),mcd->name().data()));
781 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
788 // look for a global member
789 if ((mn=Doxygen::functionNameSDict->find(name)))
791 //printf("global var `%s'\n",name.data());
792 if (mn->count()==1) // global defined only once
794 MemberDef *md=mn->getFirst();
795 if (!md->isStatic() || md->getBodyDef()==g_sourceFileDef)
797 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
802 else if (mn->count()>1) // global defined more than once
804 MemberNameIterator it(*mn);
806 for (;(md=it.current());++it)
808 //printf("mn=%p md=%p md->getBodyDef()=%p g_sourceFileDef=%p\n",
810 // md->getBodyDef(),g_sourceFileDef);
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())
819 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
820 //printf("returning member %s in source file %s\n",md->name().data(),g_sourceFileDef->name().data());
830 static void updateCallContextForSmartPointer()
832 Definition *d = g_theCallContext.getScope();
833 //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : "<none>");
835 if (d && d->definitionType()==Definition::TypeClass && (md=((ClassDef*)d)->isSmartPointer()))
837 ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope());
840 g_theCallContext.setScope(ncd);
841 //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data());
846 static bool getLinkInScope(const QCString &c, // scope
847 const QCString &m, // member
848 const char *memberText, // exact text
849 CodeOutputInterface &ol,
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()))
863 //printf("found it %s!\n",md->qualifiedName().data());
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))
872 ol.writeCodeAnchor(anchor);
877 Definition *d = md->getOuterScope()==Doxygen::globalScope ?
878 md->getFileDef() : md->getOuterScope();
879 if (md->getGroupDef()) d = md->getGroupDef();
880 if (d && d->isLinkable())
882 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
883 //printf("g_currentDefinition=%p g_currentMemberDef=%p g_insideBody=%d\n",
884 // g_currentDefinition,g_currentMemberDef,g_insideBody);
886 if (g_currentDefinition && g_currentMemberDef &&
887 md!=g_currentMemberDef && g_insideBody && g_collectXRefs)
889 addDocCrossReference(g_currentMemberDef,md);
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());
893 writeMultiLineCodeLink(ol,md, text ? text : memberText);
894 addToSearchIndex(text ? text : memberText);
901 static bool getLink(const char *className,
902 const char *memberName,
903 CodeOutputInterface &ol,
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))
912 if (!g_curClassName.isEmpty())
914 if (!c.isEmpty()) c.prepend("::");
915 c.prepend(g_curClassName);
916 return getLinkInScope(c,m,memberName,ol,text,varOnly);
923 static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName,
924 bool typeOnly=FALSE,bool varOnly=FALSE)
927 if (*clName=='~') // correct for matching negated values i.s.o. destructors.
932 QCString className=clName;
933 if (className.isEmpty()) return;
934 if (g_insideProtocolList) // for Obj-C
940 className = substitute(className,"\\","::"); // for PHP namespaces
942 else if (g_insideCS || g_insideJava)
944 className = substitute(className,".","::"); // for PHP namespaces
946 ClassDef *cd=0,*lcd=0;
950 //printf("generateClassOrGlobalLink(className=%s)\n",className.data());
951 if ((lcd=g_theVarContext.findVariable(className))==0) // not a local variable
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)
961 QCString bareName = className.left(i); //stripTemplateSpecifiersFromScope(className);
962 DBG_CTX((stderr,"bareName=%s\n",bareName.data()));
963 if (bareName!=className)
965 cd=getResolvedClass(d,g_sourceFileDef,bareName,&md); // try unspecialized version
968 NamespaceDef *nd = getResolvedNamespace(className);
971 g_theCallContext.setScope(nd);
972 addToSearchIndex(className);
973 writeMultiLineCodeLink(*g_code,nd,clName);
976 //printf("md=%s\n",md?md->name().data():"<none>");
977 DBG_CTX((stderr,"is found as a type cd=%s nd=%s\n",
978 cd?cd->name().data():"<null>",
979 nd?nd->name().data():"<null>"));
980 if (cd==0 && md==0) // also see if it is variable or enum or enum value
982 if (getLink(g_classScope,clName,ol,clName,varOnly))
990 //printf("local variable!\n");
991 if (lcd!=VariableContext::dummyContext)
993 //printf("non-dummy context lcd=%s!\n",lcd->name().data());
994 g_theCallContext.setScope(lcd);
996 // to following is needed for links to a global variable, but is
997 // no good for a link to a local variable that is also a global symbol.
999 //if (getLink(g_classScope,clName,ol,clName))
1005 DBG_CTX((stderr,"is a local variable cd=%p!\n",cd));
1007 if (cd && cd->isLinkable()) // is it a linkable class
1009 DBG_CTX((stderr,"is linkable class %s\n",clName));
1013 anchor.sprintf("_a%d",g_anchorCount);
1014 //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
1015 // g_exampleFile.data());
1016 if (cd->addExample(anchor,g_exampleName,g_exampleFile))
1018 ol.writeCodeAnchor(anchor);
1022 writeMultiLineCodeLink(ol,cd,clName);
1023 addToSearchIndex(className);
1024 g_theCallContext.setScope(cd);
1027 Definition *d = md->getOuterScope()==Doxygen::globalScope ?
1028 md->getFileDef() : md->getOuterScope();
1029 if (md->getGroupDef()) d = md->getGroupDef();
1030 if (d && d->isLinkable() && md->isLinkable() &&
1031 g_currentMemberDef && g_collectXRefs)
1033 addDocCrossReference(g_currentMemberDef,md);
1037 else // not a class, maybe a global member
1039 DBG_CTX((stderr,"class %s not linkable! cd=%p md=%p typeOnly=%d\n",clName,cd,md,typeOnly));
1040 if (!isLocal && (md!=0 || (cd==0 && !typeOnly))) // not a class, see if it is a global enum/variable/typedef.
1042 if (md==0) // not found as a typedef
1044 md = setCallContextForVar(clName);
1045 //printf("setCallContextForVar(%s) md=%p g_currentDefinition=%p\n",clName,md,g_currentDefinition);
1046 if (md && g_currentDefinition)
1048 DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n",
1049 md->name().data(),g_currentDefinition->name().data(),
1050 isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md),
1051 md->getOuterScope()->name().data()));
1054 if (md && g_currentDefinition &&
1055 isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md)==-1)
1057 md=0; // variable not accessible
1060 if (md && (!varOnly || md->isVariable()))
1062 DBG_CTX((stderr,"is a global md=%p g_currentDefinition=%s linkable=%d\n",md,g_currentDefinition?g_currentDefinition->name().data():"<none>",md->isLinkable()));
1063 if (md->isLinkable())
1066 if (!g_forceTagReference.isEmpty()) // explicit reference to symbol in tag file
1068 text=g_forceTagReference;
1069 if (text.right(4)==".tag") // strip .tag if present
1071 text=text.left(text.length()-4);
1073 text+=getLanguageSpecificSeparator(md->getLanguage());
1076 md->setLocalName(text);
1078 else // normal reference
1082 writeMultiLineCodeLink(ol,md,text);
1083 addToSearchIndex(clName);
1084 if (g_currentMemberDef && g_collectXRefs)
1086 addDocCrossReference(g_currentMemberDef,md);
1093 // nothing found, just write out the word
1094 DBG_CTX((stderr,"not found!\n"));
1095 codifyLines(clName);
1096 addToSearchIndex(clName);
1100 static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const char *memName)
1102 // extract class definition of the return type in order to resolve
1103 // a->b()->c() like call chains
1105 //printf("type=`%s' args=`%s' class=%s\n",
1106 // xmd->typeString(),xmd->argsString(),
1107 // xmd->getClassDef()->name().data());
1112 anchor.sprintf("a%d",g_anchorCount);
1113 //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
1114 // g_exampleFile.data());
1115 if (xmd->addExample(anchor,g_exampleName,g_exampleFile))
1117 ol.writeCodeAnchor(anchor);
1122 ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope());
1123 DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass));
1124 g_theCallContext.setScope(typeClass);
1126 Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
1127 xmd->getFileDef() : xmd->getOuterScope();
1128 if (xmd->getGroupDef()) xd = xmd->getGroupDef();
1129 if (xd && xd->isLinkable())
1132 //printf("g_currentDefiniton=%p g_currentMemberDef=%p xmd=%p g_insideBody=%d\n",g_currentDefinition,g_currentMemberDef,xmd,g_insideBody);
1134 if (xmd->templateMaster()) xmd = xmd->templateMaster();
1136 if (xmd->isLinkable())
1138 // add usage reference
1139 if (g_currentDefinition && g_currentMemberDef &&
1140 /*xmd!=g_currentMemberDef &&*/ g_insideBody && g_collectXRefs)
1142 addDocCrossReference(g_currentMemberDef,xmd);
1145 // write the actual link
1146 writeMultiLineCodeLink(ol,xmd,memName);
1147 addToSearchIndex(memName);
1155 static bool generateClassMemberLink(CodeOutputInterface &ol,Definition *def,const char *memName)
1157 if (def && def->definitionType()==Definition::TypeClass)
1159 ClassDef *cd = (ClassDef*)def;
1160 MemberDef *xmd = cd->getMemberByName(memName);
1161 //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd);
1164 return generateClassMemberLink(ol,xmd,memName);
1168 Definition *innerDef = cd->findInnerCompound(memName);
1171 g_theCallContext.setScope(innerDef);
1172 addToSearchIndex(memName);
1173 writeMultiLineCodeLink(*g_code,innerDef,memName);
1178 else if (def && def->definitionType()==Definition::TypeNamespace)
1180 NamespaceDef *nd = (NamespaceDef*)def;
1181 //printf("Looking for %s inside namespace %s\n",memName,nd->name().data());
1182 Definition *innerDef = nd->findInnerCompound(memName);
1185 g_theCallContext.setScope(innerDef);
1186 addToSearchIndex(memName);
1187 writeMultiLineCodeLink(*g_code,innerDef,memName);
1194 static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName,
1197 //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n",
1198 // varName.data(),memName,g_classScope.data());
1200 if (varName.isEmpty()) return;
1202 // look for the variable in the current context
1203 ClassDef *vcd = g_theVarContext.findVariable(varName);
1206 if (vcd!=VariableContext::dummyContext)
1208 //printf("Class found!\n");
1209 if (getLink(vcd->name(),memName,ol))
1211 //printf("Found result!\n");
1214 if (vcd->baseClasses())
1216 BaseClassListIterator bcli(*vcd->baseClasses());
1217 for ( ; bcli.current() ; ++bcli)
1219 if (getLink(bcli.current()->classDef->name(),memName,ol))
1221 //printf("Found result!\n");
1228 else // variable not in current context, maybe it is in a parent context
1230 vcd = getResolvedClass(g_currentDefinition,g_sourceFileDef,g_classScope);
1231 if (vcd && vcd->isLinkable())
1233 //printf("Found class %s for variable `%s'\n",g_classScope.data(),varName.data());
1234 MemberName *vmn=Doxygen::memberNameSDict->find(varName);
1238 QCString vn=varName;
1240 if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1) // explicit scope A::b(), probably static member
1242 ClassDef *jcd = getClass(vn.left(vi));
1243 vn=vn.right(vn.length()-vi-2);
1244 vmn=Doxygen::memberNameSDict->find(vn);
1245 //printf("Trying name `%s' scope=%s\n",vn.data(),scope.data());
1248 MemberNameIterator vmni(*vmn);
1250 for (;(vmd=vmni.current());++vmni)
1252 if (/*(vmd->isVariable() || vmd->isFunction()) && */
1253 vmd->getClassDef()==jcd)
1255 //printf("Found variable type=%s\n",vmd->typeString());
1256 ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1257 if (mcd && mcd->isLinkable())
1259 if (generateClassMemberLink(ol,mcd,memName)) return;
1268 //printf("There is a variable with name `%s'\n",varName);
1269 MemberNameIterator vmni(*vmn);
1271 for (;(vmd=vmni.current());++vmni)
1273 if (/*(vmd->isVariable() || vmd->isFunction()) && */
1274 vmd->getClassDef()==vcd)
1276 //printf("Found variable type=%s\n",vmd->typeString());
1277 ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1278 if (mcd && mcd->isLinkable())
1280 if (generateClassMemberLink(ol,mcd,memName)) return;
1287 // nothing found -> write result as is
1288 codifyLines(memName);
1289 addToSearchIndex(memName);
1293 static void generatePHPVariableLink(CodeOutputInterface &ol,const char *varName)
1295 QCString name = varName+7; // strip $this->
1297 //printf("generatePHPVariableLink(%s) name=%s scope=%s\n",varName,name.data(),g_classScope.data());
1298 if (!getLink(g_classScope,name,ol,varName))
1300 codifyLines(varName);
1304 static void generateFunctionLink(CodeOutputInterface &ol,const char *funcName)
1306 //CodeClassDef *ccd=0;
1308 QCString locScope=g_classScope;
1309 QCString locFunc=removeRedundantWhiteSpace(funcName);
1311 QCString funcWithScope=locFunc;
1312 QCString funcWithFullScope=locFunc;
1313 QCString fullScope=locScope;
1314 DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data()));
1316 int i=locFunc.findRev("::");
1317 if (g_currentMemberDef && g_currentMemberDef->getClassDef() &&
1318 funcName==g_currentMemberDef->localName() &&
1319 g_currentMemberDef->getDefLine()==g_yyLineNr &&
1320 generateClassMemberLink(ol,g_currentMemberDef,funcName)
1323 // special case where funcName is the name of a method that is also
1324 // defined on this line. In this case we can directly link to
1325 // g_currentMemberDef, which is not only faster, but
1326 // in case of overloaded methods, this will make sure that we link to
1327 // the correct method, and thereby get the correct reimplemented relations.
1328 // See also bug 549022.
1331 if (i==-1) i=locFunc.findRev("."),len=1;
1332 if (i==-1) i=locFunc.findRev("\\"),len=1; // for PHP
1335 funcScope=locFunc.left(i);
1336 locFunc=locFunc.right(locFunc.length()-i-len).stripWhiteSpace();
1337 int ts=locScope.find('<'); // start of template
1338 int te=locScope.findRev('>'); // end of template
1339 //printf("ts=%d te=%d\n",ts,te);
1340 if (ts!=-1 && te!=-1 && te>ts)
1342 // remove template from scope
1343 locScope=locScope.left(ts)+locScope.right(locScope.length()-te-1);
1345 ts=funcScope.find('<'); // start of template
1346 te=funcScope.findRev('>'); // end of template
1347 //printf("ts=%d te=%d\n",ts,te);
1348 if (ts!=-1 && te!=-1 && te>ts)
1350 // remove template from scope
1351 funcScope=funcScope.left(ts)+funcScope.right(funcScope.length()-te-1);
1353 if (!funcScope.isEmpty())
1355 funcWithScope = funcScope+"::"+locFunc;
1356 if (!locScope.isEmpty())
1358 fullScope=locScope+"::"+funcScope;
1361 if (!locScope.isEmpty())
1363 funcWithFullScope = locScope+"::"+funcWithScope;
1366 if (!fullScope.isEmpty() && (ccd=g_codeClassSDict->find(fullScope)))
1368 //printf("using classScope %s\n",g_classScope.data());
1369 if (ccd->baseClasses())
1371 BaseClassListIterator bcli(*ccd->baseClasses());
1372 for ( ; bcli.current() ; ++bcli)
1374 if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName))
1381 if (!locScope.isEmpty() && fullScope!=locScope && (ccd=g_codeClassSDict->find(locScope)))
1383 //printf("using classScope %s\n",g_classScope.data());
1384 if (ccd->baseClasses())
1386 BaseClassListIterator bcli(*ccd->baseClasses());
1387 for ( ; bcli.current() ; ++bcli)
1389 if (getLink(bcli.current()->classDef->name(),funcWithScope,ol,funcName))
1396 if (!getLink(locScope,funcWithScope,ol,funcName))
1398 generateClassOrGlobalLink(ol,funcName);
1401 g_forceTagReference.resize(0);
1405 /*! counts the number of lines in the input */
1406 static int countLines()
1408 const char *p=g_inputString;
1414 if (c=='\n') count++;
1416 if (p>g_inputString && *(p-1)!='\n')
1417 { // last line does not end with a \n, so we add an extra
1418 // line and explicitly terminate the line after parsing.
1420 g_needsTermination=TRUE;
1425 static void endFontClass()
1427 if (g_currentFontClass)
1429 g_code->endFontClass();
1430 g_currentFontClass=0;
1434 static void startFontClass(const char *s)
1437 g_code->startFontClass(s);
1438 g_currentFontClass=s;
1441 //----------------------------------------------------------------------------
1443 // recursively writes a linkified Objective-C method call
1444 static void writeObjCMethodCall(ObjCCallCtx *ctx)
1448 const char *p = ctx->format.data();
1449 if (!ctx->methodName.isEmpty())
1451 //printf("writeObjCMethodCall(%s) obj=%s method=%s\n",
1452 // ctx->format.data(),ctx->objectTypeOrName.data(),ctx->methodName.data());
1453 if (!ctx->objectTypeOrName.isEmpty() && ctx->objectTypeOrName.at(0)!='$')
1455 //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(),
1456 // ctx->methodName.data());
1457 ClassDef *cd = g_theVarContext.findVariable(ctx->objectTypeOrName);
1458 if (cd==0) // not a local variable
1460 if (ctx->objectTypeOrName=="self")
1462 if (g_currentDefinition &&
1463 g_currentDefinition->definitionType()==Definition::TypeClass)
1465 ctx->objectType = (ClassDef *)g_currentDefinition;
1470 ctx->objectType = getResolvedClass(
1471 g_currentDefinition,
1473 ctx->objectTypeOrName,
1476 //printf(" object is class? %p\n",ctx->objectType);
1477 if (ctx->objectType) // found class
1479 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1480 //printf(" yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>");
1482 else if (ctx->method==0) // search for class variable with the same name
1485 //printf("g_currentDefinition=%p\n",g_currentDefinition);
1486 if (g_currentDefinition &&
1487 g_currentDefinition->definitionType()==Definition::TypeClass)
1489 ctx->objectVar = ((ClassDef *)g_currentDefinition)->getMemberByName(ctx->objectTypeOrName);
1490 //printf(" ctx->objectVar=%p\n",ctx->objectVar);
1493 ctx->objectType = stripClassName(ctx->objectVar->typeString());
1494 //printf(" ctx->objectType=%p\n",ctx->objectType);
1495 if (ctx->objectType)
1497 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1498 //printf(" ctx->method=%p\n",ctx->method);
1504 else // local variable
1506 //printf(" object is local variable\n");
1507 if (cd!=VariableContext::dummyContext)
1509 ctx->method = cd->getMemberByName(ctx->methodName);
1510 //printf(" class=%p method=%p\n",cd,ctx->method);
1517 while ((c=*p++)) // for each character in ctx->format
1522 if (nc=='$') // escaped $
1524 g_code->codify("$");
1526 else // name fragment or reference to a nested call
1528 if (nc=='n') // name fragment
1532 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1534 int refId=refIdStr.toInt();
1535 QCString *pName = g_nameDict.find(refId);
1538 if (ctx->method && ctx->method->isLinkable())
1540 writeMultiLineCodeLink(*g_code,ctx->method,pName->data());
1541 if (g_currentMemberDef && g_collectXRefs)
1543 addDocCrossReference(g_currentMemberDef,ctx->method);
1548 codifyLines(pName->data());
1553 //printf("Invalid name: id=%d\n",refId);
1556 else if (nc=='o') // reference to potential object name
1560 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1562 int refId=refIdStr.toInt();
1563 QCString *pObject = g_objectDict.find(refId);
1566 if (*pObject=="self")
1568 if (g_currentDefinition &&
1569 g_currentDefinition->definitionType()==Definition::TypeClass)
1571 ctx->objectType = (ClassDef *)g_currentDefinition;
1572 if (ctx->objectType->categoryOf())
1574 ctx->objectType = ctx->objectType->categoryOf();
1576 if (ctx->objectType)
1578 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1581 startFontClass("keyword");
1582 codifyLines(pObject->data());
1585 else if (*pObject=="super")
1587 if (g_currentDefinition &&
1588 g_currentDefinition->definitionType()==Definition::TypeClass)
1590 ClassDef *cd = (ClassDef *)g_currentDefinition;
1591 if (cd->categoryOf())
1593 cd = cd->categoryOf();
1595 BaseClassList *bcd = cd->baseClasses();
1596 if (bcd) // get direct base class (there should be only one)
1598 BaseClassListIterator bli(*bcd);
1599 BaseClassDef *bclass;
1600 for (bli.toFirst();(bclass=bli.current());++bli)
1602 if (bclass->classDef->compoundType()!=ClassDef::Protocol)
1604 ctx->objectType = bclass->classDef;
1605 if (ctx->objectType)
1607 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1613 startFontClass("keyword");
1614 codifyLines(pObject->data());
1617 else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable
1619 writeMultiLineCodeLink(*g_code,ctx->objectVar,pObject->data());
1620 if (g_currentMemberDef && g_collectXRefs)
1622 addDocCrossReference(g_currentMemberDef,ctx->objectVar);
1625 else if (ctx->objectType &&
1626 ctx->objectType!=VariableContext::dummyContext &&
1627 ctx->objectType->isLinkable()
1628 ) // object is class name
1630 ClassDef *cd = ctx->objectType;
1631 writeMultiLineCodeLink(*g_code,cd,pObject->data());
1633 else // object still needs to be resolved
1635 ClassDef *cd = getResolvedClass(g_currentDefinition,
1636 g_sourceFileDef, *pObject);
1637 if (cd && cd->isLinkable())
1639 if (ctx->objectType==0) ctx->objectType=cd;
1640 writeMultiLineCodeLink(*g_code,cd,pObject->data());
1644 codifyLines(pObject->data());
1650 //printf("Invalid object: id=%d\n",refId);
1653 else if (nc=='c') // reference to nested call
1657 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1659 int refId=refIdStr.toInt();
1660 ObjCCallCtx *ictx = g_contextDict.find(refId);
1661 if (ictx) // recurse into nested call
1663 writeObjCMethodCall(ictx);
1664 if (ictx->method) // link to nested call successfully
1666 // get the ClassDef representing the method's return type
1667 if (QCString(ictx->method->typeString())=="id")
1669 // see if the method name is unique, if so we link to it
1670 MemberName *mn=Doxygen::memberNameSDict->find(ctx->methodName);
1671 //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n",
1672 // mn==0?-1:(int)mn->count(),
1673 // ictx->method->name().data(),
1674 // ctx->methodName.data());
1675 if (mn && mn->count()==1) // member name unique
1677 ctx->method = mn->getFirst();
1682 ctx->objectType = stripClassName(ictx->method->typeString());
1683 if (ctx->objectType)
1685 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1688 //printf(" ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType);
1693 //printf("Invalid context: id=%d\n",refId);
1696 else if (nc=='w') // some word
1700 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1702 int refId=refIdStr.toInt();
1703 QCString *pWord = g_wordDict.find(refId);
1706 codifyLines(pWord->data());
1709 else // illegal marker
1711 ASSERT(!"invalid escape sequence");
1715 else // normal non-marker character
1722 //printf("%s %s]\n",ctx->objectTypeOrName.data(),ctx->methodName.data());
1723 //printf("}=(type='%s',name='%s')",
1724 // ctx->objectTypeOrName.data(),
1725 // ctx->methodName.data());
1728 // Replaces an Objective-C method name fragment s by a marker of the form
1729 // $n12, the number (12) can later be used as a key for obtaining the name
1730 // fragment, from g_nameDict
1731 static QCString escapeName(const char *s)
1734 result.sprintf("$n%d",g_currentNameId);
1735 g_nameDict.insert(g_currentNameId,new QCString(s));
1740 static QCString escapeObject(const char *s)
1743 result.sprintf("$o%d",g_currentObjId);
1744 g_objectDict.insert(g_currentObjId,new QCString(s));
1749 static QCString escapeWord(const char *s)
1752 result.sprintf("$w%d",g_currentWordId);
1753 g_wordDict.insert(g_currentWordId,new QCString(s));
1758 /* -----------------------------------------------------------------
1761 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
1763 static int yyread(char *buf,int max_size)
1766 while( c < max_size && g_inputString[g_inputPosition] )
1768 *buf = g_inputString[g_inputPosition++] ;
1778 ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
1780 SCOPENAME ({SEP}{BN}*)?({ID}{BN}*{SEP}{BN}*)*("~"{BN}*)?{ID}
1781 TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">"
1782 SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?{SEP}{BN}*)*)((~{BN}*)?{ID})
1783 SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*{SEP}{BN}*)+
1784 KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property")
1785 KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|"alignas"|"alignof"|{KEYWORD_OBJC})
1786 FLOWKW ("break"|"case"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"for"|"foreach"|"for each"|"goto"|"if"|"return"|"switch"|"throw"|"throws"|"try"|"while"|"@try"|"@catch"|"@finally")
1787 TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
1788 CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast")
1789 CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'"))
1790 ARITHOP "+"|"-"|"/"|"*"|"%"|"--"|"++"
1791 ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|="
1792 LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"
1793 BITOP "&"|"|"|"^"|"<<"|">>"|"~"
1794 OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
1795 RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"("
1796 RAWEND ")"[^ \t\(\)\\]{0,16}\"
1806 %x RemoveSpecialCComment
1807 %x StripSpecialCComment
1818 %x CppCliTypeModifierFollowup
1839 <Body>^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") {
1840 startFontClass("preprocessor");
1841 g_code->codify(yytext);
1842 BEGIN( ReadInclude );
1844 <Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ {
1846 startFontClass("keyword");
1847 codifyLines(yytext);
1849 if (!g_insideTemplate)
1852 <Body>(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") {
1853 if (g_insideTemplate) REJECT;
1854 startFontClass("keyword");
1855 codifyLines(yytext);
1859 <Body>"property"|"event"/{BN}* {
1860 if (g_insideTemplate) REJECT;
1861 startFontClass("keyword");
1862 codifyLines(yytext);
1865 <Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ {
1866 startFontClass("keyword");
1867 codifyLines(yytext);
1869 if (!g_insideTemplate)
1872 <Body>("package")[ \t\n]+ {
1873 startFontClass("keyword");
1874 codifyLines(yytext);
1876 BEGIN( PackageName );
1879 if (!g_insideObjC) REJECT;
1880 codifyLines(yytext);
1883 <Body,ClassVar,Bases>"-"|"+" {
1884 if (!g_insideObjC || g_insideBody)
1886 g_code->codify(yytext);
1888 else // Start of Objective-C method
1890 //printf("Method!\n");
1891 g_code->codify(yytext);
1896 g_code->codify(yytext);
1900 g_code->codify(yytext);
1901 BEGIN(ObjCParamType);
1903 <ObjCParams,ObjCMethod>";"|"{" {
1904 g_code->codify(yytext);
1908 if (g_searchingForBody)
1910 g_searchingForBody=FALSE;
1913 if (g_insideBody) g_bodyCurlyCount++;
1914 if (!g_curClassName.isEmpty()) // valid class name
1916 pushScope(g_curClassName);
1917 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
1918 g_scopeStack.push(SCOPEBLOCK);
1925 <ObjCParams>{ID}{B}*":" {
1926 g_code->codify(yytext);
1928 <ObjCParamType>{TYPEKW} {
1929 startFontClass("keywordtype");
1930 g_code->codify(yytext);
1934 <ObjCParamType>{ID} {
1935 generateClassOrGlobalLink(*g_code,yytext);
1938 <ObjCParamType>")" {
1939 g_code->codify(yytext);
1943 g_code->codify(yytext);
1945 g_theVarContext.addVariable(g_parmType,g_parmName);
1946 g_parmType.resize(0);g_parmName.resize(0);
1948 <ObjCMethod,ObjCParams,ObjCParamType>{ID} {
1949 generateClassOrGlobalLink(*g_code,yytext);
1951 <ObjCMethod,ObjCParams,ObjCParamType>. {
1952 g_code->codify(yytext);
1954 <ObjCMethod,ObjCParams,ObjCParamType>\n {
1955 codifyLines(yytext);
1957 <ReadInclude>[^\n\"\>]+/(">"|"\"") {
1961 //QCString absPath = yytext;
1962 //if (g_sourceFileDef && QDir::isRelativePath(absPath))
1964 // absPath = QDir::cleanDirPath(g_sourceFileDef->getPath()+"/"+absPath);
1967 FileDef *fd=findFileDef(Doxygen::inputNameDict,yytext,ambig);
1968 //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd);
1969 if (fd && fd->isLinkable())
1971 if (ambig) // multiple input files match the name
1973 //printf("===== yes %s is ambiguous\n",yytext);
1974 QCString name = QDir::cleanDirPath(yytext).utf8();
1975 if (!name.isEmpty() && g_sourceFileDef)
1977 FileName *fn = Doxygen::inputNameDict->find(name);
1980 FileNameIterator fni(*fn);
1981 // for each include name
1982 for (fni.toFirst();!found && (fd=fni.current());++fni)
1984 // see if this source file actually includes the file
1985 found = g_sourceFileDef->isIncluded(fd->absFilePath());
1986 //printf(" include file %s found=%d\n",fd->absFilePath().data(),found);
1991 else // not ambiguous
1996 //printf(" include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found);
1999 writeMultiLineCodeLink(*g_code,fd,yytext);
2003 g_code->codify(yytext);
2008 g_code->codify(text);
2012 <Body,Bases>^[ \t]*"#" {
2013 startFontClass("preprocessor");
2014 g_lastSkipCppContext = YY_START;
2015 g_code->codify(yytext);
2019 g_code->codify(yytext);
2021 <SkipCPP>[^\n\/\\]+ {
2022 g_code->codify(yytext);
2024 <SkipCPP>\\[\r]?\n {
2025 codifyLines(yytext);
2028 g_code->codify(yytext);
2030 <Body,FuncCall>"{" {
2031 g_theVarContext.pushScope();
2033 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2034 g_scopeStack.push(INNERBLOCK);
2036 if (g_searchingForBody)
2038 g_searchingForBody=FALSE;
2041 g_code->codify(yytext);
2051 <Body,MemberCall,MemberCall2>"}" {
2052 g_theVarContext.popScope();
2056 int *scope = g_scopeStack.pop();
2057 DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2058 if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
2063 g_code->codify(yytext);
2065 DBG_CTX((stderr,"g_bodyCurlyCount=%d\n",g_bodyCurlyCount));
2066 if (--g_bodyCurlyCount<=0)
2069 g_currentMemberDef=0;
2070 if (g_currentDefinition)
2071 g_currentDefinition=g_currentDefinition->getOuterScope();
2075 <Body,ClassVar>"@end" {
2076 //printf("End of objc scope fd=%s\n",g_sourceFileDef->name().data());
2077 if (g_sourceFileDef)
2079 FileDef *fd=g_sourceFileDef;
2080 g_insideObjC = fd->name().lower().right(2)==".m" ||
2081 fd->name().lower().right(3)==".mm";
2082 //printf("insideObjC=%d\n",g_insideObjC);
2086 g_insideObjC = FALSE;
2090 g_theVarContext.popScope();
2092 int *scope = g_scopeStack.pop();
2093 DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2094 if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
2101 startFontClass("keyword");
2102 g_code->codify(yytext);
2105 g_currentMemberDef=0;
2106 if (g_currentDefinition)
2107 g_currentDefinition=g_currentDefinition->getOuterScope();
2110 <ClassName,ClassVar>";" {
2111 g_code->codify(yytext);
2112 g_searchingForBody=FALSE;
2115 <ClassName,ClassVar>[*&^%]+ {
2116 g_type=g_curClassName.copy();
2118 g_code->codify(yytext);
2119 BEGIN( Body ); // variable of type struct *
2121 <ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")" {
2122 startFontClass("keyword");
2123 g_code->codify(yytext);
2126 <ClassName>{ID}("::"{ID})* {
2127 g_curClassName=yytext;
2129 if (g_curClassName=="alignas")
2131 startFontClass("keyword");
2132 g_code->codify(yytext);
2138 generateClassOrGlobalLink(*g_code,yytext);
2144 g_code->codify(yytext);
2145 BEGIN( AlignAsEnd );
2147 <AlignAs>\n { g_yyLineNr++;
2148 codifyLines(yytext);
2150 <AlignAs>. { g_code->codify(yytext); }
2151 <AlignAsEnd>"(" { g_code->codify(yytext);
2155 g_code->codify(yytext);
2156 if (--g_bracketCount<=0)
2161 <AlignAsEnd>\n { g_yyLineNr++;
2162 codifyLines(yytext);
2164 <AlignAsEnd>. { g_code->codify(yytext); }
2165 <ClassName>{ID}("\\"{ID})* { // PHP namespace
2166 g_curClassName=substitute(yytext,"\\","::");
2167 g_scopeStack.push(CLASSBLOCK);
2168 pushScope(g_curClassName);
2170 generateClassOrGlobalLink(*g_code,yytext);
2173 <ClassName>{ID}{B}*"("{ID}")" { // Obj-C category
2174 g_curClassName=removeRedundantWhiteSpace(yytext);
2175 g_scopeStack.push(CLASSBLOCK);
2176 pushScope(g_curClassName);
2178 generateClassOrGlobalLink(*g_code,yytext);
2181 <PackageName>{ID}("."{ID})* {
2182 g_curClassName=substitute(yytext,".","::");
2183 //printf("found package: %s\n",g_curClassName.data());
2185 codifyLines(yytext);
2191 <ClassVar>("extends"|"implements") { // Java
2192 startFontClass("keyword");
2193 codifyLines(yytext);
2195 g_curClassBases.clear();
2198 <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") {
2199 DBG_CTX((stderr,"***** C++/CLI modifier %s on g_curClassName=%s\n",yytext,g_curClassName.data()));
2200 startFontClass("keyword");
2201 codifyLines(yytext);
2203 BEGIN( CppCliTypeModifierFollowup );
2206 g_type = g_curClassName.copy();
2210 g_theVarContext.addVariable(g_type,g_name);
2212 generateClassOrGlobalLink(*g_code,yytext);
2214 <ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* {
2215 codifyLines(yytext);
2216 g_curClassBases.clear();
2219 <PackageName>[ \t]*";" |
2220 <Bases>^{B}*/"@"{ID} | // Objective-C interface
2221 <Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* {
2222 g_theVarContext.pushScope();
2223 g_code->codify(yytext);
2225 if (YY_START==ClassVar && g_curClassName.isEmpty())
2227 g_curClassName = g_name.copy();
2229 if (g_searchingForBody)
2231 g_searchingForBody=FALSE;
2234 if (g_insideBody) g_bodyCurlyCount++;
2235 if (!g_curClassName.isEmpty()) // valid class name
2237 DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2238 g_scopeStack.push(CLASSBLOCK);
2239 pushScope(g_curClassName);
2240 DBG_CTX((stderr,"***** g_curClassName=%s\n",g_curClassName.data()));
2241 if (getResolvedClass(g_currentDefinition,g_sourceFileDef,g_curClassName)==0)
2243 DBG_CTX((stderr,"Adding new class %s\n",g_curClassName.data()));
2244 ClassDef *ncd=new ClassDef("<code>",1,1,
2245 g_curClassName,ClassDef::Class,0,0,FALSE);
2246 g_codeClassSDict->append(g_curClassName,ncd);
2247 // insert base classes.
2248 char *s=g_curClassBases.first();
2252 bcd=g_codeClassSDict->find(s);
2253 if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s);
2254 if (bcd && bcd!=ncd)
2256 ncd->insertBaseClass(bcd,s,Public,Normal);
2258 s=g_curClassBases.next();
2261 //printf("g_codeClassList.count()=%d\n",g_codeClassList.count());
2263 else // not a class name -> assume inner block
2265 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2266 g_scopeStack.push(INNERBLOCK);
2268 g_curClassName.resize(0);
2269 g_curClassBases.clear();
2272 <Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" {
2273 startFontClass("keyword");
2274 g_code->codify(yytext);
2277 <Bases>{SEP}?({ID}{SEP})*{ID} {
2278 DBG_CTX((stderr,"%s:addBase(%s)\n",g_curClassName.data(),yytext));
2279 g_curClassBases.inSort(yytext);
2280 generateClassOrGlobalLink(*g_code,yytext);
2283 g_code->codify(yytext);
2287 BEGIN ( SkipSharp );
2291 g_insideProtocolList=TRUE;
2295 g_code->codify(yytext);
2296 g_insideProtocolList=FALSE;
2299 g_code->codify(yytext);
2303 g_code->codify(yytext);
2304 if (--g_sharpCount<=0)
2308 g_code->codify(yytext);
2310 BEGIN ( SkipSharp );
2313 g_code->codify(yytext);
2317 g_code->codify(yytext);
2318 if (--g_sharpCount<=0)
2324 g_code->codify(yytext);
2328 <Body>{SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" {
2330 generateFunctionLink(*g_code,yytext);
2336 <Body>{SCOPEPREFIX}?"operator"/"(" {
2338 generateFunctionLink(*g_code,yytext);
2344 <Body>{SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\(\n]+/"(" {
2346 generateFunctionLink(*g_code,yytext);
2352 <Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9]) {
2353 startFontClass("keyword");
2354 codifyLines(yytext);
2356 g_insideTemplate=TRUE;
2359 <Body>"using"{BN}+"namespace"{BN}+ {
2360 startFontClass("keyword");
2361 codifyLines(yytext);
2365 <UsingName>{ID}("::"{ID})* { addUsingDirective(yytext);
2366 generateClassOrGlobalLink(*g_code,yytext);
2367 DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2368 g_scopeStack.push(CLASSBLOCK);
2372 <UsingName>\n { codifyLines(yytext); BEGIN(Body); }
2373 <UsingName>. { codifyLines(yytext); BEGIN(Body); }
2374 <Body,FuncCall>"$"?"this"("->"|".") { g_code->codify(yytext); // this-> for C++, this. for C#
2376 <Body>{KEYWORD}/([^a-z_A-Z0-9]) {
2377 startFontClass("keyword");
2378 codifyLines(yytext);
2379 if (QCString(yytext)=="typedef")
2386 <Body>{KEYWORD}/{B}* {
2387 startFontClass("keyword");
2388 codifyLines(yytext);
2391 <Body>{KEYWORD}/{BN}*"(" {
2392 startFontClass("keyword");
2393 codifyLines(yytext);
2395 g_name.resize(0);g_type.resize(0);
2397 <FuncCall>"in"/{BN}* {
2398 if (!g_inForEachExpression) REJECT;
2399 startFontClass("keywordflow");
2400 codifyLines(yytext);
2402 // insert the variable in the parent scope, see bug 546158
2403 g_theVarContext.popScope();
2404 g_theVarContext.addVariable(g_parmType,g_parmName);
2405 g_theVarContext.pushScope();
2406 g_name.resize(0);g_type.resize(0);
2408 <Body>{FLOWKW}/{BN}*"(" {
2409 startFontClass("keywordflow");
2410 codifyLines(yytext);
2412 g_name.resize(0);g_type.resize(0);
2413 g_inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0);
2416 <Body>{FLOWKW}/([^a-z_A-Z0-9]) {
2417 startFontClass("keywordflow");
2418 codifyLines(yytext);
2420 if (g_inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0))
2422 g_inFunctionTryBlock=FALSE;
2425 <Body>{FLOWKW}/{B}* {
2426 startFontClass("keywordflow");
2427 codifyLines(yytext);
2430 <Body>"*"{B}*")" { // end of cast?
2431 g_code->codify(yytext);
2432 g_theCallContext.popScope();
2434 g_parmType = g_name;
2437 <Body>[\\|\)\+\-\/\%\~\!] {
2438 g_code->codify(yytext);
2439 g_name.resize(0);g_type.resize(0);
2442 g_theCallContext.popScope();
2447 <Body,TemplDecl,ObjCMethod>{TYPEKW}/{B}* {
2448 startFontClass("keywordtype");
2449 g_code->codify(yytext);
2454 <Body>"generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* {
2455 startFontClass("keyword");
2456 g_code->codify(yytext);
2461 <Body>"template"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { // template<...>
2462 startFontClass("keyword");
2463 g_code->codify(yytext);
2468 <TemplDecl>"class"|"typename" {
2469 startFontClass("keyword");
2470 codifyLines(yytext);
2474 g_code->codify(yytext);
2478 g_code->codify(yytext);
2480 if (g_sharpCount<=0)
2486 startFontClass("keyword");
2487 codifyLines(yytext);
2489 BEGIN( g_lastTemplCastContext );
2491 <TemplCast>{ID}("::"{ID})* {
2492 generateClassOrGlobalLink(*g_code,yytext);
2494 <TemplCast>("const"|"volatile"){B}* {
2495 startFontClass("keyword");
2496 codifyLines(yytext);
2500 codifyLines(yytext);
2502 <Body,FuncCall>{CASTKW}"<" { // static_cast<T>(
2503 startFontClass("keyword");
2504 codifyLines(yytext);
2506 g_lastTemplCastContext = YY_START;
2509 <Body>"$this->"{SCOPENAME}/{BN}*[;,)\]] { // PHP member variable
2511 generatePHPVariableLink(*g_code,yytext);
2514 <Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"("::"{ID})*/{B}* { // A<T> *pt;
2515 int i=QCString(yytext).find('<');
2516 QCString kw = QCString(yytext).left(i).stripWhiteSpace();
2517 if (kw.right(5)=="_cast" && YY_START==Body)
2522 generateClassOrGlobalLink(*g_code,yytext);
2525 <Body>{SCOPENAME}/{BN}*[;,)\]] { // "int var;" or "var, var2" or "debug(f) macro"
2527 // changed this to generateFunctionLink, see bug 624514
2528 //generateClassOrGlobalLink(*g_code,yytext,FALSE,TRUE);
2529 generateFunctionLink(*g_code,yytext);
2532 <Body>{SCOPENAME}/{B}* { // p->func()
2534 generateClassOrGlobalLink(*g_code,yytext);
2537 <Body>"("{B}*("*"{B}*)+{SCOPENAME}*{B}*")"/{B}* { // (*p)->func() but not "if (p) ..."
2538 g_code->codify(yytext);
2539 int s=0;while (s<(int)yyleng && !isId(yytext[s])) s++;
2540 int e=(int)yyleng-1;while (e>=0 && !isId(yytext[e])) e--;
2541 QCString varname = ((QCString)yytext).mid(s,e-s+1);
2545 <Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo()
2547 generateFunctionLink(*g_code,yytext);
2553 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN} {
2554 QCString text=yytext;
2555 int i=text.find('R');
2556 g_code->codify(text.left(i+1));
2557 startFontClass("stringliteral");
2558 g_code->codify(yytext+i+1);
2559 g_lastStringContext=YY_START;
2560 g_inForEachExpression = FALSE;
2561 g_delimiter = yytext+i+2;
2562 g_delimiter=g_delimiter.left(g_delimiter.length()-1);
2565 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\" {
2566 startFontClass("stringliteral");
2567 g_code->codify(yytext);
2568 g_lastStringContext=YY_START;
2569 g_inForEachExpression = FALSE;
2570 BEGIN( SkipString );
2572 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\' {
2573 startFontClass("stringliteral");
2574 g_code->codify(yytext);
2575 g_lastStringContext=YY_START;
2576 g_inForEachExpression = FALSE;
2577 BEGIN( SkipStringS );
2579 <SkipString>[^\"\\\r\n]* {
2580 g_code->codify(yytext);
2582 <SkipStringS>[^\'\\\r\n]* {
2583 g_code->codify(yytext);
2585 <SkipString,SkipStringS>"//"|"/*" {
2586 g_code->codify(yytext);
2589 g_code->codify(yytext);
2591 BEGIN( g_lastStringContext );
2594 g_code->codify(yytext);
2596 BEGIN( g_lastStringContext );
2598 <SkipString,SkipStringS>\\. {
2599 g_code->codify(yytext);
2601 <RawString>{RAWEND} {
2602 g_code->codify(yytext);
2603 QCString delimiter = yytext+1;
2604 delimiter=delimiter.left(delimiter.length()-1);
2605 if (delimiter==g_delimiter)
2607 BEGIN( g_lastStringContext );
2610 <RawString>[^)\n]+ { g_code->codify(yytext); }
2611 <RawString>. { g_code->codify(yytext); }
2612 <RawString>\n { codifyLines(yytext); }
2613 <SkipVerbString>[^"\n]+ {
2614 g_code->codify(yytext);
2616 <SkipVerbString>\"\" { // escaped quote
2617 g_code->codify(yytext);
2619 <SkipVerbString>\" { // end of string
2620 g_code->codify(yytext);
2622 BEGIN( g_lastVerbStringContext );
2625 g_code->codify(yytext);
2627 <SkipVerbString>\n {
2628 codifyLines(yytext);
2631 g_code->codify(yytext);
2632 g_name.resize(0);g_type.resize(0);
2635 if (g_insideTemplate)
2639 g_code->codify(yytext);
2642 if (g_insideTemplate)
2644 if (--g_sharpCount<=0)
2646 g_insideTemplate=FALSE;
2649 g_code->codify(yytext);
2651 <Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'" {
2652 startFontClass("charliteral");
2653 g_code->codify(yytext);
2657 if (yytext[0]=='-') // -> could be overloaded
2659 updateCallContextForSmartPointer();
2661 g_code->codify(yytext);
2662 g_memCallContext = YY_START;
2663 BEGIN( MemberCall );
2665 <MemberCall>{SCOPETNAME}/{BN}*"(" {
2666 if (g_theCallContext.getScope())
2668 if (!generateClassMemberLink(*g_code,g_theCallContext.getScope(),yytext))
2670 g_code->codify(yytext);
2671 addToSearchIndex(yytext);
2677 g_code->codify(yytext);
2678 addToSearchIndex(yytext);
2683 if (g_memCallContext==Body)
2689 BEGIN(g_memCallContext);
2692 <MemberCall>{SCOPENAME}/{B}* {
2693 if (g_theCallContext.getScope())
2695 DBG_CTX((stderr,"g_theCallContext.getClass()=%p\n",g_theCallContext.getScope()));
2696 if (!generateClassMemberLink(*g_code,g_theCallContext.getScope(),yytext))
2698 g_code->codify(yytext);
2699 addToSearchIndex(yytext);
2705 DBG_CTX((stderr,"no class context!\n"));
2706 g_code->codify(yytext);
2707 addToSearchIndex(yytext);
2711 BEGIN(g_memCallContext);
2714 if (g_insideObjC && *yytext=='[')
2716 //printf("Found start of ObjC call!\n");
2717 // start of a method call
2718 g_contextDict.setAutoDelete(TRUE);
2719 g_nameDict.setAutoDelete(TRUE);
2720 g_objectDict.setAutoDelete(TRUE);
2721 g_wordDict.setAutoDelete(TRUE);
2722 g_contextDict.clear();
2724 g_objectDict.clear();
2727 g_currentNameId = 0;
2736 g_code->codify(yytext);
2737 g_saveName = g_name.copy();
2738 g_saveType = g_type.copy();
2739 if (*yytext!='[' && !g_type.isEmpty())
2741 //printf("g_scopeStack.bottom()=%p\n",g_scopeStack.bottom());
2742 //if (g_scopeStack.top()!=CLASSBLOCK) // commented out for bug731363
2744 //printf("AddVariable: '%s' '%s' context=%d\n",
2745 // g_type.data(),g_name.data(),g_theVarContext.count());
2746 g_theVarContext.addVariable(g_type,g_name);
2750 if (*yytext==';' || *yytext=='=')
2755 else if (*yytext=='[')
2757 g_theCallContext.pushScope();
2760 g_parmType.resize(0);
2761 g_parmName.resize(0);
2765 <ObjCMemberCall>{ID} {
2766 if (qstrcmp(yytext,"self")==0 || qstrcmp(yytext,"super")==0)
2768 // TODO: get proper base class for "super"
2769 g_theCallContext.setClass(getClass(g_curClassName));
2770 startFontClass("keyword");
2771 g_code->codify(yytext);
2776 generateClassOrGlobalLink(*g_code,yytext);
2779 BEGIN(ObjCMemberCall2);
2781 <ObjCMemberCall>"[" {
2782 g_code->codify(yytext);
2783 g_theCallContext.pushScope();
2785 <ObjCMemberCall2>{ID}":"? {
2787 if (g_theCallContext.getClass())
2789 //printf("Calling method %s\n",g_name.data());
2790 if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),g_name))
2792 g_code->codify(yytext);
2793 addToSearchIndex(g_name);
2798 g_code->codify(yytext);
2799 addToSearchIndex(g_name);
2802 BEGIN(ObjCMemberCall3);
2804 <ObjCMemberCall2,ObjCMemberCall3>"]" {
2805 g_theCallContext.popScope();
2806 g_code->codify(yytext);
2810 <ObjCCall,ObjCMName>"[" {
2812 g_currentCtx->format+=*yytext;
2816 <ObjCCall,ObjCMName>"]" {
2817 g_currentCtx->format+=*yytext;
2818 restoreObjCContext();
2820 if (g_currentCtx==0)
2823 writeObjCMethodCall(g_contextDict.find(0));
2826 //printf("close\n");
2829 g_currentCtx->format+=escapeObject(yytext);
2830 if (g_braceCount==0)
2832 g_currentCtx->objectTypeOrName=yytext;
2833 //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
2837 <ObjCMName>{ID}/{BN}*"]" {
2838 if (g_braceCount==0 &&
2839 g_currentCtx->methodName.isEmpty())
2841 g_currentCtx->methodName=yytext;
2842 g_currentCtx->format+=escapeName(yytext);
2846 g_currentCtx->format+=escapeWord(yytext);
2849 <ObjCMName>{ID}/{BN}*":" {
2850 if (g_braceCount==0)
2852 g_currentCtx->methodName+=yytext;
2853 g_currentCtx->methodName+=":";
2855 g_currentCtx->format+=escapeName(yytext);
2857 <ObjCSkipStr>[^\n\"$\\]* { g_currentCtx->format+=yytext; }
2858 <ObjCSkipStr>\\. { g_currentCtx->format+=yytext; }
2859 <ObjCSkipStr>"\"" { g_currentCtx->format+=yytext;
2860 BEGIN(g_lastStringContext);
2862 <ObjCCall,ObjCMName>{CHARLIT} { g_currentCtx->format+=yytext; }
2863 <ObjCCall,ObjCMName>"@"?"\"" { g_currentCtx->format+=yytext;
2864 g_lastStringContext=YY_START;
2867 <ObjCCall,ObjCMName,ObjCSkipStr>"$" { g_currentCtx->format+="$$"; }
2868 <ObjCCall,ObjCMName>"(" { g_currentCtx->format+=*yytext; g_braceCount++; }
2869 <ObjCCall,ObjCMName>")" { g_currentCtx->format+=*yytext; g_braceCount--; }
2870 <ObjCSkipStr>"@"/"\"" { // needed to prevent matching the global rule (for C#)
2871 g_currentCtx->format+=yytext;
2873 <ObjCCall,ObjCMName,ObjCSkipStr>{ID} { g_currentCtx->format+=escapeWord(yytext); }
2874 <ObjCCall,ObjCMName,ObjCSkipStr>. { g_currentCtx->format+=*yytext; }
2875 <ObjCCall,ObjCMName,ObjCSkipStr>\n { g_currentCtx->format+=*yytext; }
2878 g_theCallContext.popScope();
2879 g_code->codify(yytext);
2880 // TODO: nested arrays like: a[b[0]->func()]->func()
2881 g_name = g_saveName.copy();
2882 g_type = g_saveType.copy();
2885 g_code->codify(yytext);
2887 <Body>[0-9]+[xX][0-9A-Fa-f]+ {
2888 g_code->codify(yytext);
2890 <MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) {
2892 //g_parmName=yytext;
2893 startFontClass("keyword");
2894 g_code->codify(yytext);
2897 <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKW}/([^a-z_A-Z0-9]) {
2900 startFontClass("keywordtype");
2901 g_code->codify(yytext);
2904 <MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) {
2907 startFontClass("keywordflow");
2908 g_code->codify(yytext);
2911 <MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* {
2914 generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
2916 <FuncCall>";" { // probably a cast, not a function call
2917 g_code->codify(yytext);
2918 g_inForEachExpression = FALSE;
2921 <MemberCall2,FuncCall>, {
2922 g_code->codify(yytext);
2923 g_theVarContext.addVariable(g_parmType,g_parmName);
2924 g_parmType.resize(0);g_parmName.resize(0);
2926 <MemberCall2,FuncCall>"{" {
2927 if (g_bracketCount>0)
2929 g_code->codify(yytext);
2930 g_skipInlineInitContext=YY_START;
2939 <InlineInit>"{" { g_curlyCount++;
2940 g_code->codify(yytext);
2943 g_code->codify(yytext);
2944 if (--g_curlyCount<=0)
2946 BEGIN(g_skipInlineInitContext);
2950 codifyLines(yytext);
2953 g_code->codify(yytext);
2955 <MemberCall2,FuncCall>"(" {
2956 g_parmType.resize(0);g_parmName.resize(0);
2957 g_code->codify(yytext);
2959 g_theCallContext.pushScope();
2960 if (YY_START==FuncCall && !g_insideBody)
2962 g_theVarContext.pushScope();
2965 <MemberCall2,FuncCall>{OPERATOR} { // operator
2966 if (qstrcmp(yytext,"*") &&
2967 qstrcmp(yytext,"&") &&
2968 qstrcmp(yytext,"^") &&
2969 qstrcmp(yytext,"%")) // typically a pointer or reference
2971 // not a * or &, or C++/CLI's ^ or %
2972 g_parmType.resize(0);g_parmName.resize(0);
2974 g_code->codify(yytext);
2976 <MemberCall,MemberCall2,FuncCall>("*"{B}*)?")" {
2977 if (yytext[0]==')') // no a pointer cast
2979 //printf("addVariable(%s,%s)\n",g_parmType.data(),g_parmName.data());
2980 g_theVarContext.addVariable(g_parmType,g_parmName);
2984 g_parmType.resize(0);
2985 g_parmName.resize(0);
2987 g_theCallContext.popScope();
2988 g_inForEachExpression = FALSE;
2989 //g_theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b().
2990 g_code->codify(yytext);
2991 if (--g_bracketCount<=0)
2993 if (g_name.isEmpty())
3003 <CallEnd>[ \t\n]* { codifyLines(yytext); }
3005 <MemberCall2,FuncCall>")"[ \t\n]*[;:] {
3008 codifyLines(yytext);
3010 if (*yytext==';') g_searchingForBody=FALSE;
3011 if (!g_type.isEmpty())
3013 DBG_CTX((stderr,"add variable g_type=%s g_name=%s)\n",g_type.data(),g_name.data()));
3014 g_theVarContext.addVariable(g_type,g_name);
3016 g_parmType.resize(0);g_parmName.resize(0);
3017 g_theCallContext.setScope(0);
3018 if (*yytext==';' || g_insideBody)
3022 g_theVarContext.popScope();
3024 g_name.resize(0);g_type.resize(0);
3033 <CallEnd>("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") {
3034 startFontClass("keyword");
3035 codifyLines(yytext);
3038 <CallEnd,OldStyleArgs>("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" {
3041 g_theVarContext.pushScope();
3043 g_theVarContext.addVariable(g_parmType,g_parmName);
3044 //g_theCallContext.popScope();
3045 g_parmType.resize(0);g_parmName.resize(0);
3046 int index = g_name.findRev("::");
3047 DBG_CTX((stderr,"g_name=%s\n",g_name.data()));
3050 QCString scope = g_name.left(index);
3051 if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::");
3052 ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope);
3055 setClassScope(cd->name());
3056 g_scopeStack.push(SCOPEBLOCK);
3057 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3061 //setClassScope(g_realScope);
3062 g_scopeStack.push(INNERBLOCK);
3063 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3068 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3069 g_scopeStack.push(INNERBLOCK);
3071 yytext[yyleng-1]='\0';
3072 QCString cv(yytext);
3073 if (!cv.stripWhiteSpace().isEmpty())
3075 startFontClass("keyword");
3076 codifyLines(yytext);
3079 else // just whitespace
3081 codifyLines(yytext);
3083 g_code->codify("{");
3084 if (g_searchingForBody)
3086 g_searchingForBody=FALSE;
3089 if (g_insideBody) g_bodyCurlyCount++;
3091 g_type.resize(0); g_name.resize(0);
3094 <CallEnd>"try" { // function-try-block
3095 startFontClass("keyword");
3096 g_code->codify(yytext);
3098 g_inFunctionTryBlock=TRUE;
3101 if (g_insideBody || !g_parmType.isEmpty())
3105 // could be K&R style definition
3108 generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3109 BEGIN(OldStyleArgs);
3111 <OldStyleArgs>{ID} {
3114 generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3116 <OldStyleArgs>[,;] {
3117 g_code->codify(yytext);
3118 g_theVarContext.addVariable(g_parmType,g_parmName);
3119 if (*yytext==';') g_parmType.resize(0);
3120 g_parmName.resize(0);
3122 <CallEnd,OldStyleArgs>"#" {
3123 startFontClass("preprocessor");
3124 g_lastSkipCppContext = Body;
3125 g_code->codify(yytext);
3132 g_theVarContext.popScope();
3134 g_name.resize(0);g_args.resize(0);
3135 g_parmType.resize(0);g_parmName.resize(0);
3139 g_code->codify(yytext);
3140 g_type.resize(0); g_name.resize(0);
3144 g_code->codify(yytext);
3146 if (g_searchingForBody)
3148 g_searchingForBody=FALSE;
3151 if (g_insideBody) g_bodyCurlyCount++;
3152 if (g_name.find("::")!=-1)
3154 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3155 g_scopeStack.push(SCOPEBLOCK);
3156 setClassScope(g_realScope);
3160 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3161 g_scopeStack.push(INNERBLOCK);
3163 g_type.resize(0); g_name.resize(0);
3167 generateClassOrGlobalLink(*g_code,yytext);
3169 <FuncCall>{ID}/"(" {
3170 generateFunctionLink(*g_code,yytext);
3172 <FuncCall>{ID}/("."|"->") {
3174 generateClassOrGlobalLink(*g_code,yytext);
3175 BEGIN( MemberCall2 );
3177 <FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}*{B}*")"{B}*)/("."|"->") {
3178 g_code->codify(yytext);
3179 int s=0;while (!isId(yytext[s])) s++;
3180 int e=(int)yyleng-1;while (!isId(yytext[e])) e--;
3181 g_name=((QCString)yytext).mid(s,e-s+1);
3182 BEGIN( MemberCall2 );
3184 <MemberCall2>{ID}/([ \t\n]*"(") {
3185 if (!g_args.isEmpty())
3186 generateMemberLink(*g_code,g_args,yytext);
3188 generateClassOrGlobalLink(*g_code,yytext);
3192 <MemberCall2>{ID}/([ \t\n]*("."|"->")) {
3193 //g_code->codify(yytext);
3195 generateClassOrGlobalLink(*g_code,yytext);
3196 BEGIN( MemberCall2 );
3198 <MemberCall2>"->"|"." {
3199 if (yytext[0]=='-') // -> could be overloaded
3201 updateCallContextForSmartPointer();
3203 g_code->codify(yytext);
3204 g_memCallContext = YY_START;
3205 BEGIN( MemberCall );
3207 <SkipComment>"/*"("!"?)"*/" {
3208 g_code->codify(yytext);
3210 BEGIN( g_lastCContext ) ;
3212 <SkipComment>"//"|"/*" {
3213 g_code->codify(yytext);
3215 <SkipComment>[^*/\n]+ {
3216 g_code->codify(yytext);
3218 <SkipComment>[ \t]*"*/" {
3219 g_code->codify(yytext);
3221 if (g_lastCContext==SkipCPP)
3223 startFontClass("preprocessor");
3225 BEGIN( g_lastCContext ) ;
3227 <SkipCxxComment>[^\r\n]*"\\"[\r]?\n { // line continuation
3228 codifyLines(yytext);
3230 <SkipCxxComment>[^\r\n]+ {
3231 g_code->codify(yytext);
3234 <SkipCxxComment>\n {
3237 BEGIN( g_lastCContext ) ;
3240 g_code->codify(yytext);
3242 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] {
3243 g_yyLineNr+=QCString(yytext).contains('\n');
3245 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? {
3246 g_yyLineNr+=QCString(yytext).contains('\n');
3248 if (g_lastSpecialCContext==SkipCxxComment)
3249 { // force end of C++ comment here
3251 BEGIN( g_lastCContext ) ;
3255 BEGIN(g_lastSpecialCContext);
3258 <RemoveSpecialCComment>"*/" {
3259 BEGIN(g_lastSpecialCContext);
3261 <RemoveSpecialCComment>[^*\n]+
3262 <RemoveSpecialCComment>"//"|"/*"
3263 <RemoveSpecialCComment>\n { g_yyLineNr++; }
3264 <RemoveSpecialCComment>.
3265 <MemberCall>[^a-z_A-Z0-9(\n] {
3266 g_code->codify(yytext);
3269 BEGIN(g_memCallContext);
3271 <*>\n({B}*"//"[!/][^\n]*\n)+ { // remove special one-line comment
3272 if (YY_START==SkipCPP) REJECT;
3273 if (Config_getBool("STRIP_CODE_COMMENTS"))
3275 g_yyLineNr+=((QCString)yytext).contains('\n');
3280 startFontClass("comment");
3281 codifyLines(yytext);
3284 if (YY_START==SkipCxxComment)
3287 BEGIN( g_lastCContext ) ;
3292 codifyLines(yytext);
3293 BEGIN( g_lastSkipCppContext ) ;
3295 <*>\n{B}*"//@"[{}].*\n { // remove one-line group marker
3296 if (Config_getBool("STRIP_CODE_COMMENTS"))
3303 startFontClass("comment");
3304 codifyLines(yytext);
3307 if (YY_START==SkipCxxComment)
3310 BEGIN( g_lastCContext ) ;
3313 <*>\n{B}*"/*@"[{}] { // remove one-line group marker
3314 if (Config_getBool("STRIP_CODE_COMMENTS"))
3316 g_lastSpecialCContext = YY_START;
3318 BEGIN(RemoveSpecialCComment);
3322 // check is to prevent getting stuck in skipping C++ comments
3323 if (YY_START != SkipCxxComment)
3325 g_lastCContext = YY_START ;
3327 startFontClass("comment");
3328 codifyLines(yytext);
3332 <*>^{B}*"//@"[{}].*\n { // remove one-line group marker
3333 if (Config_getBool("STRIP_CODE_COMMENTS"))
3340 startFontClass("comment");
3341 codifyLines(yytext);
3345 <*>^{B}*"/*@"[{}] { // remove multi-line group marker
3346 if (Config_getBool("STRIP_CODE_COMMENTS"))
3348 g_lastSpecialCContext = YY_START;
3349 BEGIN(RemoveSpecialCComment);
3353 // check is to prevent getting stuck in skipping C++ comments
3354 if (YY_START != SkipCxxComment)
3356 g_lastCContext = YY_START ;
3358 startFontClass("comment");
3359 g_code->codify(yytext);
3363 <*>^{B}*"//"[!/][^\n]*\n { // remove special one-line comment
3364 if (Config_getBool("STRIP_CODE_COMMENTS"))
3371 startFontClass("comment");
3372 codifyLines(yytext);
3376 <*>"//"[!/][^\n]*\n { // strip special one-line comment
3377 if (YY_START==SkipComment || YY_START==SkipString) REJECT;
3378 if (Config_getBool("STRIP_CODE_COMMENTS"))
3380 char c[2]; c[0]='\n'; c[1]=0;
3385 startFontClass("comment");
3386 codifyLines(yytext);
3390 <*>"/*[tag:"[^\]\n]*"]*/"{B}* { // special pattern /*[tag:filename]*/ to force linking to a tag file
3391 g_forceTagReference=yytext;
3392 int s=g_forceTagReference.find(':');
3393 int e=g_forceTagReference.findRev(']');
3394 g_forceTagReference = g_forceTagReference.mid(s+1,e-s-1);
3396 <*>\n{B}*"/*"[!*]/[^/*] {
3397 if (Config_getBool("STRIP_CODE_COMMENTS"))
3399 g_lastSpecialCContext = YY_START;
3401 BEGIN(RemoveSpecialCComment);
3405 // check is to prevent getting stuck in skipping C++ comments
3406 if (YY_START != SkipCxxComment)
3408 g_lastCContext = YY_START ;
3410 startFontClass("comment");
3411 codifyLines(yytext);
3415 <*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line
3416 if (Config_getBool("STRIP_CODE_COMMENTS"))
3418 g_lastSpecialCContext = YY_START;
3419 BEGIN(RemoveSpecialCComment);
3423 // check is to prevent getting stuck in skipping C++ comments
3424 if (YY_START != SkipCxxComment)
3426 g_lastCContext = YY_START ;
3428 startFontClass("comment");
3429 g_code->codify(yytext);
3433 <*>"/*"[!*]/[^/*] { // special C comment block half way a line
3434 if (YY_START==SkipString) REJECT;
3435 if (Config_getBool("STRIP_CODE_COMMENTS"))
3437 g_lastSpecialCContext = YY_START;
3438 BEGIN(RemoveSpecialCComment);
3442 // check is to prevent getting stuck in skipping C++ comments
3443 if (YY_START != SkipCxxComment)
3445 g_lastCContext = YY_START ;
3447 startFontClass("comment");
3448 g_code->codify(yytext);
3453 if (YY_START==SkipString) REJECT;
3454 if (!Config_getBool("STRIP_CODE_COMMENTS"))
3456 startFontClass("comment");
3457 g_code->codify(yytext);
3462 startFontClass("comment");
3463 g_code->codify(yytext);
3464 // check is to prevent getting stuck in skipping C++ comments
3465 if (YY_START != SkipCxxComment)
3467 g_lastCContext = YY_START ;
3469 BEGIN( SkipComment ) ;
3471 <*>@\" { // C# verbatim string
3472 startFontClass("stringliteral");
3473 g_code->codify(yytext);
3474 g_lastVerbStringContext=YY_START;
3475 BEGIN(SkipVerbString);
3478 startFontClass("comment");
3479 g_code->codify(yytext);
3480 g_lastCContext = YY_START ;
3481 BEGIN( SkipCxxComment ) ;
3484 g_code->codify(yytext);
3485 g_theCallContext.pushScope();
3488 g_code->codify(yytext);
3489 g_theCallContext.popScope();
3493 codifyLines(yytext);
3497 g_code->codify(yytext);
3500 <*>([ \t\n]*"\n"){2,} { // combine multiple blank lines
3501 //QCString sepLine=yytext;
3502 //g_code->codify("\n\n");
3503 //g_yyLineNr+=sepLine.contains('\n');
3504 //char sepLine[3]="\n\n";
3505 codifyLines(yytext);
3511 /*@ ----------------------------------------------------------------------------
3514 static void saveObjCContext()
3518 g_currentCtx->format+=QCString().sprintf("$c%d",g_currentCtxId);
3519 if (g_braceCount==0 && YY_START==ObjCCall)
3521 g_currentCtx->objectTypeOrName=g_currentCtx->format.mid(1);
3522 //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
3524 g_contextStack.push(g_currentCtx);
3528 //printf("Trying to save NULL context!\n");
3530 ObjCCallCtx *newCtx = new ObjCCallCtx;
3531 newCtx->id = g_currentCtxId;
3532 newCtx->lexState = YY_START;
3533 newCtx->braceCount = g_braceCount;
3534 newCtx->objectType = 0;
3535 newCtx->objectVar = 0;
3537 //printf("save state=%d\n",YY_START);
3538 g_contextDict.insert(g_currentCtxId,newCtx);
3539 g_currentCtx = newCtx;
3544 static void restoreObjCContext()
3546 //printf("restore state=%d->%d\n",YY_START,g_currentCtx->lexState);
3547 BEGIN(g_currentCtx->lexState);
3548 g_braceCount = g_currentCtx->braceCount;
3549 if (!g_contextStack.isEmpty())
3551 g_currentCtx = g_contextStack.pop();
3556 //printf("Trying to pop context while g_contextStack is empty!\n");
3560 void resetCCodeParserState()
3562 //printf("***initParseCodeContext()\n");
3563 g_forceTagReference.resize(0);
3564 g_theVarContext.clear();
3565 g_classScopeLengthStack.setAutoDelete(TRUE);
3566 g_classScopeLengthStack.clear();
3567 delete g_codeClassSDict;
3568 g_codeClassSDict = new ClassSDict(17);
3569 g_codeClassSDict->setAutoDelete(TRUE);
3570 g_codeClassSDict->clear();
3571 g_curClassBases.clear();
3575 void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s,
3576 SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd,
3577 int startLine,int endLine,bool inlineFragment,
3578 MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
3581 //printf("***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n",
3582 // exBlock,exName,fd,className,searchCtx?searchCtx->name().data():"<none>");
3584 if (s.isEmpty()) return;
3586 printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
3588 TooltipManager::instance()->clearTooltips();
3589 if (g_codeClassSDict==0)
3591 resetCCodeParserState();
3595 g_inputPosition = 0;
3596 g_currentFontClass = 0;
3597 g_needsTermination = FALSE;
3598 g_searchCtx = searchCtx;
3599 g_collectXRefs = collectXRefs;
3600 g_inFunctionTryBlock = FALSE;
3602 g_inputLines = endLine+1;
3604 g_inputLines = countLines();
3607 g_yyLineNr = startLine;
3612 g_bodyCurlyCount = 0;
3615 g_insideTemplate = FALSE;
3616 g_theCallContext.clear();
3617 g_scopeStack.clear();
3618 g_classScope = className;
3619 //printf("parseCCode %s\n",className);
3620 g_exampleBlock = exBlock;
3621 g_exampleName = exName;
3622 g_sourceFileDef = fd;
3623 g_lineNumbers = fd!=0 && showLineNumbers;
3624 bool cleanupSourceDef = FALSE;
3627 // create a dummy filedef for the example
3628 g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
3629 cleanupSourceDef = TRUE;
3631 g_insideObjC = lang==SrcLangExt_ObjC;
3632 g_insideJava = lang==SrcLangExt_Java;
3633 g_insideCS = lang==SrcLangExt_CSharp;
3634 g_insidePHP = lang==SrcLangExt_PHP;
3635 if (g_sourceFileDef)
3637 setCurrentDoc("l00001");
3639 g_currentDefinition = 0;
3640 g_currentMemberDef = 0;
3641 g_searchingForBody = exBlock;
3642 g_insideBody = FALSE;
3644 if (!g_exampleName.isEmpty())
3646 g_exampleFile = convertNameToFile(g_exampleName+"-example",FALSE,TRUE);
3647 //printf("g_exampleFile=%s\n",g_exampleFile.data());
3649 g_includeCodeFragment = inlineFragment;
3650 //printf("** exBlock=%d exName=%s include=%d\n",exBlock,exName,inlineFragment);
3655 g_parmName.resize(0);
3656 g_parmType.resize(0);
3657 if (memberDef) setParameterList(memberDef);
3658 codeYYrestart( codeYYin );
3662 if (g_needsTermination)
3665 DBG_CTX((stderr,"endCodeLine(%d)\n",g_yyLineNr));
3666 g_code->endCodeLine();
3670 TooltipManager::instance()->writeTooltips(*g_code);
3672 if (cleanupSourceDef)
3674 // delete the temporary file definition used for this example
3675 delete g_sourceFileDef;
3679 printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
3683 void codeFreeScanner()
3685 #if defined(YY_FLEX_SUBMINOR_VERSION)
3688 codeYYlex_destroy();
3695 #if !defined(YY_FLEX_SUBMINOR_VERSION)
3696 extern "C" { // some bogus code to keep the compiler happy
3697 void codeYYdummy() { yy_flex_realloc(0,0); }
3699 #elif YY_FLEX_SUBMINOR_VERSION<33
3700 #error "You seem to be using a version of flex newer than 2.5.4 but older than 2.5.33. These versions do NOT work with doxygen! Please use version <=2.5.4 or >=2.5.33 or expect things to be parsed wrongly!"