Loading src/commentscan.l +38 −2 Original line number Diff line number Diff line Loading @@ -116,6 +116,8 @@ static bool handleToc(const QCString &s); static bool handleInherit(const QCString &); static bool handleExtends(const QCString &); static bool handleCopyDoc(const QCString &); static bool handleCopyBrief(const QCString &); static bool handleCopyDetails(const QCString &); typedef bool (*DocCmdFunc)(const QCString &name); Loading Loading @@ -218,8 +220,8 @@ static DocCmdMap docCmdMap[] = { "author", 0, TRUE }, { "authors", 0, TRUE }, { "copydoc", &handleCopyDoc, TRUE }, { "copybrief", 0, FALSE }, { "copydetails", 0, TRUE }, { "copybrief", &handleCopyBrief, FALSE }, { "copydetails", &handleCopyDetails, TRUE }, { "copyright", 0, TRUE }, { "date", 0, TRUE }, { "dotfile", 0, TRUE }, Loading Loading @@ -2674,9 +2676,43 @@ static bool handleExtends(const QCString &) return FALSE; } static bool handleCopyBrief(const QCString &) { if (current->brief.isEmpty() && current->doc.isEmpty()) { // if we don't have a brief or detailed description yet, // then the @copybrief should end up in the brief description. // otherwise it will be copied inline (see bug691315 & bug700788) setOutput(OutputBrief); } if (g_spaceBeforeCmd) { addOutput(' '); g_spaceBeforeCmd=FALSE; } addOutput("\\copybrief "); return FALSE; } static bool handleCopyDetails(const QCString &) { setOutput(OutputDoc); if (g_spaceBeforeCmd) { addOutput(' '); g_spaceBeforeCmd=FALSE; } addOutput("\\copydetails "); return FALSE; } static bool handleCopyDoc(const QCString &) { setOutput(OutputBrief); if (g_spaceBeforeCmd) { addOutput(' '); g_spaceBeforeCmd=FALSE; } addOutput("\\copybrief "); g_copyDocArg.resize(0); BEGIN(CopyDoc); Loading src/docparser.cpp +141 −53 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ #include "reflist.h" #include "formula.h" #include "config.h" #include "growbuf.h" // debug off #define DBG(x) do {} while(0) Loading Loading @@ -1528,39 +1529,6 @@ handlepara: //--------------------------------------------------------------------------- static int handleDocCopy(DocNode *parent,QList<DocNode> &children) { int tok=doctokenizerYYlex(); int cmdId = Mappers::cmdMapper->map(g_token->name); if (tok!=TK_WHITESPACE) { warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", qPrint(g_token->name)); return 0; } tok=doctokenizerYYlex(); if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " "argument of command %s\n", qPrint(g_token->name)); return 0; } else if (tok!=TK_WORD && tok!=TK_LNKWORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", tokToString(tok),qPrint(g_token->name)); return 0; } DocCopy *cpy = new DocCopy(parent,g_token->name, cmdId==CMD_COPYDOC || cmdId==CMD_COPYBRIEF, cmdId==CMD_COPYDOC || cmdId==CMD_COPYDETAILS); cpy->parse(children); delete cpy; return TK_NEWPARA; } //--------------------------------------------------------------------------- static void handleImg(DocNode *parent,QList<DocNode> &children,const HtmlAttribList &tagHtmlAttribs) { HtmlAttribListIterator li(tagHtmlAttribs); Loading Loading @@ -1757,10 +1725,6 @@ static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children, { delete par; } if (retval==RetVal_CopyDoc) { retval=handleDocCopy(parent,children); } } while (retval==TK_NEWPARA); if (lastPar) lastPar->markLast(); Loading Loading @@ -3239,10 +3203,6 @@ int DocInternal::parse(int level) { warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found",doctokenizerYYlineno); } else if (retval==RetVal_CopyDoc) { retval=handleDocCopy(this,m_children); } } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Subsection && Loading Loading @@ -5597,7 +5557,8 @@ int DocPara::handleCommand(const QCString &cmdName) case CMD_COPYDOC: // fall through case CMD_COPYBRIEF: // fall through case CMD_COPYDETAILS: retval = RetVal_CopyDoc; //retval = RetVal_CopyDoc; // these commands should already be resolved by processCopyDoc() break; case CMD_INCLUDE: handleInclude(cmdName,DocInclude::Include); Loading Loading @@ -6648,10 +6609,6 @@ int DocSection::parse() { warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); } else if (retval==RetVal_CopyDoc) { retval=handleDocCopy(this,m_children); } } while (retval!=0 && retval!=RetVal_Internal && retval!=RetVal_Section && Loading Loading @@ -6868,10 +6825,6 @@ void DocRoot::parse() { warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!"); } else if (retval==RetVal_CopyDoc) { retval=handleDocCopy(this,m_children); } } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Internal); if (lastPar) lastPar->markLast(); Loading Loading @@ -6909,6 +6862,140 @@ void DocRoot::parse() DBG(("DocRoot::parse() end\n")); } static QCString extractCopyDocId(const char *data, uint &j, uint len) { uint s=j; uint e=j; int round=0; bool insideDQuote=FALSE; bool insideSQuote=FALSE; bool found=FALSE; while (j<len && !found) { if (!insideSQuote && !insideDQuote) { switch (data[j]) { case '(': round++; break; case ')': round--; break; case '"': insideDQuote=TRUE; break; case '\'': insideSQuote=TRUE; break; case ' ': // fall through case '\t': // fall through case '\n': found=(round==0); break; } } else if (insideSQuote) // look for single quote end { if (data[j]=='\'' && (j==0 || data[j]!='\\')) { insideSQuote=FALSE; } } else if (insideDQuote) // look for double quote end { if (data[j]=='"' && (j==0 || data[j]!='\\')) { insideDQuote=FALSE; } } if (!found) j++; } e=j; QCString id(e-s+1); if (e>s) memcpy(id.data(),data+s,e-s); id.at(e-s)='\0'; //printf("extractCopyDocId=%s input='%s'\n",id.data(),&data[s]); return id; } static uint isCopyBriefOrDetailsCmd(const char *data, uint i,uint len,bool &brief) { int j=0; if (i==0 || (data[i-1]!='@' && data[i-1]!='\\')) // not an escaped command { if (i+10<len && qstrncmp(data+i+1,"copybrief",9)==0) // @copybrief or \copybrief { j=i+10; brief=TRUE; } else if (i+12<len && qstrncmp(data+i+1,"copydetails",11)==0) // @copydetails or \copydetails { j=i+12; brief=FALSE; } } return j; } static QCString processCopyDoc(const char *data,uint &len) { //printf("processCopyDoc start '%s'\n",data); GrowBuf buf; uint i=0; while (i<len) { char c = data[i]; if (c=='@' || c=='\\') // look for a command { bool isBrief=TRUE; uint j=isCopyBriefOrDetailsCmd(data,i,len,isBrief); if (j>0) { // skip whitespace while (j<len && (data[j]==' ' || data[j]=='\t')) j++; // extract the argument QCString id = extractCopyDocId(data,j,len); Definition *def; QCString doc,brief; //printf("resolving docs='%s'\n",id.data()); if (findDocsForMemberOrCompound(id,&doc,&brief,&def)) { //printf("found it def=%p brief='%s' doc='%s' isBrief=%d\n",def,brief.data(),doc.data(),isBrief); if (g_copyStack.findRef(def)==-1) // definition not parsed earlier { g_copyStack.append(def); if (isBrief) { uint l=brief.length(); buf.addStr(processCopyDoc(brief,l)); } else { uint l=doc.length(); buf.addStr(processCopyDoc(doc,l)); } g_copyStack.remove(def); } else { warn_doc_error(g_fileName,doctokenizerYYlineno, "Found recursive @copy%s or @copydoc relation for argument '%s'.\n", isBrief?"brief":"details",id.data()); } } // skip over command i=j; } else { buf.addChar(c); i++; } } else // not a command, just copy { buf.addChar(c); i++; } } len = buf.getPos(); buf.addChar(0); return buf.get(); } //-------------------------------------------------------------------------- DocRoot *validatingParseDoc(const char *fileName,int startLine, Loading Loading @@ -7074,12 +7161,13 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine); doctokenizerYYlineno=startLine; QCString inpStr=input; uint inpLen = inpStr.length(); if (inpLen>0 && inpStr.at(inpLen-1)!='\n') uint inpLen=qstrlen(input); QCString inpStr = processCopyDoc(input,inpLen); if (inpStr.isEmpty() || inpStr.at(inpStr.length()-1)!='\n') { inpStr+='\n'; } //printf("processCopyDoc(in='%s' out='%s')\n",input,inpStr.data()); doctokenizerYYinit(inpStr,g_fileName); // build abstract syntax tree Loading Loading
src/commentscan.l +38 −2 Original line number Diff line number Diff line Loading @@ -116,6 +116,8 @@ static bool handleToc(const QCString &s); static bool handleInherit(const QCString &); static bool handleExtends(const QCString &); static bool handleCopyDoc(const QCString &); static bool handleCopyBrief(const QCString &); static bool handleCopyDetails(const QCString &); typedef bool (*DocCmdFunc)(const QCString &name); Loading Loading @@ -218,8 +220,8 @@ static DocCmdMap docCmdMap[] = { "author", 0, TRUE }, { "authors", 0, TRUE }, { "copydoc", &handleCopyDoc, TRUE }, { "copybrief", 0, FALSE }, { "copydetails", 0, TRUE }, { "copybrief", &handleCopyBrief, FALSE }, { "copydetails", &handleCopyDetails, TRUE }, { "copyright", 0, TRUE }, { "date", 0, TRUE }, { "dotfile", 0, TRUE }, Loading Loading @@ -2674,9 +2676,43 @@ static bool handleExtends(const QCString &) return FALSE; } static bool handleCopyBrief(const QCString &) { if (current->brief.isEmpty() && current->doc.isEmpty()) { // if we don't have a brief or detailed description yet, // then the @copybrief should end up in the brief description. // otherwise it will be copied inline (see bug691315 & bug700788) setOutput(OutputBrief); } if (g_spaceBeforeCmd) { addOutput(' '); g_spaceBeforeCmd=FALSE; } addOutput("\\copybrief "); return FALSE; } static bool handleCopyDetails(const QCString &) { setOutput(OutputDoc); if (g_spaceBeforeCmd) { addOutput(' '); g_spaceBeforeCmd=FALSE; } addOutput("\\copydetails "); return FALSE; } static bool handleCopyDoc(const QCString &) { setOutput(OutputBrief); if (g_spaceBeforeCmd) { addOutput(' '); g_spaceBeforeCmd=FALSE; } addOutput("\\copybrief "); g_copyDocArg.resize(0); BEGIN(CopyDoc); Loading
src/docparser.cpp +141 −53 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ #include "reflist.h" #include "formula.h" #include "config.h" #include "growbuf.h" // debug off #define DBG(x) do {} while(0) Loading Loading @@ -1528,39 +1529,6 @@ handlepara: //--------------------------------------------------------------------------- static int handleDocCopy(DocNode *parent,QList<DocNode> &children) { int tok=doctokenizerYYlex(); int cmdId = Mappers::cmdMapper->map(g_token->name); if (tok!=TK_WHITESPACE) { warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", qPrint(g_token->name)); return 0; } tok=doctokenizerYYlex(); if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " "argument of command %s\n", qPrint(g_token->name)); return 0; } else if (tok!=TK_WORD && tok!=TK_LNKWORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", tokToString(tok),qPrint(g_token->name)); return 0; } DocCopy *cpy = new DocCopy(parent,g_token->name, cmdId==CMD_COPYDOC || cmdId==CMD_COPYBRIEF, cmdId==CMD_COPYDOC || cmdId==CMD_COPYDETAILS); cpy->parse(children); delete cpy; return TK_NEWPARA; } //--------------------------------------------------------------------------- static void handleImg(DocNode *parent,QList<DocNode> &children,const HtmlAttribList &tagHtmlAttribs) { HtmlAttribListIterator li(tagHtmlAttribs); Loading Loading @@ -1757,10 +1725,6 @@ static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children, { delete par; } if (retval==RetVal_CopyDoc) { retval=handleDocCopy(parent,children); } } while (retval==TK_NEWPARA); if (lastPar) lastPar->markLast(); Loading Loading @@ -3239,10 +3203,6 @@ int DocInternal::parse(int level) { warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found",doctokenizerYYlineno); } else if (retval==RetVal_CopyDoc) { retval=handleDocCopy(this,m_children); } } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Subsection && Loading Loading @@ -5597,7 +5557,8 @@ int DocPara::handleCommand(const QCString &cmdName) case CMD_COPYDOC: // fall through case CMD_COPYBRIEF: // fall through case CMD_COPYDETAILS: retval = RetVal_CopyDoc; //retval = RetVal_CopyDoc; // these commands should already be resolved by processCopyDoc() break; case CMD_INCLUDE: handleInclude(cmdName,DocInclude::Include); Loading Loading @@ -6648,10 +6609,6 @@ int DocSection::parse() { warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); } else if (retval==RetVal_CopyDoc) { retval=handleDocCopy(this,m_children); } } while (retval!=0 && retval!=RetVal_Internal && retval!=RetVal_Section && Loading Loading @@ -6868,10 +6825,6 @@ void DocRoot::parse() { warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!"); } else if (retval==RetVal_CopyDoc) { retval=handleDocCopy(this,m_children); } } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Internal); if (lastPar) lastPar->markLast(); Loading Loading @@ -6909,6 +6862,140 @@ void DocRoot::parse() DBG(("DocRoot::parse() end\n")); } static QCString extractCopyDocId(const char *data, uint &j, uint len) { uint s=j; uint e=j; int round=0; bool insideDQuote=FALSE; bool insideSQuote=FALSE; bool found=FALSE; while (j<len && !found) { if (!insideSQuote && !insideDQuote) { switch (data[j]) { case '(': round++; break; case ')': round--; break; case '"': insideDQuote=TRUE; break; case '\'': insideSQuote=TRUE; break; case ' ': // fall through case '\t': // fall through case '\n': found=(round==0); break; } } else if (insideSQuote) // look for single quote end { if (data[j]=='\'' && (j==0 || data[j]!='\\')) { insideSQuote=FALSE; } } else if (insideDQuote) // look for double quote end { if (data[j]=='"' && (j==0 || data[j]!='\\')) { insideDQuote=FALSE; } } if (!found) j++; } e=j; QCString id(e-s+1); if (e>s) memcpy(id.data(),data+s,e-s); id.at(e-s)='\0'; //printf("extractCopyDocId=%s input='%s'\n",id.data(),&data[s]); return id; } static uint isCopyBriefOrDetailsCmd(const char *data, uint i,uint len,bool &brief) { int j=0; if (i==0 || (data[i-1]!='@' && data[i-1]!='\\')) // not an escaped command { if (i+10<len && qstrncmp(data+i+1,"copybrief",9)==0) // @copybrief or \copybrief { j=i+10; brief=TRUE; } else if (i+12<len && qstrncmp(data+i+1,"copydetails",11)==0) // @copydetails or \copydetails { j=i+12; brief=FALSE; } } return j; } static QCString processCopyDoc(const char *data,uint &len) { //printf("processCopyDoc start '%s'\n",data); GrowBuf buf; uint i=0; while (i<len) { char c = data[i]; if (c=='@' || c=='\\') // look for a command { bool isBrief=TRUE; uint j=isCopyBriefOrDetailsCmd(data,i,len,isBrief); if (j>0) { // skip whitespace while (j<len && (data[j]==' ' || data[j]=='\t')) j++; // extract the argument QCString id = extractCopyDocId(data,j,len); Definition *def; QCString doc,brief; //printf("resolving docs='%s'\n",id.data()); if (findDocsForMemberOrCompound(id,&doc,&brief,&def)) { //printf("found it def=%p brief='%s' doc='%s' isBrief=%d\n",def,brief.data(),doc.data(),isBrief); if (g_copyStack.findRef(def)==-1) // definition not parsed earlier { g_copyStack.append(def); if (isBrief) { uint l=brief.length(); buf.addStr(processCopyDoc(brief,l)); } else { uint l=doc.length(); buf.addStr(processCopyDoc(doc,l)); } g_copyStack.remove(def); } else { warn_doc_error(g_fileName,doctokenizerYYlineno, "Found recursive @copy%s or @copydoc relation for argument '%s'.\n", isBrief?"brief":"details",id.data()); } } // skip over command i=j; } else { buf.addChar(c); i++; } } else // not a command, just copy { buf.addChar(c); i++; } } len = buf.getPos(); buf.addChar(0); return buf.get(); } //-------------------------------------------------------------------------- DocRoot *validatingParseDoc(const char *fileName,int startLine, Loading Loading @@ -7074,12 +7161,13 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine); doctokenizerYYlineno=startLine; QCString inpStr=input; uint inpLen = inpStr.length(); if (inpLen>0 && inpStr.at(inpLen-1)!='\n') uint inpLen=qstrlen(input); QCString inpStr = processCopyDoc(input,inpLen); if (inpStr.isEmpty() || inpStr.at(inpStr.length()-1)!='\n') { inpStr+='\n'; } //printf("processCopyDoc(in='%s' out='%s')\n",input,inpStr.data()); doctokenizerYYinit(inpStr,g_fileName); // build abstract syntax tree Loading