1 /******************************************************************************
5 * Copyright (C) 1997-2015 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.
17 %option never-interactive
18 %option prefix="codeYY"
34 #include "outputlist.h"
36 #include "membername.h"
37 #include "searchindex.h"
38 #include "arguments.h"
41 #include "classlist.h"
44 #include "namespacedef.h"
47 // Toggle for some debugging info
48 //#define DBG_CTX(x) fprintf x
49 #define DBG_CTX(x) do { } while(0)
51 #define YY_NO_UNISTD_H 1
53 #define CLASSBLOCK (int *)4
54 #define SCOPEBLOCK (int *)8
55 #define INNERBLOCK (int *)12
57 /* -----------------------------------------------------------------
61 static CodeOutputInterface * g_code;
63 static ClassSDict *g_codeClassSDict = 0;
64 static QCString g_curClassName;
65 static QStrList g_curClassBases;
67 static QCString g_parmType;
68 static QCString g_parmName;
70 static const char * g_inputString; //!< the code fragment as text
71 static int g_inputPosition; //!< read offset during parsing
72 static int g_inputLines; //!< number of line in the code fragment
73 static int g_yyLineNr; //!< current line number
74 static int g_yyColNr; //!< current column number
75 static bool g_needsTermination;
77 static bool g_exampleBlock;
78 static QCString g_exampleName;
79 static QCString g_exampleFile;
81 static bool g_insideTemplate = FALSE;
82 static QCString g_type;
83 static QCString g_name;
84 static QCString g_args;
85 static QCString g_classScope;
86 static QCString g_realScope;
87 static QStack<int> g_scopeStack; //!< 1 if bracket starts a scope,
88 // 2 for internal blocks
89 static int g_anchorCount;
90 static FileDef * g_sourceFileDef;
91 static bool g_lineNumbers;
92 static Definition * g_currentDefinition;
93 static MemberDef * g_currentMemberDef;
94 static bool g_includeCodeFragment;
95 static const char * g_currentFontClass;
96 static bool g_searchingForBody;
97 static bool g_insideBody;
98 static int g_bodyCurlyCount;
99 static QCString g_saveName;
100 static QCString g_saveType;
101 static QCString g_delimiter;
103 static int g_bracketCount = 0;
104 static int g_curlyCount = 0;
105 static int g_sharpCount = 0;
106 static bool g_inFunctionTryBlock = FALSE;
107 static bool g_inForEachExpression = FALSE;
109 static int g_lastTemplCastContext;
110 static int g_lastSpecialCContext;
111 static int g_lastStringContext;
112 static int g_lastSkipCppContext;
113 static int g_lastVerbStringContext;
114 static int g_lastObjCCallContext;
115 static int g_memCallContext;
116 static int g_lastCContext;
117 static int g_skipInlineInitContext;
119 static bool g_insideObjC;
120 static bool g_insideJava;
121 static bool g_insideCS;
122 static bool g_insidePHP;
123 static bool g_insideProtocolList;
125 static bool g_lexInit = FALSE;
127 static QStack<int> g_classScopeLengthStack;
129 static int g_prefixed_with_this_keyword = FALSE;
130 static Definition *g_searchCtx;
131 static bool g_collectXRefs;
133 // context for an Objective-C method call
138 QCString objectTypeOrName;
140 ClassDef *objectType;
141 MemberDef *objectVar;
148 // globals for objective-C method calls
149 static ObjCCallCtx *g_currentCtx=0;
150 static int g_currentCtxId=0;
151 static int g_currentNameId=0;
152 static int g_currentObjId=0;
153 static int g_currentWordId=0;
154 static int g_currentCommentId=0;
155 static QStack<ObjCCallCtx> g_contextStack;
156 static QIntDict<ObjCCallCtx> g_contextDict;
157 static QIntDict<QCString> g_nameDict;
158 static QIntDict<QCString> g_objectDict;
159 static QIntDict<QCString> g_wordDict;
160 static QIntDict<QCString> g_commentDict;
161 static int g_braceCount=0;
163 static void saveObjCContext();
164 static void restoreObjCContext();
166 static QCString g_forceTagReference;
169 //-------------------------------------------------------------------
171 /*! Represents a stack of variable to class mappings as found in the
172 * code. Each scope is enclosed in pushScope() and popScope() calls.
173 * Variables are added by calling addVariables() and one can search
174 * for variable using findVariable().
176 class VariableContext
179 static const ClassDef *dummyContext;
181 class Scope : public SDict<ClassDef>
184 Scope() : SDict<ClassDef>(17) {}
189 m_scopes.setAutoDelete(TRUE);
191 virtual ~VariableContext()
197 m_scopes.append(new Scope);
198 DBG_CTX((stderr,"** Push var context %d\n",m_scopes.count()));
203 if (m_scopes.count()>0)
205 DBG_CTX((stderr,"** Pop var context %d\n",m_scopes.count()));
206 m_scopes.remove(m_scopes.count()-1);
210 DBG_CTX((stderr,"** ILLEGAL: Pop var context\n"));
217 m_globalScope.clear();
220 void clearExceptGlobal()
222 DBG_CTX((stderr,"** Clear var context\n"));
226 void addVariable(const QCString &type,const QCString &name);
227 ClassDef *findVariable(const QCString &name);
229 int count() const { return m_scopes.count(); }
233 QList<Scope> m_scopes;
236 void VariableContext::addVariable(const QCString &type,const QCString &name)
238 //printf("VariableContext::addVariable(%s,%s)\n",type.data(),name.data());
239 QCString ltype = type.simplifyWhiteSpace();
240 QCString lname = name.simplifyWhiteSpace();
241 if (ltype.left(7)=="struct ")
243 ltype = ltype.right(ltype.length()-7);
245 else if (ltype.left(6)=="union ")
247 ltype = ltype.right(ltype.length()-6);
249 if (ltype.isEmpty() || lname.isEmpty()) return;
250 DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' g_currentDefinition=%s\n",
251 ltype.data(),lname.data(),g_currentDefinition?g_currentDefinition->name().data():"<none>"));
252 Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast();
256 (varType=g_codeClassSDict->find(ltype)) || // look for class definitions inside the code block
257 (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,ltype)) // look for global class definitions
260 DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data()));
261 scope->append(lname,varType); // add it to a list
263 else if ((i=ltype.find('<'))!=-1)
265 // probably a template class
266 QCString typeName(ltype.left(i));
267 ClassDef* newDef = 0;
268 QCString templateArgs(ltype.right(ltype.length() - i));
270 ( // look for class definitions inside the code block
271 (varType=g_codeClassSDict->find(typeName)) ||
272 // otherwise look for global class definitions
273 (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,typeName,0,0,TRUE,TRUE))
274 ) && // and it must be a template
275 varType->templateArguments())
277 newDef = varType->getVariableInstance( templateArgs );
281 DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data()));
282 scope->append(lname, newDef);
286 // Doesn't seem to be a template. Try just the base name.
287 addVariable(typeName,name);
292 if (m_scopes.count()>0) // for local variables add a dummy entry so the name
293 // is hidden to avoid false links to global variables with the same name
294 // TODO: make this work for namespaces as well!
296 DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data()));
297 scope->append(lname,dummyContext);
301 DBG_CTX((stderr,"** addVariable: not adding variable!\n"));
306 ClassDef *VariableContext::findVariable(const QCString &name)
308 if (name.isEmpty()) return 0;
309 ClassDef *result = 0;
310 QListIterator<Scope> sli(m_scopes);
313 // search from inner to outer scope
314 for (sli.toLast();(scope=sli.current());--sli)
316 result = scope->find(key);
319 DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result));
323 // nothing found -> also try the global scope
324 result=m_globalScope.find(name);
325 DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result));
329 static VariableContext g_theVarContext;
330 const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8;
332 //-------------------------------------------------------------------
339 Ctx() : name(g_name), type(g_type), d(0) {}
347 m_defList.append(new Ctx);
348 m_defList.setAutoDelete(TRUE);
350 virtual ~CallContext() {}
351 void setScope(Definition *d)
353 Ctx *ctx = m_defList.getLast();
356 DBG_CTX((stderr,"** Set call context %s (%p)\n",d==0 ? "<null>" : d->name().data(),d));
362 m_defList.append(new Ctx);
363 DBG_CTX((stderr,"** Push call context %d\n",m_defList.count()));
367 if (m_defList.count()>1)
369 DBG_CTX((stderr,"** Pop call context %d\n",m_defList.count()));
370 Ctx *ctx = m_defList.getLast();
376 m_defList.removeLast();
380 DBG_CTX((stderr,"** ILLEGAL: Pop call context\n"));
385 DBG_CTX((stderr,"** Clear call context\n"));
387 m_defList.append(new Ctx);
389 Definition *getScope() const
391 Ctx *ctx = m_defList.getLast();
392 if (ctx) return ctx->d; else return 0;
396 QList<Ctx> m_defList;
399 static CallContext g_theCallContext;
401 //-------------------------------------------------------------------
403 /*! add class/namespace name s to the scope */
404 static void pushScope(const char *s)
406 g_classScopeLengthStack.push(new int(g_classScope.length()));
407 if (g_classScope.isEmpty() || leftScopeMatch(s,g_classScope))
413 g_classScope += "::";
416 //printf("pushScope(%s) result: `%s'\n",s,g_classScope.data());
419 /*! remove the top class/namespace name from the scope */
420 static void popScope()
422 if (!g_classScopeLengthStack.isEmpty())
424 int *pLength = g_classScopeLengthStack.pop();
425 g_classScope.truncate(*pLength);
430 //err("Too many end of scopes found!\n");
432 //printf("popScope() result: `%s'\n",g_classScope.data());
435 static void setCurrentDoc(const QCString &anchor)
437 if (Doxygen::searchIndex)
441 g_code->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
445 g_code->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
450 static void addToSearchIndex(const char *text)
452 if (Doxygen::searchIndex)
454 g_code->addWord(text,FALSE);
458 static void setClassScope(const QCString &name)
460 //printf("setClassScope(%s)\n",name.data());
462 n=n.simplifyWhiteSpace();
463 int ts=n.find('<'); // start of template
464 int te=n.findRev('>'); // end of template
465 //printf("ts=%d te=%d\n",ts,te);
466 if (ts!=-1 && te!=-1 && te>ts)
468 // remove template from scope
469 n=n.left(ts)+n.right(n.length()-te-1);
471 while (!g_classScopeLengthStack.isEmpty())
475 g_classScope.resize(0);
477 while ((i=n.find("::"))!=-1)
479 pushScope(n.left(i));
483 //printf("--->New class scope `%s'\n",g_classScope.data());
486 /*! start a new line of code, inserting a line number if g_sourceFileDef
487 * is TRUE. If a definition starts at the current line, then the line
488 * number is linked to the documentation of that definition.
490 static void startCodeLine()
492 //if (g_currentFontClass) { g_code->endFontClass(); }
493 if (g_sourceFileDef && g_lineNumbers)
495 //QCString lineNumber,lineAnchor;
496 //lineNumber.sprintf("%05d",g_yyLineNr);
497 //lineAnchor.sprintf("l%05d",g_yyLineNr);
499 Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
500 //printf("%s:startCodeLine(%d)=%p\n",g_sourceFileDef->name().data(),g_yyLineNr,d);
501 if (!g_includeCodeFragment && d)
503 g_currentDefinition = d;
504 g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
505 g_insideBody = FALSE;
506 g_searchingForBody = TRUE;
507 g_realScope = d->name();
512 g_parmType.resize(0);
513 g_parmName.resize(0);
514 //printf("Real scope: `%s'\n",g_realScope.data());
515 g_bodyCurlyCount = 0;
517 lineAnchor.sprintf("l%05d",g_yyLineNr);
518 if (g_currentMemberDef)
520 g_code->writeLineNumber(g_currentMemberDef->getReference(),
521 g_currentMemberDef->getOutputFileBase(),
522 g_currentMemberDef->anchor(),g_yyLineNr);
523 setCurrentDoc(lineAnchor);
525 else if (d->isLinkableInProject())
527 g_code->writeLineNumber(d->getReference(),
528 d->getOutputFileBase(),
530 setCurrentDoc(lineAnchor);
535 g_code->writeLineNumber(0,0,0,g_yyLineNr);
538 DBG_CTX((stderr,"startCodeLine(%d)\n",g_yyLineNr));
539 g_code->startCodeLine(g_sourceFileDef && g_lineNumbers);
540 if (g_currentFontClass)
542 g_code->startFontClass(g_currentFontClass);
547 static void endFontClass();
548 static void startFontClass(const char *s);
550 static void endCodeLine()
552 DBG_CTX((stderr,"endCodeLine(%d)\n",g_yyLineNr));
554 g_code->endCodeLine();
557 static void nextCodeLine()
559 const char * fc = g_currentFontClass;
561 if (g_yyLineNr<g_inputLines)
563 g_currentFontClass = fc;
568 /*! write a code fragment `text' that may span multiple lines, inserting
569 * line numbers for each line.
571 static void codifyLines(const char *text)
573 //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
574 const char *p=text,*sp=p;
580 while ((c=*p++) && c!='\n') { g_yyColNr++; }
586 int l = (int)(p-sp-1);
587 char *tmp = (char*)malloc(l+1);
602 /*! writes a link to a fragment \a text that may span multiple lines, inserting
603 * line numbers for each line. If \a text contains newlines, the link will be
604 * split into multiple links with the same destination, one for each line.
606 static void writeMultiLineCodeLink(CodeOutputInterface &ol,
610 static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
611 TooltipManager::instance()->addTooltip(d);
612 QCString ref = d->getReference();
613 QCString file = d->getOutputFileBase();
614 QCString anchor = d->anchor();
616 if (!sourceTooltips) // fall back to simple "title" tooltips
618 tooltip = d->briefDescriptionAsTooltip();
621 char *p=(char *)text;
626 while ((c=*p++) && c!='\n') { }
631 //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
632 ol.writeCodeLink(ref,file,anchor,sp,tooltip);
637 //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
638 ol.writeCodeLink(ref,file,anchor,sp,tooltip);
644 static void addType()
646 if (g_name=="const") { g_name.resize(0); return; }
647 if (!g_type.isEmpty()) g_type += ' ' ;
650 if (!g_type.isEmpty()) g_type += ' ' ;
655 static void addParmType()
657 if (g_parmName=="const") { g_parmName.resize(0); return; }
658 if (!g_parmType.isEmpty()) g_parmType += ' ' ;
659 g_parmType += g_parmName ;
660 g_parmName.resize(0) ;
663 static void addUsingDirective(const char *name)
665 if (g_sourceFileDef && name)
667 NamespaceDef *nd = Doxygen::namespaceSDict->find(name);
670 g_sourceFileDef->addUsingDirective(nd);
675 static void setParameterList(MemberDef *md)
677 g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : "";
678 ArgumentList *al = md->argumentList();
680 ArgumentListIterator it(*al);
682 for (;(a=it.current());++it)
684 g_parmName = a->name.copy();
685 g_parmType = a->type.copy();
686 int i = g_parmType.find('*');
687 if (i!=-1) g_parmType = g_parmType.left(i);
688 i = g_parmType.find('&');
689 if (i!=-1) g_parmType = g_parmType.left(i);
690 g_parmType.stripPrefix("const ");
691 g_parmType=g_parmType.stripWhiteSpace();
692 g_theVarContext.addVariable(g_parmType,g_parmName);
696 static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
702 while (extractClassNameFromType(type,pos,className,templSpec)!=-1)
704 QCString clName=className+templSpec;
706 if (!g_classScope.isEmpty())
708 cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName);
712 cd=getResolvedClass(d,g_sourceFileDef,clName);
714 //printf("stripClass trying `%s' = %p\n",clName.data(),cd);
724 static MemberDef *setCallContextForVar(const QCString &name)
726 if (name.isEmpty()) return 0;
727 DBG_CTX((stderr,"setCallContextForVar(%s) g_classScope=%s\n",name.data(),g_classScope.data()));
729 int scopeEnd = name.findRev("::");
730 if (scopeEnd!=-1) // name with explicit scope
732 QCString scope = name.left(scopeEnd);
733 QCString locName = name.right(name.length()-scopeEnd-2);
734 //printf("explicit scope: name=%s scope=%s\n",locName.data(),scope.data());
735 ClassDef *mcd = getClass(scope);
736 if (mcd && !locName.isEmpty())
738 MemberDef *md=mcd->getMemberByName(locName);
741 //printf("name=%s scope=%s\n",locName.data(),scope.data());
742 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
746 else // check namespace as well
748 NamespaceDef *mnd = getResolvedNamespace(scope);
749 if (mnd && !locName.isEmpty())
751 MemberDef *md=mnd->getMemberByName(locName);
754 //printf("name=%s scope=%s\n",locName.data(),scope.data());
755 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
763 ClassDef *mcd = g_theVarContext.findVariable(name);
764 if (mcd) // local variable
766 DBG_CTX((stderr,"local variable?\n"));
767 if (mcd!=VariableContext::dummyContext)
769 DBG_CTX((stderr,"local var `%s' mcd=%s\n",name.data(),mcd->name().data()));
770 g_theCallContext.setScope(mcd);
775 DBG_CTX((stderr,"class member? scope=%s\n",g_classScope.data()));
776 // look for a class member
777 mcd = getClass(g_classScope);
780 DBG_CTX((stderr,"Inside class %s\n",mcd->name().data()));
781 MemberDef *md=mcd->getMemberByName(name);
784 DBG_CTX((stderr,"Found member %s\n",md->name().data()));
785 if (g_scopeStack.top()!=CLASSBLOCK)
787 DBG_CTX((stderr,"class member `%s' mcd=%s\n",name.data(),mcd->name().data()));
788 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
795 // look for a global member
796 if ((mn=Doxygen::functionNameSDict->find(name)))
798 //printf("global var `%s'\n",name.data());
799 if (mn->count()==1) // global defined only once
801 MemberDef *md=mn->getFirst();
802 if (!md->isStatic() || md->getBodyDef()==g_sourceFileDef)
804 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
809 else if (mn->count()>1) // global defined more than once
811 MemberNameIterator it(*mn);
813 for (;(md=it.current());++it)
815 //printf("mn=%p md=%p md->getBodyDef()=%p g_sourceFileDef=%p\n",
817 // md->getBodyDef(),g_sourceFileDef);
819 // in case there are multiple members we could link to, we
820 // only link to members if defined in the same file or
821 // defined as external.
822 if ((!md->isStatic() || md->getBodyDef()==g_sourceFileDef) &&
823 (g_forceTagReference.isEmpty() || g_forceTagReference==md->getReference())
826 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
827 //printf("returning member %s in source file %s\n",md->name().data(),g_sourceFileDef->name().data());
837 static void updateCallContextForSmartPointer()
839 Definition *d = g_theCallContext.getScope();
840 //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : "<none>");
842 if (d && d->definitionType()==Definition::TypeClass && (md=((ClassDef*)d)->isSmartPointer()))
844 ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope());
847 g_theCallContext.setScope(ncd);
848 //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data());
853 static bool getLinkInScope(const QCString &c, // scope
854 const QCString &m, // member
855 const char *memberText, // exact text
856 CodeOutputInterface &ol,
866 DBG_CTX((stderr,"getLinkInScope: trying `%s'::`%s' varOnly=%d\n",c.data(),m.data(),varOnly));
867 if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef,FALSE,g_forceTagReference) &&
868 (!varOnly || md->isVariable()))
870 if (md->isLinkable())
872 //printf("found it %s!\n",md->qualifiedName().data());
876 anchor.sprintf("a%d",g_anchorCount);
877 //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
878 // g_exampleFile.data());
879 if (md->addExample(anchor,g_exampleName,g_exampleFile))
881 ol.writeCodeAnchor(anchor);
886 Definition *d = md->getOuterScope()==Doxygen::globalScope ?
887 md->getFileDef() : md->getOuterScope();
888 if (md->getGroupDef()) d = md->getGroupDef();
889 if (d && d->isLinkable())
891 g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
892 //printf("g_currentDefinition=%p g_currentMemberDef=%p g_insideBody=%d\n",
893 // g_currentDefinition,g_currentMemberDef,g_insideBody);
895 if (g_currentDefinition && g_currentMemberDef &&
896 md!=g_currentMemberDef && g_insideBody && g_collectXRefs)
898 addDocCrossReference(g_currentMemberDef,md);
900 //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());
902 writeMultiLineCodeLink(ol,md, text ? text : memberText);
903 addToSearchIndex(text ? text : memberText);
907 else // found member, but is is not linkable, so make sure content inside is not assign
908 // to the previous member, see bug762760
910 DBG_CTX((stderr,"unlinkable member %s\n",md->name().data()));
911 g_currentMemberDef = 0;
917 static bool getLink(const char *className,
918 const char *memberName,
919 CodeOutputInterface &ol,
923 //printf("getLink(%s,%s) g_curClassName=%s\n",className,memberName,g_curClassName.data());
924 QCString m=removeRedundantWhiteSpace(memberName);
925 QCString c=className;
926 if (!getLinkInScope(c,m,memberName,ol,text,varOnly))
928 if (!g_curClassName.isEmpty())
930 if (!c.isEmpty()) c.prepend("::");
931 c.prepend(g_curClassName);
932 return getLinkInScope(c,m,memberName,ol,text,varOnly);
939 static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName,
940 bool typeOnly=FALSE,bool varOnly=FALSE)
943 if (*clName=='~') // correct for matching negated values i.s.o. destructors.
948 QCString className=clName;
949 if (className.isEmpty()) return;
950 if (g_insideProtocolList) // for Obj-C
956 className = substitute(className,"\\","::"); // for PHP namespaces
958 else if (g_insideCS || g_insideJava)
960 className = substitute(className,".","::"); // for PHP namespaces
962 ClassDef *cd=0,*lcd=0;
966 //printf("generateClassOrGlobalLink(className=%s)\n",className.data());
967 if (!g_prefixed_with_this_keyword || (lcd=g_theVarContext.findVariable(className))==0) // not a local variable
969 Definition *d = g_currentDefinition;
970 //printf("d=%s g_sourceFileDef=%s\n",d?d->name().data():"<none>",g_sourceFileDef?g_sourceFileDef->name().data():"<none>");
971 cd = getResolvedClass(d,g_sourceFileDef,className,&md);
972 DBG_CTX((stderr,"non-local variable name=%s context=%d cd=%s md=%s!\n",
973 className.data(),g_theVarContext.count(),cd?cd->name().data():"<none>",
974 md?md->name().data():"<none>"));
975 if (cd==0 && md==0 && (i=className.find('<'))!=-1)
977 QCString bareName = className.left(i); //stripTemplateSpecifiersFromScope(className);
978 DBG_CTX((stderr,"bareName=%s\n",bareName.data()));
979 if (bareName!=className)
981 cd=getResolvedClass(d,g_sourceFileDef,bareName,&md); // try unspecialized version
984 NamespaceDef *nd = getResolvedNamespace(className);
987 g_theCallContext.setScope(nd);
988 addToSearchIndex(className);
989 writeMultiLineCodeLink(*g_code,nd,clName);
992 //printf("md=%s\n",md?md->name().data():"<none>");
993 DBG_CTX((stderr,"is found as a type cd=%s nd=%s\n",
994 cd?cd->name().data():"<null>",
995 nd?nd->name().data():"<null>"));
996 if (cd==0 && md==0) // also see if it is variable or enum or enum value
998 if (getLink(g_classScope,clName,ol,clName,varOnly))
1006 //printf("local variable!\n");
1007 if (lcd!=VariableContext::dummyContext)
1009 //printf("non-dummy context lcd=%s!\n",lcd->name().data());
1010 g_theCallContext.setScope(lcd);
1012 // to following is needed for links to a global variable, but is
1013 // no good for a link to a local variable that is also a global symbol.
1015 //if (getLink(g_classScope,clName,ol,clName))
1021 DBG_CTX((stderr,"is a local variable cd=%p!\n",cd));
1023 g_prefixed_with_this_keyword = FALSE; // discard the "this" prefix for the next calls
1025 if (cd && cd->isLinkable()) // is it a linkable class
1027 DBG_CTX((stderr,"is linkable class %s\n",clName));
1031 anchor.sprintf("_a%d",g_anchorCount);
1032 //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
1033 // g_exampleFile.data());
1034 if (cd->addExample(anchor,g_exampleName,g_exampleFile))
1036 ol.writeCodeAnchor(anchor);
1040 writeMultiLineCodeLink(ol,cd,clName);
1041 addToSearchIndex(className);
1042 g_theCallContext.setScope(cd);
1045 Definition *d = md->getOuterScope()==Doxygen::globalScope ?
1046 md->getFileDef() : md->getOuterScope();
1047 if (md->getGroupDef()) d = md->getGroupDef();
1048 if (d && d->isLinkable() && md->isLinkable() &&
1049 g_currentMemberDef && g_collectXRefs)
1051 addDocCrossReference(g_currentMemberDef,md);
1055 else // not a class, maybe a global member
1057 DBG_CTX((stderr,"class %s not linkable! cd=%p md=%p typeOnly=%d\n",clName,cd,md,typeOnly));
1058 if (!isLocal && (md!=0 || (cd==0 && !typeOnly))) // not a class, see if it is a global enum/variable/typedef.
1060 if (md==0) // not found as a typedef
1062 md = setCallContextForVar(clName);
1063 //printf("setCallContextForVar(%s) md=%p g_currentDefinition=%p\n",clName,md,g_currentDefinition);
1064 if (md && g_currentDefinition)
1066 DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n",
1067 md->name().data(),g_currentDefinition->name().data(),
1068 isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md),
1069 md->getOuterScope()->name().data()));
1072 if (md && g_currentDefinition &&
1073 isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md)==-1)
1075 md=0; // variable not accessible
1078 if (md && (!varOnly || md->isVariable()))
1080 DBG_CTX((stderr,"is a global md=%p g_currentDefinition=%s linkable=%d\n",md,g_currentDefinition?g_currentDefinition->name().data():"<none>",md->isLinkable()));
1081 if (md->isLinkable())
1084 if (!g_forceTagReference.isEmpty()) // explicit reference to symbol in tag file
1086 text=g_forceTagReference;
1087 if (text.right(4)==".tag") // strip .tag if present
1089 text=text.left(text.length()-4);
1091 text+=getLanguageSpecificSeparator(md->getLanguage());
1094 md->setLocalName(text);
1096 else // normal reference
1100 writeMultiLineCodeLink(ol,md,text);
1101 addToSearchIndex(clName);
1102 if (g_currentMemberDef && g_collectXRefs)
1104 addDocCrossReference(g_currentMemberDef,md);
1111 // nothing found, just write out the word
1112 DBG_CTX((stderr,"not found!\n"));
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 DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass));
1142 g_theCallContext.setScope(typeClass);
1144 Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
1145 xmd->getFileDef() : 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 && g_collectXRefs)
1160 addDocCrossReference(g_currentMemberDef,xmd);
1163 // write the actual link
1164 writeMultiLineCodeLink(ol,xmd,memName);
1165 addToSearchIndex(memName);
1173 static bool generateClassMemberLink(CodeOutputInterface &ol,Definition *def,const char *memName)
1175 if (def && def->definitionType()==Definition::TypeClass)
1177 ClassDef *cd = (ClassDef*)def;
1178 MemberDef *xmd = cd->getMemberByName(memName);
1179 //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd);
1182 return generateClassMemberLink(ol,xmd,memName);
1186 Definition *innerDef = cd->findInnerCompound(memName);
1189 g_theCallContext.setScope(innerDef);
1190 addToSearchIndex(memName);
1191 writeMultiLineCodeLink(*g_code,innerDef,memName);
1196 else if (def && def->definitionType()==Definition::TypeNamespace)
1198 NamespaceDef *nd = (NamespaceDef*)def;
1199 //printf("Looking for %s inside namespace %s\n",memName,nd->name().data());
1200 Definition *innerDef = nd->findInnerCompound(memName);
1203 g_theCallContext.setScope(innerDef);
1204 addToSearchIndex(memName);
1205 writeMultiLineCodeLink(*g_code,innerDef,memName);
1212 static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName,
1215 //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n",
1216 // varName.data(),memName,g_classScope.data());
1218 if (varName.isEmpty()) return;
1220 // look for the variable in the current context
1221 ClassDef *vcd = g_theVarContext.findVariable(varName);
1224 if (vcd!=VariableContext::dummyContext)
1226 //printf("Class found!\n");
1227 if (getLink(vcd->name(),memName,ol))
1229 //printf("Found result!\n");
1232 if (vcd->baseClasses())
1234 BaseClassListIterator bcli(*vcd->baseClasses());
1235 for ( ; bcli.current() ; ++bcli)
1237 if (getLink(bcli.current()->classDef->name(),memName,ol))
1239 //printf("Found result!\n");
1246 else // variable not in current context, maybe it is in a parent context
1248 vcd = getResolvedClass(g_currentDefinition,g_sourceFileDef,g_classScope);
1249 if (vcd && vcd->isLinkable())
1251 //printf("Found class %s for variable `%s'\n",g_classScope.data(),varName.data());
1252 MemberName *vmn=Doxygen::memberNameSDict->find(varName);
1256 QCString vn=varName;
1257 if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1) // explicit scope A::b(), probably static member
1259 ClassDef *jcd = getClass(vn.left(vi));
1260 vn=vn.right(vn.length()-vi-2);
1261 vmn=Doxygen::memberNameSDict->find(vn);
1262 //printf("Trying name `%s' scope=%s\n",vn.data(),scope.data());
1265 MemberNameIterator vmni(*vmn);
1267 for (;(vmd=vmni.current());++vmni)
1269 if (/*(vmd->isVariable() || vmd->isFunction()) && */
1270 vmd->getClassDef()==jcd)
1272 //printf("Found variable type=%s\n",vmd->typeString());
1273 ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1274 if (mcd && mcd->isLinkable())
1276 if (generateClassMemberLink(ol,mcd,memName)) return;
1285 //printf("There is a variable with name `%s'\n",varName);
1286 MemberNameIterator vmni(*vmn);
1288 for (;(vmd=vmni.current());++vmni)
1290 if (/*(vmd->isVariable() || vmd->isFunction()) && */
1291 vmd->getClassDef()==vcd)
1293 //printf("Found variable type=%s\n",vmd->typeString());
1294 ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
1295 if (mcd && mcd->isLinkable())
1297 if (generateClassMemberLink(ol,mcd,memName)) return;
1304 // nothing found -> write result as is
1305 codifyLines(memName);
1306 addToSearchIndex(memName);
1310 static void generatePHPVariableLink(CodeOutputInterface &ol,const char *varName)
1312 QCString name = varName+7; // strip $this->
1314 //printf("generatePHPVariableLink(%s) name=%s scope=%s\n",varName,name.data(),g_classScope.data());
1315 if (!getLink(g_classScope,name,ol,varName))
1317 codifyLines(varName);
1321 static void generateFunctionLink(CodeOutputInterface &ol,const char *funcName)
1323 //CodeClassDef *ccd=0;
1325 QCString locScope=g_classScope;
1326 QCString locFunc=removeRedundantWhiteSpace(funcName);
1328 QCString funcWithScope=locFunc;
1329 QCString funcWithFullScope=locFunc;
1330 QCString fullScope=locScope;
1331 DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data()));
1333 int i=locFunc.findRev("::");
1334 if (g_currentMemberDef && g_currentMemberDef->getClassDef() &&
1335 funcName==g_currentMemberDef->localName() &&
1336 g_currentMemberDef->getDefLine()==g_yyLineNr &&
1337 generateClassMemberLink(ol,g_currentMemberDef,funcName)
1340 // special case where funcName is the name of a method that is also
1341 // defined on this line. In this case we can directly link to
1342 // g_currentMemberDef, which is not only faster, but
1343 // in case of overloaded methods, this will make sure that we link to
1344 // the correct method, and thereby get the correct reimplemented relations.
1345 // See also bug 549022.
1348 if (i==-1) i=locFunc.findRev("."),len=1;
1349 if (i==-1) i=locFunc.findRev("\\"),len=1; // for PHP
1352 funcScope=locFunc.left(i);
1353 locFunc=locFunc.right(locFunc.length()-i-len).stripWhiteSpace();
1354 int ts=locScope.find('<'); // start of template
1355 int te=locScope.findRev('>'); // end of template
1356 //printf("ts=%d te=%d\n",ts,te);
1357 if (ts!=-1 && te!=-1 && te>ts)
1359 // remove template from scope
1360 locScope=locScope.left(ts)+locScope.right(locScope.length()-te-1);
1362 ts=funcScope.find('<'); // start of template
1363 te=funcScope.findRev('>'); // end of template
1364 //printf("ts=%d te=%d\n",ts,te);
1365 if (ts!=-1 && te!=-1 && te>ts)
1367 // remove template from scope
1368 funcScope=funcScope.left(ts)+funcScope.right(funcScope.length()-te-1);
1370 if (!funcScope.isEmpty())
1372 funcWithScope = funcScope+"::"+locFunc;
1373 if (!locScope.isEmpty())
1375 fullScope=locScope+"::"+funcScope;
1378 if (!locScope.isEmpty())
1380 funcWithFullScope = locScope+"::"+funcWithScope;
1383 if (!fullScope.isEmpty() && (ccd=g_codeClassSDict->find(fullScope)))
1385 //printf("using classScope %s\n",g_classScope.data());
1386 if (ccd->baseClasses())
1388 BaseClassListIterator bcli(*ccd->baseClasses());
1389 for ( ; bcli.current() ; ++bcli)
1391 if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName))
1398 if (!locScope.isEmpty() && fullScope!=locScope && (ccd=g_codeClassSDict->find(locScope)))
1400 //printf("using classScope %s\n",g_classScope.data());
1401 if (ccd->baseClasses())
1403 BaseClassListIterator bcli(*ccd->baseClasses());
1404 for ( ; bcli.current() ; ++bcli)
1406 if (getLink(bcli.current()->classDef->name(),funcWithScope,ol,funcName))
1413 if (!getLink(locScope,funcWithScope,ol,funcName))
1415 generateClassOrGlobalLink(ol,funcName);
1418 g_forceTagReference.resize(0);
1422 /*! counts the number of lines in the input */
1423 static int countLines()
1425 const char *p=g_inputString;
1431 if (c=='\n') count++;
1433 if (p>g_inputString && *(p-1)!='\n')
1434 { // last line does not end with a \n, so we add an extra
1435 // line and explicitly terminate the line after parsing.
1437 g_needsTermination=TRUE;
1442 static void endFontClass()
1444 if (g_currentFontClass)
1446 g_code->endFontClass();
1447 g_currentFontClass=0;
1451 static void startFontClass(const char *s)
1454 g_code->startFontClass(s);
1455 g_currentFontClass=s;
1458 //----------------------------------------------------------------------------
1460 // recursively writes a linkified Objective-C method call
1461 static void writeObjCMethodCall(ObjCCallCtx *ctx)
1465 const char *p = ctx->format.data();
1466 if (!ctx->methodName.isEmpty())
1468 //printf("writeObjCMethodCall(%s) obj=%s method=%s\n",
1469 // ctx->format.data(),ctx->objectTypeOrName.data(),ctx->methodName.data());
1470 if (!ctx->objectTypeOrName.isEmpty() && ctx->objectTypeOrName.at(0)!='$')
1472 //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(),
1473 // ctx->methodName.data());
1474 ClassDef *cd = g_theVarContext.findVariable(ctx->objectTypeOrName);
1475 if (cd==0) // not a local variable
1477 if (ctx->objectTypeOrName=="self")
1479 if (g_currentDefinition &&
1480 g_currentDefinition->definitionType()==Definition::TypeClass)
1482 ctx->objectType = (ClassDef *)g_currentDefinition;
1487 ctx->objectType = getResolvedClass(
1488 g_currentDefinition,
1490 ctx->objectTypeOrName,
1493 //printf(" object is class? %p\n",ctx->objectType);
1494 if (ctx->objectType) // found class
1496 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1497 //printf(" yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>");
1499 else if (ctx->method==0) // search for class variable with the same name
1502 //printf("g_currentDefinition=%p\n",g_currentDefinition);
1503 if (g_currentDefinition &&
1504 g_currentDefinition->definitionType()==Definition::TypeClass)
1506 ctx->objectVar = ((ClassDef *)g_currentDefinition)->getMemberByName(ctx->objectTypeOrName);
1507 //printf(" ctx->objectVar=%p\n",ctx->objectVar);
1510 ctx->objectType = stripClassName(ctx->objectVar->typeString());
1511 //printf(" ctx->objectType=%p\n",ctx->objectType);
1512 if (ctx->objectType)
1514 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1515 //printf(" ctx->method=%p\n",ctx->method);
1521 else // local variable
1523 //printf(" object is local variable\n");
1524 if (cd!=VariableContext::dummyContext)
1526 ctx->method = cd->getMemberByName(ctx->methodName);
1527 //printf(" class=%p method=%p\n",cd,ctx->method);
1534 while ((c=*p++)) // for each character in ctx->format
1539 if (nc=='$') // escaped $
1541 g_code->codify("$");
1543 else // name fragment or reference to a nested call
1545 if (nc=='n') // name fragment
1549 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1551 int refId=refIdStr.toInt();
1552 QCString *pName = g_nameDict.find(refId);
1555 if (ctx->method && ctx->method->isLinkable())
1557 writeMultiLineCodeLink(*g_code,ctx->method,pName->data());
1558 if (g_currentMemberDef && g_collectXRefs)
1560 addDocCrossReference(g_currentMemberDef,ctx->method);
1565 codifyLines(pName->data());
1570 //printf("Invalid name: id=%d\n",refId);
1573 else if (nc=='o') // reference to potential object name
1577 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1579 int refId=refIdStr.toInt();
1580 QCString *pObject = g_objectDict.find(refId);
1583 if (*pObject=="self")
1585 if (g_currentDefinition &&
1586 g_currentDefinition->definitionType()==Definition::TypeClass)
1588 ctx->objectType = (ClassDef *)g_currentDefinition;
1589 if (ctx->objectType->categoryOf())
1591 ctx->objectType = ctx->objectType->categoryOf();
1593 if (ctx->objectType)
1595 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1598 startFontClass("keyword");
1599 codifyLines(pObject->data());
1602 else if (*pObject=="super")
1604 if (g_currentDefinition &&
1605 g_currentDefinition->definitionType()==Definition::TypeClass)
1607 ClassDef *cd = (ClassDef *)g_currentDefinition;
1608 if (cd->categoryOf())
1610 cd = cd->categoryOf();
1612 BaseClassList *bcd = cd->baseClasses();
1613 if (bcd) // get direct base class (there should be only one)
1615 BaseClassListIterator bli(*bcd);
1616 BaseClassDef *bclass;
1617 for (bli.toFirst();(bclass=bli.current());++bli)
1619 if (bclass->classDef->compoundType()!=ClassDef::Protocol)
1621 ctx->objectType = bclass->classDef;
1622 if (ctx->objectType)
1624 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1630 startFontClass("keyword");
1631 codifyLines(pObject->data());
1634 else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable
1636 writeMultiLineCodeLink(*g_code,ctx->objectVar,pObject->data());
1637 if (g_currentMemberDef && g_collectXRefs)
1639 addDocCrossReference(g_currentMemberDef,ctx->objectVar);
1642 else if (ctx->objectType &&
1643 ctx->objectType!=VariableContext::dummyContext &&
1644 ctx->objectType->isLinkable()
1645 ) // object is class name
1647 ClassDef *cd = ctx->objectType;
1648 writeMultiLineCodeLink(*g_code,cd,pObject->data());
1650 else // object still needs to be resolved
1652 ClassDef *cd = getResolvedClass(g_currentDefinition,
1653 g_sourceFileDef, *pObject);
1654 if (cd && cd->isLinkable())
1656 if (ctx->objectType==0) ctx->objectType=cd;
1657 writeMultiLineCodeLink(*g_code,cd,pObject->data());
1661 codifyLines(pObject->data());
1667 //printf("Invalid object: id=%d\n",refId);
1670 else if (nc=='c') // reference to nested call
1674 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1676 int refId=refIdStr.toInt();
1677 ObjCCallCtx *ictx = g_contextDict.find(refId);
1678 if (ictx) // recurse into nested call
1680 writeObjCMethodCall(ictx);
1681 if (ictx->method) // link to nested call successfully
1683 // get the ClassDef representing the method's return type
1684 if (QCString(ictx->method->typeString())=="id")
1686 // see if the method name is unique, if so we link to it
1687 MemberName *mn=Doxygen::memberNameSDict->find(ctx->methodName);
1688 //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n",
1689 // mn==0?-1:(int)mn->count(),
1690 // ictx->method->name().data(),
1691 // ctx->methodName.data());
1692 if (mn && mn->count()==1) // member name unique
1694 ctx->method = mn->getFirst();
1699 ctx->objectType = stripClassName(ictx->method->typeString());
1700 if (ctx->objectType)
1702 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
1705 //printf(" ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType);
1710 //printf("Invalid context: id=%d\n",refId);
1713 else if (nc=='w') // some word
1717 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1719 int refId=refIdStr.toInt();
1720 QCString *pWord = g_wordDict.find(refId);
1723 codifyLines(pWord->data());
1726 else if (nc=='d') // comment block
1730 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
1732 int refId=refIdStr.toInt();
1733 QCString *pComment = g_commentDict.find(refId);
1736 startFontClass("comment");
1737 codifyLines(pComment->data());
1741 else // illegal marker
1743 ASSERT(!"invalid escape sequence");
1747 else // normal non-marker character
1754 //printf("%s %s]\n",ctx->objectTypeOrName.data(),ctx->methodName.data());
1755 //printf("}=(type='%s',name='%s')",
1756 // ctx->objectTypeOrName.data(),
1757 // ctx->methodName.data());
1760 // Replaces an Objective-C method name fragment s by a marker of the form
1761 // $n12, the number (12) can later be used as a key for obtaining the name
1762 // fragment, from g_nameDict
1763 static QCString escapeName(const char *s)
1766 result.sprintf("$n%d",g_currentNameId);
1767 g_nameDict.insert(g_currentNameId,new QCString(s));
1772 static QCString escapeObject(const char *s)
1775 result.sprintf("$o%d",g_currentObjId);
1776 g_objectDict.insert(g_currentObjId,new QCString(s));
1781 static QCString escapeWord(const char *s)
1784 result.sprintf("$w%d",g_currentWordId);
1785 g_wordDict.insert(g_currentWordId,new QCString(s));
1790 static QCString escapeComment(const char *s)
1793 result.sprintf("$d%d",g_currentCommentId);
1794 g_commentDict.insert(g_currentCommentId,new QCString(s));
1795 g_currentCommentId++;
1799 /* -----------------------------------------------------------------
1802 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
1804 static int yyread(char *buf,int max_size)
1807 while( c < max_size && g_inputString[g_inputPosition] )
1809 *buf = g_inputString[g_inputPosition++] ;
1819 ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
1821 SCOPENAME ({SEP}{BN}*)?({ID}{BN}*{SEP}{BN}*)*("~"{BN}*)?{ID}
1822 TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">"
1823 SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?{SEP}{BN}*)*)((~{BN}*)?{ID})
1824 SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*{SEP}{BN}*)+
1825 KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property")
1826 KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"set"|"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})
1827 FLOWKW ("break"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"return"|"switch"|"throw"|"throws"|"@catch"|"@finally")
1828 FLOWCONDITION ("case"|"for"|"foreach"|"for each"|"goto"|"if"|"try"|"while"|"@try")
1829 TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
1830 CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast")
1831 CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'"))
1832 ARITHOP "+"|"-"|"/"|"*"|"%"|"--"|"++"
1833 ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|="
1834 LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"
1835 BITOP "&"|"|"|"^"|"<<"|">>"|"~"
1836 OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
1837 RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"("
1838 RAWEND ")"[^ \t\(\)\\]{0,16}\"
1848 %x RemoveSpecialCComment
1849 %x StripSpecialCComment
1860 %x CppCliTypeModifierFollowup
1882 <Body>^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") {
1883 startFontClass("preprocessor");
1884 g_code->codify(yytext);
1885 BEGIN( ReadInclude );
1887 <Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ {
1889 startFontClass("keyword");
1890 codifyLines(yytext);
1892 if (!g_insideTemplate)
1895 <Body>(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") {
1896 if (g_insideTemplate) REJECT;
1897 startFontClass("keyword");
1898 codifyLines(yytext);
1902 <Body>"property"|"event"/{BN}* {
1903 if (g_insideTemplate) REJECT;
1904 startFontClass("keyword");
1905 codifyLines(yytext);
1908 <Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ {
1909 startFontClass("keyword");
1910 codifyLines(yytext);
1912 if (!g_insideTemplate)
1915 <Body>("package")[ \t\n]+ {
1916 startFontClass("keyword");
1917 codifyLines(yytext);
1919 BEGIN( PackageName );
1922 if (!g_insideObjC) REJECT;
1923 codifyLines(yytext);
1926 <Body,ClassVar,Bases>"-"|"+" {
1927 if (!g_insideObjC || g_insideBody)
1929 g_code->codify(yytext);
1931 else // Start of Objective-C method
1933 //printf("Method!\n");
1934 g_code->codify(yytext);
1939 g_code->codify(yytext);
1943 g_code->codify(yytext);
1944 BEGIN(ObjCParamType);
1946 <ObjCParams,ObjCMethod>";"|"{" {
1947 g_code->codify(yytext);
1950 if (g_searchingForBody)
1952 g_searchingForBody=FALSE;
1955 if (g_insideBody) g_bodyCurlyCount++;
1956 if (!g_curClassName.isEmpty()) // valid class name
1958 pushScope(g_curClassName);
1959 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
1960 g_scopeStack.push(SCOPEBLOCK);
1967 <ObjCParams>{ID}{B}*":" {
1968 g_code->codify(yytext);
1970 <ObjCParamType>{TYPEKW} {
1971 startFontClass("keywordtype");
1972 g_code->codify(yytext);
1976 <ObjCParamType>{ID} {
1977 generateClassOrGlobalLink(*g_code,yytext);
1980 <ObjCParamType>")" {
1981 g_code->codify(yytext);
1985 g_code->codify(yytext);
1987 g_theVarContext.addVariable(g_parmType,g_parmName);
1988 g_parmType.resize(0);g_parmName.resize(0);
1990 <ObjCMethod,ObjCParams,ObjCParamType>{ID} {
1991 generateClassOrGlobalLink(*g_code,yytext);
1993 <ObjCMethod,ObjCParams,ObjCParamType>. {
1994 g_code->codify(yytext);
1996 <ObjCMethod,ObjCParams,ObjCParamType>\n {
1997 codifyLines(yytext);
1999 <ReadInclude>[^\n\"\>]+/(">"|"\"") {
2003 //QCString absPath = yytext;
2004 //if (g_sourceFileDef && QDir::isRelativePath(absPath))
2006 // absPath = QDir::cleanDirPath(g_sourceFileDef->getPath()+"/"+absPath);
2009 FileDef *fd=findFileDef(Doxygen::inputNameDict,yytext,ambig);
2010 //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd);
2011 if (fd && fd->isLinkable())
2013 if (ambig) // multiple input files match the name
2015 //printf("===== yes %s is ambiguous\n",yytext);
2016 QCString name = QDir::cleanDirPath(yytext).utf8();
2017 if (!name.isEmpty() && g_sourceFileDef)
2019 FileName *fn = Doxygen::inputNameDict->find(name);
2022 FileNameIterator fni(*fn);
2023 // for each include name
2024 for (fni.toFirst();!found && (fd=fni.current());++fni)
2026 // see if this source file actually includes the file
2027 found = g_sourceFileDef->isIncluded(fd->absFilePath());
2028 //printf(" include file %s found=%d\n",fd->absFilePath().data(),found);
2033 else // not ambiguous
2038 //printf(" include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found);
2041 writeMultiLineCodeLink(*g_code,fd,yytext);
2045 g_code->codify(yytext);
2050 g_code->codify(text);
2054 <Body,Bases>^[ \t]*"#" {
2055 startFontClass("preprocessor");
2056 g_lastSkipCppContext = YY_START;
2057 g_code->codify(yytext);
2061 g_code->codify(yytext);
2063 <SkipCPP>[^\n\/\\]+ {
2064 g_code->codify(yytext);
2066 <SkipCPP>\\[\r]?\n {
2067 codifyLines(yytext);
2070 g_code->codify(yytext);
2072 <Body,FuncCall>"{" {
2073 g_theVarContext.pushScope();
2075 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2076 g_scopeStack.push(INNERBLOCK);
2078 if (g_searchingForBody)
2080 g_searchingForBody=FALSE;
2083 g_code->codify(yytext);
2092 <Body,FuncCall,MemberCall,MemberCall2>"}" {
2093 g_theVarContext.popScope();
2097 int *scope = g_scopeStack.pop();
2098 DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2099 if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
2104 g_code->codify(yytext);
2106 DBG_CTX((stderr,"g_bodyCurlyCount=%d\n",g_bodyCurlyCount));
2107 if (--g_bodyCurlyCount<=0)
2110 g_currentMemberDef=0;
2111 if (g_currentDefinition)
2112 g_currentDefinition=g_currentDefinition->getOuterScope();
2116 <Body,ClassVar>"@end" {
2117 //printf("End of objc scope fd=%s\n",g_sourceFileDef->name().data());
2118 if (g_sourceFileDef)
2120 FileDef *fd=g_sourceFileDef;
2121 g_insideObjC = fd->name().lower().right(2)==".m" ||
2122 fd->name().lower().right(3)==".mm";
2123 //printf("insideObjC=%d\n",g_insideObjC);
2127 g_insideObjC = FALSE;
2131 g_theVarContext.popScope();
2133 int *scope = g_scopeStack.pop();
2134 DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
2135 if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
2142 startFontClass("keyword");
2143 g_code->codify(yytext);
2146 g_currentMemberDef=0;
2147 if (g_currentDefinition)
2148 g_currentDefinition=g_currentDefinition->getOuterScope();
2151 <ClassName,ClassVar>";" {
2152 g_code->codify(yytext);
2153 g_searchingForBody=FALSE;
2156 <ClassName,ClassVar>[*&^%]+ {
2157 g_type=g_curClassName.copy();
2159 g_code->codify(yytext);
2160 BEGIN( Body ); // variable of type struct *
2162 <ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")" {
2163 startFontClass("keyword");
2164 g_code->codify(yytext);
2167 <ClassName>{ID}("::"{ID})* {
2168 g_curClassName=yytext;
2170 if (g_curClassName=="alignas")
2172 startFontClass("keyword");
2173 g_code->codify(yytext);
2179 generateClassOrGlobalLink(*g_code,yytext);
2185 g_code->codify(yytext);
2186 BEGIN( AlignAsEnd );
2188 <AlignAs>\n { g_yyLineNr++;
2189 codifyLines(yytext);
2191 <AlignAs>. { g_code->codify(yytext); }
2192 <AlignAsEnd>"(" { g_code->codify(yytext);
2196 g_code->codify(yytext);
2197 if (--g_bracketCount<=0)
2202 <AlignAsEnd>\n { g_yyLineNr++;
2203 codifyLines(yytext);
2205 <AlignAsEnd>. { g_code->codify(yytext); }
2206 <ClassName>{ID}("\\"{ID})* { // PHP namespace
2207 g_curClassName=substitute(yytext,"\\","::");
2208 g_scopeStack.push(CLASSBLOCK);
2209 pushScope(g_curClassName);
2211 generateClassOrGlobalLink(*g_code,yytext);
2214 <ClassName>{ID}{B}*"("{ID}")" { // Obj-C category
2215 g_curClassName=removeRedundantWhiteSpace(yytext);
2216 g_scopeStack.push(CLASSBLOCK);
2217 pushScope(g_curClassName);
2219 generateClassOrGlobalLink(*g_code,yytext);
2222 <PackageName>{ID}("."{ID})* {
2223 g_curClassName=substitute(yytext,".","::");
2224 //printf("found package: %s\n",g_curClassName.data());
2226 codifyLines(yytext);
2232 <ClassVar>("extends"|"implements") { // Java
2233 startFontClass("keyword");
2234 codifyLines(yytext);
2236 g_curClassBases.clear();
2239 <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") {
2240 DBG_CTX((stderr,"***** C++/CLI modifier %s on g_curClassName=%s\n",yytext,g_curClassName.data()));
2241 startFontClass("keyword");
2242 codifyLines(yytext);
2244 BEGIN( CppCliTypeModifierFollowup );
2247 g_type = g_curClassName.copy();
2251 g_theVarContext.addVariable(g_type,g_name);
2253 generateClassOrGlobalLink(*g_code,yytext);
2255 <ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* {
2256 codifyLines(yytext);
2257 g_curClassBases.clear();
2260 <PackageName>[ \t]*";" |
2261 <Bases>^{B}*/"@"{ID} | // Objective-C interface
2262 <Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* {
2263 g_theVarContext.pushScope();
2264 g_code->codify(yytext);
2265 if (YY_START==ClassVar && g_curClassName.isEmpty())
2267 g_curClassName = g_name.copy();
2269 if (g_searchingForBody)
2271 g_searchingForBody=FALSE;
2274 if (g_insideBody) g_bodyCurlyCount++;
2275 if (!g_curClassName.isEmpty()) // valid class name
2277 DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2278 g_scopeStack.push(CLASSBLOCK);
2279 pushScope(g_curClassName);
2280 DBG_CTX((stderr,"***** g_curClassName=%s\n",g_curClassName.data()));
2281 if (getResolvedClass(g_currentDefinition,g_sourceFileDef,g_curClassName)==0)
2283 DBG_CTX((stderr,"Adding new class %s\n",g_curClassName.data()));
2284 ClassDef *ncd=new ClassDef("<code>",1,1,
2285 g_curClassName,ClassDef::Class,0,0,FALSE);
2286 g_codeClassSDict->append(g_curClassName,ncd);
2287 // insert base classes.
2288 char *s=g_curClassBases.first();
2292 bcd=g_codeClassSDict->find(s);
2293 if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s);
2294 if (bcd && bcd!=ncd)
2296 ncd->insertBaseClass(bcd,s,Public,Normal);
2298 s=g_curClassBases.next();
2301 //printf("g_codeClassList.count()=%d\n",g_codeClassList.count());
2303 else // not a class name -> assume inner block
2305 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
2306 g_scopeStack.push(INNERBLOCK);
2308 g_curClassName.resize(0);
2309 g_curClassBases.clear();
2312 <Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" {
2313 startFontClass("keyword");
2314 g_code->codify(yytext);
2317 <Bases>{SEP}?({ID}{SEP})*{ID} {
2318 DBG_CTX((stderr,"%s:addBase(%s)\n",g_curClassName.data(),yytext));
2319 g_curClassBases.inSort(yytext);
2320 generateClassOrGlobalLink(*g_code,yytext);
2323 g_code->codify(yytext);
2327 BEGIN ( SkipSharp );
2331 g_insideProtocolList=TRUE;
2335 g_code->codify(yytext);
2336 g_insideProtocolList=FALSE;
2339 g_code->codify(yytext);
2343 g_code->codify(yytext);
2344 if (--g_sharpCount<=0)
2348 g_code->codify(yytext);
2350 BEGIN ( SkipSharp );
2353 g_code->codify(yytext);
2357 g_code->codify(yytext);
2358 if (--g_sharpCount<=0)
2364 g_code->codify(yytext);
2368 <Body>{SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" {
2370 generateFunctionLink(*g_code,yytext);
2376 <Body>{SCOPEPREFIX}?"operator"/"(" {
2378 generateFunctionLink(*g_code,yytext);
2384 <Body>{SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\(\n]+/"(" {
2386 generateFunctionLink(*g_code,yytext);
2392 <Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9]) {
2393 startFontClass("keyword");
2394 codifyLines(yytext);
2396 g_insideTemplate=TRUE;
2399 <Body>"using"{BN}+"namespace"{BN}+ {
2400 startFontClass("keyword");
2401 codifyLines(yytext);
2405 <UsingName>{ID}("::"{ID})* { addUsingDirective(yytext);
2406 generateClassOrGlobalLink(*g_code,yytext);
2407 DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
2408 g_scopeStack.push(CLASSBLOCK);
2412 <UsingName>\n { codifyLines(yytext); BEGIN(Body); }
2413 <UsingName>. { codifyLines(yytext); BEGIN(Body); }
2414 <Body,FuncCall>"$"?"this"("->"|".") { g_code->codify(yytext); // this-> for C++, this. for C#
2415 g_prefixed_with_this_keyword = TRUE;
2417 <Body>{KEYWORD}/([^a-z_A-Z0-9]) {
2418 startFontClass("keyword");
2419 codifyLines(yytext);
2420 if (QCString(yytext)=="typedef")
2427 <Body>{KEYWORD}/{B}* {
2428 startFontClass("keyword");
2429 codifyLines(yytext);
2432 <Body>{KEYWORD}/{BN}*"(" {
2433 startFontClass("keyword");
2434 codifyLines(yytext);
2436 g_name.resize(0);g_type.resize(0);
2438 <FuncCall>"in"/{BN}* {
2439 if (!g_inForEachExpression) REJECT;
2440 startFontClass("keywordflow");
2441 codifyLines(yytext);
2443 // insert the variable in the parent scope, see bug 546158
2444 g_theVarContext.popScope();
2445 g_theVarContext.addVariable(g_parmType,g_parmName);
2446 g_theVarContext.pushScope();
2447 g_name.resize(0);g_type.resize(0);
2449 <Body>{FLOWKW}/{BN}*"(" {
2450 startFontClass("keywordflow");
2451 codifyLines(yytext);
2453 g_name.resize(0);g_type.resize(0);
2454 g_inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0);
2457 <Body>{FLOWCONDITION}/{BN}*"(" {
2458 if (g_currentMemberDef && g_currentMemberDef->isFunction())
2460 g_currentMemberDef->addFlowKeyWord();
2462 startFontClass("keywordflow");
2463 codifyLines(yytext);
2465 g_name.resize(0);g_type.resize(0);
2466 g_inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0);
2469 <Body>{FLOWKW}/([^a-z_A-Z0-9]) {
2470 startFontClass("keywordflow");
2471 codifyLines(yytext);
2473 if (g_inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0))
2475 g_inFunctionTryBlock=FALSE;
2478 <Body>{FLOWCONDITION}/([^a-z_A-Z0-9]) {
2479 if (g_currentMemberDef && g_currentMemberDef->isFunction())
2481 g_currentMemberDef->addFlowKeyWord();
2483 startFontClass("keywordflow");
2484 codifyLines(yytext);
2486 if (g_inFunctionTryBlock && (strcmp(yytext,"catch")==0 || strcmp(yytext,"finally")==0))
2488 g_inFunctionTryBlock=FALSE;
2491 <Body>{FLOWKW}/{B}* {
2492 startFontClass("keywordflow");
2493 codifyLines(yytext);
2496 <Body>{FLOWCONDITION}/{B}* {
2497 if (g_currentMemberDef && g_currentMemberDef->isFunction())
2499 g_currentMemberDef->addFlowKeyWord();
2501 startFontClass("keywordflow");
2502 codifyLines(yytext);
2505 <Body>"*"{B}*")" { // end of cast?
2506 g_code->codify(yytext);
2507 g_theCallContext.popScope();
2509 g_parmType = g_name;
2512 <Body>[\\|\)\+\-\/\%\~\!] {
2513 g_code->codify(yytext);
2514 g_name.resize(0);g_type.resize(0);
2517 g_theCallContext.popScope();
2522 <Body,TemplDecl,ObjCMethod>{TYPEKW}/{B}* {
2523 startFontClass("keywordtype");
2524 g_code->codify(yytext);
2529 <Body>"generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* {
2530 startFontClass("keyword");
2531 g_code->codify(yytext);
2536 <Body>"template"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { // template<...>
2537 startFontClass("keyword");
2538 g_code->codify(yytext);
2543 <TemplDecl>"class"|"typename" {
2544 startFontClass("keyword");
2545 codifyLines(yytext);
2549 g_code->codify(yytext);
2553 g_code->codify(yytext);
2555 if (g_sharpCount<=0)
2561 startFontClass("keyword");
2562 codifyLines(yytext);
2564 BEGIN( g_lastTemplCastContext );
2566 <TemplCast>{ID}("::"{ID})* {
2567 generateClassOrGlobalLink(*g_code,yytext);
2569 <TemplCast>("const"|"volatile"){B}* {
2570 startFontClass("keyword");
2571 codifyLines(yytext);
2575 codifyLines(yytext);
2577 <Body,FuncCall>{CASTKW}"<" { // static_cast<T>(
2578 startFontClass("keyword");
2579 codifyLines(yytext);
2581 g_lastTemplCastContext = YY_START;
2584 <Body>"$this->"{SCOPENAME}/{BN}*[;,)\]] { // PHP member variable
2586 generatePHPVariableLink(*g_code,yytext);
2589 <Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"("::"{ID})*/{B}* { // A<T> *pt;
2590 int i=QCString(yytext).find('<');
2591 QCString kw = QCString(yytext).left(i).stripWhiteSpace();
2592 if (kw.right(5)=="_cast" && YY_START==Body)
2597 generateClassOrGlobalLink(*g_code,yytext);
2600 <Body>{SCOPENAME}/{BN}*[:;,)\]] { // "int var;" or "var, var2" or "debug(f) macro" , or int var : 5;
2602 // changed this to generateFunctionLink, see bug 624514
2603 //generateClassOrGlobalLink(*g_code,yytext,FALSE,TRUE);
2604 generateFunctionLink(*g_code,yytext);
2607 <Body>{SCOPENAME}/{B}* { // p->func()
2609 generateClassOrGlobalLink(*g_code,yytext);
2612 <Body>"("{B}*("*"{B}*)+{SCOPENAME}*{B}*")"/{B}* { // (*p)->func() but not "if (p) ..."
2613 g_code->codify(yytext);
2614 int s=0;while (s<(int)yyleng && !isId(yytext[s])) s++;
2615 int e=(int)yyleng-1;while (e>=0 && !isId(yytext[e])) e--;
2616 QCString varname = ((QCString)yytext).mid(s,e-s+1);
2620 <Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo()
2622 generateFunctionLink(*g_code,yytext);
2628 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN} {
2629 QCString text=yytext;
2630 int i=text.find('R');
2631 g_code->codify(text.left(i+1));
2632 startFontClass("stringliteral");
2633 g_code->codify(yytext+i+1);
2634 g_lastStringContext=YY_START;
2635 g_inForEachExpression = FALSE;
2636 g_delimiter = yytext+i+2;
2637 g_delimiter=g_delimiter.left(g_delimiter.length()-1);
2640 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\" {
2641 startFontClass("stringliteral");
2642 g_code->codify(yytext);
2643 g_lastStringContext=YY_START;
2644 g_inForEachExpression = FALSE;
2645 BEGIN( SkipString );
2647 <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\' {
2648 startFontClass("stringliteral");
2649 g_code->codify(yytext);
2650 g_lastStringContext=YY_START;
2651 g_inForEachExpression = FALSE;
2652 BEGIN( SkipStringS );
2654 <SkipString>[^\"\\\r\n]* {
2655 g_code->codify(yytext);
2657 <SkipStringS>[^\'\\\r\n]* {
2658 g_code->codify(yytext);
2660 <SkipString,SkipStringS>"//"|"/*" {
2661 g_code->codify(yytext);
2664 g_code->codify(yytext);
2666 BEGIN( g_lastStringContext );
2669 g_code->codify(yytext);
2671 BEGIN( g_lastStringContext );
2673 <SkipString,SkipStringS>\\. {
2674 g_code->codify(yytext);
2676 <RawString>{RAWEND} {
2677 g_code->codify(yytext);
2678 QCString delimiter = yytext+1;
2679 delimiter=delimiter.left(delimiter.length()-1);
2680 if (delimiter==g_delimiter)
2682 BEGIN( g_lastStringContext );
2685 <RawString>[^)\n]+ { g_code->codify(yytext); }
2686 <RawString>. { g_code->codify(yytext); }
2687 <RawString>\n { codifyLines(yytext); }
2688 <SkipVerbString>[^"\n]+ {
2689 g_code->codify(yytext);
2691 <SkipVerbString>\"\" { // escaped quote
2692 g_code->codify(yytext);
2694 <SkipVerbString>\" { // end of string
2695 g_code->codify(yytext);
2697 BEGIN( g_lastVerbStringContext );
2700 g_code->codify(yytext);
2702 <SkipVerbString>\n {
2703 codifyLines(yytext);
2706 g_code->codify(yytext);
2707 g_name.resize(0);g_type.resize(0);
2710 if (g_insideTemplate)
2714 g_code->codify(yytext);
2717 if (g_insideTemplate)
2719 if (--g_sharpCount<=0)
2721 g_insideTemplate=FALSE;
2724 g_code->codify(yytext);
2726 <Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'" {
2727 startFontClass("charliteral");
2728 g_code->codify(yytext);
2732 if (yytext[0]=='-') // -> could be overloaded
2734 updateCallContextForSmartPointer();
2736 g_code->codify(yytext);
2737 g_memCallContext = YY_START;
2738 BEGIN( MemberCall );
2740 <MemberCall>{SCOPETNAME}/{BN}*"(" {
2741 if (g_theCallContext.getScope())
2743 if (!generateClassMemberLink(*g_code,g_theCallContext.getScope(),yytext))
2745 g_code->codify(yytext);
2746 addToSearchIndex(yytext);
2752 g_code->codify(yytext);
2753 addToSearchIndex(yytext);
2758 if (g_memCallContext==Body)
2764 BEGIN(g_memCallContext);
2767 <MemberCall>{SCOPENAME}/{B}* {
2768 if (g_theCallContext.getScope())
2770 DBG_CTX((stderr,"g_theCallContext.getClass()=%p\n",g_theCallContext.getScope()));
2771 if (!generateClassMemberLink(*g_code,g_theCallContext.getScope(),yytext))
2773 g_code->codify(yytext);
2774 addToSearchIndex(yytext);
2780 DBG_CTX((stderr,"no class context!\n"));
2781 g_code->codify(yytext);
2782 addToSearchIndex(yytext);
2786 BEGIN(g_memCallContext);
2789 if (g_insideObjC && *yytext=='[')
2791 //printf("Found start of ObjC call!\n");
2792 // start of a method call
2793 g_contextDict.setAutoDelete(TRUE);
2794 g_nameDict.setAutoDelete(TRUE);
2795 g_objectDict.setAutoDelete(TRUE);
2796 g_wordDict.setAutoDelete(TRUE);
2797 g_commentDict.setAutoDelete(TRUE);
2798 g_contextDict.clear();
2800 g_objectDict.clear();
2802 g_commentDict.clear();
2804 g_currentNameId = 0;
2813 g_code->codify(yytext);
2814 g_saveName = g_name.copy();
2815 g_saveType = g_type.copy();
2816 if (*yytext!='[' && !g_type.isEmpty())
2818 //printf("g_scopeStack.bottom()=%p\n",g_scopeStack.bottom());
2819 //if (g_scopeStack.top()!=CLASSBLOCK) // commented out for bug731363
2821 //printf("AddVariable: '%s' '%s' context=%d\n",
2822 // g_type.data(),g_name.data(),g_theVarContext.count());
2823 g_theVarContext.addVariable(g_type,g_name);
2827 if (*yytext==';' || *yytext=='=')
2832 else if (*yytext=='[')
2834 g_theCallContext.pushScope();
2837 g_parmType.resize(0);
2838 g_parmName.resize(0);
2842 <ObjCMemberCall>{ID} {
2843 if (qstrcmp(yytext,"self")==0 || qstrcmp(yytext,"super")==0)
2845 // TODO: get proper base class for "super"
2846 g_theCallContext.setClass(getClass(g_curClassName));
2847 startFontClass("keyword");
2848 g_code->codify(yytext);
2853 generateClassOrGlobalLink(*g_code,yytext);
2856 BEGIN(ObjCMemberCall2);
2858 <ObjCMemberCall>"[" {
2859 g_code->codify(yytext);
2860 g_theCallContext.pushScope();
2862 <ObjCMemberCall2>{ID}":"? {
2864 if (g_theCallContext.getClass())
2866 //printf("Calling method %s\n",g_name.data());
2867 if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),g_name))
2869 g_code->codify(yytext);
2870 addToSearchIndex(g_name);
2875 g_code->codify(yytext);
2876 addToSearchIndex(g_name);
2879 BEGIN(ObjCMemberCall3);
2881 <ObjCMemberCall2,ObjCMemberCall3>"]" {
2882 g_theCallContext.popScope();
2883 g_code->codify(yytext);
2887 <ObjCCall,ObjCMName>"["|"{" {
2889 g_currentCtx->format+=*yytext;
2893 <ObjCCall,ObjCMName>"]"|"}" {
2894 g_currentCtx->format+=*yytext;
2895 restoreObjCContext();
2897 if (g_currentCtx==0)
2900 writeObjCMethodCall(g_contextDict.find(0));
2903 //printf("close\n");
2905 <ObjCCall,ObjCMName>"//".* {
2906 g_currentCtx->format+=escapeComment(yytext);
2908 <ObjCCall,ObjCMName>"/*" {
2909 g_lastObjCCallContext = YY_START;
2910 g_currentCtx->comment=yytext;
2911 BEGIN(ObjCCallComment);
2913 <ObjCCallComment>"*/" {
2914 g_currentCtx->comment+=yytext;
2915 g_currentCtx->format+=escapeComment(g_currentCtx->comment);
2916 BEGIN(g_lastObjCCallContext);
2918 <ObjCCallComment>[^*\n]+ { g_currentCtx->comment+=yytext; }
2919 <ObjCCallComment>"//"|"/*" { g_currentCtx->comment+=yytext; }
2920 <ObjCCallComment>\n { g_currentCtx->comment+=*yytext; }
2921 <ObjCCallComment>. { g_currentCtx->comment+=*yytext; }
2923 g_currentCtx->format+=escapeObject(yytext);
2924 if (g_braceCount==0)
2926 g_currentCtx->objectTypeOrName=yytext;
2927 //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
2931 <ObjCMName>{ID}/{BN}*"]" {
2932 if (g_braceCount==0 &&
2933 g_currentCtx->methodName.isEmpty())
2935 g_currentCtx->methodName=yytext;
2936 g_currentCtx->format+=escapeName(yytext);
2940 g_currentCtx->format+=escapeWord(yytext);
2943 <ObjCMName>{ID}/{BN}*":" {
2944 if (g_braceCount==0)
2946 g_currentCtx->methodName+=yytext;
2947 g_currentCtx->methodName+=":";
2949 g_currentCtx->format+=escapeName(yytext);
2951 <ObjCSkipStr>[^\n\"$\\]* { g_currentCtx->format+=yytext; }
2952 <ObjCSkipStr>\\. { g_currentCtx->format+=yytext; }
2953 <ObjCSkipStr>"\"" { g_currentCtx->format+=yytext;
2954 BEGIN(g_lastStringContext);
2956 <ObjCCall,ObjCMName>{CHARLIT} { g_currentCtx->format+=yytext; }
2957 <ObjCCall,ObjCMName>"@"?"\"" { g_currentCtx->format+=yytext;
2958 g_lastStringContext=YY_START;
2961 <ObjCCall,ObjCMName,ObjCSkipStr>"$" { g_currentCtx->format+="$$"; }
2962 <ObjCCall,ObjCMName>"(" { g_currentCtx->format+=*yytext; g_braceCount++; }
2963 <ObjCCall,ObjCMName>")" { g_currentCtx->format+=*yytext; g_braceCount--; }
2964 <ObjCSkipStr>"@"/"\"" { // needed to prevent matching the global rule (for C#)
2965 g_currentCtx->format+=yytext;
2967 <ObjCCall,ObjCMName,ObjCSkipStr>{ID} { g_currentCtx->format+=escapeWord(yytext); }
2968 <ObjCCall,ObjCMName,ObjCSkipStr>. { g_currentCtx->format+=*yytext; }
2969 <ObjCCall,ObjCMName,ObjCSkipStr>\n { g_currentCtx->format+=*yytext; }
2972 g_theCallContext.popScope();
2973 g_code->codify(yytext);
2974 // TODO: nested arrays like: a[b[0]->func()]->func()
2975 g_name = g_saveName.copy();
2976 g_type = g_saveType.copy();
2979 g_code->codify(yytext);
2981 <Body>[0-9]+[xX][0-9A-Fa-f]+ {
2982 g_code->codify(yytext);
2984 <MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) {
2986 //g_parmName=yytext;
2987 startFontClass("keyword");
2988 g_code->codify(yytext);
2991 <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKW}/([^a-z_A-Z0-9]) {
2994 startFontClass("keywordtype");
2995 g_code->codify(yytext);
2998 <MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) {
3001 startFontClass("keywordflow");
3002 g_code->codify(yytext);
3005 <MemberCall2,FuncCall>{FLOWCONDITION}/([^a-z_A-Z0-9]) {
3006 if (g_currentMemberDef && g_currentMemberDef->isFunction())
3008 g_currentMemberDef->addFlowKeyWord();
3012 startFontClass("keywordflow");
3013 g_code->codify(yytext);
3016 <MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* {
3019 generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3021 <FuncCall>";" { // probably a cast, not a function call
3022 g_code->codify(yytext);
3023 g_inForEachExpression = FALSE;
3026 <MemberCall2,FuncCall>, {
3027 g_code->codify(yytext);
3028 g_theVarContext.addVariable(g_parmType,g_parmName);
3029 g_parmType.resize(0);g_parmName.resize(0);
3031 <MemberCall2,FuncCall>"{" {
3032 if (g_bracketCount>0)
3034 g_code->codify(yytext);
3035 g_skipInlineInitContext=YY_START;
3044 <InlineInit>"{" { g_curlyCount++;
3045 g_code->codify(yytext);
3048 g_code->codify(yytext);
3049 if (--g_curlyCount<=0)
3051 BEGIN(g_skipInlineInitContext);
3055 codifyLines(yytext);
3058 g_code->codify(yytext);
3060 <MemberCall2,FuncCall>"(" {
3061 g_parmType.resize(0);g_parmName.resize(0);
3062 g_code->codify(yytext);
3064 g_theCallContext.pushScope();
3065 if (YY_START==FuncCall && !g_insideBody)
3067 g_theVarContext.pushScope();
3070 <MemberCall2,FuncCall>{OPERATOR} { // operator
3071 if (qstrcmp(yytext,"*") &&
3072 qstrcmp(yytext,"&") &&
3073 qstrcmp(yytext,"^") &&
3074 qstrcmp(yytext,"%")) // typically a pointer or reference
3076 // not a * or &, or C++/CLI's ^ or %
3077 g_parmType.resize(0);g_parmName.resize(0);
3079 g_code->codify(yytext);
3081 <MemberCall,MemberCall2,FuncCall>("*"{B}*)?")" {
3082 if (yytext[0]==')') // no a pointer cast
3084 //printf("addVariable(%s,%s)\n",g_parmType.data(),g_parmName.data());
3085 if (g_parmType.isEmpty())
3087 g_parmType=g_parmName;
3088 g_parmName.resize(0);
3090 g_theVarContext.addVariable(g_parmType,g_parmName);
3094 g_parmType = g_parmName;
3095 g_parmName.resize(0);
3096 g_theVarContext.addVariable(g_parmType,g_parmName);
3098 g_theCallContext.popScope();
3099 g_inForEachExpression = FALSE;
3100 //g_theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b().
3101 g_code->codify(yytext);
3102 if (--g_bracketCount<=0)
3104 if (g_name.isEmpty())
3114 <CallEnd>[ \t\n]* { codifyLines(yytext); }
3116 <MemberCall2,FuncCall>")"[ \t\n]*[;:] {
3119 codifyLines(yytext);
3121 if (*yytext==';') g_searchingForBody=FALSE;
3122 if (!g_type.isEmpty())
3124 DBG_CTX((stderr,"add variable g_type=%s g_name=%s)\n",g_type.data(),g_name.data()));
3125 g_theVarContext.addVariable(g_type,g_name);
3127 g_parmType.resize(0);g_parmName.resize(0);
3128 g_theCallContext.setScope(0);
3129 if (*yytext==';' || g_insideBody)
3133 g_theVarContext.popScope();
3135 g_name.resize(0);g_type.resize(0);
3144 <CallEnd>("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") {
3145 startFontClass("keyword");
3146 codifyLines(yytext);
3149 <CallEnd,OldStyleArgs>("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" {
3152 g_theVarContext.pushScope();
3154 g_theVarContext.addVariable(g_parmType,g_parmName);
3155 //g_theCallContext.popScope();
3156 g_parmType.resize(0);g_parmName.resize(0);
3157 int index = g_name.findRev("::");
3158 DBG_CTX((stderr,"g_name=%s\n",g_name.data()));
3161 QCString scope = g_name.left(index);
3162 if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::");
3163 ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope);
3166 setClassScope(cd->name());
3167 g_scopeStack.push(SCOPEBLOCK);
3168 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3172 //setClassScope(g_realScope);
3173 g_scopeStack.push(INNERBLOCK);
3174 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3179 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3180 g_scopeStack.push(INNERBLOCK);
3182 yytext[yyleng-1]='\0';
3183 QCString cv(yytext);
3184 if (!cv.stripWhiteSpace().isEmpty())
3186 startFontClass("keyword");
3187 codifyLines(yytext);
3190 else // just whitespace
3192 codifyLines(yytext);
3194 g_code->codify("{");
3195 if (g_searchingForBody)
3197 g_searchingForBody=FALSE;
3200 if (g_insideBody) g_bodyCurlyCount++;
3201 g_type.resize(0); g_name.resize(0);
3204 <CallEnd>"try" { // function-try-block
3205 startFontClass("keyword");
3206 g_code->codify(yytext);
3208 g_inFunctionTryBlock=TRUE;
3211 if (g_insideBody || !g_parmType.isEmpty())
3215 // could be K&R style definition
3218 generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3219 BEGIN(OldStyleArgs);
3221 <OldStyleArgs>{ID} {
3224 generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
3226 <OldStyleArgs>[,;] {
3227 g_code->codify(yytext);
3228 g_theVarContext.addVariable(g_parmType,g_parmName);
3229 if (*yytext==';') g_parmType.resize(0);
3230 g_parmName.resize(0);
3232 <CallEnd,OldStyleArgs>"#" {
3233 startFontClass("preprocessor");
3234 g_lastSkipCppContext = Body;
3235 g_code->codify(yytext);
3242 g_theVarContext.popScope();
3244 g_name.resize(0);g_args.resize(0);
3245 g_parmType.resize(0);g_parmName.resize(0);
3249 g_code->codify(yytext);
3250 g_type.resize(0); g_name.resize(0);
3254 g_code->codify(yytext);
3255 if (g_searchingForBody)
3257 g_searchingForBody=FALSE;
3260 if (g_insideBody) g_bodyCurlyCount++;
3261 if (g_name.find("::")!=-1)
3263 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
3264 g_scopeStack.push(SCOPEBLOCK);
3265 setClassScope(g_realScope);
3269 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
3270 g_scopeStack.push(INNERBLOCK);
3272 g_type.resize(0); g_name.resize(0);
3276 generateClassOrGlobalLink(*g_code,yytext);
3278 <FuncCall>{ID}/"(" {
3279 generateFunctionLink(*g_code,yytext);
3281 <FuncCall>{ID}/("."|"->") {
3283 generateClassOrGlobalLink(*g_code,yytext);
3284 BEGIN( MemberCall2 );
3286 <FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}*{B}*")"{B}*)/("."|"->") {
3287 g_code->codify(yytext);
3288 int s=0;while (!isId(yytext[s])) s++;
3289 int e=(int)yyleng-1;while (!isId(yytext[e])) e--;
3290 g_name=((QCString)yytext).mid(s,e-s+1);
3291 BEGIN( MemberCall2 );
3293 <MemberCall2>{ID}/([ \t\n]*"(") {
3294 if (!g_args.isEmpty())
3295 generateMemberLink(*g_code,g_args,yytext);
3297 generateClassOrGlobalLink(*g_code,yytext);
3301 <MemberCall2>{ID}/([ \t\n]*("."|"->")) {
3302 //g_code->codify(yytext);
3304 generateClassOrGlobalLink(*g_code,yytext);
3305 BEGIN( MemberCall2 );
3307 <MemberCall2>"->"|"." {
3308 if (yytext[0]=='-') // -> could be overloaded
3310 updateCallContextForSmartPointer();
3312 g_code->codify(yytext);
3313 g_memCallContext = YY_START;
3314 BEGIN( MemberCall );
3316 <SkipComment>"/*"("!"?)"*/" {
3317 g_code->codify(yytext);
3319 BEGIN( g_lastCContext ) ;
3321 <SkipComment>"//"|"/*" {
3322 g_code->codify(yytext);
3324 <SkipComment>[^*/\n]+ {
3325 g_code->codify(yytext);
3327 <SkipComment>[ \t]*"*/" {
3328 g_code->codify(yytext);
3330 if (g_lastCContext==SkipCPP)
3332 startFontClass("preprocessor");
3334 BEGIN( g_lastCContext ) ;
3336 <SkipCxxComment>[^\r\n]*"\\"[\r]?\n { // line continuation
3337 codifyLines(yytext);
3339 <SkipCxxComment>[^\r\n]+ {
3340 g_code->codify(yytext);
3343 <SkipCxxComment>\n {
3346 BEGIN( g_lastCContext ) ;
3349 g_code->codify(yytext);
3351 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] {
3352 g_yyLineNr+=QCString(yytext).contains('\n');
3354 <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? {
3355 g_yyLineNr+=QCString(yytext).contains('\n');
3357 if (g_lastSpecialCContext==SkipCxxComment)
3358 { // force end of C++ comment here
3360 BEGIN( g_lastCContext ) ;
3364 BEGIN(g_lastSpecialCContext);
3367 <RemoveSpecialCComment>"*/" {
3368 BEGIN(g_lastSpecialCContext);
3370 <RemoveSpecialCComment>[^*\n]+
3371 <RemoveSpecialCComment>"//"|"/*"
3372 <RemoveSpecialCComment>\n { g_yyLineNr++; }
3373 <RemoveSpecialCComment>.
3374 <MemberCall>[^a-z_A-Z0-9(\n] {
3375 g_code->codify(yytext);
3378 BEGIN(g_memCallContext);
3380 <*>\n({B}*"//"[!/][^\n]*\n)+ { // remove special one-line comment
3381 if (YY_START==SkipCPP) REJECT;
3382 if (Config_getBool(STRIP_CODE_COMMENTS))
3384 g_yyLineNr+=((QCString)yytext).contains('\n');
3389 startFontClass("comment");
3390 codifyLines(yytext);
3393 if (YY_START==SkipCxxComment)
3396 BEGIN( g_lastCContext ) ;
3401 codifyLines(yytext);
3402 BEGIN( g_lastSkipCppContext ) ;
3404 <*>\n{B}*"//@"[{}].*\n { // remove one-line group marker
3405 if (Config_getBool(STRIP_CODE_COMMENTS))
3412 startFontClass("comment");
3413 codifyLines(yytext);
3416 if (YY_START==SkipCxxComment)
3419 BEGIN( g_lastCContext ) ;
3422 <*>\n{B}*"/*@"[{}] { // remove one-line group marker
3423 if (Config_getBool(STRIP_CODE_COMMENTS))
3425 g_lastSpecialCContext = YY_START;
3427 BEGIN(RemoveSpecialCComment);
3431 // check is to prevent getting stuck in skipping C++ comments
3432 if (YY_START != SkipCxxComment)
3434 g_lastCContext = YY_START ;
3436 startFontClass("comment");
3437 codifyLines(yytext);
3441 <*>^{B}*"//@"[{}].*\n { // remove one-line group marker
3442 if (Config_getBool(STRIP_CODE_COMMENTS))
3449 startFontClass("comment");
3450 codifyLines(yytext);
3454 <*>^{B}*"/*@"[{}] { // remove multi-line group marker
3455 if (Config_getBool(STRIP_CODE_COMMENTS))
3457 g_lastSpecialCContext = YY_START;
3458 BEGIN(RemoveSpecialCComment);
3462 // check is to prevent getting stuck in skipping C++ comments
3463 if (YY_START != SkipCxxComment)
3465 g_lastCContext = YY_START ;
3467 startFontClass("comment");
3468 g_code->codify(yytext);
3472 <*>^{B}*"//"[!/][^\n]*\n { // remove special one-line comment
3473 if (Config_getBool(STRIP_CODE_COMMENTS))
3480 startFontClass("comment");
3481 codifyLines(yytext);
3485 <*>"//"[!/][^\n]*\n { // strip special one-line comment
3486 if (YY_START==SkipComment || YY_START==SkipString) REJECT;
3487 if (Config_getBool(STRIP_CODE_COMMENTS))
3489 char c[2]; c[0]='\n'; c[1]=0;
3494 startFontClass("comment");
3495 codifyLines(yytext);
3499 <*>"/*[tag:"[^\]\n]*"]*/"{B}* { // special pattern /*[tag:filename]*/ to force linking to a tag file
3500 g_forceTagReference=yytext;
3501 int s=g_forceTagReference.find(':');
3502 int e=g_forceTagReference.findRev(']');
3503 g_forceTagReference = g_forceTagReference.mid(s+1,e-s-1);
3505 <*>\n{B}*"/*"[!*]/[^/*] {
3506 if (Config_getBool(STRIP_CODE_COMMENTS))
3508 g_lastSpecialCContext = YY_START;
3510 BEGIN(RemoveSpecialCComment);
3514 // check is to prevent getting stuck in skipping C++ comments
3515 if (YY_START != SkipCxxComment)
3517 g_lastCContext = YY_START ;
3519 startFontClass("comment");
3520 codifyLines(yytext);
3524 <*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line
3525 if (Config_getBool(STRIP_CODE_COMMENTS))
3527 g_lastSpecialCContext = YY_START;
3528 BEGIN(RemoveSpecialCComment);
3532 // check is to prevent getting stuck in skipping C++ comments
3533 if (YY_START != SkipCxxComment)
3535 g_lastCContext = YY_START ;
3537 startFontClass("comment");
3538 g_code->codify(yytext);
3542 <*>"/*"[!*]/[^/*] { // special C comment block half way a line
3543 if (YY_START==SkipString) REJECT;
3544 if (Config_getBool(STRIP_CODE_COMMENTS))
3546 g_lastSpecialCContext = YY_START;
3547 BEGIN(RemoveSpecialCComment);
3551 // check is to prevent getting stuck in skipping C++ comments
3552 if (YY_START != SkipCxxComment)
3554 g_lastCContext = YY_START ;
3556 startFontClass("comment");
3557 g_code->codify(yytext);
3562 if (YY_START==SkipString) REJECT;
3563 if (!Config_getBool(STRIP_CODE_COMMENTS))
3565 startFontClass("comment");
3566 g_code->codify(yytext);
3571 startFontClass("comment");
3572 g_code->codify(yytext);
3573 // check is to prevent getting stuck in skipping C++ comments
3574 if (YY_START != SkipCxxComment)
3576 g_lastCContext = YY_START ;
3578 BEGIN( SkipComment ) ;
3580 <*>@\" { // C# verbatim string
3581 startFontClass("stringliteral");
3582 g_code->codify(yytext);
3583 g_lastVerbStringContext=YY_START;
3584 BEGIN(SkipVerbString);
3587 startFontClass("comment");
3588 g_code->codify(yytext);
3589 g_lastCContext = YY_START ;
3590 BEGIN( SkipCxxComment ) ;
3593 g_code->codify(yytext);
3594 g_theCallContext.pushScope();
3597 g_code->codify(yytext);
3598 g_theCallContext.popScope();
3602 codifyLines(yytext);
3606 g_code->codify(yytext);
3609 <*>([ \t\n]*"\n"){2,} { // combine multiple blank lines
3610 //QCString sepLine=yytext;
3611 //g_code->codify("\n\n");
3612 //g_yyLineNr+=sepLine.contains('\n');
3613 //char sepLine[3]="\n\n";
3614 codifyLines(yytext);
3620 /*@ ----------------------------------------------------------------------------
3623 static void saveObjCContext()
3627 g_currentCtx->format+=QCString().sprintf("$c%d",g_currentCtxId);
3628 if (g_braceCount==0 && YY_START==ObjCCall)
3630 g_currentCtx->objectTypeOrName=g_currentCtx->format.mid(1);
3631 //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
3633 g_contextStack.push(g_currentCtx);
3637 //printf("Trying to save NULL context!\n");
3639 ObjCCallCtx *newCtx = new ObjCCallCtx;
3640 newCtx->id = g_currentCtxId;
3641 newCtx->lexState = YY_START;
3642 newCtx->braceCount = g_braceCount;
3643 newCtx->objectType = 0;
3644 newCtx->objectVar = 0;
3646 //printf("save state=%d\n",YY_START);
3647 g_contextDict.insert(g_currentCtxId,newCtx);
3648 g_currentCtx = newCtx;
3653 static void restoreObjCContext()
3655 //printf("restore state=%d->%d\n",YY_START,g_currentCtx->lexState);
3656 BEGIN(g_currentCtx->lexState);
3657 g_braceCount = g_currentCtx->braceCount;
3658 if (!g_contextStack.isEmpty())
3660 g_currentCtx = g_contextStack.pop();
3665 //printf("Trying to pop context while g_contextStack is empty!\n");
3669 void resetCCodeParserState()
3671 //printf("***initParseCodeContext()\n");
3672 g_forceTagReference.resize(0);
3673 g_theVarContext.clear();
3674 g_classScopeLengthStack.setAutoDelete(TRUE);
3675 g_classScopeLengthStack.clear();
3676 delete g_codeClassSDict;
3677 g_codeClassSDict = new ClassSDict(17);
3678 g_codeClassSDict->setAutoDelete(TRUE);
3679 g_codeClassSDict->clear();
3680 g_curClassBases.clear();
3684 void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s,
3685 SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd,
3686 int startLine,int endLine,bool inlineFragment,
3687 MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
3690 //printf("***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n",
3691 // exBlock,exName,fd,className,searchCtx?searchCtx->name().data():"<none>");
3693 if (s.isEmpty()) return;
3695 printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
3697 TooltipManager::instance()->clearTooltips();
3698 if (g_codeClassSDict==0)
3700 resetCCodeParserState();
3704 g_inputPosition = 0;
3705 g_currentFontClass = 0;
3706 g_needsTermination = FALSE;
3707 g_searchCtx = searchCtx;
3708 g_collectXRefs = collectXRefs;
3709 g_inFunctionTryBlock = FALSE;
3712 g_yyLineNr = startLine;
3717 g_inputLines = endLine+1;
3719 g_inputLines = g_yyLineNr + countLines() - 1;
3722 g_bodyCurlyCount = 0;
3725 g_insideTemplate = FALSE;
3726 g_theCallContext.clear();
3727 g_scopeStack.clear();
3728 g_classScope = className;
3729 //printf("parseCCode %s\n",className);
3730 g_exampleBlock = exBlock;
3731 g_exampleName = exName;
3732 g_sourceFileDef = fd;
3733 g_lineNumbers = fd!=0 && showLineNumbers;
3734 bool cleanupSourceDef = FALSE;
3737 // create a dummy filedef for the example
3738 g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
3739 cleanupSourceDef = TRUE;
3741 g_insideObjC = lang==SrcLangExt_ObjC;
3742 g_insideJava = lang==SrcLangExt_Java;
3743 g_insideCS = lang==SrcLangExt_CSharp;
3744 g_insidePHP = lang==SrcLangExt_PHP;
3745 if (g_sourceFileDef)
3747 setCurrentDoc("l00001");
3749 g_currentDefinition = 0;
3750 g_currentMemberDef = 0;
3751 g_searchingForBody = exBlock;
3752 g_insideBody = FALSE;
3754 if (!g_exampleName.isEmpty())
3756 g_exampleFile = convertNameToFile(g_exampleName+"-example",FALSE,TRUE);
3757 //printf("g_exampleFile=%s\n",g_exampleFile.data());
3759 g_includeCodeFragment = inlineFragment;
3760 //printf("** exBlock=%d exName=%s include=%d\n",exBlock,exName,inlineFragment);
3765 g_parmName.resize(0);
3766 g_parmType.resize(0);
3767 if (memberDef) setParameterList(memberDef);
3768 codeYYrestart( codeYYin );
3772 if (g_needsTermination)
3775 DBG_CTX((stderr,"endCodeLine(%d)\n",g_yyLineNr));
3776 g_code->endCodeLine();
3780 TooltipManager::instance()->writeTooltips(*g_code);
3782 if (cleanupSourceDef)
3784 // delete the temporary file definition used for this example
3785 delete g_sourceFileDef;
3789 printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
3793 void codeFreeScanner()
3795 #if defined(YY_FLEX_SUBMINOR_VERSION)
3798 codeYYlex_destroy();
3805 #if !defined(YY_FLEX_SUBMINOR_VERSION)
3806 extern "C" { // some bogus code to keep the compiler happy
3807 void codeYYdummy() { yy_flex_realloc(0,0); }
3809 #elif YY_FLEX_MAJOR_VERSION<=2 && YY_FLEX_MINOR_VERSION<=5 && YY_FLEX_SUBMINOR_VERSION<33
3810 #error "You seem to be using a version of flex newer than 2.5.4. These are currently incompatible with 2.5.4, and do NOT work with doxygen! Please use version 2.5.4 or expect things to be parsed wrongly! A bug report has been submitted (#732132)."