From e7d47ec23ba1b109754d6e47b1eb4d341efc3b36 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Thu, 21 Nov 2019 20:55:57 +0100 Subject: Made code.l scanner reentrant --- src/code.h | 14 +- src/code.l | 5860 ++++++++++++++++++++++++++++--------------------------- src/doxygen.cpp | 4 +- src/scanner.l | 7 +- 4 files changed, 3009 insertions(+), 2876 deletions(-) diff --git a/src/code.h b/src/code.h index da6b80e..a86ecc0 100644 --- a/src/code.h +++ b/src/code.h @@ -26,12 +26,20 @@ class MemberDef; class QCString; class Definition; -void parseCCode(CodeOutputInterface &,const char *,const QCString &, +class CodeScanner +{ + public: + CodeScanner(); + virtual ~CodeScanner(); + void parseCCode(CodeOutputInterface &,const char *,const QCString &, SrcLangExt lang, bool isExample, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs); -void resetCCodeParserState(); -void codeFreeScanner(); + void reset(); + private: + struct Private; + Private *p; +}; #endif diff --git a/src/code.l b/src/code.l index 4998421..32a0f7e 100644 --- a/src/code.l +++ b/src/code.l @@ -16,6 +16,8 @@ */ %option never-interactive %option prefix="codeYY" +%option reentrant +%option extra-type="struct codeYY_state *" %{ @@ -28,6 +30,7 @@ #include #include +#include "code.h" #include "entry.h" #include "doxygen.h" #include "message.h" @@ -58,76 +61,6 @@ * 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 int g_yyColNr; //!< current column 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 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_lastObjCCallContext; -static int g_memCallContext; -static int g_lastCContext; -static int g_skipInlineInitContext; - -static SrcLangExt g_lang; -static bool g_insideObjC; -static bool g_insideProtocolList; - -static bool g_lexInit = FALSE; - -static QStack g_classScopeLengthStack; - -static int g_prefixed_with_this_keyword = FALSE; -static const Definition *g_searchCtx; -static bool g_collectXRefs; - // context for an Objective-C method call struct ObjCCallCtx { @@ -143,31 +76,6 @@ struct ObjCCallCtx 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 int g_currentCommentId=0; -static QStack g_contextStack; -static QIntDict g_contextDict; -static QIntDict g_nameDict; -static QIntDict g_objectDict; -static QIntDict g_wordDict; -static QIntDict g_commentDict; -static int g_braceCount=0; - -static void saveObjCContext(); -static void restoreObjCContext(); - -static const char *stateToString(int state); - -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 @@ -223,7 +131,7 @@ class VariableContext m_scopes.clear(); } - void addVariable(const QCString &type,const QCString &name); + void addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name); ClassDef *findVariable(const QCString &name); int count() const { return m_scopes.count(); } @@ -233,102 +141,6 @@ class VariableContext QList 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():"")); - Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast(); - const 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 ( !typeName.isEmpty() && - ( // 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().empty()) - { - 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 sli(m_scopes); - Scope *scope; - QCString key = name; - // search from inner to outer scope - for (sli.toLast();(scope=sli.current());--sli) - { - result = scope->find(key); - if (result) - { - DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); - return result; - } - } - // 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 @@ -396,2266 +208,997 @@ class CallContext QList m_defList; }; -static CallContext g_theCallContext; - -//------------------------------------------------------------------- -/*! add class/namespace name s to the scope */ -static void pushScope(const char *s) +struct codeYY_state { - g_classScopeLengthStack.push(new int(g_classScope.length())); - if (g_classScope.isEmpty() || leftScopeMatch(s,g_classScope)) - { - g_classScope = s; - } - else - { - g_classScope += "::"; - g_classScope += s; - } - //printf("pushScope(%s) result: '%s'\n",s,g_classScope.data()); -} + CodeOutputInterface * code = 0; + + ClassSDict *codeClassSDict = 0; + QCString curClassName; + QStrList curClassBases; + + QCString parmType; + QCString parmName; + + const char * inputString = 0; //!< the code fragment as text + int inputPosition = 0; //!< read offset during parsing + int inputLines = 0; //!< number of line in the code fragment + int yyLineNr = 0; //!< current line number + int yyColNr = 0; //!< current column number + bool needsTermination = FALSE; + + bool exampleBlock = FALSE; + QCString exampleName; + QCString exampleFile; + + bool insideTemplate = FALSE; + QCString type; + QCString name; + QCString args; + QCString classScope; + QCString realScope; + QStack scopeStack; //!< 1 if bracket starts a scope, + // 2 for internal blocks + int anchorCount = 0; + FileDef * sourceFileDef = 0; + bool lineNumbers = FALSE; + Definition * currentDefinition = 0; + MemberDef * currentMemberDef = 0; + bool includeCodeFragment = FALSE; + const char * currentFontClass = 0; + bool searchingForBody = FALSE; + bool insideBody = FALSE; + int bodyCurlyCount = 0; + QCString saveName; + QCString saveType; + QCString delimiter; + + int bracketCount = 0; + int curlyCount = 0; + int sharpCount = 0; + bool inFunctionTryBlock = FALSE; + bool inForEachExpression = FALSE; + + int lastTemplCastContext = 0; + int lastSpecialCContext = 0; + int lastStringContext = 0; + int lastSkipCppContext = 0; + int lastVerbStringContext = 0; + int lastObjCCallContext = 0; + int memCallContext = 0; + int lastCContext = 0; + int skipInlineInitContext = 0; + + SrcLangExt lang = SrcLangExt_Unknown; + bool insideObjC = FALSE; + bool insideProtocolList = FALSE; + + bool lexInit = FALSE; + + QStack classScopeLengthStack; + + int prefixed_with_this_keyword = FALSE; + const Definition *searchCtx = 0; + bool collectXRefs = FALSE; + + ObjCCallCtx * currentCtx=0; + int currentCtxId=0; + int currentNameId=0; + int currentObjId=0; + int currentWordId=0; + int currentCommentId=0; + QStack contextStack; + QIntDict contextDict; + QIntDict nameDict; + QIntDict objectDict; + QIntDict wordDict; + QIntDict commentDict; + int braceCount=0; + + QCString forceTagReference; + VariableContext theVarContext; + CallContext theCallContext; +}; -/*! 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("Too many end of scopes found!\n"); - } - //printf("popScope() result: '%s'\n",g_classScope.data()); -} +static bool isCastKeyword(const QCString &s); -static void setCurrentDoc(const QCString &anchor) -{ - if (Doxygen::searchIndex) - { - if (g_searchCtx) - { - g_code->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE); - } - else - { - g_code->setCurrentDoc(g_sourceFileDef,anchor,TRUE); - } - } -} +//------------------------------------------------------------------- -static void addToSearchIndex(const char *text) -{ - if (Doxygen::searchIndex) - { - g_code->addWord(text,FALSE); - } -} +static void saveObjCContext(yyscan_t yyscanner); +static void restoreObjCContext(yyscan_t yyscanner); +static const char *stateToString(yyscan_t yyscanner,int state); +static void addUsingDirective(yyscan_t yyscanner,const char *name); +static void pushScope(yyscan_t yyscanner,const char *s); +static void popScope(yyscan_t yyscanner); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); +static void addToSearchIndex(yyscan_t yyscanner,const char *text); +static void setClassScope(yyscan_t yyscanner,const QCString &name); +static void startCodeLine(yyscan_t yyscanner); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void startFontClass(yyscan_t yyscanner,const char *s); +static void endFontClass(yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, + const Definition *d, + const char *text); +static void addType(yyscan_t yyscanner); +static void addParmType(yyscan_t yyscanner); +static void addUsingDirective(yyscan_t yyscanner,const char *name); +static void setParameterList(yyscan_t yyscanner,const MemberDef *md); +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d); +static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); +static void updateCallContextForSmartPointer(yyscan_t yyscanner); +static bool getLinkInScope(yyscan_t yyscanner,const QCString &c, // scope + const QCString &m, // member + const char *memberText, // exact text + CodeOutputInterface &ol, + const char *text, + bool varOnly=FALSE + ); +static bool getLink(yyscan_t yyscanner,const char *className, + const char *memberName, + CodeOutputInterface &ol, + const char *text=0, + bool varOnly=FALSE); +static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *clName, + bool typeOnly=FALSE,bool varOnly=FALSE); +static bool generateClassMemberLink(yyscan_t yyscanner,CodeOutputInterface &ol,MemberDef *xmd,const char *memName); +static bool generateClassMemberLink(yyscan_t yyscanner,CodeOutputInterface &ol,const Definition *def,const char *memName); +static void generateMemberLink(yyscan_t yyscanner,CodeOutputInterface &ol,const QCString &varName, + const char *memName); +static void generatePHPVariableLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *varName); +static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *funcName); +static int countLines(yyscan_t yyscanner); +static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx); +static QCString escapeName(yyscan_t yyscanner,const char *s); +static QCString escapeObject(yyscan_t yyscanner,const char *s); +static QCString escapeWord(yyscan_t yyscanner,const char *s); +static QCString escapeComment(yyscan_t yyscanner,const char *s); +static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const QCString &kw); +static int yyread(yyscan_t yyscanner,char *buf,int max_size); -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); - 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); - } - } - DBG_CTX((stderr,"startCodeLine(%d)\n",g_yyLineNr)); - g_code->startCodeLine(g_sourceFileDef && g_lineNumbers); - if (g_currentFontClass) - { - g_code->startFontClass(g_currentFontClass); - } -} - +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); -static void endFontClass(); -static void startFontClass(const char *s); -static void endCodeLine() -{ - DBG_CTX((stderr,"endCodeLine(%d)\n",g_yyLineNr)); - endFontClass(); - g_code->endCodeLine(); -} +%} -static void nextCodeLine() -{ - const char * fc = g_currentFontClass; - endCodeLine(); - if (g_yyLineNr]*">" +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"|"set"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"null"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|"alignas"|"alignof"|{KEYWORD_OBJC}) +FLOWKW ("break"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"return"|"switch"|"throw"|"throws"|"@catch"|"@finally") +FLOWCONDITION ("case"|"for"|"foreach"|"for each"|"goto"|"if"|"try"|"while"|"@try") +TYPEKW ("bool"|"byte"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr") +TYPEKWSL ("LocalObject"|"Object"|"Value") +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}\" -/*! 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') { g_yyColNr++; } - if (c=='\n') - { - g_yyLineNr++; - g_yyColNr=1; - //*(p-1)='\0'; - int l = (int)(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; - } - } -} +%option noyywrap -/*! 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 Definition *d, - const char *text) -{ - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); - QCString ref = d->getReference(); - QCString file = d->getOutputFileBase(); - QCString anchor = d->anchor(); - QCString tooltip; - if (!sourceTooltips) // fall back to simple "title" tooltips - { - tooltip = d->briefDescriptionAsTooltip(); - } - 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; - } - } -} +%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 AlignAs +%x AlignAsEnd +%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 ObjCCallComment +%x OldStyleArgs +%x UsingName +%x RawString +%x InlineInit -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) ; -} +<*>\x0d +^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") { + startFontClass(yyscanner,"preprocessor"); + yyextra->code->codify(yytext); + BEGIN( ReadInclude ); + } +("@interface"|"@implementation"|"@protocol")[ \t\n]+ { + yyextra->insideObjC=TRUE; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (!yyextra->insideTemplate) + BEGIN( ClassName ); + } +(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") { + if (yyextra->insideTemplate) REJECT; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( ClassName ); + } +"property"|"event"/{BN}* { + if (yyextra->insideTemplate) REJECT; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (!yyextra->insideTemplate) + BEGIN( ClassName ); + } +("package")[ \t\n]+ { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( PackageName ); + } +\n { + if (!yyextra->insideObjC) REJECT; + codifyLines(yyscanner,yytext); + BEGIN(Body); + } +"-"|"+" { + if (!yyextra->insideObjC || yyextra->insideBody) + { + yyextra->code->codify(yytext); + } + else // Start of Objective-C method + { + //printf("Method!\n"); + yyextra->code->codify(yytext); + BEGIN(ObjCMethod); + } + } +":" { + yyextra->code->codify(yytext); + BEGIN(ObjCParams); + } +"(" { + yyextra->code->codify(yytext); + BEGIN(ObjCParamType); + } +";"|"{" { + yyextra->code->codify(yytext); + if (*yytext=='{') + { + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + if (!yyextra->curClassName.isEmpty()) // valid class name + { + pushScope(yyscanner,yyextra->curClassName); + DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n")); + yyextra->scopeStack.push(SCOPEBLOCK); + } + } + yyextra->type.resize(0); + yyextra->name.resize(0); + BEGIN(Body); + } +{ID}{B}*":" { + yyextra->code->codify(yytext); + } +{TYPEKW} { + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->parmType=yytext; + } +{ID} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->parmType=yytext; + } +")" { + yyextra->code->codify(yytext); + BEGIN(ObjCParams); + } +{ID} { + yyextra->code->codify(yytext); + yyextra->parmName=yytext; + yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + } +{ID} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +. { + yyextra->code->codify(yytext); + } +\n { + codifyLines(yyscanner,yytext); + } +[^\n\"\>]+/(">"|"\"") { + //FileInfo *f; + bool ambig; + bool found=FALSE; + //QCString absPath = yytext; + //if (yyextra->sourceFileDef && QDir::isRelativePath(absPath)) + //{ + // absPath = QDir::cleanDirPath(yyextra->sourceFileDef->getPath()+"/"+absPath); + //} -static void addUsingDirective(const char *name) -{ - if (g_sourceFileDef && name) - { - NamespaceDef *nd = Doxygen::namespaceSDict->find(name); - if (nd) - { - g_sourceFileDef->addUsingDirective(nd); - } - } -} + 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 = QDir::cleanDirPath(yytext).utf8(); + if (!name.isEmpty() && yyextra->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 = yyextra->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() : "",found); + if (found) + { + writeMultiLineCodeLink(yyscanner,*yyextra->code,fd,yytext); + } + else + { + yyextra->code->codify(yytext); + } + char c=yyinput(yyscanner); + QCString text; + text+=c; + yyextra->code->codify(text); + endFontClass(yyscanner); + BEGIN( Body ); + } +^[ \t]*"#" { + startFontClass(yyscanner,"preprocessor"); + yyextra->lastSkipCppContext = YY_START; + yyextra->code->codify(yytext); + BEGIN( SkipCPP ) ; + } +. { + yyextra->code->codify(yytext); + } +[^\n\/\\]+ { + yyextra->code->codify(yytext); + } +\\[\r]?\n { + codifyLines(yyscanner,yytext); + } +"//" { + yyextra->code->codify(yytext); + } +"{" { + yyextra->theVarContext.pushScope(); -static void setParameterList(const MemberDef *md) -{ - g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : ""; - for (const Argument &a : md->argumentList()) - { - g_parmName = a.name; - g_parmType = a.type; - 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); - } -} + DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); + yyextra->scopeStack.push(INNERBLOCK); -static const 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; - const 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; - } - } + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + yyextra->code->codify(yytext); + if (yyextra->insideBody) + { + yyextra->bodyCurlyCount++; + } + yyextra->type.resize(0); + yyextra->name.resize(0); + BEGIN( Body ); + } +"}" { + yyextra->theVarContext.popScope(); + yyextra->type.resize(0); + yyextra->name.resize(0); - return 0; -} + int *scope = yyextra->scopeStack.pop(); + DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); + if (scope==SCOPEBLOCK || scope==CLASSBLOCK) + { + popScope(yyscanner); + } -static MemberDef *setCallContextForVar(const QCString &name) -{ - if (name.isEmpty()) return 0; - DBG_CTX((stderr,"setCallContextForVar(%s) g_classScope=%s\n",name.data(),g_classScope.data())); + yyextra->code->codify(yytext); - 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.setScope(stripClassName(md->typeString(),md->getOuterScope())); - return md; - } - } - else // check namespace as well - { - const 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.setScope(stripClassName(md->typeString(),md->getOuterScope())); - return md; - } - } - } - } - - MemberName *mn; - ClassDef *mcd = g_theVarContext.findVariable(name); - if (mcd) // local variable - { - DBG_CTX((stderr,"local variable?\n")); - if (mcd!=VariableContext::dummyContext) - { - DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcd->name().data())); - g_theCallContext.setScope(mcd); - } - } - else - { - DBG_CTX((stderr,"class member? scope=%s\n",g_classScope.data())); - // look for a class member - mcd = getClass(g_classScope); - if (mcd) - { - DBG_CTX((stderr,"Inside class %s\n",mcd->name().data())); - MemberDef *md=mcd->getMemberByName(name); - if (md) - { - DBG_CTX((stderr,"Found member %s\n",md->name().data())); - if (g_scopeStack.top()!=CLASSBLOCK) - { - DBG_CTX((stderr,"class member '%s' mcd=%s\n",name.data(),mcd->name().data())); - g_theCallContext.setScope(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.setScope(stripClassName(md->typeString(),md->getOuterScope())); - return md; - } - return 0; - } - else if (mn->count()>1) // global defined more than once - { - MemberNameIterator it(*mn); - MemberDef *md; - for (;(md=it.current());++it) - { - //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.setScope(stripClassName(md->typeString(),md->getOuterScope())); - //printf("returning member %s in source file %s\n",md->name().data(),g_sourceFileDef->name().data()); - return md; - } - } - return 0; - } - } - return 0; -} - -static void updateCallContextForSmartPointer() -{ - const Definition *d = g_theCallContext.getScope(); - //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : ""); - MemberDef *md; - if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast(d))->isSmartPointer())) - { - const ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope()); - if (ncd) - { - g_theCallContext.setScope(ncd); - //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data()); - } - } -} + DBG_CTX((stderr,"yyextra->bodyCurlyCount=%d\n",yyextra->bodyCurlyCount)); + if (--yyextra->bodyCurlyCount<=0) + { + yyextra->insideBody=FALSE; + yyextra->currentMemberDef=0; + if (yyextra->currentDefinition) + yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); + } + BEGIN(Body); + } +"@end" { + //printf("End of objc scope fd=%s\n",yyextra->sourceFileDef->name().data()); + if (yyextra->sourceFileDef) + { + FileDef *fd=yyextra->sourceFileDef; + yyextra->insideObjC = fd->name().lower().right(2)==".m" || + fd->name().lower().right(3)==".mm"; + //printf("insideObjC=%d\n",yyextra->insideObjC); + } + else + { + yyextra->insideObjC = FALSE; + } + if (yyextra->insideBody) + { + yyextra->theVarContext.popScope(); -static bool getLinkInScope(const QCString &c, // scope - const QCString &m, // member - const char *memberText, // exact text - CodeOutputInterface &ol, - const char *text, - bool varOnly=FALSE - ) -{ - const MemberDef *md = 0; - const ClassDef *cd = 0; - const FileDef *fd = 0; - const NamespaceDef *nd = 0; - const GroupDef *gd = 0; - DBG_CTX((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) && - (!varOnly || md->isVariable())) - { - if (md->isLinkable()) - { - //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 (const_cast(md)->addExample(anchor,g_exampleName,g_exampleFile)) - { - ol.writeCodeAnchor(anchor); - g_anchorCount++; - } - } + int *scope = yyextra->scopeStack.pop(); + DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); + if (scope==SCOPEBLOCK || scope==CLASSBLOCK) + { + popScope(yyscanner); + } + yyextra->insideBody=FALSE; + } - const Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->resolveAlias()->getFileDef() : md->getOuterScope(); - if (md->resolveAlias()->getGroupDef()) d = md->resolveAlias()->getGroupDef(); - if (d && d->isLinkable()) - { - g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope())); - //printf("g_currentDefinition=%p g_currentMemberDef=%p g_insideBody=%d\n", - // g_currentDefinition,g_currentMemberDef,g_insideBody); + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); - if (g_currentDefinition && g_currentMemberDef && - md!=g_currentMemberDef && g_insideBody && g_collectXRefs) - { - addDocCrossReference(g_currentMemberDef,const_cast(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()); - - writeMultiLineCodeLink(ol,md, text ? text : memberText); - addToSearchIndex(text ? text : memberText); - return TRUE; - } - } - else // found member, but it is not linkable, so make sure content inside is not assigned - // to the previous member, see bug762760 - { - DBG_CTX((stderr,"unlinkable member %s\n",md->name().data())); - g_currentMemberDef = 0; - } - } - 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"; - } - if (g_lang==SrcLangExt_PHP) - { - className = substitute(className,"\\","::"); // for PHP namespaces - } - else if (g_lang==SrcLangExt_CSharp || g_lang==SrcLangExt_Java) - { - className = substitute(className,".","::"); // for PHP namespaces - } - const ClassDef *cd=0,*lcd=0; - const MemberDef *md=0; - bool isLocal=FALSE; - - //printf("generateClassOrGlobalLink(className=%s)\n",className.data()); - if (!g_prefixed_with_this_keyword || (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():"",g_sourceFileDef?g_sourceFileDef->name().data():""); - cd = getResolvedClass(d,g_sourceFileDef,className,&md); - DBG_CTX((stderr,"non-local variable name=%s context=%d cd=%s md=%s!\n", - className.data(),g_theVarContext.count(),cd?cd->name().data():"", - md?md->name().data():"")); - if (cd==0 && md==0 && (i=className.find('<'))!=-1) - { - QCString bareName = className.left(i); //stripTemplateSpecifiersFromScope(className); - DBG_CTX((stderr,"bareName=%s\n",bareName.data())); - if (bareName!=className) - { - cd=getResolvedClass(d,g_sourceFileDef,bareName,&md); // try unspecialized version - } - } - const NamespaceDef *nd = getResolvedNamespace(className); - if (nd && nd->isLinkable()) - { - g_theCallContext.setScope(nd); - addToSearchIndex(className); - writeMultiLineCodeLink(*g_code,nd,clName); - return; - } - //printf("md=%s\n",md?md->name().data():""); - DBG_CTX((stderr,"is found as a type cd=%s nd=%s\n", - cd?cd->name().data():"", - nd?nd->name().data():"")); - 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.setScope(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; - DBG_CTX((stderr,"is a local variable cd=%p!\n",cd)); - } - g_prefixed_with_this_keyword = FALSE; // discard the "this" prefix for the next calls - - if (cd && cd->isLinkable()) // is it a linkable class - { - DBG_CTX((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 (const_cast(cd)->addExample(anchor,g_exampleName,g_exampleFile)) - { - ol.writeCodeAnchor(anchor); - g_anchorCount++; - } - } - writeMultiLineCodeLink(ol,cd,clName); - addToSearchIndex(className); - g_theCallContext.setScope(cd); - if (md) - { - const Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getFileDef() : md->getOuterScope(); - if (md->getGroupDef()) d = md->getGroupDef(); - if (d && d->isLinkable() && md->isLinkable() && - g_currentMemberDef && g_collectXRefs) - { - addDocCrossReference(g_currentMemberDef,const_cast(md)); - } - } - } - else // not a class, maybe a global member - { - DBG_CTX((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) - { - DBG_CTX((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())) - { - DBG_CTX((stderr,"is a global md=%p g_currentDefinition=%s linkable=%d\n",md,g_currentDefinition?g_currentDefinition->name().data():"",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; - const_cast(md)->setName(text); - const_cast(md)->setLocalName(text); - } - else // normal reference - { - text=clName; - } - writeMultiLineCodeLink(ol,md,text); - addToSearchIndex(clName); - if (g_currentMemberDef && g_collectXRefs) - { - addDocCrossReference(g_currentMemberDef,const_cast(md)); - } - return; - } - } - } - - // nothing found, just write out the word - DBG_CTX((stderr,"not found!\n")); - 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++; - } - } - - const ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); - DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass)); - g_theCallContext.setScope(typeClass); - - const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? - xmd->getFileDef() : xmd->getOuterScope(); - if (xmd->getGroupDef()) xd = xmd->getGroupDef(); - if (xd && xd->isLinkable()) - { - - //printf("g_currentDefinition=%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 && g_collectXRefs) - { - addDocCrossReference(g_currentMemberDef,xmd); - } - - // write the actual link - writeMultiLineCodeLink(ol,xmd,memName); - addToSearchIndex(memName); - return TRUE; - } - } - - return FALSE; -} - -static bool generateClassMemberLink(CodeOutputInterface &ol,const Definition *def,const char *memName) -{ - if (def && def->definitionType()==Definition::TypeClass) - { - const ClassDef *cd = dynamic_cast(def); - MemberDef *xmd = cd->getMemberByName(memName); - //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd); - if (xmd) - { - return generateClassMemberLink(ol,xmd,memName); - } - else - { - Definition *innerDef = cd->findInnerCompound(memName); - if (innerDef) - { - g_theCallContext.setScope(innerDef); - addToSearchIndex(memName); - writeMultiLineCodeLink(*g_code,innerDef,memName); - return TRUE; - } - } - } - else if (def && def->definitionType()==Definition::TypeNamespace) - { - const NamespaceDef *nd = dynamic_cast(def); - //printf("Looking for %s inside namespace %s\n",memName,nd->name().data()); - Definition *innerDef = nd->findInnerCompound(memName); - if (innerDef) - { - g_theCallContext.setScope(innerDef); - addToSearchIndex(memName); - writeMultiLineCodeLink(*g_code,innerDef,memName); - return TRUE; - } - } - 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 - const 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; - 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); - const MemberDef *vmd; - for (;(vmd=vmni.current());++vmni) - { - if (/*(vmd->isVariable() || vmd->isFunction()) && */ - vmd->getClassDef()==jcd) - { - //printf("Found variable type=%s\n",vmd->typeString()); - const 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); - const MemberDef *vmd; - for (;(vmd=vmni.current());++vmni) - { - if (/*(vmd->isVariable() || vmd->isFunction()) && */ - vmd->getClassDef()==vcd) - { - //printf("Found variable type=%s\n",vmd->typeString()); - const ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope()); - if (mcd && mcd->isLinkable()) - { - if (generateClassMemberLink(ol,mcd,memName)) return; - } - } - } - } - } - } - // nothing found -> write result as is - 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); - if (g_lang==SrcLangExt_PHP && locFunc.startsWith("self::")) locFunc=locFunc.mid(4); - QCString funcScope; - QCString funcWithScope=locFunc; - QCString funcWithFullScope=locFunc; - QCString fullScope=locScope; - DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data())); - int len=2; - int i=locFunc.findRev("::"); - if (g_currentMemberDef && g_currentMemberDef->resolveAlias()->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 = dynamic_cast(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():""); - } - 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 = (dynamic_cast(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->methodName.isEmpty()) - { - 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->methodName.isEmpty()) - { - 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()) - { - writeMultiLineCodeLink(*g_code,ctx->method,pName->data()); - if (g_currentMemberDef && g_collectXRefs) - { - addDocCrossReference(g_currentMemberDef,const_cast(ctx->method)); - } - } - else - { - 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 = dynamic_cast(g_currentDefinition); - if (ctx->objectType->categoryOf()) - { - ctx->objectType = ctx->objectType->categoryOf(); - } - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - 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 = dynamic_cast(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->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - } - } - } - } - } - startFontClass("keyword"); - codifyLines(pObject->data()); - endFontClass(); - } - else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable - { - writeMultiLineCodeLink(*g_code,ctx->objectVar,pObject->data()); - if (g_currentMemberDef && g_collectXRefs) - { - addDocCrossReference(g_currentMemberDef,const_cast(ctx->objectVar)); - } - } - else if (ctx->objectType && - ctx->objectType!=VariableContext::dummyContext && - ctx->objectType->isLinkable() - ) // object is class name - { - const ClassDef *cd = ctx->objectType; - writeMultiLineCodeLink(*g_code,cd,pObject->data()); - } - else // object still needs to be resolved - { - const ClassDef *cd = getResolvedClass(g_currentDefinition, - g_sourceFileDef, *pObject); - if (cd && cd->isLinkable()) - { - if (ctx->objectType==0) ctx->objectType=cd; - writeMultiLineCodeLink(*g_code,cd,pObject->data()); - } - else - { - 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->methodName.isEmpty()) - { - 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) - { - codifyLines(pWord->data()); - } - } - else if (nc=='d') // comment block - { - nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - QCString *pComment = g_commentDict.find(refId); - if (pComment) - { - startFontClass("comment"); - codifyLines(pComment->data()); - endFontClass(); - } - } - 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; -} - -static QCString escapeComment(const char *s) -{ - QCString result; - result.sprintf("$d%d",g_currentCommentId); - g_commentDict.insert(g_currentCommentId,new QCString(s)); - g_currentCommentId++; - return result; -} - -static bool skipLanguageSpecificKeyword(const QCString &kw) -{ - return g_lang==SrcLangExt_Cpp && (kw == "remove" || kw == "set" || kw == "get"); -} - -static bool isCastKeyword(const QCString &s) -{ - int i=s.find('<'); - if (i==-1) return FALSE; - QCString kw = s.left(i).stripWhiteSpace(); - return kw=="const_cast" || kw=="static_cast" || kw=="dynamic_cast" || kw=="reinterpret_cast"; -} - -/* ----------------------------------------------------------------- - */ -#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"|"set"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"null"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|"alignas"|"alignof"|{KEYWORD_OBJC}) -FLOWKW ("break"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"return"|"switch"|"throw"|"throws"|"@catch"|"@finally") -FLOWCONDITION ("case"|"for"|"foreach"|"for each"|"goto"|"if"|"try"|"while"|"@try") -TYPEKW ("bool"|"byte"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr") -TYPEKWSL ("LocalObject"|"Object"|"Value") -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 AlignAs -%x AlignAsEnd -%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 ObjCCallComment -%x OldStyleArgs -%x UsingName -%x RawString -%x InlineInit - -%% - -<*>\x0d -^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") { - startFontClass("preprocessor"); - g_code->codify(yytext); - BEGIN( ReadInclude ); - } -("@interface"|"@implementation"|"@protocol")[ \t\n]+ { - g_insideObjC=TRUE; - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - if (!g_insideTemplate) - BEGIN( ClassName ); - } -(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") { - if (g_insideTemplate) REJECT; - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - BEGIN( ClassName ); - } -"property"|"event"/{BN}* { - if (g_insideTemplate) REJECT; - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - if (!g_insideTemplate) - BEGIN( ClassName ); - } -("package")[ \t\n]+ { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - BEGIN( PackageName ); - } -\n { - if (!g_insideObjC) REJECT; - codifyLines(yytext); - BEGIN(Body); - } -"-"|"+" { - if (!g_insideObjC || g_insideBody) - { - g_code->codify(yytext); - } - else // Start of Objective-C method - { - //printf("Method!\n"); - g_code->codify(yytext); - BEGIN(ObjCMethod); - } - } -":" { - g_code->codify(yytext); - BEGIN(ObjCParams); - } -"(" { - g_code->codify(yytext); - BEGIN(ObjCParamType); - } -";"|"{" { - g_code->codify(yytext); - if (*yytext=='{') - { - 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); - } -{ID}{B}*":" { - g_code->codify(yytext); - } -{TYPEKW} { - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - g_parmType=yytext; - } -{ID} { - generateClassOrGlobalLink(*g_code,yytext); - g_parmType=yytext; - } -")" { - g_code->codify(yytext); - BEGIN(ObjCParams); - } -{ID} { - g_code->codify(yytext); - g_parmName=yytext; - g_theVarContext.addVariable(g_parmType,g_parmName); - g_parmType.resize(0);g_parmName.resize(0); - } -{ID} { - generateClassOrGlobalLink(*g_code,yytext); - } -. { - g_code->codify(yytext); - } -\n { - codifyLines(yytext); - } -[^\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 = QDir::cleanDirPath(yytext).utf8(); - 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() : "",found); - if (found) - { - writeMultiLineCodeLink(*g_code,fd,yytext); - } - else - { - g_code->codify(yytext); - } - char c=yyinput(); - QCString text; - text+=c; - g_code->codify(text); - endFontClass(); - BEGIN( Body ); - } -^[ \t]*"#" { - startFontClass("preprocessor"); - g_lastSkipCppContext = YY_START; - g_code->codify(yytext); - BEGIN( SkipCPP ) ; - } -. { - g_code->codify(yytext); - } -[^\n\/\\]+ { - g_code->codify(yytext); - } -\\[\r]?\n { - codifyLines(yytext); - } -"//" { - g_code->codify(yytext); - } -"{" { - 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); - if (g_insideBody) - { - g_bodyCurlyCount++; - } - g_type.resize(0); - g_name.resize(0); - BEGIN( Body ); - } -"}" { - 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); - - DBG_CTX((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); - } -"@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); - } -";" { - g_code->codify(yytext); - g_searchingForBody=FALSE; - BEGIN( Body ); - } -[*&^%]+ { - g_type=g_curClassName.copy(); - g_name.resize(0); - g_code->codify(yytext); - BEGIN( Body ); // variable of type struct * - } -"__declspec"{B}*"("{B}*{ID}{B}*")" { - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); - } -{ID}("."{ID})* | -{ID}("::"{ID})* { - if (g_lang==SrcLangExt_CSharp) - g_curClassName=substitute(yytext,".","::"); - else - g_curClassName=yytext; - addType(); - if (g_curClassName=="alignas") - { - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); - BEGIN( AlignAs ); - } - else - { - generateClassOrGlobalLink(*g_code,yytext); - BEGIN( ClassVar ); - } - } -"(" { - g_bracketCount=1; - g_code->codify(yytext); - BEGIN( AlignAsEnd ); - } -\n { g_yyLineNr++; - codifyLines(yytext); - } -. { g_code->codify(yytext); } -"(" { g_code->codify(yytext); - g_bracketCount++; - } -")" { - g_code->codify(yytext); - if (--g_bracketCount<=0) - { - BEGIN(ClassName); - } - } -\n { g_yyLineNr++; - codifyLines(yytext); - } -. { g_code->codify(yytext); } -{ID}("\\"{ID})* { // PHP namespace - g_curClassName=substitute(yytext,"\\","::"); - g_scopeStack.push(CLASSBLOCK); - pushScope(g_curClassName); - addType(); - generateClassOrGlobalLink(*g_code,yytext); - BEGIN( ClassVar ); - } -{ID}{B}*"("{ID}")" { // Obj-C category - g_curClassName=removeRedundantWhiteSpace(yytext); - g_scopeStack.push(CLASSBLOCK); - pushScope(g_curClassName); - addType(); - generateClassOrGlobalLink(*g_code,yytext); - BEGIN( ClassVar ); - } -{ID}("."{ID})* { - g_curClassName=substitute(yytext,".","::"); - //printf("found package: %s\n",g_curClassName.data()); - addType(); - codifyLines(yytext); - } -"=" { - unput(*yytext); - BEGIN( Body ); - } -("extends"|"implements") { // Java, Slice - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - g_curClassBases.clear(); - BEGIN( Bases ); - } -("sealed"|"abstract")/{BN}*(":"|"{") { - DBG_CTX((stderr,"***** C++/CLI modifier %s on g_curClassName=%s\n",yytext,g_curClassName.data())); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - BEGIN( CppCliTypeModifierFollowup ); - } -{ID} { - g_type = g_curClassName.copy(); - g_name = yytext; - if (g_insideBody) - { - g_theVarContext.addVariable(g_type,g_name); - } - generateClassOrGlobalLink(*g_code,yytext); - } -{B}*":"{B}* { - codifyLines(yytext); - g_curClassBases.clear(); - BEGIN( Bases ); - } -[ \t]*";" | -^{B}*/"@"{ID} | // Objective-C interface -{B}*"{"{B}* { - g_theVarContext.pushScope(); - g_code->codify(yytext); - 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); - DBG_CTX((stderr,"***** g_curClassName=%s\n",g_curClassName.data())); - if (getResolvedClass(g_currentDefinition,g_sourceFileDef,g_curClassName)==0) - { - DBG_CTX((stderr,"Adding new class %s\n",g_curClassName.data())); - ClassDef *ncd=createClassDef("",1,1, - g_curClassName,ClassDef::Class,0,0,FALSE); - g_codeClassSDict->append(g_curClassName,ncd); - // insert base classes. - char *s=g_curClassBases.first(); - while (s) - { - const ClassDef *bcd=g_codeClassSDict->find(s); - if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s); - if (bcd && bcd!=ncd) - { - ncd->insertBaseClass(const_cast(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 ); - } -"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" { - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); - } -{SEP}?({ID}{SEP})*{ID} { - DBG_CTX((stderr,"%s:addBase(%s)\n",g_curClassName.data(),yytext)); - g_curClassBases.inSort(yytext); - generateClassOrGlobalLink(*g_code,yytext); - } -"<" { - g_code->codify(yytext); - if (!g_insideObjC) - { - g_sharpCount=1; - BEGIN ( SkipSharp ); - } - else - { - g_insideProtocolList=TRUE; - } - } -">" { - g_code->codify(yytext); - g_insideProtocolList=FALSE; - } -"<" { - g_code->codify(yytext); - ++g_sharpCount; - } -">" { - g_code->codify(yytext); - if (--g_sharpCount<=0) - BEGIN ( Bases ); - } -"\"" { - g_code->codify(yytext); - g_lastStringContext=YY_START; - BEGIN(SkipString); - } -"\'" { - g_code->codify(yytext); - g_lastStringContext=YY_START; - BEGIN(SkipStringS); - } -"(" { - g_code->codify(yytext); - g_sharpCount=1; - BEGIN ( SkipSharp ); - } -"(" { - g_code->codify(yytext); - ++g_sharpCount; - } -")" { - g_code->codify(yytext); - if (--g_sharpCount<=0) - BEGIN ( Bases ); - } - - -"," { - g_code->codify(yytext); - } - + yyextra->currentMemberDef=0; + if (yyextra->currentDefinition) + yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); + BEGIN(Body); + } +";" { + yyextra->code->codify(yytext); + yyextra->searchingForBody=FALSE; + BEGIN( Body ); + } +[*&^%]+ { + yyextra->type=yyextra->curClassName.copy(); + yyextra->name.resize(0); + yyextra->code->codify(yytext); + BEGIN( Body ); // variable of type struct * + } +"__declspec"{B}*"("{B}*{ID}{B}*")" { + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +{ID}("."{ID})* | +{ID}("::"{ID})* { + if (yyextra->lang==SrcLangExt_CSharp) + yyextra->curClassName=substitute(yytext,".","::"); + else + yyextra->curClassName=yytext; + addType(yyscanner); + if (yyextra->curClassName=="alignas") + { + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( AlignAs ); + } + else + { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( ClassVar ); + } + } +"(" { + yyextra->bracketCount=1; + yyextra->code->codify(yytext); + BEGIN( AlignAsEnd ); + } +\n { yyextra->yyLineNr++; + codifyLines(yyscanner,yytext); + } +. { yyextra->code->codify(yytext); } +"(" { yyextra->code->codify(yytext); + yyextra->bracketCount++; + } +")" { + yyextra->code->codify(yytext); + if (--yyextra->bracketCount<=0) + { + BEGIN(ClassName); + } + } +\n { yyextra->yyLineNr++; + codifyLines(yyscanner,yytext); + } +. { yyextra->code->codify(yytext); } +{ID}("\\"{ID})* { // PHP namespace + yyextra->curClassName=substitute(yytext,"\\","::"); + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yyextra->curClassName); + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( ClassVar ); + } +{ID}{B}*"("{ID}")" { // Obj-C category + yyextra->curClassName=removeRedundantWhiteSpace(yytext); + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yyextra->curClassName); + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( ClassVar ); + } +{ID}("."{ID})* { + yyextra->curClassName=substitute(yytext,".","::"); + //printf("found package: %s\n",yyextra->curClassName.data()); + addType(yyscanner); + codifyLines(yyscanner,yytext); + } +"=" { + unput(*yytext); + BEGIN( Body ); + } +("extends"|"implements") { // Java, Slice + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->curClassBases.clear(); + BEGIN( Bases ); + } +("sealed"|"abstract")/{BN}*(":"|"{") { + DBG_CTX((stderr,"***** C++/CLI modifier %s on yyextra->curClassName=%s\n",yytext,yyextra->curClassName.data())); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( CppCliTypeModifierFollowup ); + } +{ID} { + yyextra->type = yyextra->curClassName.copy(); + yyextra->name = yytext; + if (yyextra->insideBody) + { + yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); + } + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +{B}*":"{B}* { + codifyLines(yyscanner,yytext); + yyextra->curClassBases.clear(); + BEGIN( Bases ); + } +[ \t]*";" | +^{B}*/"@"{ID} | // Objective-C interface +{B}*"{"{B}* { + yyextra->theVarContext.pushScope(); + yyextra->code->codify(yytext); + if (YY_START==ClassVar && yyextra->curClassName.isEmpty()) + { + yyextra->curClassName = yyextra->name.copy(); + } + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + if (!yyextra->curClassName.isEmpty()) // valid class name + { + DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n")); + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yyextra->curClassName); + DBG_CTX((stderr,"***** yyextra->curClassName=%s\n",yyextra->curClassName.data())); + if (getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->curClassName)==0) + { + DBG_CTX((stderr,"Adding new class %s\n",yyextra->curClassName.data())); + ClassDef *ncd=createClassDef("",1,1, + yyextra->curClassName,ClassDef::Class,0,0,FALSE); + yyextra->codeClassSDict->append(yyextra->curClassName,ncd); + // insert base classes. + char *s=yyextra->curClassBases.first(); + while (s) + { + const ClassDef *bcd=yyextra->codeClassSDict->find(s); + if (bcd==0) bcd=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,s); + if (bcd && bcd!=ncd) + { + ncd->insertBaseClass(const_cast(bcd),s,Public,Normal); + } + s=yyextra->curClassBases.next(); + } + } + //printf("yyextra->codeClassList.count()=%d\n",yyextra->codeClassList.count()); + } + else // not a class name -> assume inner block + { + DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); + yyextra->scopeStack.push(INNERBLOCK); + } + yyextra->curClassName.resize(0); + yyextra->curClassBases.clear(); + BEGIN( Body ); + } +"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" { + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +{SEP}?({ID}{SEP})*{ID} { + DBG_CTX((stderr,"%s:addBase(%s)\n",yyextra->curClassName.data(),yytext)); + yyextra->curClassBases.inSort(yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +"<" { + yyextra->code->codify(yytext); + if (!yyextra->insideObjC) + { + yyextra->sharpCount=1; + BEGIN ( SkipSharp ); + } + else + { + yyextra->insideProtocolList=TRUE; + } + } +">" { + yyextra->code->codify(yytext); + yyextra->insideProtocolList=FALSE; + } +"<" { + yyextra->code->codify(yytext); + ++yyextra->sharpCount; + } +">" { + yyextra->code->codify(yytext); + if (--yyextra->sharpCount<=0) + BEGIN ( Bases ); + } +"\"" { + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + BEGIN(SkipString); + } +"\'" { + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + BEGIN(SkipStringS); + } +"(" { + yyextra->code->codify(yytext); + yyextra->sharpCount=1; + BEGIN ( SkipSharp ); + } +"(" { + yyextra->code->codify(yytext); + ++yyextra->sharpCount; + } +")" { + yyextra->code->codify(yytext); + if (--yyextra->sharpCount<=0) + BEGIN ( Bases ); + } + + +"," { + yyextra->code->codify(yytext); + } + {SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" { - addType(); - generateFunctionLink(*g_code,yytext); - g_bracketCount=0; - g_args.resize(0); - g_name+=yytext; + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; BEGIN( FuncCall ); } {SCOPEPREFIX}?"operator"/"(" { - addType(); - generateFunctionLink(*g_code,yytext); - g_bracketCount=0; - g_args.resize(0); - g_name+=yytext; + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; BEGIN( FuncCall ); } {SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\(\n]+/"(" { - addType(); - generateFunctionLink(*g_code,yytext); - g_bracketCount=0; - g_args.resize(0); - g_name+=yytext; + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; BEGIN( FuncCall ); } ("template"|"generic")/([^a-zA-Z0-9]) { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - g_insideTemplate=TRUE; - g_sharpCount=0; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->insideTemplate=TRUE; + yyextra->sharpCount=0; } "using"{BN}+"namespace"{BN}+ { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); BEGIN(UsingName); } -{ID}("::"{ID})* { addUsingDirective(yytext); - generateClassOrGlobalLink(*g_code,yytext); +{ID}("::"{ID})* { addUsingDirective(yyscanner,yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n")); - g_scopeStack.push(CLASSBLOCK); - pushScope(yytext); + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yytext); BEGIN(Body); } -\n { codifyLines(yytext); BEGIN(Body); } -. { codifyLines(yytext); BEGIN(Body); } -"$"?"this"("->"|".") { g_code->codify(yytext); // this-> for C++, this. for C# - g_prefixed_with_this_keyword = TRUE; +\n { codifyLines(yyscanner,yytext); BEGIN(Body); } +. { codifyLines(yyscanner,yytext); BEGIN(Body); } +"$"?"this"("->"|".") { yyextra->code->codify(yytext); // this-> for C++, this. for C# + yyextra->prefixed_with_this_keyword = TRUE; } {KEYWORD}/([^a-z_A-Z0-9]) { - if (g_lang==SrcLangExt_Java && qstrcmp("internal",yytext) ==0) REJECT; - if (skipLanguageSpecificKeyword(yytext)) REJECT; - startFontClass("keyword"); - codifyLines(yytext); + if (yyextra->lang==SrcLangExt_Java && qstrcmp("internal",yytext) ==0) REJECT; + if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); if (QCString(yytext)=="typedef") { - addType(); - g_name+=yytext; + addType(yyscanner); + yyextra->name+=yytext; } - endFontClass(); + endFontClass(yyscanner); } {KEYWORD}/{B}* { - if (skipLanguageSpecificKeyword(yytext)) REJECT; - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); + if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } {KEYWORD}/{BN}*"(" { - if (skipLanguageSpecificKeyword(yytext)) REJECT; - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - g_name.resize(0);g_type.resize(0); + if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->name.resize(0);yyextra->type.resize(0); } "in"/{BN}* { - if (!g_inForEachExpression) REJECT; - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); + if (!yyextra->inForEachExpression) REJECT; + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); // 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); + yyextra->theVarContext.popScope(); + yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + yyextra->theVarContext.pushScope(); + yyextra->name.resize(0);yyextra->type.resize(0); } {FLOWKW}/{BN}*"(" { - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - g_name.resize(0);g_type.resize(0); - g_inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0); + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->name.resize(0);yyextra->type.resize(0); + yyextra->inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0); BEGIN(FuncCall); } {FLOWCONDITION}/{BN}*"(" { - if (g_currentMemberDef && g_currentMemberDef->isFunction()) + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) { - g_currentMemberDef->incrementFlowKeyWordCount(); + yyextra->currentMemberDef->incrementFlowKeyWordCount(); } - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - g_name.resize(0);g_type.resize(0); - g_inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0); + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->name.resize(0);yyextra->type.resize(0); + yyextra->inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0); BEGIN(FuncCall); } {FLOWKW}/([^a-z_A-Z0-9]) { - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - if (g_inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0)) + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (yyextra->inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0)) { - g_inFunctionTryBlock=FALSE; + yyextra->inFunctionTryBlock=FALSE; } } {FLOWCONDITION}/([^a-z_A-Z0-9]) { - if (g_currentMemberDef && g_currentMemberDef->isFunction()) + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) { - g_currentMemberDef->incrementFlowKeyWordCount(); + yyextra->currentMemberDef->incrementFlowKeyWordCount(); } - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - if (g_inFunctionTryBlock && (strcmp(yytext,"catch")==0 || strcmp(yytext,"finally")==0)) + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (yyextra->inFunctionTryBlock && (strcmp(yytext,"catch")==0 || strcmp(yytext,"finally")==0)) { - g_inFunctionTryBlock=FALSE; + yyextra->inFunctionTryBlock=FALSE; } } {FLOWKW}/{B}* { - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } {FLOWCONDITION}/{B}* { - if (g_currentMemberDef && g_currentMemberDef->isFunction()) + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) { - g_currentMemberDef->incrementFlowKeyWordCount(); + yyextra->currentMemberDef->incrementFlowKeyWordCount(); } - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } "*"{B}*")" { // end of cast? - g_code->codify(yytext); - g_theCallContext.popScope(g_name, g_type); - g_bracketCount--; - g_parmType = g_name; + yyextra->code->codify(yytext); + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->bracketCount--; + yyextra->parmType = yyextra->name; BEGIN(FuncCall); } [\\|\)\+\-\/\%\~\!] { - g_code->codify(yytext); - g_name.resize(0);g_type.resize(0); + yyextra->code->codify(yytext); + yyextra->name.resize(0);yyextra->type.resize(0); if (*yytext==')') { - g_theCallContext.popScope(g_name, g_type); - g_bracketCount--; + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->bracketCount--; BEGIN(FuncCall); } } {TYPEKW}/{B}* { - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - addType(); - g_name+=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + addType(yyscanner); + yyextra->name+=yytext; } {TYPEKWSL}/{B}* { - if (g_lang!=SrcLangExt_Slice) + if (yyextra->lang!=SrcLangExt_Slice) { REJECT; } else { - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - addType(); - g_name+=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + addType(yyscanner); + yyextra->name+=yytext; } } "generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); - g_sharpCount=0; + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->sharpCount=0; BEGIN(TemplDecl); } "template"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { // template<...> - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); - g_sharpCount=0; + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->sharpCount=0; BEGIN(TemplDecl); } "class"|"typename" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } "<" { - g_code->codify(yytext); - g_sharpCount++; + yyextra->code->codify(yytext); + yyextra->sharpCount++; } ">" { - g_code->codify(yytext); - g_sharpCount--; - if (g_sharpCount<=0) + yyextra->code->codify(yytext); + yyextra->sharpCount--; + if (yyextra->sharpCount<=0) { BEGIN(Body); } } ">" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - BEGIN( g_lastTemplCastContext ); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastTemplCastContext ); } {ID}("::"{ID})* { - generateClassOrGlobalLink(*g_code,yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); } ("const"|"volatile"){B}* { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } [*^]* { - codifyLines(yytext); + codifyLines(yyscanner,yytext); } {CASTKW}{B}*"<" { // static_cast( - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - g_lastTemplCastContext = YY_START; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->lastTemplCastContext = YY_START; BEGIN(TemplCast); } "$this->"{SCOPENAME}/{BN}*[;,)\]] { // PHP member variable - addType(); - generatePHPVariableLink(*g_code,yytext); - g_name+=yytext+7; + addType(yyscanner); + generatePHPVariableLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext+7; } {SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>\(]*">"("::"{ID})*/{B}* { // A *pt; if (isCastKeyword(yytext) && YY_START==Body) { REJECT; } - addType(); - generateClassOrGlobalLink(*g_code,yytext); - g_name+=yytext; + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; } {SCOPENAME}/{BN}*[:;,)\]] { // "int var;" or "var, var2" or "debug(f) macro" , or int var : 5; - addType(); + addType(yyscanner); // changed this to generateFunctionLink, see bug 624514 - //generateClassOrGlobalLink(*g_code,yytext,FALSE,TRUE); - generateFunctionLink(*g_code,yytext); - g_name+=yytext; + //generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,FALSE,TRUE); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; } {SCOPENAME}/{B}* { // p->func() - addType(); - generateClassOrGlobalLink(*g_code,yytext); - g_name+=yytext; + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; } "("{B}*("*"{B}*)+{SCOPENAME}*{B}*")"/{B}* { // (*p)->func() but not "if (p) ..." - g_code->codify(yytext); + yyextra->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; + addType(yyscanner); + yyextra->name=varname; } {SCOPETNAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"/{BN}*"(" | {SCOPETNAME}/{BN}*"(" { // a() or c::a() or t::a() or A\B\foo() @@ -2663,223 +1206,223 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" { REJECT; } - addType(); - generateFunctionLink(*g_code,yytext); - g_bracketCount=0; - g_args.resize(0); - g_name+=yytext; + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; BEGIN( FuncCall ); } {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); + yyextra->code->codify(text.left(i+1)); + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext+i+1); + yyextra->lastStringContext=YY_START; + yyextra->inForEachExpression = FALSE; + yyextra->delimiter = yytext+i+2; + yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); BEGIN( RawString ); } \" { - startFontClass("stringliteral"); - g_code->codify(yytext); - g_lastStringContext=YY_START; - g_inForEachExpression = FALSE; + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + yyextra->inForEachExpression = FALSE; BEGIN( SkipString ); } \' { - startFontClass("stringliteral"); - g_code->codify(yytext); - g_lastStringContext=YY_START; - g_inForEachExpression = FALSE; + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + yyextra->inForEachExpression = FALSE; BEGIN( SkipStringS ); } [^\"\\\r\n]* { - g_code->codify(yytext); + yyextra->code->codify(yytext); } [^\'\\\r\n]* { - g_code->codify(yytext); + yyextra->code->codify(yytext); } "//"|"/*" { - g_code->codify(yytext); + yyextra->code->codify(yytext); } @?\" { - g_code->codify(yytext); - endFontClass(); - BEGIN( g_lastStringContext ); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastStringContext ); } \' { - g_code->codify(yytext); - endFontClass(); - BEGIN( g_lastStringContext ); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastStringContext ); } \\. { - g_code->codify(yytext); + yyextra->code->codify(yytext); } {RAWEND} { - g_code->codify(yytext); + yyextra->code->codify(yytext); QCString delimiter = yytext+1; delimiter=delimiter.left(delimiter.length()-1); - if (delimiter==g_delimiter) + if (delimiter==yyextra->delimiter) { - BEGIN( g_lastStringContext ); + BEGIN( yyextra->lastStringContext ); } } -[^)\n]+ { g_code->codify(yytext); } -. { g_code->codify(yytext); } -\n { codifyLines(yytext); } +[^)\n]+ { yyextra->code->codify(yytext); } +. { yyextra->code->codify(yytext); } +\n { codifyLines(yyscanner,yytext); } [^"\n]+ { - g_code->codify(yytext); + yyextra->code->codify(yytext); } \"\" { // escaped quote - g_code->codify(yytext); + yyextra->code->codify(yytext); } \" { // end of string - g_code->codify(yytext); - endFontClass(); - BEGIN( g_lastVerbStringContext ); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastVerbStringContext ); } . { - g_code->codify(yytext); + yyextra->code->codify(yytext); } \n { - codifyLines(yytext); + codifyLines(yyscanner,yytext); } ":" { - g_code->codify(yytext); - g_name.resize(0);g_type.resize(0); + yyextra->code->codify(yytext); + yyextra->name.resize(0);yyextra->type.resize(0); } "<" { - if (g_insideTemplate) + if (yyextra->insideTemplate) { - g_sharpCount++; + yyextra->sharpCount++; } - g_code->codify(yytext); + yyextra->code->codify(yytext); } ">" { - if (g_insideTemplate) + if (yyextra->insideTemplate) { - if (--g_sharpCount<=0) + if (--yyextra->sharpCount<=0) { - g_insideTemplate=FALSE; + yyextra->insideTemplate=FALSE; } } - g_code->codify(yytext); + yyextra->code->codify(yytext); } "'"((\\0[Xx0-9]+)|(\\.)|(.))"'" { - startFontClass("charliteral"); - g_code->codify(yytext); - endFontClass(); + startFontClass(yyscanner,"charliteral"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } "."|"->" { if (yytext[0]=='-') // -> could be overloaded { - updateCallContextForSmartPointer(); + updateCallContextForSmartPointer(yyscanner); } - g_code->codify(yytext); - g_memCallContext = YY_START; + yyextra->code->codify(yytext); + yyextra->memCallContext = YY_START; BEGIN( MemberCall ); } {SCOPETNAME}/{BN}*"(" { - if (g_theCallContext.getScope()) + if (yyextra->theCallContext.getScope()) { - if (!generateClassMemberLink(*g_code,g_theCallContext.getScope(),yytext)) + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) { - g_code->codify(yytext); - addToSearchIndex(yytext); + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); } - g_name.resize(0); + yyextra->name.resize(0); } else { - g_code->codify(yytext); - addToSearchIndex(yytext); - g_name.resize(0); + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + yyextra->name.resize(0); } - g_type.resize(0); - if (g_memCallContext==Body) + yyextra->type.resize(0); + if (yyextra->memCallContext==Body) { BEGIN(FuncCall); } else { - BEGIN(g_memCallContext); + BEGIN(yyextra->memCallContext); } } {SCOPENAME}/{B}* { - if (g_theCallContext.getScope()) + if (yyextra->theCallContext.getScope()) { - DBG_CTX((stderr,"g_theCallContext.getClass()=%p\n",g_theCallContext.getScope())); - if (!generateClassMemberLink(*g_code,g_theCallContext.getScope(),yytext)) + DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope())); + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) { - g_code->codify(yytext); - addToSearchIndex(yytext); + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); } - g_name.resize(0); + yyextra->name.resize(0); } else { DBG_CTX((stderr,"no class context!\n")); - g_code->codify(yytext); - addToSearchIndex(yytext); - g_name.resize(0); + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + yyextra->name.resize(0); } - g_type.resize(0); - BEGIN(g_memCallContext); + yyextra->type.resize(0); + BEGIN(yyextra->memCallContext); } [,=;\[] { - if (g_insideObjC && *yytext=='[') + if (yyextra->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_commentDict.setAutoDelete(TRUE); - g_contextDict.clear(); - g_nameDict.clear(); - g_objectDict.clear(); - g_wordDict.clear(); - g_commentDict.clear(); - g_currentCtxId = 0; - g_currentNameId = 0; - g_currentObjId = 0; - g_currentCtx = 0; - g_braceCount = 0; + yyextra->contextDict.setAutoDelete(TRUE); + yyextra->nameDict.setAutoDelete(TRUE); + yyextra->objectDict.setAutoDelete(TRUE); + yyextra->wordDict.setAutoDelete(TRUE); + yyextra->commentDict.setAutoDelete(TRUE); + yyextra->contextDict.clear(); + yyextra->nameDict.clear(); + yyextra->objectDict.clear(); + yyextra->wordDict.clear(); + yyextra->commentDict.clear(); + yyextra->currentCtxId = 0; + yyextra->currentNameId = 0; + yyextra->currentObjId = 0; + yyextra->currentCtx = 0; + yyextra->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()) + yyextra->code->codify(yytext); + yyextra->saveName = yyextra->name.copy(); + yyextra->saveType = yyextra->type.copy(); + if (*yytext!='[' && !yyextra->type.isEmpty()) { - //printf("g_scopeStack.bottom()=%p\n",g_scopeStack.bottom()); - //if (g_scopeStack.top()!=CLASSBLOCK) // commented out for bug731363 + //printf("yyextra->scopeStack.bottom()=%p\n",yyextra->scopeStack.bottom()); + //if (yyextra->scopeStack.top()!=CLASSBLOCK) // commented out for bug731363 { //printf("AddVariable: '%s' '%s' context=%d\n", - // g_type.data(),g_name.data(),g_theVarContext.count()); - g_theVarContext.addVariable(g_type,g_name); + // yyextra->type.data(),yyextra->name.data(),yyextra->theVarContext.count()); + yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); } - g_name.resize(0); + yyextra->name.resize(0); } if (*yytext==';' || *yytext=='=') { - g_type.resize(0); - g_name.resize(0); + yyextra->type.resize(0); + yyextra->name.resize(0); } else if (*yytext=='[') { - g_theCallContext.pushScope(g_name, g_type); + yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); } - g_args.resize(0); - g_parmType.resize(0); - g_parmName.resize(0); + yyextra->args.resize(0); + yyextra->parmType.resize(0); + yyextra->parmName.resize(0); } } /* @@ -2887,216 +1430,216 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" if (qstrcmp(yytext,"self")==0 || qstrcmp(yytext,"super")==0) { // TODO: get proper base class for "super" - g_theCallContext.setClass(getClass(g_curClassName)); - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); + yyextra->theCallContext.setClass(getClass(yyextra->curClassName)); + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } else { - generateClassOrGlobalLink(*g_code,yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); } - g_name.resize(0); + yyextra->name.resize(0); BEGIN(ObjCMemberCall2); } "[" { - g_code->codify(yytext); - g_theCallContext.pushScope(g_name, g_type); + yyextra->code->codify(yytext); + yyextra->theCallContext.pushScope(yyscanner,yyextra->name, yyextra->type); } {ID}":"? { - g_name+=yytext; - if (g_theCallContext.getClass()) + yyextra->name+=yytext; + if (yyextra->theCallContext.getClass()) { - //printf("Calling method %s\n",g_name.data()); - if (!generateClassMemberLink(*g_code,g_theCallContext.getClass(),g_name)) + //printf("Calling method %s\n",yyextra->name.data()); + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getClass(),yyextra->name)) { - g_code->codify(yytext); - addToSearchIndex(g_name); + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yyextra->name); } } else { - g_code->codify(yytext); - addToSearchIndex(g_name); + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yyextra->name); } - g_name.resize(0); + yyextra->name.resize(0); BEGIN(ObjCMemberCall3); } "]" { - g_theCallContext.popScope(g_name, g_type); - g_code->codify(yytext); + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->code->codify(yytext); BEGIN(Body); } */ "["|"{" { - saveObjCContext(); - g_currentCtx->format+=*yytext; + saveObjCContext(yyscanner); + yyextra->currentCtx->format+=*yytext; BEGIN(ObjCCall); //printf("open\n"); } "]"|"}" { - g_currentCtx->format+=*yytext; - restoreObjCContext(); + yyextra->currentCtx->format+=*yytext; + restoreObjCContext(yyscanner); BEGIN(ObjCMName); - if (g_currentCtx==0) + if (yyextra->currentCtx==0) { // end of call - writeObjCMethodCall(g_contextDict.find(0)); + writeObjCMethodCall(yyscanner,yyextra->contextDict.find(0)); BEGIN(Body); } //printf("close\n"); } "//".* { - g_currentCtx->format+=escapeComment(yytext); + yyextra->currentCtx->format+=escapeComment(yyscanner,yytext); } "/*" { - g_lastObjCCallContext = YY_START; - g_currentCtx->comment=yytext; + yyextra->lastObjCCallContext = YY_START; + yyextra->currentCtx->comment=yytext; BEGIN(ObjCCallComment); } "*/" { - g_currentCtx->comment+=yytext; - g_currentCtx->format+=escapeComment(g_currentCtx->comment); - BEGIN(g_lastObjCCallContext); + yyextra->currentCtx->comment+=yytext; + yyextra->currentCtx->format+=escapeComment(yyscanner,yyextra->currentCtx->comment); + BEGIN(yyextra->lastObjCCallContext); } -[^*\n]+ { g_currentCtx->comment+=yytext; } -"//"|"/*" { g_currentCtx->comment+=yytext; } -\n { g_currentCtx->comment+=*yytext; } -. { g_currentCtx->comment+=*yytext; } +[^*\n]+ { yyextra->currentCtx->comment+=yytext; } +"//"|"/*" { yyextra->currentCtx->comment+=yytext; } +\n { yyextra->currentCtx->comment+=*yytext; } +. { yyextra->currentCtx->comment+=*yytext; } {ID} { - g_currentCtx->format+=escapeObject(yytext); - if (g_braceCount==0) + yyextra->currentCtx->format+=escapeObject(yyscanner,yytext); + if (yyextra->braceCount==0) { - g_currentCtx->objectTypeOrName=yytext; - //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data()); + yyextra->currentCtx->objectTypeOrName=yytext; + //printf("new type=%s\n",yyextra->currentCtx->objectTypeOrName.data()); BEGIN(ObjCMName); } } {ID}/{BN}*"]" { - if (g_braceCount==0 && - g_currentCtx->methodName.isEmpty()) + if (yyextra->braceCount==0 && + yyextra->currentCtx->methodName.isEmpty()) { - g_currentCtx->methodName=yytext; - g_currentCtx->format+=escapeName(yytext); + yyextra->currentCtx->methodName=yytext; + yyextra->currentCtx->format+=escapeName(yyscanner,yytext); } else { - g_currentCtx->format+=escapeWord(yytext); + yyextra->currentCtx->format+=escapeWord(yyscanner,yytext); } } {ID}/{BN}*":" { - if (g_braceCount==0) + if (yyextra->braceCount==0) { - g_currentCtx->methodName+=yytext; - g_currentCtx->methodName+=":"; + yyextra->currentCtx->methodName+=yytext; + yyextra->currentCtx->methodName+=":"; } - g_currentCtx->format+=escapeName(yytext); + yyextra->currentCtx->format+=escapeName(yyscanner,yytext); } -[^\n\"$\\]* { g_currentCtx->format+=yytext; } -\\. { g_currentCtx->format+=yytext; } -"\"" { g_currentCtx->format+=yytext; - BEGIN(g_lastStringContext); +[^\n\"$\\]* { yyextra->currentCtx->format+=yytext; } +\\. { yyextra->currentCtx->format+=yytext; } +"\"" { yyextra->currentCtx->format+=yytext; + BEGIN(yyextra->lastStringContext); } -{CHARLIT} { g_currentCtx->format+=yytext; } -"@"?"\"" { g_currentCtx->format+=yytext; - g_lastStringContext=YY_START; +{CHARLIT} { yyextra->currentCtx->format+=yytext; } +"@"?"\"" { yyextra->currentCtx->format+=yytext; + yyextra->lastStringContext=YY_START; BEGIN(ObjCSkipStr); } -"$" { g_currentCtx->format+="$$"; } -"(" { g_currentCtx->format+=*yytext; g_braceCount++; } -")" { g_currentCtx->format+=*yytext; g_braceCount--; } +"$" { yyextra->currentCtx->format+="$$"; } +"(" { yyextra->currentCtx->format+=*yytext; yyextra->braceCount++; } +")" { yyextra->currentCtx->format+=*yytext; yyextra->braceCount--; } "@"/"\"" { // needed to prevent matching the global rule (for C#) - g_currentCtx->format+=yytext; + yyextra->currentCtx->format+=yytext; } -{ID} { g_currentCtx->format+=escapeWord(yytext); } -. { g_currentCtx->format+=*yytext; } -\n { g_currentCtx->format+=*yytext; } +{ID} { yyextra->currentCtx->format+=escapeWord(yyscanner,yytext); } +. { yyextra->currentCtx->format+=*yytext; } +\n { yyextra->currentCtx->format+=*yytext; } "]" { - g_theCallContext.popScope(g_name, g_type); - g_code->codify(yytext); + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->code->codify(yytext); // TODO: nested arrays like: a[b[0]->func()]->func() - g_name = g_saveName.copy(); - g_type = g_saveType.copy(); + yyextra->name = yyextra->saveName.copy(); + yyextra->type = yyextra->saveType.copy(); } [0-9]+ { - g_code->codify(yytext); + yyextra->code->codify(yytext); } [0-9]+[xX][0-9A-Fa-f]+ { - g_code->codify(yytext); + yyextra->code->codify(yytext); } {KEYWORD}/([^a-z_A-Z0-9]) { - //addParmType(); - //g_parmName=yytext; - if (skipLanguageSpecificKeyword(yytext)) REJECT; - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); + //addParmType(yyscanner); + //yyextra->parmName=yytext; + if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } {TYPEKW}/([^a-z_A-Z0-9]) { - addParmType(); - g_parmName=yytext; - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } {TYPEKWSL}/([^a-z_A-Z0-9]) { - if (g_lang!=SrcLangExt_Slice) + if (yyextra->lang!=SrcLangExt_Slice) { REJECT; } else { - addParmType(); - g_parmName=yytext; - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } } {FLOWKW}/([^a-z_A-Z0-9]) { - addParmType(); - g_parmName=yytext; - startFontClass("keywordflow"); - g_code->codify(yytext); - endFontClass(); + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordflow"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } {FLOWCONDITION}/([^a-z_A-Z0-9]) { - if (g_currentMemberDef && g_currentMemberDef->isFunction()) + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) { - g_currentMemberDef->incrementFlowKeyWordCount(); + yyextra->currentMemberDef->incrementFlowKeyWordCount(); } - addParmType(); - g_parmName=yytext; - startFontClass("keywordflow"); - g_code->codify(yytext); - endFontClass(); + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordflow"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } {ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* { if (isCastKeyword(yytext)) { REJECT; } - addParmType(); - g_parmName=yytext; - generateClassOrGlobalLink(*g_code,yytext,!g_insideBody); + addParmType(yyscanner); + yyextra->parmName=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); } ";" { // probably a cast, not a function call - g_code->codify(yytext); - g_inForEachExpression = FALSE; + yyextra->code->codify(yytext); + yyextra->inForEachExpression = FALSE; BEGIN( Body ); } , { - g_code->codify(yytext); - g_theVarContext.addVariable(g_parmType,g_parmName); - g_parmType.resize(0);g_parmName.resize(0); + yyextra->code->codify(yytext); + yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); } "{" { - if (g_bracketCount>0) + if (yyextra->bracketCount>0) { - g_code->codify(yytext); - g_skipInlineInitContext=YY_START; - g_curlyCount=0; + yyextra->code->codify(yytext); + yyextra->skipInlineInitContext=YY_START; + yyextra->curlyCount=0; BEGIN(InlineInit); } else @@ -3104,30 +1647,30 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" REJECT; } } -"{" { g_curlyCount++; - g_code->codify(yytext); +"{" { yyextra->curlyCount++; + yyextra->code->codify(yytext); } "}" { - g_code->codify(yytext); - if (--g_curlyCount<=0) + yyextra->code->codify(yytext); + if (--yyextra->curlyCount<=0) { - BEGIN(g_skipInlineInitContext); + BEGIN(yyextra->skipInlineInitContext); } } \n { - codifyLines(yytext); + codifyLines(yyscanner,yytext); } . { - g_code->codify(yytext); + yyextra->code->codify(yytext); } "(" { - g_parmType.resize(0);g_parmName.resize(0); - g_code->codify(yytext); - g_bracketCount++; - g_theCallContext.pushScope(g_name, g_type); - if (YY_START==FuncCall && !g_insideBody) + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + yyextra->code->codify(yytext); + yyextra->bracketCount++; + yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); + if (YY_START==FuncCall && !yyextra->insideBody) { - g_theVarContext.pushScope(); + yyextra->theVarContext.pushScope(); } } {OPERATOR} { // operator @@ -3137,34 +1680,34 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" qstrcmp(yytext,"%")) // typically a pointer or reference { // not a * or &, or C++/CLI's ^ or % - g_parmType.resize(0);g_parmName.resize(0); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); } - g_code->codify(yytext); + yyextra->code->codify(yytext); } ("*"{B}*)?")" { if (yytext[0]==')') // no a pointer cast { - //printf("addVariable(%s,%s)\n",g_parmType.data(),g_parmName.data()); - if (g_parmType.isEmpty()) + //printf("addVariable(%s,%s)\n",yyextra->parmType.data(),yyextra->parmName.data()); + if (yyextra->parmType.isEmpty()) { - g_parmType=g_parmName; - g_parmName.resize(0); + yyextra->parmType=yyextra->parmName; + yyextra->parmName.resize(0); } - g_theVarContext.addVariable(g_parmType,g_parmName); + yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } else { - g_parmType = g_parmName; - g_parmName.resize(0); - g_theVarContext.addVariable(g_parmType,g_parmName); + yyextra->parmType = yyextra->parmName; + yyextra->parmName.resize(0); + yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } - g_theCallContext.popScope(g_name, g_type); - 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) + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->inForEachExpression = FALSE; + //yyextra->theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b(). + yyextra->code->codify(yytext); + if (--yyextra->bracketCount<=0) { - if (g_name.isEmpty()) + if (yyextra->name.isEmpty()) { BEGIN( Body ); } @@ -3174,319 +1717,319 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } } } -[ \t\n]* { codifyLines(yytext); } +[ \t\n]* { codifyLines(yyscanner,yytext); } /* ")"[ \t\n]*[;:] { */ [;:] { - codifyLines(yytext); - g_bracketCount=0; - if (*yytext==';') g_searchingForBody=FALSE; - if (!g_type.isEmpty()) + codifyLines(yyscanner,yytext); + yyextra->bracketCount=0; + if (*yytext==';') yyextra->searchingForBody=FALSE; + if (!yyextra->type.isEmpty()) { - DBG_CTX((stderr,"add variable g_type=%s g_name=%s)\n",g_type.data(),g_name.data())); - g_theVarContext.addVariable(g_type,g_name); + DBG_CTX((stderr,"add variable yyextra->type=%s yyextra->name=%s)\n",yyextra->type.data(),yyextra->name.data())); + yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); } - g_parmType.resize(0);g_parmName.resize(0); - g_theCallContext.setScope(0); - if (*yytext==';' || g_insideBody) + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + yyextra->theCallContext.setScope(0); + if (*yytext==';' || yyextra->insideBody) { - if (!g_insideBody) + if (!yyextra->insideBody) { - g_theVarContext.popScope(); + yyextra->theVarContext.popScope(); } - g_name.resize(0);g_type.resize(0); + yyextra->name.resize(0);yyextra->type.resize(0); BEGIN( Body ); } else { - g_bracketCount=0; + yyextra->bracketCount=0; BEGIN( SkipInits ); } } ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } ("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" { - if (g_insideBody) + if (yyextra->insideBody) { - g_theVarContext.pushScope(); + yyextra->theVarContext.pushScope(); } - g_theVarContext.addVariable(g_parmType,g_parmName); - //g_theCallContext.popScope(g_name, g_type); - g_parmType.resize(0);g_parmName.resize(0); - int index = g_name.findRev("::"); - DBG_CTX((stderr,"g_name=%s\n",g_name.data())); + yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + //yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + int index = yyextra->name.findRev("::"); + DBG_CTX((stderr,"yyextra->name=%s\n",yyextra->name.data())); if (index!=-1) { - QCString scope = g_name.left(index); - if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::"); - const ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope); + QCString scope = yyextra->name.left(index); + if (!yyextra->classScope.isEmpty()) scope.prepend(yyextra->classScope+"::"); + const ClassDef *cd=getResolvedClass(Doxygen::globalScope,yyextra->sourceFileDef,scope); if (cd) { - setClassScope(cd->name()); - g_scopeStack.push(SCOPEBLOCK); + setClassScope(yyscanner,cd->name()); + yyextra->scopeStack.push(SCOPEBLOCK); DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n")); } else { - //setClassScope(g_realScope); - g_scopeStack.push(INNERBLOCK); + //setClassScope(yyscanner,yyextra->realScope); + yyextra->scopeStack.push(INNERBLOCK); DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); } } else { DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - g_scopeStack.push(INNERBLOCK); + yyextra->scopeStack.push(INNERBLOCK); } yytext[yyleng-1]='\0'; QCString cv(yytext); if (!cv.stripWhiteSpace().isEmpty()) { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } else // just whitespace { - codifyLines(yytext); + codifyLines(yyscanner,yytext); } - g_code->codify("{"); - if (g_searchingForBody) + yyextra->code->codify("{"); + if (yyextra->searchingForBody) { - g_searchingForBody=FALSE; - g_insideBody=TRUE; + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; } - if (g_insideBody) g_bodyCurlyCount++; - g_type.resize(0); g_name.resize(0); + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + yyextra->type.resize(0); yyextra->name.resize(0); BEGIN( Body ); } "try" { // function-try-block - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); - g_inFunctionTryBlock=TRUE; + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->inFunctionTryBlock=TRUE; } {ID} { - if (g_insideBody || !g_parmType.isEmpty()) + if (yyextra->insideBody || !yyextra->parmType.isEmpty()) { REJECT; } // could be K&R style definition - addParmType(); - g_parmName=yytext; - generateClassOrGlobalLink(*g_code,yytext,!g_insideBody); + addParmType(yyscanner); + yyextra->parmName=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); BEGIN(OldStyleArgs); } {ID} { - addParmType(); - g_parmName=yytext; - generateClassOrGlobalLink(*g_code,yytext,!g_insideBody); + addParmType(yyscanner); + yyextra->parmName=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); } [,;] { - g_code->codify(yytext); - g_theVarContext.addVariable(g_parmType,g_parmName); - if (*yytext==';') g_parmType.resize(0); - g_parmName.resize(0); + yyextra->code->codify(yytext); + yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + if (*yytext==';') yyextra->parmType.resize(0); + yyextra->parmName.resize(0); } "#" { - startFontClass("preprocessor"); - g_lastSkipCppContext = Body; - g_code->codify(yytext); + startFontClass(yyscanner,"preprocessor"); + yyextra->lastSkipCppContext = Body; + yyextra->code->codify(yytext); BEGIN( SkipCPP ); } . { unput(*yytext); - if (!g_insideBody) + if (!yyextra->insideBody) { - g_theVarContext.popScope(); + yyextra->theVarContext.popScope(); } - g_name.resize(0);g_args.resize(0); - g_parmType.resize(0);g_parmName.resize(0); + yyextra->name.resize(0);yyextra->args.resize(0); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); BEGIN( Body ); } ";" { - g_code->codify(yytext); - g_type.resize(0); g_name.resize(0); + yyextra->code->codify(yytext); + yyextra->type.resize(0); yyextra->name.resize(0); BEGIN( Body ); } "{" { - g_code->codify(yytext); - if (g_searchingForBody) + yyextra->code->codify(yytext); + if (yyextra->searchingForBody) { - g_searchingForBody=FALSE; - g_insideBody=TRUE; + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; } - if (g_insideBody) g_bodyCurlyCount++; - if (g_name.find("::")!=-1) + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + if (yyextra->name.find("::")!=-1) { DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n")); - g_scopeStack.push(SCOPEBLOCK); - setClassScope(g_realScope); + yyextra->scopeStack.push(SCOPEBLOCK); + setClassScope(yyscanner,yyextra->realScope); } else { DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - g_scopeStack.push(INNERBLOCK); + yyextra->scopeStack.push(INNERBLOCK); } - g_type.resize(0); g_name.resize(0); + yyextra->type.resize(0); yyextra->name.resize(0); BEGIN( Body ); } {ID} { - generateClassOrGlobalLink(*g_code,yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); } {ID}/"(" { - generateFunctionLink(*g_code,yytext); + generateFunctionLink(yyscanner,*yyextra->code,yytext); } {ID}/("."|"->") { - g_name=yytext; - generateClassOrGlobalLink(*g_code,yytext); + yyextra->name=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); BEGIN( MemberCall2 ); } ("("{B}*("*"{B}*)+{ID}*{B}*")"{B}*)/("."|"->") { - g_code->codify(yytext); + yyextra->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); + yyextra->name=((QCString)yytext).mid(s,e-s+1); BEGIN( MemberCall2 ); } {ID}/([ \t\n]*"(") { - if (!g_args.isEmpty()) - generateMemberLink(*g_code,g_args,yytext); + if (!yyextra->args.isEmpty()) + generateMemberLink(yyscanner,*yyextra->code,yyextra->args,yytext); else - generateClassOrGlobalLink(*g_code,yytext); - g_args.resize(0); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->args.resize(0); BEGIN( FuncCall ); } {ID}/([ \t\n]*("."|"->")) { - //g_code->codify(yytext); - g_name=yytext; - generateClassOrGlobalLink(*g_code,yytext); + //yyextra->code->codify(yytext); + yyextra->name=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); BEGIN( MemberCall2 ); } "->"|"." { if (yytext[0]=='-') // -> could be overloaded { - updateCallContextForSmartPointer(); + updateCallContextForSmartPointer(yyscanner); } - g_code->codify(yytext); - g_memCallContext = YY_START; + yyextra->code->codify(yytext); + yyextra->memCallContext = YY_START; BEGIN( MemberCall ); } "/*"("!"?)"*/" { - g_code->codify(yytext); - endFontClass(); - BEGIN( g_lastCContext ) ; + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; } "//"|"/*" { - g_code->codify(yytext); + yyextra->code->codify(yytext); } [^*/\n]+ { - g_code->codify(yytext); + yyextra->code->codify(yytext); } [ \t]*"*/" { - g_code->codify(yytext); - endFontClass(); - if (g_lastCContext==SkipCPP) + yyextra->code->codify(yytext); + endFontClass(yyscanner); + if (yyextra->lastCContext==SkipCPP) { - startFontClass("preprocessor"); + startFontClass(yyscanner,"preprocessor"); } - BEGIN( g_lastCContext ) ; + BEGIN( yyextra->lastCContext ) ; } [^\r\n]*"\\"[\r]?\n { // line continuation - codifyLines(yytext); + codifyLines(yyscanner,yytext); } [^\r\n]+ { - g_code->codify(yytext); + yyextra->code->codify(yytext); } \r \n { unput('\n'); - endFontClass(); - BEGIN( g_lastCContext ) ; + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; } . { - g_code->codify(yytext); + yyextra->code->codify(yytext); } "*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] { - g_yyLineNr+=QCString(yytext).contains('\n'); + yyextra->yyLineNr+=QCString(yytext).contains('\n'); } "*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? { - g_yyLineNr+=QCString(yytext).contains('\n'); - nextCodeLine(); - if (g_lastSpecialCContext==SkipCxxComment) + yyextra->yyLineNr+=QCString(yytext).contains('\n'); + nextCodeLine(yyscanner); + if (yyextra->lastSpecialCContext==SkipCxxComment) { // force end of C++ comment here - endFontClass(); - BEGIN( g_lastCContext ) ; + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; } else { - BEGIN(g_lastSpecialCContext); + BEGIN(yyextra->lastSpecialCContext); } } "*/" { - BEGIN(g_lastSpecialCContext); + BEGIN(yyextra->lastSpecialCContext); } [^*\n]+ "//"|"/*" -\n { g_yyLineNr++; } +\n { yyextra->yyLineNr++; } . [^a-z_A-Z0-9(\n] { - g_code->codify(yytext); - g_type.resize(0); - g_name.resize(0); - BEGIN(g_memCallContext); + yyextra->code->codify(yytext); + yyextra->type.resize(0); + yyextra->name.resize(0); + BEGIN(yyextra->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(); + yyextra->yyLineNr+=((QCString)yytext).contains('\n'); + nextCodeLine(yyscanner); } else { - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } if (YY_START==SkipCxxComment) { - endFontClass(); - BEGIN( g_lastCContext ) ; + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; } } \n/.*\n { - endFontClass(); - codifyLines(yytext); - BEGIN( g_lastSkipCppContext ) ; + endFontClass(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN( yyextra->lastSkipCppContext ) ; } <*>\n{B}*"//@"[{}].*\n { // remove one-line group marker if (Config_getBool(STRIP_CODE_COMMENTS)) { - g_yyLineNr+=2; - nextCodeLine(); + yyextra->yyLineNr+=2; + nextCodeLine(yyscanner); } else { - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } if (YY_START==SkipCxxComment) { - endFontClass(); - BEGIN( g_lastCContext ) ; + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; } } <*>\n{B}*"/*@"[{}] { // remove one-line group marker if (Config_getBool(STRIP_CODE_COMMENTS)) { - if (YY_START != RemoveSpecialCComment) g_lastSpecialCContext = YY_START; - g_yyLineNr++; + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + yyextra->yyLineNr++; BEGIN(RemoveSpecialCComment); } else @@ -3494,30 +2037,30 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" // check is to prevent getting stuck in skipping C++ comments if (YY_START != SkipComment && YY_START != SkipCxxComment) { - g_lastCContext = YY_START ; + yyextra->lastCContext = YY_START ; } - startFontClass("comment"); - codifyLines(yytext); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); BEGIN(SkipComment); } } <*>^{B}*"//@"[{}].*\n { // remove one-line group marker if (Config_getBool(STRIP_CODE_COMMENTS)) { - g_yyLineNr++; - nextCodeLine(); + yyextra->yyLineNr++; + nextCodeLine(yyscanner); } else { - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } } <*>^{B}*"/*@"[{}] { // remove multi-line group marker if (Config_getBool(STRIP_CODE_COMMENTS)) { - if (YY_START != RemoveSpecialCComment) g_lastSpecialCContext = YY_START; + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; BEGIN(RemoveSpecialCComment); } else @@ -3525,24 +2068,24 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" // check is to prevent getting stuck in skipping C++ comments if (YY_START != SkipComment && YY_START != SkipCxxComment) { - g_lastCContext = YY_START ; + yyextra->lastCContext = YY_START ; } - startFontClass("comment"); - g_code->codify(yytext); + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); BEGIN(SkipComment); } } <*>^{B}*"//"[!/][^\n]*\n { // remove special one-line comment if (Config_getBool(STRIP_CODE_COMMENTS)) { - g_yyLineNr++; - //nextCodeLine(); + yyextra->yyLineNr++; + //nextCodeLine(yyscanner); } else { - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } } <*>"//"[!/][^\n]*\n { // strip special one-line comment @@ -3550,26 +2093,26 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" if (Config_getBool(STRIP_CODE_COMMENTS)) { char c[2]; c[0]='\n'; c[1]=0; - codifyLines(c); + codifyLines(yyscanner,c); } else { - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); } } <*>"/*[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); + yyextra->forceTagReference=yytext; + int s=yyextra->forceTagReference.find(':'); + int e=yyextra->forceTagReference.findRev(']'); + yyextra->forceTagReference = yyextra->forceTagReference.mid(s+1,e-s-1); } <*>\n{B}*"/*"[!*]/[^/*] { if (Config_getBool(STRIP_CODE_COMMENTS)) { - if (YY_START != RemoveSpecialCComment) g_lastSpecialCContext = YY_START; - g_yyLineNr++; + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + yyextra->yyLineNr++; BEGIN(RemoveSpecialCComment); } else @@ -3577,17 +2120,17 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" // check is to prevent getting stuck in skipping C++ comments if (YY_START != SkipComment && YY_START != SkipCxxComment) { - g_lastCContext = YY_START ; + yyextra->lastCContext = YY_START ; } - startFontClass("comment"); - codifyLines(yytext); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); BEGIN(SkipComment); } } <*>^{B}*"/**"[*]+/[^/] { // special C "banner" comment block at a new line if (Config_getBool(JAVADOC_BANNER) && Config_getBool(STRIP_CODE_COMMENTS)) { - if (YY_START != RemoveSpecialCComment) g_lastSpecialCContext = YY_START; + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; BEGIN(RemoveSpecialCComment); } else @@ -3595,17 +2138,17 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" // check is to prevent getting stuck in skipping C++ comments if (YY_START != SkipComment && YY_START != SkipCxxComment) { - g_lastCContext = YY_START ; + yyextra->lastCContext = YY_START ; } - startFontClass("comment"); - g_code->codify(yytext); + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); BEGIN(SkipComment); } } <*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line if (Config_getBool(STRIP_CODE_COMMENTS)) { - if (YY_START != RemoveSpecialCComment) g_lastSpecialCContext = YY_START; + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; BEGIN(RemoveSpecialCComment); } else @@ -3613,10 +2156,10 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" // check is to prevent getting stuck in skipping C++ comments if (YY_START != SkipComment && YY_START != SkipCxxComment) { - g_lastCContext = YY_START ; + yyextra->lastCContext = YY_START ; } - startFontClass("comment"); - g_code->codify(yytext); + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); BEGIN(SkipComment); } } @@ -3624,7 +2167,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" if (YY_START==SkipString) REJECT; if (Config_getBool(STRIP_CODE_COMMENTS)) { - if (YY_START != RemoveSpecialCComment) g_lastSpecialCContext = YY_START; + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; BEGIN(RemoveSpecialCComment); } else @@ -3632,10 +2175,10 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" // check is to prevent getting stuck in skipping C++ comments if (YY_START != SkipComment && YY_START != SkipCxxComment) { - g_lastCContext = YY_START ; + yyextra->lastCContext = YY_START ; } - startFontClass("comment"); - g_code->codify(yytext); + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); BEGIN(SkipComment); } } @@ -3643,134 +2186,1724 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" if (YY_START==SkipString) REJECT; if (!Config_getBool(STRIP_CODE_COMMENTS)) { - startFontClass("comment"); - g_code->codify(yytext); - endFontClass(); + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } } [^\*\n]+ { - g_code->codify(yytext); + yyextra->code->codify(yytext); } <*>"/*" { - startFontClass("comment"); - g_code->codify(yytext); + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); // check is to prevent getting stuck in skipping C++ comments if (YY_START != SkipComment && YY_START != SkipCxxComment) { - g_lastCContext = YY_START ; + yyextra->lastCContext = YY_START ; } BEGIN( SkipComment ) ; } <*>@\" { // C# verbatim string - startFontClass("stringliteral"); - g_code->codify(yytext); - g_lastVerbStringContext=YY_START; + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext); + yyextra->lastVerbStringContext=YY_START; BEGIN(SkipVerbString); } <*>"//" { - startFontClass("comment"); - g_code->codify(yytext); - g_lastCContext = YY_START ; + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + yyextra->lastCContext = YY_START ; BEGIN( SkipCxxComment ) ; } <*>"("|"[" { - g_code->codify(yytext); - g_theCallContext.pushScope(g_name, g_type); + yyextra->code->codify(yytext); + yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); } <*>")"|"]" { - g_code->codify(yytext); - g_theCallContext.popScope(g_name, g_type); + yyextra->code->codify(yytext); + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); } <*>\n { - g_yyColNr++; - codifyLines(yytext); + yyextra->yyColNr++; + codifyLines(yyscanner,yytext); } <*>. { - g_yyColNr++; - g_code->codify(yytext); + yyextra->yyColNr++; + yyextra->code->codify(yytext); } /* <*>([ \t\n]*"\n"){2,} { // combine multiple blank lines //QCString sepLine=yytext; - //g_code->codify("\n\n"); - //g_yyLineNr+=sepLine.contains('\n'); + //yyextra->code->codify("\n\n"); + //yyextra->yyLineNr+=sepLine.contains('\n'); //char sepLine[3]="\n\n"; - codifyLines(yytext); + codifyLines(yyscanner,yytext); } */ -%% +%% + +/*@ ---------------------------------------------------------------------------- + */ + +void VariableContext::addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //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():"")); + Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast(); + const ClassDef *varType; + int i=0; + if ( + (varType=yyextra->codeClassSDict->find(ltype)) || // look for class definitions inside the code block + (varType=getResolvedClass(yyextra->currentDefinition,yyextra->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 ( !typeName.isEmpty() && + ( // look for class definitions inside the code block + (varType=yyextra->codeClassSDict->find(typeName)) || + // otherwise look for global class definitions + (varType=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,typeName,0,0,TRUE,TRUE)) + ) && // and it must be a template + !varType->templateArguments().empty()) + { + 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(yyscanner,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 sli(m_scopes); + Scope *scope; + QCString key = name; + // search from inner to outer scope + for (sli.toLast();(scope=sli.current());--sli) + { + result = scope->find(key); + if (result) + { + DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); + return result; + } + } + // nothing found -> also try the global scope + result=m_globalScope.find(name); + DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); + return result; +} + +const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8; + +//------------------------------------------------------------------- + +/*! add class/namespace name s to the scope */ +static void pushScope(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->classScopeLengthStack.push(new int(yyextra->classScope.length())); + if (yyextra->classScope.isEmpty() || leftScopeMatch(s,yyextra->classScope)) + { + yyextra->classScope = s; + } + else + { + yyextra->classScope += "::"; + yyextra->classScope += s; + } + //printf("pushScope(%s) result: '%s'\n",s,yyextra->classScope.data()); +} + + +/*! remove the top class/namespace name from the scope */ +static void popScope(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->classScopeLengthStack.isEmpty()) + { + int *pLength = yyextra->classScopeLengthStack.pop(); + yyextra->classScope.truncate(*pLength); + delete pLength; + } + else + { + //err("Too many end of scopes found!\n"); + } + //printf("popScope() result: '%s'\n",yyextra->classScope.data()); +} + +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (Doxygen::searchIndex) + { + if (yyextra->searchCtx) + { + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); + } + else + { + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); + } + } +} + +static void addToSearchIndex(yyscan_t yyscanner,const char *text) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (Doxygen::searchIndex) + { + yyextra->code->addWord(text,FALSE); + } +} + +static void setClassScope(yyscan_t yyscanner,const QCString &name) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //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 (!yyextra->classScopeLengthStack.isEmpty()) + { + popScope(yyscanner); + } + yyextra->classScope.resize(0); + int i; + while ((i=n.find("::"))!=-1) + { + pushScope(yyscanner,n.left(i)); + n = n.mid(i+2); + } + pushScope(yyscanner,n); + //printf("--->New class scope '%s'\n",yyextra->classScope.data()); +} + +/*! start a new line of code, inserting a line number if yyextra->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(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //if (yyextra->currentFontClass) { yyextra->code->endFontClass(yyscanner); } + if (yyextra->sourceFileDef && yyextra->lineNumbers) + { + //QCString lineNumber,lineAnchor; + //lineNumber.sprintf("%05d",yyextra->yyLineNr); + //lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + //printf("%s:startCodeLine(%d)=%p\n",yyextra->sourceFileDef->name().data(),yyextra->yyLineNr,d); + if (!yyextra->includeCodeFragment && d) + { + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + yyextra->insideBody = FALSE; + yyextra->searchingForBody = TRUE; + yyextra->realScope = d->name(); + //yyextra->classScope = ""; + yyextra->type.resize(0); + yyextra->name.resize(0); + yyextra->args.resize(0); + yyextra->parmType.resize(0); + yyextra->parmName.resize(0); + //printf("Real scope: '%s'\n",yyextra->realScope.data()); + yyextra->bodyCurlyCount = 0; + QCString lineAnchor; + lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + if (yyextra->currentMemberDef) + { + yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); + } + else if (d->isLinkableInProject()) + { + yyextra->code->writeLineNumber(d->getReference(), + d->getOutputFileBase(), + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); + } + } + else + { + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); + } + } + DBG_CTX((stderr,"startCodeLine(%d)\n",yyextra->yyLineNr)); + yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers); + if (yyextra->currentFontClass) + { + yyextra->code->startFontClass(yyextra->currentFontClass); + } +} + + + +static void endCodeLine(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + DBG_CTX((stderr,"endCodeLine(%d)\n",yyextra->yyLineNr)); + endFontClass(yyscanner); + yyextra->code->endCodeLine(); +} + +static void nextCodeLine(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char * fc = yyextra->currentFontClass; + endCodeLine(yyscanner); + if (yyextra->yyLineNrinputLines) + { + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); + } +} + +/*! write a code fragment 'text' that may span multiple lines, inserting + * line numbers for each line. + */ +static void codifyLines(yyscan_t yyscanner,const char *text) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,text); + const char *p=text,*sp=p; + char c; + bool done=FALSE; + while (!done) + { + sp=p; + while ((c=*p++) && c!='\n') { yyextra->yyColNr++; } + if (c=='\n') + { + yyextra->yyLineNr++; + yyextra->yyColNr=1; + //*(p-1)='\0'; + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); + nextCodeLine(yyscanner); + } + else + { + yyextra->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(yyscan_t yyscanner,CodeOutputInterface &ol, + const Definition *d, + const char *text) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + TooltipManager::instance()->addTooltip(d); + QCString ref = d->getReference(); + QCString file = d->getOutputFileBase(); + QCString anchor = d->anchor(); + QCString tooltip; + if (!sourceTooltips) // fall back to simple "title" tooltips + { + tooltip = d->briefDescriptionAsTooltip(); + } + bool done=FALSE; + char *p=(char *)text; + while (!done) + { + char *sp=p; + char c; + while ((c=*p++) && c!='\n') { } + if (c=='\n') + { + yyextra->yyLineNr++; + *(p-1)='\0'; + //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); + ol.writeCodeLink(ref,file,anchor,sp,tooltip); + nextCodeLine(yyscanner); + } + else + { + //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); + ol.writeCodeLink(ref,file,anchor,sp,tooltip); + done=TRUE; + } + } +} + +static void addType(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->name=="const") { yyextra->name.resize(0); return; } + if (!yyextra->type.isEmpty()) yyextra->type += ' ' ; + yyextra->type += yyextra->name ; + yyextra->name.resize(0) ; + if (!yyextra->type.isEmpty()) yyextra->type += ' ' ; + yyextra->type += yyextra->args ; + yyextra->args.resize(0) ; +} + +static void addParmType(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->parmName=="const") { yyextra->parmName.resize(0); return; } + if (!yyextra->parmType.isEmpty()) yyextra->parmType += ' ' ; + yyextra->parmType += yyextra->parmName ; + yyextra->parmName.resize(0) ; +} + +static void addUsingDirective(yyscan_t yyscanner,const char *name) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->sourceFileDef && name) + { + NamespaceDef *nd = Doxygen::namespaceSDict->find(name); + if (nd) + { + yyextra->sourceFileDef->addUsingDirective(nd); + } + } +} + +static void setParameterList(yyscan_t yyscanner,const MemberDef *md) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->classScope = md->getClassDef() ? md->getClassDef()->name().data() : ""; + for (const Argument &a : md->argumentList()) + { + yyextra->parmName = a.name; + yyextra->parmType = a.type; + int i = yyextra->parmType.find('*'); + if (i!=-1) yyextra->parmType = yyextra->parmType.left(i); + i = yyextra->parmType.find('&'); + if (i!=-1) yyextra->parmType = yyextra->parmType.left(i); + yyextra->parmType.stripPrefix("const "); + yyextra->parmType=yyextra->parmType.stripWhiteSpace(); + yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + } +} + +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + int pos=0; + QCString type = s; + QCString className; + QCString templSpec; + while (extractClassNameFromType(type,pos,className,templSpec)!=-1) + { + QCString clName=className+templSpec; + const ClassDef *cd=0; + if (!yyextra->classScope.isEmpty()) + { + cd=getResolvedClass(d,yyextra->sourceFileDef,yyextra->classScope+"::"+clName); + } + if (cd==0) + { + cd=getResolvedClass(d,yyextra->sourceFileDef,clName); + } + //printf("stripClass trying '%s' = %p\n",clName.data(),cd); + if (cd) + { + return cd; + } + } + + return 0; +} + +static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) +{ + if (name.isEmpty()) return 0; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + DBG_CTX((stderr,"setCallContextForVar(%s) yyextra->classScope=%s\n",name.data(),yyextra->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()); + yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + return md; + } + } + else // check namespace as well + { + const 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()); + yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + return md; + } + } + } + } + + MemberName *mn; + ClassDef *mcd = yyextra->theVarContext.findVariable(name); + if (mcd) // local variable + { + DBG_CTX((stderr,"local variable?\n")); + if (mcd!=VariableContext::dummyContext) + { + DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcd->name().data())); + yyextra->theCallContext.setScope(mcd); + } + } + else + { + DBG_CTX((stderr,"class member? scope=%s\n",yyextra->classScope.data())); + // look for a class member + mcd = getClass(yyextra->classScope); + if (mcd) + { + DBG_CTX((stderr,"Inside class %s\n",mcd->name().data())); + MemberDef *md=mcd->getMemberByName(name); + if (md) + { + DBG_CTX((stderr,"Found member %s\n",md->name().data())); + if (yyextra->scopeStack.top()!=CLASSBLOCK) + { + DBG_CTX((stderr,"class member '%s' mcd=%s\n",name.data(),mcd->name().data())); + yyextra->theCallContext.setScope(stripClassName(yyscanner,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()==yyextra->sourceFileDef) + { + yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + return md; + } + return 0; + } + else if (mn->count()>1) // global defined more than once + { + MemberNameIterator it(*mn); + MemberDef *md; + for (;(md=it.current());++it) + { + //printf("mn=%p md=%p md->getBodyDef()=%p yyextra->sourceFileDef=%p\n", + // mn,md, + // md->getBodyDef(),yyextra->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()==yyextra->sourceFileDef) && + (yyextra->forceTagReference.isEmpty() || yyextra->forceTagReference==md->getReference()) + ) + { + yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + //printf("returning member %s in source file %s\n",md->name().data(),yyextra->sourceFileDef->name().data()); + return md; + } + } + return 0; + } + } + return 0; +} + +static void updateCallContextForSmartPointer(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const Definition *d = yyextra->theCallContext.getScope(); + //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : ""); + MemberDef *md; + if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast(d))->isSmartPointer())) + { + const ClassDef *ncd = stripClassName(yyscanner,md->typeString(),md->getOuterScope()); + if (ncd) + { + yyextra->theCallContext.setScope(ncd); + //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data()); + } + } +} + +static bool getLinkInScope(yyscan_t yyscanner, + const QCString &c, // scope + const QCString &m, // member + const char *memberText, // exact text + CodeOutputInterface &ol, + const char *text, + bool varOnly + ) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const MemberDef *md = 0; + const ClassDef *cd = 0; + const FileDef *fd = 0; + const NamespaceDef *nd = 0; + const GroupDef *gd = 0; + DBG_CTX((stderr,"getLinkInScope: trying '%s'::'%s' varOnly=%d\n",c.data(),m.data(),varOnly)); + if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,yyextra->sourceFileDef,FALSE,yyextra->forceTagReference) && + (!varOnly || md->isVariable())) + { + if (md->isLinkable()) + { + //printf("found it %s!\n",md->qualifiedName().data()); + if (yyextra->exampleBlock) + { + QCString anchor; + anchor.sprintf("a%d",yyextra->anchorCount); + //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),yyextra->exampleName.data(), + // yyextra->exampleFile.data()); + if (const_cast(md)->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) + { + ol.writeCodeAnchor(anchor); + yyextra->anchorCount++; + } + } + + const Definition *d = md->getOuterScope()==Doxygen::globalScope ? + md->resolveAlias()->getFileDef() : md->getOuterScope(); + if (md->resolveAlias()->getGroupDef()) d = md->resolveAlias()->getGroupDef(); + if (d && d->isLinkable()) + { + yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p yyextra->insideBody=%d\n", + // yyextra->currentDefinition,yyextra->currentMemberDef,yyextra->insideBody); + + if (yyextra->currentDefinition && yyextra->currentMemberDef && + md!=yyextra->currentMemberDef && yyextra->insideBody && yyextra->collectXRefs) + { + addDocCrossReference(yyextra->currentMemberDef,const_cast(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()); + + writeMultiLineCodeLink(yyscanner,ol,md, text ? text : memberText); + addToSearchIndex(yyscanner,text ? text : memberText); + return TRUE; + } + } + else // found member, but it is not linkable, so make sure content inside is not assigned + // to the previous member, see bug762760 + { + DBG_CTX((stderr,"unlinkable member %s\n",md->name().data())); + yyextra->currentMemberDef = 0; + } + } + return FALSE; +} + +static bool getLink(yyscan_t yyscanner, + const char *className, + const char *memberName, + CodeOutputInterface &ol, + const char *text, + bool varOnly) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("getLink(%s,%s) yyextra->curClassName=%s\n",className,memberName,yyextra->curClassName.data()); + QCString m=removeRedundantWhiteSpace(memberName); + QCString c=className; + if (!getLinkInScope(yyscanner,c,m,memberName,ol,text,varOnly)) + { + if (!yyextra->curClassName.isEmpty()) + { + if (!c.isEmpty()) c.prepend("::"); + c.prepend(yyextra->curClassName); + return getLinkInScope(yyscanner,c,m,memberName,ol,text,varOnly); + } + return FALSE; + } + return TRUE; +} + +static void generateClassOrGlobalLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + const char *clName, + bool typeOnly, + bool varOnly) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + int i=0; + if (*clName=='~') // correct for matching negated values i.s.o. destructors. + { + yyextra->code->codify("~"); + clName++; + } + QCString className=clName; + if (className.isEmpty()) return; + if (yyextra->insideProtocolList) // for Obj-C + { + className+="-p"; + } + if (yyextra->lang==SrcLangExt_PHP) + { + className = substitute(className,"\\","::"); // for PHP namespaces + } + else if (yyextra->lang==SrcLangExt_CSharp || yyextra->lang==SrcLangExt_Java) + { + className = substitute(className,".","::"); // for PHP namespaces + } + const ClassDef *cd=0,*lcd=0; + const MemberDef *md=0; + bool isLocal=FALSE; + + //printf("generateClassOrGlobalLink(className=%s)\n",className.data()); + if (!yyextra->prefixed_with_this_keyword || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable + { + Definition *d = yyextra->currentDefinition; + //printf("d=%s yyextra->sourceFileDef=%s\n",d?d->name().data():"",yyextra->sourceFileDef?yyextra->sourceFileDef->name().data():""); + cd = getResolvedClass(d,yyextra->sourceFileDef,className,&md); + DBG_CTX((stderr,"non-local variable name=%s context=%d cd=%s md=%s!\n", + className.data(),yyextra->theVarContext.count(),cd?cd->name().data():"", + md?md->name().data():"")); + if (cd==0 && md==0 && (i=className.find('<'))!=-1) + { + QCString bareName = className.left(i); //stripTemplateSpecifiersFromScope(className); + DBG_CTX((stderr,"bareName=%s\n",bareName.data())); + if (bareName!=className) + { + cd=getResolvedClass(d,yyextra->sourceFileDef,bareName,&md); // try unspecialized version + } + } + const NamespaceDef *nd = getResolvedNamespace(className); + if (nd && nd->isLinkable()) + { + yyextra->theCallContext.setScope(nd); + addToSearchIndex(yyscanner,className); + writeMultiLineCodeLink(yyscanner,*yyextra->code,nd,clName); + return; + } + //printf("md=%s\n",md?md->name().data():""); + DBG_CTX((stderr,"is found as a type cd=%s nd=%s\n", + cd?cd->name().data():"", + nd?nd->name().data():"")); + if (cd==0 && md==0) // also see if it is variable or enum or enum value + { + if (getLink(yyscanner,yyextra->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()); + yyextra->theCallContext.setScope(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(yyscanner,yyextra->classScope,clName,ol,clName)) + //{ + //return; + //} + } + isLocal=TRUE; + DBG_CTX((stderr,"is a local variable cd=%p!\n",cd)); + } + yyextra->prefixed_with_this_keyword = FALSE; // discard the "this" prefix for the next calls + + if (cd && cd->isLinkable()) // is it a linkable class + { + DBG_CTX((stderr,"is linkable class %s\n",clName)); + if (yyextra->exampleBlock) + { + QCString anchor; + anchor.sprintf("_a%d",yyextra->anchorCount); + //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),yyextra->exampleName.data(), + // yyextra->exampleFile.data()); + if (const_cast(cd)->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) + { + ol.writeCodeAnchor(anchor); + yyextra->anchorCount++; + } + } + writeMultiLineCodeLink(yyscanner,ol,cd,clName); + addToSearchIndex(yyscanner,className); + yyextra->theCallContext.setScope(cd); + if (md) + { + const Definition *d = md->getOuterScope()==Doxygen::globalScope ? + md->getFileDef() : md->getOuterScope(); + if (md->getGroupDef()) d = md->getGroupDef(); + if (d && d->isLinkable() && md->isLinkable() && + yyextra->currentMemberDef && yyextra->collectXRefs) + { + addDocCrossReference(yyextra->currentMemberDef,const_cast(md)); + } + } + } + else // not a class, maybe a global member + { + DBG_CTX((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(yyscanner,clName); + //printf("setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",clName,md,yyextra->currentDefinition); + if (md && yyextra->currentDefinition) + { + DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n", + md->name().data(),yyextra->currentDefinition->name().data(), + isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md), + md->getOuterScope()->name().data())); + } + + if (md && yyextra->currentDefinition && + isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md)==-1) + { + md=0; // variable not accessible + } + } + if (md && (!varOnly || md->isVariable())) + { + DBG_CTX((stderr,"is a global md=%p yyextra->currentDefinition=%s linkable=%d\n",md,yyextra->currentDefinition?yyextra->currentDefinition->name().data():"",md->isLinkable())); + if (md->isLinkable()) + { + QCString text; + if (!yyextra->forceTagReference.isEmpty()) // explicit reference to symbol in tag file + { + text=yyextra->forceTagReference; + if (text.right(4)==".tag") // strip .tag if present + { + text=text.left(text.length()-4); + } + text+=getLanguageSpecificSeparator(md->getLanguage()); + text+=clName; + const_cast(md)->setName(text); + const_cast(md)->setLocalName(text); + } + else // normal reference + { + text=clName; + } + writeMultiLineCodeLink(yyscanner,ol,md,text); + addToSearchIndex(yyscanner,clName); + if (yyextra->currentMemberDef && yyextra->collectXRefs) + { + addDocCrossReference(yyextra->currentMemberDef,const_cast(md)); + } + return; + } + } + } + + // nothing found, just write out the word + DBG_CTX((stderr,"not found!\n")); + codifyLines(yyscanner,clName); + addToSearchIndex(yyscanner,clName); + } +} + +static bool generateClassMemberLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + MemberDef *xmd, + const char *memName) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + // 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 (yyextra->exampleBlock) + { + QCString anchor; + anchor.sprintf("a%d",yyextra->anchorCount); + //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),yyextra->exampleName.data(), + // yyextra->exampleFile.data()); + if (xmd->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) + { + ol.writeCodeAnchor(anchor); + yyextra->anchorCount++; + } + } + + const ClassDef *typeClass = stripClassName(yyscanner,removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); + DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass)); + yyextra->theCallContext.setScope(typeClass); + + const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? + xmd->getFileDef() : xmd->getOuterScope(); + if (xmd->getGroupDef()) xd = xmd->getGroupDef(); + if (xd && xd->isLinkable()) + { + + //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p xmd=%p yyextra->insideBody=%d\n",yyextra->currentDefinition,yyextra->currentMemberDef,xmd,yyextra->insideBody); + + if (xmd->templateMaster()) xmd = xmd->templateMaster(); + + if (xmd->isLinkable()) + { + // add usage reference + if (yyextra->currentDefinition && yyextra->currentMemberDef && + /*xmd!=yyextra->currentMemberDef &&*/ yyextra->insideBody && yyextra->collectXRefs) + { + addDocCrossReference(yyextra->currentMemberDef,xmd); + } + + // write the actual link + writeMultiLineCodeLink(yyscanner,ol,xmd,memName); + addToSearchIndex(yyscanner,memName); + return TRUE; + } + } + + return FALSE; +} + +static bool generateClassMemberLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + const Definition *def, + const char *memName) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (def && def->definitionType()==Definition::TypeClass) + { + const ClassDef *cd = dynamic_cast(def); + MemberDef *xmd = cd->getMemberByName(memName); + //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd); + if (xmd) + { + return generateClassMemberLink(yyscanner,ol,xmd,memName); + } + else + { + Definition *innerDef = cd->findInnerCompound(memName); + if (innerDef) + { + yyextra->theCallContext.setScope(innerDef); + addToSearchIndex(yyscanner,memName); + writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); + return TRUE; + } + } + } + else if (def && def->definitionType()==Definition::TypeNamespace) + { + const NamespaceDef *nd = dynamic_cast(def); + //printf("Looking for %s inside namespace %s\n",memName,nd->name().data()); + Definition *innerDef = nd->findInnerCompound(memName); + if (innerDef) + { + yyextra->theCallContext.setScope(innerDef); + addToSearchIndex(yyscanner,memName); + writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); + return TRUE; + } + } + return FALSE; +} + +static void generateMemberLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + const QCString &varName, + const char *memName) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n", + // varName.data(),memName,yyextra->classScope.data()); + + if (varName.isEmpty()) return; + + // look for the variable in the current context + const ClassDef *vcd = yyextra->theVarContext.findVariable(varName); + if (vcd) + { + if (vcd!=VariableContext::dummyContext) + { + //printf("Class found!\n"); + if (getLink(yyscanner,vcd->name(),memName,ol)) + { + //printf("Found result!\n"); + return; + } + if (vcd->baseClasses()) + { + BaseClassListIterator bcli(*vcd->baseClasses()); + for ( ; bcli.current() ; ++bcli) + { + if (getLink(yyscanner,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(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->classScope); + if (vcd && vcd->isLinkable()) + { + //printf("Found class %s for variable '%s'\n",yyextra->classScope.data(),varName.data()); + MemberName *vmn=Doxygen::memberNameSDict->find(varName); + if (vmn==0) + { + int vi; + QCString vn=varName; + 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); + const MemberDef *vmd; + for (;(vmd=vmni.current());++vmni) + { + if (/*(vmd->isVariable() || vmd->isFunction()) && */ + vmd->getClassDef()==jcd) + { + //printf("Found variable type=%s\n",vmd->typeString()); + const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); + if (mcd && mcd->isLinkable()) + { + if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; + } + } + } + } + } + } + if (vmn) + { + //printf("There is a variable with name '%s'\n",varName); + MemberNameIterator vmni(*vmn); + const MemberDef *vmd; + for (;(vmd=vmni.current());++vmni) + { + if (/*(vmd->isVariable() || vmd->isFunction()) && */ + vmd->getClassDef()==vcd) + { + //printf("Found variable type=%s\n",vmd->typeString()); + const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); + if (mcd && mcd->isLinkable()) + { + if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; + } + } + } + } + } + } + // nothing found -> write result as is + codifyLines(yyscanner,memName); + addToSearchIndex(yyscanner,memName); + return; +} + +static void generatePHPVariableLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *varName) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString name = varName+7; // strip $this-> + name.prepend("$"); + //printf("generatePHPVariableLink(%s) name=%s scope=%s\n",varName,name.data(),yyextra->classScope.data()); + if (!getLink(yyscanner,yyextra->classScope,name,ol,varName)) + { + codifyLines(yyscanner,varName); + } +} + +static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *funcName) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //CodeClassDef *ccd=0; + ClassDef *ccd=0; + QCString locScope=yyextra->classScope; + QCString locFunc=removeRedundantWhiteSpace(funcName); + if (yyextra->lang==SrcLangExt_PHP && locFunc.startsWith("self::")) locFunc=locFunc.mid(4); + QCString funcScope; + QCString funcWithScope=locFunc; + QCString funcWithFullScope=locFunc; + QCString fullScope=locScope; + DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data())); + int len=2; + int i=locFunc.findRev("::"); + if (yyextra->currentMemberDef && yyextra->currentMemberDef->resolveAlias()->getClassDef() && + funcName==yyextra->currentMemberDef->localName() && + yyextra->currentMemberDef->getDefLine()==yyextra->yyLineNr && + generateClassMemberLink(yyscanner,ol,yyextra->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 + // yyextra->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=yyextra->codeClassSDict->find(fullScope))) + { + //printf("using classScope %s\n",yyextra->classScope.data()); + if (ccd->baseClasses()) + { + BaseClassListIterator bcli(*ccd->baseClasses()); + for ( ; bcli.current() ; ++bcli) + { + if (getLink(yyscanner,bcli.current()->classDef->name(),locFunc,ol,funcName)) + { + goto exit; + } + } + } + } + if (!locScope.isEmpty() && fullScope!=locScope && (ccd=yyextra->codeClassSDict->find(locScope))) + { + //printf("using classScope %s\n",yyextra->classScope.data()); + if (ccd->baseClasses()) + { + BaseClassListIterator bcli(*ccd->baseClasses()); + for ( ; bcli.current() ; ++bcli) + { + if (getLink(yyscanner,bcli.current()->classDef->name(),funcWithScope,ol,funcName)) + { + goto exit; + } + } + } + } + if (!getLink(yyscanner,locScope,funcWithScope,ol,funcName)) + { + generateClassOrGlobalLink(yyscanner,ol,funcName); + } +exit: + yyextra->forceTagReference.resize(0); + return; +} + +/*! counts the number of lines in the input */ +static int countLines(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=yyextra->inputString; + char c; + int count=1; + while ((c=*p)) + { + p++ ; + if (c=='\n') count++; + } + if (p>yyextra->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++, + yyextra->needsTermination=TRUE; + } + return count; +} + +static void endFontClass(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentFontClass) + { + yyextra->code->endFontClass(); + yyextra->currentFontClass=0; + } +} + +static void startFontClass(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; +} + +//---------------------------------------------------------------------------- + +// recursively writes a linkified Objective-C method call +static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) +{ + if (ctx==0) return; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + 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 = yyextra->theVarContext.findVariable(ctx->objectTypeOrName); + if (cd==0) // not a local variable + { + if (ctx->objectTypeOrName=="self") + { + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ctx->objectType = dynamic_cast(yyextra->currentDefinition); + } + } + else + { + ctx->objectType = getResolvedClass( + yyextra->currentDefinition, + yyextra->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():""); + } + else if (ctx->method==0) // search for class variable with the same name + { + //printf(" no\n"); + //printf("yyextra->currentDefinition=%p\n",yyextra->currentDefinition); + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ctx->objectVar = (dynamic_cast(yyextra->currentDefinition))->getMemberByName(ctx->objectTypeOrName); + //printf(" ctx->objectVar=%p\n",ctx->objectVar); + if (ctx->objectVar) + { + ctx->objectType = stripClassName(yyscanner,ctx->objectVar->typeString(),yyextra->currentDefinition); + //printf(" ctx->objectType=%p\n",ctx->objectType); + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + 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->methodName.isEmpty()) + { + 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 $ + { + yyextra->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 = yyextra->nameDict.find(refId); + if (pName) + { + if (ctx->method && ctx->method->isLinkable()) + { + writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->method,pName->data()); + if (yyextra->currentMemberDef && yyextra->collectXRefs) + { + addDocCrossReference(yyextra->currentMemberDef,const_cast(ctx->method)); + } + } + else + { + codifyLines(yyscanner,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 = yyextra->objectDict.find(refId); + if (pObject) + { + if (*pObject=="self") + { + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ctx->objectType = dynamic_cast(yyextra->currentDefinition); + if (ctx->objectType->categoryOf()) + { + ctx->objectType = ctx->objectType->categoryOf(); + } + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + } + } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,pObject->data()); + endFontClass(yyscanner); + } + else if (*pObject=="super") + { + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ClassDef *cd = dynamic_cast(yyextra->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->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + } + } + } + } + } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,pObject->data()); + endFontClass(yyscanner); + } + else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable + { + writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->objectVar,pObject->data()); + if (yyextra->currentMemberDef && yyextra->collectXRefs) + { + addDocCrossReference(yyextra->currentMemberDef,const_cast(ctx->objectVar)); + } + } + else if (ctx->objectType && + ctx->objectType!=VariableContext::dummyContext && + ctx->objectType->isLinkable() + ) // object is class name + { + const ClassDef *cd = ctx->objectType; + writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,pObject->data()); + } + else // object still needs to be resolved + { + const ClassDef *cd = getResolvedClass(yyextra->currentDefinition, + yyextra->sourceFileDef, *pObject); + if (cd && cd->isLinkable()) + { + if (ctx->objectType==0) ctx->objectType=cd; + writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,pObject->data()); + } + else + { + codifyLines(yyscanner,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 = yyextra->contextDict.find(refId); + if (ictx) // recurse into nested call + { + writeObjCMethodCall(yyscanner,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(yyscanner,ictx->method->typeString(),yyextra->currentDefinition); + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + 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 = yyextra->wordDict.find(refId); + if (pWord) + { + codifyLines(yyscanner,pWord->data()); + } + } + else if (nc=='d') // comment block + { + nc=*p++; + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + QCString *pComment = yyextra->commentDict.find(refId); + if (pComment) + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,pComment->data()); + endFontClass(yyscanner); + } + } + else // illegal marker + { + ASSERT(!"invalid escape sequence"); + } + } + } + else // normal non-marker character + { + char s[2]; + s[0]=c;s[1]=0; + codifyLines(yyscanner,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 yyextra->nameDict +static QCString escapeName(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString result; + result.sprintf("$n%d",yyextra->currentNameId); + yyextra->nameDict.insert(yyextra->currentNameId,new QCString(s)); + yyextra->currentNameId++; + return result; +} + +static QCString escapeObject(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString result; + result.sprintf("$o%d",yyextra->currentObjId); + yyextra->objectDict.insert(yyextra->currentObjId,new QCString(s)); + yyextra->currentObjId++; + return result; +} + +static QCString escapeWord(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString result; + result.sprintf("$w%d",yyextra->currentWordId); + yyextra->wordDict.insert(yyextra->currentWordId,new QCString(s)); + yyextra->currentWordId++; + return result; +} + +static QCString escapeComment(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString result; + result.sprintf("$d%d",yyextra->currentCommentId); + yyextra->commentDict.insert(yyextra->currentCommentId,new QCString(s)); + yyextra->currentCommentId++; + return result; +} + +static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const QCString &kw) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + return yyextra->lang==SrcLangExt_Cpp && (kw == "remove" || kw == "set" || kw == "get"); +} + +static bool isCastKeyword(const QCString &s) +{ + int i=s.find('<'); + if (i==-1) return FALSE; + QCString kw = s.left(i).stripWhiteSpace(); + return kw=="const_cast" || kw=="static_cast" || kw=="dynamic_cast" || kw=="reinterpret_cast"; +} + +static int yyread(yyscan_t yyscanner,char *buf,int max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + int inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + yyextra->inputPosition; + int c=0; + while( c < max_size && *s ) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} -/*@ ---------------------------------------------------------------------------- - */ -static void saveObjCContext() +static void saveObjCContext(yyscan_t yyscanner) { - if (g_currentCtx) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentCtx) { - g_currentCtx->format+=QCString().sprintf("$c%d",g_currentCtxId); - if (g_braceCount==0 && YY_START==ObjCCall) + yyextra->currentCtx->format+=QCString().sprintf("$c%d",yyextra->currentCtxId); + if (yyextra->braceCount==0 && YY_START==ObjCCall) { - g_currentCtx->objectTypeOrName=g_currentCtx->format.mid(1); - //printf("new type=%s\n",g_currentCtx->objectTypeOrName.data()); + yyextra->currentCtx->objectTypeOrName=yyextra->currentCtx->format.mid(1); + //printf("new type=%s\n",yyextra->currentCtx->objectTypeOrName.data()); } - g_contextStack.push(g_currentCtx); + yyextra->contextStack.push(yyextra->currentCtx); } else { //printf("Trying to save NULL context!\n"); } ObjCCallCtx *newCtx = new ObjCCallCtx; - newCtx->id = g_currentCtxId; + newCtx->id = yyextra->currentCtxId; newCtx->lexState = YY_START; - newCtx->braceCount = g_braceCount; + newCtx->braceCount = yyextra->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++; + yyextra->contextDict.insert(yyextra->currentCtxId,newCtx); + yyextra->currentCtx = newCtx; + yyextra->braceCount = 0; + yyextra->currentCtxId++; } -static void restoreObjCContext() +static void restoreObjCContext(yyscan_t yyscanner) { - //printf("restore state=%d->%d\n",YY_START,g_currentCtx->lexState); - BEGIN(g_currentCtx->lexState); - g_braceCount = g_currentCtx->braceCount; - if (!g_contextStack.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("restore state=%d->%d\n",YY_START,yyextra->currentCtx->lexState); + BEGIN(yyextra->currentCtx->lexState); + yyextra->braceCount = yyextra->currentCtx->braceCount; + if (!yyextra->contextStack.isEmpty()) { - g_currentCtx = g_contextStack.pop(); + yyextra->currentCtx = yyextra->contextStack.pop(); } else { - g_currentCtx = 0; - //printf("Trying to pop context while g_contextStack is empty!\n"); + yyextra->currentCtx = 0; + //printf("Trying to pop context while yyextra->contextStack is empty!\n"); } } -void resetCCodeParserState() +struct CodeScanner::Private +{ + yyscan_t yyscanner; + codeYY_state state; +}; + +CodeScanner::CodeScanner() +{ + p = new Private; + codeYYlex_init_extra(&p->state,&p->yyscanner); + YY_EXTRA_TYPE state = codeYYget_extra(p->yyscanner); +} + +CodeScanner::~CodeScanner() { - //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; + codeYYlex_destroy(p->yyscanner); + delete p; } -void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s, +void CodeScanner::reset() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + //printf("***CodeParser::reset()\n"); + yyextra->forceTagReference.resize(0); + yyextra->theVarContext.clear(); + yyextra->classScopeLengthStack.setAutoDelete(TRUE); + yyextra->classScopeLengthStack.clear(); + delete yyextra->codeClassSDict; + yyextra->codeClassSDict = new ClassSDict(17); + yyextra->codeClassSDict->setAutoDelete(TRUE); + yyextra->codeClassSDict->clear(); + yyextra->curClassBases.clear(); + yyextra->anchorCount = 0; +} + +void CodeScanner::parseCCode(CodeOutputInterface &od,const char *className,const QCString &s, SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs) { + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n", // exBlock,exName,fd,className,searchCtx?searchCtx->name().data():""); @@ -3778,103 +3911,92 @@ void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s, printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - if (g_codeClassSDict==0) + if (yyextra->codeClassSDict==0) { - resetCCodeParserState(); + reset(); } - g_code = &od; - g_inputString = s; - g_inputPosition = 0; - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_searchCtx = searchCtx; - g_collectXRefs = collectXRefs; - g_inFunctionTryBlock = FALSE; + yyextra->code = &od; + yyextra->inputString = s; + yyextra->inputPosition = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = FALSE; + yyextra->searchCtx = searchCtx; + yyextra->collectXRefs = collectXRefs; + yyextra->inFunctionTryBlock = FALSE; if (startLine!=-1) - g_yyLineNr = startLine; + yyextra->yyLineNr = startLine; else - g_yyLineNr = 1; + yyextra->yyLineNr = 1; if (endLine!=-1) - g_inputLines = endLine+1; + yyextra->inputLines = endLine+1; else - g_inputLines = g_yyLineNr + countLines() - 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; + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; + + yyextra->curlyCount = 0; + yyextra->bodyCurlyCount = 0; + yyextra->bracketCount = 0; + yyextra->sharpCount = 0; + yyextra->insideTemplate = FALSE; + yyextra->theCallContext.clear(); + yyextra->scopeStack.clear(); + yyextra->classScope = className; //printf("parseCCode %s\n",className); - g_exampleBlock = exBlock; - g_exampleName = exName; - g_sourceFileDef = fd; - g_lineNumbers = fd!=0 && showLineNumbers; + yyextra->exampleBlock = exBlock; + yyextra->exampleName = exName; + yyextra->sourceFileDef = fd; + yyextra->lineNumbers = fd!=0 && showLineNumbers; bool cleanupSourceDef = FALSE; if (fd==0) { // create a dummy filedef for the example - g_sourceFileDef = createFileDef("",(exName?exName:"generated")); + yyextra->sourceFileDef = createFileDef("",(exName?exName:"generated")); cleanupSourceDef = TRUE; } - g_lang = lang; - g_insideObjC = lang==SrcLangExt_ObjC; - if (g_sourceFileDef) + yyextra->lang = lang; + yyextra->insideObjC = lang==SrcLangExt_ObjC; + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc(yyscanner,"l00001"); } - g_currentDefinition = 0; - g_currentMemberDef = 0; - g_searchingForBody = exBlock; - g_insideBody = FALSE; - g_bracketCount = 0; - if (!g_exampleName.isEmpty()) + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; + yyextra->searchingForBody = exBlock; + yyextra->insideBody = FALSE; + yyextra->bracketCount = 0; + if (!yyextra->exampleName.isEmpty()) { - g_exampleFile = convertNameToFile(g_exampleName+"-example",FALSE,TRUE); - //printf("g_exampleFile=%s\n",g_exampleFile.data()); + yyextra->exampleFile = convertNameToFile(yyextra->exampleName+"-example",FALSE,TRUE); + //printf("yyextra->exampleFile=%s\n",yyextra->exampleFile.data()); } - g_includeCodeFragment = inlineFragment; + yyextra->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 ); + startCodeLine(yyscanner); + yyextra->type.resize(0); + yyextra->name.resize(0); + yyextra->args.resize(0); + yyextra->parmName.resize(0); + yyextra->parmType.resize(0); + if (memberDef) setParameterList(yyscanner,memberDef); BEGIN( Body ); - codeYYlex(); - g_lexInit=TRUE; - if (g_needsTermination) + codeYYlex(yyscanner); + yyextra->lexInit=TRUE; + if (yyextra->needsTermination) { - endFontClass(); - DBG_CTX((stderr,"endCodeLine(%d)\n",g_yyLineNr)); - g_code->endCodeLine(); + endFontClass(yyscanner); + DBG_CTX((stderr,"endCodeLine(%d)\n",yyextra->yyLineNr)); + yyextra->code->endCodeLine(); } if (cleanupSourceDef) { // delete the temporary file definition used for this example - delete g_sourceFileDef; - g_sourceFileDef=0; + delete yyextra->sourceFileDef; + yyextra->sourceFileDef=0; } printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); return; } -void codeFreeScanner() -{ -#if defined(YY_FLEX_SUBMINOR_VERSION) - if (g_lexInit) - { - codeYYlex_destroy(); - } -#endif -} - #include "code.l.h" diff --git a/src/doxygen.cpp b/src/doxygen.cpp index b4a4deb..d4d55e7 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -8992,7 +8992,8 @@ static void generateExampleDocs() for (pdi.toFirst();(pd=pdi.current());++pdi) { msg("Generating docs for example %s...\n",pd->name().data()); - resetCCodeParserState(); + ParserInterface *pIntf = Doxygen::parserManager->getParser(".c"); // TODO: do this on code type + pIntf->resetCodeParserState(); QCString n=pd->getOutputFileBase(); startFile(*g_outputList,n,n,pd->name()); startTitle(*g_outputList,n); @@ -10187,7 +10188,6 @@ void cleanUpDoxygen() delete theTranslator; delete g_outputList; Mappers::freeMappers(); - codeFreeScanner(); if (Doxygen::symbolMap) { diff --git a/src/scanner.l b/src/scanner.l index 37fcb1c..2b277db 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -201,6 +201,8 @@ static bool g_nestedComment=0; static std::vector< std::pair > > g_outerScopeEntries; +static CodeScanner g_codeScanner; + static const char *stateToString(int state); //----------------------------------------------------------------------------- @@ -7359,6 +7361,7 @@ void CLanguageScanner::parseInput(const char *fileName, printlex(yy_flex_debug, FALSE, __FILE__, fileName); } + void CLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf, const char * scopeName, const QCString & input, @@ -7375,7 +7378,7 @@ void CLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf, bool collectXRefs ) { - ::parseCCode(codeOutIntf,scopeName,input,lang,isExampleBlock,exampleName, + g_codeScanner.parseCCode(codeOutIntf,scopeName,input,lang,isExampleBlock,exampleName, fileDef,startLine,endLine,inlineFragment,memberDef, showLineNumbers,searchCtx,collectXRefs); } @@ -7392,7 +7395,7 @@ bool CLanguageScanner::needsPreprocessing(const QCString &extension) const void CLanguageScanner::resetCodeParserState() { - ::resetCCodeParserState(); + g_codeScanner.reset(); } void CLanguageScanner::parsePrototype(const char *text) -- cgit v0.12