Doxygen
Loading...
Searching...
No Matches
code.l File Reference
#include <stdint.h>
#include "code.h"
#include <algorithm>
#include <cctype>
#include <cstdint>
#include <memory>
#include <mutex>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include "arguments.h"
#include "classlist.h"
#include "conceptdef.h"
#include "config.h"
#include "debug.h"
#include "dir.h"
#include "doxygen.h"
#include "entry.h"
#include "filedef.h"
#include "filename.h"
#include "groupdef.h"
#include "membername.h"
#include "message.h"
#include "moduledef.h"
#include "namespacedef.h"
#include "outputlist.h"
#include "scopedtypevariant.h"
#include "searchindex.h"
#include "symbolresolver.h"
#include "tooltip.h"
#include "util.h"
#include "doxygen_lex.h"
#include "code.l.h"
Include dependency graph for code.l:

Go to the source code of this file.

Classes

struct  ObjCCallCtx
struct  codeYY_state
struct  CCodeParser::Private

Macros

#define YY_TYPEDEF_YY_SCANNER_T
#define DBG_CTX(x)
#define YY_NO_UNISTD_H   1
#define CLASSBLOCK   1
#define SCOPEBLOCK   2
#define INNERBLOCK   3
#define YY_INPUT(buf, result, max_size)

Typedefs

typedef yyguts_t * yyscan_t

Functions

static bool isCastKeyword (const char *s)
static const char * stateToString (int state)
static void saveObjCContext (yyscan_t yyscanner)
static void restoreObjCContext (yyscan_t yyscanner)
static void pushScope (yyscan_t yyscanner, const DString &s)
static void popScope (yyscan_t yyscanner)
static void setCurrentDoc (yyscan_t yyscanner, const DString &anchor)
static void addToSearchIndex (yyscan_t yyscanner, const DString &text)
static void setClassScope (yyscan_t yyscanner, const DString &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, bool specialComment=false)
static void endFontClass (yyscan_t yyscanner, bool specialComment=false)
static void codifyLines (yyscan_t yyscanner, const DString &text)
static void incrementFlowKeyWordCount (yyscan_t yyscanner)
static void writeMultiLineCodeLink (yyscan_t yyscanner, OutputCodeList &ol, const Definition *d, const DString &text)
static void addType (yyscan_t yyscanner)
static void addParmType (yyscan_t yyscanner)
static void addUsingDirective (yyscan_t yyscanner, const DString &name)
static void setParameterList (yyscan_t yyscanner, const MemberDef *md)
static const ClassDefstripClassName (yyscan_t yyscanner, const DString &s, const Definition *d)
static const MemberDefsetCallContextForVar (yyscan_t yyscanner, const DString &name)
static void updateCallContextForSmartPointer (yyscan_t yyscanner)
static bool getLinkInScope (yyscan_t yyscanner, const DString &c, const DString &m, const DString &memberText, OutputCodeList &ol, const DString &text, bool varOnly=false)
static bool getLink (yyscan_t yyscanner, const DString &className, const DString &memberName, OutputCodeList &ol, const DString &text=DString(), bool varOnly=false)
static void generateClassOrGlobalLink (yyscan_t yyscanner, OutputCodeList &ol, const DString &clName, bool typeOnly=false, bool varOnly=false)
static bool generateClassMemberLink (yyscan_t yyscanner, OutputCodeList &ol, const MemberDef *xmd, const DString &memName)
static bool generateClassMemberLink (yyscan_t yyscanner, OutputCodeList &ol, const Definition *def, const DString &memName)
static void generateMemberLink (yyscan_t yyscanner, OutputCodeList &ol, const DString &varName, const DString &memName)
static void generatePHPVariableLink (yyscan_t yyscanner, OutputCodeList &ol, const char *varName)
static void generateFunctionLink (yyscan_t yyscanner, OutputCodeList &ol, const DString &funcName)
static int countLines (yyscan_t yyscanner)
static void writeObjCMethodCall (yyscan_t yyscanner, ObjCCallCtx *ctx)
static DString escapeName (yyscan_t yyscanner, const DString &s)
static DString escapeObject (yyscan_t yyscanner, const DString &s)
static DString escapeWord (yyscan_t yyscanner, const DString &s)
static DString escapeComment (yyscan_t yyscanner, const DString &s)
static bool skipLanguageSpecificKeyword (yyscan_t yyscanner, const char *kw)
static int yyread (yyscan_t yyscanner, char *buf, int max_size)
static void addVariable (yyscan_t yyscanner, DString type, DString name)
static bool startsWithKeyword (const DString &str, const DString &kw)
static void endCodeFold (yyscan_t yyscanner)
static const char * getLexerFILE ()
int yylex (yyscan_t yyscanner)
static void codeFolding (yyscan_t yyscanner, const Definition *d)

Macro Definition Documentation

◆ CLASSBLOCK

#define CLASSBLOCK   1

Definition at line 74 of file code.l.

Referenced by setCallContextForVar().

◆ DBG_CTX

◆ INNERBLOCK

#define INNERBLOCK   3

Definition at line 76 of file code.l.

◆ SCOPEBLOCK

#define SCOPEBLOCK   2

Definition at line 75 of file code.l.

◆ YY_INPUT

#define YY_INPUT ( buf,
result,
max_size )
Value:
result=yyread(yyscanner,buf,max_size);
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition code.l:3981

Definition at line 257 of file code.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 72 of file code.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 22 of file code.l.

Typedef Documentation

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 24 of file code.l.

Function Documentation

◆ addParmType()

void addParmType ( yyscan_t yyscanner)
static

Definition at line 2608 of file code.l.

2609{
2610 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2611 if (yyextra->parmName=="const") { yyextra->parmName.clear(); return; }
2612 if (!yyextra->parmType.empty()) yyextra->parmType += ' ' ;
2613 yyextra->parmType += yyextra->parmName ;
2614 yyextra->parmName.clear() ;
2615}

◆ addToSearchIndex()

void addToSearchIndex ( yyscan_t yyscanner,
const DString & text )
static

Definition at line 2301 of file code.l.

2302{
2303 if (Doxygen::searchIndex.enabled())
2304 {
2305 Doxygen::searchIndex.addWord(text,false);
2306 }
static SearchIndexIntf searchIndex
Definition doxygen.h:117
void addWord(const DString &word, bool hiPriority)
2307}

References SearchIndexIntf::addWord(), and Doxygen::searchIndex.

Referenced by generateClassMemberLink(), generateClassMemberLink(), generateClassOrGlobalLink(), generateMemberLink(), and getLinkInScope().

◆ addType()

void addType ( yyscan_t yyscanner)
static

Definition at line 2596 of file code.l.

2597{
2598 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2599 if (yyextra->name=="const") { yyextra->name.clear(); return; }
2600 if (!yyextra->type.empty()) yyextra->type += ' ' ;
2601 yyextra->type += yyextra->name ;
2602 yyextra->name.clear() ;
2603 if (!yyextra->type.empty()) yyextra->type += ' ' ;
2604 yyextra->type += yyextra->args ;
2605 yyextra->args.clear() ;
2606}

◆ addUsingDirective()

void addUsingDirective ( yyscan_t yyscanner,
const DString & name )
static

Definition at line 2617 of file code.l.

2618{
2619 //printf("AddUsingDirective(%s)\n",qPrint(name));
2620 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2621 if (yyextra->sourceFileDef && !name.empty())
2622 {
2624 if (nd)
2625 {
2626 yyextra->theUsingContext.emplace(name.str(),nd);
2627 }
2628 }
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
const std::string & str() const
Definition dstring.h:645
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:108
const T * find(const std::string &key) const
Definition linkedmap.h:47
An abstract interface of a namespace symbol.
2629}

References DString::empty(), LinkedMap< T, Hash, KeyEqual, Map >::find(), Doxygen::namespaceLinkedMap, and DString::str().

◆ addVariable()

void addVariable ( yyscan_t yyscanner,
DString type,
DString name )
static

Definition at line 2187 of file code.l.

2188{
2189 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2190 DBG_CTX((stderr,"VariableContext::addVariable(%s,%s)\n",qPrint(type),qPrint(name)));
2191 DString ltype = type.simplifyWhiteSpace();
2192 DString lname = name.simplifyWhiteSpace();
2193 ltype.stripPrefix("struct ");
2194 ltype.stripPrefix("union ");
2195 if (ltype.empty() || lname.empty()) return;
2196 ltype = substitute(ltype,".","::");
2197 DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' currentDefinition=%s\n",
2198 qPrint(ltype),qPrint(lname),yyextra->currentDefinition?qPrint(yyextra->currentDefinition->name()):"<none>"));
2199 auto it = yyextra->codeClassMap.find(ltype.str());
2200 if (it!=yyextra->codeClassMap.end()) // look for class definitions inside the code block
2201 {
2202 DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",qPrint(ltype),qPrint(lname)));
2203 yyextra->theVarContext.addVariable(lname,std::move(it->second)); // add it to a list
2204 }
2205 else
2206 {
2207 auto findVariableType = [&yyscanner,&yyg,&ltype,&lname,&name](const Definition *d) -> const ClassDef *
2208 {
2209 const ClassDef *varDef = yyextra->symbolResolver.resolveClass(d,ltype,true);
2210 if (varDef)
2211 {
2212 DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",qPrint(ltype),qPrint(lname)));
2213 yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varDef)); // add it to a list
2214 }
2215 else if (size_t i=ltype.find('<') ; i!=DString::npos)
2216 {
2217 // probably a template class
2218 addVariable(yyscanner,ltype.left(i),name);
2219 }
2220 return varDef;
2221 };
2222 const ClassDef *varDef = findVariableType(yyextra->currentDefinition);
2223 if (varDef==nullptr) // also check via using directive
2224 {
2225 for (const auto &[usingName,namespaceDef] : yyextra->theUsingContext)
2226 {
2227 varDef = findVariableType(namespaceDef);
2228 if (varDef) break;
2229 }
2230 }
2231 if (varDef==nullptr)
2232 {
2233 if (!yyextra->theVarContext.atGlobalScope()) // for local variables add a dummy entry so the name
2234 // is hidden to avoid false links to global variables with the same name
2235 // TODO: make this work for namespaces as well!
2236 {
2237 DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",qPrint(lname)));
2238 yyextra->theVarContext.addVariable(lname,ScopedTypeVariant());
2239 }
2240 else
2241 {
2242 DBG_CTX((stderr,"** addVariable: not adding variable!\n"));
2243 }
2244 }
2245 }
A abstract class representing of a compound symbol.
Definition classdef.h:100
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
DString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple internal white...
Definition dstring.cpp:127
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:178
bool stripPrefix(const DString &prefix)
Definition dstring.h:290
The common base class of all entity definitions found in the sources.
Definition definition.h:77
#define DBG_CTX(x)
Definition code.l:70
static void addVariable(yyscan_t yyscanner, DString type, DString name)
Definition code.l:2187
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
Definition dstring.cpp:485
const char * qPrint(const char *s)
Definition dstring.h:783
2246}

References addVariable(), DBG_CTX, DString::empty(), DString::npos, qPrint(), DString::simplifyWhiteSpace(), DString::str(), DString::stripPrefix(), and substitute().

Referenced by addVariable(), and setParameterList().

◆ codeFolding()

void codeFolding ( yyscan_t yyscanner,
const Definition * d )
static

Definition at line 2359 of file code.l.

2360{
2361 if (Config_getBool(HTML_CODE_FOLDING))
2362 {
2363 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2364 //fprintf(stderr,"codeFolding at %d\n",yyextra->yyLineNr);
2365 //if (d)
2366 // fprintf(stderr,"%d: codeFolding: candidate=%s [%d..%d]\n",yyextra->yyLineNr,qPrint(d->qualifiedName()),d->getStartDefLine(),d->getEndBodyLine());
2367 endCodeFold(yyscanner);
2368 if (d)
2369 {
2370 int startLine = d->getStartDefLine();
2371 int endLine = d->getEndBodyLine();
2372 if (endLine!=-1 && startLine!=endLine &&
2373 // since the end of a section is closed after the last line, we need to avoid starting a
2374 // new section if the previous section ends at the same line, i.e. something like
2375 // struct X {
2376 // ...
2377 // }; struct S { <- start of S and end of X at the same line
2378 // ...
2379 // };
2380 (yyextra->foldStack.empty() || yyextra->foldStack.back()->getEndBodyLine()!=startLine))
2381 {
2382 //printf("%d: start codeFolding for %s [%d..%d]\n",yyextra->yyLineNr,qPrint(d->name()),d->getStartDefLine(),d->getEndBodyLine());
2384 {
2385 const MemberDef *md = toMemberDef(d);
2386 if (md && md->isDefine())
2387 {
2388 yyextra->code->startFold(yyextra->yyLineNr,"",""); // #define X ...
2389 }
2390 else if (md && md->isCallable())
2391 {
2392 yyextra->code->startFold(yyextra->yyLineNr,"{","}"); // func() { ... }
2393 }
2394 else
2395 {
2396 yyextra->code->startFold(yyextra->yyLineNr,"{","};"); // enum X { ... }
2397 }
2398 }
2400 {
2401 yyextra->code->startFold(yyextra->yyLineNr,"{","};"); // class X { ... };
2402 }
2403 else
2404 {
2405 yyextra->code->startFold(yyextra->yyLineNr,"{","}"); // namespace X {...}
2406 }
2407 yyextra->foldStack.push_back(d);
2408 }
2409 }
2410 }
virtual int getEndBodyLine() const =0
virtual DefType definitionType() const =0
virtual int getStartDefLine() const =0
A model of a class/file/namespace member symbol.
Definition memberdef.h:45
virtual bool isDefine() const =0
virtual bool isCallable() const =0
static void endCodeFold(yyscan_t yyscanner)
Definition code.l:2338
#define Config_getBool(name)
Definition config.h:33
MemberDef * toMemberDef(Definition *d)
2411}

References Config_getBool, Definition::definitionType(), endCodeFold(), Definition::getEndBodyLine(), Definition::getStartDefLine(), MemberDef::isCallable(), MemberDef::isDefine(), toMemberDef(), Definition::TypeClass, and Definition::TypeMember.

Referenced by startCodeLine().

◆ codifyLines()

void codifyLines ( yyscan_t yyscanner,
const DString & text )
static

write a code fragment 'text' that may span multiple lines, inserting line numbers for each line.

Definition at line 2513 of file code.l.

2514{
2515 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2516 DBG_CTX((stderr,"codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,qPrint(text)));
2517 if (text.empty()) return;
2518 const char *p=text.data(),*sp=p;
2519 char c;
2520 bool done=false;
2521 while (!done)
2522 {
2523 sp=p;
2524 while ((c=*p++) && c!='\n');
2525 if (c=='\n')
2526 {
2527 yyextra->yyLineNr++;
2528 size_t l = static_cast<size_t>(p-sp-1);
2529 yyextra->code->codify(DString(sp,l));
2530 nextCodeLine(yyscanner);
2531 }
2532 else
2533 {
2534 yyextra->code->codify(sp);
2535 done=true;
2536 }
2537 }
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
static void nextCodeLine(yyscan_t yyscanner)
Definition code.l:2495
2538}

References DString::data(), DBG_CTX, DString::empty(), nextCodeLine(), and qPrint().

Referenced by generateClassOrGlobalLink(), generateMemberLink(), generatePHPVariableLink(), and writeObjCMethodCall().

◆ countLines()

int countLines ( yyscan_t yyscanner)
static

counts the number of lines in the input

Definition at line 3472 of file code.l.

3473{
3474 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3475 const char *p=yyextra->inputString;
3476 char c = 0;
3477 int count=1;
3478 while ((c=*p))
3479 {
3480 p++ ;
3481 if (c=='\n') count++;
3482 }
3483 if (p>yyextra->inputString && *(p-1)!='\n')
3484 { // last line does not end with a \n, so we add an extra
3485 count++;
3486 }
3487 return count;
3488}

Referenced by CCodeParser::parseCode().

◆ endCodeFold()

void endCodeFold ( yyscan_t yyscanner)
static

Definition at line 2338 of file code.l.

2339{
2340 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2341 while (!yyextra->foldStack.empty())
2342 {
2343 const Definition *dd = yyextra->foldStack.back();
2344 if (dd->getEndBodyLine()+1==yyextra->yyLineNr) // +1 to close the section after the end of the body
2345 {
2346 yyextra->code->endFold();
2347 //fprintf(stderr,"%d: end codeFolding for %s [%d..%d]\n",yyextra->yyLineNr,qPrint(dd->name()),dd->getStartDefLine(),dd->getEndBodyLine());
2348 yyextra->foldStack.pop_back();
2349 }
2350 else
2351 {
2352 //fprintf(stderr,"no end of block dd=%s end=%d\n",qPrint(dd->qualifiedName()),dd->getEndBodyLine());
2353 break;
2354 }
2355 }
2356}

References Definition::getEndBodyLine().

Referenced by codeFolding().

◆ endCodeLine()

void endCodeLine ( yyscan_t yyscanner)
static

Definition at line 2486 of file code.l.

2487{
2488 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2489 DBG_CTX((stderr,"endCodeLine(%d)\n",yyextra->yyLineNr));
2490 endFontClass(yyscanner);
2491 yyextra->code->endCodeLine();
2492 yyextra->insideCodeLine = false;
static void endFontClass(yyscan_t yyscanner, bool specialComment=false)
Definition code.l:3490
2493}

References DBG_CTX, and endFontClass().

Referenced by nextCodeLine(), nextCodeLine(), and CCodeParser::parseCode().

◆ endFontClass()

void endFontClass ( yyscan_t yyscanner,
bool specialComment = false )
static

Definition at line 3490 of file code.l.

3491{
3492 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3493 if (yyextra->currentFontClass)
3494 {
3495 yyextra->code->endFontClass();
3496 yyextra->currentFontClass=nullptr;
3497 }
3498 if (specialComment && yyextra->insideSpecialComment)
3499 {
3500 yyextra->code->endSpecialComment();
3501 yyextra->insideSpecialComment = false;
3502 }
3503}

Referenced by endCodeLine(), endCodeLine(), startFontClass(), startFontClass(), and writeObjCMethodCall().

◆ escapeComment()

DString escapeComment ( yyscan_t yyscanner,
const DString & s )
static

Definition at line 3921 of file code.l.

3922{
3923 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3924 DString result;
3925 result.sprintf("$d%d",yyextra->currentCommentId);
3926 yyextra->commentMap.emplace(yyextra->currentCommentId,s);
3927 yyextra->currentCommentId++;
3928 return result;
DString & sprintf(const char *format,...)
Definition dstring.cpp:34
3929}

References DString::sprintf().

◆ escapeName()

DString escapeName ( yyscan_t yyscanner,
const DString & s )
static

Definition at line 3891 of file code.l.

3892{
3893 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3894 DString result;
3895 result.sprintf("$n%d",yyextra->currentNameId);
3896 yyextra->nameMap.emplace(yyextra->currentNameId,s);
3897 yyextra->currentNameId++;
3898 return result;
3899}

References DString::sprintf().

◆ escapeObject()

DString escapeObject ( yyscan_t yyscanner,
const DString & s )
static

Definition at line 3901 of file code.l.

3902{
3903 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3904 DString result;
3905 result.sprintf("$o%d",yyextra->currentObjId);
3906 yyextra->objectMap.emplace(yyextra->currentObjId,s);
3907 yyextra->currentObjId++;
3908 return result;
3909}

References DString::sprintf().

◆ escapeWord()

DString escapeWord ( yyscan_t yyscanner,
const DString & s )
static

Definition at line 3911 of file code.l.

3912{
3913 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3914 DString result;
3915 result.sprintf("$w%d",yyextra->currentWordId);
3916 yyextra->wordMap.emplace(yyextra->currentWordId,s);
3917 yyextra->currentWordId++;
3918 return result;
3919}

References DString::sprintf().

◆ generateClassMemberLink() [1/2]

bool generateClassMemberLink ( yyscan_t yyscanner,
OutputCodeList & ol,
const Definition * def,
const DString & memName )
static

Definition at line 3206 of file code.l.

3210{
3211 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3212 if (def && def->definitionType()==Definition::TypeClass)
3213 {
3214 const ClassDef *cd = toClassDef(def);
3215 const MemberDef *xmd = cd->getMemberByName(memName);
3216 DBG_CTX((stderr,"generateClassMemberLink(class=%s,member=%s)=%p\n",qPrint(def->name()),qPrint(memName),(void*)xmd));
3217 if (xmd)
3218 {
3219 return generateClassMemberLink(yyscanner,ol,xmd,memName);
3220 }
3221 else
3222 {
3223 const Definition *innerDef = cd->findInnerCompound(memName);
3224 if (innerDef)
3225 {
3226 yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef));
3227 addToSearchIndex(yyscanner,memName);
3228 writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName);
3229 return true;
3230 }
3231 }
3232 }
3233 else if (def && def->definitionType()==Definition::TypeNamespace)
3234 {
3235 const NamespaceDef *nd = toNamespaceDef(def);
3236 DBG_CTX((stderr,"Looking for %s inside namespace %s\n",qPrint(memName),qPrint(nd->name())));
3237 const Definition *innerDef = nd->findInnerCompound(memName);
3238 if (innerDef)
3239 {
3240 yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef));
3241 addToSearchIndex(yyscanner,memName);
3242 writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName);
3243 return true;
3244 }
3245 }
3246 return false;
virtual const MemberDef * getMemberByName(const DString &) const =0
Returns the member with the given name.
virtual const DString & name() const =0
virtual const Definition * findInnerCompound(const DString &name) const =0
ClassDef * toClassDef(Definition *d)
static void addToSearchIndex(yyscan_t yyscanner, const DString &text)
Definition code.l:2301
static void writeMultiLineCodeLink(yyscan_t yyscanner, OutputCodeList &ol, const Definition *d, const DString &text)
Definition code.l:2558
static bool generateClassMemberLink(yyscan_t yyscanner, OutputCodeList &ol, const MemberDef *xmd, const DString &memName)
Definition code.l:3144
NamespaceDef * toNamespaceDef(Definition *d)
3247}

