📄 code.l
字号:
/****************************************************************************** * * * * Copyright (C) 1997-2001 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * */%{/* * includes */#include <stdio.h>#include <assert.h>#include <ctype.h>#include <qregexp.h>#include "qtbc.h"#include "scanner.h"#include "entry.h"#include "doxygen.h"#include "message.h"#include "outputlist.h"#include "util.h"#include "membername.h"#define YY_NEVER_INTERACTIVE 1 // Toggle for some debugging info//#define DBG_CTX(x) fprintf x#define DBG_CTX(x) do { } while(0) #define SCOPEBLOCK (int *)4#define INNERBLOCK (int *)8/* ----------------------------------------------------------------- * statics */ static OutputDocInterface * g_code;static ClassSDict g_codeClassSDict(17);static ClassDef *g_curClassDef;static QCString g_curClassName;static QStrList g_curClassBases;// TODO: is this still needed? if so, make it workstatic bool g_inClass;static QCString g_parmType;static QCString g_parmName;static const char * g_inputString; //!< the code fragment as textstatic int g_inputPosition; //!< read offset during parsing static int g_inputLines; //!< number of line in the code fragmentstatic int g_yyLineNr; //!< current line numberstatic bool g_exampleBlock;static QCString g_exampleName;static QCString g_exampleFile;static bool g_insideTemplate = FALSE;static QCString g_type;static QCString g_name;static QCString g_args;static QCString g_classScope;static QCString g_realScope;static QStack<int> g_scopeStack; //!< 1 if bracket starts a scope, 2 for internal blocks static int g_anchorCount;static FileDef * g_sourceFileDef;static Definition * g_currentDefinition;static MemberDef * g_currentMemberDef;static bool g_includeCodeFragment;static const char * g_currentFontClass;static bool g_searchingForBody;static bool g_insideBody;static int g_bodyCurlyCount;static QCString g_saveName;static QCString g_saveType;static int g_bracketCount = 0;static int g_curlyCount = 0;static int g_sharpCount = 0;static int g_lastSpecialCContext;static int g_lastStringContext;static int g_memCallContext;static int g_lastCContext;//-------------------------------------------------------------------/*! Represents a stack of variable to class mappings as found in the * code. Each scope is enclosed in pushScope() and popScope() calls. * Variables are added by calling addVariables() and one can search * for variable using findVariable(). */class VariableContext{ public: class Scope : public SDict<ClassDef> { public: Scope() : SDict<ClassDef>(17) {} }; VariableContext() { m_scopes.setAutoDelete(TRUE); } virtual ~VariableContext() { } void pushScope() { m_scopes.append(new Scope); DBG_CTX((stderr,"** Push var context %d\n",m_scopes.count())); } void popScope() { if (m_scopes.count()>0) { DBG_CTX((stderr,"** Pop var context %d\n",m_scopes.count())); m_scopes.remove(m_scopes.count()-1); } else { DBG_CTX((stderr,"** ILLEGAL: Pop var context\n")); } } void clear() { m_scopes.clear(); m_globalScope.clear(); } void clearExceptGlobal() { DBG_CTX((stderr,"** Clear var context\n")); m_scopes.clear(); } void addVariable(const QCString &type,const QCString &name); ClassDef *findVariable(const QCString &name); Scope m_globalScope; QList<Scope> m_scopes;};void VariableContext::addVariable(const QCString &type,const QCString &name){ QCString ltype = type.simplifyWhiteSpace(); QCString lname = name.simplifyWhiteSpace(); if (ltype.left(7)=="struct ") { ltype = ltype.right(ltype.length()-7); } else if (ltype.left(6)=="union ") { ltype = ltype.right(ltype.length()-6); } if (ltype.isEmpty() || lname.isEmpty()) return; DBG_CTX((stderr,"** AddVariable trying: type=%s name=%s\n",ltype.data(),lname.data())); Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast(); ClassDef *varType; int i=0; if ( (varType=g_codeClassSDict[ltype]) || // look for class definitions inside the code block (varType=getResolvedClass(g_currentDefinition,ltype)) // look for global class definitions ) { DBG_CTX((stderr,"** AddVariable type=%s name=%s\n",ltype.data(),lname.data())); scope->append(lname,varType); // add it to a list } else if ((i=ltype.find('<'))!=-1) { // probably a template class, try without arguments as well addVariable(ltype.left(i),name); }}ClassDef *VariableContext::findVariable(const QCString &name){ if (name.isEmpty()) return 0; ClassDef *result = 0; QListIterator<Scope> sli(m_scopes); Scope *scope; // search from inner to outer scope for (sli.toLast();(scope=sli.current());--sli) { result = scope->find(name); if (result) { DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); return result; } } // nothing found -> also try the global scope result=m_globalScope.find(name); DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); return result;}static VariableContext g_theVarContext;//-------------------------------------------------------------------class CallContext{ public: CallContext() { m_classList.append(0); } virtual ~CallContext() {} void setClass(ClassDef *cd) { DBG_CTX((stderr,"** Set call context %s (%p)\n",cd==0 ? "<null>" : cd->name().data(),cd)); m_classList.removeLast(); m_classList.append(cd); } void pushScope() { m_classList.append(0); DBG_CTX((stderr,"** Push call context %d\n",m_classList.count())); } void popScope() { if (m_classList.count()>1) { DBG_CTX((stderr,"** Pop call context %d\n",m_classList.count())); m_classList.removeLast(); } else { DBG_CTX((stderr,"** ILLEGAL: Pop call context\n")); } } void clear() { DBG_CTX((stderr,"** Clear call context\n")); m_classList.clear(); m_classList.append(0); } ClassDef *getClass() const { return m_classList.getLast(); } private: QList<ClassDef> m_classList; };static CallContext g_theCallContext;//-------------------------------------------------------------------/*! add class/namespace name s to the scope */static void pushScope(const char *s){ if (g_classScope.isEmpty()) { g_classScope = s; } else { g_classScope += "::"; g_classScope += s; } //printf("pushScope() result: `%s'\n",g_classScope.data());}/*! remove the top class/namespace name from the scope */static void popScope(){ if (!g_classScope.isEmpty()) { int i=g_classScope.findRev("::"); if (i==-1) // last name, strip all { g_classScope.resize(0); } else // strip name { g_classScope = g_classScope.left(i); } } else { //err("Error: Too many end of scopes found!\n"); } //printf("popScope() result: `%s'\n",g_classScope.data());}static void setClassScope(const QCString &name){ //printf("setClassScope(%s)\n",name.data()); QCString n=name; n=n.simplifyWhiteSpace(); int ts=n.find('<'); // start of template int te=n.findRev('>'); // end of template //printf("ts=%d te=%d\n",ts,te); if (ts!=-1 && te!=-1 && te>ts) { // remove template from scope n=n.left(ts)+n.right(n.length()-te-1); } g_classScope = n; //printf("--->New class scope `%s'\n",g_classScope.data());}/*! start a new line of code, inserting a line number if g_sourceFileDef * is TRUE. If a definition starts at the current line, then the line * number is linked to the documentation of that definition. */static void startCodeLine(){ //if (g_currentFontClass) { g_code->endFontClass(); } if (g_sourceFileDef) { //QCString lineNumber,lineAnchor; //lineNumber.sprintf("%05d",g_yyLineNr); //lineAnchor.sprintf("l%05d",g_yyLineNr); Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); //g_code->startLineNumber(); if (!g_includeCodeFragment && d && d->isLinkableInProject()) { g_currentDefinition = d; g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); QCString anchor; g_insideBody = FALSE; g_searchingForBody = TRUE; g_realScope = d->name().copy(); //printf("Real scope: `%s'\n",g_realScope.data()); g_bodyCurlyCount = 0; if (g_currentMemberDef) anchor=g_currentMemberDef->getBodyAnchor(); //g_code->startCodeAnchor(lineAnchor); //g_code->writeCodeLink(d->getReference(),d->getOutputFileBase(), // anchor,lineNumber); //g_code->endCodeAnchor(); g_code->writeLineNumber(d->getReference(),d->getOutputFileBase(), anchor,g_yyLineNr); } else { //g_code->codify(lineNumber); g_code->writeLineNumber(0,0,0,g_yyLineNr); } //g_code->endLineNumber(); } g_code->startCodeLine(); if (g_currentFontClass) { g_code->startFontClass(g_currentFontClass); }}static void endFontClass();static void endCodeLine(){ if (g_currentFontClass) { g_code->endFontClass(); } g_code->endCodeLine();}/*! write a code fragment `text' that may span multiple lines, inserting * line numbers for each line. */static void codifyLines(char *text){ //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); char *p=text,*sp=p; char c; bool done=FALSE; while (!done) { sp=p; while ((c=*p++) && c!='\n'); if (c=='\n') { g_yyLineNr++; *(p-1)='\0'; g_code->codify(sp); endCodeLine(); if (g_yyLineNr<g_inputLines) { startCodeLine(); } } else { g_code->codify(sp); done=TRUE; } }}/*! writes a link to a fragment \a text that may span multiple lines, inserting * line numbers for each line. If \a text contains newlines, the link will be * split into multiple links with the same destination, one for each line. */static void writeMultiLineCodeLink(OutputDocInterface &ol, const char *ref,const char *file, const char *anchor,const char *text){ bool done=FALSE; char *p=(char *)text; while (!done) { char *sp=p; char c; while ((c=*p++) && c!='\n'); if (c=='\n') { g_yyLineNr++; *(p-1)='\0'; ol.writeCodeLink(ref,file,anchor,sp); endCodeLine(); if (g_yyLineNr<g_inputLines) { startCodeLine(); } } else { ol.writeCodeLink(ref,file,anchor,sp); done=TRUE; } }}static void addType(){ if (g_name=="const") { g_name.resize(0); return; } if (!g_type.isEmpty()) g_type += ' ' ; g_type += g_name ; g_name.resize(0) ; if (!g_type.isEmpty()) g_type += ' ' ; g_type += g_args ; g_args.resize(0) ;}static void addParmType(){ if (g_parmName=="const") { g_parmName.resize(0); return; } if (!g_parmType.isEmpty()) g_parmType += ' ' ; g_parmType += g_parmName ; g_parmName.resize(0) ;}void setParameterList(MemberDef *md){ g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : ""; ArgumentList *al = md->argumentList(); if (al==0) return; Argument *a = al->first(); while (a) { g_parmName = a->name.copy(); g_parmType = a->type.copy(); int i = g_parmType.find('*'); if (i!=-1) g_parmType = g_parmType.left(i); i = g_parmType.find('&'); if (i!=-1) g_parmType = g_parmType.left(i); if (g_parmType.left(6)=="const ") g_parmType = g_parmType.right(g_parmType.length()-6); g_parmType=g_parmType.stripWhiteSpace(); g_theVarContext.addVariable(g_parmType,g_parmName); a = al->next(); }}static ClassDef *stripClassName(const char *s){ int pos=0; QCString type = s; QCString className; QCString templSpec; while (extractClassNameFromType(type,pos,className,templSpec)) { QCString clName=className+templSpec; ClassDef *cd=0; if (!g_classScope.isEmpty()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -