summaryrefslogtreecommitdiff
path: root/src/code.l
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-11-08 06:36:54 -0800
committerAnas Nashif <anas.nashif@intel.com>2012-11-08 06:36:54 -0800
commitcccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb (patch)
tree7f31b77ace4359e85dc3d3f66c853858c0bca7a4 /src/code.l
downloaddoxygen-cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb.tar.gz
doxygen-cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb.tar.bz2
doxygen-cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb.zip
Imported Upstream version 1.8.2upstream/1.8.2
Diffstat (limited to 'src/code.l')
-rw-r--r--src/code.l3660
1 files changed, 3660 insertions, 0 deletions
diff --git a/src/code.l b/src/code.l
new file mode 100644
index 0000000..d365c7c
--- /dev/null
+++ b/src/code.l
@@ -0,0 +1,3660 @@
+/******************************************************************************
+ *
+ *
+ *
+ * Copyright (C) 1997-2012 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <qregexp.h>
+#include <qdir.h>
+
+#include "qtbc.h"
+#include "entry.h"
+#include "doxygen.h"
+#include "message.h"
+#include "outputlist.h"
+#include "util.h"
+#include "membername.h"
+#include "searchindex.h"
+#include "arguments.h"
+
+#define YY_NEVER_INTERACTIVE 1
+
+// Toggle for some debugging info
+//#define DBG_CTX(x) fprintf x
+#define DBG_CTX(x) do { } while(0)
+
+#define CLASSBLOCK (int *)4
+#define SCOPEBLOCK (int *)8
+#define INNERBLOCK (int *)12
+
+/* -----------------------------------------------------------------
+ * statics
+ */
+
+static CodeOutputInterface * g_code;
+
+static ClassSDict *g_codeClassSDict = 0;
+static QCString g_curClassName;
+static QStrList g_curClassBases;
+
+static QCString g_parmType;
+static QCString g_parmName;
+
+static const char * g_inputString; //!< the code fragment as text
+static int g_inputPosition; //!< read offset during parsing
+static int g_inputLines; //!< number of line in the code fragment
+static int g_yyLineNr; //!< current line number
+static bool g_needsTermination;
+
+static bool g_exampleBlock;
+static QCString g_exampleName;
+static QCString g_exampleFile;
+
+static bool g_insideTemplate = FALSE;
+static QCString g_type;
+static QCString g_name;
+static QCString g_args;
+static QCString g_classScope;
+static QCString g_realScope;
+static QStack<int> g_scopeStack; //!< 1 if bracket starts a scope,
+ // 2 for internal blocks
+static int g_anchorCount;
+static FileDef * g_sourceFileDef;
+static bool g_lineNumbers;
+static Definition * g_currentDefinition;
+static MemberDef * g_currentMemberDef;
+static bool g_includeCodeFragment;
+static const char * g_currentFontClass;
+static bool g_searchingForBody;
+static bool g_insideBody;
+static int g_bodyCurlyCount;
+static QCString g_saveName;
+static QCString g_saveType;
+static QCString g_delimiter;
+
+static int g_bracketCount = 0;
+static int g_curlyCount = 0;
+static int g_sharpCount = 0;
+static bool g_inFunctionTryBlock = FALSE;
+static bool g_inForEachExpression = FALSE;
+
+static int g_lastTemplCastContext;
+static int g_lastSpecialCContext;
+static int g_lastStringContext;
+static int g_lastSkipCppContext;
+static int g_lastVerbStringContext;
+static int g_memCallContext;
+static int g_lastCContext;
+
+static bool g_insideObjC;
+static bool g_insideProtocolList;
+
+static bool g_lexInit = FALSE;
+
+static QStack<int> g_classScopeLengthStack;
+
+static Definition *g_searchCtx;
+
+// context for an Objective-C method call
+struct ObjCCallCtx
+{
+ int id;
+ QCString methodName;
+ QCString objectTypeOrName;
+ ClassDef *objectType;
+ MemberDef *objectVar;
+ MemberDef *method;
+ QCString format;
+ int lexState;
+ int braceCount;
+};
+
+// globals for objective-C method calls
+static ObjCCallCtx *g_currentCtx=0;
+static int g_currentCtxId=0;
+static int g_currentNameId=0;
+static int g_currentObjId=0;
+static int g_currentWordId=0;
+static QStack<ObjCCallCtx> g_contextStack;
+static QIntDict<ObjCCallCtx> g_contextDict;
+static QIntDict<QCString> g_nameDict;
+static QIntDict<QCString> g_objectDict;
+static QIntDict<QCString> g_wordDict;
+static int g_braceCount=0;
+
+static void saveObjCContext();
+static void restoreObjCContext();
+
+static QCString g_forceTagReference;
+
+
+//-------------------------------------------------------------------
+
+/*! Represents a stack of variable to class mappings as found in the
+ * code. Each scope is enclosed in pushScope() and popScope() calls.
+ * Variables are added by calling addVariables() and one can search
+ * for variable using findVariable().
+ */
+class VariableContext
+{
+ public:
+ static const ClassDef *dummyContext;
+
+ class Scope : public SDict<ClassDef>
+ {
+ public:
+ Scope() : SDict<ClassDef>(17) {}
+ };
+
+ VariableContext()
+ {
+ m_scopes.setAutoDelete(TRUE);
+ }
+ virtual ~VariableContext()
+ {
+ }
+
+ void pushScope()
+ {
+ m_scopes.append(new Scope);
+ DBG_CTX((stderr,"** Push var context %d\n",m_scopes.count()));
+ }
+
+ void popScope()
+ {
+ if (m_scopes.count()>0)
+ {
+ DBG_CTX((stderr,"** Pop var context %d\n",m_scopes.count()));
+ m_scopes.remove(m_scopes.count()-1);
+ }
+ else
+ {
+ DBG_CTX((stderr,"** ILLEGAL: Pop var context\n"));
+ }
+ }
+
+ void clear()
+ {
+ m_scopes.clear();
+ m_globalScope.clear();
+ }
+
+ void clearExceptGlobal()
+ {
+ DBG_CTX((stderr,"** Clear var context\n"));
+ m_scopes.clear();
+ }
+
+ void addVariable(const QCString &type,const QCString &name);
+ ClassDef *findVariable(const QCString &name);
+
+ int count() const { return m_scopes.count(); }
+
+ private:
+ Scope m_globalScope;
+ QList<Scope> m_scopes;
+};
+
+void VariableContext::addVariable(const QCString &type,const QCString &name)
+{
+ //printf("VariableContext::addVariable(%s,%s)\n",type.data(),name.data());
+ QCString ltype = type.simplifyWhiteSpace();
+ QCString lname = name.simplifyWhiteSpace();
+ if (ltype.left(7)=="struct ")
+ {
+ ltype = ltype.right(ltype.length()-7);
+ }
+ else if (ltype.left(6)=="union ")
+ {
+ ltype = ltype.right(ltype.length()-6);
+ }
+ if (ltype.isEmpty() || lname.isEmpty()) return;
+ DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' g_currentDefinition=%s\n",
+ ltype.data(),lname.data(),g_currentDefinition?g_currentDefinition->name().data():"<none>"));
+ Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast();
+ ClassDef *varType;
+ int i=0;
+ if (
+ (varType=g_codeClassSDict->find(ltype)) || // look for class definitions inside the code block
+ (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,ltype)) // look for global class definitions
+ )
+ {
+ DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data()));
+ scope->append(lname,varType); // add it to a list
+ }
+ else if ((i=ltype.find('<'))!=-1)
+ {
+ // probably a template class
+ QCString typeName(ltype.left(i));
+ ClassDef* newDef = 0;
+ QCString templateArgs(ltype.right(ltype.length() - i));
+ if (
+ ( // look for class definitions inside the code block
+ (varType=g_codeClassSDict->find(typeName)) ||
+ // otherwise look for global class definitions
+ (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,typeName,0,0,TRUE,TRUE))
+ ) && // and it must be a template
+ varType->templateArguments())
+ {
+ newDef = varType->getVariableInstance( templateArgs );
+ }
+ if (newDef)
+ {
+ DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data()));
+ scope->append(lname, newDef);
+ }
+ else
+ {
+ // Doesn't seem to be a template. Try just the base name.
+ addVariable(typeName,name);
+ }
+ }
+ else
+ {
+ if (m_scopes.count()>0) // for local variables add a dummy entry so the name
+ // is hidden to avoid false links to global variables with the same name
+ // TODO: make this work for namespaces as well!
+ {
+ DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data()));
+ scope->append(lname,dummyContext);
+ }
+ else
+ {
+ DBG_CTX((stderr,"** addVariable: not adding variable!\n"));
+ }
+ }
+}
+
+ClassDef *VariableContext::findVariable(const QCString &name)
+{
+ if (name.isEmpty()) return 0;
+ ClassDef *result = 0;
+ //QListIterator<Scope> sli(m_scopes);
+ Scope *scope;
+ QCString key = name;
+ // search from inner to outer scope
+ scope = m_scopes.last();
+ //for (sli.toLast();(scope=sli.current());--sli)
+ while (scope)
+ {
+ result = scope->find(key);
+ if (result)
+ {
+ DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result));
+ return result;
+ }
+ scope = m_scopes.prev();
+ }
+ // nothing found -> also try the global scope
+ result=m_globalScope.find(name);
+ DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result));
+ return result;
+}
+
+static VariableContext g_theVarContext;
+const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8;
+
+//-------------------------------------------------------------------
+
+class CallContext
+{
+ public:
+ struct Ctx
+ {
+ Ctx() : name(g_name), type(g_type), cd(0) {}
+ QCString name;
+ QCString type;
+ ClassDef *cd;
+ };
+
+ CallContext()
+ {
+ m_classList.append(new Ctx);
+ m_classList.setAutoDelete(TRUE);
+ }
+ virtual ~CallContext() {}
+ void setClass(ClassDef *cd)
+ {
+ Ctx *ctx = m_classList.getLast();
+ if (ctx)
+ {
+ DBG_CTX((stderr,"** Set call context %s (%p)\n",cd==0 ? "<null>" : cd->name().data(),cd));
+ ctx->cd=cd;
+ }
+ }
+ void pushScope()
+ {
+ m_classList.append(new Ctx);
+ DBG_CTX((stderr,"** Push call context %d\n",m_classList.count()));
+ }
+ void popScope()
+ {
+ if (m_classList.count()>1)
+ {
+ DBG_CTX((stderr,"** Pop call context %d\n",m_classList.count()));
+ Ctx *ctx = m_classList.getLast();
+ if (ctx)
+ {
+ g_name = ctx->name;
+ g_type = ctx->type;
+ }
+ m_classList.removeLast();
+ }
+ else
+ {
+ DBG_CTX((stderr,"** ILLEGAL: Pop call context\n"));
+ }
+ }
+ void clear()
+ {
+ DBG_CTX((stderr,"** Clear call context\n"));
+ m_classList.clear();
+ m_classList.append(new Ctx);
+ }
+ ClassDef *getClass() const
+ {
+ Ctx *ctx = m_classList.getLast();
+ if (ctx) return ctx->cd; else return 0;
+ }
+
+ private:
+ QList<Ctx> m_classList;
+};
+
+static CallContext g_theCallContext;
+
+//-------------------------------------------------------------------
+
+/*! add class/namespace name s to the scope */
+static void pushScope(const char *s)
+{
+ g_classScopeLengthStack.push(new int(g_classScope.length()));
+ if (g_classScope.isEmpty())
+ {
+ g_classScope = s;
+ }
+ else
+ {
+ g_classScope += "::";
+ g_classScope += s;
+ }
+ //printf("pushScope(%s) result: `%s'\n",s,g_classScope.data());
+}
+
+/*! remove the top class/namespace name from the scope */
+static void popScope()
+{
+ if (!g_classScopeLengthStack.isEmpty())
+ {
+ int *pLength = g_classScopeLengthStack.pop();
+ g_classScope.truncate(*pLength);
+ delete pLength;
+ }
+ else
+ {
+ //err("Error: Too many end of scopes found!\n");
+ }
+ //printf("popScope() result: `%s'\n",g_classScope.data());
+}
+
+static void setCurrentDoc(const QCString &anchor)
+{
+ if (Doxygen::searchIndex)
+ {
+ if (g_searchCtx)
+ {
+ Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
+ }
+ else
+ {
+ Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
+ }
+ }
+}
+
+static void addToSearchIndex(const char *text)
+{
+ if (Doxygen::searchIndex)
+ {
+ Doxygen::searchIndex->addWord(text,FALSE);
+ }
+}
+
+static void setClassScope(const QCString &name)
+{
+ //printf("setClassScope(%s)\n",name.data());
+ QCString n=name;
+ n=n.simplifyWhiteSpace();
+ int ts=n.find('<'); // start of template
+ int te=n.findRev('>'); // end of template
+ //printf("ts=%d te=%d\n",ts,te);
+ if (ts!=-1 && te!=-1 && te>ts)
+ {
+ // remove template from scope
+ n=n.left(ts)+n.right(n.length()-te-1);
+ }
+ while (!g_classScopeLengthStack.isEmpty())
+ {
+ popScope();
+ }
+ g_classScope.resize(0);
+ int i;
+ while ((i=n.find("::"))!=-1)
+ {
+ pushScope(n.left(i));
+ n = n.mid(i+2);
+ }
+ pushScope(n);
+ //printf("--->New class scope `%s'\n",g_classScope.data());
+}
+
+/*! start a new line of code, inserting a line number if g_sourceFileDef
+ * is TRUE. If a definition starts at the current line, then the line
+ * number is linked to the documentation of that definition.
+ */
+static void startCodeLine()
+{
+ //if (g_currentFontClass) { g_code->endFontClass(); }
+ if (g_sourceFileDef && g_lineNumbers)
+ {
+ //QCString lineNumber,lineAnchor;
+ //lineNumber.sprintf("%05d",g_yyLineNr);
+ //lineAnchor.sprintf("l%05d",g_yyLineNr);
+
+ Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
+ //printf("%s:startCodeLine(%d)=%p\n",g_sourceFileDef->name().data(),g_yyLineNr,d);
+ if (!g_includeCodeFragment && d)
+ {
+ g_currentDefinition = d;
+ g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
+ //printf("->startCodeLine(%s)=%p\n",d->name().data(),g_currentMemberDef);
+ g_insideBody = FALSE;
+ g_searchingForBody = TRUE;
+ g_realScope = d->name();
+ //g_classScope = "";
+ g_type.resize(0);
+ g_name.resize(0);
+ g_args.resize(0);
+ g_parmType.resize(0);
+ g_parmName.resize(0);
+ //printf("Real scope: `%s'\n",g_realScope.data());
+ g_bodyCurlyCount = 0;
+ QCString lineAnchor;
+ lineAnchor.sprintf("l%05d",g_yyLineNr);
+ if (g_currentMemberDef)
+ {
+ g_code->writeLineNumber(g_currentMemberDef->getReference(),
+ g_currentMemberDef->getOutputFileBase(),
+ g_currentMemberDef->anchor(),g_yyLineNr);
+ setCurrentDoc(lineAnchor);
+ }
+ else if (d->isLinkableInProject())
+ {
+ g_code->writeLineNumber(d->getReference(),
+ d->getOutputFileBase(),
+ 0,g_yyLineNr);
+ setCurrentDoc(lineAnchor);
+ }
+ }
+ else
+ {
+ g_code->writeLineNumber(0,0,0,g_yyLineNr);
+ }
+ }
+ g_code->startCodeLine(g_sourceFileDef && g_lineNumbers);
+ if (g_currentFontClass)
+ {
+ g_code->startFontClass(g_currentFontClass);
+ }
+}
+
+
+static void endFontClass();
+static void startFontClass(const char *s);
+
+static void endCodeLine()
+{
+ endFontClass();
+ g_code->endCodeLine();
+}
+
+static void nextCodeLine()
+{
+ const char * fc = g_currentFontClass;
+ endCodeLine();
+ if (g_yyLineNr<g_inputLines)
+ {
+ g_currentFontClass = fc;
+ startCodeLine();
+ }
+}
+
+/*! write a code fragment `text' that may span multiple lines, inserting
+ * line numbers for each line.
+ */
+static void codifyLines(const char *text)
+{
+ //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
+ const char *p=text,*sp=p;
+ char c;
+ bool done=FALSE;
+ while (!done)
+ {
+ sp=p;
+ while ((c=*p++) && c!='\n') { }
+ if (c=='\n')
+ {
+ g_yyLineNr++;
+ //*(p-1)='\0';
+ int l = p-sp-1;
+ char *tmp = (char*)malloc(l+1);
+ memcpy(tmp,sp,l);
+ tmp[l]='\0';
+ g_code->codify(tmp);
+ free(tmp);
+ nextCodeLine();
+ }
+ else
+ {
+ g_code->codify(sp);
+ done=TRUE;
+ }
+ }
+}
+
+/*! writes a link to a fragment \a text that may span multiple lines, inserting
+ * line numbers for each line. If \a text contains newlines, the link will be
+ * split into multiple links with the same destination, one for each line.
+ */
+static void writeMultiLineCodeLink(CodeOutputInterface &ol,
+ const char *ref,const char *file,
+ const char *anchor,const char *text,
+ const char *tooltip)
+{
+ bool done=FALSE;
+ char *p=(char *)text;
+ while (!done)
+ {
+ char *sp=p;
+ char c;
+ while ((c=*p++) && c!='\n') { }
+ if (c=='\n')
+ {
+ g_yyLineNr++;
+ *(p-1)='\0';
+ //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
+ ol.writeCodeLink(ref,file,anchor,sp,tooltip);
+ nextCodeLine();
+ }
+ else
+ {
+ //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
+ ol.writeCodeLink(ref,file,anchor,sp,tooltip);
+ done=TRUE;
+ }
+ }
+}
+
+static void addType()
+{
+ if (g_name=="const") { g_name.resize(0); return; }
+ if (!g_type.isEmpty()) g_type += ' ' ;
+ g_type += g_name ;
+ g_name.resize(0) ;
+ if (!g_type.isEmpty()) g_type += ' ' ;
+ g_type += g_args ;
+ g_args.resize(0) ;
+}
+
+static void addParmType()
+{
+ if (g_parmName=="const") { g_parmName.resize(0); return; }
+ if (!g_parmType.isEmpty()) g_parmType += ' ' ;
+ g_parmType += g_parmName ;
+ g_parmName.resize(0) ;
+}
+
+static void addUsingDirective(const char *name)
+{
+ if (g_sourceFileDef && name)
+ {
+ NamespaceDef *nd = Doxygen::namespaceSDict->find(name);
+ if (nd)
+ {
+ g_sourceFileDef->addUsingDirective(nd);
+ }
+ }
+}
+
+static void setParameterList(MemberDef *md)
+{
+ g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : "";
+ LockingPtr<ArgumentList> al = md->argumentList();
+ if (al==0) return;
+ Argument *a = al->first();
+ while (a)
+ {
+ g_parmName = a->name.copy();
+ g_parmType = a->type.copy();
+ int i = g_parmType.find('*');
+ if (i!=-1) g_parmType = g_parmType.left(i);
+ i = g_parmType.find('&');
+ if (i!=-1) g_parmType = g_parmType.left(i);
+ g_parmType.stripPrefix("const ");
+ g_parmType=g_parmType.stripWhiteSpace();
+ g_theVarContext.addVariable(g_parmType,g_parmName);
+ a = al->next();
+ }
+}
+
+static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
+{
+ int pos=0;
+ QCString type = s;
+ QCString className;
+ QCString templSpec;
+ while (extractClassNameFromType(type,pos,className,templSpec)!=-1)
+ {
+ QCString clName=className+templSpec;
+ ClassDef *cd=0;
+ if (!g_classScope.isEmpty())
+ {
+ cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName);
+ }
+ if (cd==0)
+ {
+ cd=getResolvedClass(d,g_sourceFileDef,clName);
+ }
+ //printf("stripClass trying `%s' = %p\n",clName.data(),cd);
+ if (cd)
+ {
+ return cd;
+ }
+ }
+
+ return 0;
+}
+
+static MemberDef *setCallContextForVar(const QCString &name)
+{
+ if (name.isEmpty()) return 0;
+ //fprintf(stderr,"setCallContextForVar(%s) g_classScope=%s\n",name.data(),g_classScope.data());
+
+ int scopeEnd = name.findRev("::");
+ if (scopeEnd!=-1) // name with explicit scope
+ {
+ QCString scope = name.left(scopeEnd);
+ QCString locName = name.right(name.length()-scopeEnd-2);
+ //printf("explicit scope: name=%s scope=%s\n",locName.data(),scope.data());
+ ClassDef *mcd = getClass(scope);
+ if (mcd && !locName.isEmpty())
+ {
+ MemberDef *md=mcd->getMemberByName(locName);
+ if (md)
+ {
+ //printf("name=%s scope=%s\n",locName.data(),scope.data());
+ g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
+ return md;
+ }
+ }
+ else // check namespace as well
+ {
+ NamespaceDef *mnd = getResolvedNamespace(scope);
+ if (mnd && !locName.isEmpty())
+ {
+ MemberDef *md=mnd->getMemberByName(locName);
+ if (md)
+ {
+ //printf("name=%s scope=%s\n",locName.data(),scope.data());
+ g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
+ return md;
+ }
+ }
+ }
+ }
+
+ MemberName *mn;
+ ClassDef *mcd = g_theVarContext.findVariable(name);
+ if (mcd) // local variable
+ {
+ //fprintf(stderr,"local variable?\n");
+ if (mcd!=VariableContext::dummyContext)
+ {
+ //fprintf(stderr,"local var `%s' mcd=%s\n",name.data(),mcd->name().data());
+ g_theCallContext.setClass(mcd);
+ }
+ }
+ else
+ {
+ //fprintf(stderr,"class member? scope=%s\n",g_classScope.data());
+ // look for a class member
+ mcd = getClass(g_classScope);
+ if (mcd)
+ {
+ //fprintf(stderr,"Inside class %s\n",mcd->name().data());
+ MemberDef *md=mcd->getMemberByName(name);
+ if (md)
+ {
+ //fprintf(stderr,"Found member %s\n",md->name().data());
+ if (g_scopeStack.top()!=CLASSBLOCK)
+ {
+ //fprintf(stderr,"class member `%s' mcd=%s\n",name.data(),mcd->name().data());
+ g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
+ }
+ return md;
+ }
+ }
+ }
+
+ // look for a global member
+ if ((mn=Doxygen::functionNameSDict->find(name)))
+ {
+ //printf("global var `%s'\n",name.data());
+ if (mn->count()==1) // global defined only once
+ {
+ MemberDef *md=mn->getFirst();
+ if (!md->isStatic() || md->getBodyDef()==g_sourceFileDef)
+ {
+ g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
+ return md;
+ }
+ return 0;
+ }
+ else if (mn->count()>1) // global defined more than once
+ {
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ //printf("mn=%p md=%p md->getBodyDef()=%p g_sourceFileDef=%p\n",
+ // mn,md,
+ // md->getBodyDef(),g_sourceFileDef);
+
+ // in case there are multiple members we could link to, we
+ // only link to members if defined in the same file or
+ // defined as external.
+ if ((!md->isStatic() || md->getBodyDef()==g_sourceFileDef) &&
+ (g_forceTagReference.isEmpty() || g_forceTagReference==md->getReference())
+ )
+ {
+ g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
+ //printf("returning member %s in source file %s\n",md->name().data(),g_sourceFileDef->name().data());
+ return md;
+ }
+ md=mn->next();
+ }
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static void updateCallContextForSmartPointer()
+{
+ ClassDef *cd = g_theCallContext.getClass();
+ //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? cd->name().data() : "<none>");
+ MemberDef *md;
+ if (cd && (md=cd->isSmartPointer()))
+ {
+ ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope());
+ if (ncd)
+ {
+ g_theCallContext.setClass(ncd);
+ //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data());
+ }
+ }
+}
+
+static void addDocCrossReference(MemberDef *src,MemberDef *dst)
+{
+ static bool referencedByRelation = Config_getBool("REFERENCED_BY_RELATION");
+ static bool referencesRelation = Config_getBool("REFERENCES_RELATION");
+ static bool callerGraph = Config_getBool("CALLER_GRAPH");
+ static bool callGraph = Config_getBool("CALL_GRAPH");
+
+ //printf("--> addDocCrossReference src=%s,dst=%s\n",src->name().data(),dst->name().data());
+ if (dst->isTypedef() || dst->isEnumerate()) return; // don't add types
+ if ((referencedByRelation || callerGraph || dst->hasCallerGraph()) &&
+ (src->isFunction() || src->isSlot())
+ )
+ {
+ dst->addSourceReferencedBy(src);
+ MemberDef *mdDef = dst->memberDefinition();
+ if (mdDef)
+ {
+ mdDef->addSourceReferencedBy(src);
+ }
+ MemberDef *mdDecl = dst->memberDeclaration();
+ if (mdDecl)
+ {
+ mdDecl->addSourceReferencedBy(src);
+ }
+ }
+ if ((referencesRelation || callGraph || src->hasCallGraph()) &&
+ (src->isFunction() || src->isSlot())
+ )
+ {
+ src->addSourceReferences(dst);
+ MemberDef *mdDef = src->memberDefinition();
+ if (mdDef)
+ {
+ mdDef->addSourceReferences(dst);
+ }
+ MemberDef *mdDecl = src->memberDeclaration();
+ if (mdDecl)
+ {
+ mdDecl->addSourceReferences(dst);
+ }
+ }
+
+}
+
+static bool getLinkInScope(const QCString &c, // scope
+ const QCString &m, // member
+ const char *memberText, // exact text
+ CodeOutputInterface &ol,
+ const char *text,
+ bool varOnly=FALSE
+ )
+{
+ MemberDef *md;
+ ClassDef *cd;
+ FileDef *fd;
+ NamespaceDef *nd;
+ GroupDef *gd;
+ //fprintf(stderr,"getLinkInScope: trying `%s'::`%s' varOnly=%d\n",c.data(),m.data(),varOnly);
+ if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef,FALSE,g_forceTagReference) &&
+ md->isLinkable() && (!varOnly || md->isVariable()))
+ {
+ //printf("found it %s!\n",md->qualifiedName().data());
+ if (g_exampleBlock)
+ {
+ QCString anchor;
+ anchor.sprintf("a%d",g_anchorCount);
+ //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
+ // g_exampleFile.data());
+ if (md->addExample(anchor,g_exampleName,g_exampleFile))
+ {
+ ol.writeCodeAnchor(anchor);
+ g_anchorCount++;
+ }
+ }
+
+ Definition *d = md->getOuterScope()==Doxygen::globalScope ?
+ md->getBodyDef() : md->getOuterScope();
+ if (md->getGroupDef()) d = md->getGroupDef();
+ if (d && d->isLinkable())
+ {
+ g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
+ //printf("g_currentDefinition=%p g_currentMemberDef=%p g_insideBody=%d\n",
+ // g_currentDefinition,g_currentMemberDef,g_insideBody);
+
+ if (g_currentDefinition && g_currentMemberDef &&
+ md!=g_currentMemberDef && g_insideBody)
+ {
+ addDocCrossReference(g_currentMemberDef,md);
+ }
+ //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());
+
+ ol.linkableSymbol(g_yyLineNr,md->name(),md,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ writeMultiLineCodeLink(ol,md->getReference(),
+ md->getOutputFileBase(),
+ md->anchor(),
+ text ? text : memberText,
+ md->briefDescriptionAsTooltip());
+ addToSearchIndex(text ? text : memberText);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static bool getLink(const char *className,
+ const char *memberName,
+ CodeOutputInterface &ol,
+ const char *text=0,
+ bool varOnly=FALSE)
+{
+ //printf("getLink(%s,%s) g_curClassName=%s\n",className,memberName,g_curClassName.data());
+ QCString m=removeRedundantWhiteSpace(memberName);
+ QCString c=className;
+ if (!getLinkInScope(c,m,memberName,ol,text,varOnly))
+ {
+ if (!g_curClassName.isEmpty())
+ {
+ if (!c.isEmpty()) c.prepend("::");
+ c.prepend(g_curClassName);
+ return getLinkInScope(c,m,memberName,ol,text,varOnly);
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName,
+ bool typeOnly=FALSE,bool varOnly=FALSE)
+{
+ int i=0;
+ if (*clName=='~') // correct for matching negated values i.s.o. destructors.
+ {
+ g_code->codify("~");
+ clName++;
+ }
+ QCString className=clName;
+ if (className.isEmpty()) return;
+ if (g_insideProtocolList) // for Obj-C
+ {
+ className+="-p";
+ }
+ className = substitute(className,"\\","::"); // for PHP namespaces
+ ClassDef *cd=0,*lcd=0;
+ MemberDef *md=0;
+ bool isLocal=FALSE;
+
+ //printf("generateClassOrGlobalLink(className=%s)\n",className.data());
+ if ((lcd=g_theVarContext.findVariable(className))==0) // not a local variable
+ {
+ Definition *d = g_currentDefinition;
+ //printf("d=%s g_sourceFileDef=%s\n",d?d->name().data():"<none>",g_sourceFileDef?g_sourceFileDef->name().data():"<none>");
+ cd = getResolvedClass(d,g_sourceFileDef,className,&md);
+ //fprintf(stderr,"non-local variable name=%s context=%d cd=%s md=%s!\n",
+ // className.data(),g_theVarContext.count(),cd?cd->name().data():"<none>",
+ // md?md->name().data():"<none>");
+ if (cd==0 && md==0 && (i=className.find('<'))!=-1)
+ {
+ QCString bareName = className.left(i); //stripTemplateSpecifiersFromScope(className);
+ //fprintf(stderr,"bareName=%s\n",bareName.data());
+ if (bareName!=className)
+ {
+ cd=getResolvedClass(d,g_sourceFileDef,bareName,&md); // try unspecialized version
+ }
+ }
+ //printf("md=%s\n",md?md->name().data():"<none>");
+ //fprintf(stderr,"is found as a type %s\n",cd?cd->name().data():"<null>");
+ if (cd==0 && md==0) // also see if it is variable or enum or enum value
+ {
+ if (getLink(g_classScope,clName,ol,clName,varOnly))
+ {
+ return;
+ }
+ }
+ }
+ else
+ {
+ //printf("local variable!\n");
+ if (lcd!=VariableContext::dummyContext)
+ {
+ //printf("non-dummy context lcd=%s!\n",lcd->name().data());
+ g_theCallContext.setClass(lcd);
+
+ // to following is needed for links to a global variable, but is
+ // no good for a link to a local variable that is also a global symbol.
+
+ //if (getLink(g_classScope,clName,ol,clName))
+ //{
+ //return;
+ //}
+ }
+ isLocal=TRUE;
+ //fprintf(stderr,"is a local variable cd=%p!\n",cd);
+ }
+ if (cd && cd->isLinkable()) // is it a linkable class
+ {
+ //fprintf(stderr,"is linkable class %s\n",clName);
+ if (g_exampleBlock)
+ {
+ QCString anchor;
+ anchor.sprintf("_a%d",g_anchorCount);
+ //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
+ // g_exampleFile.data());
+ if (cd->addExample(anchor,g_exampleName,g_exampleFile))
+ {
+ ol.writeCodeAnchor(anchor);
+ g_anchorCount++;
+ }
+ }
+ ol.linkableSymbol(g_yyLineNr,cd->name(),cd,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ writeMultiLineCodeLink(ol,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),clName,cd->briefDescriptionAsTooltip());
+ addToSearchIndex(className);
+ g_theCallContext.setClass(cd);
+ if (md)
+ {
+ Definition *d = md->getOuterScope()==Doxygen::globalScope ?
+ md->getBodyDef() : md->getOuterScope();
+ if (md->getGroupDef()) d = md->getGroupDef();
+ if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef)
+ {
+ addDocCrossReference(g_currentMemberDef,md);
+ }
+ }
+ }
+ else // not a class, maybe a global member
+ {
+ //fprintf(stderr,"class %s not linkable! cd=%p md=%p typeOnly=%d\n",clName,cd,md,typeOnly);
+ if (!isLocal && (md!=0 || (cd==0 && !typeOnly))) // not a class, see if it is a global enum/variable/typedef.
+ {
+ if (md==0) // not found as a typedef
+ {
+ md = setCallContextForVar(clName);
+ //printf("setCallContextForVar(%s) md=%p g_currentDefinition=%p\n",clName,md,g_currentDefinition);
+ if (md && g_currentDefinition)
+ {
+ //fprintf(stderr,"%s accessible from %s? %d md->getOuterScope=%s\n",
+ // md->name().data(),g_currentDefinition->name().data(),
+ // isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md),
+ // md->getOuterScope()->name().data());
+ }
+
+ if (md && g_currentDefinition &&
+ isAccessibleFrom(g_currentDefinition,g_sourceFileDef,md)==-1)
+ {
+ md=0; // variable not accessible
+ }
+ }
+ if (md && (!varOnly || md->isVariable()))
+ {
+ //fprintf(stderr,"is a global md=%p g_currentDefinition=%s linkable=%d\n",md,g_currentDefinition?g_currentDefinition->name().data():"<none>",md->isLinkable());
+ if (md->isLinkable())
+ {
+ QCString text;
+ if (!g_forceTagReference.isEmpty()) // explicit reference to symbol in tag file
+ {
+ text=g_forceTagReference;
+ if (text.right(4)==".tag") // strip .tag if present
+ {
+ text=text.left(text.length()-4);
+ }
+ text+=getLanguageSpecificSeparator(md->getLanguage());
+ text+=clName;
+ md->setName(text);
+ md->setLocalName(text);
+ }
+ else // normal reference
+ {
+ text=clName;
+ }
+ ol.linkableSymbol(g_yyLineNr,md->name(),md,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ writeMultiLineCodeLink(ol,md->getReference(),md->getOutputFileBase(),md->anchor(),text,md->briefDescriptionAsTooltip());
+ addToSearchIndex(clName);
+ if (g_currentMemberDef)
+ {
+ addDocCrossReference(g_currentMemberDef,md);
+ }
+ return;
+ }
+ }
+ }
+
+ // nothing found, just write out the word
+ //fprintf(stderr,"not found!\n");
+ ol.linkableSymbol(g_yyLineNr,clName,0,
+ g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
+ codifyLines(clName);
+ addToSearchIndex(clName);
+ }
+}
+
+static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const char *memName)
+{
+ // extract class definition of the return type in order to resolve
+ // a->b()->c() like call chains
+
+ //printf("type=`%s' args=`%s' class=%s\n",
+ // xmd->typeString(),xmd->argsString(),
+ // xmd->getClassDef()->name().data());
+
+ if (g_exampleBlock)
+ {
+ QCString anchor;
+ anchor.sprintf("a%d",g_anchorCount);
+ //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
+ // g_exampleFile.data());
+ if (xmd->addExample(anchor,g_exampleName,g_exampleFile))
+ {
+ ol.writeCodeAnchor(anchor);
+ g_anchorCount++;
+ }
+ }
+
+ ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope());
+ //fprintf(stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass);
+ g_theCallContext.setClass(typeClass);
+
+ Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
+ xmd->getBodyDef() : xmd->getOuterScope();
+ if (xmd->getGroupDef()) xd = xmd->getGroupDef();
+ if (xd && xd->isLinkable())
+ {
+
+ //printf("g_currentDefiniton=%p g_currentMemberDef=%p xmd=%p g_insideBody=%d\n",g_currentDefinition,g_currentMemberDef,xmd,g_insideBody);
+
+ if (xmd->templateMaster()) xmd = xmd->templateMaster();
+
+ if (xmd->isLinkable())
+ {
+ // add usage reference
+ if (g_currentDefinition && g_currentMemberDef &&
+ /*xmd!=g_currentMemberDef &&*/ g_insideBody)
+ {
+ addDocCrossReference(g_currentMemberDef,xmd);
+ }
+
+ // write the actual link
+ ol.linkableSymbol(g_yyLineNr,xmd->name(),xmd,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ writeMultiLineCodeLink(ol,xmd->getReference(),
+ xmd->getOutputFileBase(),xmd->anchor(),memName,xmd->briefDescriptionAsTooltip());
+ addToSearchIndex(memName);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static bool generateClassMemberLink(CodeOutputInterface &ol,ClassDef *mcd,const char *memName)
+{
+ if (mcd)
+ {
+ MemberDef *xmd = mcd->getMemberByName(memName);
+ //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",mcd->name().data(),memName,xmd);
+ if (xmd)
+ {
+ return generateClassMemberLink(ol,xmd,memName);
+ }
+ }
+
+ return FALSE;
+}
+
+static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName,
+ char *memName)
+{
+ //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n",
+ // varName.data(),memName,g_classScope.data());
+
+ if (varName.isEmpty()) return;
+
+ // look for the variable in the current context
+ ClassDef *vcd = g_theVarContext.findVariable(varName);
+ if (vcd)
+ {
+ if (vcd!=VariableContext::dummyContext)
+ {
+ //printf("Class found!\n");
+ if (getLink(vcd->name(),memName,ol))
+ {
+ //printf("Found result!\n");
+ return;
+ }
+ if (vcd->baseClasses())
+ {
+ BaseClassListIterator bcli(*vcd->baseClasses());
+ for ( ; bcli.current() ; ++bcli)
+ {
+ if (getLink(bcli.current()->classDef->name(),memName,ol))
+ {
+ //printf("Found result!\n");
+ return;
+ }
+ }
+ }
+ }
+ }
+ else // variable not in current context, maybe it is in a parent context
+ {
+ vcd = getResolvedClass(g_currentDefinition,g_sourceFileDef,g_classScope);
+ if (vcd && vcd->isLinkable())
+ {
+ //printf("Found class %s for variable `%s'\n",g_classScope.data(),varName.data());
+ MemberName *vmn=Doxygen::memberNameSDict->find(varName);
+ if (vmn==0)
+ {
+ int vi;
+ QCString vn=varName;
+ QCString scope;
+ if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1) // explicit scope A::b(), probably static member
+ {
+ ClassDef *jcd = getClass(vn.left(vi));
+ vn=vn.right(vn.length()-vi-2);
+ vmn=Doxygen::memberNameSDict->find(vn);
+ //printf("Trying name `%s' scope=%s\n",vn.data(),scope.data());
+ if (vmn)
+ {
+ MemberNameIterator vmni(*vmn);
+ MemberDef *vmd;
+ for (;(vmd=vmni.current());++vmni)
+ {
+ if (/*(vmd->isVariable() || vmd->isFunction()) && */
+ vmd->getClassDef()==jcd)
+ {
+ //printf("Found variable type=%s\n",vmd->typeString());
+ ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
+ if (mcd && mcd->isLinkable())
+ {
+ if (generateClassMemberLink(ol,mcd,memName)) return;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (vmn)
+ {
+ //printf("There is a variable with name `%s'\n",varName);
+ MemberNameIterator vmni(*vmn);
+ MemberDef *vmd;
+ for (;(vmd=vmni.current());++vmni)
+ {
+ if (/*(vmd->isVariable() || vmd->isFunction()) && */
+ vmd->getClassDef()==vcd)
+ {
+ //printf("Found variable type=%s\n",vmd->typeString());
+ ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
+ if (mcd && mcd->isLinkable())
+ {
+ if (generateClassMemberLink(ol,mcd,memName)) return;
+ }
+ }
+ }
+ }
+ }
+ }
+ // nothing found -> write result as is
+ ol.linkableSymbol(g_yyLineNr,memName,0,
+ g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
+ codifyLines(memName);
+ addToSearchIndex(memName);
+ return;
+}
+
+static void generatePHPVariableLink(CodeOutputInterface &ol,const char *varName)
+{
+ QCString name = varName+7; // strip $this->
+ name.prepend("$");
+ //printf("generatePHPVariableLink(%s) name=%s scope=%s\n",varName,name.data(),g_classScope.data());
+ if (!getLink(g_classScope,name,ol,varName))
+ {
+ codifyLines(varName);
+ }
+}
+
+static void generateFunctionLink(CodeOutputInterface &ol,const char *funcName)
+{
+ //CodeClassDef *ccd=0;
+ ClassDef *ccd=0;
+ QCString locScope=g_classScope;
+ QCString locFunc=removeRedundantWhiteSpace(funcName);
+ QCString funcScope;
+ QCString funcWithScope=locFunc;
+ QCString funcWithFullScope=locFunc;
+ QCString fullScope=locScope;
+ //fprintf(stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data());
+ int len=2;
+ int i=locFunc.findRev("::");
+ if (g_currentMemberDef && g_currentMemberDef->getClassDef() &&
+ funcName==g_currentMemberDef->localName() &&
+ g_currentMemberDef->getDefLine()==g_yyLineNr &&
+ generateClassMemberLink(ol,g_currentMemberDef,funcName)
+ )
+ {
+ // special case where funcName is the name of a method that is also
+ // defined on this line. In this case we can directly link to
+ // g_currentMemberDef, which is not only faster, but
+ // in case of overloaded methods, this will make sure that we link to
+ // the correct method, and thereby get the correct reimplemented relations.
+ // See also bug 549022.
+ goto exit;
+ }
+ if (i==-1) i=locFunc.findRev("."),len=1;
+ if (i==-1) i=locFunc.findRev("\\"),len=1; // for PHP
+ if (i>0)
+ {
+ funcScope=locFunc.left(i);
+ locFunc=locFunc.right(locFunc.length()-i-len).stripWhiteSpace();
+ int ts=locScope.find('<'); // start of template
+ int te=locScope.findRev('>'); // end of template
+ //printf("ts=%d te=%d\n",ts,te);
+ if (ts!=-1 && te!=-1 && te>ts)
+ {
+ // remove template from scope
+ locScope=locScope.left(ts)+locScope.right(locScope.length()-te-1);
+ }
+ ts=funcScope.find('<'); // start of template
+ te=funcScope.findRev('>'); // end of template
+ //printf("ts=%d te=%d\n",ts,te);
+ if (ts!=-1 && te!=-1 && te>ts)
+ {
+ // remove template from scope
+ funcScope=funcScope.left(ts)+funcScope.right(funcScope.length()-te-1);
+ }
+ if (!funcScope.isEmpty())
+ {
+ funcWithScope = funcScope+"::"+locFunc;
+ if (!locScope.isEmpty())
+ {
+ fullScope=locScope+"::"+funcScope;
+ }
+ }
+ if (!locScope.isEmpty())
+ {
+ funcWithFullScope = locScope+"::"+funcWithScope;
+ }
+ }
+ if (!fullScope.isEmpty() && (ccd=g_codeClassSDict->find(fullScope)))
+ {
+ //printf("using classScope %s\n",g_classScope.data());
+ if (ccd->baseClasses())
+ {
+ BaseClassListIterator bcli(*ccd->baseClasses());
+ for ( ; bcli.current() ; ++bcli)
+ {
+ if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName))
+ {
+ goto exit;
+ }
+ }
+ }
+ }
+ if (!locScope.isEmpty() && fullScope!=locScope && (ccd=g_codeClassSDict->find(locScope)))
+ {
+ //printf("using classScope %s\n",g_classScope.data());
+ if (ccd->baseClasses())
+ {
+ BaseClassListIterator bcli(*ccd->baseClasses());
+ for ( ; bcli.current() ; ++bcli)
+ {
+ if (getLink(bcli.current()->classDef->name(),funcWithScope,ol,funcName))
+ {
+ goto exit;
+ }
+ }
+ }
+ }
+ if (!getLink(locScope,funcWithScope,ol,funcName))
+ {
+ generateClassOrGlobalLink(ol,funcName);
+ }
+exit:
+ g_forceTagReference.resize(0);
+ return;
+}
+
+/*! counts the number of lines in the input */
+static int countLines()
+{
+ const char *p=g_inputString;
+ char c;
+ int count=1;
+ while ((c=*p))
+ {
+ p++ ;
+ if (c=='\n') count++;
+ }
+ if (p>g_inputString && *(p-1)!='\n')
+ { // last line does not end with a \n, so we add an extra
+ // line and explicitly terminate the line after parsing.
+ count++,
+ g_needsTermination=TRUE;
+ }
+ return count;
+}
+
+static void endFontClass()
+{
+ if (g_currentFontClass)
+ {
+ g_code->endFontClass();
+ g_currentFontClass=0;
+ }
+}
+
+static void startFontClass(const char *s)
+{
+ endFontClass();
+ g_code->startFontClass(s);
+ g_currentFontClass=s;
+}
+
+//----------------------------------------------------------------------------
+
+// recursively writes a linkified Objective-C method call
+static void writeObjCMethodCall(ObjCCallCtx *ctx)
+{
+ if (ctx==0) return;
+ char c;
+ const char *p = ctx->format.data();
+ if (!ctx->methodName.isEmpty())
+ {
+ //printf("writeObjCMethodCall(%s) obj=%s method=%s\n",
+ // ctx->format.data(),ctx->objectTypeOrName.data(),ctx->methodName.data());
+ if (!ctx->objectTypeOrName.isEmpty() && ctx->objectTypeOrName.at(0)!='$')
+ {
+ //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(),
+ // ctx->methodName.data());
+ ClassDef *cd = g_theVarContext.findVariable(ctx->objectTypeOrName);
+ if (cd==0) // not a local variable
+ {
+ if (ctx->objectTypeOrName=="self")
+ {
+ if (g_currentDefinition &&
+ g_currentDefinition->definitionType()==Definition::TypeClass)
+ {
+ ctx->objectType = (ClassDef *)g_currentDefinition;
+ }
+ }
+ else
+ {
+ ctx->objectType = getResolvedClass(
+ g_currentDefinition,
+ g_sourceFileDef,
+ ctx->objectTypeOrName,
+ &ctx->method);
+ }
+ //printf(" object is class? %p\n",ctx->objectType);
+ if (ctx->objectType) // found class
+ {
+ ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
+ //printf(" yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>");
+ }
+ else if (ctx->method==0) // search for class variable with the same name
+ {
+ //printf(" no\n");
+ //printf("g_currentDefinition=%p\n",g_currentDefinition);
+ if (g_currentDefinition &&
+ g_currentDefinition->definitionType()==Definition::TypeClass)
+ {
+ ctx->objectVar = ((ClassDef *)g_currentDefinition)->getMemberByName(ctx->objectTypeOrName);
+ //printf(" ctx->objectVar=%p\n",ctx->objectVar);
+ if (ctx->objectVar)
+ {
+ ctx->objectType = stripClassName(ctx->objectVar->typeString());
+ //printf(" ctx->objectType=%p\n",ctx->objectType);
+ if (ctx->objectType)
+ {
+ ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
+ //printf(" ctx->method=%p\n",ctx->method);
+ }
+ }
+ }
+ }
+ }
+ else // local variable
+ {
+ //printf(" object is local variable\n");
+ if (cd!=VariableContext::dummyContext)
+ {
+ ctx->method = cd->getMemberByName(ctx->methodName);
+ //printf(" class=%p method=%p\n",cd,ctx->method);
+ }
+ }
+ }
+ }
+
+ //printf("[");
+ while ((c=*p++)) // for each character in ctx->format
+ {
+ if (c=='$')
+ {
+ char nc=*p++;
+ if (nc=='$') // escaped $
+ {
+ g_code->codify("$");
+ }
+ else // name fragment or reference to a nested call
+ {
+ if (nc=='n') // name fragment
+ {
+ nc=*p++;
+ QCString refIdStr;
+ while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
+ p--;
+ int refId=refIdStr.toInt();
+ QCString *pName = g_nameDict.find(refId);
+ if (pName)
+ {
+ if (ctx->method && ctx->method->isLinkable())
+ {
+ g_code->linkableSymbol(g_yyLineNr,ctx->method->name(),ctx->method,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ writeMultiLineCodeLink(*g_code,
+ ctx->method->getReference(),
+ ctx->method->getOutputFileBase(),
+ ctx->method->anchor(),
+ pName->data(),
+ ctx->method->briefDescriptionAsTooltip());
+ if (g_currentMemberDef)
+ {
+ addDocCrossReference(g_currentMemberDef,ctx->method);
+ }
+ }
+ else
+ {
+ g_code->linkableSymbol(g_yyLineNr,pName->data(),0,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ codifyLines(pName->data());
+ }
+ }
+ else
+ {
+ //printf("Invalid name: id=%d\n",refId);
+ }
+ }
+ else if (nc=='o') // reference to potential object name
+ {
+ nc=*p++;
+ QCString refIdStr;
+ while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
+ p--;
+ int refId=refIdStr.toInt();
+ QCString *pObject = g_objectDict.find(refId);
+ if (pObject)
+ {
+ if (*pObject=="self")
+ {
+ if (g_currentDefinition &&
+ g_currentDefinition->definitionType()==Definition::TypeClass)
+ {
+ ctx->objectType = (ClassDef *)g_currentDefinition;
+ if (ctx->objectType->categoryOf())
+ {
+ ctx->objectType = ctx->objectType->categoryOf();
+ }
+ if (ctx->objectType)
+ {
+ ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
+ }
+ }
+ startFontClass("keyword");
+ codifyLines(pObject->data());
+ endFontClass();
+ }
+ else if (*pObject=="super")
+ {
+ if (g_currentDefinition &&
+ g_currentDefinition->definitionType()==Definition::TypeClass)
+ {
+ ClassDef *cd = (ClassDef *)g_currentDefinition;
+ if (cd->categoryOf())
+ {
+ cd = cd->categoryOf();
+ }
+ BaseClassList *bcd = cd->baseClasses();
+ if (bcd) // get direct base class (there should be only one)
+ {
+ BaseClassListIterator bli(*bcd);
+ BaseClassDef *bclass;
+ for (bli.toFirst();(bclass=bli.current());++bli)
+ {
+ if (bclass->classDef->compoundType()!=ClassDef::Protocol)
+ {
+ ctx->objectType = bclass->classDef;
+ if (ctx->objectType)
+ {
+ ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
+ }
+ }
+ }
+ }
+ }
+ startFontClass("keyword");
+ codifyLines(pObject->data());
+ endFontClass();
+ }
+ else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable
+ {
+ g_code->linkableSymbol(g_yyLineNr,ctx->objectVar->name(),ctx->objectVar,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ writeMultiLineCodeLink(*g_code,
+ ctx->objectVar->getReference(),
+ ctx->objectVar->getOutputFileBase(),
+ ctx->objectVar->anchor(),
+ pObject->data(),
+ ctx->objectVar->briefDescriptionAsTooltip());
+ if (g_currentMemberDef)
+ {
+ addDocCrossReference(g_currentMemberDef,ctx->objectVar);
+ }
+ }
+ else if (ctx->objectType &&
+ ctx->objectType!=VariableContext::dummyContext &&
+ ctx->objectType->isLinkable()
+ ) // object is class name
+ {
+ ClassDef *cd = ctx->objectType;
+ g_code->linkableSymbol(g_yyLineNr,cd->name(),cd,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ writeMultiLineCodeLink(*g_code,
+ cd->getReference(),
+ cd->getOutputFileBase(),
+ cd->anchor(),
+ pObject->data(),
+ cd->briefDescriptionAsTooltip());
+ }
+ else // object still needs to be resolved
+ {
+ ClassDef *cd = getResolvedClass(g_currentDefinition,
+ g_sourceFileDef, *pObject);
+ if (cd && cd->isLinkable())
+ {
+ if (ctx->objectType==0) ctx->objectType=cd;
+ g_code->linkableSymbol(g_yyLineNr,cd->name(),cd,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ writeMultiLineCodeLink(*g_code,
+ cd->getReference(),
+ cd->getOutputFileBase(),
+ cd->anchor(),
+ pObject->data(),
+ cd->briefDescriptionAsTooltip());
+ }
+ else
+ {
+ g_code->linkableSymbol(g_yyLineNr,pObject->data(),0,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ codifyLines(pObject->data());
+ }
+ }
+ }
+ else
+ {
+ //printf("Invalid object: id=%d\n",refId);
+ }
+ }
+ else if (nc=='c') // reference to nested call
+ {
+ nc=*p++;
+ QCString refIdStr;
+ while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
+ p--;
+ int refId=refIdStr.toInt();
+ ObjCCallCtx *ictx = g_contextDict.find(refId);
+ if (ictx) // recurse into nested call
+ {
+ writeObjCMethodCall(ictx);
+ if (ictx->method) // link to nested call successfully
+ {
+ // get the ClassDef representing the method's return type
+ if (QCString(ictx->method->typeString())=="id")
+ {
+ // see if the method name is unique, if so we link to it
+ MemberName *mn=Doxygen::memberNameSDict->find(ctx->methodName);
+ //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n",
+ // mn==0?-1:(int)mn->count(),
+ // ictx->method->name().data(),
+ // ctx->methodName.data());
+ if (mn && mn->count()==1) // member name unique
+ {
+ ctx->method = mn->getFirst();
+ }
+ }
+ else
+ {
+ ctx->objectType = stripClassName(ictx->method->typeString());
+ if (ctx->objectType)
+ {
+ ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
+ }
+ }
+ //printf(" ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType);
+ }
+ }
+ else
+ {
+ //printf("Invalid context: id=%d\n",refId);
+ }
+ }
+ else if (nc=='w') // some word
+ {
+ nc=*p++;
+ QCString refIdStr;
+ while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
+ p--;
+ int refId=refIdStr.toInt();
+ QCString *pWord = g_wordDict.find(refId);
+ if (pWord)
+ {
+ g_code->linkableSymbol(g_yyLineNr,pWord->data(),0,
+ g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
+ codifyLines(pWord->data());
+ }
+ }
+ else // illegal marker
+ {
+ ASSERT(!"invalid escape sequence");
+ }
+ }
+ }
+ else // normal non-marker character
+ {
+ char s[2];
+ s[0]=c;s[1]=0;
+ codifyLines(s);
+ }
+ }
+ //printf("%s %s]\n",ctx->objectTypeOrName.data(),ctx->methodName.data());
+ //printf("}=(type='%s',name='%s')",
+ // ctx->objectTypeOrName.data(),
+ // ctx->methodName.data());
+}
+
+// Replaces an Objective-C method name fragment s by a marker of the form
+// $n12, the number (12) can later be used as a key for obtaining the name
+// fragment, from g_nameDict
+static QCString escapeName(const char *s)
+{
+ QCString result;
+ result.sprintf("$n%d",g_currentNameId);
+ g_nameDict.insert(g_currentNameId,new QCString(s));
+ g_currentNameId++;
+ return result;
+}
+
+static QCString escapeObject(const char *s)
+{
+ QCString result;
+ result.sprintf("$o%d",g_currentObjId);
+ g_objectDict.insert(g_currentObjId,new QCString(s));
+ g_currentObjId++;
+ return result;
+}
+
+static QCString escapeWord(const char *s)
+{
+ QCString result;
+ result.sprintf("$w%d",g_currentWordId);
+ g_wordDict.insert(g_currentWordId,new QCString(s));
+ g_currentWordId++;
+ return result;
+}
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && g_inputString[g_inputPosition] )
+ {
+ *buf = g_inputString[g_inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+B [ \t]
+BN [ \t\n\r]
+ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
+SEP ("::"|"\\")
+SCOPENAME ({SEP}{BN}*)?({ID}{BN}*{SEP}{BN}*)*("~"{BN}*)?{ID}
+TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">"
+SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?{SEP}{BN}*)*)((~{BN}*)?{ID})
+SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*{SEP}{BN}*)+
+KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property")
+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})
+FLOWKW ("break"|"case"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"for"|"foreach"|"for each"|"goto"|"if"|"return"|"switch"|"throw"|"throws"|"try"|"while"|"@try"|"@catch"|"@finally")
+TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
+CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast")
+CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'"))
+ARITHOP "+"|"-"|"/"|"*"|"%"|"--"|"++"
+ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|="
+LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"
+BITOP "&"|"|"|"^"|"<<"|">>"|"~"
+OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
+RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"("
+RAWEND ")"[^ \t\(\)\\]{0,16}\"
+
+%option noyywrap
+
+%x SkipString
+%x SkipStringS
+%x SkipVerbString
+%x SkipCPP
+%x SkipComment
+%x SkipCxxComment
+%x RemoveSpecialCComment
+%x StripSpecialCComment
+%x Body
+%x FuncCall
+%x MemberCall
+%x MemberCall2
+%x SkipInits
+%x ClassName
+%x PackageName
+%x ClassVar
+%x CppCliTypeModifierFollowup
+%x Bases
+%x SkipSharp
+%x ReadInclude
+%x TemplDecl
+%x TemplCast
+%x CallEnd
+%x ObjCMethod
+%x ObjCParams
+%x ObjCParamType
+%x ObjCCall
+%x ObjCMName
+%x ObjCSkipStr
+%x OldStyleArgs
+%x UsingName
+%x RawString
+
+%%
+
+<*>\x0d
+<Body>^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") {
+ startFontClass("preprocessor");
+ g_code->codify(yytext);
+ BEGIN( ReadInclude );
+ }
+<Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ {
+ g_insideObjC=TRUE;
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ if (!g_insideTemplate)
+ BEGIN( ClassName );
+ }
+<Body>(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") {
+ if (g_insideTemplate) REJECT;
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ BEGIN( ClassName );
+ }
+<Body>"property"|"event"/{BN}* {
+ if (g_insideTemplate) REJECT;
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ }
+<Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ if (!g_insideTemplate)
+ BEGIN( ClassName );
+ }
+<Body>("package")[ \t\n]+ {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ BEGIN( PackageName );
+ }
+<ClassVar>\n {
+ if (!g_insideObjC) REJECT;
+ codifyLines(yytext);
+ BEGIN(Body);
+ }
+<Body,ClassVar,Bases>"-"|"+" {
+ if (!g_insideObjC || g_insideBody)
+ {
+ g_code->codify(yytext);
+ }
+ else // Start of Objective-C method
+ {
+ //printf("Method!\n");
+ g_code->codify(yytext);
+ BEGIN(ObjCMethod);
+ }
+ }
+<ObjCMethod>":" {
+ g_code->codify(yytext);
+ BEGIN(ObjCParams);
+ }
+<ObjCParams>"(" {
+ g_code->codify(yytext);
+ BEGIN(ObjCParamType);
+ }
+<ObjCParams,ObjCMethod>";"|"{" {
+ g_code->codify(yytext);
+ if (*yytext=='{')
+ {
+ g_curlyCount++;
+ if (g_searchingForBody)
+ {
+ g_searchingForBody=FALSE;
+ g_insideBody=TRUE;
+ }
+ if (g_insideBody) g_bodyCurlyCount++;
+ if (!g_curClassName.isEmpty()) // valid class name
+ {
+ pushScope(g_curClassName);
+ DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
+ g_scopeStack.push(SCOPEBLOCK);
+ }
+ }
+ g_type.resize(0);
+ g_name.resize(0);
+ BEGIN(Body);
+ }
+<ObjCParams>{ID}{B}*":" {
+ g_code->codify(yytext);
+ }
+<ObjCParamType>{TYPEKW} {
+ startFontClass("keywordtype");
+ g_code->codify(yytext);
+ endFontClass();
+ g_parmType=yytext;
+ }
+<ObjCParamType>{ID} {
+ generateClassOrGlobalLink(*g_code,yytext);
+ g_parmType=yytext;
+ }
+<ObjCParamType>")" {
+ g_code->codify(yytext);
+ BEGIN(ObjCParams);
+ }
+<ObjCParams>{ID} {
+ g_code->linkableSymbol(g_yyLineNr,yytext,0,
+ g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
+ g_code->codify(yytext);
+ g_parmName=yytext;
+ g_theVarContext.addVariable(g_parmType,g_parmName);
+ g_parmType.resize(0);g_parmName.resize(0);
+ }
+<ObjCMethod,ObjCParams,ObjCParamType>{ID} {
+ generateClassOrGlobalLink(*g_code,yytext);
+ }
+<ObjCMethod,ObjCParams,ObjCParamType>. {
+ g_code->codify(yytext);
+ }
+<ObjCMethod,ObjCParams,ObjCParamType>\n {
+ codifyLines(yytext);
+ }
+<ReadInclude>[^\n\"\>]+/(">"|"\"") {
+ //FileInfo *f;
+ bool ambig;
+ bool found=FALSE;
+ //QCString absPath = yytext;
+ //if (g_sourceFileDef && QDir::isRelativePath(absPath))
+ //{
+ // absPath = QDir::cleanDirPath(g_sourceFileDef->getPath()+"/"+absPath);
+ //}
+
+ FileDef *fd=findFileDef(Doxygen::inputNameDict,yytext,ambig);
+ //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd);
+ if (fd && fd->isLinkable())
+ {
+ if (ambig) // multiple input files match the name
+ {
+ //printf("===== yes %s is ambiguous\n",yytext);
+ QCString name = convertToQCString(QDir::cleanDirPath(yytext));
+ if (!name.isEmpty() && g_sourceFileDef)
+ {
+ FileName *fn = Doxygen::inputNameDict->find(name);
+ if (fn)
+ {
+ FileNameIterator fni(*fn);
+ // for each include name
+ for (fni.toFirst();!found && (fd=fni.current());++fni)
+ {
+ // see if this source file actually includes the file
+ found = g_sourceFileDef->isIncluded(fd->absFilePath());
+ //printf(" include file %s found=%d\n",fd->absFilePath().data(),found);
+ }
+ }
+ }
+ }
+ else // not ambiguous
+ {
+ found = TRUE;
+ }
+ }
+ //printf(" include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found);
+ if (found)
+ {
+ g_code->writeCodeLink(fd->getReference(),fd->getOutputFileBase(),0,yytext,fd->briefDescriptionAsTooltip());
+ }
+ else
+ {
+ g_code->codify(yytext);
+ }
+ char c=yyinput();
+ QCString text;
+ text+=c;
+ g_code->codify(text);
+ endFontClass();
+ BEGIN( Body );
+ }
+<Body,Bases>^[ \t]*"#" {
+ startFontClass("preprocessor");
+ g_lastSkipCppContext = YY_START;
+ g_code->codify(yytext);
+ BEGIN( SkipCPP ) ;
+ }
+<SkipCPP>. {
+ g_code->codify(yytext);
+ }
+<SkipCPP>[^\n\/\\]+ {
+ g_code->codify(yytext);
+ }
+<SkipCPP>\\[\r]?\n {
+ codifyLines(yytext);
+ }
+<SkipCPP>"//" {
+ g_code->codify(yytext);
+ }
+<Body,FuncCall>"{" {
+ g_theVarContext.pushScope();
+
+ DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
+ g_scopeStack.push(INNERBLOCK);
+
+ if (g_searchingForBody)
+ {
+ g_searchingForBody=FALSE;
+ g_insideBody=TRUE;
+ }
+ g_code->codify(yytext);
+ g_curlyCount++;
+ if (g_insideBody)
+ {
+ g_bodyCurlyCount++;
+ }
+ g_type.resize(0);
+ g_name.resize(0);
+ BEGIN( Body );
+ }
+<Body,MemberCall,MemberCall2>"}" {
+ g_theVarContext.popScope();
+ g_type.resize(0);
+ g_name.resize(0);
+
+ int *scope = g_scopeStack.pop();
+ DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
+ if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
+ {
+ popScope();
+ }
+
+ g_code->codify(yytext);
+
+ //fprintf(stderr,"g_bodyCurlyCount=%d\n",g_bodyCurlyCount);
+ if (--g_bodyCurlyCount<=0)
+ {
+ g_insideBody=FALSE;
+ g_currentMemberDef=0;
+ if (g_currentDefinition)
+ g_currentDefinition=g_currentDefinition->getOuterScope();
+ }
+ BEGIN(Body);
+ }
+<Body,ClassVar>"@end" {
+ //printf("End of objc scope fd=%s\n",g_sourceFileDef->name().data());
+ if (g_sourceFileDef)
+ {
+ FileDef *fd=g_sourceFileDef;
+ g_insideObjC = fd->name().lower().right(2)==".m" ||
+ fd->name().lower().right(3)==".mm";
+ //printf("insideObjC=%d\n",g_insideObjC);
+ }
+ else
+ {
+ g_insideObjC = FALSE;
+ }
+ if (g_insideBody)
+ {
+ g_theVarContext.popScope();
+
+ int *scope = g_scopeStack.pop();
+ DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
+ if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
+ {
+ popScope();
+ }
+ g_insideBody=FALSE;
+ }
+
+ startFontClass("keyword");
+ g_code->codify(yytext);
+ endFontClass();
+
+ g_currentMemberDef=0;
+ if (g_currentDefinition)
+ g_currentDefinition=g_currentDefinition->getOuterScope();
+ BEGIN(Body);
+ }
+<ClassName,ClassVar>";" {
+ g_code->codify(yytext);
+ g_searchingForBody=FALSE;
+ BEGIN( Body );
+ }
+<ClassName,ClassVar>[*&^%]+ {
+ g_type=g_curClassName.copy();
+ g_name.resize(0);
+ g_code->codify(yytext);
+ BEGIN( Body ); // variable of type struct *
+ }
+<ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")" {
+ startFontClass("keyword");
+ g_code->codify(yytext);
+ endFontClass();
+ }
+<ClassName>{ID}("::"{ID})* {
+ g_curClassName=yytext;
+ addType();
+ generateClassOrGlobalLink(*g_code,yytext);
+ BEGIN( ClassVar );
+ }
+<ClassName>{ID}("\\"{ID})* { // PHP namespace
+ g_curClassName=substitute(yytext,"\\","::");
+ g_scopeStack.push(CLASSBLOCK);
+ pushScope(g_curClassName);
+ addType();
+ generateClassOrGlobalLink(*g_code,yytext);
+ BEGIN( ClassVar );
+ }
+<ClassName>{ID}{B}*"("{ID}")" { // Obj-C category
+ g_curClassName=removeRedundantWhiteSpace(yytext);
+ g_scopeStack.push(CLASSBLOCK);
+ pushScope(g_curClassName);
+ addType();
+ generateClassOrGlobalLink(*g_code,yytext);
+ BEGIN( ClassVar );
+ }
+<PackageName>{ID}("."{ID})* {
+ g_curClassName=substitute(yytext,".","::");
+ //printf("found package: %s\n",g_curClassName.data());
+ addType();
+ codifyLines(yytext);
+ }
+<ClassVar>"=" {
+ unput(*yytext);
+ BEGIN( Body );
+ }
+<ClassVar>("extends"|"implements") { // Java
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ g_curClassBases.clear();
+ BEGIN( Bases );
+ }
+<ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") {
+ //fprintf(stderr,"***** C++/CLI modifier %s on g_curClassName=%s\n",yytext,g_curClassName.data());
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ BEGIN( CppCliTypeModifierFollowup );
+ }
+<ClassVar>{ID} {
+ g_type = g_curClassName.copy();
+ g_name = yytext;
+ if (g_insideBody)
+ {
+ g_theVarContext.addVariable(g_type,g_name);
+ }
+ generateClassOrGlobalLink(*g_code,yytext);
+ }
+<ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* {
+ codifyLines(yytext);
+ g_curClassBases.clear();
+ BEGIN( Bases );
+ }
+<PackageName>[ \t]*";" |
+<Bases>^{B}*/"@"{ID} | // Objective-C interface
+<Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* {
+ g_theVarContext.pushScope();
+ g_code->codify(yytext);
+ g_curlyCount++;
+ if (YY_START==ClassVar && g_curClassName.isEmpty())
+ {
+ g_curClassName = g_name.copy();
+ }
+ if (g_searchingForBody)
+ {
+ g_searchingForBody=FALSE;
+ g_insideBody=TRUE;
+ }
+ if (g_insideBody) g_bodyCurlyCount++;
+ if (!g_curClassName.isEmpty()) // valid class name
+ {
+ DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
+ g_scopeStack.push(CLASSBLOCK);
+ pushScope(g_curClassName);
+ //fprintf(stderr,"***** g_curClassName=%s\n",g_curClassName.data());
+ if (getResolvedClass(g_currentDefinition,g_sourceFileDef,g_curClassName)==0)
+ {
+ //fprintf(stderr,"Adding new class %s\n",g_curClassName.data());
+ ClassDef *ncd=new ClassDef("<code>",1,
+ g_curClassName,ClassDef::Class,0,0,FALSE);
+ g_codeClassSDict->append(g_curClassName,ncd);
+ // insert base classes.
+ char *s=g_curClassBases.first();
+ while (s)
+ {
+ ClassDef *bcd;
+ bcd=g_codeClassSDict->find(s);
+ if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s);
+ if (bcd && bcd!=ncd)
+ {
+ ncd->insertBaseClass(bcd,s,Public,Normal);
+ }
+ s=g_curClassBases.next();
+ }
+ }
+ //printf("g_codeClassList.count()=%d\n",g_codeClassList.count());
+ }
+ else // not a class name -> assume inner block
+ {
+ DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
+ g_scopeStack.push(INNERBLOCK);
+ }
+ g_curClassName.resize(0);
+ g_curClassBases.clear();
+ BEGIN( Body );
+ }
+<Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" {
+ startFontClass("keyword");
+ g_code->codify(yytext);
+ endFontClass();
+ }
+<Bases>{SEP}?({ID}{SEP})*{ID} {
+ //fprintf(stderr,"%s:addBase(%s)\n",g_curClassName.data(),yytext);
+ g_curClassBases.inSort(yytext);
+ generateClassOrGlobalLink(*g_code,yytext);
+ }
+<Bases>"<" {
+ g_code->codify(yytext);
+ if (!g_insideObjC)
+ {
+ g_sharpCount=1;
+ BEGIN ( SkipSharp );
+ }
+ else
+ {
+ g_insideProtocolList=TRUE;
+ }
+ }
+<Bases>">" {
+ g_code->codify(yytext);
+ g_insideProtocolList=FALSE;
+ }
+<SkipSharp>"<" {
+ g_code->codify(yytext);
+ ++g_sharpCount;
+ }
+<SkipSharp>">" {
+ g_code->codify(yytext);
+ if (--g_sharpCount<=0)
+ BEGIN ( Bases );
+ }
+<Bases>"(" {
+ g_code->codify(yytext);
+ g_sharpCount=1;
+ BEGIN ( SkipSharp );
+ }
+<SkipSharp>"(" {
+ g_code->codify(yytext);
+ ++g_sharpCount;
+ }
+<SkipSharp>")" {
+ g_code->codify(yytext);
+ if (--g_sharpCount<=0)
+ BEGIN ( Bases );
+ }
+
+
+<Bases>"," {
+ g_code->codify(yytext);
+ }
+
+
+<Body>{SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" {
+ addType();
+ generateFunctionLink(*g_code,yytext);
+ g_bracketCount=0;
+ g_args.resize(0);
+ g_name+=yytext;
+ BEGIN( FuncCall );
+ }
+<Body>{SCOPEPREFIX}?"operator"/"(" {
+ addType();
+ generateFunctionLink(*g_code,yytext);
+ g_bracketCount=0;
+ g_args.resize(0);
+ g_name+=yytext;
+ BEGIN( FuncCall );
+ }
+<Body>{SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\(\n]+/"(" {
+ addType();
+ generateFunctionLink(*g_code,yytext);
+ g_bracketCount=0;
+ g_args.resize(0);
+ g_name+=yytext;
+ BEGIN( FuncCall );
+ }
+<Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9]) {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ g_insideTemplate=TRUE;
+ g_sharpCount=0;
+ }
+<Body>"using"{BN}+"namespace"{BN}+ {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ BEGIN(UsingName);
+ }
+<UsingName>{ID}("::"{ID})* { addUsingDirective(yytext);
+ generateClassOrGlobalLink(*g_code,yytext);
+ DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
+ g_scopeStack.push(CLASSBLOCK);
+ pushScope(yytext);
+ BEGIN(Body);
+ }
+<UsingName>\n { codifyLines(yytext); BEGIN(Body); }
+<UsingName>. { codifyLines(yytext); BEGIN(Body); }
+<Body,FuncCall>"$"?"this"("->"|".") { g_code->codify(yytext); // this-> for C++, this. for C#
+ }
+<Body>{KEYWORD}/([^a-z_A-Z0-9]) {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ if (QCString(yytext)=="typedef")
+ {
+ addType();
+ g_name+=yytext;
+ }
+ endFontClass();
+ }
+<Body>{KEYWORD}/{B}* {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ }
+<Body>{KEYWORD}/{BN}*"(" {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ g_name.resize(0);g_type.resize(0);
+ }
+<FuncCall>"in"/{BN}* {
+ if (!g_inForEachExpression) REJECT;
+ startFontClass("keywordflow");
+ codifyLines(yytext);
+ endFontClass();
+ // insert the variable in the parent scope, see bug 546158
+ g_theVarContext.popScope();
+ g_theVarContext.addVariable(g_parmType,g_parmName);
+ g_theVarContext.pushScope();
+ g_name.resize(0);g_type.resize(0);
+ }
+<Body>{FLOWKW}/{BN}*"(" {
+ startFontClass("keywordflow");
+ codifyLines(yytext);
+ endFontClass();
+ g_name.resize(0);g_type.resize(0);
+ g_inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0);
+ BEGIN(FuncCall);
+ }
+<Body>{FLOWKW}/([^a-z_A-Z0-9]) {
+ startFontClass("keywordflow");
+ codifyLines(yytext);
+ endFontClass();
+ if (g_inFunctionTryBlock && (strcmp(yytext,"catch")==0 || strcmp(yytext,"finally")==0))
+ {
+ g_inFunctionTryBlock=FALSE;
+ }
+ }
+<Body>{FLOWKW}/{B}* {
+ startFontClass("keywordflow");
+ codifyLines(yytext);
+ endFontClass();
+ }
+<Body>"*"{B}*")" { // end of cast?
+ g_code->codify(yytext);
+ g_theCallContext.popScope();
+ g_bracketCount--;
+ g_parmType = g_name;
+ BEGIN(FuncCall);
+ }
+<Body>[\\|\)\+\-\/\%\~\!] {
+ g_code->codify(yytext);
+ g_name.resize(0);g_type.resize(0);
+ if (*yytext==')')
+ {
+ g_theCallContext.popScope();
+ g_bracketCount--;
+ BEGIN(FuncCall);
+ }
+ }
+<Body,TemplDecl,ObjCMethod>{TYPEKW}/{B}* {
+ startFontClass("keywordtype");
+ g_code->codify(yytext);
+ endFontClass();
+ addType();
+ g_name+=yytext;
+ }
+<Body>"generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* {
+ startFontClass("keyword");
+ g_code->codify(yytext);
+ endFontClass();
+ g_sharpCount=0;
+ BEGIN(TemplDecl);
+ }
+<Body>"template"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { // template<...>
+ startFontClass("keyword");
+ g_code->codify(yytext);
+ endFontClass();
+ g_sharpCount=0;
+ BEGIN(TemplDecl);
+ }
+<TemplDecl>"class"|"typename" {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ }
+<TemplDecl>"<" {
+ g_code->codify(yytext);
+ g_sharpCount++;
+ }
+<TemplDecl>">" {
+ g_code->codify(yytext);
+ g_sharpCount--;
+ if (g_sharpCount<=0)
+ {
+ BEGIN(Body);
+ }
+ }
+<TemplCast>">" {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ BEGIN( g_lastTemplCastContext );
+ }
+<TemplCast>{ID}("::"{ID})* {
+ generateClassOrGlobalLink(*g_code,yytext);
+ }
+<TemplCast>("const"|"volatile"){B}* {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ }
+<TemplCast>[*^]* {
+ codifyLines(yytext);
+ }
+<Body,FuncCall>{CASTKW}"<" { // static_cast<T>(
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ g_lastTemplCastContext = YY_START;
+ BEGIN(TemplCast);
+ }
+<Body>"$this->"{SCOPENAME}/{BN}*[;,)\]] { // PHP member variable
+ addType();
+ generatePHPVariableLink(*g_code,yytext);
+ g_name+=yytext+7;
+ }
+<Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"("::"{ID})*/{B}* { // A<T> *pt;
+ int i=QCString(yytext).find('<');
+ QCString kw = QCString(yytext).left(i).stripWhiteSpace();
+ if (kw.right(5)=="_cast" && YY_START==Body)
+ {
+ REJECT;
+ }
+ addType();
+ generateClassOrGlobalLink(*g_code,yytext);
+ g_name+=yytext;
+ }
+<Body>{SCOPENAME}/{BN}*[;,)\]] { // "int var;" or "var, var2" or "debug(f) macro"
+ addType();
+ // changed this to generateFunctionLink, see bug 624514
+ //generateClassOrGlobalLink(*g_code,yytext,FALSE,TRUE);
+ generateFunctionLink(*g_code,yytext);
+ g_name+=yytext;
+ }
+<Body>{SCOPENAME}/{B}* { // p->func()
+ addType();
+ generateClassOrGlobalLink(*g_code,yytext);
+ g_name+=yytext;
+ }
+<Body>"("{B}*("*"{B}*)+{SCOPENAME}*{B}*")"/{B}* { // (*p)->func() but not "if (p) ..."
+ g_code->codify(yytext);
+ int s=0;while (s<(int)yyleng && !isId(yytext[s])) s++;
+ int e=(int)yyleng-1;while (e>=0 && !isId(yytext[e])) e--;
+ QCString varname = ((QCString)yytext).mid(s,e-s+1);
+ addType();
+ g_name=varname;
+ }
+<Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo()
+ addType();
+ generateFunctionLink(*g_code,yytext);
+ g_bracketCount=0;
+ g_args.resize(0);
+ g_name+=yytext;
+ BEGIN( FuncCall );
+ }
+<FuncCall,Body,MemberCall,MemberCall2,SkipInits>{RAWBEGIN} {
+ QCString text=yytext;
+ int i=text.find('R');
+ g_code->codify(text.left(i+1));
+ startFontClass("stringliteral");
+ g_code->codify(yytext+i+1);
+ g_lastStringContext=YY_START;
+ g_inForEachExpression = FALSE;
+ g_delimiter = yytext+i+2;
+ g_delimiter=g_delimiter.left(g_delimiter.length()-1);
+ BEGIN( RawString );
+ }
+<FuncCall,Body,MemberCall,MemberCall2,SkipInits>\" {
+ startFontClass("stringliteral");
+ g_code->codify(yytext);
+ g_lastStringContext=YY_START;
+ g_inForEachExpression = FALSE;
+ BEGIN( SkipString );
+ }
+<FuncCall,Body,MemberCall,MemberCall2,SkipInits>\' {
+ startFontClass("stringliteral");
+ g_code->codify(yytext);
+ g_lastStringContext=YY_START;
+ g_inForEachExpression = FALSE;
+ BEGIN( SkipStringS );
+ }
+<SkipString>[^\"\\\r\n]* {
+ g_code->codify(yytext);
+ }
+<SkipStringS>[^\'\\\r\n]* {
+ g_code->codify(yytext);
+ }
+<SkipString,SkipStringS>"//"|"/*" {
+ g_code->codify(yytext);
+ }
+<SkipString>@?\" {
+ g_code->codify(yytext);
+ endFontClass();
+ BEGIN( g_lastStringContext );
+ }
+<SkipStringS>\' {
+ g_code->codify(yytext);
+ endFontClass();
+ BEGIN( g_lastStringContext );
+ }
+<SkipString,SkipStringS>\\. {
+ g_code->codify(yytext);
+ }
+<RawString>{RAWEND} {
+ g_code->codify(yytext);
+ QCString delimiter = yytext+1;
+ delimiter=delimiter.left(delimiter.length()-1);
+ if (delimiter==g_delimiter)
+ {
+ BEGIN( g_lastStringContext );
+ }
+ }
+<RawString>[^)]+ { g_code->codify(yytext); }
+<RawString>. { g_code->codify(yytext); }
+<RawString>\n { codifyLines(yytext); }
+<SkipVerbString>[^"\n]+ {
+ g_code->codify(yytext);
+ }
+<SkipVerbString>\"\" { // escaped quote
+ g_code->codify(yytext);
+ }
+<SkipVerbString>\" { // end of string
+ g_code->codify(yytext);
+ endFontClass();
+ BEGIN( g_lastVerbStringContext );
+ }
+<SkipVerbString>. {
+ g_code->codify(yytext);
+ }
+<SkipVerbString>\n {
+ codifyLines(yytext);
+ }
+<Body>":" {
+ g_code->codify(yytext);
+ g_name.resize(0);g_type.resize(0);
+ }
+<Body>"<" {
+ if (g_insideTemplate)
+ {
+ g_sharpCount++;
+ }
+ g_code->codify(yytext);
+ }
+<Body>">" {
+ if (g_insideTemplate)
+ {
+ if (--g_sharpCount<=0)
+ {
+ g_insideTemplate=FALSE;
+ }
+ }
+ g_code->codify(yytext);
+ }
+<Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'" {
+ startFontClass("charliteral");
+ g_code->codify(yytext);
+ endFontClass();
+ }
+<Body>"."|"->" {
+ if (yytext[0]=='-') // -> could be overloaded
+ {
+ updateCallContextForSmartPointer();
+ }
+ g_code->codify(yytext);
+ g_memCallContext = YY_START;
+ BEGIN( MemberCall );
+ }
+<MemberCall>{SCOPETNAME}/{BN}*"(" {
+ if (g_theCallContext.getClass())
+ {
+ if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),yytext))
+ {
+ g_code->linkableSymbol(g_yyLineNr,yytext,0,
+ g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
+ g_code->codify(yytext);
+ addToSearchIndex(yytext);
+ }
+ g_name.resize(0);
+ }
+ else
+ {
+ g_code->linkableSymbol(g_yyLineNr,yytext,0,
+ g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
+ g_code->codify(yytext);
+ addToSearchIndex(yytext);
+ g_name.resize(0);
+ }
+ g_type.resize(0);
+ g_bracketCount=0;
+ if (g_memCallContext==Body)
+ {
+ BEGIN(FuncCall);
+ }
+ else
+ {
+ BEGIN(g_memCallContext);
+ }
+ }
+<MemberCall>{SCOPENAME}/{B}* {
+ if (g_theCallContext.getClass())
+ {
+ //fprintf(stderr,"g_theCallContext.getClass()=%p\n",g_theCallContext.getClass());
+ if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),yytext))
+ {
+ g_code->linkableSymbol(g_yyLineNr,yytext,0,
+ g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
+ g_code->codify(yytext);
+ addToSearchIndex(yytext);
+ }
+ g_name.resize(0);
+ }
+ else
+ {
+ //fprintf(stderr,"no class context!\n");
+ g_code->codify(yytext);
+ addToSearchIndex(yytext);
+ g_name.resize(0);
+ }
+ g_type.resize(0);
+ BEGIN(g_memCallContext);
+ }
+<Body>[,=;\[] {
+ if (g_insideObjC && *yytext=='[')
+ {
+ //printf("Found start of ObjC call!\n");
+ // start of a method call
+ g_contextDict.setAutoDelete(TRUE);
+ g_nameDict.setAutoDelete(TRUE);
+ g_objectDict.setAutoDelete(TRUE);
+ g_wordDict.setAutoDelete(TRUE);
+ g_contextDict.clear();
+ g_nameDict.clear();
+ g_objectDict.clear();
+ g_wordDict.clear();
+ g_currentCtxId = 0;
+ g_currentNameId = 0;
+ g_currentObjId = 0;
+ g_currentCtx = 0;
+ g_braceCount = 0;
+ unput('[');
+ BEGIN(ObjCCall);
+ }
+ else
+ {
+ g_code->codify(yytext);
+ g_saveName = g_name.copy();
+ g_saveType = g_type.copy();
+ if (*yytext!='[' && !g_type.isEmpty())
+ {
+ //printf("g_scopeStack.bottom()=%p\n",g_scopeStack.bottom());
+ if (g_scopeStack.top()!=CLASSBLOCK)
+ {
+ //printf("AddVariable: '%s' '%s' context=%d\n",
+ // g_type.data(),g_name.data(),g_theVarContext.count());
+ g_theVarContext.addVariable(g_type,g_name);
+ }
+ g_name.resize(0);
+ }
+ if (*yytext==';' || *yytext=='=')
+ {
+ g_type.resize(0);
+ g_name.resize(0);
+ }
+ else if (*yytext=='[')
+ {
+ g_theCallContext.pushScope();
+ }
+ g_args.resize(0);
+ g_parmType.resize(0);
+ g_parmName.resize(0);
+ }
+ }
+ /*
+<ObjCMemberCall>{ID} {
+ if (strcmp(yytext,"self")==0 || strcmp(yytext,"super")==0)
+ {
+ // TODO: get proper base class for "super"
+ g_theCallContext.setClass(getClass(g_curClassName));
+ startFontClass("keyword");
+ g_code->codify(yytext);
+ endFontClass();
+ }
+ else
+ {
+ generateClassOrGlobalLink(*g_code,yytext);
+ }
+ g_name.resize(0);
+ BEGIN(ObjCMemberCall2);
+ }
+<ObjCMemberCall>"[" {
+ g_code->codify(yytext);
+ g_theCallContext.pushScope();
+ }
+<ObjCMemberCall2>{ID}":"? {
+ g_name+=yytext;
+ if (g_theCallContext.getClass())
+ {
+ //printf("Calling method %s\n",g_name.data());
+ if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),g_name))
+ {
+ g_code->codify(yytext);
+ addToSearchIndex(g_name);
+ }
+ }
+ else
+ {
+ g_code->codify(yytext);
+ addToSearchIndex(g_name);
+ }
+ g_name.resize(0);
+ BEGIN(ObjCMemberCall3);
+ }
+<ObjCMemberCall2,ObjCMemberCall3>"]" {
+ g_theCallContext.popScope();
+ g_code->codify(yytext);
+ BEGIN(Body);
+ }
+ */
+<ObjCCall,ObjCMName>"[" {
+ saveObjCContext();
+ g_currentCtx->format+=*yytext;
+ BEGIN(ObjCCall);
+ //printf("open\n");
+ }
+<ObjCCall,ObjCMName>"]" {
+ g_currentCtx->format+=*yytext;
+ restoreObjCContext();
+ BEGIN(ObjCMName);
+ if (g_currentCtx==0)
+ {
+ // end of call
+ writeObjCMethodCall(g_contextDict.find(0));
+ BEGIN(Body);
+ }
+ //printf("close\n");
+ }
+<ObjCCall>{ID} {
+ g_currentCtx->format+=escapeObject(yytext);
+ if (g_braceCount==0)
+ {
+ g_currentCtx->objectTypeOrName=yytext;
+ //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
+ BEGIN(ObjCMName);
+ }
+ }
+<ObjCMName>{ID}/{BN}*"]" {
+ if (g_braceCount==0 &&
+ g_currentCtx->methodName.isEmpty())
+ {
+ g_currentCtx->methodName=yytext;
+ g_currentCtx->format+=escapeName(yytext);
+ }
+ else
+ {
+ g_currentCtx->format+=escapeWord(yytext);
+ }
+ }
+<ObjCMName>{ID}/{BN}*":" {
+ if (g_braceCount==0)
+ {
+ g_currentCtx->methodName+=yytext;
+ g_currentCtx->methodName+=":";
+ }
+ g_currentCtx->format+=escapeName(yytext);
+ }
+<ObjCSkipStr>[^\n\"$\\]* { g_currentCtx->format+=yytext; }
+<ObjCSkipStr>\\. { g_currentCtx->format+=yytext; }
+<ObjCSkipStr>"\"" { g_currentCtx->format+=yytext;
+ BEGIN(g_lastStringContext);
+ }
+<ObjCCall,ObjCMName>{CHARLIT} { g_currentCtx->format+=yytext; }
+<ObjCCall,ObjCMName>"@"?"\"" { g_currentCtx->format+=yytext;
+ g_lastStringContext=YY_START;
+ BEGIN(ObjCSkipStr);
+ }
+<ObjCCall,ObjCMName,ObjCSkipStr>"$" { g_currentCtx->format+="$$"; }
+<ObjCCall,ObjCMName>"(" { g_currentCtx->format+=*yytext; g_braceCount++; }
+<ObjCCall,ObjCMName>")" { g_currentCtx->format+=*yytext; g_braceCount--; }
+<ObjCSkipStr>"@"/"\"" { // needed to prevent matching the global rule (for C#)
+ g_currentCtx->format+=yytext;
+ }
+<ObjCCall,ObjCMName,ObjCSkipStr>{ID} { g_currentCtx->format+=escapeWord(yytext); }
+<ObjCCall,ObjCMName,ObjCSkipStr>. { g_currentCtx->format+=*yytext; }
+<ObjCCall,ObjCMName,ObjCSkipStr>\n { g_currentCtx->format+=*yytext; }
+
+<Body>"]" {
+ g_theCallContext.popScope();
+ g_code->codify(yytext);
+ // TODO: nested arrays like: a[b[0]->func()]->func()
+ g_name = g_saveName.copy();
+ g_type = g_saveType.copy();
+ }
+<Body>[0-9]+ {
+ g_code->codify(yytext);
+ }
+<Body>[0-9]+[xX][0-9A-Fa-f]+ {
+ g_code->codify(yytext);
+ }
+<MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) {
+ //addParmType();
+ //g_parmName=yytext;
+ startFontClass("keyword");
+ g_code->codify(yytext);
+ endFontClass();
+ }
+<MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKW}/([^a-z_A-Z0-9]) {
+ addParmType();
+ g_parmName=yytext;
+ startFontClass("keywordtype");
+ g_code->codify(yytext);
+ endFontClass();
+ }
+<MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) {
+ addParmType();
+ g_parmName=yytext;
+ startFontClass("keywordflow");
+ g_code->codify(yytext);
+ endFontClass();
+ }
+<MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* {
+ addParmType();
+ g_parmName=yytext;
+ generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
+ }
+<FuncCall>";" { // probably a cast, not a function call
+ g_code->codify(yytext);
+ g_inForEachExpression = FALSE;
+ BEGIN( Body );
+ }
+<MemberCall2,FuncCall>, {
+ g_code->codify(yytext);
+ g_theVarContext.addVariable(g_parmType,g_parmName);
+ g_parmType.resize(0);g_parmName.resize(0);
+ }
+<MemberCall2,FuncCall>"(" {
+ g_parmType.resize(0);g_parmName.resize(0);
+ g_code->codify(yytext);
+ g_bracketCount++;
+ g_theCallContext.pushScope();
+ if (YY_START==FuncCall && !g_insideBody)
+ {
+ g_theVarContext.pushScope();
+ }
+ }
+<MemberCall2,FuncCall>{OPERATOR} { // operator
+ if (strcmp(yytext,"*") &&
+ strcmp(yytext,"&") &&
+ strcmp(yytext,"^") &&
+ strcmp(yytext,"%")) // typically a pointer or reference
+ {
+ // not a * or &, or C++/CLI's ^ or %
+ g_parmType.resize(0);g_parmName.resize(0);
+ }
+ g_code->codify(yytext);
+ }
+<MemberCall,MemberCall2,FuncCall>("*"{B}*)?")" {
+ if (yytext[0]==')') // no a pointer cast
+ {
+ //printf("addVariable(%s,%s)\n",g_parmType.data(),g_parmName.data());
+ g_theVarContext.addVariable(g_parmType,g_parmName);
+ }
+ else
+ {
+ g_parmType.resize(0);
+ g_parmName.resize(0);
+ }
+ g_theCallContext.popScope();
+ g_inForEachExpression = FALSE;
+ //g_theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b().
+ g_code->codify(yytext);
+ if (--g_bracketCount<=0)
+ {
+ if (g_name.isEmpty())
+ {
+ BEGIN( Body );
+ }
+ else
+ {
+ BEGIN( CallEnd );
+ }
+ }
+ }
+<CallEnd>[ \t\n]* { codifyLines(yytext); }
+ /*
+<MemberCall2,FuncCall>")"[ \t\n]*[;:] {
+ */
+<CallEnd>[;:] {
+ codifyLines(yytext);
+ g_bracketCount=0;
+ if (*yytext==';') g_searchingForBody=FALSE;
+ if (!g_type.isEmpty())
+ {
+ //fprintf(stderr,"add variable g_type=%s g_name=%s)\n",g_type.data(),g_name.data());
+ g_theVarContext.addVariable(g_type,g_name);
+ }
+ g_parmType.resize(0);g_parmName.resize(0);
+ g_theCallContext.setClass(0);
+ if (*yytext==';' || g_insideBody)
+ {
+ if (!g_insideBody)
+ {
+ g_theVarContext.popScope();
+ }
+ g_name.resize(0);g_type.resize(0);
+ BEGIN( Body );
+ }
+ else
+ {
+ g_bracketCount=0;
+ BEGIN( SkipInits );
+ }
+ }
+<CallEnd>("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ }
+<CallEnd,OldStyleArgs>("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" {
+ if (g_insideBody)
+ {
+ g_theVarContext.pushScope();
+ }
+ g_theVarContext.addVariable(g_parmType,g_parmName);
+ //g_theCallContext.popScope();
+ g_parmType.resize(0);g_parmName.resize(0);
+ int index = g_name.findRev("::");
+ //fprintf(stderr,"g_name=%s\n",g_name.data());
+ if (index!=-1)
+ {
+ QCString scope = g_name.left(index);
+ if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::");
+ ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope);
+ if (cd)
+ {
+ setClassScope(cd->name());
+ g_scopeStack.push(SCOPEBLOCK);
+ DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
+ }
+ else
+ {
+ //setClassScope(g_realScope);
+ g_scopeStack.push(INNERBLOCK);
+ DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
+ }
+ }
+ else
+ {
+ DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
+ g_scopeStack.push(INNERBLOCK);
+ }
+ yytext[yyleng-1]='\0';
+ QCString cv(yytext);
+ if (!cv.stripWhiteSpace().isEmpty())
+ {
+ startFontClass("keyword");
+ codifyLines(yytext);
+ endFontClass();
+ }
+ else // just whitespace
+ {
+ codifyLines(yytext);
+ }
+ g_code->codify("{");
+ if (g_searchingForBody)
+ {
+ g_searchingForBody=FALSE;
+ g_insideBody=TRUE;
+ }
+ if (g_insideBody) g_bodyCurlyCount++;
+ g_curlyCount++;
+ g_type.resize(0); g_name.resize(0);
+ BEGIN( Body );
+ }
+<CallEnd>"try" { // function-try-block
+ startFontClass("keyword");
+ g_code->codify(yytext);
+ endFontClass();
+ g_inFunctionTryBlock=TRUE;
+ }
+<CallEnd>{ID} {
+ if (g_insideBody || !g_parmType.isEmpty())
+ {
+ REJECT;
+ }
+ // could be K&R style definition
+ addParmType();
+ g_parmName=yytext;
+ generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
+ BEGIN(OldStyleArgs);
+ }
+<OldStyleArgs>{ID} {
+ addParmType();
+ g_parmName=yytext;
+ generateClassOrGlobalLink(*g_code,yytext,!g_insideBody);
+ }
+<OldStyleArgs>[,;] {
+ g_code->codify(yytext);
+ g_theVarContext.addVariable(g_parmType,g_parmName);
+ if (*yytext==';') g_parmType.resize(0);
+ g_parmName.resize(0);
+ }
+<CallEnd,OldStyleArgs>"#" {
+ startFontClass("preprocessor");
+ g_lastSkipCppContext = Body;
+ g_code->codify(yytext);
+ BEGIN( SkipCPP );
+ }
+<CallEnd>. {
+ unput(*yytext);
+ if (!g_insideBody)
+ {
+ g_theVarContext.popScope();
+ }
+ g_name.resize(0);g_args.resize(0);
+ g_parmType.resize(0);g_parmName.resize(0);
+ BEGIN( Body );
+ }
+<SkipInits>";" {
+ g_code->codify(yytext);
+ g_type.resize(0); g_name.resize(0);
+ BEGIN( Body );
+ }
+<SkipInits>"{" {
+ g_code->codify(yytext);
+ g_curlyCount++;
+ if (g_searchingForBody)
+ {
+ g_searchingForBody=FALSE;
+ g_insideBody=TRUE;
+ }
+ if (g_insideBody) g_bodyCurlyCount++;
+ if (g_name.find("::")!=-1)
+ {
+ DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
+ g_scopeStack.push(SCOPEBLOCK);
+ setClassScope(g_realScope);
+ }
+ else
+ {
+ DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
+ g_scopeStack.push(INNERBLOCK);
+ }
+ g_type.resize(0); g_name.resize(0);
+ BEGIN( Body );
+ }
+<SkipInits>{ID} {
+ generateClassOrGlobalLink(*g_code,yytext);
+ }
+<FuncCall>{ID}/"(" {
+ generateFunctionLink(*g_code,yytext);
+ }
+<FuncCall>{ID}/("."|"->") {
+ g_name=yytext;
+ generateClassOrGlobalLink(*g_code,yytext);
+ BEGIN( MemberCall2 );
+ }
+<FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}*{B}*")"{B}*)/("."|"->") {
+ g_code->codify(yytext);
+ int s=0;while (!isId(yytext[s])) s++;
+ int e=(int)yyleng-1;while (!isId(yytext[e])) e--;
+ g_name=((QCString)yytext).mid(s,e-s+1);
+ BEGIN( MemberCall2 );
+ }
+<MemberCall2>{ID}/([ \t\n]*"(") {
+ if (!g_args.isEmpty())
+ generateMemberLink(*g_code,g_args,yytext);
+ else
+ generateClassOrGlobalLink(*g_code,yytext);
+ g_args.resize(0);
+ BEGIN( FuncCall );
+ }
+<MemberCall2>{ID}/([ \t\n]*("."|"->")) {
+ //g_code->codify(yytext);
+ g_name=yytext;
+ generateClassOrGlobalLink(*g_code,yytext);
+ BEGIN( MemberCall2 );
+ }
+<MemberCall2>"->"|"." {
+ if (yytext[0]=='-') // -> could be overloaded
+ {
+ updateCallContextForSmartPointer();
+ }
+ g_code->codify(yytext);
+ g_memCallContext = YY_START;
+ BEGIN( MemberCall );
+ }
+<SkipComment>"/*"("!"?)"*/" {
+ g_code->codify(yytext);
+ endFontClass();
+ BEGIN( g_lastCContext ) ;
+ }
+<SkipComment>"//"|"/*" {
+ g_code->codify(yytext);
+ }
+<SkipComment>[^*/\n]+ {
+ g_code->codify(yytext);
+ }
+<SkipComment>[ \t]*"*/" {
+ g_code->codify(yytext);
+ endFontClass();
+ if (g_lastCContext==SkipCPP)
+ {
+ startFontClass("preprocessor");
+ }
+ BEGIN( g_lastCContext ) ;
+ }
+<SkipCxxComment>[^\r\n]*"\\"[\r]?\n { // line continuation
+ codifyLines(yytext);
+ }
+<SkipCxxComment>[^\r\n]+ {
+ g_code->codify(yytext);
+ }
+<SkipCxxComment>\r
+<SkipCxxComment>\n {
+ unput('\n');
+ endFontClass();
+ BEGIN( g_lastCContext ) ;
+ }
+<SkipCxxComment>. {
+ g_code->codify(yytext);
+ }
+<RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] {
+ g_yyLineNr+=QCString(yytext).contains('\n');
+ }
+<RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? {
+ g_yyLineNr+=QCString(yytext).contains('\n');
+ nextCodeLine();
+ if (g_lastSpecialCContext==SkipCxxComment)
+ { // force end of C++ comment here
+ endFontClass();
+ BEGIN( g_lastCContext ) ;
+ }
+ else
+ {
+ BEGIN(g_lastSpecialCContext);
+ }
+ }
+<RemoveSpecialCComment>"*/" {
+ BEGIN(g_lastSpecialCContext);
+ }
+<RemoveSpecialCComment>[^*\n]+
+<RemoveSpecialCComment>"//"|"/*"
+<RemoveSpecialCComment>\n { g_yyLineNr++; }
+<RemoveSpecialCComment>.
+<MemberCall>[^a-z_A-Z0-9(\n] {
+ g_code->codify(yytext);
+ g_type.resize(0);
+ g_name.resize(0);
+ BEGIN(g_memCallContext);
+ }
+<*>\n({B}*"//"[!/][^\n]*\n)+ { // remove special one-line comment
+ if (YY_START==SkipCPP) REJECT;
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ g_yyLineNr+=((QCString)yytext).contains('\n');
+ nextCodeLine();
+ }
+ else
+ {
+ startFontClass("comment");
+ codifyLines(yytext);
+ endFontClass();
+ }
+ if (YY_START==SkipCxxComment)
+ {
+ endFontClass();
+ BEGIN( g_lastCContext ) ;
+ }
+ }
+<SkipCPP>\n/.*\n {
+ codifyLines(yytext);
+ endFontClass();
+ BEGIN( g_lastSkipCppContext ) ;
+ }
+<*>\n{B}*"//@"[{}].*\n { // remove one-line group marker
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ g_yyLineNr+=2;
+ nextCodeLine();
+ }
+ else
+ {
+ startFontClass("comment");
+ codifyLines(yytext);
+ endFontClass();
+ }
+ if (YY_START==SkipCxxComment)
+ {
+ endFontClass();
+ BEGIN( g_lastCContext ) ;
+ }
+ }
+<*>\n{B}*"/*@"[{}] { // remove one-line group marker
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ g_lastSpecialCContext = YY_START;
+ g_yyLineNr++;
+ BEGIN(RemoveSpecialCComment);
+ }
+ else
+ {
+ // check is to prevent getting stuck in skipping C++ comments
+ if (YY_START != SkipCxxComment)
+ {
+ g_lastCContext = YY_START ;
+ }
+ startFontClass("comment");
+ codifyLines(yytext);
+ BEGIN(SkipComment);
+ }
+ }
+<*>^{B}*"//@"[{}].*\n { // remove one-line group marker
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ g_yyLineNr++;
+ nextCodeLine();
+ }
+ else
+ {
+ startFontClass("comment");
+ codifyLines(yytext);
+ endFontClass();
+ }
+ }
+<*>^{B}*"/*@"[{}] { // remove multi-line group marker
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ g_lastSpecialCContext = YY_START;
+ BEGIN(RemoveSpecialCComment);
+ }
+ else
+ {
+ // check is to prevent getting stuck in skipping C++ comments
+ if (YY_START != SkipCxxComment)
+ {
+ g_lastCContext = YY_START ;
+ }
+ startFontClass("comment");
+ g_code->codify(yytext);
+ BEGIN(SkipComment);
+ }
+ }
+<*>^{B}*"//"[!/][^\n]*\n { // remove special one-line comment
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ g_yyLineNr++;
+ nextCodeLine();
+ }
+ else
+ {
+ startFontClass("comment");
+ codifyLines(yytext);
+ endFontClass();
+ }
+ }
+<*>"//"[!/][^\n]*\n { // strip special one-line comment
+ if (YY_START==SkipComment || YY_START==SkipString) REJECT;
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ char c[2]; c[0]='\n'; c[1]=0;
+ codifyLines(c);
+ }
+ else
+ {
+ startFontClass("comment");
+ codifyLines(yytext);
+ endFontClass();
+ }
+ }
+<*>"/*[tag:"[^\]\n]*"]*/"{B}* { // special pattern /*[tag:filename]*/ to force linking to a tag file
+ g_forceTagReference=yytext;
+ int s=g_forceTagReference.find(':');
+ int e=g_forceTagReference.findRev(']');
+ g_forceTagReference = g_forceTagReference.mid(s+1,e-s-1);
+ }
+<*>\n{B}*"/*"[!*]/[^/*] {
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ g_lastSpecialCContext = YY_START;
+ g_yyLineNr++;
+ BEGIN(RemoveSpecialCComment);
+ }
+ else
+ {
+ // check is to prevent getting stuck in skipping C++ comments
+ if (YY_START != SkipCxxComment)
+ {
+ g_lastCContext = YY_START ;
+ }
+ startFontClass("comment");
+ codifyLines(yytext);
+ BEGIN(SkipComment);
+ }
+ }
+<*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ g_lastSpecialCContext = YY_START;
+ BEGIN(RemoveSpecialCComment);
+ }
+ else
+ {
+ // check is to prevent getting stuck in skipping C++ comments
+ if (YY_START != SkipCxxComment)
+ {
+ g_lastCContext = YY_START ;
+ }
+ startFontClass("comment");
+ g_code->codify(yytext);
+ BEGIN(SkipComment);
+ }
+ }
+<*>"/*"[!*]/[^/*] { // special C comment block half way a line
+ if (YY_START==SkipString) REJECT;
+ if (Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ g_lastSpecialCContext = YY_START;
+ BEGIN(RemoveSpecialCComment);
+ }
+ else
+ {
+ // check is to prevent getting stuck in skipping C++ comments
+ if (YY_START != SkipCxxComment)
+ {
+ g_lastCContext = YY_START ;
+ }
+ startFontClass("comment");
+ g_code->codify(yytext);
+ BEGIN(SkipComment);
+ }
+ }
+<*>"/*"("!"?)"*/" {
+ if (YY_START==SkipString) REJECT;
+ if (!Config_getBool("STRIP_CODE_COMMENTS"))
+ {
+ startFontClass("comment");
+ g_code->codify(yytext);
+ endFontClass();
+ }
+ }
+<*>"/*" {
+ startFontClass("comment");
+ g_code->codify(yytext);
+ // check is to prevent getting stuck in skipping C++ comments
+ if (YY_START != SkipCxxComment)
+ {
+ g_lastCContext = YY_START ;
+ }
+ BEGIN( SkipComment ) ;
+ }
+<*>@\" { // C# verbatim string
+ startFontClass("stringliteral");
+ g_code->codify(yytext);
+ g_lastVerbStringContext=YY_START;
+ BEGIN(SkipVerbString);
+ }
+<*>"//" {
+ startFontClass("comment");
+ g_code->codify(yytext);
+ g_lastCContext = YY_START ;
+ BEGIN( SkipCxxComment ) ;
+ }
+<*>"("|"[" {
+ g_code->codify(yytext);
+ g_theCallContext.pushScope();
+ }
+<*>")"|"]" {
+ g_code->codify(yytext);
+ g_theCallContext.popScope();
+ }
+<*>\n {
+ codifyLines(yytext);
+ }
+<*>. {
+ g_code->codify(yytext);
+ }
+ /*
+<*>([ \t\n]*"\n"){2,} { // combine multiple blank lines
+ //QCString sepLine=yytext;
+ //g_code->codify("\n\n");
+ //g_yyLineNr+=sepLine.contains('\n');
+ //char sepLine[3]="\n\n";
+ codifyLines(yytext);
+ }
+ */
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+static void saveObjCContext()
+{
+ if (g_currentCtx)
+ {
+ g_currentCtx->format+=QCString().sprintf("$c%d",g_currentCtxId);
+ if (g_braceCount==0 && YY_START==ObjCCall)
+ {
+ g_currentCtx->objectTypeOrName=g_currentCtx->format.mid(1);
+ //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data());
+ }
+ g_contextStack.push(g_currentCtx);
+ }
+ else
+ {
+ //printf("Trying to save NULL context!\n");
+ }
+ ObjCCallCtx *newCtx = new ObjCCallCtx;
+ newCtx->id = g_currentCtxId;
+ newCtx->lexState = YY_START;
+ newCtx->braceCount = g_braceCount;
+ newCtx->objectType = 0;
+ newCtx->objectVar = 0;
+ newCtx->method = 0;
+ //printf("save state=%d\n",YY_START);
+ g_contextDict.insert(g_currentCtxId,newCtx);
+ g_currentCtx = newCtx;
+ g_braceCount = 0;
+ g_currentCtxId++;
+}
+
+static void restoreObjCContext()
+{
+ //printf("restore state=%d->%d\n",YY_START,g_currentCtx->lexState);
+ BEGIN(g_currentCtx->lexState);
+ g_braceCount = g_currentCtx->braceCount;
+ if (!g_contextStack.isEmpty())
+ {
+ g_currentCtx = g_contextStack.pop();
+ }
+ else
+ {
+ g_currentCtx = 0;
+ //printf("Trying to pop context while g_contextStack is empty!\n");
+ }
+}
+
+void resetCCodeParserState()
+{
+ //printf("***initParseCodeContext()\n");
+ g_forceTagReference.resize(0);
+ g_theVarContext.clear();
+ g_classScopeLengthStack.setAutoDelete(TRUE);
+ g_classScopeLengthStack.clear();
+ delete g_codeClassSDict;
+ g_codeClassSDict = new ClassSDict(17);
+ g_codeClassSDict->setAutoDelete(TRUE);
+ g_codeClassSDict->clear();
+ g_curClassBases.clear();
+ g_anchorCount = 0;
+}
+
+void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s,
+ bool exBlock, const char *exName,FileDef *fd,
+ int startLine,int endLine,bool inlineFragment,
+ MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx)
+{
+ //printf("***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n",
+ // exBlock,exName,fd,className,searchCtx?searchCtx->name().data():"<none>");
+ if (s.isEmpty()) return;
+ if (g_codeClassSDict==0)
+ {
+ resetCCodeParserState();
+ }
+ g_code = &od;
+ g_inputString = s;
+ g_inputPosition = 0;
+ g_currentFontClass = 0;
+ g_needsTermination = FALSE;
+ g_searchCtx = searchCtx;
+ g_inFunctionTryBlock = FALSE;
+ if (endLine!=-1)
+ g_inputLines = endLine+1;
+ else
+ g_inputLines = countLines();
+
+ if (startLine!=-1)
+ g_yyLineNr = startLine;
+ else
+ g_yyLineNr = 1;
+
+ g_curlyCount = 0;
+ g_bodyCurlyCount = 0;
+ g_bracketCount = 0;
+ g_sharpCount = 0;
+ g_insideTemplate = FALSE;
+ g_theCallContext.clear();
+ g_scopeStack.clear();
+ g_classScope = className;
+ //printf("parseCCode %s\n",className);
+ g_exampleBlock = exBlock;
+ g_exampleName = exName;
+ g_sourceFileDef = fd;
+ g_lineNumbers = fd!=0 && showLineNumbers;
+ bool cleanupSourceDef = FALSE;
+ if (fd==0)
+ {
+ // create a dummy filedef for the example
+ g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
+ cleanupSourceDef = TRUE;
+ }
+ if (g_sourceFileDef)
+ {
+ setCurrentDoc("l00001");
+ g_insideObjC = g_sourceFileDef->name().lower().right(2)==".m" ||
+ g_sourceFileDef->name().lower().right(3)==".mm";
+ }
+ g_currentDefinition = 0;
+ g_currentMemberDef = 0;
+ g_searchingForBody = exBlock;
+ g_insideBody = FALSE;
+ g_bracketCount = 0;
+ if (!g_exampleName.isEmpty())
+ {
+ g_exampleFile = convertNameToFile(g_exampleName+"-example",FALSE,TRUE);
+ //printf("g_exampleFile=%s\n",g_exampleFile.data());
+ }
+ g_includeCodeFragment = inlineFragment;
+ //printf("** exBlock=%d exName=%s include=%d\n",exBlock,exName,inlineFragment);
+ startCodeLine();
+ g_type.resize(0);
+ g_name.resize(0);
+ g_args.resize(0);
+ g_parmName.resize(0);
+ g_parmType.resize(0);
+ if (memberDef) setParameterList(memberDef);
+ codeYYrestart( codeYYin );
+ BEGIN( Body );
+ codeYYlex();
+ g_lexInit=TRUE;
+ if (g_needsTermination)
+ {
+ endFontClass();
+ g_code->endCodeLine();
+ }
+ if (cleanupSourceDef)
+ {
+ // delete the temporary file definition used for this example
+ delete g_sourceFileDef;
+ g_sourceFileDef=0;
+ }
+ return;
+}
+
+void codeFreeScanner()
+{
+#if defined(YY_FLEX_SUBMINOR_VERSION)
+ if (g_lexInit)
+ {
+ codeYYlex_destroy();
+ }
+#endif
+}
+
+
+
+#if !defined(YY_FLEX_SUBMINOR_VERSION)
+extern "C" { // some bogus code to keep the compiler happy
+ void codeYYdummy() { yy_flex_realloc(0,0); }
+}
+#elif YY_FLEX_SUBMINOR_VERSION<33
+#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!"
+#endif
+