References addToSearchIndex(), DBG_CTX, Definition::definitionType(), Definition::findInnerCompound(), generateClassMemberLink(), ClassDef::getMemberByName(), Definition::name(), qPrint(), toClassDef(), toNamespaceDef(), Definition::TypeClass, Definition::TypeNamespace, and writeMultiLineCodeLink().

◆ generateClassMemberLink() [2/2]

bool generateClassMemberLink ( yyscan_t yyscanner,
OutputCodeList & ol,
const MemberDef * xmd,
const DString & memName )
static

Definition at line 3144 of file code.l.

3148{
3149 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3150 // extract class definition of the return type in order to resolve
3151 // a->b()->c() like call chains
3152
3153 DBG_CTX((stderr,"type='%s' args='%s' class=%s\n",
3154 qPrint(xmd->typeString()),qPrint(xmd->argsString()),
3155 qPrint(xmd->getClassDef()->name())));
virtual DString argsString() const =0
virtual const ClassDef * getClassDef() const =0
virtual DString typeString() const =0
3156
3157 if (yyextra->exampleBlock)
3158 {
3159 std::lock_guard<std::mutex> lock(Doxygen::addExampleMutex);
3160 DString anchor;
3161 anchor.sprintf("a%d",yyextra->anchorCount);
3162 DBG_CTX((stderr,"addExampleFile(%s,%s,%s)\n",qPrint(anchor),qPrint(yyextra->exampleName),
3163 qPrint(yyextra->exampleFile)));
3164 MemberDefMutable *mdm = toMemberDefMutable(const_cast<MemberDef*>(xmd));
3165 if (mdm && mdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile))
3166 {
3167 ol.writeCodeAnchor(anchor);
3168 yyextra->anchorCount++;
3169 }
3170 }
static std::mutex addExampleMutex
Definition doxygen.h:133
virtual bool addExample(const DString &anchor, const DString &name, const DString &file)=0
void writeCodeAnchor(const DString &name)
Definition outputlist.h:273
MemberDefMutable * toMemberDefMutable(Definition *d)
3171
3172 const ClassDef *typeClass = stripClassName(yyscanner,removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope());
3173 DBG_CTX((stderr,"%s -> typeName=%p\n",qPrint(xmd->typeString()),(void*)typeClass));
3174 yyextra->theCallContext.setScope(ScopedTypeVariant(typeClass));
virtual Definition * getOuterScope() const =0
static const ClassDef * stripClassName(yyscan_t yyscanner, const DString &s, const Definition *d)
Definition code.l:2648
DString removeAnonymousScopes(const DString &str)
Definition util.cpp:98
3175
3176 const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
3177 xmd->getFileDef() : xmd->getOuterScope();
3178 if (xmd->getGroupDef()) xd = xmd->getGroupDef();
3179 if (xd && xd->isLinkable())
3180 {
virtual bool isLinkable() const =0
static NamespaceDefMutable * globalScope
Definition doxygen.h:114
virtual GroupDef * getGroupDef()=0
virtual const FileDef * getFileDef() const =0
3181
3182 DBG_CTX((stderr,"yyextra->currentDefinition=%p yyextra->currentMemberDef=%p xmd=%p yyextra->insideBody=%d\n",
3183 (void*)yyextra->currentDefinition,(void*)yyextra->currentMemberDef,(void*)xmd,yyextra->insideBody));
3184
3185 if (xmd->templateMaster()) xmd = xmd->templateMaster();
virtual const MemberDef * templateMaster() const =0
3186
3187 if (xmd->isLinkable())
3188 {
3189 // add usage reference
3190 if (yyextra->currentDefinition && yyextra->currentMemberDef &&
3191 yyextra->insideBody && yyextra->collectXRefs)
3192 {
3193 addDocCrossReference(yyextra->currentMemberDef,xmd);
3194 }
void addDocCrossReference(const MemberDef *s, const MemberDef *d)
3195
3196 // write the actual link
3197 writeMultiLineCodeLink(yyscanner,ol,xmd,memName);
3198 addToSearchIndex(yyscanner,memName);
3199 return true;
3200 }
3201 }
3202
3203 return false;
3204}

References addDocCrossReference(), MemberDefMutable::addExample(), Doxygen::addExampleMutex, addToSearchIndex(), MemberDef::argsString(), DBG_CTX, MemberDef::getClassDef(), MemberDef::getFileDef(), MemberDef::getGroupDef(), Definition::getOuterScope(), Doxygen::globalScope, Definition::isLinkable(), Definition::name(), qPrint(), removeAnonymousScopes(), DString::sprintf(), stripClassName(), toMemberDefMutable(), MemberDef::typeString(), OutputCodeList::writeCodeAnchor(), and writeMultiLineCodeLink().

Referenced by generateClassMemberLink(), generateFunctionLink(), and generateMemberLink().

◆ generateClassOrGlobalLink()

void generateClassOrGlobalLink ( yyscan_t yyscanner,
OutputCodeList & ol,
const DString & clName,
bool typeOnly = false,
bool varOnly = false )
static

Definition at line 2915 of file code.l.

2920{
2921 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2922 DString scopeName=scName;
2923 if (!scopeName.empty() && scopeName[0]=='~') // correct for matching negated values i.s.o. destructors.
2924 {
2925 scopeName=scopeName.mid(1);
2926 }
2927 if (scopeName.empty())
2928 {
2929 yyextra->code->codify("~");
2930 return;
2931 }
2932 if (yyextra->insideProtocolList) // for Obj-C
2933 {
2934 scopeName+="-p";
2935 }
2936 if (yyextra->lang==SrcLangExt::PHP)
2937 {
2938 scopeName = substitute(scopeName,"\\","::"); // for PHP namespaces
2939 }
2940 else if (yyextra->lang==SrcLangExt::CSharp || yyextra->lang==SrcLangExt::Java)
2941 {
2942 scopeName = substitute(scopeName,".","::"); // for C#/Java namespaces
2943 }
2944 if (yyextra->currentDefinition==nullptr && !yyextra->scopeName.empty())
2945 {
2946 scopeName = yyextra->scopeName+"::"+scopeName;
2947 }
2948 const ScopedTypeVariant *lcd=nullptr;
2949 const Definition *sym=nullptr;
2950 bool isLocal=false;
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
2951
2952 DBG_CTX((stderr,"generateClassOrGlobalLink(name=%s) yyextra->scopeName=%s scopeName=%s\n",qPrint(scName),qPrint(yyextra->scopeName),qPrint(scopeName)));
2953 if (!yyextra->isPrefixedWithThis || (lcd=yyextra->theVarContext.findVariable(scopeName))==nullptr) // not a local variable
2954 {
2955 DString bareName = scopeName;
2956 if (size_t i=scopeName.find('<') ; i!=DString::npos) bareName = bareName.left(i);
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
DString left(size_t len) const
Definition dstring.h:306
2957
2958 auto checkForSymbol = [&yyg,&bareName,&scopeName](const Definition *parent,
2959 const Definition *&sym_)
2960 {
2961 sym_ = yyextra->symbolResolver.resolveSymbol(parent,scopeName,DString(),false,true);
2962 DBG_CTX((stderr,"non-local variable name=%s sym=%s!\n",
2963 qPrint(scopeName),sym_?qPrint(sym_->name()):"<none>"));
2964 if (sym_==nullptr && !bareName.empty())
2965 {
2966 DBG_CTX((stderr,"bareName=%s\n",qPrint(bareName)));
2967 if (bareName!=scopeName)
2968 {
2969 sym_ = yyextra->symbolResolver.resolveSymbol(parent,bareName,DString(),false,true); // try unspecialized version
2970 }
2971 }
2972 };
2973 const Definition *d = yyextra->currentDefinition;
2974 DBG_CTX((stderr,"d=%s yyextra->sourceFileDef=%s\n",d?qPrint(d->name()):"<none>",yyextra->sourceFileDef?qPrint(yyextra->sourceFileDef->name()):"<none>"));
2975 checkForSymbol(d,sym);
2976 if (sym==nullptr && d && d->definitionType()==Definition::TypeClass)
2977 {
2978 const FileDef *fd = toClassDef(d)->getFileDef();
2979 if (fd)
2980 {
2981 // also check for using directive in the file that defines this class
2982 for (const auto &nd : fd->getUsedNamespaces())
2983 {
2984 checkForSymbol(nd,sym);
2985 if (sym) break;
2986 }
2987 }
2988 }
2989 if (sym==nullptr)
2990 {
2991 // also check via using directive
2992 for (const auto &[usingName,namespaceDef] : yyextra->theUsingContext)
2993 {
2994 checkForSymbol(namespaceDef,sym);
2995 if (sym) break;
2996 }
2997 }
virtual FileDef * getFileDef() const =0
Returns the file in which this compound's definition can be found.
A model of a file symbol.
Definition filedef.h:97
virtual const LinkedRefMap< NamespaceDef > & getUsedNamespaces() const =0
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1335
2998
2999 const NamespaceDef *nd = getResolvedNamespace(scopeName);
3000 if (nd && nd->isLinkable())
3001 {
3002 yyextra->theCallContext.setScope(ScopedTypeVariant(nd));
3003 addToSearchIndex(yyscanner,scopeName);
3004 writeMultiLineCodeLink(yyscanner,*yyextra->code,nd,scName);
3005 return;
3006 }
3007 const ConceptDef *conceptDef = getResolvedConcept(d,bareName);
3008 if (conceptDef && conceptDef->isLinkable())
3009 {
3010 yyextra->theCallContext.setScope(ScopedTypeVariant(conceptDef));
3011 addToSearchIndex(yyscanner,scopeName);
3012 writeMultiLineCodeLink(yyscanner,*yyextra->code,conceptDef,scName);
3013 return;
3014 }
3015 DBG_CTX((stderr,"sym=%s\n",sym?qPrint(sym->name()):"<none>"));
3016 DBG_CTX((stderr,"is found as a type sym=%s nd=%s\n",
3017 sym?qPrint(sym->name()):"<null>",
3018 nd?qPrint(nd->name()):"<null>"));
3019 if (sym==nullptr) // also see if it is variable or enum or enum value
3020 {
3021 if (getLink(yyscanner,yyextra->scopeName,scName,ol,scName,varOnly))
3022 {
3023 return;
3024 }
3025 }
3026 }
3027 else
3028 {
3029 DBG_CTX((stderr,"local variable!\n"));
3030 if (!lcd->isDummy())
3031 {
3032 DBG_CTX((stderr,"non-dummy context lcd=%s!\n",qPrint(lcd->name())));
3033 yyextra->theCallContext.setScope(*lcd);
DString name() const
static bool getLink(yyscan_t yyscanner, const DString &className, const DString &memberName, OutputCodeList &ol, const DString &text=DString(), bool varOnly=false)
Definition code.l:2890
ConceptDef * getResolvedConcept(const Definition *d, const DString &name)
NamespaceDef * getResolvedNamespace(const DString &name)
3034
3035 // to following is needed for links to a global variable, but is
3036 // no good for a link to a local variable that is also a global symbol.
3037
3038 //if (getLink(yyscanner,yyextra->scopeName,scName,ol,scName))
3039 //{
3040 //return;
3041 //}
3042 }
3043 isLocal=true;
3044 DBG_CTX((stderr,"is a local variable sym=%p!\n",(void*)sym));
3045 }
3046 yyextra->isPrefixedWithThis = false; // discard the "this" prefix for the next calls
3047
3048 if (sym && sym->isLinkable()) // is it a linkable class
3049 {
3050 DBG_CTX((stderr,"%s is linkable type=%d\n",qPrint(sym->name()),int(sym->definitionType())));
3051 if (yyextra->exampleBlock)
3052 {
3053 std::lock_guard<std::mutex> lock(Doxygen::addExampleMutex);
3054 DString anchor;
3055 anchor.sprintf("_a%d",yyextra->anchorCount);
3056 DBG_CTX((stderr,"addExampleClass(%s,%s,%s)\n",qPrint(anchor),qPrint(yyextra->exampleName),
3057 qPrint(yyextra->exampleFile)));
3059 {
3060 ClassDefMutable *cdm = toClassDefMutable(const_cast<Definition*>(sym));
3061 if (cdm && cdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile))
3062 {
3063 ol.writeCodeAnchor(anchor);
3064 yyextra->anchorCount++;
3065 }
3066 }
3067 else if (sym->definitionType()==Definition::TypeMember)
3068 {
3069 MemberDefMutable *mdm = toMemberDefMutable(const_cast<Definition*>(sym));
3070 if (mdm && mdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile))
3071 {
3072 ol.writeCodeAnchor(anchor);
3073 yyextra->anchorCount++;
3074 }
3075 }
3076 }
3077 writeMultiLineCodeLink(yyscanner,ol,sym,scName);
3078 addToSearchIndex(yyscanner,scopeName);
3079 if (sym && sym->definitionType()==Definition::TypeMember)
3080 {
3081 const MemberDef *md = toMemberDef(sym);
3082 const Definition *d = sym->getOuterScope()==Doxygen::globalScope ?
3083 md->getFileDef() : md->getOuterScope();
3084 if (md->getGroupDef()) d = md->getGroupDef();
3085 if (d && d->isLinkable() && md->isLinkable() &&
3086 yyextra->currentMemberDef && yyextra->collectXRefs)
3087 {
3088 addDocCrossReference(yyextra->currentMemberDef,md);
3089 }
3090 setCallContextForVar(yyscanner,scName);
3091 }
3092 else
3093 {
3094 yyextra->theCallContext.setScope(ScopedTypeVariant(sym));
3095 }
3096 }
3097 else // not a class, maybe a global member
3098 {
3099 const MemberDef *md = sym && sym->definitionType()==Definition::TypeMember ? toMemberDef(sym) : nullptr;
3100 DBG_CTX((stderr,"class %s not linkable! cd=%p typeOnly=%d\n",qPrint(scName),(void*)sym,typeOnly));
3101 if (!isLocal && (md || (!sym && !typeOnly))) // not a class, see if it is a global enum/variable/typedef.
3102 {
3103 if (md==nullptr) // not found as a typedef
3104 {
3105 md = setCallContextForVar(yyscanner,scName);
3106 DBG_CTX((stderr,"setCallContextForVar(%s) md=%p yyextra->currentDefinition=%s\n",qPrint(scName),(void*)md,yyextra->currentDefinition ? qPrint(yyextra->currentDefinition->name()) : "<none>"));
3107 if (md && yyextra->currentDefinition)
3108 {
3109 DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n",
3110 qPrint(md->name()),qPrint(yyextra->currentDefinition->name()),
3111 yyextra->symbolResolver.isAccessibleFrom(yyextra->currentDefinition,md),
3112 qPrint(md->getOuterScope()->name())));
3113 }
virtual bool addExample(const DString &anchor, const DString &name, const DString &file)=0
ClassDefMutable * toClassDefMutable(Definition *d)
static const MemberDef * setCallContextForVar(yyscan_t yyscanner, const DString &name)
Definition code.l:2679
3114
3115 if (md && yyextra->currentDefinition &&
3116 yyextra->symbolResolver.isAccessibleFrom(yyextra->currentDefinition,md)==-1)
3117 {
3118 md=nullptr; // variable not accessible
3119 }
3120 }
3121 if (md && (!varOnly || md->isVariable()))
3122 {
3123 DBG_CTX((stderr,"is a global md=%p yyextra->currentDefinition=%s linkable=%d\n",(void*)md,yyextra->currentDefinition?qPrint(yyextra->currentDefinition->name()):"<none>",md->isLinkable()));
3124 if (md->isLinkable())
3125 {
3126 writeMultiLineCodeLink(yyscanner,ol,md,scName);
3127 addToSearchIndex(yyscanner,scName);
3128 if (yyextra->currentMemberDef && yyextra->collectXRefs)
3129 {
3130 addDocCrossReference(yyextra->currentMemberDef,md);
3131 }
3132 return;
3133 }
3134 }
3135 }
3136
3137 // nothing found, just write out the word
3138 DBG_CTX((stderr,"not found!\n"));
3139 codifyLines(yyscanner,scName);
3140 addToSearchIndex(yyscanner,scName);
3141 }
static void codifyLines(yyscan_t yyscanner, const DString &text)
Definition code.l:2513
3142}

References addDocCrossReference(), ClassDefMutable::addExample(), MemberDefMutable::addExample(), Doxygen::addExampleMutex, addToSearchIndex(), codifyLines(), DBG_CTX, Definition::definitionType(), DString::empty(), DString::find(), ClassDef::getFileDef(), MemberDef::getFileDef(), MemberDef::getGroupDef(), getLink(), Definition::getOuterScope(), getResolvedConcept(), getResolvedNamespace(), FileDef::getUsedNamespaces(), Doxygen::globalScope, ScopedTypeVariant::isDummy(), Definition::isLinkable(), MemberDef::isVariable(), DString::left(), DString::mid(), Definition::name(), ScopedTypeVariant::name(), DString::npos, parent(), qPrint(), setCallContextForVar(), DString::sprintf(), substitute(), toClassDef(), toClassDefMutable(), toMemberDef(), toMemberDefMutable(), Definition::TypeClass, Definition::TypeMember, OutputCodeList::writeCodeAnchor(), and writeMultiLineCodeLink().

Referenced by generateFunctionLink().

◆ generateFunctionLink()

void generateFunctionLink ( yyscan_t yyscanner,
OutputCodeList & ol,
const DString & funcName )
static

Definition at line 3354 of file code.l.

3355{
3356 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3357 //CodeClassDef *ccd=nullptr;
3358 DString locScope=yyextra->scopeName;
3359 DString locFunc=removeRedundantWhiteSpace(funcName);
3360 if (yyextra->lang==SrcLangExt::PHP && locFunc.startsWith("self::")) locFunc=locFunc.mid(4);
3361 DString funcScope;
3362 DString funcWithScope=locFunc;
3363 DString funcWithFullScope=locFunc;
3364 DString fullScope=locScope;
3365 DBG_CTX((stderr,"*** locScope=%s locFunc=%s\n",qPrint(locScope),qPrint(locFunc)));
3366 size_t len=2;
3367 size_t i=locFunc.rfind("::");
3368 if (yyextra->currentMemberDef && yyextra->currentMemberDef->resolveAlias()->getClassDef() &&
3369 funcName==yyextra->currentMemberDef->localName() &&
3370 yyextra->currentMemberDef->getDefLine()==yyextra->yyLineNr &&
3371 generateClassMemberLink(yyscanner,ol,yyextra->currentMemberDef,funcName)
3372 )
3373 {
3374 // special case where funcName is the name of a method that is also
3375 // defined on this line. In this case we can directly link to
3376 // yyextra->currentMemberDef, which is not only faster, but
3377 // in case of overloaded methods, this will make sure that we link to
3378 // the correct method, and thereby get the correct reimplemented relations.
3379 // See also bug 549022.
3380 goto exit;
3381 }
3382 if (i==DString::npos)
3383 {
3384 i=locFunc.rfind(".");
3385 len=1;
3386 }
3387 if (i==DString::npos)
3388 {
3389 i=locFunc.rfind("\\");
3390 len=1; // for PHP
3391 }
3392 if (i!=DString::npos && i>0)
3393 {
3394 funcScope=locFunc.left(i);
3395 locFunc=locFunc.mid(i+len).stripWhiteSpace();
3396 size_t ts=locScope.find('<'); // start of template
3397 size_t te=locScope.rfind('>'); // end of template
3398 DBG_CTX((stderr,"ts=%zu te=%zu\n",ts,te));
3399 if (ts!=DString::npos && te!=DString::npos && te>ts)
3400 {
3401 // remove template from scope
3402 locScope=locScope.left(ts)+locScope.mid(te+1);
3403 }
3404 ts=funcScope.find('<'); // start of template
3405 te=funcScope.rfind('>'); // end of template
3406 DBG_CTX((stderr,"ts=%zu te=%zu\n",ts,te));
3407 if (ts!=DString::npos && te!=DString::npos && te>ts)
3408 {
3409 // remove template from scope
3410 funcScope=funcScope.left(ts)+funcScope.mid(te+1);
3411 }
3412 if (!funcScope.empty())
3413 {
3414 funcWithScope = funcScope+"::"+locFunc;
3415 if (!locScope.empty())
3416 {
3417 fullScope=locScope+"::"+funcScope;
3418 }
3419 }
3420 if (!locScope.empty())
3421 {
3422 funcWithFullScope = locScope+"::"+funcWithScope;
3423 }
3424 }
size_t rfind(char c, size_t pos=npos) const
Definition dstring.h:244
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:337
bool startsWith(const char *s) const
Definition dstring.h:600
DString removeRedundantWhiteSpace(const DString &s)
Definition util.cpp:426
3425
3426 if (!fullScope.empty())
3427 {
3428 auto it = yyextra->codeClassMap.find(fullScope.str());
3429 if (it!=yyextra->codeClassMap.end())
3430 {
3431 ScopedTypeVariant ccd = it->second;
3432 if (ccd.localDef() && !ccd.localDef()->baseClasses().empty())
3433 {
3434 for (const auto &bcName : ccd.localDef()->baseClasses())
3435 {
3436 if (getLink(yyscanner,bcName,locFunc,ol,funcName))
3437 {
3438 goto exit;
3439 }
3440 }
3441 }
3442 }
3443 }
std::vector< DString > baseClasses() const
3444
3445 if (!locScope.empty() && fullScope!=locScope)
3446 {
3447 auto it = yyextra->codeClassMap.find(locScope.str());
3448 if (it!=yyextra->codeClassMap.end())
3449 {
3450 ScopedTypeVariant ccd = it->second;
3451 if (ccd.localDef() && !ccd.localDef()->baseClasses().empty())
3452 {
3453 for (const auto &bcName : ccd.localDef()->baseClasses())
3454 {
3455 if (getLink(yyscanner,bcName,funcWithScope,ol,funcName))
3456 {
3457 goto exit;
3458 }
3459 }
3460 }
3461 }
3462 }
3463 if (!getLink(yyscanner,locScope,funcWithScope,ol,funcName))
3464 {
3465 generateClassOrGlobalLink(yyscanner,ol,funcName);
3466 }
static void generateClassOrGlobalLink(yyscan_t yyscanner, OutputCodeList &ol, const DString &clName, bool typeOnly=false, bool varOnly=false)
Definition code.l:2915
3467exit:
3468 return;
3469}

