1 /******************************************************************************
5 * Copyright (C) 1997-2012 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.
33 #include "outputlist.h"
35 #include "membername.h"
36 #include "searchindex.h"
37 #include "arguments.h"
39 #define YY_NEVER_INTERACTIVE 1
41 // Toggle for some debugging info
42 //#define DBG_CTX(x) fprintf x
43 #define DBG_CTX(x) do { } while(0)
45 #define CLASSBLOCK (int *)4
46 #define SCOPEBLOCK (int *)8
47 #define INNERBLOCK (int *)12
49 /* -----------------------------------------------------------------
53 static CodeOutputInterface * g_code;
55 static ClassSDict *g_codeClassSDict = 0;
56 static QCString g_curClassName;
57 static QStrList g_curClassBases;
59 static QCString g_parmType;
60 static QCString g_parmName;
62 static const char * g_inputString; //!< the code fragment as text
63 static int g_inputPosition; //!< read offset during parsing
64 static int g_inputLines; //!< number of line in the code fragment
65 static int g_yyLineNr; //!< current line number
66 static bool g_needsTermination;
68 static bool g_exampleBlock;
69 static QCString g_exampleName;
70 static QCString g_exampleFile;
72 static bool g_insideTemplate = FALSE;
73 static QCString g_type;
74 static QCString g_name;
75 static QCString g_args;
76 static QCString g_classScope;
77 static QCString g_realScope;
78 static QStack<int> g_scopeStack; //!< 1 if bracket starts a scope,
79 // 2 for internal blocks
80 static int g_anchorCount;
81 static FileDef * g_sourceFileDef;
82 static bool g_lineNumbers;
83 static Definition * g_currentDefinition;
84 static MemberDef * g_currentMemberDef;
85 static bool g_includeCodeFragment;
86 static const char * g_currentFontClass;
87 static bool g_searchingForBody;
88 static bool g_insideBody;
89 static int g_bodyCurlyCount;
90 static QCString g_saveName;
91 static QCString g_saveType;
92 static QCString g_delimiter;
94 static int g_bracketCount = 0;
95 static int g_curlyCount = 0;
96 static int g_sharpCount = 0;
97 static bool g_inFunctionTryBlock = FALSE;
98 static bool g_inForEachExpression = FALSE;
100 static int g_lastTemplCastContext;
101 static int g_lastSpecialCContext;
102 static int g_lastStringContext;
103 static int g_lastSkipCppContext;
104 static int g_lastVerbStringContext;
105 static int g_memCallContext;
106 static int g_lastCContext;
108 static bool g_insideObjC;
109 static bool g_insideProtocolList;
111 static bool g_lexInit = FALSE;
113 static QStack<int> g_classScopeLengthStack;
115 static Definition *g_searchCtx;
117 // context for an Objective-C method call
122 QCString objectTypeOrName;
123 ClassDef *objectType;
124 MemberDef *objectVar;
131 // globals for objective-C method calls
132 static ObjCCallCtx *g_currentCtx=0;
133 static int g_currentCtxId=0;
134 static int g_currentNameId=0;
135 static int g_currentObjId=0;
136 static int g_currentWordId=0;
137 static QStack<ObjCCallCtx> g_contextStack;
138 static QIntDict<ObjCCallCtx> g_contextDict;
139 static QIntDict<QCString> g_nameDict;
140 static QIntDict<QCString> g_objectDict;
141 static QIntDict<QCString> g_wordDict;
142 static int g_braceCount=0;
144 static void saveObjCContext();
145 static void restoreObjCContext();
147 static QCString g_forceTagReference;
150 //-------------------------------------------------------------------
152 /*! Represents a stack of variable to class mappings as found in the
153 * code. Each scope is enclosed in pushScope() and popScope() calls.
154 * Variables are added by calling addVariables() and one can search
155 * for variable using findVariable().
157 class VariableContext
160 static const ClassDef *dummyContext;
162 class Scope : public SDict<ClassDef>
165 Scope() : SDict<ClassDef>(17) {}
170 m_scopes.setAutoDelete(TRUE);
172 virtual ~VariableContext()
178 m_scopes.append(new Scope);
179 DBG_CTX((stderr,"** Push var context %d\n",m_scopes.count()));
184 if (m_scopes.count()>0)
186 DBG_CTX((stderr,"** Pop var context %d\n",m_scopes.count()));
187 m_scopes.remove(m_scopes.count()-1);
191 DBG_CTX((stderr,"** ILLEGAL: Pop var context\n"));
198 m_globalScope.clear();
201 void clearExceptGlobal()
203 DBG_CTX((stderr,"** Clear var context\n"));
207 void addVariable(const QCString &type,const QCString &name);
208 ClassDef *findVariable(const QCString &name);
210 int count() const { return m_scopes.count(); }
214 QList<Scope> m_scopes;
217 void VariableContext::addVariable(const QCString &type,const QCString &name)
219 //printf("VariableContext::addVariable(%s,%s)\n",type.data(),name.data());
220 QCString ltype = type.simplifyWhiteSpace();
221 QCString lname = name.simplifyWhiteSpace();
222 if (ltype.left(7)=="struct ")
224 ltype = ltype.right(ltype.length()-7);
226 else if (ltype.left(6)=="union ")
228 ltype = ltype.right(ltype.length()-6);
230 if (ltype.isEmpty() || lname.isEmpty()) return;
231 DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' g_currentDefinition=%s\n",
232 ltype.data(),lname.data(),g_currentDefinition?g_currentDefinition->name().data():"<none>"));
233 Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast();
237 (varType=g_codeClassSDict->find(ltype)) || // look for class definitions inside the code block
238 (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,ltype)) // look for global class definitions
241 DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data()));
242 scope->append(lname,varType); // add it to a list
244 else if ((i=ltype.find('<'))!=-1)
246 // probably a template class
247 QCString typeName(ltype.left(i));
248 ClassDef* newDef = 0;
249 QCString templateArgs(ltype.right(ltype.length() - i));
251 ( // look for class definitions inside the code block
252 (varType=g_codeClassSDict->find(typeName)) ||
253 // otherwise look for global class definitions
254 (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,typeName,0,0,TRUE,TRUE))
255 ) && // and it must be a template
256 varType->templateArguments())
258 newDef = varType->getVariableInstance( templateArgs );
262 DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data()));
263 scope->append(lname, newDef);
267 // Doesn't seem to be a template. Try just the base name.
268 addVariable(typeName,name);
273 if (m_scopes.count()>0) // for local variables add a dummy entry so the name
274 // is hidden to avoid false links to global variables with the same name
275 // TODO: make this work for namespaces as well!
277 DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data()));
278 scope->append(lname,dummyContext);
282 DBG_CTX((stderr,"** addVariable: not adding variable!\n"));
287 ClassDef *VariableContext::findVariable(const QCString &name)
289 if (name.isEmpty()) return 0;
290 ClassDef *result = 0;
291 //QListIterator<Scope> sli(m_scopes);
294 // search from inner to outer scope
295 scope = m_scopes.last();
296 //for (sli.toLast();(scope=sli.current());--sli)
299 result = scope->find(key);
302 DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result));
305 scope = m_scopes.prev();
307 // nothing found -> also try the global scope
308 result=m_globalScope.find(name);
309 DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result));
313 static VariableContext g_theVarContext;
314 const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8;
316 //-------------------------------------------------------------------
323 Ctx() : name(g_name), type(g_type), cd(0) {}
331 m_classList.append(new Ctx);
332 m_classList.setAutoDelete(TRUE);
334 virtual ~CallContext() {}
335 void setClass(ClassDef *cd)
337 Ctx *ctx = m_classList.getLast();
340 DBG_CTX((stderr,"** Set call context %s (%p)\n",cd==0 ? "<null>" : cd->name().data(),cd));
346 m_classList.append(new Ctx);
347 DBG_CTX((stderr,"** Push call context %d\n",m_classList.count()));
351 if (m_classList.count()>1)
353 DBG_CTX((stderr,"** Pop call context %d\n",m_classList.count()));
354 Ctx *ctx = m_classList.getLast();
360 m_classList.removeLast();
364 DBG_CTX((stderr,"** ILLEGAL: Pop call context\n"));
369 DBG_CTX((stderr,"** Clear call context\n"));
371 m_classList.append(new Ctx);
373 ClassDef *getClass() const
375 Ctx *ctx = m_classList.getLast();
376 if (ctx) return ctx->cd; else return 0;
380 QList<Ctx> m_classList;
383 static CallContext g_theCallContext;
385 //-------------------------------------------------------------------
387 /*! add class/namespace name s to the scope */
388 static void pushScope(const char *s)
390 g_classScopeLengthStack.push(new int(g_classScope.length()));
391 if (g_classScope.isEmpty())
397 g_classScope += "::";
400 //printf("pushScope(%s) result: `%s'\n",s,g_classScope.data());
403 /*! remove the top class/namespace name from the scope */
404 static void popScope()
406 if (!g_classScopeLengthStack.isEmpty())
408 int *pLength = g_classScopeLengthStack.pop();
409 g_classScope.truncate(*pLength);
414 //err("Error: Too many end of scopes found!\n");
416 //printf("popScope() result: `%s'\n",g_classScope.data());
419 static void setCurrentDoc(const QCString &anchor)
421 if (Doxygen::searchIndex)
425 Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
429 Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
434 static void addToSearchIndex(const char *text)
436 if (Doxygen::searchIndex)
438 Doxygen::searchIndex->addWord(text,FALSE);
442 static void setClassScope(const QCString &name)
444 //printf("setClassScope(%s)\n",name.data());
446 n=n.simplifyWhiteSpace();
447 int ts=n.find('<'); // start of template
448 int te=n.findRev('>'); // end of template
449 //printf("ts=%d te=%d\n",ts,te);
450 if (ts!=-1 && te!=-1 && te>ts)
452 // remove template from scope
453 n=n.left(ts)+n.right(n.length()-te-1);
455 while (!g_classScopeLengthStack.isEmpty())
459 g_classScope.resize(0);
461 while ((i=n.find("::"))!=-1)
463 pushScope(n.left(i));
467 //printf("--->New class scope `%s'\n",g_classScope.data());
470 /*! start a new line of code, inserting a line number if g_sourceFileDef
471 * is TRUE. If a definition starts at the current line, then the line
472 * number is linked to the documentation of that definition.
474 static void startCodeLine()
476 //if (g_currentFontClass) { g_code->endFontClass(); }
477 if (g_sourceFileDef && g_lineNumbers)
479 //QCString lineNumber,lineAnchor;
480 //lineNumber.sprintf("%05d",g_yyLineNr);
481 //lineAnchor.sprintf("l%05d",g_yyLineNr);
483 Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
484 //printf("%s:startCodeLine(%d)=%p\n",g_sourceFileDef->name().data(),g_yyLineNr,d);
485 if (!g_includeCodeFragment && d)
487 g_currentDefinition = d;
488 g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
489 //printf("->startCodeLine(%s)=%p\n",d->name().data(),g_currentMemberDef);
490 g_insideBody = FALSE;
491 g_searchingForBody = TRUE;
492 g_realScope = d->name();
497 g_parmType.resize(0);
498 g_parmName.resize(0);
499 //printf("Real scope: `%s'\n",g_realScope.data());
500 g_bodyCurlyCount = 0;
502 lineAnchor.sprintf("l%05d",g_yyLineNr);
503 if (g_currentMemberDef)
505 g_code->writeLineNumber(g_currentMemberDef->getReference(),
506 g_currentMemberDef->getOutputFileBase(),
507 g_currentMemberDef->anchor(),g_yyLineNr);
508 setCurrentDoc(lineAnchor);
510 else if (d->isLinkableInProject())
512 g_code->writeLineNumber(d->getReference(),
513 d->getOutputFileBase(),
515 setCurrentDoc(lineAnchor);
520 g_code->writeLineNumber(0,0,0,g_yyLineNr);
523 g_code->startCodeLine(g_sourceFileDef && g_lineNumbers);
524 if (g_currentFontClass)
526 g_code->startFontClass(g_currentFontClass);
531 static void endFontClass();
532 static void startFontClass(const char *s);
534 static void endCodeLine()
537 g_code->endCodeLine();
540 static void nextCodeLine()
542 const char * fc = g_currentFontClass;
544 if (g_yyLineNr<g_inputLines)
546 g_currentFontClass = fc;
551 /*! write a code fragment `text' that may span multiple lines, inserting
552 * line numbers for each line.
554 static void codifyLines(const char *text)
556 //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
557 const char *p=text,*sp=p;
563 while ((c=*p++) && c!='\n') { }
569 char *tmp = (char*)malloc(l+1);
584 /*! writes a link to a fragment \a text that may span multiple lines, inserting
585 * line numbers for each line. If \a text contains newlines, the link will be
586 * split into multiple links with the same destination, one for each line.
588 static void writeMultiLineCodeLink(CodeOutputInterface &ol,
589 const char *ref,const char *file,
590 const char *anchor,const char *text,
594 char *p=(char *)text;
599 while ((c=*p++) && c!='\n') { }
604 //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
605 ol.writeCodeLink(ref,file,anchor,sp,tooltip);
610 //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
611 ol.writeCodeLink(ref,file,anchor,sp,tooltip);
617 static void addType()
619 if (g_name=="const") { g_name.resize(0); return; }
620 if (!g_type.isEmpty()) g_type += ' ' ;
623 if (!g_type.isEmpty()) g_type += ' ' ;
628 static void addParmType()
630 if (g_parmName=="const") { g_parmName.resize(0); return; }
631 if (!g_parmType.isEmpty()) g_parmType += ' ' ;
632 g_parmType += g_parmName ;
633 g_parmName.resize(0) ;
636 static void addUsingDirective(const char *name)
638 if (g_sourceFileDef && name)
640 NamespaceDef *nd = Doxygen::namespaceSDict->find(name);
643 g_sourceFileDef->addUsingDirective(nd);
648 static void setParameterList(MemberDef *md)
650 g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : "";
651 LockingPtr<ArgumentList> al = md->argumentList();
653 Argument *a = al->first();
656 g_parmName = a->name.copy();
657 g_parmType = a->type.copy();
658 int i = g_parmType.find('*');
659 if (i!=-1) g_parmType = g_parmType.left(i);
660 i = g_parmType.find('&');
661 if (i!=-1) g_parmType = g_parmType.left(i);
662 g_parmType.stripPrefix("const ");
663 g_parmType=g_parmType.stripWhiteSpace();
664 g_theVarContext.addVariable(g_parmType,g_parmName);
669 static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
675 while (extractClassNameFromType(type,pos,className,templSpec)!=-1)
677 QCString clName=className+templSpec;
679 if (!g_classScope.isEmpty())
681 cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName);
685 cd=getResolvedClass(d,g_sourceFileDef,clName);
687 //printf("stripClass trying `%s' = %p\n",clName.data(),cd);
697 static MemberDef *setCallContextForVar(const QCString &name)
699 if (name.isEmpty()) return 0;
700 //fprintf(stderr,"setCallContextForVar(%s) g_classScope=%s\n",name.data(),g_classScope.data());
702 int scopeEnd = name.findRev("::");
703 if (scopeEnd!=-1) // name with explicit scope
705 QCString scope = name.left(scopeEnd);
706 QCString locName = name.right(name.length()-scopeEnd-2);
707 //printf("explicit scope: name=%s scope=%s\n",locName.data(),scope.data());
708 ClassDef *mcd = getClass(scope);
709 if (mcd && !locName.isEmpty())
711 MemberDef *md=mcd->getMemberByName(locName);
714 //printf("name=%s scope=%s\n",locName.data(),scope.data());
715 g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
719 else // check namespace as well
721 NamespaceDef *mnd = getResolvedNamespace(scope);
722 if (mnd && !locName.isEmpty())
724 MemberDef *md=mnd->getMemberByName(locName);
727 //printf("name=%s scope=%s\n",locName.data(),scope.data());
728 g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
736 ClassDef *mcd = g_theVarContext.findVariable(name);
737 if (mcd) // local variable
739 //fprintf(stderr,"local variable?\n");
740 if (mcd!=VariableContext::dummyContext)
742 //fprintf(stderr,"local var `%s' mcd=%s\n",name.data(),mcd->name().data());
743 g_theCallContext.setClass(mcd);
748 //fprintf(stderr,"class member? scope=%s\n",g_classScope.data());
749 // look for a class member
750 mcd = getClass(g_classScope);
753 //fprintf(stderr,"Inside class %s\n",mcd->name().data());
754 MemberDef *md=mcd->getMemberByName(name);
757 //fprintf(stderr,"Found member %s\n",md->name().data());
758 if (g_scopeStack.top()!=CLASSBLOCK)
760 //fprintf(stderr,"class member `%s' mcd=%s\n",name.data(),mcd->name().data());
761 g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
768 // look for a global member
769 if ((mn=Doxygen::functionNameSDict->find(name)))
771 //printf("global var `%s'\n",name.data());
772 if (mn->count()==1) // global defined only once
774 MemberDef *md=mn->getFirst();
775 if (!md->isStatic() || md->getBodyDef()==g_sourceFileDef)
777 g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
782 else if (mn->count()>1) // global defined more than once
784 MemberDef *md=mn->first();
787 //printf("mn=%p md=%p md->getBodyDef()=%p g_sourceFileDef=%p\n",
789 // md->getBodyDef(),g_sourceFileDef);
791 // in case there are multiple members we could link to, we
792 // only link to members if defined in the same file or
793 // defined as external.
794 if ((!md->isStatic() || md->getBodyDef()==g_sourceFileDef) &&
795 (g_forceTagReference.isEmpty() || g_forceTagReference==md->getReference())
798 g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
799 //printf("returning member %s in source file %s\n",md->name().data(),g_sourceFileDef->name().data());
810 static void updateCallContextForSmartPointer()
812 ClassDef *cd = g_theCallContext.getClass();
813 //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? cd->name().data() : "<none>");
815 if (cd && (md=cd->isSmartPointer()))
817 ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope());
820 g_theCallContext.setClass(ncd);
821 //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data());
826 static void addDocCrossReference(MemberDef *src,MemberDef *dst)
828 static bool referencedByRelation = Config_getBool("REFERENCED_BY_RELATION");
829 static bool referencesRelation = Config_getBool("REFERENCES_RELATION");
830 static bool callerGraph = Config_getBool("CALLER_GRAPH");
831 static bool callGraph = Config_getBool("CALL_GRAPH");
833 //printf("--> addDocCrossReference src=%s,dst=%s\n",src->name().data(),dst->name().data());
834 if (dst->isTypedef() || dst->isEnumerate()) return; // don't add types
835 if ((referencedByRelation || callerGraph || dst->hasCallerGraph()) &&
836 (src->isFunction() || src->isSlot())
839 dst->addSourceReferencedBy(src);
840 MemberDef *mdDef = dst->memberDefinition();
843 mdDef->addSourceReferencedBy(src);
845 MemberDef *mdDecl = dst->memberDeclaration();
848 mdDecl->addSourceReferencedBy(src);
851 if ((referencesRelation || callGraph || src->hasCallGraph()) &&
852 (src->isFunction() || src->isSlot())
855 src->addSourceReferences(dst);
856 MemberDef *mdDef = src->memberDefinition();
859 mdDef->addSourceReferences(dst);
861 MemberDef *mdDecl = src->memberDeclaration();
864 mdDecl->addSourceReferences(dst);
870 static bool getLinkInScope(const QCString &c, // scope
871 const QCString &m, // member
872 const char *memberText, // exact text
873 CodeOutputInterface &ol,
883 //fprintf(stderr,"getLinkInScope: trying `%s'::`%s' varOnly=%d\n",c.data(),m.data(),varOnly);
884 if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef,FALSE,g_forceTagReference) &&
885 md->isLinkable() && (!varOnly || md->isVariable()))
887 //printf("found it %s!\n",md->qualifiedName().data());
891 anchor.sprintf("a%d",g_anchorCount);
892 //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
893 // g_exampleFile.data());
894 if (md->addExample(anchor,g_exampleName,g_exampleFile))
896 ol.writeCodeAnchor(anchor);
901 Definition *d = md->getOuterScope()==Doxygen::globalScope ?
902 md->getBodyDef() : md->getOuterScope();
903 if (md->getGroupDef()) d = md->getGroupDef();
904 if (d && d->isLinkable())
906 g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
907 //printf("g_currentDefinition=%p g_currentMemberDef=%p g_insideBody=%d\n",
908 // g_currentDefinition,g_currentMemberDef,g_insideBody);
910 if (g_currentDefinition && g_currentMemberDef &&
911 md!=g_currentMemberDef && g_insideBody)
913 addDocCrossReference(g_currentMemberDef,md);
915 //printf("d->getReference()=`%s' d->getOutputBase()=`%s' name=`%s' member name=`%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data());
917 ol.linkableSymbol(g_yyLineNr,md->name(),md,
918 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
919 writeMultiLineCodeLink(ol,md->getReference(),
920 md->getOutputFileBase(),
922 text ? text : memberText,
923 md->briefDescriptionAsTooltip());
924 addToSearchIndex(text ? text : memberText);
931 static bool getLink(const char *className,
932 const char *memberName,
933 CodeOutputInterface &ol,
937 //printf("getLink(%s,%s) g_curClassName=%s\n",className,memberName,g_curClassName.data());
938 QCString m=removeRedundantWhiteSpace(memberName);
939 QCString c=className;
940 if (!getLinkInScope(c,m,memberName,ol,text,varOnly))
942 if (!g_curClassName.isEmpty())
944 if (!c.isEmpty()) c.prepend("::");
945 c.prepend(g_curClassName);
946 return getLinkInScope(c,m,memberName,ol,text,varOnly);
953 static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName,
954 bool typeOnly=FALSE,bool varOnly=FALSE)
957 if (*clName=='~') // correct for matching negated values i.s.o. destructors.
962 QCString className=clName;
963 if (className.isEmpty()) return;
964 if (g_insideProtocolList) // for Obj-C
968 className = substitute(className,"\\","::"); // for PHP namespaces
969 ClassDef *cd=0,*lcd=0;
973 //printf("generateClassOrGlobalLink(className=%s)\n",className.data());
974 if ((lcd=g_theVarContext.findVariable(className))==0) // not a local variable
976 Definition *d = g_currentDefinition;
977 //printf("d=%s g_sourceFileDef=%s\n",d?d->name().data():"<none>",g_sourceFileDef?g_sourceFileDef->name().data():"<none>");
978 cd = getResolvedClass(d,g_sourceFileDef,className,&md);
979 //fprintf(stderr,"non-local variable name=%s context=%d cd=%s md=%s!\n",
980 // className.data(),g_theVarContext.count(),cd?cd->name().data():"<none>",
981 // md?md->name().data():"<none>");
982 if (cd==0 && md==0 && (i=className.find('<'))!=-1)
984 QCString bareName = className.left(i); //stripTemplateSpecifiersFromScope(className);
985 //fprintf(stderr,"bareName=%s\n",bareName.data());
986 if (bareName!=className)
988 cd=getResolvedClass(d,g_sourceFileDef,bareName,&md); // try unspecialized version
991 //printf("md=%s\n",md?md->name().data():"<none>");
992 //fprintf(stderr,"is found as a type %s\n",cd?cd->name().data():"<null>");
993 if (cd==0 && md==0) // also see if it is variable or enum or enum value
995 if (getLink(g_classScope,clName,ol,clName,varOnly))
1003 //printf("local variable!\n");
1004 if (lcd!=VariableContext::dummyContext)
1006 //printf("non-dummy context lcd=%s!\n",lcd->name().data());
1007 g_theCallContext.setClass(lcd);
1009 // to following is needed for links to a global variable, but is
1010 // no good for a link to a local variable that is also a global symbol.
1012 //if (getLink(g_classScope,clName,ol,clName))
1018 //fprintf(stderr,"is a local variable cd=%p!\n",cd);
1020 if (cd && cd->isLinkable()) // is it a linkable class
1022 //fprintf(stderr,"is linkable class %s\n",clName);
1026 anchor.sprintf("_a%d",g_anchorCount);
1027 //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
1028 // g_exampleFile.data());
1029 if (cd->addExample(anchor,g_exampleName,g_exampleFile))
1031 ol.writeCodeAnchor(anchor);
1035 ol.linkableSymbol(g_yyLineNr,cd->name(),cd,
1036 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1037 writeMultiLineCodeLink(ol,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),clName,cd->briefDescriptionAsTooltip());
1038 addToSearchIndex(className);
1039 g_theCallContext.setClass(cd);
1042 Definition *d = md->getOuterScope()==Doxygen::globalScope ?
1043 md->getBodyDef() : md->getOuterScope();
1044 if (md->getGroupDef()) d = md->getGroupDef();
1045 if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef)
1047 addDocCrossReference(g_currentMemberDef,md);
1051 else // not a class, maybe a global member
1053 //fprintf(stderr,"class %s not linkable! cd=%p md=%p typeOnly=%d\n",clName,cd,md,typeOnly);
1054 if (!isLocal && (md!=0 || (cd==0 && !typeOnly))) // not a class, see if it is a global enum/variable/typedef.
1056 if (md==0) // not found as a typedef
1058 md = setCallContextForVar(clName);
1059 //printf("setCallContextForVar(%s) md=%p g_currentDefinition=%p\n",clName,md,g_currentDefinition);
1060 if (md && g_currentDefinition)
1062 //fprintf(stderr,"%s accessible from %s? %d md->getOuterScope=%s\n",
1063 // md->name().data(),g_currentDefinition->name().data(),
1064 // isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md),
1065 // md->getOuterScope()->name().data());
1068 if (md && g_currentDefinition &&
1069 isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md)==-1)
1071 md=0; // variable not accessible
1074 if (md && (!varOnly || md->isVariable()))
1076 //fprintf(stderr,"is a global md=%p g_currentDefinition=%s linkable=%d\n",md,g_currentDefinition?g_currentDefinition->name().data():"<none>",md->isLinkable());
1077 if (md->isLinkable())
1080 if (!g_forceTagReference.isEmpty()) // explicit reference to symbol in tag file
1082 text=g_forceTagReference;
1083 if (text.right(4)==".tag") // strip .tag if present
1085 text=text.left(text.length()-4);
1087 text+=getLanguageSpecificSeparator(md->getLanguage());
1090 md->setLocalName(text);
1092 else // normal reference
1096 ol.linkableSymbol(g_yyLineNr,md->name(),md,
1097 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1098 writeMultiLineCodeLink(ol,md->getReference(),md->getOutputFileBase(),md->anchor(),text,md->briefDescriptionAsTooltip());
1099 addToSearchIndex(clName);
1100 if (g_currentMemberDef)
1102 addDocCrossReference(g_currentMemberDef,md);
1109 // nothing found, just write out the word
1110 //fprintf(stderr,"not found!\n");
1111 ol.linkableSymbol(g_yyLineNr,clName,0,
1112 g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
1113 codifyLines(clName);
1114 addToSearchIndex(clName);
1118 static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const char *memName)
1120 // extract class definition of the return type in order to resolve
1121 // a->b()->c() like call chains
1123 //printf("type=`%s' args=`%s' class=%s\n",
1124 // xmd->typeString(),xmd->argsString(),
1125 // xmd->getClassDef()->name().data());
1130 anchor.sprintf("a%d",g_anchorCount);
1131 //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
1132 // g_exampleFile.data());
1133 if (xmd->addExample(anchor,g_exampleName,g_exampleFile))
1135 ol.writeCodeAnchor(anchor);
1140 ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope());
1141 //fprintf(stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass);
1142 g_theCallContext.setClass(typeClass);
1144 Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
1145 xmd->getBodyDef() : xmd->getOuterScope();
1146 if (xmd->getGroupDef()) xd = xmd->getGroupDef();
1147 if (xd && xd->isLinkable())
1150 //printf("g_currentDefiniton=%p g_currentMemberDef=%p xmd=%p g_insideBody=%d\n",g_currentDefinition,g_currentMemberDef,xmd,g_insideBody);
1152 if (xmd->templateMaster()) xmd = xmd->templateMaster();
1154 if (xmd->isLinkable())
1156 // add usage reference
1157 if (g_currentDefinition && g_currentMemberDef &&
1158 /*xmd!=g_currentMemberDef &&*/ g_insideBody)
1160 addDocCrossReference(g_currentMemberDef,xmd);
1163 // write the actual link
1164 ol.linkableSymbol(g_yyLineNr,xmd->name(),xmd,
1165 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1166 writeMultiLineCodeLink(ol,xmd->getReference(),
1167 xmd->getOutputFileBase(),xmd->anchor(),memName,xmd->briefDescriptionAsTooltip());
1168 addToSearchIndex(memName);
1176 static bool generateClassMemberLink(CodeOutputInterface &ol,ClassDef *mcd,const char *memName)
1180 MemberDef *xmd = mcd->getMemberByName(memName);
1181 //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",mcd->name().data(),memName,xmd);
1184 return generateClassMemberLink(ol,xmd,memName);
1191 static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName,
1194 //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n",
1195 // varName.data(),memName,g_classScope.data());
1197 if (varName.isEmpty()) return;
1199 // look for the variable in the current context
1200 ClassDef *vcd = g_theVarContext.findVariable(varName);
1203 if (vcd!=VariableContext::dummyContext)
1205 //printf("Class found!\n");
1206 if (getLink(vcd->name(),memName,ol))
1208 //printf("Found result!\n");
1211 if (vcd->baseClasses())
1213 BaseClassListIterator bcli(*vcd->baseClasses());
1214 for ( ; bcli.current() ; ++bcli)
1216 if (getLink(bcli.current()->classDef->name(),memName,ol))
1218 //printf("Found result!\n");
1225 else // variable not in current context, maybe it is in a parent context
1227 vcd = getResolvedClass(g_currentDefinition,g_sourceFileDef,g_classScope);
1228 if (vcd && vcd->isLinkable())
1230 //printf("Found class %s for variable `%s'\n",g_classScope.data(),varName.data());
1231 MemberName *vmn=Doxygen::memberNameSDict->find(varName);
1235 QCString vn=varName;
1237 if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1) // explicit scope A::b(), probably static member
1239 ClassDef *jcd = getClass(vn.left(vi));
1240 vn=vn.right(vn.length()-vi-2);
1241 vmn=Doxygen::memberNameSDict->find(vn);
1242 //printf("Trying name `%s' scope=%s\n",vn.data(),scope.data());
1245 MemberNameIterator vmni(*vmn);
1247 for (;(vmd=vmni.current());++vmni)
1249 if (/*(vmd->isVariable() || vmd->isFunction()) && */
1250 vmd->getClassDef()==jcd)
1252 //printf("Found variable type=%s\n",vmd->typeString());
1253 ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1254 if (mcd && mcd->isLinkable())
1256 if (generateClassMemberLink(ol,mcd,memName)) return;
1265 //printf("There is a variable with name `%s'\n",varName);
1266 MemberNameIterator vmni(*vmn);
1268 for (;(vmd=vmni.current());++vmni)
1270 if (/*(vmd->isVariable() || vmd->isFunction()) && */
1271 vmd->getClassDef()==vcd)
1273 //printf("Found variable type=%s\n",vmd->typeString());
1274 ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1275 if (mcd && mcd->isLinkable())
1277 if (generateClassMemberLink(ol,mcd,memName)) return;
1284 // nothing found -> write result as is
1285 ol.linkableSymbol(g_yyLineNr,memName,0,
1286 g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
1287 codifyLines(memName);
1288 addToSearchIndex(memName);
1292 static void generatePHPVariableLink(CodeOutputInterface &ol,const char *varName)
1294 QCString name = varName+7; // strip $this->
1296 //printf("generatePHPVariableLink(%s) name=%s scope=%s\n",varName,name.data(),g_classScope.data());
1297 if (!getLink(g_classScope,name,ol,varName))
1299 codifyLines(varName);
1303 static void generateFunctionLink(CodeOutputInterface &ol,const char *funcName)
1305 //CodeClassDef *ccd=0;
1307 QCString locScope=g_classScope;
1308 QCString locFunc=removeRedundantWhiteSpace(funcName);
1310 QCString funcWithScope=locFunc;
1311 QCString funcWithFullScope=locFunc;
1312 QCString fullScope=locScope;
1313 //fprintf(stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data());
1315 int i=locFunc.findRev("::");
1316 if (g_currentMemberDef && g_currentMemberDef->getClassDef() &&
1317 funcName==g_currentMemberDef->localName() &&
1318 g_currentMemberDef->getDefLine()==g_yyLineNr &&
1319 generateClassMemberLink(ol,g_currentMemberDef,funcName)
1322 // special case where funcName is the name of a method that is also
1323 // defined on this line. In this case we can directly link to
1324 // g_currentMemberDef, which is not only faster, but
1325 // in case of overloaded methods, this will make sure that we link to
1326 // the correct method, and thereby get the correct reimplemented relations.
1327 // See also bug 549022.
1330 if (i==-1) i=locFunc.findRev("."),len=1;
1331 if (i==-1) i=locFunc.findRev("\\"),len=1; // for PHP
1334 funcScope=locFunc.left(i);
1335 locFunc=locFunc.right(locFunc.length()-i-len).stripWhiteSpace();
1336 int ts=locScope.find('<'); // start of template
1337 int te=locScope.findRev('>'); // end of template
1338 //printf("ts=%d te=%d\n",ts,te);
1339 if (ts!=-1 && te!=-1 && te>ts)
1341 // remove template from scope
1342 locScope=locScope.left(ts)+locScope.right(locScope.length()-te-1);
1344 ts=funcScope.find('<'); // start of template
1345 te=funcScope.findRev('>'); // end of template
1346 //printf("ts=%d te=%d\n",ts,te);
1347 if (ts!=-1 && te!=-1 && te>ts)
1349 // remove template from scope
1350 funcScope=funcScope.left(ts)+funcScope.right(funcScope.length()-te-1);
1352 if (!funcScope.isEmpty())
1354 funcWithScope = funcScope+"::"+locFunc;
1355 if (!locScope.isEmpty())
1357 fullScope=locScope+"::"+funcScope;
1360 if (!locScope.isEmpty())
1362 funcWithFullScope = locScope+"::"+funcWithScope;
1365 if (!fullScope.isEmpty() && (ccd=g_codeClassSDict->find(fullScope)))
1367 //printf("using classScope %s\n",g_classScope.data());
1368 if (ccd->baseClasses())
1370 BaseClassListIterator bcli(*ccd->baseClasses());
1371 for ( ; bcli.current() ; ++bcli)
1373 if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName))
1380 if (!locScope.isEmpty() && fullScope!=locScope && (ccd=g_codeClassSDict->find(locScope)))
1382 //printf("using classScope %s\n",g_classScope.data());
1383 if (ccd->baseClasses())
1385 BaseClassListIterator bcli(*ccd->baseClasses());
1386 for ( ; bcli.current() ; ++bcli)
1388 if (getLink(bcli.current()->classDef->name(),funcWithScope,ol,funcName))
1395 if (!getLink(locScope,funcWithScope,ol,funcName))
1397 generateClassOrGlobalLink(ol,funcName);
1400 g_forceTagReference.resize(0);
1404 /*! counts the number of lines in the input */
1405 static int countLines()
1407 const char *p=g_inputString;
1413 if (c=='\n') count++;
1415 if (p>g_inputString && *(p-1)!='\n')
1416 { // last line does not end with a \n, so we add an extra
1417 // line and explicitly terminate the line after parsing.
1419 g_needsTermination=TRUE;
1424 static void endFontClass()
1426 if (g_currentFontClass)
1428 g_code->endFontClass();
1429 g_currentFontClass=0;
1433 static void startFontClass(const char *s)
1436 g_code->startFontClass(s);
1437 g_currentFontClass=s;
1440 //----------------------------------------------------------------------------
1442 // recursively writes a linkified Objective-C method call
1443 static void writeObjCMethodCall(ObjCCallCtx *ctx)
1447 const char *p = ctx->format.data();
1448 if (!ctx->methodName.isEmpty())
1450 //printf("writeObjCMethodCall(%s) obj=%s method=%s\n",
1451 // ctx->format.data(),ctx->objectTypeOrName.data(),ctx->methodName.data());
1452 if (!ctx->objectTypeOrName.isEmpty() && ctx->objectTypeOrName.at(0)!='$')
1454 //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(),
1455 // ctx->methodName.data());
1456 ClassDef *cd = g_theVarContext.findVariable(ctx->objectTypeOrName);
1457 if (cd==0) // not a local variable
1459 if (ctx->objectTypeOrName=="self")
1461 if (g_currentDefinition &&
1462 g_currentDefinition->definitionType()==Definition::TypeClass)
1464 ctx->objectType = (ClassDef *)g_currentDefinition;
1469 ctx->objectType = getResolvedClass(
1470 g_currentDefinition,
1472 ctx->objectTypeOrName,
1475 //printf(" object is class? %p\n",ctx->objectType);
1476 if (ctx->objectType) // found class
1478 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1479 //printf(" yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>");
1481 else if (ctx->method==0) // search for class variable with the same name
1484 //printf("g_currentDefinition=%p\n",g_currentDefinition);
1485 if (g_currentDefinition &&
1486 g_currentDefinition->definitionType()==Definition::TypeClass)
1488 ctx->objectVar = ((ClassDef *)g_currentDefinition)->getMemberByName(ctx->objectTypeOrName);
1489 //printf(" ctx->objectVar=%p\n",ctx->objectVar);
1492 ctx->objectType = stripClassName(ctx->objectVar->typeString());
1493 //printf(" ctx->objectType=%p\n",ctx->objectType);
1494 if (ctx->objectType)
1496 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1497 //printf(" ctx->method=%p\n",ctx->method);
1503 else // local variable
1505 //printf(" object is local variable\n");
1506 if (cd!=VariableContext::dummyContext)
1508 ctx->method = cd->getMemberByName(ctx->methodName);
1509 //printf(" class=%p method=%p\n",cd,ctx->method);
1516 while ((c=*p++)) // for each character in ctx->format
1521 if (nc=='$') // escaped $
1523 g_code->codify("$");
1525 else // name fragment or reference to a nested call
1527 if (nc=='n') // name fragment
1531 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1533 int refId=refIdStr.toInt();
1534 QCString *pName = g_nameDict.find(refId);
1537 if (ctx->method && ctx->method->isLinkable())
1539 g_code->linkableSymbol(g_yyLineNr,ctx->method->name(),ctx->method,
1540 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1541 writeMultiLineCodeLink(*g_code,
1542 ctx->method->getReference(),
1543 ctx->method->getOutputFileBase(),
1544 ctx->method->anchor(),
1546 ctx->method->briefDescriptionAsTooltip());
1547 if (g_currentMemberDef)
1549 addDocCrossReference(g_currentMemberDef,ctx->method);
1554 g_code->linkableSymbol(g_yyLineNr,pName->data(),0,
1555 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1556 codifyLines(pName->data());
1561 //printf("Invalid name: id=%d\n",refId);
1564 else if (nc=='o') // reference to potential object name
1568 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1570 int refId=refIdStr.toInt();
1571 QCString *pObject = g_objectDict.find(refId);
1574 if (*pObject=="self")
1576 if (g_currentDefinition &&
1577 g_currentDefinition->definitionType()==Definition::TypeClass)
1579 ctx->objectType = (ClassDef *)g_currentDefinition;
1580 if (ctx->objectType->categoryOf())
1582 ctx->objectType = ctx->objectType->categoryOf();
1584 if (ctx->objectType)
1586 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1589 startFontClass("keyword");
1590 codifyLines(pObject->data());
1593 else if (*pObject=="super")
1595 if (g_currentDefinition &&
1596 g_currentDefinition->definitionType()==Definition::TypeClass)
1598 ClassDef *cd = (ClassDef *)g_currentDefinition;
1599 if (cd->categoryOf())
1601 cd = cd->categoryOf();
1603 BaseClassList *bcd = cd->baseClasses();
1604 if (bcd) // get direct base class (there should be only one)
1606 BaseClassListIterator bli(*bcd);
1607 BaseClassDef *bclass;
1608 for (bli.toFirst();(bclass=bli.current());++bli)
1610 if (bclass->classDef->compoundType()!=ClassDef::Protocol)
1612 ctx->objectType = bclass->classDef;
1613 if (ctx->objectType)
1615 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1621 startFontClass("keyword");
1622 codifyLines(pObject->data());
1625 else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable
1627 g_code->linkableSymbol(g_yyLineNr,ctx->objectVar->name(),ctx->objectVar,
1628 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1629 writeMultiLineCodeLink(*g_code,
1630 ctx->objectVar->getReference(),
1631 ctx->objectVar->getOutputFileBase(),
1632 ctx->objectVar->anchor(),
1634 ctx->objectVar->briefDescriptionAsTooltip());
1635 if (g_currentMemberDef)
1637 addDocCrossReference(g_currentMemberDef,ctx->objectVar);
1640 else if (ctx->objectType &&
1641 ctx->objectType!=VariableContext::dummyContext &&
1642 ctx->objectType->isLinkable()
1643 ) // object is class name
1645 ClassDef *cd = ctx->objectType;
1646 g_code->linkableSymbol(g_yyLineNr,cd->name(),cd,
1647 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1648 writeMultiLineCodeLink(*g_code,
1650 cd->getOutputFileBase(),
1653 cd->briefDescriptionAsTooltip());
1655 else // object still needs to be resolved
1657 ClassDef *cd = getResolvedClass(g_currentDefinition,
1658 g_sourceFileDef, *pObject);
1659 if (cd && cd->isLinkable())
1661 if (ctx->objectType==0) ctx->objectType=cd;
1662 g_code->linkableSymbol(g_yyLineNr,cd->name(),cd,
1663 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1664 writeMultiLineCodeLink(*g_code,
1666 cd->getOutputFileBase(),
1669 cd->briefDescriptionAsTooltip());
1673 g_code->linkableSymbol(g_yyLineNr,pObject->data(),0,
1674 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1675 codifyLines(pObject->data());
1681 //printf("Invalid object: id=%d\n",refId);
1684 else if (nc=='c') // reference to nested call
1688 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1690 int refId=refIdStr.toInt();
1691 ObjCCallCtx *ictx = g_contextDict.find(refId);
1692 if (ictx) // recurse into nested call
1694 writeObjCMethodCall(ictx);
1695 if (ictx->method) // link to nested call successfully
1697 // get the ClassDef representing the method's return type
1698 if (QCString(ictx->method->typeString())=="id")
1700 // see if the method name is unique, if so we link to it
1701 MemberName *mn=Doxygen::memberNameSDict->find(ctx->methodName);
1702 //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n",
1703 // mn==0?-1:(int)mn->count(),
1704 // ictx->method->name().data(),
1705 // ctx->methodName.data());
1706 if (mn && mn->count()==1) // member name unique
1708 ctx->method = mn->getFirst();
1713 ctx->objectType = stripClassName(ictx->method->typeString());
1714 if (ctx->objectType)
1716 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1719 //printf(" ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType);
1724 //printf("Invalid context: id=%d\n",refId);
1727 else if (nc=='w') // some word
1731 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1733 int refId=refIdStr.toInt();
1734 QCString *pWord = g_wordDict.find(refId);
1737 g_code->linkableSymbol(g_yyLineNr,pWord->data(),0,
1738 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
1739 codifyLines(pWord->data());
1742 else // illegal marker
1744 ASSERT(!"invalid escape sequence");
1748 else // normal non-marker character
1755 //printf("%s %s]\n",ctx->objectTypeOrName.data(),ctx->methodName.data());
1756 //printf("}=(type='%s',name='%s')",
1757 // ctx->objectTypeOrName.data(),
1758 // ctx->methodName.data());
1761 // Replaces an Objective-C method name fragment s by a marker of the form
1762 // $n12, the number (12) can later be used as a key for obtaining the name
1763 // fragment, from g_nameDict
1764 static QCString escapeName(const char *s)
1767 result.sprintf("$n%d",g_currentNameId);
1768 g_nameDict.insert(g_currentNameId,new QCString(s));
1773 static QCString escapeObject(const char *s)
1776 result.sprintf("$o%d",g_currentObjId);
1777 g_objectDict.insert(g_currentObjId,new QCString(s));
1782 static QCString escapeWord(const char *s)
1785 result.sprintf("$w%d",g_currentWordId);
1786 g_wordDict.insert(g_currentWordId,new QCString(s));
1791 /* -----------------------------------------------------------------
1794 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
1796 static int yyread(char *buf,int max_size)
1799 while( c < max_size && g_inputString[g_inputPosition] )
1801 *buf = g_inputString[g_inputPosition++] ;
1811 ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
1813 SCOPENAME ({SEP}{BN}*)?({ID}{BN}*{SEP}{BN}*)*("~"{BN}*)?{ID}
1814 TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">"
1815 SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?{SEP}{BN}*)*)((~{BN}*)?{ID})
1816 SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*{SEP}{BN}*)+
1817 KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property")
1818 KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"set"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|{KEYWORD_OBJC})
1819 FLOWKW ("break"|"case"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"for"|"foreach"|"for each"|"goto"|"if"|"return"|"switch"|"throw"|"throws"|"try"|"while"|"@try"|"@catch"|"@finally")
1820 TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
1821 CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast")
1822 CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'"))
1823 ARITHOP "+"|"-"|"/"|"*"|"%"|"--"|"++"
1824 ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|="
1825 LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"
1826 BITOP "&"|"|"|"^"|"<<"|">>"|"~"
1827 OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
1828 RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"("
1829 RAWEND ")"[^ \t\(\)\\]{0,16}\"
1839 %x RemoveSpecialCComment
1840 %x StripSpecialCComment
1849 %x CppCliTypeModifierFollowup
1869 <Body>^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") {
1870 startFontClass("preprocessor");
1871 g_code->codify(yytext);
1872 BEGIN( ReadInclude );
1874 <Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ {
1876 startFontClass("keyword");
1877 codifyLines(yytext);
1879 if (!g_insideTemplate)
1882 <Body>(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") {
1883 if (g_insideTemplate) REJECT;
1884 startFontClass("keyword");
1885 codifyLines(yytext);
1889 <Body>"property"|"event"/{BN}* {
1890 if (g_insideTemplate) REJECT;
1891 startFontClass("keyword");
1892 codifyLines(yytext);
1895 <Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ {
1896 startFontClass("keyword");
1897 codifyLines(yytext);
1899 if (!g_insideTemplate)
1902 <Body>("package")[ \t\n]+ {
1903 startFontClass("keyword");
1904 codifyLines(yytext);
1906 BEGIN( PackageName );
1909 if (!g_insideObjC) REJECT;
1910 codifyLines(yytext);
1913 <Body,ClassVar,Bases>"-"|"+" {
1914 if (!g_insideObjC || g_insideBody)
1916 g_code->codify(yytext);
1918 else // Start of Objective-C method
1920 //printf("Method!\n");
1921 g_code->codify(yytext);
1926 g_code->codify(yytext);
1930 g_code->codify(yytext);
1931 BEGIN(ObjCParamType);
1933 <ObjCParams,ObjCMethod>";"|"{" {
1934 g_code->codify(yytext);
1938 if (g_searchingForBody)
1940 g_searchingForBody=FALSE;
1943 if (g_insideBody) g_bodyCurlyCount++;
1944 if (!g_curClassName.isEmpty()) // valid class name
1946 pushScope(g_curClassName);
1947 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
1948 g_scopeStack.push(SCOPEBLOCK);
1955 <ObjCParams>{ID}{B}*":" {
1956 g_code->codify(yytext);
1958 <ObjCParamType>{TYPEKW} {
1959 startFontClass("keywordtype");
1960 g_code->codify(yytext);
1964 <ObjCParamType>{ID} {
1965 generateClassOrGlobalLink(*g_code,yytext);
1968 <ObjCParamType>")" {
1969 g_code->codify(yytext);
1973 g_code->linkableSymbol(g_yyLineNr,yytext,0,
1974 g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
1975 g_code->codify(yytext);
1977 g_theVarContext.addVariable(g_parmType,g_parmName);
1978 g_parmType.resize(0);g_parmName.resize(0);
1980 <ObjCMethod,ObjCParams,ObjCParamType>{ID} {
1981 generateClassOrGlobalLink(*g_code,yytext);
1983 <ObjCMethod,ObjCParams,ObjCParamType>. {
1984 g_code->codify(yytext);
1986 <ObjCMethod,ObjCParams,ObjCParamType>\n {
1987 codifyLines(yytext);
1989 <ReadInclude>[^\n\"\>]+/(">"|"\"") {
1993 //QCString absPath = yytext;
1994 //if (g_sourceFileDef && QDir::isRelativePath(absPath))
1996 // absPath = QDir::cleanDirPath(g_sourceFileDef->getPath()+"/"+absPath);
1999 FileDef *fd=findFileDef(Doxygen::inputNameDict,yytext,ambig);
2000 //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd);
2001 if (fd && fd->isLinkable())
2003 if (ambig) // multiple input files match the name
2005 //printf("===== yes %s is ambiguous\n",yytext);
2006 QCString name = convertToQCString(QDir::cleanDirPath(yytext));
2007 if (!name.isEmpty() && g_sourceFileDef)
2009 FileName *fn = Doxygen::inputNameDict->find(name);
2012 FileNameIterator fni(*fn);
2013 // for each include name
2014 for (fni.toFirst();!found && (fd=fni.current());++fni)
2016 // see if this source file actually includes the file
2017 found = g_sourceFileDef->isIncluded(fd->absFilePath());
2018 //printf(" include file %s found=%d\n",fd->absFilePath().data(),found);
2023 else // not ambiguous
2028 //printf(" include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found);
2031 g_code->writeCodeLink(fd->getReference(),fd->getOutputFileBase(),0,yytext,fd->briefDescriptionAsTooltip());
2035 g_code->codify(yytext);
2040 g_code->codify(text);
2044 <Body,Bases>^[ \t]*"#" {
2045 startFontClass("preprocessor");
2046 g_lastSkipCppContext = YY_START;
2047 g_code->codify(yytext);
2051 g_code->codify(yytext);
2053 <SkipCPP>[^\n\/\\]+ {
2054 g_code->codify(yytext);
2056 <SkipCPP>\\[\r]?\n {
2057 codifyLines(yytext);
2060 g_code->codify(yytext);
2062 <Body,FuncCall>"{" {
2063 g_theVarContext.pushScope();
2065 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2066 g_scopeStack.push(INNERBLOCK);
2068 if (g_searchingForBody)
2070 g_searchingForBody=FALSE;
2073 g_code->codify(yytext);
2083 <Body,MemberCall,MemberCall2>"}" {
2084 g_theVarContext.popScope();
2088 int *scope = g_scopeStack.pop();
2089 DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2090 if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
2095 g_code->codify(yytext);
2097 //fprintf(stderr,"g_bodyCurlyCount=%d\n",g_bodyCurlyCount);
2098 if (--g_bodyCurlyCount<=0)
2101 g_currentMemberDef=0;
2102 if (g_currentDefinition)
2103 g_currentDefinition=g_currentDefinition->getOuterScope();
2107 <Body,ClassVar>"@end" {
2108 //printf("End of objc scope fd=%s\n",g_sourceFileDef->name().data());
2109 if (g_sourceFileDef)
2111 FileDef *fd=g_sourceFileDef;
2112 g_insideObjC = fd->name().lower().right(2)==".m" ||
2113 fd->name().lower().right(3)==".mm";
2114 //printf("insideObjC=%d\n",g_insideObjC);
2118 g_insideObjC = FALSE;
2122 g_theVarContext.popScope();
2124 int *scope = g_scopeStack.pop();
2125 DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2126 if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
2133 startFontClass("keyword");
2134 g_code->codify(yytext);
2137 g_currentMemberDef=0;
2138 if (g_currentDefinition)
2139 g_currentDefinition=g_currentDefinition->getOuterScope();
2142 <ClassName,ClassVar>";" {
2143 g_code->codify(yytext);
2144 g_searchingForBody=FALSE;
2147 <ClassName,ClassVar>[*&^%]+ {
2148 g_type=g_curClassName.copy();
2150 g_code->codify(yytext);
2151 BEGIN( Body ); // variable of type struct *
2153 <ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")" {
2154 startFontClass("keyword");
2155 g_code->codify(yytext);
2158 <ClassName>{ID}("::"{ID})* {
2159 g_curClassName=yytext;
2161 generateClassOrGlobalLink(*g_code,yytext);
2164 <ClassName>{ID}("\\"{ID})* { // PHP namespace
2165 g_curClassName=substitute(yytext,"\\","::");
2166 g_scopeStack.push(CLASSBLOCK);
2167 pushScope(g_curClassName);
2169 generateClassOrGlobalLink(*g_code,yytext);
2172 <ClassName>{ID}{B}*"("{ID}")" { // Obj-C category
2173 g_curClassName=removeRedundantWhiteSpace(yytext);
2174 g_scopeStack.push(CLASSBLOCK);
2175 pushScope(g_curClassName);
2177 generateClassOrGlobalLink(*g_code,yytext);
2180 <PackageName>{ID}("."{ID})* {
2181 g_curClassName=substitute(yytext,".","::");
2182 //printf("found package: %s\n",g_curClassName.data());
2184 codifyLines(yytext);
2190 <ClassVar>("extends"|"implements") { // Java
2191 startFontClass("keyword");
2192 codifyLines(yytext);
2194 g_curClassBases.clear();
2197 <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") {
2198 //fprintf(stderr,"***** C++/CLI modifier %s on g_curClassName=%s\n",yytext,g_curClassName.data());
2199 startFontClass("keyword");
2200 codifyLines(yytext);
2202 BEGIN( CppCliTypeModifierFollowup );
2205 g_type = g_curClassName.copy();
2209 g_theVarContext.addVariable(g_type,g_name);
2211 generateClassOrGlobalLink(*g_code,yytext);
2213 <ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* {
2214 codifyLines(yytext);
2215 g_curClassBases.clear();
2218 <PackageName>[ \t]*";" |
2219 <Bases>^{B}*/"@"{ID} | // Objective-C interface
2220 <Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* {
2221 g_theVarContext.pushScope();
2222 g_code->codify(yytext);
2224 if (YY_START==ClassVar && g_curClassName.isEmpty())
2226 g_curClassName = g_name.copy();
2228 if (g_searchingForBody)
2230 g_searchingForBody=FALSE;
2233 if (g_insideBody) g_bodyCurlyCount++;
2234 if (!g_curClassName.isEmpty()) // valid class name
2236 DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2237 g_scopeStack.push(CLASSBLOCK);
2238 pushScope(g_curClassName);
2239 //fprintf(stderr,"***** g_curClassName=%s\n",g_curClassName.data());
2240 if (getResolvedClass(g_currentDefinition,g_sourceFileDef,g_curClassName)==0)
2242 //fprintf(stderr,"Adding new class %s\n",g_curClassName.data());
2243 ClassDef *ncd=new ClassDef("<code>",1,
2244 g_curClassName,ClassDef::Class,0,0,FALSE);
2245 g_codeClassSDict->append(g_curClassName,ncd);
2246 // insert base classes.
2247 char *s=g_curClassBases.first();
2251 bcd=g_codeClassSDict->find(s);
2252 if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s);
2253 if (bcd && bcd!=ncd)
2255 ncd->insertBaseClass(bcd,s,Public,Normal);
2257 s=g_curClassBases.next();
2260 //printf("g_codeClassList.count()=%d\n",g_codeClassList.count());
2262 else // not a class name -> assume inner block
2264 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2265 g_scopeStack.push(INNERBLOCK);
2267 g_curClassName.resize(0);
2268 g_curClassBases.clear();
2271 <Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" {
2272 startFontClass("keyword");
2273 g_code->codify(yytext);
2276 <Bases>{SEP}?({ID}{SEP})*{ID} {
2277 //fprintf(stderr,"%s:addBase(%s)\n",g_curClassName.data(),yytext);
2278 g_curClassBases.inSort(yytext);
2279 generateClassOrGlobalLink(*g_code,yytext);
2282 g_code->codify(yytext);
2286 BEGIN ( SkipSharp );
2290 g_insideProtocolList=TRUE;
2294 g_code->codify(yytext);
2295 g_insideProtocolList=FALSE;
2298 g_code->codify(yytext);
2302 g_code->codify(yytext);
2303 if (--g_sharpCount<=0)
2307 g_code->codify(yytext);
2309 BEGIN ( SkipSharp );
2312 g_code->codify(yytext);
2316 g_code->codify(yytext);
2317 if (--g_sharpCount<=0)
2323 g_code->codify(yytext);
2327 <Body>{SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" {
2329 generateFunctionLink(*g_code,yytext);
2335 <Body>{SCOPEPREFIX}?"operator"/"(" {
2337 generateFunctionLink(*g_code,yytext);
2343 <Body>{SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\(\n]+/"(" {
2345 generateFunctionLink(*g_code,yytext);
2351 <Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9]) {
2352 startFontClass("keyword");
2353 codifyLines(yytext);
2355 g_insideTemplate=TRUE;
2358 <Body>"using"{BN}+"namespace"{BN}+ {
2359 startFontClass("keyword");
2360 codifyLines(yytext);
2364 <UsingName>{ID}("::"{ID})* { addUsingDirective(yytext);
2365 generateClassOrGlobalLink(*g_code,yytext);
2366 DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2367 g_scopeStack.push(CLASSBLOCK);
2371 <UsingName>\n { codifyLines(yytext); BEGIN(Body); }
2372 <UsingName>. { codifyLines(yytext); BEGIN(Body); }
2373 <Body,FuncCall>"$"?"this"("->"|".") { g_code->codify(yytext); // this-> for C++, this. for C#
2375 <Body>{KEYWORD}/([^a-z_A-Z0-9]) {
2376 startFontClass("keyword");
2377 codifyLines(yytext);
2378 if (QCString(yytext)=="typedef")
2385 <Body>{KEYWORD}/{B}* {
2386 startFontClass("keyword");
2387 codifyLines(yytext);
2390 <Body>{KEYWORD}/{BN}*"(" {
2391 startFontClass("keyword");
2392 codifyLines(yytext);
2394 g_name.resize(0);g_type.resize(0);
2396 <FuncCall>"in"/{BN}* {
2397 if (!g_inForEachExpression) REJECT;
2398 startFontClass("keywordflow");
2399 codifyLines(yytext);
2401 // insert the variable in the parent scope, see bug 546158
2402 g_theVarContext.popScope();
2403 g_theVarContext.addVariable(g_parmType,g_parmName);
2404 g_theVarContext.pushScope();
2405 g_name.resize(0);g_type.resize(0);
2407 <Body>{FLOWKW}/{BN}*"(" {
2408 startFontClass("keywordflow");
2409 codifyLines(yytext);
2411 g_name.resize(0);g_type.resize(0);
2412 g_inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0);
2415 <Body>{FLOWKW}/([^a-z_A-Z0-9]) {
2416 startFontClass("keywordflow");
2417 codifyLines(yytext);
2419 if (g_inFunctionTryBlock && (strcmp(yytext,"catch")==0 || strcmp(yytext,"finally")==0))
2421 g_inFunctionTryBlock=FALSE;
2424 <Body>{FLOWKW}/{B}* {
2425 startFontClass("keywordflow");
2426 codifyLines(yytext);
2429 <Body>"*"{B}*")" { // end of cast?
2430 g_code->codify(yytext);
2431 g_theCallContext.popScope();
2433 g_parmType = g_name;
2436 <Body>[\\|\)\+\-\/\%\~\!] {
2437 g_code->codify(yytext);
2438 g_name.resize(0);g_type.resize(0);
2441 g_theCallContext.popScope();
2446 <Body,TemplDecl,ObjCMethod>{TYPEKW}/{B}* {
2447 startFontClass("keywordtype");
2448 g_code->codify(yytext);
2453 <Body>"generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* {
2454 startFontClass("keyword");
2455 g_code->codify(yytext);
2460 <Body>"template"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { // template<...>
2461 startFontClass("keyword");
2462 g_code->codify(yytext);
2467 <TemplDecl>"class"|"typename" {
2468 startFontClass("keyword");
2469 codifyLines(yytext);
2473 g_code->codify(yytext);
2477 g_code->codify(yytext);
2479 if (g_sharpCount<=0)
2485 startFontClass("keyword");
2486 codifyLines(yytext);
2488 BEGIN( g_lastTemplCastContext );
2490 <TemplCast>{ID}("::"{ID})* {
2491 generateClassOrGlobalLink(*g_code,yytext);
2493 <TemplCast>("const"|"volatile"){B}* {
2494 startFontClass("keyword");
2495 codifyLines(yytext);
2499 codifyLines(yytext);
2501 <Body,FuncCall>{CASTKW}"<" { // static_cast<T>(
2502 startFontClass("keyword");
2503 codifyLines(yytext);
2505 g_lastTemplCastContext = YY_START;
2508 <Body>"$this->"{SCOPENAME}/{BN}*[;,)\]] { // PHP member variable
2510 generatePHPVariableLink(*g_code,yytext);
2513 <Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"("::"{ID})*/{B}* { // A<T> *pt;
2514 int i=QCString(yytext).find('<');
2515 QCString kw = QCString(yytext).left(i).stripWhiteSpace();
2516 if (kw.right(5)=="_cast" && YY_START==Body)
2521 generateClassOrGlobalLink(*g_code,yytext);
2524 <Body>{SCOPENAME}/{BN}*[;,)\]] { // "int var;" or "var, var2" or "debug(f) macro"
2526 // changed this to generateFunctionLink, see bug 624514
2527 //generateClassOrGlobalLink(*g_code,yytext,FALSE,TRUE);
2528 generateFunctionLink(*g_code,yytext);
2531 <Body>{SCOPENAME}/{B}* { // p->func()
2533 generateClassOrGlobalLink(*g_code,yytext);
2536 <Body>"("{B}*("*"{B}*)+{SCOPENAME}*{B}*")"/{B}* { // (*p)->func() but not "if (p) ..."
2537 g_code->codify(yytext);
2538 int s=0;while (s<(int)yyleng && !isId(yytext[s])) s++;
2539 int e=(int)yyleng-1;while (e>=0 && !isId(yytext[e])) e--;
2540 QCString varname = ((QCString)yytext).mid(s,e-s+1);
2544 <Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo()
2546 generateFunctionLink(*g_code,yytext);
2552 <FuncCall,Body,MemberCall,MemberCall2,SkipInits>{RAWBEGIN} {
2553 QCString text=yytext;
2554 int i=text.find('R');
2555 g_code->codify(text.left(i+1));
2556 startFontClass("stringliteral");
2557 g_code->codify(yytext+i+1);
2558 g_lastStringContext=YY_START;
2559 g_inForEachExpression = FALSE;
2560 g_delimiter = yytext+i+2;
2561 g_delimiter=g_delimiter.left(g_delimiter.length()-1);
2564 <FuncCall,Body,MemberCall,MemberCall2,SkipInits>\" {
2565 startFontClass("stringliteral");
2566 g_code->codify(yytext);
2567 g_lastStringContext=YY_START;
2568 g_inForEachExpression = FALSE;
2569 BEGIN( SkipString );
2571 <FuncCall,Body,MemberCall,MemberCall2,SkipInits>\' {
2572 startFontClass("stringliteral");
2573 g_code->codify(yytext);
2574 g_lastStringContext=YY_START;
2575 g_inForEachExpression = FALSE;
2576 BEGIN( SkipStringS );
2578 <SkipString>[^\"\\\r\n]* {
2579 g_code->codify(yytext);
2581 <SkipStringS>[^\'\\\r\n]* {
2582 g_code->codify(yytext);
2584 <SkipString,SkipStringS>"//"|"/*" {
2585 g_code->codify(yytext);
2588 g_code->codify(yytext);
2590 BEGIN( g_lastStringContext );
2593 g_code->codify(yytext);
2595 BEGIN( g_lastStringContext );
2597 <SkipString,SkipStringS>\\. {
2598 g_code->codify(yytext);
2600 <RawString>{RAWEND} {
2601 g_code->codify(yytext);
2602 QCString delimiter = yytext+1;
2603 delimiter=delimiter.left(delimiter.length()-1);
2604 if (delimiter==g_delimiter)
2606 BEGIN( g_lastStringContext );
2609 <RawString>[^)]+ { g_code->codify(yytext); }
2610 <RawString>. { g_code->codify(yytext); }
2611 <RawString>\n { codifyLines(yytext); }
2612 <SkipVerbString>[^"\n]+ {
2613 g_code->codify(yytext);
2615 <SkipVerbString>\"\" { // escaped quote
2616 g_code->codify(yytext);
2618 <SkipVerbString>\" { // end of string
2619 g_code->codify(yytext);
2621 BEGIN( g_lastVerbStringContext );
2624 g_code->codify(yytext);
2626 <SkipVerbString>\n {
2627 codifyLines(yytext);
2630 g_code->codify(yytext);
2631 g_name.resize(0);g_type.resize(0);
2634 if (g_insideTemplate)
2638 g_code->codify(yytext);
2641 if (g_insideTemplate)
2643 if (--g_sharpCount<=0)
2645 g_insideTemplate=FALSE;
2648 g_code->codify(yytext);
2650 <Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'" {
2651 startFontClass("charliteral");
2652 g_code->codify(yytext);
2656 if (yytext[0]=='-') // -> could be overloaded
2658 updateCallContextForSmartPointer();
2660 g_code->codify(yytext);
2661 g_memCallContext = YY_START;
2662 BEGIN( MemberCall );
2664 <MemberCall>{SCOPETNAME}/{BN}*"(" {
2665 if (g_theCallContext.getClass())
2667 if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),yytext))
2669 g_code->linkableSymbol(g_yyLineNr,yytext,0,
2670 g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
2671 g_code->codify(yytext);
2672 addToSearchIndex(yytext);
2678 g_code->linkableSymbol(g_yyLineNr,yytext,0,
2679 g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
2680 g_code->codify(yytext);
2681 addToSearchIndex(yytext);
2686 if (g_memCallContext==Body)
2692 BEGIN(g_memCallContext);
2695 <MemberCall>{SCOPENAME}/{B}* {
2696 if (g_theCallContext.getClass())
2698 //fprintf(stderr,"g_theCallContext.getClass()=%p\n",g_theCallContext.getClass());
2699 if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),yytext))
2701 g_code->linkableSymbol(g_yyLineNr,yytext,0,
2702 g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
2703 g_code->codify(yytext);
2704 addToSearchIndex(yytext);
2710 //fprintf(stderr,"no class context!\n");
2711 g_code->codify(yytext);
2712 addToSearchIndex(yytext);
2716 BEGIN(g_memCallContext);
2719 if (g_insideObjC && *yytext=='[')
2721 //printf("Found start of ObjC call!\n");
2722 // start of a method call
2723 g_contextDict.setAutoDelete(TRUE);
2724 g_nameDict.setAutoDelete(TRUE);
2725 g_objectDict.setAutoDelete(TRUE);
2726 g_wordDict.setAutoDelete(TRUE);
2727 g_contextDict.clear();
2729 g_objectDict.clear();
2732 g_currentNameId = 0;
2741 g_code->codify(yytext);
2742 g_saveName = g_name.copy();
2743 g_saveType = g_type.copy();
2744 if (*yytext!='[' && !g_type.isEmpty())
2746 //printf("g_scopeStack.bottom()=%p\n",g_scopeStack.bottom());
2747 if (g_scopeStack.top()!=CLASSBLOCK)
2749 //printf("AddVariable: '%s' '%s' context=%d\n",
2750 // g_type.data(),g_name.data(),g_theVarContext.count());
2751 g_theVarContext.addVariable(g_type,g_name);
2755 if (*yytext==';' || *yytext=='=')
2760 else if (*yytext=='[')
2762 g_theCallContext.pushScope();
2765 g_parmType.resize(0);
2766 g_parmName.resize(0);
2770 <ObjCMemberCall>{ID} {
2771 if (strcmp(yytext,"self")==0 || strcmp(yytext,"super")==0)
2773 // TODO: get proper base class for "super"
2774 g_theCallContext.setClass(getClass(g_curClassName));
2775 startFontClass("keyword");
2776 g_code->codify(yytext);
2781 generateClassOrGlobalLink(*g_code,yytext);
2784 BEGIN(ObjCMemberCall2);
2786 <ObjCMemberCall>"[" {
2787 g_code->codify(yytext);
2788 g_theCallContext.pushScope();
2790 <ObjCMemberCall2>{ID}":"? {
2792 if (g_theCallContext.getClass())
2794 //printf("Calling method %s\n",g_name.data());
2795 if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),g_name))
2797 g_code->codify(yytext);
2798 addToSearchIndex(g_name);
2803 g_code->codify(yytext);
2804 addToSearchIndex(g_name);
2807 BEGIN(ObjCMemberCall3);
2809 <ObjCMemberCall2,ObjCMemberCall3>"]" {
2810 g_theCallContext.popScope();
2811 g_code->codify(yytext);
2815 <ObjCCall,ObjCMName>"[" {
2817 g_currentCtx->format+=*yytext;
2821 <ObjCCall,ObjCMName>"]" {
2822 g_currentCtx->format+=*yytext;
2823 restoreObjCContext();
2825 if (g_currentCtx==0)
2828 writeObjCMethodCall(g_contextDict.find(0));
2831 //printf("close\n");
2834 g_currentCtx->format+=escapeObject(yytext);
2835 if (g_braceCount==0)
2837 g_currentCtx->objectTypeOrName=yytext;
2838 //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
2842 <ObjCMName>{ID}/{BN}*"]" {
2843 if (g_braceCount==0 &&
2844 g_currentCtx->methodName.isEmpty())
2846 g_currentCtx->methodName=yytext;
2847 g_currentCtx->format+=escapeName(yytext);
2851 g_currentCtx->format+=escapeWord(yytext);
2854 <ObjCMName>{ID}/{BN}*":" {
2855 if (g_braceCount==0)
2857 g_currentCtx->methodName+=yytext;
2858 g_currentCtx->methodName+=":";
2860 g_currentCtx->format+=escapeName(yytext);
2862 <ObjCSkipStr>[^\n\"$\\]* { g_currentCtx->format+=yytext; }
2863 <ObjCSkipStr>\\. { g_currentCtx->format+=yytext; }
2864 <ObjCSkipStr>"\"" { g_currentCtx->format+=yytext;
2865 BEGIN(g_lastStringContext);
2867 <ObjCCall,ObjCMName>{CHARLIT} { g_currentCtx->format+=yytext; }
2868 <ObjCCall,ObjCMName>"@"?"\"" { g_currentCtx->format+=yytext;
2869 g_lastStringContext=YY_START;
2872 <ObjCCall,ObjCMName,ObjCSkipStr>"$" { g_currentCtx->format+="$$"; }
2873 <ObjCCall,ObjCMName>"(" { g_currentCtx->format+=*yytext; g_braceCount++; }
2874 <ObjCCall,ObjCMName>")" { g_currentCtx->format+=*yytext; g_braceCount--; }
2875 <ObjCSkipStr>"@"/"\"" { // needed to prevent matching the global rule (for C#)
2876 g_currentCtx->format+=yytext;
2878 <ObjCCall,ObjCMName,ObjCSkipStr>{ID} { g_currentCtx->format+=escapeWord(yytext); }
2879 <ObjCCall,ObjCMName,ObjCSkipStr>. { g_currentCtx->format+=*yytext; }
2880 <ObjCCall,ObjCMName,ObjCSkipStr>\n { g_currentCtx->format+=*yytext; }
2883 g_theCallContext.popScope();
2884 g_code->codify(yytext);
2885 // TODO: nested arrays like: a[b[0]->func()]->func()
2886 g_name = g_saveName.copy();
2887 g_type = g_saveType.copy();
2890 g_code->codify(yytext);
2892 <Body>[0-9]+[xX][0-9A-Fa-f]+ {
2893 g_code->codify(yytext);
2895 <MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) {
2897 //g_parmName=yytext;
2898 startFontClass("keyword");
2899 g_code->codify(yytext);
2902 <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKW}/([^a-z_A-Z0-9]) {
2905 startFontClass("keywordtype");
2906 g_code->codify(yytext);
2909 <MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) {
2912 startFontClass("keywordflow");
2913 g_code->codify(yytext);
2916 <MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* {
2919 generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
2921 <FuncCall>";" { // probably a cast, not a function call
2922 g_code->codify(yytext);
2923 g_inForEachExpression = FALSE;
2926 <MemberCall2,FuncCall>, {
2927 g_code->codify(yytext);
2928 g_theVarContext.addVariable(g_parmType,g_parmName);
2929 g_parmType.resize(0);g_parmName.resize(0);
2931 <MemberCall2,FuncCall>"(" {
2932 g_parmType.resize(0);g_parmName.resize(0);
2933 g_code->codify(yytext);
2935 g_theCallContext.pushScope();
2936 if (YY_START==FuncCall && !g_insideBody)
2938 g_theVarContext.pushScope();
2941 <MemberCall2,FuncCall>{OPERATOR} { // operator
2942 if (strcmp(yytext,"*") &&
2943 strcmp(yytext,"&") &&
2944 strcmp(yytext,"^") &&
2945 strcmp(yytext,"%")) // typically a pointer or reference
2947 // not a * or &, or C++/CLI's ^ or %
2948 g_parmType.resize(0);g_parmName.resize(0);
2950 g_code->codify(yytext);
2952 <MemberCall,MemberCall2,FuncCall>("*"{B}*)?")" {
2953 if (yytext[0]==')') // no a pointer cast
2955 //printf("addVariable(%s,%s)\n",g_parmType.data(),g_parmName.data());
2956 g_theVarContext.addVariable(g_parmType,g_parmName);
2960 g_parmType.resize(0);
2961 g_parmName.resize(0);
2963 g_theCallContext.popScope();
2964 g_inForEachExpression = FALSE;
2965 //g_theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b().
2966 g_code->codify(yytext);
2967 if (--g_bracketCount<=0)
2969 if (g_name.isEmpty())
2979 <CallEnd>[ \t\n]* { codifyLines(yytext); }
2981 <MemberCall2,FuncCall>")"[ \t\n]*[;:] {
2984 codifyLines(yytext);
2986 if (*yytext==';') g_searchingForBody=FALSE;
2987 if (!g_type.isEmpty())
2989 //fprintf(stderr,"add variable g_type=%s g_name=%s)\n",g_type.data(),g_name.data());
2990 g_theVarContext.addVariable(g_type,g_name);
2992 g_parmType.resize(0);g_parmName.resize(0);
2993 g_theCallContext.setClass(0);
2994 if (*yytext==';' || g_insideBody)
2998 g_theVarContext.popScope();
3000 g_name.resize(0);g_type.resize(0);
3009 <CallEnd>("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") {
3010 startFontClass("keyword");
3011 codifyLines(yytext);
3014 <CallEnd,OldStyleArgs>("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" {
3017 g_theVarContext.pushScope();
3019 g_theVarContext.addVariable(g_parmType,g_parmName);
3020 //g_theCallContext.popScope();
3021 g_parmType.resize(0);g_parmName.resize(0);
3022 int index = g_name.findRev("::");
3023 //fprintf(stderr,"g_name=%s\n",g_name.data());
3026 QCString scope = g_name.left(index);
3027 if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::");
3028 ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope);
3031 setClassScope(cd->name());
3032 g_scopeStack.push(SCOPEBLOCK);
3033 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3037 //setClassScope(g_realScope);
3038 g_scopeStack.push(INNERBLOCK);
3039 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3044 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3045 g_scopeStack.push(INNERBLOCK);
3047 yytext[yyleng-1]='\0';
3048 QCString cv(yytext);
3049 if (!cv.stripWhiteSpace().isEmpty())
3051 startFontClass("keyword");
3052 codifyLines(yytext);
3055 else // just whitespace
3057 codifyLines(yytext);
3059 g_code->codify("{");
3060 if (g_searchingForBody)
3062 g_searchingForBody=FALSE;
3065 if (g_insideBody) g_bodyCurlyCount++;
3067 g_type.resize(0); g_name.resize(0);
3070 <CallEnd>"try" { // function-try-block
3071 startFontClass("keyword");
3072 g_code->codify(yytext);
3074 g_inFunctionTryBlock=TRUE;
3077 if (g_insideBody || !g_parmType.isEmpty())
3081 // could be K&R style definition
3084 generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3085 BEGIN(OldStyleArgs);
3087 <OldStyleArgs>{ID} {
3090 generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3092 <OldStyleArgs>[,;] {
3093 g_code->codify(yytext);
3094 g_theVarContext.addVariable(g_parmType,g_parmName);
3095 if (*yytext==';') g_parmType.resize(0);
3096 g_parmName.resize(0);
3098 <CallEnd,OldStyleArgs>"#" {
3099 startFontClass("preprocessor");
3100 g_lastSkipCppContext = Body;
3101 g_code->codify(yytext);
3108 g_theVarContext.popScope();
3110 g_name.resize(0);g_args.resize(0);
3111 g_parmType.resize(0);g_parmName.resize(0);
3115 g_code->codify(yytext);
3116 g_type.resize(0); g_name.resize(0);
3120 g_code->codify(yytext);
3122 if (g_searchingForBody)
3124 g_searchingForBody=FALSE;
3127 if (g_insideBody) g_bodyCurlyCount++;
3128 if (g_name.find("::")!=-1)
3130 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3131 g_scopeStack.push(SCOPEBLOCK);
3132 setClassScope(g_realScope);
3136 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3137 g_scopeStack.push(INNERBLOCK);
3139 g_type.resize(0); g_name.resize(0);
3143 generateClassOrGlobalLink(*g_code,yytext);
3145 <FuncCall>{ID}/"(" {
3146 generateFunctionLink(*g_code,yytext);
3148 <FuncCall>{ID}/("."|"->") {
3150 generateClassOrGlobalLink(*g_code,yytext);
3151 BEGIN( MemberCall2 );
3153 <FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}*{B}*")"{B}*)/("."|"->") {
3154 g_code->codify(yytext);
3155 int s=0;while (!isId(yytext[s])) s++;
3156 int e=(int)yyleng-1;while (!isId(yytext[e])) e--;
3157 g_name=((QCString)yytext).mid(s,e-s+1);
3158 BEGIN( MemberCall2 );
3160 <MemberCall2>{ID}/([ \t\n]*"(") {
3161 if (!g_args.isEmpty())
3162 generateMemberLink(*g_code,g_args,yytext);
3164 generateClassOrGlobalLink(*g_code,yytext);
3168 <MemberCall2>{ID}/([ \t\n]*("."|"->")) {
3169 //g_code->codify(yytext);
3171 generateClassOrGlobalLink(*g_code,yytext);
3172 BEGIN( MemberCall2 );
3174 <MemberCall2>"->"|"." {
3175 if (yytext[0]=='-') // -> could be overloaded
3177 updateCallContextForSmartPointer();
3179 g_code->codify(yytext);
3180 g_memCallContext = YY_START;
3181 BEGIN( MemberCall );
3183 <SkipComment>"/*"("!"?)"*/" {
3184 g_code->codify(yytext);
3186 BEGIN( g_lastCContext ) ;
3188 <SkipComment>"//"|"/*" {
3189 g_code->codify(yytext);
3191 <SkipComment>[^*/\n]+ {
3192 g_code->codify(yytext);
3194 <SkipComment>[ \t]*"*/" {
3195 g_code->codify(yytext);
3197 if (g_lastCContext==SkipCPP)
3199 startFontClass("preprocessor");
3201 BEGIN( g_lastCContext ) ;
3203 <SkipCxxComment>[^\r\n]*"\\"[\r]?\n { // line continuation
3204 codifyLines(yytext);
3206 <SkipCxxComment>[^\r\n]+ {
3207 g_code->codify(yytext);
3210 <SkipCxxComment>\n {
3213 BEGIN( g_lastCContext ) ;
3216 g_code->codify(yytext);
3218 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] {
3219 g_yyLineNr+=QCString(yytext).contains('\n');
3221 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? {
3222 g_yyLineNr+=QCString(yytext).contains('\n');
3224 if (g_lastSpecialCContext==SkipCxxComment)
3225 { // force end of C++ comment here
3227 BEGIN( g_lastCContext ) ;
3231 BEGIN(g_lastSpecialCContext);
3234 <RemoveSpecialCComment>"*/" {
3235 BEGIN(g_lastSpecialCContext);
3237 <RemoveSpecialCComment>[^*\n]+
3238 <RemoveSpecialCComment>"//"|"/*"
3239 <RemoveSpecialCComment>\n { g_yyLineNr++; }
3240 <RemoveSpecialCComment>.
3241 <MemberCall>[^a-z_A-Z0-9(\n] {
3242 g_code->codify(yytext);
3245 BEGIN(g_memCallContext);
3247 <*>\n({B}*"//"[!/][^\n]*\n)+ { // remove special one-line comment
3248 if (YY_START==SkipCPP) REJECT;
3249 if (Config_getBool("STRIP_CODE_COMMENTS"))
3251 g_yyLineNr+=((QCString)yytext).contains('\n');
3256 startFontClass("comment");
3257 codifyLines(yytext);
3260 if (YY_START==SkipCxxComment)
3263 BEGIN( g_lastCContext ) ;
3267 codifyLines(yytext);
3269 BEGIN( g_lastSkipCppContext ) ;
3271 <*>\n{B}*"//@"[{}].*\n { // remove one-line group marker
3272 if (Config_getBool("STRIP_CODE_COMMENTS"))
3279 startFontClass("comment");
3280 codifyLines(yytext);
3283 if (YY_START==SkipCxxComment)
3286 BEGIN( g_lastCContext ) ;
3289 <*>\n{B}*"/*@"[{}] { // remove one-line group marker
3290 if (Config_getBool("STRIP_CODE_COMMENTS"))
3292 g_lastSpecialCContext = YY_START;
3294 BEGIN(RemoveSpecialCComment);
3298 // check is to prevent getting stuck in skipping C++ comments
3299 if (YY_START != SkipCxxComment)
3301 g_lastCContext = YY_START ;
3303 startFontClass("comment");
3304 codifyLines(yytext);
3308 <*>^{B}*"//@"[{}].*\n { // remove one-line group marker
3309 if (Config_getBool("STRIP_CODE_COMMENTS"))
3316 startFontClass("comment");
3317 codifyLines(yytext);
3321 <*>^{B}*"/*@"[{}] { // remove multi-line group marker
3322 if (Config_getBool("STRIP_CODE_COMMENTS"))
3324 g_lastSpecialCContext = YY_START;
3325 BEGIN(RemoveSpecialCComment);
3329 // check is to prevent getting stuck in skipping C++ comments
3330 if (YY_START != SkipCxxComment)
3332 g_lastCContext = YY_START ;
3334 startFontClass("comment");
3335 g_code->codify(yytext);
3339 <*>^{B}*"//"[!/][^\n]*\n { // remove special one-line comment
3340 if (Config_getBool("STRIP_CODE_COMMENTS"))
3347 startFontClass("comment");
3348 codifyLines(yytext);
3352 <*>"//"[!/][^\n]*\n { // strip special one-line comment
3353 if (YY_START==SkipComment || YY_START==SkipString) REJECT;
3354 if (Config_getBool("STRIP_CODE_COMMENTS"))
3356 char c[2]; c[0]='\n'; c[1]=0;
3361 startFontClass("comment");
3362 codifyLines(yytext);
3366 <*>"/*[tag:"[^\]\n]*"]*/"{B}* { // special pattern /*[tag:filename]*/ to force linking to a tag file
3367 g_forceTagReference=yytext;
3368 int s=g_forceTagReference.find(':');
3369 int e=g_forceTagReference.findRev(']');
3370 g_forceTagReference = g_forceTagReference.mid(s+1,e-s-1);
3372 <*>\n{B}*"/*"[!*]/[^/*] {
3373 if (Config_getBool("STRIP_CODE_COMMENTS"))
3375 g_lastSpecialCContext = YY_START;
3377 BEGIN(RemoveSpecialCComment);
3381 // check is to prevent getting stuck in skipping C++ comments
3382 if (YY_START != SkipCxxComment)
3384 g_lastCContext = YY_START ;
3386 startFontClass("comment");
3387 codifyLines(yytext);
3391 <*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line
3392 if (Config_getBool("STRIP_CODE_COMMENTS"))
3394 g_lastSpecialCContext = YY_START;
3395 BEGIN(RemoveSpecialCComment);
3399 // check is to prevent getting stuck in skipping C++ comments
3400 if (YY_START != SkipCxxComment)
3402 g_lastCContext = YY_START ;
3404 startFontClass("comment");
3405 g_code->codify(yytext);
3409 <*>"/*"[!*]/[^/*] { // special C comment block half way a line
3410 if (YY_START==SkipString) REJECT;
3411 if (Config_getBool("STRIP_CODE_COMMENTS"))
3413 g_lastSpecialCContext = YY_START;
3414 BEGIN(RemoveSpecialCComment);
3418 // check is to prevent getting stuck in skipping C++ comments
3419 if (YY_START != SkipCxxComment)
3421 g_lastCContext = YY_START ;
3423 startFontClass("comment");
3424 g_code->codify(yytext);
3429 if (YY_START==SkipString) REJECT;
3430 if (!Config_getBool("STRIP_CODE_COMMENTS"))
3432 startFontClass("comment");
3433 g_code->codify(yytext);
3438 startFontClass("comment");
3439 g_code->codify(yytext);
3440 // check is to prevent getting stuck in skipping C++ comments
3441 if (YY_START != SkipCxxComment)
3443 g_lastCContext = YY_START ;
3445 BEGIN( SkipComment ) ;
3447 <*>@\" { // C# verbatim string
3448 startFontClass("stringliteral");
3449 g_code->codify(yytext);
3450 g_lastVerbStringContext=YY_START;
3451 BEGIN(SkipVerbString);
3454 startFontClass("comment");
3455 g_code->codify(yytext);
3456 g_lastCContext = YY_START ;
3457 BEGIN( SkipCxxComment ) ;
3460 g_code->codify(yytext);
3461 g_theCallContext.pushScope();
3464 g_code->codify(yytext);
3465 g_theCallContext.popScope();
3468 codifyLines(yytext);
3471 g_code->codify(yytext);
3474 <*>([ \t\n]*"\n"){2,} { // combine multiple blank lines
3475 //QCString sepLine=yytext;
3476 //g_code->codify("\n\n");
3477 //g_yyLineNr+=sepLine.contains('\n');
3478 //char sepLine[3]="\n\n";
3479 codifyLines(yytext);
3485 /*@ ----------------------------------------------------------------------------
3488 static void saveObjCContext()
3492 g_currentCtx->format+=QCString().sprintf("$c%d",g_currentCtxId);
3493 if (g_braceCount==0 && YY_START==ObjCCall)
3495 g_currentCtx->objectTypeOrName=g_currentCtx->format.mid(1);
3496 //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
3498 g_contextStack.push(g_currentCtx);
3502 //printf("Trying to save NULL context!\n");
3504 ObjCCallCtx *newCtx = new ObjCCallCtx;
3505 newCtx->id = g_currentCtxId;
3506 newCtx->lexState = YY_START;
3507 newCtx->braceCount = g_braceCount;
3508 newCtx->objectType = 0;
3509 newCtx->objectVar = 0;
3511 //printf("save state=%d\n",YY_START);
3512 g_contextDict.insert(g_currentCtxId,newCtx);
3513 g_currentCtx = newCtx;
3518 static void restoreObjCContext()
3520 //printf("restore state=%d->%d\n",YY_START,g_currentCtx->lexState);
3521 BEGIN(g_currentCtx->lexState);
3522 g_braceCount = g_currentCtx->braceCount;
3523 if (!g_contextStack.isEmpty())
3525 g_currentCtx = g_contextStack.pop();
3530 //printf("Trying to pop context while g_contextStack is empty!\n");
3534 void resetCCodeParserState()
3536 //printf("***initParseCodeContext()\n");
3537 g_forceTagReference.resize(0);
3538 g_theVarContext.clear();
3539 g_classScopeLengthStack.setAutoDelete(TRUE);
3540 g_classScopeLengthStack.clear();
3541 delete g_codeClassSDict;
3542 g_codeClassSDict = new ClassSDict(17);
3543 g_codeClassSDict->setAutoDelete(TRUE);
3544 g_codeClassSDict->clear();
3545 g_curClassBases.clear();
3549 void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s,
3550 bool exBlock, const char *exName,FileDef *fd,
3551 int startLine,int endLine,bool inlineFragment,
3552 MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx)
3554 //printf("***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n",
3555 // exBlock,exName,fd,className,searchCtx?searchCtx->name().data():"<none>");
3556 if (s.isEmpty()) return;
3557 if (g_codeClassSDict==0)
3559 resetCCodeParserState();
3563 g_inputPosition = 0;
3564 g_currentFontClass = 0;
3565 g_needsTermination = FALSE;
3566 g_searchCtx = searchCtx;
3567 g_inFunctionTryBlock = FALSE;
3569 g_inputLines = endLine+1;
3571 g_inputLines = countLines();
3574 g_yyLineNr = startLine;
3579 g_bodyCurlyCount = 0;
3582 g_insideTemplate = FALSE;
3583 g_theCallContext.clear();
3584 g_scopeStack.clear();
3585 g_classScope = className;
3586 //printf("parseCCode %s\n",className);
3587 g_exampleBlock = exBlock;
3588 g_exampleName = exName;
3589 g_sourceFileDef = fd;
3590 g_lineNumbers = fd!=0 && showLineNumbers;
3591 bool cleanupSourceDef = FALSE;
3594 // create a dummy filedef for the example
3595 g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
3596 cleanupSourceDef = TRUE;
3598 if (g_sourceFileDef)
3600 setCurrentDoc("l00001");
3601 g_insideObjC = g_sourceFileDef->name().lower().right(2)==".m" ||
3602 g_sourceFileDef->name().lower().right(3)==".mm";
3604 g_currentDefinition = 0;
3605 g_currentMemberDef = 0;
3606 g_searchingForBody = exBlock;
3607 g_insideBody = FALSE;
3609 if (!g_exampleName.isEmpty())
3611 g_exampleFile = convertNameToFile(g_exampleName+"-example",FALSE,TRUE);
3612 //printf("g_exampleFile=%s\n",g_exampleFile.data());
3614 g_includeCodeFragment = inlineFragment;
3615 //printf("** exBlock=%d exName=%s include=%d\n",exBlock,exName,inlineFragment);
3620 g_parmName.resize(0);
3621 g_parmType.resize(0);
3622 if (memberDef) setParameterList(memberDef);
3623 codeYYrestart( codeYYin );
3627 if (g_needsTermination)
3630 g_code->endCodeLine();
3632 if (cleanupSourceDef)
3634 // delete the temporary file definition used for this example
3635 delete g_sourceFileDef;
3641 void codeFreeScanner()
3643 #if defined(YY_FLEX_SUBMINOR_VERSION)
3646 codeYYlex_destroy();
3653 #if !defined(YY_FLEX_SUBMINOR_VERSION)
3654 extern "C" { // some bogus code to keep the compiler happy
3655 void codeYYdummy() { yy_flex_realloc(0,0); }
3657 #elif YY_FLEX_SUBMINOR_VERSION<33
3658 #error "You seem to be using a version of flex newer than 2.5.4 but older than 2.5.33. These versions do NOT work with doxygen! Please use version <=2.5.4 or >=2.5.33 or expect things to be parsed wrongly!"