References LocalDef::baseClasses(), DBG_CTX, DString::empty(), DString::find(), generateClassMemberLink(), generateClassOrGlobalLink(), getLink(), DString::left(), ScopedTypeVariant::localDef(), DString::mid(), DString::npos, qPrint(), removeRedundantWhiteSpace(), DString::rfind(), DString::startsWith(), DString::str(), and DString::stripWhiteSpace().

◆ generateMemberLink()

void generateMemberLink ( yyscan_t yyscanner,
OutputCodeList & ol,
const DString & varName,
const DString & memName )
static

Definition at line 3249 of file code.l.

3253{
3254 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3255 DBG_CTX((stderr,"generateMemberLink(object=%s,mem=%s) classScope=%s\n",
3256 qPrint(varName),qPrint(memName),qPrint(yyextra->scopeName)));
3257
3258 if (varName.empty()) return;
3259
3260 // look for the variable in the current context
3261 const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(varName);
3262 if (stv)
3263 {
3264 if (!stv->isDummy())
3265 {
3266 DBG_CTX((stderr,"Class found!\n"));
3267 if (getLink(yyscanner,stv->name(),memName,ol))
3268 {
3269 DBG_CTX((stderr,"Found result!\n"));
3270 return;
3271 }
3272 if (stv->localDef() && !stv->localDef()->baseClasses().empty())
3273 {
3274 for (const auto &bcName : stv->localDef()->baseClasses())
3275 {
3276 if (getLink(yyscanner,bcName,memName,ol))
3277 {
3278 DBG_CTX((stderr,"Found result!\n"));
3279 return;
3280 }
3281 }
3282 }
3283 }
3284 }
3285 else // variable not in current context, maybe it is in a parent context
3286 {
3287 const ClassDef *vcd = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,yyextra->scopeName,true);
3288 if (vcd && vcd->isLinkable())
3289 {
3290 DBG_CTX((stderr,"Found class %s for variable '%s'\n",qPrint(yyextra->scopeName),qPrint(varName)));
3292 if (vmn==nullptr)
3293 {
3294 DString vn=varName;
3295 if (size_t vi=vn.rfind("::"); vi!=DString::npos || (vi=vn.rfind('.'))!=DString::npos) // explicit scope A::b(), probably static member
3296 {
3297 const ClassDef *jcd = getClass(vn.left(vi));
3298 vn=vn.mid(vi+2);
3300 //printf("Trying name '%s' scope=%s\n",qPrint(vn),qPrint(scope));
3301 if (vmn)
3302 {
3303 for (const auto &vmd : *vmn)
3304 {
3305 if (vmd->getClassDef()==jcd)
3306 {
3307 DBG_CTX((stderr,"Found variable type=%s\n",qPrint(vmd->typeString())));
3308 const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope());
3309 if (mcd && mcd->isLinkable())
3310 {
3311 if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return;
3312 }
3313 }
3314 }
3315 }
3316 }
3317 }
3318 if (vmn)
3319 {
3320 DBG_CTX((stderr,"There is a variable with name '%s'\n",qPrint(varName)));
3321 for (const auto &vmd : *vmn)
3322 {
3323 if (vmd->getClassDef()==vcd)
3324 {
3325 DBG_CTX((stderr,"Found variable type=%s\n",qPrint(vmd->typeString())));
3326 const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope());
3327 if (mcd && mcd->isLinkable())
3328 {
3329 if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return;
3330 }
3331 }
3332 }
3333 }
3334 }
3335 }
3336 // nothing found -> write result as is
3337 codifyLines(yyscanner,memName);
3338 addToSearchIndex(yyscanner,memName);
3339 return;
static MemberNameLinkedMap * memberNameLinkedMap
Definition doxygen.h:104
ClassDef * getClass(const DString &n)
3340}

References addToSearchIndex(), LocalDef::baseClasses(), codifyLines(), DBG_CTX, DString::empty(), LinkedMap< T, Hash, KeyEqual, Map >::find(), generateClassMemberLink(), getClass(), getLink(), ScopedTypeVariant::isDummy(), Definition::isLinkable(), DString::left(), ScopedTypeVariant::localDef(), Doxygen::memberNameLinkedMap, DString::mid(), ScopedTypeVariant::name(), DString::npos, qPrint(), DString::rfind(), and stripClassName().

◆ generatePHPVariableLink()

void generatePHPVariableLink ( yyscan_t yyscanner,
OutputCodeList & ol,
const char * varName )
static

Definition at line 3342 of file code.l.

3343{
3344 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3345 DString name(varName+7); // strip $this->
3346 name.prepend("$");
3347 DBG_CTX((stderr,"generatePHPVariableLink(%s) name=%s scope=%s\n",varName,qPrint(name),qPrint(yyextra->scopeName)));
3348 if (!getLink(yyscanner,yyextra->scopeName,name,ol,varName))
3349 {
3350 codifyLines(yyscanner,varName);
3351 }
3352}

References codifyLines(), DBG_CTX, getLink(), DString::prepend(), and qPrint().

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 260 of file code.l.

260{return __FILE__;}

◆ getLink()

bool getLink ( yyscan_t yyscanner,
const DString & className,
const DString & memberName,
OutputCodeList & ol,
const DString & text = DString(),
bool varOnly = false )
static

Definition at line 2890 of file code.l.

2896{
2897 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2898 DBG_CTX((stderr,"getLink(%s,%s) yyextra->curClassName=%s\n",
2899 qPrint(className),qPrint(memberName),qPrint(yyextra->curClassName)));
2900 DString m=removeRedundantWhiteSpace(memberName);
2901 DString c=className;
2902 if (!getLinkInScope(yyscanner,c,m,memberName,ol,text,varOnly))
2903 {
2904 if (!yyextra->curClassName.empty())
2905 {
2906 if (!c.empty()) c.prepend("::");
2907 c.prepend(yyextra->curClassName);
2908 return getLinkInScope(yyscanner,c,m,memberName,ol,text,varOnly);
2909 }
2910 return false;
2911 }
2912 return true;
DString & prepend(const char *s)
Definition dstring.h:515
static bool getLinkInScope(yyscan_t yyscanner, const DString &c, const DString &m, const DString &memberText, OutputCodeList &ol, const DString &text, bool varOnly=false)
Definition code.l:2806
2913}

References DBG_CTX, DString::empty(), getLinkInScope(), DString::prepend(), qPrint(), and removeRedundantWhiteSpace().

Referenced by generateClassOrGlobalLink(), generateFunctionLink(), generateMemberLink(), and generatePHPVariableLink().

◆ getLinkInScope()

bool getLinkInScope ( yyscan_t yyscanner,
const DString & c,
const DString & m,
const DString & memberText,
OutputCodeList & ol,
const DString & text,
bool varOnly = false )
static

Definition at line 2806 of file code.l.

2814{
2815 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2816 DBG_CTX((stderr,"getLinkInScope: trying '%s'::'%s' varOnly=%d\n",qPrint(c),qPrint(m),varOnly));
2817 GetDefInput input(c,m,"()");
2818 input.currentFile = yyextra->sourceFileDef;
2819 input.insideCode = true;
2820 GetDefResult result = getDefs(input);
2821 DBG_CTX((stderr,"scopeNameLengthStack.size()=%zu\n",yyextra->scopeNameLengthStack.size()));
2822 if (!result.found && !yyextra->scopeNameLengthStack.empty() && c==yyextra->scopeName)
2823 {
2824 DString localName = yyextra->scopeName.mid(yyextra->scopeNameLengthStack[0]+2); // try also without leading scope
2825 auto it = yyextra->codeClassMap.find(localName.str());
2826 if (it!=yyextra->codeClassMap.end())
2827 {
2828 ScopedTypeVariant ccd = it->second;
2829 if (ccd.localDef() && !ccd.localDef()->baseClasses().empty())
2830 {
2831 for (const auto &bcName : ccd.localDef()->baseClasses())
2832 {
2833 DBG_CTX((stderr,"trying lookup via base class %s\n",qPrint(bcName)));
2834 input.scopeName = bcName;
2835 result = getDefs(input);
2836 if (result.found) break;
2837 }
2838 }
2839 }
2840 }
2841 if (result.found && result.md && (!varOnly || result.md->isVariable()))
2842 {
2843 if (result.md->isLinkable())
2844 {
2845 DBG_CTX((stderr,"found it %s!\n",qPrint(result.md->qualifiedName())));
2846 if (yyextra->exampleBlock)
2847 {
2848 std::lock_guard<std::mutex> lock(Doxygen::addExampleMutex);
2849 DString anchor;
2850 anchor.sprintf("a%d",yyextra->anchorCount);
2851 DBG_CTX((stderr,"addExampleFile(%s,%s,%s)\n",qPrint(anchor),qPrint(yyextra->exampleName),
2852 qPrint(yyextra->exampleFile)));
2853 MemberDefMutable *mdm = toMemberDefMutable(const_cast<MemberDef*>(result.md));
2854 if (mdm && mdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile))
2855 {
2856 ol.writeCodeAnchor(anchor);
2857 yyextra->anchorCount++;
2858 }
2859 }
virtual DString qualifiedName() const =0
virtual bool isVariable() const =0
const MemberDef * md
Definition util.h:95
bool found
Definition util.h:94
GetDefResult getDefs(const GetDefInput &input)
Definition util.cpp:1866
2860
2861 const Definition *d = result.md->getOuterScope()==Doxygen::globalScope ?
2862 result.md->resolveAlias()->getFileDef() : result.md->getOuterScope();
2863 if (result.md->resolveAlias()->getGroupDef()) d = result.md->resolveAlias()->getGroupDef();
2864 if (d && d->isLinkable())
2865 {
2866 const ClassDef *ncd = stripClassName(yyscanner,result.md->typeString(),result.md->getOuterScope());
2867 if (ncd)
2868 {
2869 yyextra->theCallContext.setScope(ScopedTypeVariant(ncd));
2870 }
2871 DBG_CTX((stderr,"yyextra->currentDefinition=%p yyextra->currentMemberDef=%p yyextra->insideBody=%d\n",
2872 (void*)yyextra->currentDefinition,(void*)yyextra->currentMemberDef,yyextra->insideBody));
virtual MemberDef * resolveAlias()=0
2873
2874 if (yyextra->currentDefinition && yyextra->currentMemberDef &&
2875 yyextra->insideBody && yyextra->collectXRefs)
2876 {
2877 addDocCrossReference(yyextra->currentMemberDef,result.md);
2878 }
2879 DBG_CTX((stderr,"d->getReference()='%s' d->getOutputBase()='%s' name='%s' member name='%s'\n",qPrint(d->getReference()),qPrint(d->getOutputFileBase()),qPrint(d->name()),qPrint(result.md->name())));
virtual DString getReference() const =0
virtual DString getOutputFileBase() const =0
2880
2881 writeMultiLineCodeLink(yyscanner,ol,result.md, !text.empty() ? text : memberText);
2882 addToSearchIndex(yyscanner,!text.empty() ? text : memberText);
2883 return true;
2884 }
2885 }
2886 }
2887 return false;
2888}

References addDocCrossReference(), MemberDefMutable::addExample(), Doxygen::addExampleMutex, addToSearchIndex(), LocalDef::baseClasses(), GetDefInput::currentFile, DBG_CTX, DString::empty(), DString::find(), GetDefResult::found, getDefs(), MemberDef::getFileDef(), MemberDef::getGroupDef(), Definition::getOuterScope(), Definition::getOutputFileBase(), Definition::getReference(), Doxygen::globalScope, GetDefInput::insideCode, Definition::isLinkable(), MemberDef::isVariable(), ScopedTypeVariant::localDef(), GetDefResult::md, DString::mid(), Definition::name(), qPrint(), Definition::qualifiedName(), MemberDef::resolveAlias(), GetDefInput::scopeName, DString::sprintf(), DString::str(), stripClassName(), toMemberDefMutable(), MemberDef::typeString(), OutputCodeList::writeCodeAnchor(), and writeMultiLineCodeLink().

Referenced by getLink().

◆ incrementFlowKeyWordCount()

void incrementFlowKeyWordCount ( yyscan_t yyscanner)
static

Definition at line 2540 of file code.l.

2541{
2542 std::lock_guard<std::mutex> lock(Doxygen::countFlowKeywordsMutex);
2543 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2544 if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction())
2545 {
2546 MemberDefMutable *md = toMemberDefMutable(const_cast<MemberDef*>(yyextra->currentMemberDef));
2547 if (md)
2548 {
2550 }
2551 }
static std::mutex countFlowKeywordsMutex
Definition doxygen.h:132
virtual void incrementFlowKeyWordCount()=0
2552}

References Doxygen::countFlowKeywordsMutex, MemberDefMutable::incrementFlowKeyWordCount(), and toMemberDefMutable().

◆ isCastKeyword()

bool isCastKeyword ( const char * s)
static

Definition at line 3972 of file code.l.

3973{
3974 DString s(keyword);
3975 size_t i=s.find('<');
3976 if (i==DString::npos) return false;
3977 DString kw = s.left(i).stripWhiteSpace();
3978 return kw=="const_cast" || kw=="static_cast" || kw=="dynamic_cast" || kw=="reinterpret_cast";
3979}

References DString::find(), DString::left(), DString::npos, and DString::stripWhiteSpace().

◆ nextCodeLine()

void nextCodeLine ( yyscan_t yyscanner)
static

Definition at line 2495 of file code.l.

2496{
2497 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2498 const char * fc = yyextra->currentFontClass;
2499 if (yyextra->insideCodeLine)
2500 {
2501 endCodeLine(yyscanner);
2502 }
2503 if (yyextra->yyLineNr<yyextra->inputLines)
2504 {
2505 yyextra->currentFontClass = fc;
2506 startCodeLine(yyscanner);
2507 }
static void endCodeLine(yyscan_t yyscanner)
Definition code.l:2486
static void startCodeLine(yyscan_t yyscanner)
Definition code.l:2417
2508}

References endCodeLine(), and startCodeLine().

Referenced by codifyLines(), codifyLines(), and writeMultiLineCodeLink().

◆ popScope()

void popScope ( yyscan_t yyscanner)
static

remove the top class/namespace name from the scope

Definition at line 2269 of file code.l.

2270{
2271 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2272 if (!yyextra->scopeNameLengthStack.empty())
2273 {
2274 int length = yyextra->scopeNameLengthStack.back();
2275 yyextra->scopeNameLengthStack.pop_back();
2276 yyextra->scopeName.resize(length);
2277 }
2278 else
2279 {
2280 //err("Too many end of scopes found!\n");
2281 }
2282 DBG_CTX((stderr,"popScope() result: '%s'\n",qPrint(yyextra->scopeName)));
2283}

References DBG_CTX, and qPrint().

Referenced by setClassScope().

◆ pushScope()

void pushScope ( yyscan_t yyscanner,
const DString & s )
static

add class/namespace name s to the scope

Definition at line 2251 of file code.l.

2252{
2253 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2254 yyextra->scopeNameLengthStack.push_back(int(yyextra->scopeName.length()));
2255 if (yyextra->scopeName.empty() || leftScopeMatch(s,yyextra->scopeName))
2256 {
2257 yyextra->scopeName = s;
2258 }
2259 else
2260 {
2261 yyextra->scopeName += "::";
2262 yyextra->scopeName += s;
2263 }
2264 DBG_CTX((stderr,"pushScope(%s) result: '%s'\n",qPrint(s),qPrint(yyextra->scopeName)));
bool leftScopeMatch(const DString &scope, const DString &name)
Definition util.cpp:740
2265}

References DBG_CTX, leftScopeMatch(), and qPrint().

Referenced by setClassScope().

◆ restoreObjCContext()

void restoreObjCContext ( yyscan_t yyscanner)
static

Definition at line 4028 of file code.l.

4029{
4030 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4031 DBG_CTX((stderr,"restore state=%d->%d\n",YY_START,yyextra->currentCtx->lexState));
4032 BEGIN(yyextra->currentCtx->lexState);
4033 yyextra->braceCount = yyextra->currentCtx->braceCount;
4034 if (!yyextra->contextStack.empty())
4035 {
4036 yyextra->currentCtx = yyextra->contextStack.top();
4037 yyextra->contextStack.pop();
4038 }
4039 else
4040 {
4041 yyextra->currentCtx = nullptr;
4042 DBG_CTX((stderr,"Trying to pop context while yyextra->contextStack is empty!\n"));
4043 }
4044}

References DBG_CTX.

◆ saveObjCContext()

void saveObjCContext ( yyscan_t yyscanner)
static

Definition at line 3997 of file code.l.

3998{
3999 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4000 if (yyextra->currentCtx)
4001 {
4002 yyextra->currentCtx->format+=DString().sprintf("$c%d",yyextra->currentCtxId);
4003 if (yyextra->braceCount==0 && YY_START==ObjCCall)
4004 {
4005 yyextra->currentCtx->objectTypeOrName=yyextra->currentCtx->format.mid(1);
4006 DBG_CTX((stderr,"new type=%s\n",qPrint(yyextra->currentCtx->objectTypeOrName)));
4007 }
4008 yyextra->contextStack.push(yyextra->currentCtx);
4009 }
4010 else
4011 {
4012 DBG_CTX((stderr,"Trying to save NULL context!\n"));
4013 }
4014 auto newCtx = std::make_unique<ObjCCallCtx>();
4015 newCtx->id = yyextra->currentCtxId;
4016 newCtx->lexState = YY_START;
4017 newCtx->braceCount = yyextra->braceCount;
4018 newCtx->objectType = nullptr;
4019 newCtx->objectVar = nullptr;
4020 newCtx->method = nullptr;
4021 DBG_CTX((stderr,"save state=%d\n",YY_START));
4022 yyextra->currentCtx = newCtx.get();
4023 yyextra->contextMap.emplace(yyextra->currentCtxId,std::move(newCtx));
4024 yyextra->braceCount = 0;
4025 yyextra->currentCtxId++;
4026}

References DBG_CTX, qPrint(), and DString::sprintf().

◆ setCallContextForVar()

const MemberDef * setCallContextForVar ( yyscan_t yyscanner,
const DString & name )
static

Definition at line 2679 of file code.l.

2680{
2681 if (name.empty()) return nullptr;
2682 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2683 DBG_CTX((stderr,"setCallContextForVar(%s) yyextra->scopeName=%s\n",qPrint(name),qPrint(yyextra->scopeName)));
2684
2685 size_t scopeEnd = name.rfind("::");
2686 if (scopeEnd!=DString::npos) // name with explicit scope
2687 {
2688 DString scope = name.left(scopeEnd);
2689 DString locName = name.mid(scopeEnd+2);
2690 DBG_CTX((stderr,"explicit scope: name=%s scope=%s\n",qPrint(locName),qPrint(scope)));
2691 const ClassDef *mcd = getClass(scope);
2692 if (mcd && !locName.empty())
2693 {
2694 const MemberDef *md=mcd->getMemberByName(locName);
2695 if (md)
2696 {
2697 DBG_CTX((stderr,"name=%s scope=%s\n",qPrint(locName),qPrint(scope)));
2698 yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope())));
2699 return md;
2700 }
2701 }
2702 else // check namespace as well
2703 {
2704 const NamespaceDef *mnd = getResolvedNamespace(scope);
2705 if (mnd && !locName.empty())
2706 {
2707 const MemberDef *md=mnd->getMemberByName(locName);
2708 if (md)
2709 {
2710 DBG_CTX((stderr,"name=%s scope=%s\n",qPrint(locName),qPrint(scope)));
2711 yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope())));
2712 return md;
2713 }
2714 }
2715 }
2716 }
virtual const MemberDef * getMemberByName(const DString &) const =0
2717
2718 const ScopedTypeVariant *mcv = yyextra->theVarContext.findVariable(name);
2719 if (mcv)
2720 {
2721 DBG_CTX((stderr,"local variable?\n"));
2722 if (!mcv->isDummy()) // locally found variable
2723 {
2724 DBG_CTX((stderr,"local var '%s' mcd=%s\n",qPrint(name),qPrint(mcv->name())));
2725 yyextra->theCallContext.setScope(*mcv);
2726 }
2727 }
2728 else
2729 {
2730 DBG_CTX((stderr,"class member? scope=%s\n",qPrint(yyextra->scopeName)));
2731 // look for a class member
2732 const ClassDef *mcd = getClass(yyextra->scopeName);
2733 if (mcd)
2734 {
2735 DBG_CTX((stderr,"Inside class %s\n",qPrint(mcd->name())));
2736 const MemberDef *md=mcd->getMemberByName(name);
2737 if (md)
2738 {
2739 DBG_CTX((stderr,"Found member %s\n",qPrint(md->name())));
2740 if (yyextra->scopeStack.empty() || yyextra->scopeStack.top()!=CLASSBLOCK)
2741 {
2742 DBG_CTX((stderr,"class member '%s' mcd=%s\n",qPrint(name),qPrint(mcd->name())));
2743 yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope())));
2744 }
2745 return md;
2746 }
2747 }
2748 }
#define CLASSBLOCK
Definition code.l:74
2749
2750 // look for a global member
2752 if (mn)
2753 {
2754 DBG_CTX((stderr,"global var '%s'\n",qPrint(name)));
2755 if (mn->size()==1) // global defined only once
2756 {
2757 const std::unique_ptr<MemberDef> &md=mn->front();
2758 if (!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef)
2759 {
2760 yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope())));
2761 return md.get();
2762 }
2763 return nullptr;
2764 }
2765 else if (mn->size()>1) // global defined more than once
2766 {
2767 for (const auto &md : *mn)
2768 {
2769 //printf("mn=%p md=%p md->getBodyDef()=%p yyextra->sourceFileDef=%p\n",
2770 // mn,md,
2771 // md->getBodyDef(),yyextra->sourceFileDef);
static MemberNameLinkedMap * functionNameLinkedMap
Definition doxygen.h:105
Ptr & front()
Definition membername.h:49
size_t size() const
Definition membername.h:46
2772
2773 // in case there are multiple members we could link to, we
2774 // only link to members if defined in the same file or
2775 // defined as external.
2776 if (!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef)
2777 {
2778 yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope())));
2779 DBG_CTX((stderr,"returning member %s in source file %s\n",qPrint(md->name()),qPrint(yyextra->sourceFileDef->name())));
2780 return md.get();
2781 }
2782 }
2783 return nullptr;
2784 }
2785 }
2786 return nullptr;
2787}

References CLASSBLOCK, DBG_CTX, DString::empty(), LinkedMap< T, Hash, KeyEqual, Map >::find(), MemberName::front(), Doxygen::functionNameLinkedMap, getClass(), ClassDef::getMemberByName(), NamespaceDef::getMemberByName(), Definition::getOuterScope(), getResolvedNamespace(), ScopedTypeVariant::isDummy(), DString::left(), DString::mid(), Definition::name(), ScopedTypeVariant::name(), DString::npos, qPrint(), DString::rfind(), MemberName::size(), stripClassName(), and MemberDef::typeString().

Referenced by generateClassOrGlobalLink().

◆ setClassScope()

void setClassScope ( yyscan_t yyscanner,
const DString & name )
static

Definition at line 2309 of file code.l.

2310{
2311 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2312 DBG_CTX((stderr,"setClassScope(%s)\n",qPrint(name)));
2313 DString n=name;
2314 n=n.simplifyWhiteSpace();
2315 size_t ts=n.find('<'); // start of template
2316 size_t te=n.rfind('>'); // end of template
2317 DBG_CTX((stderr,"ts=%zu te=%zu\n",ts,te));
2318 if (ts!=DString::npos && te!=DString::npos && te>ts)
2319 {
2320 // remove template from scope
2321 n=n.left(ts)+n.mid(te+1);
2322 }
2323 while (!yyextra->scopeNameLengthStack.empty())
2324 {
2325 popScope(yyscanner);
2326 }
2327 yyextra->scopeName.clear();
2328 size_t i;
2329 while ((i=n.find("::"))!=DString::npos)
2330 {
2331 pushScope(yyscanner,n.left(i));
2332 n = n.mid(i+2);
2333 }
2334 pushScope(yyscanner,n);
2335 DBG_CTX((stderr,"--->New class scope '%s'\n",qPrint(yyextra->scopeName)));
static void pushScope(yyscan_t yyscanner, const DString &s)
Definition code.l:2251
static void popScope(yyscan_t yyscanner)
Definition code.l:2269
2336}

References DBG_CTX, DString::find(), DString::left(), DString::mid(), DString::npos, popScope(), pushScope(), qPrint(), DString::rfind(), and DString::simplifyWhiteSpace().

◆ setCurrentDoc()

void setCurrentDoc ( yyscan_t yyscanner,
const DString & anchor )
static

Definition at line 2285 of file code.l.

2286{
2287 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2288 if (Doxygen::searchIndex.enabled())
2289 {
2290 if (yyextra->searchCtx)
2291 {
2292 Doxygen::searchIndex.setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false);
2293 }
2294 else
2295 {
2296 Doxygen::searchIndex.setCurrentDoc(yyextra->sourceFileDef,anchor,true);
2297 }
2298 }
void setCurrentDoc(const Definition *ctx, const DString &anchor, bool isSourceFile)
2299}

References Doxygen::searchIndex, and SearchIndexIntf::setCurrentDoc().

Referenced by CCodeParser::parseCode(), startCodeLine(), and startCodeLine().

◆ setParameterList()

void setParameterList ( yyscan_t yyscanner,
const MemberDef * md )
static

Definition at line 2631 of file code.l.

2632{
2633 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2634 for (const Argument &a : md->argumentList())
2635 {
2636 yyextra->parmName = a.name;
2637 yyextra->parmType = a.type;
2638 size_t i = yyextra->parmType.find('*');
2639 if (i!=DString::npos) yyextra->parmType = yyextra->parmType.left(i);
2640 i = yyextra->parmType.find('&');
2641 if (i!=DString::npos) yyextra->parmType = yyextra->parmType.left(i);
2642 yyextra->parmType.stripPrefix("const ");
2643 yyextra->parmType=yyextra->parmType.stripWhiteSpace();
2644 addVariable(yyscanner,yyextra->parmType,yyextra->parmName);
2645 }
This class contains the information about the argument of a function or template.
Definition arguments.h:27
virtual const ArgumentList & argumentList() const =0
2646}

References addVariable(), MemberDef::argumentList(), and DString::npos.

Referenced by CCodeParser::parseCode().

◆ skipLanguageSpecificKeyword()

bool skipLanguageSpecificKeyword ( yyscan_t yyscanner,
const char * kw )
static

Definition at line 3931 of file code.l.

3932{
3933 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3934 static const std::unordered_set<std::string> non_cpp_keywords = {
3935 "__assume", "__super", "abstract", "function",
3936 "gcnew", "gcroot", "generic", "get",
3937 "internal", "null", "pin_ptr", "raise",
3938 "remove", "self", "set", "transient",
3939 "sealed"
3940 };
3941 static const std::unordered_set<std::string> non_java_keywords = {
3942 "alignas", "alignof", "and", "and_eq", "asm",
3943 "atomic_cancel", "atomic_commit", "atomic_noexcept", "auto", "bitand",
3944 "bitor", "bool", "char8_t", "char16_t", "char32_t",
3945 "compl", "concept", "consteval", "constexpr", "constinit",
3946 "const_cast", "co_await", "co_return", "co_yield", "decltype",
3947 "delete", "dynamic_cast", "explicit", "export", "extern",
3948 "friend", "inline", "mutable", "namespace", "noexcept",
3949 "not", "not_eq", "nullptr", "operator", "or",
3950 "or_eq", "reflexpr", "register", "reinterpret_cast", "requires",
3951 "signed", "sizeof", "static_assert", "_Static_assert", "static_cast", "struct",
3952 "template", "thread_local", "typedef", "typeid", "typename",
3953 "union", "unsigned", "using", "virtual", "wchar_t",
3954 "xor", "xor_eq", "override", "sealed"
3955 };
3956 bool retval = false;
3957 switch (yyextra->lang)
3958 {
3959 case SrcLangExt::Cpp:
3960 retval = (non_cpp_keywords.find(keyword) != non_cpp_keywords.end());
3961 break;
3962 case SrcLangExt::Java:
3963 retval = (non_java_keywords.find(keyword) != non_java_keywords.end());
3964 break;
3965 default:
3966 retval = false;
3967 break;
3968 }
3969 return retval;
3970}

◆ startCodeLine()

void startCodeLine ( yyscan_t yyscanner)
static

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.

Definition at line 2417 of file code.l.

2418{
2419 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2420 //if (yyextra->currentFontClass) { yyextra->code->endFontClass(yyscanner); }
2421 if (yyextra->sourceFileDef && yyextra->lineNumbers)
2422 {
2423 //DString lineNumber,lineAnchor;
2424 //lineNumber.sprintf("%05d",yyextra->yyLineNr);
2425 //lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
2426
2427 const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr);
2428 //printf("%s:startCodeLine(%d)=%p\n",qPrint(yyextra->sourceFileDef->name()),yyextra->yyLineNr,(void*)d);
2429 DBG_CTX((stderr,"%s:startCodeLine(%d)=%p\n",qPrint(yyextra->sourceFileDef->name()),yyextra->yyLineNr,(void*)d));
2430 if (!yyextra->includeCodeFragment && d)
2431 {
2432 yyextra->currentDefinition = d;
2433 yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr);
2434 yyextra->insideBody = false;
2435 yyextra->searchingForBody = true;
2436 yyextra->realScope = d!=Doxygen::globalScope ? d->name() : "";
2437 yyextra->type.clear();
2438 yyextra->name.clear();
2439 yyextra->args.clear();
2440 yyextra->parmType.clear();
2441 yyextra->parmName.clear();
2442 DBG_CTX((stderr,"Real scope: '%s'\n",qPrint(yyextra->realScope)));
2443 yyextra->bodyCurlyCount = 0;
2444 DString lineAnchor;
2445 lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
2446 if (yyextra->currentMemberDef)
2447 {
2448 codeFolding(yyscanner,yyextra->currentMemberDef);
2449 yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
2450 yyextra->currentMemberDef->getOutputFileBase(),
2451 yyextra->currentMemberDef->anchor(),
2452 yyextra->yyLineNr,!yyextra->includeCodeFragment);
2453 setCurrentDoc(yyscanner,lineAnchor);
2454 }
2455 else if (d->isLinkableInProject())
2456 {
2457 codeFolding(yyscanner,d);
2458 yyextra->code->writeLineNumber(d->getReference(),
2459 d->getOutputFileBase(),
2460 DString(),yyextra->yyLineNr,!yyextra->includeCodeFragment);
2461 setCurrentDoc(yyscanner,lineAnchor);
2462 }
2463 else
2464 {
2465 codeFolding(yyscanner,nullptr);
2466 }
2467 }
2468 else
2469 {
2470 codeFolding(yyscanner,nullptr);
2471 yyextra->code->writeLineNumber(DString(),DString(),DString(),yyextra->yyLineNr,
2472 !yyextra->includeCodeFragment);
2473 }
2474 }
2475 DBG_CTX((stderr,"startCodeLine(%d)\n",yyextra->yyLineNr));
2476 yyextra->code->startCodeLine(yyextra->yyLineNr);
2477 yyextra->insideCodeLine = true;
2478 if (yyextra->currentFontClass)
2479 {
2480 yyextra->code->startFontClass(yyextra->currentFontClass);
2481 }
void clear()
Definition dstring.h:214
virtual bool isLinkableInProject() const =0
static void setCurrentDoc(yyscan_t yyscanner, const DString &anchor)
Definition code.l:2285
static void codeFolding(yyscan_t yyscanner, const Definition *d)
Definition code.l:2359
2482}

References DString::clear(), codeFolding(), DBG_CTX, Definition::getOutputFileBase(), Definition::getReference(), Doxygen::globalScope, Definition::isLinkableInProject(), Definition::name(), qPrint(), setCurrentDoc(), and DString::sprintf().

Referenced by nextCodeLine(), nextCodeLine(), and CCodeParser::parseCode().

◆ startFontClass()

void startFontClass ( yyscan_t yyscanner,
const char * s,
bool specialComment = false )
static

Definition at line 3505 of file code.l.

3506{
3507 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3508 endFontClass(yyscanner);
3509 if (specialComment)
3510 {
3511 yyextra->code->startSpecialComment();
3512 yyextra->insideSpecialComment = true;
3513 }
3514 yyextra->code->startFontClass(s);
3515 yyextra->currentFontClass=s;
3516}

References endFontClass().

Referenced by writeObjCMethodCall().

◆ startsWithKeyword()

bool startsWithKeyword ( const DString & str,
const DString & kw )
static

Definition at line 2180 of file code.l.

2181{
2182 if (str.length()<kw.length()) return false; // string too short to match
2183 return str==kw || // exact match
2184 (str.startsWith(kw) && !isId(str.at(kw.length()))); // match that is not a substring
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:686
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
bool isId(char c)
Returns true if c is a valid character for an identifier.
Definition dstring.h:895
2185}

References DString::at(), isId(), DString::length(), and DString::startsWith().

◆ stateToString()

const char * stateToString ( int state)
static

◆ stripClassName()

const ClassDef * stripClassName ( yyscan_t yyscanner,
const DString & s,
const Definition * d )
static

Definition at line 2648 of file code.l.

2649{
2650 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2651 DBG_CTX((stderr,"stripClassName(scope=%s,type=%s) scopeName=%s\n",
2652 qPrint(d?d->name():""),qPrint(s),qPrint(yyextra->scopeName)));
2653 int pos=0;
2654 DString type = s;
2655 DString className;
2656 DString templSpec;
2657 while (extractClassNameFromType(type,pos,className,templSpec)!=-1)
2658 {
2659 DString clName=className+templSpec;
2660 const ClassDef *cd=nullptr;
2661 if (!yyextra->scopeName.empty())
2662 {
2663 cd=yyextra->symbolResolver.resolveClass(d,yyextra->scopeName+"::"+clName,true);
2664 }
2665 if (cd==nullptr)
2666 {
2667 cd=yyextra->symbolResolver.resolveClass(d,clName,true);
2668 }
2669 DBG_CTX((stderr,"stripClass trying '%s' = %p\n",qPrint(clName),(void*)cd));
2670 if (cd)
2671 {
2672 return cd;
2673 }
2674 }
int extractClassNameFromType(const DString &type, int &pos, DString &name, DString &templSpec, SrcLangExt lang)
Definition util.cpp:3380
2675
2676 return nullptr;
2677}

References DBG_CTX, extractClassNameFromType(), Definition::name(), and qPrint().

Referenced by generateClassMemberLink(), generateMemberLink(), getLinkInScope(), setCallContextForVar(), updateCallContextForSmartPointer(), and writeObjCMethodCall().

◆ updateCallContextForSmartPointer()

void updateCallContextForSmartPointer ( yyscan_t yyscanner)
static

Definition at line 2789 of file code.l.

2790{
2791 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2792 const Definition *d = yyextra->theCallContext.getScope().globalDef();
2793 //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? qPrint(d->name()) : "<none>");
2794 const MemberDef *md = nullptr;
2795 if (d && d->definitionType()==Definition::TypeClass && (md=(toClassDef(d))->isSmartPointer()))
2796 {
2797 const ClassDef *ncd = stripClassName(yyscanner,md->typeString(),md->getOuterScope());
2798 if (ncd)
2799 {
2800 yyextra->theCallContext.setScope(ScopedTypeVariant(ncd));
2801 //printf("Found smart pointer call %s->%s!\n",qPrint(cd->name()),qPrint(ncd->name()));
2802 }
2803 }
2804}

References Definition::definitionType(), Definition::getOuterScope(), stripClassName(), toClassDef(), Definition::TypeClass, and MemberDef::typeString().

◆ writeMultiLineCodeLink()

void writeMultiLineCodeLink ( yyscan_t yyscanner,
OutputCodeList & ol,
const Definition * d,
const DString & text )
static

writes a link to a fragment text that may span multiple lines, inserting line numbers for each line. If text contains newlines, the link will be split into multiple links with the same destination, one for each line.

Definition at line 2558 of file code.l.

2561{
2562 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2563 bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
2564 yyextra->tooltipManager.addTooltip(d);
2565 DString ref = d->getReference();
2566 DString file = d->getOutputFileBase();
2567 DString anchor = d->anchor();
2568 DString tooltip;
2569 if (!sourceTooltips) // fall back to simple "title" tooltips
2570 {
2571 tooltip = d->briefDescriptionAsTooltip();
2572 }
2573 bool done=false;
2574 const char *p=text.data();
2575 while (!done)
2576 {
2577 const char *sp=p;
2578 char c = 0;
2579 while ((c=*p++) && c!='\n') { }
2580 if (c=='\n')
2581 {
2582 yyextra->yyLineNr++;
2583 DBG_CTX((stderr,"writeCodeLink(%s,%s,%s,%s)\n",qPrint(ref),qPrint(file),qPrint(anchor),qPrint(DString(sp,p-sp-1))));
2584 ol.writeCodeLink(d->codeSymbolType(),ref,file,anchor,DString(sp,p-sp-1),tooltip);
2585 nextCodeLine(yyscanner);
2586 }
2587 else
2588 {
2589 DBG_CTX((stderr,"writeCodeLink(%s,%s,%s,%s)\n",qPrint(ref),qPrint(file),qPrint(anchor),sp));
2590 ol.writeCodeLink(d->codeSymbolType(),ref,file,anchor,sp,tooltip);
2591 done=true;
2592 }
2593 }
virtual DString briefDescriptionAsTooltip() const =0
virtual DString anchor() const =0
virtual CodeSymbolType codeSymbolType() const =0
void writeCodeLink(CodeSymbolType type, const DString &ref, const DString &file, const DString &anchor, const DString &name, const DString &tooltip)
Definition outputlist.h:247
2594}

References Definition::anchor(), Definition::briefDescriptionAsTooltip(), Definition::codeSymbolType(), Config_getBool, DString::data(), DBG_CTX, Definition::getOutputFileBase(), Definition::getReference(), nextCodeLine(), qPrint(), and OutputCodeList::writeCodeLink().

Referenced by generateClassMemberLink(), generateClassMemberLink(), generateClassOrGlobalLink(), getLinkInScope(), and writeObjCMethodCall().

◆ writeObjCMethodCall()

void writeObjCMethodCall ( yyscan_t yyscanner,
ObjCCallCtx * ctx )
static

Definition at line 3521 of file code.l.

3522{
3523 if (ctx==nullptr) return;
3524 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3525 char c = 0;
3526 if (!ctx->methodName.empty())
3527 {
3528 DBG_CTX((stderr,"writeObjCMethodCall(%s) obj=%s method=%s\n",
3530 if (!ctx->objectTypeOrName.empty() && ctx->objectTypeOrName.at(0)!='$')
3531 {
3532 DBG_CTX((stderr,"Looking for object=%s method=%s\n",qPrint(ctx->objectTypeOrName),
3533 qPrint(ctx->methodName)));
3534 const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(ctx->objectTypeOrName);
3535 if (stv!=nullptr) // local variable
3536 {
3537 DBG_CTX((stderr," object is local variable\n"));
3538 if (stv->globalDef() && !ctx->methodName.empty())
3539 {
3540 const ClassDef *cd = toClassDef(stv->globalDef());
3541 if (cd)
3542 {
3543 ctx->method = cd->getMemberByName(ctx->methodName);
3544 }
3545 DBG_CTX((stderr," class=%p method=%p\n",(void*)cd,(void*)ctx->method));
3546 }
3547 }
3548 }
3549 }
const Definition * globalDef() const
const MemberDef * method
Definition code.l:87
DString methodName
Definition code.l:82
DString objectTypeOrName
Definition code.l:83
DString format
Definition code.l:88
3550
3551 DBG_CTX((stderr,"["));
3552 if (!ctx->format.empty())
3553 {
3554 const char *p = ctx->format.data();
3555 bool skip = false;
3556 char skipChar = ' ';
3557 while ((c=*p++)) // for each character in ctx->format
3558 {
3559 if (skip)
3560 {
3561 char s[2];
3562 s[0]=c;s[1]=0;
3563 codifyLines(yyscanner,s);
3564 if (c==skipChar)
3565 {
3566 skip = false;
3567 skipChar = ' ';
3568 }
3569 else if (c=='\\')
3570 {
3571 c = *p++;
3572 s[0]=c;
3573 codifyLines(yyscanner,s);
3574 }
3575 }
3576 else if (c=='$')
3577 {
3578 char nc=*p++;
3579 if (nc=='$') // escaped $
3580 {
3581 yyextra->code->codify("$");
3582 }
3583 else // name fragment or reference to a nested call
3584 {
3585 if (nc=='n') // name fragment
3586 {
3587 nc=*p++;
3588 DString refIdStr;
3589 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
3590 p--;
3591 int refId=refIdStr.toInt();
3592 auto it = yyextra->nameMap.find(refId);
3593 if (it!=yyextra->nameMap.end())
3594 {
3595 DString name = it->second;
3596 if (ctx->method && ctx->method->isLinkable())
3597 {
3598 writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->method,name);
3599 if (yyextra->currentMemberDef && yyextra->collectXRefs)
3600 {
3601 addDocCrossReference(yyextra->currentMemberDef,ctx->method);
3602 }
3603 }
3604 else
3605 {
3606 codifyLines(yyscanner,name);
3607 }
3608 }
3609 else
3610 {
3611 DBG_CTX((stderr,"Invalid name: id=%d\n",refId));
3612 }
3613 }
3614 else if (nc=='o') // reference to potential object name, e.g. 'self', or 'self.var1' or 'self.var1.var2'
3615 {
3616 nc=*p++;
3617 DString refIdStr;
3618 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
3619 p--;
3620 int refId=refIdStr.toInt();
3621 auto it = yyextra->objectMap.find(refId);
3622 if (it!=yyextra->objectMap.end())
3623 {
3624 DString object = it->second;
3625 if (object=="self")
3626 {
3627 if (yyextra->currentDefinition &&
3628 yyextra->currentDefinition->definitionType()==Definition::TypeClass)
3629 {
3630 ctx->objectType = toClassDef(yyextra->currentDefinition);
3631 if (ctx->objectType->categoryOf())
3632 {
3633 ctx->objectType = ctx->objectType->categoryOf();
3634 }
3635 if (ctx->objectType && !ctx->methodName.empty())
3636 {
3637 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
3638 }
3639 }
3640 startFontClass(yyscanner,"keyword");
3641 codifyLines(yyscanner,object);
3642 endFontClass(yyscanner);
3643 }
3644 else if (object=="super")
3645 {
3646 if (yyextra->currentDefinition &&
3647 yyextra->currentDefinition->definitionType()==Definition::TypeClass)
3648 {
3649 const ClassDef *cd = toClassDef(yyextra->currentDefinition);
3650 if (cd->categoryOf())
3651 {
3652 cd = cd->categoryOf();
3653 }
3654 for (const auto &bclass : cd->baseClasses())
3655 {
3656 if (bclass.classDef->compoundType()!=ClassDef::Protocol)
3657 {
3658 ctx->objectType = bclass.classDef;
3659 if (ctx->objectType && !ctx->methodName.empty())
3660 {
3661 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
3662 }
3663 }
3664 }
3665 }
3666 startFontClass(yyscanner,"keyword");
3667 codifyLines(yyscanner,object);
3668 endFontClass(yyscanner);
3669 }
3670 else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable
3671 {
3672 writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->objectVar,object);
3673 if (yyextra->currentMemberDef && yyextra->collectXRefs)
3674 {
3675 addDocCrossReference(yyextra->currentMemberDef,ctx->objectVar);
3676 }
3677 }
3678 else if (ctx->objectType && ctx->objectType->isLinkable()) // object is class name
3679 {
3680 const ClassDef *cd = ctx->objectType;
3681 writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,object);
3682 }
3683 else // object still needs to be resolved
3684 {
3685 size_t pp = 0;
3686 size_t dotPos = object.find('.',pp);
3687 size_t len = object.length();
3688 if (dotPos==DString::npos) dotPos=len;
3689 const Definition *scope = yyextra->currentDefinition;
3690 //printf("initial scope=%s\n",scope?qPrint(scope->name()):"none");
3691 for (;;)
3692 {
3693 DString fragment = object.mid(pp,dotPos-pp);
3694 DString fragmentStripped = fragment.stripWhiteSpace();
3695 //printf("fragment=%s\n",qPrint(fragment));
3696 if (fragmentStripped=="self")
3697 {
3698 if (scope && scope->definitionType()==Definition::TypeClass)
3699 {
3700 scope = ctx->objectType = toClassDef(scope);
3701 }
3702 //printf("self scope=%s\n",scope?qPrint(scope->name()):"none");
3703 startFontClass(yyscanner,"keyword");
3704 codifyLines(yyscanner,fragment);
3705 endFontClass(yyscanner);
3706 }
3707 else
3708 {
3709 const Definition *symbol = yyextra->symbolResolver.resolveSymbol(scope,fragmentStripped,DString(),false,true);
3710 //printf("scope=%s name=%s -> symbol=%s\n",scope?qPrint(scope->name()):"none",qPrint(fragment),
3711 // symbol?qPrint(symbol->name()):"none");
3712 if (symbol && symbol->definitionType()==Definition::TypeClass)
3713 {
3714 scope = ctx->objectType = toClassDef(symbol);
3715 ctx->method = yyextra->symbolResolver.getTypedef();
3716 }
3717 else if (symbol && symbol->definitionType()==Definition::TypeMember)
3718 {
3719 scope = ctx->objectType = stripClassName(yyscanner,toMemberDef(symbol)->typeString(),scope);
3720 }
3721 if (scope && scope!=Doxygen::globalScope)
3722 {
3723 writeMultiLineCodeLink(yyscanner,*yyextra->code,scope,fragment);
3724 }
3725 else
3726 {
3727 codifyLines(yyscanner,fragment);
3728 }
3729 //printf("new scope=%s\n",scope?qPrint(scope->name()):"none");
3730 }
3731 if (dotPos==len)
3732 {
3733 break;
3734 }
3735 else // find next fragment
3736 {
3737 codifyLines(yyscanner,".");
3738 pp=dotPos+1;
3739 dotPos=object.find('.',pp);
3740 if (dotPos==DString::npos) dotPos=len;
3741 }
3742 }
3743 DBG_CTX((stderr," object is class? %p\n",(void*)ctx->objectType));
3744 if (ctx->objectType) // found class
3745 {
3746 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
3747 DBG_CTX((stderr," yes->method=%s\n",ctx->method?qPrint(ctx->method->name()):"<none>"));
3748 }
3749 else if (ctx->method==nullptr) // search for class variable with the same name
3750 {
3751 DBG_CTX((stderr," no\n"));
3752 DBG_CTX((stderr,"yyextra->currentDefinition=%p\n",(void*)yyextra->currentDefinition));
3753 if (yyextra->currentDefinition &&
3754 yyextra->currentDefinition->definitionType()==Definition::TypeClass)
3755 {
3756 ctx->objectVar = (toClassDef(yyextra->currentDefinition))->getMemberByName(ctx->objectTypeOrName);
3757 DBG_CTX((stderr," ctx->objectVar=%p\n",(void*)ctx->objectVar));
3758 if (ctx->objectVar)
3759 {
3760 ctx->objectType = stripClassName(yyscanner,ctx->objectVar->typeString(),yyextra->currentDefinition);
3761 DBG_CTX((stderr," ctx->objectType=%p\n",(void*)ctx->objectType));
3762 if (ctx->objectType && !ctx->methodName.empty())
3763 {
3764 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
3765 DBG_CTX((stderr," ctx->method=%p\n",(void*)ctx->method));
3766 }
3767 }
3768 }
3769 }
3770 }
3771 }
3772 else
3773 {
3774 DBG_CTX((stderr,"Invalid object: id=%d\n",refId));
3775 }
3776 }
3777 else if (nc=='c') // reference to nested call
3778 {
3779 nc=*p++;
3780 DString refIdStr;
3781 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
3782 p--;
3783 int refId=refIdStr.toInt();
3784 auto it = yyextra->contextMap.find(refId);
3785 if (it!=yyextra->contextMap.end()) // recurse into nested call
3786 {
3787 ObjCCallCtx *ictx = it->second.get();
3788 writeObjCMethodCall(yyscanner,ictx);
3789 if (ictx->method) // link to nested call successfully
3790 {
3791 // get the ClassDef representing the method's return type
3792 if (ictx->method->typeString()=="id")
3793 {
3794 // see if the method name is unique, if so we link to it
3796 //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n",
3797 // mn==0?-1:(int)mn->count(),
3798 // qPrint(ictx->method->name()),
3799 // qPrint(ctx->methodName));
3800 if (mn && mn->size()==1) // member name unique
3801 {
3802 ctx->method = mn->front().get();
3803 }
3804 }
3805 else
3806 {
3807 ctx->objectType = stripClassName(yyscanner,ictx->method->typeString(),yyextra->currentDefinition);
3808 if (ctx->objectType && !ctx->methodName.empty())
3809 {
3810 ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
3811 }
3812 }
3813 DBG_CTX((stderr," ***** method=%s -> object=%p\n",qPrint(ictx->method->name()),(void*)ctx->objectType));
3814 }
3815 }
3816 else
3817 {
3818 DBG_CTX((stderr,"Invalid context: id=%d\n",refId));
3819 }
3820 }
3821 else if (nc=='w') // some word
3822 {
3823 nc=*p++;
3824 DString refIdStr;
3825 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
3826 p--;
3827 int refId=refIdStr.toInt();
3828 auto it = yyextra->wordMap.find(refId);
3829 if (it!=yyextra->wordMap.end())
3830 {
3831 DString word = it->second;
3832 bool isKeyword = word=="self";
3833 if (isKeyword)
3834 {
3835 startFontClass(yyscanner,"keyword");
3836 }
3837 codifyLines(yyscanner,word);
3838 if (isKeyword)
3839 {
3840 endFontClass(yyscanner);
3841 }
3842 }
3843 }
3844 else if (nc=='d') // comment block
3845 {
3846 nc=*p++;
3847 DString refIdStr;
3848 while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; }
3849 p--;
3850 int refId=refIdStr.toInt();
3851 auto it = yyextra->commentMap.find(refId);
3852 if (it!=yyextra->commentMap.end())
3853 {
3854 DString comment = it->second;
3855 startFontClass(yyscanner,"comment");
3856 codifyLines(yyscanner,comment);
3857 endFontClass(yyscanner);
3858 }
3859 }
3860 else // illegal marker
3861 {
3862 ASSERT(0); // "invalid escape sequence"
3863 }
3864 }
3865 }
3866 else if (c=='\'' || c == '"')
3867 {
3868 char s[2];
3869 s[0]=c;s[1]=0;
3870 codifyLines(yyscanner,s);
3871 skip = true;
3872 skipChar = c;
3873 }
3874 else // normal non-marker character
3875 {
3876 char s[2];
3877 s[0]=c;s[1]=0;
3878 codifyLines(yyscanner,s);
3879 }
3880 }
3881 }
3882 DBG_CTX((stderr,"%s %s]\n",qPrint(ctx->objectTypeOrName),qPrint(ctx->methodName)));
3883 DBG_CTX((stderr,"}=(type='%s',name='%s')",
3885 qPrint(ctx->methodName)));
virtual const BaseClassList & baseClasses() const =0
Returns the list of base classes from which this class directly inherits.
virtual ClassDef * categoryOf() const =0
Returns the class of which this is a category (Objective-C only).
int toInt(bool *ok=nullptr, int base=10) const
Definition dstring.cpp:191
static void startFontClass(yyscan_t yyscanner, const char *s, bool specialComment=false)
Definition code.l:3505
static void writeObjCMethodCall(yyscan_t yyscanner, ObjCCallCtx *ctx)
Definition code.l:3521
#define ASSERT(x)
Definition message.h:142
const MemberDef * objectVar
Definition code.l:86
const ClassDef * objectType
Definition code.l:85
3886}

References addDocCrossReference(), ASSERT, DString::at(), ClassDef::baseClasses(), ClassDef::categoryOf(), codifyLines(), DString::data(), DBG_CTX, Definition::definitionType(), DString::empty(), endFontClass(), LinkedMap< T, Hash, KeyEqual, Map >::find(), ObjCCallCtx::format, MemberName::front(), ClassDef::getMemberByName(), ScopedTypeVariant::globalDef(), Doxygen::globalScope, Definition::isLinkable(), Doxygen::memberNameLinkedMap, ObjCCallCtx::method, ObjCCallCtx::methodName, DString::mid(), Definition::name(), DString::npos, ObjCCallCtx::objectType, ObjCCallCtx::objectTypeOrName, ObjCCallCtx::objectVar, ClassDef::Protocol, qPrint(), MemberName::size(), startFontClass(), stripClassName(), DString::stripWhiteSpace(), toClassDef(), DString::toInt(), toMemberDef(), Definition::TypeClass, Definition::TypeMember, MemberDef::typeString(), writeMultiLineCodeLink(), and writeObjCMethodCall().

Referenced by writeObjCMethodCall().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 375 of file code.l.

378 {
379 startFontClass(yyscanner,"preprocessor");
380 yyextra->code->codify(yytext);
381 BEGIN( ReadInclude );
382 }
383<Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ {
384 yyextra->insideObjC=true;
385 startFontClass(yyscanner,"keyword");
386 codifyLines(yyscanner,yytext);
387 endFontClass(yyscanner);
388 if (!yyextra->insideTemplate)
389 BEGIN( ClassName );
390 }
391<Body>(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") {
392 if (yyextra->insideTemplate) REJECT;
393 startFontClass(yyscanner,"keyword");
394 codifyLines(yyscanner,yytext);
395 endFontClass(yyscanner);
396 BEGIN( ClassName );
397 }
398<Body>"property"|"event"/{BN}* {
399 if (yyextra->insideTemplate) REJECT;
400 startFontClass(yyscanner,"keyword");
401 codifyLines(yyscanner,yytext);
402 endFontClass(yyscanner);
403 }
404<Body>("partial"{B}+)?("class"|"struct"|"union"|"namespace"|"interface"){B}+ {
405 startFontClass(yyscanner,"keyword");
406 codifyLines(yyscanner,yytext);
407 endFontClass(yyscanner);
408 if (!yyextra->insideTemplate)
409 BEGIN( ClassName );
410 }
411<Body>("package")[ \t\n]+ {
412 startFontClass(yyscanner,"keyword");
413 codifyLines(yyscanner,yytext);
414 endFontClass(yyscanner);
415 BEGIN( PackageName );
416 }
417<ClassVar>\n {
418 if (!yyextra->insideObjC) REJECT;
419 codifyLines(yyscanner,yytext);
420 BEGIN(Body);
421 }
422<Body,ClassVar,Bases>"-"|"+" {
423 if (!yyextra->insideObjC || yyextra->insideBody)
424 {
425 yyextra->code->codify(yytext);
426 }
427 else // Start of Objective-C method
428 {
429 DBG_CTX((stderr,"Start of Objective-C method!\n"));
430 yyextra->code->codify(yytext);
431 BEGIN(ObjCMethod);
432 }
433 }
434<ObjCMethod>":" {
435 yyextra->code->codify(yytext);
436 BEGIN(ObjCParams);
437 }
438<ObjCParams>"(" {
439 yyextra->code->codify(yytext);
440 BEGIN(ObjCParamType);
441 }
442<ObjCParams,ObjCMethod>";"|"{" {
443 yyextra->code->codify(yytext);
444 if (*yytext=='{')
445 {
446 if (yyextra->searchingForBody)
447 {
448 yyextra->searchingForBody=false;
449 yyextra->insideBody=true;
450 }
451 if (yyextra->insideBody) yyextra->bodyCurlyCount++;
452 if (!yyextra->curClassName.empty()) // valid class name
453 {
454 pushScope(yyscanner,yyextra->curClassName);
455 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
456 yyextra->scopeStack.push(SCOPEBLOCK);
457 }
458 }
459 yyextra->type.clear();
460 yyextra->name.clear();
461 BEGIN(Body);
462 }
#define SCOPEBLOCK
Definition code.l:75
463<ObjCParams>{ID}{B}*":" {
464 yyextra->code->codify(yytext);
465 }
466<ObjCParamType>{TYPEKW} {
467 startFontClass(yyscanner,"keywordtype");
468 yyextra->code->codify(yytext);
469 endFontClass(yyscanner);
470 yyextra->parmType=yytext;
471 }
472<ObjCParamType>{ID} {
473 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
474 yyextra->parmType=yytext;
475 }
476<ObjCParamType>")" {
477 yyextra->code->codify(yytext);
478 BEGIN(ObjCParams);
479 }
480<ObjCParams>{ID} {
481 yyextra->code->codify(yytext);
482 yyextra->parmName=yytext;
483 addVariable(yyscanner,yyextra->parmType,yyextra->parmName);
484 yyextra->parmType.clear();yyextra->parmName.clear();
485 }
486<ObjCMethod,ObjCParams,ObjCParamType>{ID} {
487 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
488 }
489<ObjCMethod,ObjCParams,ObjCParamType>. {
490 yyextra->code->codify(yytext);
491 }
492<ObjCMethod,ObjCParams,ObjCParamType>\n {
493 codifyLines(yyscanner,yytext);
494 }
495<ReadInclude>[^\n\">]+/(">"|"\"") {
496 //FileInfo *f;
497 bool found = false;
498 bool ambig = false;
499 DString absIncFileName = determineAbsoluteIncludeName(yyextra->absFileName,yytext);
500 const FileDef *fd=Doxygen::inputNameLinkedMap->findFileDef(absIncFileName,ambig);
501 //printf("looking for include %s -> %s fd=%p\n",yytext,qPrint(absPath),fd);
502 if (fd && fd->isLinkable())
503 {
504 if (ambig) // multiple input files match the name
505 {
506 DBG_CTX((stderr,"===== yes %s is ambiguous\n",yytext));
507 DString name(Dir::cleanDirPath(yytext));
508 if (!name.empty() && yyextra->sourceFileDef)
509 {
510 const FileName *fn = Doxygen::inputNameLinkedMap->find(name);
511 if (fn)
512 {
513 // see if this source file actually includes the file
514 auto it = std::find_if(fn->begin(),
515 fn->end(),
516 [&sfd=yyextra->sourceFileDef]
517 (const auto &lfd)
518 { return sfd->isIncluded(lfd->absFilePath()); });
519 found = it!=fn->end();
520 }
521 }
522 }
523 else // not ambiguous
524 {
525 found = true;
526 }
527 }
528 DBG_CTX((stderr," include file %s found=%d\n",fd ? qPrint(fd->absFilePath()) : "<none>",found));
529 if (found)
530 {
531 writeMultiLineCodeLink(yyscanner,*yyextra->code,fd,yytext);
532 }
533 else
534 {
535 yyextra->code->codify(yytext);
536 }
537 char c=(char)yyinput(yyscanner);
538 DString text;
539 text+=c;
540 yyextra->code->codify(text);
541 endFontClass(yyscanner);
542 BEGIN( Body );
543 }
static std::string cleanDirPath(const std::string &path)
Definition dir.cpp:363
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:97
virtual DString absFilePath() const =0
Class representing all files with a certain base name.
Definition filename.h:31
FileDef * findFileDef(const DString &n, bool &ambig) const
Returns the file definition in fnMap that matches the file name n.
Definition filename.cpp:38
DString determineAbsoluteIncludeName(const DString &curFile, const DString &incFileName)
Definition util.cpp:2929
544<Body,Bases>^[ \t]*"#" {
545 startFontClass(yyscanner,"preprocessor");
546 yyextra->lastSkipCppContext = YY_START;
547 yyextra->code->codify(yytext);
548 BEGIN( SkipCPP ) ;
549 }
550<SkipCPP>\" {
551 yyextra->code->codify(yytext);
552 yyextra->lastStringContext=YY_START;
553 BEGIN( SkipString ) ;
554 }
555<SkipCPP>. {
556 yyextra->code->codify(yytext);
557 }
558<SkipCPP>[^\n\/\\\"]+ {
559 yyextra->code->codify(yytext);
560 }
561<SkipCPP>\\‍[\r]?\n {
562 codifyLines(yyscanner,yytext);
563 }
564<SkipCPP>{CPPC}/[^/!] {
565 REJECT;
566 }
567<Body,FuncCall,MemberCall,MemberCall2>"}" {
568 yyextra->theVarContext.popScope();
569 yyextra->theCallContext.popScope(yyextra->name, yyextra->type, yyextra->bracketCount);
570 yyextra->type.clear();
571 yyextra->name.clear();
572
573 if (!yyextra->scopeStack.empty())
574 {
575 int scope = yyextra->scopeStack.top();
576 yyextra->scopeStack.pop();
577 DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
578 if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
579 {
580 popScope(yyscanner);
581 }
582 }
583
584 yyextra->code->codify(yytext);
585
586 DBG_CTX((stderr,"yyextra->bodyCurlyCount=%d\n",yyextra->bodyCurlyCount));
587 if (--yyextra->bodyCurlyCount<=0)
588 {
589 yyextra->insideBody=false;
590 yyextra->currentMemberDef=nullptr;
591 if (yyextra->currentDefinition)
592 yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope();
593 }
594 BEGIN(Body);
595 }
596<Body,ClassVar>"@end" {
597 DBG_CTX((stderr,"End of objc scope fd=%s\n",qPrint(yyextra->sourceFileDef->name())));
598 if (yyextra->sourceFileDef)
599 {
600 const FileDef *fd=yyextra->sourceFileDef;
601 yyextra->insideObjC = fd->name().lower().endsWith(".m") ||
602 fd->name().lower().endsWith(".mm");
603 DBG_CTX((stderr,"insideObjC=%d\n",yyextra->insideObjC));
604 }
605 else
606 {
607 yyextra->insideObjC = false;
608 }
609 if (yyextra->insideBody)
610 {
611 yyextra->theVarContext.popScope();
DString lower() const
Definition dstring.h:326
bool endsWith(const char *s) const
Definition dstring.h:617
612
613 if (!yyextra->scopeStack.empty())
614 {
615 int scope = yyextra->scopeStack.top();
616 yyextra->scopeStack.pop();
617 DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
618 if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
619 {
620 popScope(yyscanner);
621 }
622 }
623 yyextra->insideBody=false;
624 }
625
626 startFontClass(yyscanner,"keyword");
627 yyextra->code->codify(yytext);
628 endFontClass(yyscanner);
629
630 yyextra->currentMemberDef=nullptr;
631 if (yyextra->currentDefinition)
632 yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope();
633 BEGIN(Body);
634 }
635<ClassName,ClassVar>";" {
636 if (yyextra->lang==SrcLangExt::CSharp)
637 {
638 yyextra->code->codify(yytext);
639 yyextra->skipCodify = true;
640 unput('{');
641 }
642 else
643 {
644 yyextra->code->codify(yytext);
645 yyextra->searchingForBody=false;
646 BEGIN( Body );
647 }
648 }
649<ClassName,ClassVar>[*&^%]+ {
650 yyextra->type=yyextra->curClassName;
651 yyextra->name.clear();
652 yyextra->code->codify(yytext);
653 BEGIN( Body ); // variable of type struct *
654 }
655<ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")" {
656 startFontClass(yyscanner,"keyword");
657 yyextra->code->codify(yytext);
658 endFontClass(yyscanner);
659 }
660<ClassName>{ID}("."{ID})* |
661<ClassName>{ID}("::"{ID})* {
662 if (yyextra->lang==SrcLangExt::CSharp)
663 yyextra->curClassName=substitute(yytext,".","::");
664 else
665 yyextra->curClassName=yytext;
666 addType(yyscanner);
667 if (yyextra->curClassName=="alignas")
668 {
669 startFontClass(yyscanner,"keyword");
670 yyextra->code->codify(yytext);
671 endFontClass(yyscanner);
672 BEGIN( AlignAs );
673 }
674 else
675 {
676 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
677 BEGIN( ClassVar );
678 }
679 }
static void addType(yyscan_t yyscanner)
Definition code.l:2596
680<AlignAs>"(" {
681 yyextra->bracketCount=1;
682 yyextra->code->codify(yytext);
683 BEGIN( AlignAsEnd );
684 }
685<AlignAs>\n { yyextra->yyLineNr++;
686 codifyLines(yyscanner,yytext);
687 }
688<AlignAs>. { yyextra->code->codify(yytext); }
689<AlignAsEnd>"(" { yyextra->code->codify(yytext);
690 yyextra->bracketCount++;
691 }
692<AlignAsEnd>")" {
693 yyextra->code->codify(yytext);
694 if (--yyextra->bracketCount<=0)
695 {
696 BEGIN(ClassName);
697 }
698 }
699<AlignAsEnd>\n { yyextra->yyLineNr++;
700 codifyLines(yyscanner,yytext);
701 }
702<AlignAsEnd>. { yyextra->code->codify(yytext); }
703<ClassName>{ID}("\\"{ID})* { // PHP namespace
704 yyextra->curClassName=substitute(yytext,"\\","::");
705 yyextra->scopeStack.push(CLASSBLOCK);
706 pushScope(yyscanner,yyextra->curClassName);
707 addType(yyscanner);
708 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
709 BEGIN( ClassVar );
710 }
711<ClassName>{ID}{B}*"("{ID}")" { // Obj-C category
712 yyextra->curClassName=removeRedundantWhiteSpace(yytext);
713 yyextra->scopeStack.push(CLASSBLOCK);
714 pushScope(yyscanner,yyextra->curClassName);
715 addType(yyscanner);
716 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
717 BEGIN( ClassVar );
718 }
719<PackageName>{ID}("."{ID})* {
720 yyextra->curClassName=substitute(yytext,".","::");
721 DBG_CTX((stderr,"found package: %s\n",qPrint(yyextra->curClassName)));
722 addType(yyscanner);
723 codifyLines(yyscanner,yytext);
724 }
725<ClassVar>"=" {
726 unput(*yytext);
727 BEGIN( Body );
728 }
729<ClassVar>("extends"|"implements") { // Java, Slice
730 startFontClass(yyscanner,"keyword");
731 codifyLines(yyscanner,yytext);
732 endFontClass(yyscanner);
733 yyextra->curClassBases.clear();
734 BEGIN( Bases );
735 }
736<ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") {
737 DBG_CTX((stderr,"***** C++/CLI modifier %s on yyextra->curClassName=%s\n",yytext,qPrint(yyextra->curClassName)));
738 startFontClass(yyscanner,"keyword");
739 codifyLines(yyscanner,yytext);
740 endFontClass(yyscanner);
741 BEGIN( CppCliTypeModifierFollowup );
742 }
743<ClassVar>{ID} {
744 yyextra->type = yyextra->curClassName;
745 yyextra->name = yytext;
746 if (yyextra->insideBody)
747 {
748 addVariable(yyscanner,yyextra->type,yyextra->name);
749 }
750 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
751 }
752<ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* {
753 codifyLines(yyscanner,yytext);
754 yyextra->curClassBases.clear();
755 BEGIN( Bases );
756 }
757<PackageName>[ \t]*";" |
758<Bases>^{Bopt}/"@"{ID} | // Objective-C interface
759<Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* {
760 yyextra->theVarContext.pushScope();
761 if (!yyextra->skipCodify) yyextra->code->codify(yytext);
762 yyextra->skipCodify = false;
763 if (YY_START==ClassVar && yyextra->curClassName.empty())
764 {
765 yyextra->curClassName = yyextra->name;
766 }
767 if (yyextra->searchingForBody)
768 {
769 yyextra->searchingForBody=false;
770 yyextra->insideBody=true;
771 }
772 if (yyextra->insideBody) yyextra->bodyCurlyCount++;
773 if (!yyextra->curClassName.empty()) // valid class name
774 {
775 DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
776 yyextra->scopeStack.push(CLASSBLOCK);
777 pushScope(yyscanner,yyextra->curClassName);
778 DBG_CTX((stderr,"***** yyextra->curClassName=%s\n",qPrint(yyextra->curClassName)));
779 if (yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,yyextra->curClassName,true)==nullptr)
780 {
781 DBG_CTX((stderr,"Adding new class %s\n",qPrint(yyextra->curClassName)));
782 ScopedTypeVariant var(yyextra->curClassName);
783 // insert base classes.
784 for (const auto &s : yyextra->curClassBases)
785 {
786 const ClassDef *bcd=nullptr;
787 auto it = yyextra->codeClassMap.find(s);
788 if (it!=yyextra->codeClassMap.end())
789 {
790 bcd = toClassDef(it->second.globalDef());
791 }
792 if (bcd==nullptr) bcd=yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,s,true);
793 if (bcd && bcd->name()!=yyextra->curClassName)
794 {
795 var.localDef()->insertBaseClass(bcd->name());
796 }
797 }
798 yyextra->codeClassMap.emplace(yyextra->curClassName.str(),std::move(var));
799 }
800 //printf("yyextra->codeClassList.count()=%d\n",yyextra->codeClassList.count());
801 }
802 else // not a class name -> assume inner block
803 {
804 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
805 yyextra->scopeStack.push(INNERBLOCK);
806 }
807 yyextra->curClassName.clear();
808 yyextra->curClassBases.clear();
809 BEGIN( Body );
810 }
#define INNERBLOCK
Definition code.l:76
811<Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" {
812 startFontClass(yyscanner,"keyword");
813 yyextra->code->codify(yytext);
814 endFontClass(yyscanner);
815 }
816<Bases>{SEP}?({ID}{SEP})*{ID} {
817 DBG_CTX((stderr,"%s:addBase(%s)\n",qPrint(yyextra->curClassName),yytext));
818 yyextra->curClassBases.emplace_back(yytext);
819 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
820 }
821<Bases>"<" {
822 yyextra->code->codify(yytext);
823 if (!yyextra->insideObjC)
824 {
825 yyextra->sharpCount=1;
826 BEGIN ( SkipSharp );
827 }
828 else
829 {
830 yyextra->insideProtocolList=true;
831 }
832 }
833<Bases>">" {
834 yyextra->code->codify(yytext);
835 yyextra->insideProtocolList=false;
836 }
837<SkipSharp>"<" {
838 yyextra->code->codify(yytext);
839 ++yyextra->sharpCount;
840 }
841<SkipSharp>">" {
842 yyextra->code->codify(yytext);
843 if (--yyextra->sharpCount<=0)
844 BEGIN ( Bases );
845 }
846<SkipSharp>"\"" {
847 yyextra->code->codify(yytext);
848 yyextra->lastStringContext=YY_START;
849 BEGIN(SkipString);
850 }
851<SkipSharp>"\'" {
852 yyextra->code->codify(yytext);
853 yyextra->lastStringContext=YY_START;
854 BEGIN(SkipStringS);
855 }
856<Bases>"(" {
857 yyextra->code->codify(yytext);
858 yyextra->sharpCount=1;
859 BEGIN ( SkipSharp );
860 }
861<SkipSharp>"(" {
862 yyextra->code->codify(yytext);
863 ++yyextra->sharpCount;
864 }
865<SkipSharp>")" {
866 yyextra->code->codify(yytext);
867 if (--yyextra->sharpCount<=0)
868 BEGIN ( Bases );
869 }
870
871
872<Bases>"," {
873 yyextra->code->codify(yytext);
874 }
875
876
877<Body>{SCOPEPREFIX}?"operator"{B}*"()"{Bopt}/"(" {
878 addType(yyscanner);
879 generateFunctionLink(yyscanner,*yyextra->code,yytext);
880 yyextra->bracketCount=0;
881 yyextra->args.clear();
882 yyextra->name+=yytext;
883 BEGIN( FuncCall );
884 }
static void generateFunctionLink(yyscan_t yyscanner, OutputCodeList &ol, const DString &funcName)
Definition code.l:3354
885<Body>{SCOPEPREFIX}?"operator"/"(" {
886 addType(yyscanner);
887 generateFunctionLink(yyscanner,*yyextra->code,yytext);
888 yyextra->bracketCount=0;
889 yyextra->args.clear();
890 yyextra->name+=yytext;
891 BEGIN( FuncCall );
892 }
893<Body>{SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\‍(\n]+/"(" {
894 addType(yyscanner);
895 generateFunctionLink(yyscanner,*yyextra->code,yytext);
896 yyextra->bracketCount=0;
897 yyextra->args.clear();
898 yyextra->name+=yytext;
899 BEGIN( FuncCall );
900 }
901<Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9]) {
902 startFontClass(yyscanner,"keyword");
903 codifyLines(yyscanner,yytext);
904 endFontClass(yyscanner);
905 yyextra->insideTemplate=true;
906 yyextra->sharpCount=0;
907 }
908<Body>"concept"{BN}+ {
909 startFontClass(yyscanner,"keyword");
910 codifyLines(yyscanner,yytext);
911 endFontClass(yyscanner);
912 BEGIN(ConceptName);
913 }
914<Body>"using"{BN}+"namespace"{BN}+ {
915 startFontClass(yyscanner,"keyword");
916 codifyLines(yyscanner,yytext);
917 endFontClass(yyscanner);
918 BEGIN(UsingName);
919 }
920<Body>"using"{BN}+ {
921 startFontClass(yyscanner,"keyword");
922 codifyLines(yyscanner,yytext);
923 endFontClass(yyscanner);
924 BEGIN(UsingName);
925 }
926<Body>"module"/{B}*[:;]? { // 'module X' or 'module : private' or 'module;'
927 if (yyextra->lang!=SrcLangExt::Cpp) REJECT;
928 if (!yyextra->type.empty() || !yyextra->name.empty()) REJECT;
929 startFontClass(yyscanner,"keyword");
930 codifyLines(yyscanner,yytext);
931 endFontClass(yyscanner);
932 BEGIN(ModuleName);
933 }
934<Body>"import"/{B}*[<":]? {
935 if (yyextra->lang!=SrcLangExt::Cpp) REJECT;
936 startFontClass(yyscanner,"keyword");
937 codifyLines(yyscanner,yytext);
938 endFontClass(yyscanner);
939 BEGIN(ModuleImport);
940 }
941<ConceptName>{ID}("::"{ID})* {
942 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
943 }
944<ConceptName>"=" { codifyLines(yyscanner,yytext); BEGIN(Body); }
945<UsingName>{ID}(("::"|"."){ID})* {
946 addUsingDirective(yyscanner,substitute(yytext,".","::"));
947 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
948 BEGIN(Body);
949 }
static void addUsingDirective(yyscan_t yyscanner, const DString &name)
Definition code.l:2617
950<UsingName>\n { codifyLines(yyscanner,yytext); BEGIN(Body); }
951<UsingName>. { codifyLines(yyscanner,yytext); BEGIN(Body); }
952<Body,FuncCall>"$"?"this"("->"|".") { yyextra->code->codify(yytext); // this-> for C++, this. for C#
953 yyextra->isPrefixedWithThis = true;
954 }
955<Body>{KEYWORD}/([^a-z_A-Z0-9]) {
956 if (yyextra->lang==SrcLangExt::Java && dstrcmp("internal",yytext) ==0) REJECT;
957 if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT;
958 DString text=yytext;
959 startFontClass(yyscanner,"keyword");
960 codifyLines(yyscanner,yytext);
961 if (text=="typedef" || text.find("enum ")!=DString::npos) // typedef or strong enum
962 {
963 addType(yyscanner);
964 yyextra->name+=yytext;
965 }
966 endFontClass(yyscanner);
967 }
static bool skipLanguageSpecificKeyword(yyscan_t yyscanner, const char *kw)
Definition code.l:3931
int dstrcmp(const char *str1, const char *str2)
Definition dstring.h:50
968<Body>{KEYWORD}/{B}* {
969 if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT;
970 startFontClass(yyscanner,"keyword");
971 codifyLines(yyscanner,yytext);
972 endFontClass(yyscanner);
973 }
974<Body>{KEYWORD}/{BN}*"(" {
975 if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT;
976 startFontClass(yyscanner,"keyword");
977 codifyLines(yyscanner,yytext);
978 endFontClass(yyscanner);
979 yyextra->name.clear();yyextra->type.clear();
980 }
981<FuncCall>"in"/{BN}* {
982 if (!yyextra->inForEachExpression) REJECT;
983 startFontClass(yyscanner,"keywordflow");
984 codifyLines(yyscanner,yytext);
985 endFontClass(yyscanner);
986 // insert the variable in the parent scope, see bug 546158
987 yyextra->theVarContext.popScope();
988 addVariable(yyscanner,yyextra->parmType,yyextra->parmName);
989 yyextra->theVarContext.pushScope();
990 yyextra->name.clear();yyextra->type.clear();
991 }
992<Body>{FLOWKW}/{BN}*"(" {
993 startFontClass(yyscanner,"keywordflow");
994 codifyLines(yyscanner,yytext);
995 endFontClass(yyscanner);
996 yyextra->name.clear();yyextra->type.clear();
997 yyextra->inForEachExpression = (dstrcmp(yytext,"for each")==0 || dstrcmp(yytext, "foreach")==0);
998 BEGIN(FuncCall);
999 }
1000<Body>{FLOWCONDITION}/{BN}*"(" {
1001 incrementFlowKeyWordCount(yyscanner);
1002 startFontClass(yyscanner,"keywordflow");
1003 codifyLines(yyscanner,yytext);
1004 endFontClass(yyscanner);
1005 yyextra->name.clear();yyextra->type.clear();
1006 yyextra->inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0);
1007 BEGIN(FuncCall);
1008 }
static void incrementFlowKeyWordCount(yyscan_t yyscanner)
Definition code.l:2540
1009<Body>{FLOWKW}/([^a-z_A-Z0-9]) {
1010 startFontClass(yyscanner,"keywordflow");
1011 codifyLines(yyscanner,yytext);
1012 endFontClass(yyscanner);
1013 if (yyextra->inFunctionTryBlock && (dstrcmp(yytext,"catch")==0 || dstrcmp(yytext,"finally")==0))
1014 {
1015 yyextra->inFunctionTryBlock=false;
1016 }
1017 }
1018<Body>{FLOWCONDITION}/([^a-z_A-Z0-9]) {
1019 incrementFlowKeyWordCount(yyscanner);
1020 startFontClass(yyscanner,"keywordflow");
1021 codifyLines(yyscanner,yytext);
1022 endFontClass(yyscanner);
1023 if (yyextra->inFunctionTryBlock && (strcmp(yytext,"catch")==0 || strcmp(yytext,"finally")==0))
1024 {
1025 yyextra->inFunctionTryBlock=false;
1026 }
1027 }
1028<Body>{FLOWKW}/{B}* {
1029 startFontClass(yyscanner,"keywordflow");
1030 codifyLines(yyscanner,yytext);
1031 endFontClass(yyscanner);
1032 }
1033<Body>{FLOWCONDITION}/{B}* {
1034 incrementFlowKeyWordCount(yyscanner);
1035 startFontClass(yyscanner,"keywordflow");
1036 codifyLines(yyscanner,yytext);
1037 endFontClass(yyscanner);
1038 }
1039<Body>"*"{B}*")" { // end of cast?
1040 yyextra->code->codify(yytext);
1041 yyextra->theCallContext.popScope(yyextra->name, yyextra->type, yyextra->bracketCount);
1042 yyextra->bracketCount--;
1043 yyextra->parmType = yyextra->name;
1044 BEGIN(FuncCall);
1045 }
1046<Body>"\\‍)"|"\\‍(" {
1047 yyextra->code->codify(yytext);
1048 }
1049<Body>[\\|\‍)\+\-\/\%\~\!] {
1050 yyextra->code->codify(yytext);
1051 yyextra->name.clear();yyextra->type.clear();
1052 if (*yytext==')')
1053 {
1054 yyextra->theCallContext.popScope(yyextra->name, yyextra->type, yyextra->bracketCount);
1055 yyextra->bracketCount--;
1056 if (yyextra->bracketCount<=0)
1057 {
1058 BEGIN(FuncCall);
1059 }
1060 }
1061 }
1062<Body,TemplDecl,ObjCMethod>{TYPEKW}/{B}* {
1063 startFontClass(yyscanner,"keywordtype");
1064 yyextra->code->codify(yytext);
1065 endFontClass(yyscanner);
1066 addType(yyscanner);
1067 yyextra->name+=yytext;
1068 }
1069<Body,TemplDecl,ObjCMethod>{TYPEKWSL}/{B}* {
1070 if (yyextra->lang!=SrcLangExt::Slice)
1071 {
1072 REJECT;
1073 }
1074 else
1075 {
1076 startFontClass(yyscanner,"keywordtype");
1077 yyextra->code->codify(yytext);
1078 endFontClass(yyscanner);
1079 addType(yyscanner);
1080 yyextra->name+=yytext;
1081 }
1082 }
1083<Body>"generic"/{B}*"<"[^\n\/\-\.\{\">]*">"{B}* {
1084 startFontClass(yyscanner,"keyword");
1085 yyextra->code->codify(yytext);
1086 endFontClass(yyscanner);
1087 yyextra->sharpCount=0;
1088 BEGIN(TemplDecl);
1089 }
1090<Body>"template"/{B}*"<"[^\n\/\-\.\{\">]*">"{B}* { // template<...>
1091 startFontClass(yyscanner,"keyword");
1092 yyextra->code->codify(yytext);
1093 endFontClass(yyscanner);
1094 yyextra->sharpCount=0;
1095 BEGIN(TemplDecl);
1096 }
1097<TemplDecl>"class"|"typename" {
1098 startFontClass(yyscanner,"keyword");
1099 codifyLines(yyscanner,yytext);
1100 endFontClass(yyscanner);
1101 }
1102<TemplDecl>"<" {
1103 yyextra->code->codify(yytext);
1104 yyextra->sharpCount++;
1105 }
1106<TemplDecl>">" {
1107 yyextra->code->codify(yytext);
1108 yyextra->sharpCount--;
1109 if (yyextra->sharpCount<=0)
1110 {
1111 BEGIN(Body);
1112 }
1113 }
1114<TemplCast>">" {
1115 startFontClass(yyscanner,"keyword");
1116 codifyLines(yyscanner,yytext);
1117 endFontClass(yyscanner);
1118 BEGIN( yyextra->lastTemplCastContext );
1119 }
1120<TemplCast>{ID}("::"{ID})* {
1121 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
1122 }
1123<TemplCast>("const"|"volatile"){B}* {
1124 startFontClass(yyscanner,"keyword");
1125 codifyLines(yyscanner,yytext);
1126 endFontClass(yyscanner);
1127 }
1128<TemplCast>[*^]* {
1129 codifyLines(yyscanner,yytext);
1130 }
1131<Body,MemberCall2,FuncCall>{CASTKW}{B}*"<" { // static_cast<T>(
1132 startFontClass(yyscanner,"keyword");
1133 codifyLines(yyscanner,yytext);
1134 endFontClass(yyscanner);
1135 yyextra->lastTemplCastContext = YY_START;
1136 BEGIN(TemplCast);
1137 }
1138<Body>"$this->"{SCOPENAME}/{BN}*[;,)\‍]] { // PHP member variable
1139 addType(yyscanner);
1140 generatePHPVariableLink(yyscanner,*yyextra->code,yytext);
1141 yyextra->name+=yytext+7;
1142 }
static void generatePHPVariableLink(yyscan_t yyscanner, OutputCodeList &ol, const char *varName)
Definition code.l:3342
1143<Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\">\‍(']*">"{ENDIDopt}/{B}* { // A<T> *pt;
1144 if (isCastKeyword(yytext) && YY_START==Body)
1145 {
1146 REJECT;
1147 }
1148 addType(yyscanner);
1149 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
1150 yyextra->name+=yytext;
1151 }
static bool isCastKeyword(const char *s)
Definition code.l:3972
1152<ModuleName,ModuleImport>{MODULE_ID}({BN}*":"{BN}*{MODULE_ID})? {
1153 DString name = yytext;
1154 size_t i = name.find(':');
1155 DString partition;
1156 if (i!=DString::npos)
1157 {
1158 partition = name.mid(i+1).stripWhiteSpace();
1159 name = name.left(i).stripWhiteSpace();
1160 }
1162 if (mod)
1163 {
1164 writeMultiLineCodeLink(yyscanner,*yyextra->code,mod,yytext);
1165 }
1166 else
1167 {
1168 codifyLines(yyscanner,yytext);
1169 }
1170 }
static ModuleManager & instance()
ModuleDef * getPrimaryInterface(const DString &moduleName) const
1171<ModuleName>":"{BN}+"private" {
1172 DString text=yytext;
1173 size_t i=text.find('p');
1174 codifyLines(yyscanner,text.left(i));
1175 startFontClass(yyscanner,"keyword");
1176 codifyLines(yyscanner,text.mid(i));
1177 endFontClass(yyscanner);
1178 }
1179<ModuleName>";" { yyextra->code->codify(yytext); BEGIN(Body); }
1180<ModuleName>. { yyextra->code->codify(yytext); }
1181<ModuleName>\n { codifyLines(yyscanner,yytext); }
1182<ModuleImport>["<] { yyextra->code->codify(yytext); BEGIN(ReadInclude); }
1183<ModuleImport>";" { yyextra->code->codify(yytext); BEGIN(Body); }
1184<ModuleImport>. { yyextra->code->codify(yytext); }
1185<ModuleImport>\n { codifyLines(yyscanner,yytext); }
1186
1187<Body>{SCOPENAME}/{BN}*[:;,)\‍]] { // "int var;" or "var, var2" or "debug(f) macro" , or int var : 5;
1188 if (startsWithKeyword(yytext,"typedef") || startsWithKeyword(yytext,"using"))
1189 {
1190 REJECT;
1191 }
1192 addType(yyscanner);
1193 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
1194 yyextra->name+=yytext;
1195 }
static bool startsWithKeyword(const DString &str, const DString &kw)
Definition code.l:2180
1196<Body>{ID}("."{ID})+/{BN}+ { // CSharp/Java scope
1197 if (yyextra->lang==SrcLangExt::CSharp || yyextra->lang==SrcLangExt::Java)
1198 {
1199 addType(yyscanner);
1200 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
1201 yyextra->name+=yytext;
1202 }
1203 else
1204 {
1205 REJECT;
1206 }
1207 }
1208<Body>"export"/{B}* {
1209 if (yyextra->lang!=SrcLangExt::Cpp) REJECT;
1210 startFontClass(yyscanner,"keyword");
1211 codifyLines(yyscanner,yytext);
1212 endFontClass(yyscanner);
1213 }
1214<Body>{SCOPENAME}/{B}* { // p->func()
1215 if (startsWithKeyword(yytext,"typedef") || startsWithKeyword(yytext,"using"))
1216 {
1217 REJECT;
1218 }
1219 addType(yyscanner);
1220 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
1221 yyextra->name+=yytext;
1222 }
1223<Body>"("{B}*("*"{B}*)+{SCOPENAME}+{B}*")"/{B}* { // (*p)->func() but not "if (p) ..."
1224 yyextra->code->codify(yytext);
1225 uint32_t s=0;while (s<(uint32_t)yyleng && !isId(yytext[s])) s++;
1226 uint32_t e=(uint32_t)yyleng-1;while (e>1 && !isId(yytext[e])) e--;
1227 DString varname = ((DString)yytext).mid(s,e-s+1);
1228 addType(yyscanner);
1229 yyextra->name=std::move(varname);
1230 }
1231<Body>{SCOPETNAME}{B}*"<"[^\n\/\-\.\{\">]*">"/{BN}*"(" |
1232<Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo()
1233 if (isCastKeyword(yytext))
1234 {
1235 REJECT;
1236 }
1237 addType(yyscanner);
1238 generateFunctionLink(yyscanner,*yyextra->code,yytext);
1239 yyextra->bracketCount=0;
1240 yyextra->args.clear();
1241 yyextra->name+=yytext;
1242 BEGIN( FuncCall );
1243 }
1244<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN} {
1245 DString text(yytext);
1246 size_t i=text.find('R');
1247 yyextra->code->codify(text.left(i+1));
1248 startFontClass(yyscanner,"stringliteral");
1249 yyextra->code->codify(yytext+i+1);
1250 yyextra->lastStringContext=YY_START;
1251 yyextra->inForEachExpression = false;
1252 yyextra->delimiter = extractBeginRawStringDelimiter(yytext);
1253 BEGIN( RawString );
1254 }
DString extractBeginRawStringDelimiter(const char *rawStart)
Definition util.cpp:5339
1255<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit,ClassVar,OldStyleArgs>\" {
1256 startFontClass(yyscanner,"stringliteral");
1257 yyextra->code->codify(yytext);
1258 yyextra->lastStringContext=YY_START;
1259 yyextra->inForEachExpression = false;
1260 BEGIN( SkipString );
1261 }
1262<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{NUMBER} { //Note similar code in commentcnv.l
1263 if (yyextra->lang!=SrcLangExt::Cpp) REJECT;
1264 yyextra->code->codify(yytext);
1265 }
1266<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\' {
1267 startFontClass(yyscanner,"stringliteral");
1268 yyextra->code->codify(yytext);
1269 yyextra->lastStringContext=YY_START;
1270 yyextra->inForEachExpression = false;
1271 BEGIN( SkipStringS );
1272 }
1273<SkipString>[^\"\\\r\n]{1,100} {
1274 yyextra->code->codify(yytext);
1275 }
1276<SkipStringS>[^\'\\\r\n]{1,100} {
1277 yyextra->code->codify(yytext);
1278 }
1279<SkipString,SkipStringS>{CPPC}|{CCS} {
1280 yyextra->code->codify(yytext);
1281 }
1282<SkipString>@?\" {
1283 yyextra->code->codify(yytext);
1284 if (yyextra->lastStringContext!=SkipCPP)
1285 {
1286 endFontClass(yyscanner);
1287 }
1288 BEGIN( yyextra->lastStringContext );
1289 }
1290<SkipStringS>\' {
1291 yyextra->code->codify(yytext);
1292 endFontClass(yyscanner);
1293 BEGIN( yyextra->lastStringContext );
1294 }
1295<SkipString,SkipStringS>\\. {
1296 yyextra->code->codify(yytext);
1297 }
1298<RawString>{RAWEND} {
1299 yyextra->code->codify(yytext);
1300 if (extractEndRawStringDelimiter(yytext)==yyextra->delimiter)
1301 {
1302 BEGIN( yyextra->lastStringContext );
1303 }
1304 }
DString extractEndRawStringDelimiter(const char *rawEnd)
Definition util.cpp:5347
1305<RawString>[^)\n]+ { yyextra->code->codify(yytext); }
1306<RawString>. { yyextra->code->codify(yytext); }
1307<RawString>\n { codifyLines(yyscanner,yytext); }
1308<SkipVerbString>[^"\n]+ {
1309 yyextra->code->codify(yytext);
1310 }
1311<SkipVerbString>\"\" { // escaped quote
1312 yyextra->code->codify(yytext);
1313 }
1314<SkipVerbString>\" { // end of string
1315 yyextra->code->codify(yytext);
1316 endFontClass(yyscanner);
1317 BEGIN( yyextra->lastVerbStringContext );
1318 }
1319<SkipVerbString>. {
1320 yyextra->code->codify(yytext);
1321 }
1322<SkipVerbString>\n {
1323 codifyLines(yyscanner,yytext);
1324 }
1325<Body>":" {
1326 yyextra->code->codify(yytext);
1327 yyextra->name.clear();yyextra->type.clear();
1328 }
1329<Body>"<" {
1330 if (yyextra->insideTemplate)
1331 {
1332 yyextra->sharpCount++;
1333 }
1334 yyextra->code->codify(yytext);
1335 }
1336<Body>">" {
1337 if (yyextra->insideTemplate)
1338 {
1339 if (--yyextra->sharpCount<=0)
1340 {
1341 yyextra->insideTemplate=false;
1342 }
1343 }
1344 yyextra->code->codify(yytext);
1345 }
1346<Body,MemberCall,MemberCall2,FuncCall,OldStyleArgs>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'" {
1347 startFontClass(yyscanner,"charliteral");
1348 yyextra->code->codify(yytext);
1349 endFontClass(yyscanner);
1350 }
1351<Body>"."|"->" {
1352 if (yytext[0]=='-') // -> could be overloaded
1353 {
1355 }
1356 yyextra->code->codify(yytext);
1357 yyextra->memCallContext = YY_START;
1358 BEGIN( MemberCall );
1359 }
static void updateCallContextForSmartPointer(yyscan_t yyscanner)
Definition code.l:2789
1360<MemberCall>{SCOPETNAME}/{BN}*"(" {
1361 DBG_CTX((stderr,"MemberCall: '%s'\n",qPrint(yytext)));
1362 if (yyextra->theCallContext.getScope().globalDef())
1363 {
1364 if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext))
1365 {
1366 codifyLines(yyscanner,yytext);
1367 addToSearchIndex(yyscanner,yytext);
1368 }
1369 yyextra->name.clear();
1370 }
1371 else
1372 {
1373 codifyLines(yyscanner,yytext);
1374 addToSearchIndex(yyscanner,yytext);
1375 yyextra->name.clear();
1376 }
1377 yyextra->type.clear();
1378 if (yyextra->memCallContext==Body)
1379 {
1380 BEGIN(FuncCall);
1381 }
1382 else
1383 {
1384 BEGIN(yyextra->memCallContext);
1385 }
1386 }
1387<MemberCall>{SCOPENAME}/{B}* {
1388 if (yyextra->theCallContext.getScope().globalDef())
1389 {
1390 DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",(void*)yyextra->theCallContext.getScope().globalDef()));
1391 if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext))
1392 {
1393 codifyLines(yyscanner,yytext);
1394 addToSearchIndex(yyscanner,yytext);
1395 }
1396 yyextra->name.clear();
1397 }
1398 else
1399 {
1400 DBG_CTX((stderr,"no class context!\n"));
1401 codifyLines(yyscanner,yytext);
1402 addToSearchIndex(yyscanner,yytext);
1403 yyextra->name.clear();
1404 }
1405 yyextra->type.clear();
1406 BEGIN(yyextra->memCallContext);
1407 }
1408<Body>[,=;\‍[{] {
1409 if (yyextra->insideObjC && *yytext=='[')
1410 {
1411 DBG_CTX((stderr,"Found start of ObjC call!\n"));
1412 // start of a method call
1413 yyextra->contextMap.clear();
1414 yyextra->nameMap.clear();
1415 yyextra->objectMap.clear();
1416 yyextra->wordMap.clear();
1417 yyextra->commentMap.clear();
1418 yyextra->currentCtxId = 0;
1419 yyextra->currentNameId = 0;
1420 yyextra->currentObjId = 0;
1421 yyextra->currentCtx = nullptr;
1422 yyextra->braceCount = 0;
1423 unput('[');
1424 BEGIN(ObjCCall);
1425 }
1426 else
1427 {
1428 if (*yytext!='{') yyextra->code->codify(yytext);
1429 yyextra->saveName = yyextra->name;
1430 yyextra->saveType = yyextra->type;
1431 if (*yytext!='[' && !yyextra->type.empty())
1432 {
1433 //printf("yyextra->scopeStack.bottom()=%p\n",yyextra->scopeStack.bottom());
1434 //if (yyextra->scopeStack.top()!=CLASSBLOCK) // commented out for bug731363
1435 {
1436 //printf("AddVariable: '%s' '%s' context=%d\n",
1437 // qPrint(yyextra->type),qPrint(yyextra->name),yyextra->theVarContext.count());
1438 addVariable(yyscanner,yyextra->type,yyextra->name);
1439 }
1440 yyextra->name.clear();
1441 }
1442 if (*yytext==';' || *yytext=='=' || *yytext=='{')
1443 {
1444 yyextra->type.clear();
1445 yyextra->name.clear();
1446 }
1447 else if (*yytext=='[')
1448 {
1449 yyextra->theCallContext.pushScope(yyextra->name, yyextra->type, yyextra->bracketCount);
1450 }
1451 yyextra->args.clear();
1452 yyextra->parmType.clear();
1453 yyextra->parmName.clear();
1454 if (*yytext=='{')
1455 {
1456 BEGIN( BodyVar );
1457 unput('{');
1458 }
1459 }
1460 }
1461<Body,FuncCall,BodyVar>"{" {
1462 yyextra->theVarContext.pushScope();
1463 yyextra->theCallContext.pushScope(yyextra->name, yyextra->type, yyextra->bracketCount);
1464 yyextra->bracketCount = 0;
1465
1466 DBG_CTX((stderr,"** type='%s' name='%s'\n",qPrint(yyextra->type),qPrint(yyextra->name)));
1467 if (yyextra->type.find("enum ")!=DString::npos)
1468 { // for strong enums we need to start a scope
1469 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
1470 pushScope(yyscanner,yyextra->name);
1471 yyextra->scopeStack.push(SCOPEBLOCK);
1472 }
1473 else
1474 {
1475 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
1476 yyextra->scopeStack.push(INNERBLOCK);
1477 }
1478
1479 if (yyextra->searchingForBody)
1480 {
1481 yyextra->searchingForBody=false;
1482 yyextra->insideBody=true;
1483 }
1484 yyextra->code->codify(yytext);
1485 if (yyextra->insideBody)
1486 {
1487 yyextra->bodyCurlyCount++;
1488 }
1489 yyextra->type.clear();
1490 yyextra->name.clear();
1491 BEGIN( Body );
1492 }
1493<ObjCCall,ObjCMName>"["|"{" {
1494 saveObjCContext(yyscanner);
1495 yyextra->currentCtx->format+=*yytext;
1496 BEGIN(ObjCCall);
1497 DBG_CTX((stderr,"open\n"));
1498 }
static void saveObjCContext(yyscan_t yyscanner)
Definition code.l:3997
1499<ObjCCall,ObjCMName>"]"|"}" {
1500 yyextra->currentCtx->format+=*yytext;
1501 restoreObjCContext(yyscanner);
1502 BEGIN(ObjCMName);
1503 if (yyextra->currentCtx==nullptr)
1504 {
1505 // end of call
1506 ObjCCallCtx *ctx = nullptr;
1507 auto it = yyextra->contextMap.find(0);
1508 if (it!=yyextra->contextMap.end())
1509 {
1510 ctx = it->second.get();
1511 }
1512 writeObjCMethodCall(yyscanner,ctx);
1513 BEGIN(Body);
1514 }
1515 DBG_CTX((stderr,"close\n"));
1516 }
static void restoreObjCContext(yyscan_t yyscanner)
Definition code.l:4028
1517<ObjCCall,ObjCMName>{CPPC}.* {
1518 yyextra->currentCtx->format+=escapeComment(yyscanner,yytext);
1519 }
static DString escapeComment(yyscan_t yyscanner, const DString &s)
Definition code.l:3921
1520<ObjCCall,ObjCMName>{CCS} {
1521 yyextra->lastObjCCallContext = YY_START;
1522 yyextra->currentCtx->comment.str(yytext);
1523 BEGIN(ObjCCallComment);
1524 }
1525<ObjCCallComment>{CCE} {
1526 yyextra->currentCtx->comment << yytext;
1527 yyextra->currentCtx->format+=escapeComment(yyscanner,yyextra->currentCtx->comment.str());
1528 BEGIN(yyextra->lastObjCCallContext);
1529 }
1530<ObjCCallComment>[^*\n]+ { yyextra->currentCtx->comment << yytext; }
1531<ObjCCallComment>{CPPC}|{CCS} { yyextra->currentCtx->comment << yytext; }
1532<ObjCCallComment>\n { yyextra->currentCtx->comment << *yytext; }
1533<ObjCCallComment>. { yyextra->currentCtx->comment << *yytext; }
1534<ObjCCall>{ID}({B}*"."{B}*{ID})* {
1535 yyextra->currentCtx->format+=escapeObject(yyscanner,yytext);
1536 if (yyextra->braceCount==0)
1537 {
1538 yyextra->currentCtx->objectTypeOrName=yytext;
1539 DBG_CTX((stderr,"new type=%s\n",qPrint(yyextra->currentCtx->objectTypeOrName)));
1540 BEGIN(ObjCMName);
1541 }
1542 }
static DString escapeObject(yyscan_t yyscanner, const DString &s)
Definition code.l:3901
1543<ObjCMName>{ID}/{BN}*"]" {
1544 if (yyextra->braceCount==0 &&
1545 yyextra->currentCtx->methodName.empty())
1546 {
1547 yyextra->currentCtx->methodName=yytext;
1548 yyextra->currentCtx->format+=escapeName(yyscanner,yytext);
1549 }
1550 else
1551 {
1552 yyextra->currentCtx->format+=escapeWord(yyscanner,yytext);
1553 }
1554 }
static DString escapeName(yyscan_t yyscanner, const DString &s)
Definition code.l:3891
static DString escapeWord(yyscan_t yyscanner, const DString &s)
Definition code.l:3911
1555<ObjCMName>{ID}/{BN}*":" {
1556 if (yyextra->braceCount==0)
1557 {
1558 yyextra->currentCtx->methodName+=yytext;
1559 yyextra->currentCtx->methodName+=":";
1560 }
1561 yyextra->currentCtx->format+=escapeName(yyscanner,yytext);
1562 }
1563<ObjCSkipStr>[^\n\"$\\‍]* { yyextra->currentCtx->format+=yytext; }
1564<ObjCSkipStr>\\. { yyextra->currentCtx->format+=yytext; }
1565<ObjCSkipStr>"\"" { yyextra->currentCtx->format+=yytext;
1566 BEGIN(yyextra->lastStringContext);
1567 }
1568<ObjCCall,ObjCMName>{CHARLIT} { yyextra->currentCtx->format+=yytext; }
1569<ObjCCall,ObjCMName>"@"?"\"" { yyextra->currentCtx->format+=yytext;
1570 yyextra->lastStringContext=YY_START;
1571 BEGIN(ObjCSkipStr);
1572 }
1573<ObjCCall,ObjCMName,ObjCSkipStr>"$" { yyextra->currentCtx->format+="$$"; }
1574<ObjCCall,ObjCMName>"(" { yyextra->currentCtx->format+=*yytext; yyextra->braceCount++; }
1575<ObjCCall,ObjCMName>")" { yyextra->currentCtx->format+=*yytext; yyextra->braceCount--; }
1576<ObjCSkipStr>"@"/"\"" { // needed to prevent matching the global rule (for C#)
1577 yyextra->currentCtx->format+=yytext;
1578 }
1579<ObjCCall,ObjCMName,ObjCSkipStr>{ID} { yyextra->currentCtx->format+=escapeWord(yyscanner,yytext); }
1580<ObjCCall,ObjCMName,ObjCSkipStr>. { yyextra->currentCtx->format+=*yytext; }
1581<ObjCCall,ObjCMName,ObjCSkipStr>\n { yyextra->currentCtx->format+=*yytext; }
1582
1583<Body>"]" {
1584 yyextra->theCallContext.popScope(yyextra->name, yyextra->type, yyextra->bracketCount);
1585 yyextra->code->codify(yytext);
1586 // TODO: nested arrays like: a[b[0]->func()]->func()
1587 yyextra->name = yyextra->saveName;
1588 yyextra->type = yyextra->saveType;
1589 }
1590<Body>[0-9]+ {
1591 yyextra->code->codify(yytext);
1592 }
1593<Body>[0-9]+[xX][0-9A-Fa-f]+ {
1594 yyextra->code->codify(yytext);
1595 }
1596<MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) {
1597 //addParmType(yyscanner);
1598 //yyextra->parmName=yytext;
1599 if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT;
1600 startFontClass(yyscanner,"keyword");
1601 yyextra->code->codify(yytext);
1602 endFontClass(yyscanner);
1603 }
1604<MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKW}/([^a-z_A-Z0-9]) {
1605 addParmType(yyscanner);
1606 yyextra->parmName=yytext;
1607 startFontClass(yyscanner,"keywordtype");
1608 yyextra->code->codify(yytext);
1609 endFontClass(yyscanner);
1610 }
static void addParmType(yyscan_t yyscanner)
Definition code.l:2608
1611<MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKWSL}/([^a-z_A-Z0-9]) {
1612 if (yyextra->lang!=SrcLangExt::Slice)
1613 {
1614 REJECT;
1615 }
1616 else
1617 {
1618 addParmType(yyscanner);
1619 yyextra->parmName=yytext;
1620 startFontClass(yyscanner,"keywordtype");
1621 yyextra->code->codify(yytext);
1622 endFontClass(yyscanner);
1623 }
1624 }
1625<MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) {
1626 addParmType(yyscanner);
1627 yyextra->parmName=yytext;
1628 startFontClass(yyscanner,"keywordflow");
1629 yyextra->code->codify(yytext);
1630 endFontClass(yyscanner);
1631 }
1632<MemberCall2,FuncCall>{FLOWCONDITION}/([^a-z_A-Z0-9]) {
1633 incrementFlowKeyWordCount(yyscanner);
1634 addParmType(yyscanner);
1635 yyextra->parmName=yytext;
1636 startFontClass(yyscanner,"keywordflow");
1637 yyextra->code->codify(yytext);
1638 endFontClass(yyscanner);
1639 }
1640<MemberCall2,FuncCall>("::")?{ID}(({B}*"<"[^\n\‍[\‍](){}<>']*">")?({B}*"::"{B}*{ID})?)* {
1641 if (isCastKeyword(yytext))
1642 {
1643 REJECT;
1644 }
1645 addParmType(yyscanner);
1646 yyextra->parmName=yytext;
1647 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody);
1648 }
1649<FuncCall>";" { // probably a cast, not a function call
1650 yyextra->code->codify(yytext);
1651 yyextra->inForEachExpression = false;
1652 BEGIN( Body );
1653 }
1654<MemberCall2,FuncCall>, {
1655 yyextra->code->codify(yytext);
1656 addVariable(yyscanner,yyextra->parmType,yyextra->parmName);
1657 yyextra->parmType.clear();yyextra->parmName.clear();
1658 }
1659<MemberCall2,FuncCall>"{" {
1660 if (yyextra->bracketCount>0)
1661 {
1662 yyextra->code->codify(yytext);
1663 yyextra->skipInlineInitContext=YY_START;
1664 yyextra->curlyCount=0;
1665 BEGIN(InlineInit);
1666 }
1667 else
1668 {
1669 REJECT;
1670 }
1671 }
1672<InlineInit>"{" { yyextra->curlyCount++;
1673 yyextra->code->codify(yytext);
1674 }
1675<InlineInit>"}" {
1676 yyextra->code->codify(yytext);
1677 if (--yyextra->curlyCount<=0)
1678 {
1679 BEGIN(yyextra->skipInlineInitContext);
1680 }
1681 }
1682<InlineInit>\n {
1683 codifyLines(yyscanner,yytext);
1684 }
1685<InlineInit>. {
1686 yyextra->code->codify(yytext);
1687 }
1688<MemberCall2,FuncCall>"(" {
1689 yyextra->parmType.clear();yyextra->parmName.clear();
1690 yyextra->code->codify(yytext);
1691 yyextra->bracketCount++;
1692 yyextra->theCallContext.pushScope(yyextra->name, yyextra->type, yyextra->bracketCount);
1693 if (YY_START==FuncCall && !yyextra->insideBody)
1694 {
1695 yyextra->theVarContext.pushScope();
1696 }
1697 }
1698<MemberCall2,FuncCall>{OPERATOR} { // operator
1699 if (dstrcmp(yytext,"*") &&
1700 dstrcmp(yytext,"&") &&
1701 dstrcmp(yytext,"^") &&
1702 dstrcmp(yytext,"%")) // typically a pointer or reference
1703 {
1704 // not a * or &, or C++/CLI's ^ or %
1705 yyextra->parmType.clear();yyextra->parmName.clear();
1706 }
1707 yyextra->code->codify(yytext);
1708 }
1709<MemberCall,MemberCall2,FuncCall>("*"{B}*)?")" {
1710 if (yytext[0]==')') // no a pointer cast
1711 {
1712 DBG_CTX((stderr,"addVariable(%s,%s)\n",qPrint(yyextra->parmType),qPrint(yyextra->parmName)));
1713 if (yyextra->parmType.empty())
1714 {
1715 yyextra->parmType=yyextra->parmName;
1716 yyextra->parmName.clear();
1717 }
1718 addVariable(yyscanner,yyextra->parmType,yyextra->parmName);
1719 }
1720 else
1721 {
1722 yyextra->parmType = yyextra->parmName;
1723 yyextra->parmName.clear();
1724 addVariable(yyscanner,yyextra->parmType,yyextra->parmName);
1725 }
1726 yyextra->theCallContext.popScope(yyextra->name, yyextra->type, yyextra->bracketCount);
1727 yyextra->inForEachExpression = false;
1728 //yyextra->theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b().
1729 yyextra->code->codify(yytext);
1730 if (--yyextra->bracketCount<=0)
1731 {
1732 if (yyextra->name.empty())
1733 {
1734 BEGIN( Body );
1735 }
1736 else
1737 {
1738 BEGIN( CallEnd );
1739 }
1740 }
1741 }
1742<MemberCall,MemberCall2,FuncCall>[;:] { // recover from unexpected end of call
1743 //if (yytext[0]==';' || yyextra->bracketCount<=0)
1744 if (yyextra->bracketCount<=0)
1745 {
1746 unput(*yytext);
1747 BEGIN(CallEnd);
1748 }
1749 else
1750 {
1751 yyextra->code->codify(yytext);
1752 }
1753 }
1754<CallEnd>[ \t\n]* { codifyLines(yyscanner,yytext); }
1755<CallEnd>[;:] {
1756 codifyLines(yyscanner,yytext);
1757 yyextra->bracketCount=0;
1758 if (*yytext==';') yyextra->searchingForBody=false;
1759 if (!yyextra->type.empty())
1760 {
1761 DBG_CTX((stderr,"add variable yyextra->type=%s yyextra->name=%s)\n",qPrint(yyextra->type),qPrint(yyextra->name)));
1762 addVariable(yyscanner,yyextra->type,yyextra->name);
1763 }
1764 yyextra->parmType.clear();yyextra->parmName.clear();
1765 yyextra->theCallContext.setScope(ScopedTypeVariant());
1766 if (*yytext==';' || yyextra->insideBody)
1767 {
1768 if (!yyextra->insideBody)
1769 {
1770 yyextra->theVarContext.popScope();
1771 }
1772 yyextra->name.clear();yyextra->type.clear();
1773 BEGIN( Body );
1774 }
1775 else
1776 {
1777 yyextra->bracketCount=0;
1778 BEGIN( SkipInits );
1779 }
1780 }
1781<CallEnd>"=>" { // C# Expression Body
1782 if (yyextra->lang!=SrcLangExt::CSharp || yyextra->insideBody)
1783 {
1784 REJECT;
1785 }
1786 else
1787 {
1788 yyextra->code->codify("=>");
1789 BEGIN( Body );
1790 }
1791 }
1792<CallEnd>{ENDQopt}/{BN}*(";"|"="|"throw"{BN}*"(") {
1793 startFontClass(yyscanner,"keyword");
1794 codifyLines(yyscanner,yytext);
1795 endFontClass(yyscanner);
1796 }
1797<CallEnd,OldStyleArgs>("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" {
1798 if (yyextra->insideBody)
1799 {
1800 yyextra->theVarContext.pushScope();
1801 }
1802 addVariable(yyscanner,yyextra->parmType,yyextra->parmName);
1803 //yyextra->theCallContext.popScope(yyextra->name, yyextra->type);
1804 yyextra->parmType.clear();yyextra->parmName.clear();
1805 size_t index = yyextra->name.rfind("::");
1806 DBG_CTX((stderr,"yyextra->name=%s\n",qPrint(yyextra->name)));
1807 if (index!=DString::npos)
1808 {
1809 DString scope = yyextra->name.left(index);
1810 if (!yyextra->scopeName.empty()) scope.prepend((yyextra->scopeName+"::"));
1811 const ClassDef *cd=yyextra->symbolResolver.resolveClass(Doxygen::globalScope,scope,true);
1812 if (cd)
1813 {
1814 setClassScope(yyscanner,cd->name());
1815 yyextra->scopeStack.push(SCOPEBLOCK);
1816 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
1817 }
1818 else
1819 {
1820 //setClassScope(yyscanner,yyextra->realScope);
1821 yyextra->scopeStack.push(INNERBLOCK);
1822 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
1823 }
1824 }
1825 else
1826 {
1827 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
1828 yyextra->scopeStack.push(INNERBLOCK);
1829 }
1830 yytext[yyleng-1]='\0';
1831 DString cv(yytext);
1832 if (!cv.stripWhiteSpace().empty())
1833 {
1834 startFontClass(yyscanner,"keyword");
1835 codifyLines(yyscanner,yytext);
1836 endFontClass(yyscanner);
1837 }
1838 else // just whitespace
1839 {
1840 codifyLines(yyscanner,yytext);
1841 }
1842 yyextra->code->codify("{");
1843 if (yyextra->searchingForBody)
1844 {
1845 yyextra->searchingForBody=false;
1846 yyextra->insideBody=true;
1847 }
1848 if (yyextra->insideBody) yyextra->bodyCurlyCount++;
1849 yyextra->type.clear(); yyextra->name.clear();
1850 BEGIN( Body );
1851 }
static void setClassScope(yyscan_t yyscanner, const DString &name)
Definition code.l:2309
1852<CallEnd>"try" { // function-try-block
1853 startFontClass(yyscanner,"keyword");
1854 yyextra->code->codify(yytext);
1855 endFontClass(yyscanner);
1856 yyextra->inFunctionTryBlock=true;
1857 }
1858<CallEnd>"requires" { // function-try-block
1859 startFontClass(yyscanner,"keyword");
1860 yyextra->code->codify(yytext);
1861 endFontClass(yyscanner);
1862 }
1863<CallEnd>{ID} {
1864 if (yyextra->insideBody || !yyextra->parmType.empty())
1865 {
1866 REJECT;
1867 }
1868 // could be K&R style definition
1869 addParmType(yyscanner);
1870 yyextra->parmName=yytext;
1871 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody);
1872 BEGIN(OldStyleArgs);
1873 }
1874<OldStyleArgs>{ID} {
1875 addParmType(yyscanner);
1876 yyextra->parmName=yytext;
1877 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody);
1878 }
1879<OldStyleArgs>[,;] {
1880 yyextra->code->codify(yytext);
1881 addVariable(yyscanner,yyextra->parmType,yyextra->parmName);
1882 if (*yytext==';') yyextra->parmType.clear();
1883 yyextra->parmName.clear();
1884 }
1885<CallEnd,OldStyleArgs>"#" {
1886 startFontClass(yyscanner,"preprocessor");
1887 yyextra->lastSkipCppContext = Body;
1888 yyextra->code->codify(yytext);
1889 BEGIN( SkipCPP );
1890 }
1891<CallEnd>. {
1892 unput(*yytext);
1893 if (!yyextra->insideBody)
1894 {
1895 yyextra->theVarContext.popScope();
1896 }
1897 yyextra->name.clear();yyextra->args.clear();
1898 yyextra->parmType.clear();yyextra->parmName.clear();
1899 BEGIN( Body );
1900 }
1901<SkipInits>";" {
1902 yyextra->code->codify(yytext);
1903 yyextra->type.clear(); yyextra->name.clear();
1904 BEGIN( Body );
1905 }
1906<SkipInits>"{" {
1907 yyextra->code->codify(yytext);
1908 if (yyextra->searchingForBody)
1909 {
1910 yyextra->searchingForBody=false;
1911 yyextra->insideBody=true;
1912 }
1913 if (yyextra->insideBody) yyextra->bodyCurlyCount++;
1914 if (yyextra->name.find("::")!=DString::npos)
1915 {
1916 DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
1917 yyextra->scopeStack.push(SCOPEBLOCK);
1918 setClassScope(yyscanner,yyextra->realScope);
1919 }
1920 else
1921 {
1922 DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
1923 yyextra->scopeStack.push(INNERBLOCK);
1924 }
1925 yyextra->type.clear(); yyextra->name.clear();
1926 BEGIN( Body );
1927 }
1928<SkipInits>{ID}{B}*"{" {
1929 DString text(yytext);
1930 size_t bracketPos = text.find('{');
1931 size_t spacePos = text.find(' ');
1932 size_t len = spacePos==DString::npos ? bracketPos : spacePos;
1933 generateClassOrGlobalLink(yyscanner,*yyextra->code,text.left(len));
1934 yyextra->code->codify(yytext+len);
1935 }
1936<SkipInits>{ID} {
1937 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
1938 }
1939<FuncCall>{ID}/"(" {
1940 generateFunctionLink(yyscanner,*yyextra->code,yytext);
1941 }
1942<FuncCall>{ID}/("."|"->") {
1943 yyextra->name=yytext;
1944 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
1945 BEGIN( MemberCall2 );
1946 }
1947<FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}+{B}*")"{B}*)/("."|"->") {
1948 yyextra->code->codify(yytext);
1949 uint32_t s=0;while (!isId(yytext[s])) s++;
1950 uint32_t e=(uint32_t)yyleng-1;while (e>1 && !isId(yytext[e])) e--;
1951 yyextra->name=((DString)yytext).mid(s,e-s+1);
1952 BEGIN( MemberCall2 );
1953 }
1954<MemberCall2>{ID}/([ \t\n]*"(") {
1955 if (!yyextra->args.empty())
1956 generateMemberLink(yyscanner,*yyextra->code,yyextra->args,yytext);
1957 else
1958 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
1959 yyextra->args.clear();
1960 BEGIN( FuncCall );
1961 }
static void generateMemberLink(yyscan_t yyscanner, OutputCodeList &ol, const DString &varName, const DString &memName)
Definition code.l:3249
1962<MemberCall2>{ID}/([ \t\n]*("."|"->")) {
1963 //yyextra->code->codify(yytext);
1964 yyextra->name=yytext;
1965 generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
1966 BEGIN( MemberCall2 );
1967 }
1968<MemberCall2>"->"|"." {
1969 if (yytext[0]=='-') // -> could be overloaded
1970 {
1972 }
1973 yyextra->code->codify(yytext);
1974 yyextra->memCallContext = YY_START;
1975 BEGIN( MemberCall );
1976 }
1977<SkipComment>{CCS}("!"?){CCE} {
1978 yyextra->code->codify(yytext);
1979 endFontClass(yyscanner,true);
1980 BEGIN( yyextra->lastCContext ) ;
1981 }
1982<SkipComment>{CPPC}|{CCS} {
1983 yyextra->code->codify(yytext);
1984 }
1985<SkipComment>[^*\/\n]+ {
1986 yyextra->code->codify(yytext);
1987 }
1988<SkipComment>[ \t]*{CCE} {
1989 yyextra->code->codify(yytext);
1990 endFontClass(yyscanner,true);
1991 if (yyextra->lastCContext==SkipCPP)
1992 {
1993 startFontClass(yyscanner,"preprocessor");
1994 }
1995 BEGIN( yyextra->lastCContext ) ;
1996 }
1997<SkipCxxComment>[^\r\n]*"\\"[\r]?\n { // line continuation
1998 codifyLines(yyscanner,yytext);
1999 }
2000<SkipCxxComment>[^\r\n]+ {
2001 yyextra->code->codify(yytext);
2002 }
2003<SkipCxxComment>\r
2004<SkipCxxComment>\n {
2005 unput('\n');
2006 endFontClass(yyscanner);
2007 BEGIN( yyextra->lastCContext ) ;
2008 }
2009<SkipCxxComment>. {
2010 yyextra->code->codify(yytext);
2011 }
2012<MemberCall>[^a-z_A-Z0-9(\n] {
2013 yyextra->code->codify(yytext);
2014 yyextra->type.clear();
2015 yyextra->name.clear();
2016 BEGIN(yyextra->memCallContext);
2017 }
2018<*>\n({B}*{CPPC}[!/][^\n]*\n)+ { // remove special one-line comment
2019 if (YY_START==SkipCPP) REJECT;
2020 startFontClass(yyscanner,"comment",true);
2021 codifyLines(yyscanner,DString(yytext).left(yyleng-1));
2022 endFontClass(yyscanner,true);
2023 codifyLines(yyscanner,"\n");
2024 if (YY_START==SkipCxxComment)
2025 {
2026 BEGIN( yyextra->lastCContext ) ;
2027 }
2028 }
2029<SkipCPP>\n/(.|\n) {
2030 endFontClass(yyscanner);
2031 BEGIN( yyextra->lastSkipCppContext ) ;
2032 unput('\n');
2033 }
2034<*>\n{B}*{CPPC}"@"[{}].*\n { // remove one-line group marker
2035 startFontClass(yyscanner,"comment",true);
2036 codifyLines(yyscanner,DString(yytext).left(yyleng-1));
2037 endFontClass(yyscanner,true);
2038 codifyLines(yyscanner,"\n");
2039 if (YY_START==SkipCxxComment)
2040 {
2041 BEGIN( yyextra->lastCContext ) ;
2042 }
2043 }
2044<*>\n{B}*{CCS}"@"[{}] { // remove one-line group marker
2045 // check is to prevent getting stuck in skipping C++ comments
2046 if (YY_START != SkipComment && YY_START != SkipCxxComment)
2047 {
2048 yyextra->lastCContext = YY_START ;
2049 }
2050 startFontClass(yyscanner,"comment",true);
2051 codifyLines(yyscanner,yytext);
2052 BEGIN(SkipComment);
2053 }
2054<*>^{B}*{CPPC}"@"[{}].*\n { // remove one-line group marker
2055 startFontClass(yyscanner,"comment",true);
2056 codifyLines(yyscanner,DString(yytext).left(yyleng-1));
2057 endFontClass(yyscanner,true);
2058 codifyLines(yyscanner,"\n");
2059 }
2060<*>^{B}*{CCS}"@"[{}] { // remove multi-line group marker
2061 // check is to prevent getting stuck in skipping C++ comments
2062 if (YY_START != SkipComment && YY_START != SkipCxxComment)
2063 {
2064 yyextra->lastCContext = YY_START ;
2065 }
2066 startFontClass(yyscanner,"comment",true);
2067 yyextra->code->codify(yytext);
2068 BEGIN(SkipComment);
2069 }
2070<*>^{B}*{CPPC}[!/][^\n]* { // remove special one-line comment
2071 startFontClass(yyscanner,"comment",true);
2072 codifyLines(yyscanner,yytext);
2073 endFontClass(yyscanner,true);
2074 }
2075<*>{CPPC}[!/][^\n]* { // strip special one-line comment
2076 if (YY_START==SkipComment || YY_START==SkipString) REJECT;
2077 startFontClass(yyscanner,"comment",true);
2078 codifyLines(yyscanner,yytext);
2079 endFontClass(yyscanner,true);
2080 }
2081<*>\n{B}*{CCS}[!*]/{NCOMM} {
2082 // check is to prevent getting stuck in skipping C++ comments
2083 if (YY_START != SkipComment && YY_START != SkipCxxComment)
2084 {
2085 yyextra->lastCContext = YY_START ;
2086 }
2087 startFontClass(yyscanner,"comment",true);
2088 codifyLines(yyscanner,yytext);
2089 BEGIN(SkipComment);
2090 }
2091<*>^{B}*{CCS}"*"[*]+/[^/] {
2092 // check is to prevent getting stuck in skipping C++ comments
2093 if (YY_START != SkipComment && YY_START != SkipCxxComment)
2094 {
2095 yyextra->lastCContext = YY_START ;
2096 }
2097 // special C "banner" comment block at a new line
2098 startFontClass(yyscanner,"comment",Config_getBool(JAVADOC_BANNER));
2099 yyextra->code->codify(yytext);
2100 BEGIN(SkipComment);
2101 }
2102<*>^{B}*{CCS}[!*]/{NCOMM} { // special C comment block at a new line
2103 // check is to prevent getting stuck in skipping C++ comments
2104 if (YY_START != SkipComment && YY_START != SkipCxxComment)
2105 {
2106 yyextra->lastCContext = YY_START ;
2107 }
2108 startFontClass(yyscanner,"comment",true);
2109 yyextra->code->codify(yytext);
2110 BEGIN(SkipComment);
2111 }
2112<*>{CCS}[!*]/{NCOMM} { // special C comment block half way a line
2113 if (YY_START==SkipString) REJECT;
2114 // check is to prevent getting stuck in skipping C++ comments
2115 if (YY_START != SkipComment && YY_START != SkipCxxComment)
2116 {
2117 yyextra->lastCContext = YY_START ;
2118 }
2119 startFontClass(yyscanner,"comment",true);
2120 yyextra->code->codify(yytext);
2121 BEGIN(SkipComment);
2122 }
2123<*>{CCS}("!"?){CCE} {
2124 if (YY_START==SkipString) REJECT;
2125 bool specialComment = DString(yytext).find('!')!=DString::npos;
2126 startFontClass(yyscanner,"comment",specialComment);
2127 yyextra->code->codify(yytext);
2128 endFontClass(yyscanner,specialComment);
2129 }
2130<SkipComment>[^\*\n]+ {
2131 yyextra->code->codify(yytext);
2132 }
2133<*>{CCS} {
2134 startFontClass(yyscanner,"comment");
2135 yyextra->code->codify(yytext);
2136 // check is to prevent getting stuck in skipping C++ comments
2137 if (YY_START != SkipComment && YY_START != SkipCxxComment)
2138 {
2139 yyextra->lastCContext = YY_START ;
2140 }
2141 BEGIN( SkipComment ) ;
2142 }
2143<*>[$]?@\" { // C# (interpolated) verbatim string
2144 startFontClass(yyscanner,"stringliteral");
2145 yyextra->code->codify(yytext);
2146 yyextra->lastVerbStringContext=YY_START;
2147 BEGIN(SkipVerbString);
2148 }
2149<*>{CPPC} {
2150 startFontClass(yyscanner,"comment");
2151 yyextra->code->codify(yytext);
2152 yyextra->lastCContext = YY_START ;
2153 BEGIN( SkipCxxComment ) ;
2154 }
2155<*>"("|"[" {
2156 if (yytext[0]=='(') yyextra->bracketCount++;
2157 yyextra->code->codify(yytext);
2158 yyextra->theCallContext.pushScope(yyextra->name, yyextra->type, yyextra->bracketCount);
2159 }
2160<*>")"|"]" {
2161 if (yytext[0]==')') yyextra->bracketCount--;
2162 yyextra->code->codify(yytext);
2163 yyextra->theCallContext.popScope(yyextra->name, yyextra->type, yyextra->bracketCount);
2164 }
2165<*>\n {
2166 codifyLines(yyscanner,yytext);
2167 }
2168<*>[\x80-\xFF]* { // keep utf8 characters together...
2169 yyextra->code->codify(yytext);
2170 }
2171<*>. {
2172 yyextra->code->codify(yytext);
2173 }
2174
2175%%

◆ yyread()

int yyread ( yyscan_t yyscanner,
char * buf,
int max_size )
static

Definition at line 3981 of file code.l.

3982{
3983 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3984 yy_size_t inputPosition = yyextra->inputPosition;
3985 const char *s = yyextra->inputString + inputPosition;
3986 int c=0;
3987 while( c < max_size && *s )
3988 {
3989 *buf++ = *s++;
3990 c++;
3991 }
3992 yyextra->inputPosition += c;
3993 return c;
3994}